using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Reflection; using UserControls.Properties; using System.Resources; using AutocompleteMenuNS; using CaeGlobals; using System.Diagnostics; using System.Drawing; namespace UserControls { // http://kiwigis.blogspot.si/2009/05/adding-tab-key-support-to-propertygrid.html public class TabEnabledPropertyGrid : PropertyGrid { // Variables private AutocompleteMenu autocompleteMenu; private TextBox _editControl; private bool _tabInitialized; private bool _readOnly; // Variables public bool ReadOnly { get { return _readOnly; } set { _readOnly = value; } } // Constructors public TabEnabledPropertyGrid() : base() { InitializeComponent(); // this.LineColor = System.Drawing.SystemColors.Control; this.DisabledItemForeColor = System.Drawing.Color.FromArgb(80, 80, 80); // _tabInitialized = false; _readOnly = false; // BuildAutocompleteMenu(new string[0]); } private void InitializeComponent() { this.autocompleteMenu = new AutocompleteMenu(); this.SuspendLayout(); // // autocompleteMenu // this.autocompleteMenu.AllowsTabKey = true; this.autocompleteMenu.Font = new Font("Segoe UI", 9F); this.autocompleteMenu.ImageList = null; this.autocompleteMenu.Items = new string[0]; this.autocompleteMenu.MaximumSize = new Size(600, 200); this.autocompleteMenu.MinFragmentLength = 1; this.autocompleteMenu.SearchPattern = "[\\w\\.\\-]+"; this.autocompleteMenu.TargetControlWrapper = null; this.ResumeLayout(false); } // Event handlers private void Form_KeyDown(object sender, KeyEventArgs e) { if (!this.ContainsFocus) return; if (autocompleteMenu.Visible) { if (e.KeyCode == Keys.Enter || e.KeyCode == Keys.Tab || e.KeyCode == Keys.Escape) { e.Handled = true; e.SuppressKeyPress = true; } // if (e.KeyCode == Keys.Enter) autocompleteMenu.ProcessKey((char)Keys.Return, Keys.None); else if (e.KeyCode == Keys.Tab) autocompleteMenu.ProcessKey((char)Keys.Tab, Keys.None); else if (e.KeyCode == Keys.Escape) autocompleteMenu.ProcessKey((char)Keys.Escape, Keys.None); // return; } // Handle tab key of the property grid if (e.KeyCode == Keys.Tab) { e.Handled = true; e.SuppressKeyPress = true; // Get selected grid item GridItem gridItem = this.SelectedGridItem; if (gridItem == null) { return; } // Create a collection all visible child grid items in property grid GridItem root = gridItem; while (root.GridItemType != GridItemType.Root) { root = root.Parent; } List gridItems = new List(); this.FindItems(root, gridItems); // Get position of selected grid item in collection int index = gridItems.IndexOf(gridItem); int nextIndex = index + 1; if (nextIndex >= gridItems.Count) { e.Handled = false; e.SuppressKeyPress = false; return; } // Select next grid item in collection this.SelectedGridItem = gridItems[nextIndex]; SendKeys.Send("{Tab}"); } } private void FindItems(GridItem item, List gridItems) { switch (item.GridItemType) { case GridItemType.Root: case GridItemType.Category: foreach (GridItem i in item.GridItems) { this.FindItems(i, gridItems); } break; case GridItemType.Property: gridItems.Add(item); if (item.Expanded) { foreach (GridItem i in item.GridItems) { this.FindItems(i, gridItems); } } break; case GridItemType.ArrayValue: break; } } // Autocomplete menu private void AttachAutocompleteToInternalTextBox() { TextBox editTextBox = FindPropertyGridTextBox(); if (editTextBox != null) { // Add autocompleteMenu to edit control _editControl = editTextBox; _editControl.TextChanged += EditControl_TextChanged; _editControl.PreviewKeyDown += EditControl_PreviewKeyDown; autocompleteMenu.SetAutocompleteMenu(editTextBox, autocompleteMenu); } } private void DetachAutocompleteFromInternalTextBox() { if (_editControl != null) { // Remove autocompleteMenu from edit control autocompleteMenu.TargetControlWrapper = null; autocompleteMenu.SetAutocompleteMenu(_editControl, null); _editControl.TextChanged -= EditControl_TextChanged; _editControl.PreviewKeyDown -= EditControl_PreviewKeyDown; _editControl = null; } } private TextBox FindPropertyGridTextBox() { foreach (Control control in Controls) { if (control.GetType().Name == "PropertyGridView") { foreach (Control subControl in control.Controls) { if (subControl is TextBox tb && tb.Visible && !tb.ReadOnly) return tb; } } } return null; } private void EditControl_TextChanged(object sender, EventArgs e) { autocompleteMenu.Enabled = _editControl != null && _editControl.Text.Trim().Length > 0 && _editControl.Text.Trim()[0] == '='; } private void EditControl_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) { // Must be active to forward these keys to if (autocompleteMenu.Visible) { if (e.KeyCode == Keys.Enter || e.KeyCode == Keys.Tab || e.KeyCode == Keys.Escape) e.IsInputKey = true; } } // Overrides protected override void OnSelectedObjectsChanged(EventArgs e) { // Site if (Site == null) Site = new MySite(this); // For the Tab key to work set the key event handlers Control parent = this.Parent; while (!_tabInitialized && parent != null) { if (parent is Form frm) { // Set this property to intercept all events frm.KeyPreview = true; // Listen for keydown event frm.KeyDown += new KeyEventHandler(this.Form_KeyDown); // _tabInitialized = true; } // parent = parent.Parent; } // base.OnSelectedObjectsChanged(e); } protected override void OnGotFocus(EventArgs e) { //System.Diagnostics.Debug.WriteLine(DateTime.Now.Millisecond + " OnGotFocus"); //// Get selected griditem //GridItem gridItem = this.SelectedGridItem; //if (gridItem == null) { return; } //// Create a collection all visible child griditems in propertygrid //GridItem root = gridItem; //while (root.GridItemType != GridItemType.Root) //{ // root = root.Parent; //} //List gridItems = new List(); //this.FindItems(root, gridItems); ////this.SelectedGridItem = gridItems[0]; //this.SelectedGridItem = gridItem; ////SendKeys.Send("{Tab}"); base.OnGotFocus(e); } protected override void OnEnter(EventArgs e) { //System.Diagnostics.Debug.WriteLine(DateTime.Now.Millisecond + " OnEnter"); // Get selected griditem GridItem gridItem = this.SelectedGridItem; if (gridItem == null) { return; } // Create a collection all visible child griditems in propertygrid GridItem root = gridItem; while (root.GridItemType != GridItemType.Root) { root = root.Parent; } List gridItems = new List(); this.FindItems(root, gridItems); // if (gridItems[0].Expanded) this.SelectedGridItem = gridItems[0]; // base.OnEnter(e); } protected override void OnSelectedGridItemChanged(SelectedGridItemChangedEventArgs e) { if (_readOnly) { if (e.NewSelection.GridItemType == GridItemType.Property) { if (e.NewSelection.Parent != null && e.NewSelection.Parent.GridItemType == GridItemType.Category) { this.SelectedGridItem = e.NewSelection.Parent; return; } } } else base.OnSelectedGridItemChanged(e); // this.BeginInvoke(new Action(DetachAutocompleteFromInternalTextBox)); this.BeginInvoke(new Action(AttachAutocompleteToInternalTextBox)); } // Methods public void SetLabelColumnWidth(double labelRatio) { // get the grid view Control view = (Control)typeof(PropertyGrid).GetField("gridView", BindingFlags.Instance | BindingFlags.NonPublic).GetValue((PropertyGrid)this); //Control view = (Control)typeof(PropertyGrid).GetField("gridView", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(grid); // set label width //FieldInfo fi = view.GetType().GetField("labelWidth", BindingFlags.Instance | BindingFlags.NonPublic); //fi.SetValue(view, width); FieldInfo fi2 = view.GetType().GetField("labelRatio"); fi2.SetValue(view, labelRatio); // refresh view.Invalidate(); } // Autocomplete menu public void BuildAutocompleteMenu(IEnumerable items) { List autoCompleteItems = new List(); var constants = MyNCalc.GetFunctionConstants(); autoCompleteItems.AddRange(items); autoCompleteItems.AddRange(constants); autoCompleteItems.Sort(); List acItems = new List(); foreach (var item in autoCompleteItems) acItems.Add(new AutocompleteItem(item)); // var snippets = MyNCalc.GetFunctionSnippets(); foreach (var snippet in snippets) acItems.Add(new SnippetAutocompleteItem(snippet)); // Set as autocomplete source autocompleteMenu.SetAutocompleteItems(acItems); } } }