1 /* 2 * "GEDKeeper", the personal genealogical database editor. 3 * Copyright (C) 2009-2021 by Sergey V. Zhdanovskih, Ruslan Garipov. 4 * 5 * This file is part of "GEDKeeper". 6 * 7 * This program is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 using System; 22 using System.Drawing; 23 using System.Windows.Forms; 24 using BSLib; 25 using BSLib.Design; 26 using BSLib.Design.Graphics; 27 using BSLib.Design.Handlers; 28 using GDModel; 29 using GKCore; 30 using GKCore.Interfaces; 31 using GKCore.Lists; 32 using GKCore.Options; 33 34 namespace GKUI.Components 35 { 36 #if !MONO 37 using Microsoft.Win32; 38 #endif 39 40 /// <summary> 41 /// Static functions only for UI implementation. 42 /// </summary> 43 public static class UIHelper 44 { Rt2Rt(ExtRect ert)45 public static Rectangle Rt2Rt(ExtRect ert) 46 { 47 return new Rectangle(ert.Left, ert.Top, ert.GetWidth(), ert.GetHeight()); 48 } 49 Rt2Rt(ExtRectF ert)50 public static RectangleF Rt2Rt(ExtRectF ert) 51 { 52 return new RectangleF(ert.Left, ert.Top, ert.GetWidth(), ert.GetHeight()); 53 } 54 NormalizeFormRect(ExtRect winRect)55 public static ExtRect NormalizeFormRect(ExtRect winRect) 56 { 57 // Travis CI does not have access to UI and tests aren't performed. 58 #if !CI_MODE 59 60 //------------------------------------------------------------------ 61 // 2016-09-30 Ruslan Garipov <brigadir15@gmail.com> 62 // Restrict position and size of the main window. 63 // FIXME: DPI-aware code still required here. 64 //------------------------------------------------------------------ 65 66 Screen screen = Screen.FromRectangle(Rt2Rt(winRect)); 67 if (screen != null) { 68 Rectangle workArea = screen.WorkingArea; 69 70 int width = winRect.GetWidth(); 71 int height = winRect.GetHeight(); 72 73 // Besides disallowing to the main window to have its right 74 // and bottom borders overhanged entire virtual workspace, 75 // combined from all available monitors, this code also 76 // does not allow to have this window "between" two 77 // monitors. This may be UNWANTED BEHAVIOR. 78 winRect.Left = Math.Max(workArea.Left, Math.Min(workArea.Right - width, winRect.Left)); 79 winRect.Top = Math.Max(workArea.Top, Math.Min(workArea.Bottom - height, winRect.Top)); 80 winRect.Right = winRect.Left + width - 1; 81 winRect.Bottom = winRect.Top + height - 1; 82 } 83 84 #endif 85 86 return winRect; 87 } 88 GetFormRect(Form form)89 public static ExtRect GetFormRect(Form form) 90 { 91 if (form == null) return ExtRect.CreateEmpty(); 92 93 // You must not expect user has a top window located on the primary 94 // monitor. If a top window ain't on the primary monitor, 95 // `x` and `y` may be negative numbers. 96 97 // 2016-09-30 Ruslan Garipov <brigadir15@gmail.com> 98 // GK doesn't check size and position of the `form` here anymore. 99 // `GetFormRect` is called **before** closing the application, but 100 // there's no guarantees that user won't change a monitor settings 101 // after that. GK should restrict position of a top window on the 102 // application startup. And I'm still not sured GK should constrain 103 // a window size (either top one or child). 104 // FIXME: If `Control::Left`, `Control::Top`, `Control::Width` and 105 // `Control::Height` return physical values (device depended), code 106 // here or code that uses the result of `GetFormRect` must convert 107 // them to logical values (device independed) before storing it as 108 // the application settings. Had GK been a native Windows 109 // application, it had to do that. But since it's a .NET application 110 // I don't know is it a true. 111 return ExtRect.Create(form.Left, form.Top, form.Right, form.Bottom); 112 } 113 RestoreFormRect(Form form, ExtRect rt, FormWindowState winState)114 public static void RestoreFormRect(Form form, ExtRect rt, FormWindowState winState) 115 { 116 // check for new and empty struct 117 if (form == null || rt.IsEmpty()) return; 118 119 if (winState != FormWindowState.Minimized) { 120 form.Left = rt.Left; 121 form.Top = rt.Top; 122 form.Width = rt.GetWidth(); 123 form.Height = rt.GetHeight(); 124 125 form.WindowState = winState; 126 } else { 127 form.WindowState = FormWindowState.Maximized; 128 } 129 } 130 CenterFormByParent(Form form, IntPtr parent)131 public static void CenterFormByParent(Form form, IntPtr parent) 132 { 133 if (form == null) return; 134 135 form.StartPosition = FormStartPosition.Manual; 136 137 // Center the new window on a monitor, where the parent window 138 // is located. 139 Screen screen = Screen.FromHandle(parent); 140 if (screen != null) { 141 Rectangle workArea = screen.WorkingArea; 142 143 form.Left = workArea.Left + ((workArea.Width - form.Width) >> 1); 144 form.Top = workArea.Top + ((workArea.Height - form.Height) >> 1); 145 } 146 } 147 GetSelectedTag(this ComboBox comboBox)148 public static T GetSelectedTag<T>(this ComboBox comboBox) 149 { 150 var comboItem = comboBox.SelectedItem as ComboItem<T>; 151 T itemTag = (comboItem != null) ? comboItem.Tag : default(T); 152 return itemTag; 153 } 154 SetSelectedTag(this ComboBox comboBox, T tagValue, bool allowDefault = true)155 public static void SetSelectedTag<T>(this ComboBox comboBox, T tagValue, bool allowDefault = true) 156 { 157 foreach (object item in comboBox.Items) { 158 var comboItem = item as ComboItem<T>; 159 160 if (comboItem != null && object.Equals(comboItem.Tag, tagValue)) { 161 comboBox.SelectedItem = item; 162 return; 163 } 164 } 165 166 if (allowDefault) { 167 comboBox.SelectedIndex = 0; 168 } 169 } 170 AddToolStripItem(ContextMenuStrip contextMenu, string text, object tag, EventHandler clickHandler)171 public static ToolStripMenuItem AddToolStripItem(ContextMenuStrip contextMenu, string text, object tag, EventHandler clickHandler) 172 { 173 var tsItem = new ToolStripMenuItem(text, null, clickHandler); 174 tsItem.Tag = tag; 175 contextMenu.Items.Add(tsItem); 176 return tsItem; 177 } 178 GetMenuItemTag(ContextMenuStrip contextMenu, object sender)179 public static T GetMenuItemTag<T>(ContextMenuStrip contextMenu, object sender) 180 { 181 foreach (ToolStripMenuItem tsItem in contextMenu.Items) { 182 tsItem.Checked = false; 183 } 184 var senderItem = ((ToolStripMenuItem)sender); 185 ((ToolStripMenuItem)sender).Checked = true; 186 return (T)senderItem.Tag; 187 } 188 SetMenuItemTag(ContextMenuStrip contextMenu, T value)189 public static void SetMenuItemTag<T>(ContextMenuStrip contextMenu, T value) 190 { 191 foreach (ToolStripMenuItem tsItem in contextMenu.Items) { 192 T itemTag = (T)tsItem.Tag; 193 if (Equals(itemTag, value)) { 194 tsItem.PerformClick(); 195 break; 196 } 197 } 198 } 199 CreateRecordsView(Control parent, IBaseContext baseContext, GDMRecordType recType)200 public static GKListView CreateRecordsView(Control parent, IBaseContext baseContext, GDMRecordType recType) 201 { 202 if (parent == null) 203 throw new ArgumentNullException("parent"); 204 205 if (baseContext == null) 206 throw new ArgumentNullException("baseContext"); 207 208 GKListView recView = new GKListView(); 209 recView.HideSelection = false; 210 recView.LabelEdit = false; 211 recView.FullRowSelect = true; 212 recView.View = View.Details; 213 recView.ListMan = ListManager.Create(baseContext, recType); 214 recView.Dock = DockStyle.Fill; 215 216 parent.Controls.Add(recView); 217 parent.Controls.SetChildIndex(recView, 0); 218 219 return recView; 220 } 221 CreateListView(Control parent)222 public static GKListView CreateListView(Control parent) 223 { 224 if (parent == null) 225 throw new ArgumentNullException("parent"); 226 227 GKListView listView = new GKListView(); 228 listView.Dock = DockStyle.Fill; 229 parent.Controls.Add(listView); 230 231 return listView; 232 } 233 ConvertColor(Color color)234 public static IColor ConvertColor(Color color) 235 { 236 return new ColorHandler(color); 237 } 238 ConvertColor(IColor color)239 public static Color ConvertColor(IColor color) 240 { 241 return ((ColorHandler)color).Handle; 242 } 243 Darker(Color color, float fraction)244 public static Color Darker(Color color, float fraction) 245 { 246 int rgb = color.ToArgb(); 247 return Color.FromArgb(GfxHelper.Darker(rgb, fraction)); 248 } 249 Lighter(Color color, float fraction)250 public static Color Lighter(Color color, float fraction) 251 { 252 int rgb = color.ToArgb(); 253 return Color.FromArgb(GfxHelper.Lighter(rgb, fraction)); 254 } 255 LoadResourceImage(string resName)256 public static Bitmap LoadResourceImage(string resName) 257 { 258 return new Bitmap(GKUtils.LoadResourceStream(resName)); 259 } 260 SetControlEnabled(Control ctl, bool enabled)261 public static void SetControlEnabled(Control ctl, bool enabled) 262 { 263 if (ctl != null) { 264 ctl.Enabled = enabled; 265 ctl.BackColor = enabled ? SystemColors.Window : SystemColors.Control; 266 } 267 } 268 SetClipboardText(string text)269 public static void SetClipboardText(string text) 270 { 271 Clipboard.SetDataObject(text); 272 } 273 ProcessName(object sender)274 public static void ProcessName(object sender) 275 { 276 TextBox tb = (sender as TextBox); 277 if (tb != null && GlobalOptions.Instance.FirstCapitalLetterInNames) { 278 tb.Text = ConvertHelper.UniformName(tb.Text); 279 } 280 281 ComboBox cmb = (sender as ComboBox); 282 if (cmb != null && GlobalOptions.Instance.FirstCapitalLetterInNames) { 283 cmb.Text = ConvertHelper.UniformName(cmb.Text); 284 } 285 } 286 FixToolStrip(ToolStrip toolStrip)287 public static void FixToolStrip(ToolStrip toolStrip) 288 { 289 #if MONO 290 // dirty hack: Mono ToolStrip does not support correct AutoSize 291 toolStrip.AutoSize = false; 292 toolStrip.Height = 27; 293 #endif 294 } 295 296 #region Application's autorun 297 #if !MONO 298 RegisterStartup()299 public static void RegisterStartup() 300 { 301 if (!IsStartupItem()) { 302 RegistryKey rkApp = GetRunKey(); 303 if (rkApp != null) { 304 string trayPath = GKUtils.GetAppPath() + "GKTray.exe"; 305 rkApp.SetValue(GKData.APP_TITLE, trayPath); 306 } 307 } 308 } 309 310 public static void UnregisterStartup() 311 { 312 if (IsStartupItem()) { 313 RegistryKey rkApp = GetRunKey(); 314 if (rkApp != null) { 315 rkApp.DeleteValue(GKData.APP_TITLE, false); 316 } 317 } 318 } 319 320 public static bool IsStartupItem() 321 { 322 RegistryKey rkApp = GetRunKey(); 323 return (rkApp != null && rkApp.GetValue(GKData.APP_TITLE) != null); 324 } 325 326 private static RegistryKey GetRunKey() 327 { 328 RegistryKey rkApp = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true); 329 return rkApp; 330 } 331 332 #endif 333 #endregion 334 } 335 } 336