1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297 |
- // Permission is hereby granted, free of charge, to any person obtaining
- // a copy of this software and associated documentation files (the
- // "Software"), to deal in the Software without restriction, including
- // without limitation the rights to use, copy, modify, merge, publish,
- // distribute, sublicense, and/or sell copies of the Software, and to
- // permit persons to whom the Software is furnished to do so, subject to
- // the following conditions:
- //
- // The above copyright notice and this permission notice shall be
- // included in all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- //
- // Copyright (c) 2005-2008 Novell, Inc. (http://www.novell.com)
- //
- // Authors:
- // Jonathan Chambers (jonathan.chambers@ansys.com)
- // Ivan N. Zlatev (contact@i-nz.net)
- //
- //
- // NOT COMPLETE
- using CustomControls;
- using System.Collections;
- using System.ComponentModel;
- using System.Drawing;
- using System.Drawing.Design;
- using System.Windows.Forms.Design;
- namespace System.Windows.Forms.PropertyGridInternal
- {
- internal class PropertyGridView : UserControl, IWindowsFormsEditorService
- {
- #region Private Members
- private const char PASSWORD_PAINT_CHAR = '\u25cf'; // the dot char
- private const char PASSWORD_TEXT_CHAR = '*';
- private int V_INDENT = 16; // dpi dependent
- private const int ENTRY_SPACING = 2;
- private const int RESIZE_WIDTH = 3;
- private int VALUE_PAINT_WIDTH = 19; // dpi dependent
- private int VALUE_PAINT_INDENT = 22; // dpi dependent
- private int BOOL_PAINT_WIDTH = 11;
- private int BOOL_PAINT_INDENT = 15;
- private double splitter_percent = .5;
- private int row_height;
- private int font_height_padding = 3;
- private PropertyGridTextBox grid_textbox;
- private PropertyGrid property_grid;
- private bool resizing_grid;
- private VScrollBar vbar;
- private StringFormat string_format;
- private Font bold_font;
- private Brush inactive_text_brush;
- private ListBox dropdown_list;
- private Drawing.Point last_click;
- private ToolStripDropDown dropdown;
- #endregion
- #region Contructors
- public PropertyGridView(PropertyGrid propertyGrid)
- {
- property_grid = propertyGrid;
- this.Font = new Font("Segoe UI", 8.5f);
- bold_font = new Font(this.Font, Drawing.FontStyle.Bold);
- row_height = Font.Height + font_height_padding;
- string_format = new StringFormat();
- string_format.FormatFlags = StringFormatFlags.NoWrap;
- string_format.Trimming = StringTrimming.None;
- grid_textbox = new PropertyGridTextBox();
- grid_textbox.DropDownButtonClicked += DropDownButtonClicked;
- grid_textbox.DialogButtonClicked += DialogButtonClicked;
- vbar = new VScrollBar();
- vbar.Visible = false;
- vbar.Value = 0;
- vbar.ValueChanged += VScrollBar_HandleValueChanged;
- vbar.Dock = DockStyle.Right;
- this.Controls.Add(vbar);
- grid_textbox.Visible = false;
- grid_textbox.Font = this.Font;
- grid_textbox.BackColor = Drawing.SystemColors.Window;
- grid_textbox.ToggleValue += grid_textbox_ToggleValue;
- grid_textbox.KeyDown += grid_textbox_KeyDown;
- grid_textbox.MouseEnter += (s, e) => this.Cursor = Cursors.Default; // fix issue with splitter cursor
- grid_textbox.Validate += grid_textbox_Validate;
- this.Controls.Add(grid_textbox);
- resizing_grid = false;
- inactive_text_brush = new SolidBrush(Drawing.SystemColors.GrayText);
- BackColorChanged += new System.EventHandler(RedrawEvent);
- SetStyle(ControlStyles.Selectable, true);
- SetStyle(ControlStyles.DoubleBuffer, true);
- SetStyle(ControlStyles.UserPaint, true);
- SetStyle(ControlStyles.AllPaintingInWmPaint, true);
- SetStyle(ControlStyles.ResizeRedraw, true);
- UpdateDpiDependencies();
- }
- #endregion
- private GridEntry RootGridItem
- {
- get { return (GridEntry)property_grid.RootGridItem; }
- }
- private GridEntry SelectedGridItem
- {
- get { return (GridEntry)property_grid.SelectedGridItem; }
- set { property_grid.SelectedGridItem = value; }
- }
- #region Protected Instance Methods
- protected override void OnFontChanged(EventArgs e)
- {
- base.OnFontChanged(e);
- bold_font = new Font(this.Font, Drawing.FontStyle.Bold);
- row_height = Font.Height + font_height_padding;
- }
- protected override void OnRightToLeftChanged(EventArgs e)
- {
- base.OnRightToLeftChanged(e);
- if (RightToLeft == RightToLeft.Yes)
- {
- string_format.FormatFlags |= StringFormatFlags.DirectionRightToLeft;
- vbar.Dock = DockStyle.Left;
- }
- else
- {
- string_format.FormatFlags &= ~StringFormatFlags.DirectionRightToLeft;
- vbar.Dock = DockStyle.Right;
- }
- }
- private void InvalidateItemLabel(GridEntry item)
- {
- Invalidate(new Rectangle(0, item.Top, SplitterLocation, row_height));
- }
- private void InvalidateItem(GridEntry item)
- {
- if (item == null)
- return;
- Rectangle rect = new Rectangle(0, item.Top, Width, row_height);
- Invalidate(rect);
- if (item.Expanded)
- {
- rect = new Rectangle(0, item.Top + row_height, Width,
- Height - (item.Top + row_height));
- Invalidate(rect);
- }
- }
- // [+] expanding is handled in OnMouseDown, so in order to prevent
- // duplicate expanding ignore it here.
- //
- protected override void OnDoubleClick(EventArgs e)
- {
- if (this.SelectedGridItem != null && this.SelectedGridItem.Expandable &&
- !this.SelectedGridItem.PlusMinusBounds.Contains(last_click))
- this.SelectedGridItem.Expanded = !this.SelectedGridItem.Expanded;
- else
- ToggleValue(this.SelectedGridItem);
- }
- protected override void OnPaint(PaintEventArgs e)
- {
- // Background
- e.Graphics.FillRectangle(ResPool.GetSolidBrush(BackColor), ClientRectangle);
- int yLoc = -vbar.Value * row_height;
- if (this.RootGridItem != null)
- DrawGridItems(this.RootGridItem.GridItems, e, 1, ref yLoc);
- if (property_grid.BorderStyle != BorderStyle.None)
- this.DrawVisualStyleBorder(e.Graphics, new Rectangle(0, 0, Width - 1, Height - 1));
- UpdateScrollBar();
- }
- protected override void OnMouseWheel(MouseEventArgs e)
- {
- if (vbar == null || !vbar.Visible)
- return;
- if (e.Delta < 0)
- vbar.Value = Math.Min(vbar.Maximum - GetVisibleRowsCount() + 1, vbar.Value + 3);
- else
- vbar.Value = Math.Max(0, vbar.Value - 3);
- base.OnMouseWheel(e);
- }
- protected override void OnMouseMove(MouseEventArgs e)
- {
- if (this.RootGridItem == null)
- return;
- if (resizing_grid)
- {
- int loc = Math.Max(e.X, 2 * V_INDENT);
- SplitterPercent = 1.0 * loc / Width;
- }
- if (e.X > SplitterLocation - RESIZE_WIDTH && e.X < SplitterLocation + RESIZE_WIDTH)
- this.Cursor = Cursors.VSplit;
- else
- this.Cursor = Cursors.Default;
- base.OnMouseMove(e);
- }
- protected override void OnMouseDown(MouseEventArgs e)
- {
- base.OnMouseDown(e);
- last_click = e.Location;
- if (this.RootGridItem == null)
- return;
- if (e.X > SplitterLocation - RESIZE_WIDTH && e.X < SplitterLocation + RESIZE_WIDTH)
- {
- resizing_grid = true;
- }
- else
- {
- int offset = -vbar.Value * row_height;
- GridItem foundItem = GetSelectedGridItem(this.RootGridItem.GridItems, e.Y, ref offset);
- if (foundItem != null)
- {
- if (foundItem.Expandable && ((GridEntry)foundItem).PlusMinusBounds.Contains(e.X, e.Y))
- foundItem.Expanded = !foundItem.Expanded;
- this.SelectedGridItem = (GridEntry)foundItem;
- if (!GridLabelHitTest(e.X))
- {
- if (this.SelectedGridItem.IsBool)
- ToggleValue(this.SelectedGridItem);
- else
- {
- // send mouse down so we get the carret under cursor
- grid_textbox.SendMouseDown(e.X - grid_textbox.Left);
- }
- }
- }
- }
- }
- protected override void OnMouseUp(MouseEventArgs e)
- {
- resizing_grid = false;
- base.OnMouseUp(e);
- }
- protected override void OnResize(EventArgs e)
- {
- base.OnResize(e);
- if (this.SelectedGridItem != null) // initialized already
- UpdateView();
- }
- internal override void AfterDpiChange(float rescale)
- {
- UpdateDpiDependencies();
- base.AfterDpiChange(rescale);
- }
- private void UpdateDpiDependencies()
- {
- V_INDENT = _dpi(16);
- VALUE_PAINT_WIDTH = _dpi(19);
- VALUE_PAINT_INDENT = _dpi(22);
- BOOL_PAINT_WIDTH = _dpi(11);
- BOOL_PAINT_INDENT = _dpi(15);
- }
- private void UnfocusSelection()
- {
- Focus();
- }
- private void FocusSelection()
- {
- grid_textbox.Focus();
- }
- protected override bool ProcessDialogKey(Keys keyData)
- {
- GridEntry selectedItem = this.SelectedGridItem;
- if (selectedItem != null
- && grid_textbox.Visible)
- {
- switch (keyData)
- {
- case Keys.Enter:
- if (TrySetEntry(selectedItem, grid_textbox.Text))
- UnfocusSelection();
- return true;
- case Keys.Escape:
- if (selectedItem.IsEditable)
- UpdateItem(selectedItem); // reset value
- UnfocusSelection();
- return true;
- case Keys.Tab:
- FocusSelection();
- grid_textbox.SelectAll();
- return true;
- default:
- return false;
- }
- }
- return base.ProcessDialogKey(keyData);
- }
- private bool TrySetEntry(GridEntry entry, object value)
- {
- if (entry == null || grid_textbox.Text.Equals(entry.ValueText))
- return true;
- if (entry.IsEditable || !entry.IsEditable && (entry.HasCustomEditor || entry.AcceptedValues != null) ||
- !entry.IsMerged || entry.HasMergedValue ||
- (!entry.HasMergedValue && grid_textbox.Text != String.Empty))
- {
- string error = null;
- bool changed = entry.SetValue(value, out error);
- if (!changed && error != null)
- {
- if (property_grid.ShowError(error, MessageBoxButtons.OKCancel) == DialogResult.Cancel)
- {
- UpdateItem(entry); // restore value, repaint, etc
- UnfocusSelection();
- }
- return false;
- }
- else if (changed)
- {
- entry = SelectedGridItem;
- }
- }
- UpdateItem(entry); // restore value, repaint, etc
- return true;
- }
- protected override bool IsInputKey(Keys keyData)
- {
- switch (keyData)
- {
- case Keys.Left:
- case Keys.Right:
- case Keys.Enter:
- case Keys.Escape:
- case Keys.Up:
- case Keys.Down:
- case Keys.PageDown:
- case Keys.PageUp:
- case Keys.Home:
- case Keys.End:
- return true;
- default:
- return false;
- }
- }
- private GridEntry MoveUpFromItem(GridEntry item, int up_count)
- {
- GridItemCollection items;
- int index;
- /* move back up the visible rows (and up the hierarchy as necessary) until
- up_count == 0, or we reach the top of the display */
- while (up_count > 0)
- {
- items = item.Parent != null ? item.Parent.GridItems : this.RootGridItem.GridItems;
- index = items.IndexOf(item);
- if (index == 0)
- {
- if (item.Parent.GridItemType == GridItemType.Root) // we're at the top row
- return item;
- item = (GridEntry)item.Parent;
- up_count--;
- }
- else
- {
- GridEntry prev_item = (GridEntry)items[index - 1];
- if (prev_item.Expandable && prev_item.Expanded && prev_item.GridItems.Count > 0)
- {
- item = (GridEntry)prev_item.GridItems[prev_item.GridItems.Count - 1];
- }
- else
- {
- item = prev_item;
- }
- up_count--;
- }
- }
- return item;
- }
- private GridEntry MoveDownFromItem(GridEntry item, int down_count)
- {
- while (down_count > 0)
- {
- /* if we're a parent node and we're expanded, move to our first child */
- if (item.Expandable && item.Expanded && item.GridItems.Count > 0)
- {
- item = (GridEntry)item.GridItems[0];
- down_count--;
- }
- else
- {
- GridItem searchItem = item;
- GridItemCollection searchItems = searchItem.Parent.GridItems;
- int searchIndex = searchItems.IndexOf(searchItem);
- while (searchIndex == searchItems.Count - 1)
- {
- searchItem = searchItem.Parent;
- if (searchItem == null || searchItem.Parent == null)
- break;
- searchItems = searchItem.Parent.GridItems;
- searchIndex = searchItems.IndexOf(searchItem);
- }
- if (searchIndex == searchItems.Count - 1)
- {
- /* if we got all the way back to the root with no nodes after
- us, the original item was the last one */
- return item;
- }
- else
- {
- item = (GridEntry)searchItems[searchIndex + 1];
- down_count--;
- }
- }
- }
- return item;
- }
- protected override void OnKeyDown(KeyEventArgs e)
- {
- GridEntry selectedItem = this.SelectedGridItem;
- if (selectedItem == null)
- {
- /* XXX not sure what MS does, but at least we shouldn't crash */
- base.OnKeyDown(e);
- return;
- }
- switch (e.KeyData & Keys.KeyCode)
- {
- case Keys.Left:
- if (e.Control)
- {
- if (SplitterLocation > 2 * V_INDENT)
- SplitterPercent -= 0.01;
- e.Handled = true;
- break;
- }
- else
- {
- /* if the node is expandable and is expanded, collapse it.
- otherwise, act just like the user pressed up */
- if (selectedItem.Expandable && selectedItem.Expanded)
- {
- selectedItem.Expanded = false;
- e.Handled = true;
- break;
- }
- else
- goto case Keys.Up;
- }
- case Keys.Right:
- if (e.Control)
- {
- if (SplitterLocation < Width)
- SplitterPercent += 0.01;
- e.Handled = true;
- break;
- }
- else
- {
- /* if the node is expandable and not expanded, expand it.
- otherwise, act just like the user pressed down */
- if (selectedItem.Expandable && !selectedItem.Expanded)
- {
- selectedItem.Expanded = true;
- e.Handled = true;
- break;
- }
- else
- goto case Keys.Down;
- }
- case Keys.Enter:
- /* toggle the expanded state of the selected item */
- if (selectedItem.Expandable)
- {
- selectedItem.Expanded = !selectedItem.Expanded;
- }
- e.Handled = true;
- break;
- case Keys.Up:
- this.SelectedGridItem = MoveUpFromItem(selectedItem, 1);
- e.Handled = true;
- break;
- case Keys.Down:
- this.SelectedGridItem = MoveDownFromItem(selectedItem, 1);
- e.Handled = true;
- break;
- case Keys.PageUp:
- this.SelectedGridItem = MoveUpFromItem(selectedItem, vbar.LargeChange);
- e.Handled = true;
- break;
- case Keys.PageDown:
- this.SelectedGridItem = MoveDownFromItem(selectedItem, vbar.LargeChange);
- e.Handled = true;
- break;
- case Keys.End:
- /* find the last, most deeply nested visible item */
- GridEntry item = (GridEntry)this.RootGridItem.GridItems[this.RootGridItem.GridItems.Count - 1];
- while (item.Expandable && item.Expanded)
- item = (GridEntry)item.GridItems[item.GridItems.Count - 1];
- this.SelectedGridItem = item;
- e.Handled = true;
- break;
- case Keys.Home:
- this.SelectedGridItem = (GridEntry)this.RootGridItem.GridItems[0];
- e.Handled = true;
- break;
- }
- if (!e.Handled)
- {
- if (selectedItem != null && selectedItem.IsEditable && grid_textbox.Visible && Focused)
- {
- grid_textbox.Text = "";
- FocusSelection();
- }
- }
- base.OnKeyDown(e);
- }
- #endregion
- #region Private Helper Methods
- private int SplitterLocation
- {
- get
- {
- return (int)(splitter_percent * Width);
- }
- }
- private double SplitterPercent
- {
- set
- {
- int old_splitter_location = SplitterLocation;
- splitter_percent = Math.Max(Math.Min(value, .9), .1);
- if (old_splitter_location != SplitterLocation)
- {
- int x = old_splitter_location > SplitterLocation ? SplitterLocation : old_splitter_location;
- Invalidate(new Rectangle(x, 0, Width - x - (vbar.Visible ? vbar.Width : 0), Height));
- UpdateItem(this.SelectedGridItem);
- }
- }
- get
- {
- return splitter_percent;
- }
- }
- private bool GridLabelHitTest(int x)
- {
- bool rtl = RightToLeft == RightToLeft.Yes;
- if (!rtl && x >= 0 && x <= SplitterLocation)
- return true;
- if (rtl && x >= SplitterLocation && x <= Width)
- return true;
- return false;
- }
- private GridItem GetSelectedGridItem(GridItemCollection grid_items, int y, ref int current)
- {
- foreach (GridItem child_grid_item in grid_items)
- {
- if (y > current && y < current + row_height)
- {
- return child_grid_item;
- }
- current += row_height;
- if (child_grid_item.Expanded)
- {
- GridItem foundItem = GetSelectedGridItem(child_grid_item.GridItems, y, ref current);
- if (foundItem != null)
- return foundItem;
- }
- }
- return null;
- }
- private int GetVisibleItemsCount(GridEntry entry)
- {
- if (entry == null)
- return 0;
- int count = 0;
- foreach (GridEntry e in entry.GridItems)
- {
- count += 1;
- if (e.Expandable && e.Expanded)
- count += GetVisibleItemsCount(e);
- }
- return count;
- }
- private int GetVisibleRowsCount()
- {
- if (Height <= 0)
- return 0;
- return (this.Height - this.Padding.Vertical) / row_height;
- }
- private void UpdateScrollBar()
- {
- if (this.RootGridItem == null)
- return;
- int visibleRows = GetVisibleRowsCount();
- int openedItems = GetVisibleItemsCount(this.RootGridItem);
- if (openedItems > visibleRows)
- {
- vbar.Visible = true;
- vbar.SmallChange = 1;
- vbar.LargeChange = visibleRows;
- vbar.Maximum = Math.Max(0, openedItems);
- }
- else
- {
- vbar.Value = 0;
- vbar.Visible = false;
- }
- UpdateGridTextBoxBounds(this.SelectedGridItem);
- }
- #region Drawing Code
- private void DrawGridItems(GridItemCollection grid_items, PaintEventArgs pevent, int depth, ref int yLoc)
- {
- foreach (GridItem grid_item in grid_items)
- {
- DrawGridItem((GridEntry)grid_item, pevent, depth, ref yLoc);
- if (grid_item.Expanded)
- DrawGridItems(grid_item.GridItems, pevent, (grid_item.GridItemType == GridItemType.Category) ? depth : depth + 1, ref yLoc);
- }
- }
- private void DrawGridItemLabel(GridEntry grid_item, PaintEventArgs pevent, int depth, Rectangle rect)
- {
- bool rtl = RightToLeft == RightToLeft.Yes;
- Font font = this.Font;
- Brush brush;
- if (grid_item.GridItemType == GridItemType.Category)
- {
- font = bold_font;
- brush = ResPool.GetSolidBrush(property_grid.CategoryForeColor);
- }
- else
- {
- if (grid_item == this.SelectedGridItem)
- {
- Rectangle highlight = rect;
- if (depth > 1)
- {
- highlight.X -= rtl ? 0 : (depth - 1) * V_INDENT;
- highlight.Width += (depth - 1) * V_INDENT;
- }
- pevent.Graphics.FillRectangle(SystemBrushes.Highlight, highlight);
- // Label
- brush = SystemBrushes.HighlightText;
- }
- else
- {
- brush = grid_item.IsReadOnly && !grid_item.Expandable ? inactive_text_brush : SystemBrushes.ControlText;
- }
- }
- pevent.Graphics.DrawString(grid_item.Label, font, brush,
- new Rectangle(rect.X + 1, rect.Y + ENTRY_SPACING, rect.Width - ENTRY_SPACING, rect.Height - ENTRY_SPACING),
- string_format);
- }
- private void DrawBoolValue(GridEntry grid_item, Graphics g, Rectangle r)
- {
- if (grid_item.Value is bool b && b == true)
- {
- g.FillRectangle(Brushes.Gray, r);
- g.SmoothingMode = Drawing.Drawing2D.SmoothingMode.AntiAlias;
- g.DrawLines(ResPool.GetPen(Color.White, _dpi(1f)), new PointF[]
- {
- new PointF(r.X + _dpi(2.5f), r.Y + r.Height / 2),
- new PointF(r.X + r.Width / 2 - _dpi(0.5f), r.Bottom - _dpi(4f)),
- new PointF(r.Right - _dpi(2.5f), r.Y + _dpi(3f))
- });
- g.SmoothingMode = Drawing.Drawing2D.SmoothingMode.None;
- }
- g.DrawRectangle(Pens.Gray, r);
- }
- private void DrawPaintValue(GridEntry grid_item, Graphics g, Rectangle r)
- {
- grid_item.PaintValue(g, r);
- g.DrawRectangle(Pens.Black, r);
- }
- private void DrawGridItemValue(GridEntry grid_item, PaintEventArgs pevent, int y)
- {
- if (grid_item.PropertyDescriptor == null)
- return;
- bool rtl = RightToLeft == RightToLeft.Yes;
- int vBarWidth = vbar.Visible ? vbar.Width : 0;
- int xLoc = (rtl ? vBarWidth : SplitterLocation) + ENTRY_SPACING;
- int widthAdj = rtl ? 0 : vBarWidth;
-
- if (grid_item.IsBool)
- {
- int xRect = rtl ? SplitterLocation - BOOL_PAINT_INDENT : xLoc + _dpi(2);
- DrawBoolValue(grid_item, pevent.Graphics, new Rectangle(xRect, y + (row_height - BOOL_PAINT_WIDTH) / 2, BOOL_PAINT_WIDTH, BOOL_PAINT_WIDTH));
- xLoc += rtl ? 0 : BOOL_PAINT_INDENT;
- widthAdj += rtl ? BOOL_PAINT_INDENT : 0;
- }
- if (grid_item.PaintValueSupported)
- {
- int xRect = rtl ? SplitterLocation - VALUE_PAINT_WIDTH - ENTRY_SPACING * 2 : xLoc;
- DrawPaintValue(grid_item, pevent.Graphics, new Rectangle(xRect, y + 2, VALUE_PAINT_WIDTH + 1, row_height - ENTRY_SPACING * 2));
- xLoc += rtl ? 0 : VALUE_PAINT_INDENT;
- widthAdj += rtl ? VALUE_PAINT_INDENT + ENTRY_SPACING : 0;
- }
- Font font = this.Font;
- if (grid_item.IsResetable || !grid_item.HasDefaultValue)
- font = bold_font;
-
- Brush brush = grid_item.IsReadOnly && !grid_item.Expandable ? inactive_text_brush : SystemBrushes.ControlText;
- string valueText = String.Empty;
- if (!grid_item.IsMerged || grid_item.IsMerged && grid_item.HasMergedValue)
- {
- if (grid_item.IsPassword)
- valueText = new String(PASSWORD_PAINT_CHAR, grid_item.ValueText.Length);
- else
- valueText = grid_item.ValueText;
- }
- pevent.Graphics.DrawString(valueText, font, brush,
- new RectangleF(xLoc, y + ENTRY_SPACING, (rtl ? SplitterLocation - ENTRY_SPACING : Width) - xLoc - widthAdj - 2, row_height - ENTRY_SPACING * 2),
- string_format);
- }
- private void DrawGridItem(GridEntry grid_item, PaintEventArgs pevent, int depth, ref int yLoc)
- {
- bool rtl = RightToLeft == RightToLeft.Yes;
- if (yLoc > -row_height && yLoc < Height)
- {
- // Left column
- pevent.Graphics.FillRectangle(ResPool.GetSolidBrush(property_grid.LineColor),
- rtl ? Width - V_INDENT : 0, yLoc, V_INDENT, row_height);
- if (grid_item.GridItemType == GridItemType.Category)
- {
- var rect = new Rectangle(rtl ? 0 : depth * V_INDENT, yLoc, Width - (depth * V_INDENT), row_height);
- pevent.Graphics.FillRectangle(ResPool.GetSolidBrush(property_grid.LineColor), rect);
- DrawGridItemLabel(grid_item, pevent, depth, rect);
- }
- else
- {
- int labelWidth = (rtl ? Width - SplitterLocation : SplitterLocation) - depth * V_INDENT;
- DrawGridItemLabel(grid_item, pevent, depth,
- new Rectangle(rtl ? SplitterLocation : depth * V_INDENT, yLoc, labelWidth, row_height));
- DrawGridItemValue(grid_item, pevent, yLoc);
-
- Pen pen = ResPool.GetPen(property_grid.LineColor);
- // vertical divider line
- pevent.Graphics.DrawLine(pen, SplitterLocation, yLoc, SplitterLocation, yLoc + row_height);
- // draw the horizontal line
- pevent.Graphics.DrawLine(pen, 0, yLoc + row_height, Width, yLoc + row_height);
- }
-
- if (grid_item.Expandable)
- {
- int y = yLoc + row_height / 2;
- grid_item.PlusMinusBounds = DrawPlusMinus(pevent.Graphics, rtl ? Width - (depth - 1) * V_INDENT - ENTRY_SPACING : (depth - 1) * V_INDENT,
- y, grid_item.Expanded, grid_item == this.SelectedGridItem, depth - 1);
- }
- }
- grid_item.Top = yLoc;
- yLoc += row_height;
- }
- private Rectangle DrawPlusMinus(Graphics g, int x, int y, bool expanded, bool selected, int level)
- {
- Color color = selected && level > 0 ? Drawing.SystemColors.HighlightText : property_grid.ViewForeColor;
- Pen pen = ResPool.GetPen(color, _dpi(1.5f));
- g.SmoothingMode = Drawing.Drawing2D.SmoothingMode.AntiAlias;
- bool rtl = RightToLeft == RightToLeft.Yes;
- int _rtl = rtl ? -1 : 1;
- int _4 = _dpi(4);
- int _8 = _dpi(8);
- int _10 = _dpi(10);
- Rectangle bounds = new Rectangle(rtl ? x - _10 : x + _dpi(2), y - _4, _10, _10);
- if (!expanded)
- {
- x += _dpi(5) * _rtl;
- y -= _4;
- g.DrawLines(pen, new PointF[]
- {
- new PointF(x, y),
- new PointF(x + _4 * _rtl, y + _4),
- new PointF(x, y + _8)
- });
- }
- else
- {
- x += _dpi(3) * _rtl;
- y -= _dpi(1);
- g.DrawLines(pen, new PointF[]
- {
- new PointF(x, y),
- new PointF(x + _4 * _rtl, y + _4),
- new PointF(x + _8 * _rtl, y)
- });
- }
- g.SmoothingMode = Drawing.Drawing2D.SmoothingMode.None;
- return bounds;
- }
- #endregion
- #region Event Handling
- private void RedrawEvent(object sender, System.EventArgs e)
- {
- Refresh();
- }
- #endregion
- private void listBox_MouseUp(object sender, MouseEventArgs e)
- {
- AcceptListBoxSelection(sender);
- }
- private void listBox_KeyDown(object sender, KeyEventArgs e)
- {
- switch (e.KeyData & Keys.KeyCode)
- {
- case Keys.Enter:
- AcceptListBoxSelection(sender);
- return;
- case Keys.Escape:
- CloseDropDown();
- return;
- }
- }
- private void AcceptListBoxSelection(object sender)
- {
- GridEntry entry = this.SelectedGridItem;
- if (entry != null)
- {
- grid_textbox.Text = (string)((ListBox)sender).SelectedItem;
- CloseDropDown();
- if (TrySetEntry(entry, grid_textbox.Text))
- UnfocusSelection();
- }
- }
- private void DropDownButtonClicked(object sender, EventArgs e)
- {
- DropDownEdit();
- }
- private void DropDownEdit()
- {
- GridEntry entry = this.SelectedGridItem;
- if (entry == null)
- return;
- if (dropdown != null && dropdown.Visible)
- {
- CloseDropDown();
- return;
- }
-
- if (entry.HasCustomEditor)
- {
- entry.EditValue(this);
- }
- else
- {
- ICollection std_values = entry.AcceptedValues;
- if (std_values != null)
- {
- if (dropdown_list == null)
- {
- dropdown_list = new ListBox();
- dropdown_list.BorderStyle = BorderStyle.None;
- dropdown_list.DrawMode = DrawMode.OwnerDrawFixed;
- dropdown_list.DrawItem += (s, e) =>
- {
- e.DrawBackground();
- TextRenderer.DrawText(e.Graphics, dropdown_list.Items[e.Index].ToString(), e.Font, e.Bounds, e.ForeColor, TextFormatFlags.VerticalCenter);
- };
- dropdown_list.KeyDown += new KeyEventHandler(listBox_KeyDown);
- dropdown_list.MouseUp += new MouseEventHandler(listBox_MouseUp);
- }
- float rescale = (float)dropdown_list.DeviceDpi / DeviceDpi;
- dropdown_list.Items.Clear();
- dropdown_list.ItemHeight = (int)(row_height * rescale);
- int selected_index = 0;
- int i = 0;
- string valueText = entry.ValueText;
- foreach (object obj in std_values)
- {
- dropdown_list.Items.Add(obj);
- if (valueText != null && valueText.Equals(obj))
- selected_index = i;
- i++;
- }
- dropdown_list.Height = dropdown_list.ItemHeight * Math.Min(dropdown_list.Items.Count, 10) + _dpi(2);
- dropdown_list.Width = Width - SplitterLocation - (vbar.Visible ? vbar.Width : 0) - 1;
- if (std_values.Count > 0)
- dropdown_list.SelectedIndex = selected_index;
- DropDownControl(dropdown_list);
- }
- }
- }
- private void DialogButtonClicked(object sender, EventArgs e)
- {
- GridEntry entry = this.SelectedGridItem as GridEntry;
- if (entry != null && entry.HasCustomEditor)
- entry.EditValue((IWindowsFormsEditorService)this);
- }
- private void VScrollBar_HandleValueChanged(object sender, EventArgs e)
- {
- UpdateView();
- }
- private void grid_textbox_ToggleValue(object sender, EventArgs args)
- {
- ToggleValue(this.SelectedGridItem);
- }
- private void grid_textbox_KeyDown(object sender, KeyEventArgs e)
- {
- switch (e.KeyData & Keys.KeyCode)
- {
- case Keys.Down:
- if (e.Alt)
- {
- DropDownEdit();
- e.Handled = true;
- }
- break;
- }
- }
- private void grid_textbox_Validate(object sender, CancelEventArgs args)
- {
- if (!TrySetEntry(this.SelectedGridItem, grid_textbox.Text))
- args.Cancel = true;
- }
- private void ToggleValue(GridEntry entry)
- {
- if (entry != null && !entry.IsReadOnly && entry.GridItemType == GridItemType.Property)
- entry.ToggleValue();
- }
- internal void UpdateItem(GridEntry entry)
- {
- if (entry == null || entry.GridItemType == GridItemType.Category ||
- entry.GridItemType == GridItemType.Root)
- {
- grid_textbox.Visible = false;
- InvalidateItem(entry);
- return;
- }
- if (this.SelectedGridItem == entry)
- {
- SuspendLayout();
- grid_textbox.Visible = false;
- if (entry.IsResetable || !entry.HasDefaultValue)
- grid_textbox.Font = bold_font;
- else
- grid_textbox.Font = this.Font;
- if (entry.IsReadOnly)
- {
- grid_textbox.DropDownButtonVisible = false;
- grid_textbox.DialogButtonVisible = false;
- grid_textbox.ReadOnly = true;
- grid_textbox.ForeColor = entry.Expandable ? Drawing.SystemColors.ControlText : Drawing.SystemColors.GrayText;
- }
- else
- {
- grid_textbox.DropDownButtonVisible = entry.EditorStyle == UITypeEditorEditStyle.DropDown || entry.AcceptedValues != null;
- grid_textbox.DialogButtonVisible = entry.EditorStyle == UITypeEditorEditStyle.Modal;
- grid_textbox.ForeColor = Drawing.SystemColors.ControlText;
- grid_textbox.ReadOnly = !entry.IsEditable;
- }
- UpdateGridTextBoxBounds(entry);
- grid_textbox.PasswordChar = entry.IsPassword ? PASSWORD_TEXT_CHAR : '\0';
- grid_textbox.Text = entry.IsMerged && !entry.HasMergedValue ? String.Empty : entry.ValueText;
- grid_textbox.Visible = true;
- InvalidateItem(entry);
- ResumeLayout(false);
- }
- else
- {
- grid_textbox.Visible = false;
- }
- }
- private void UpdateGridTextBoxBounds(GridEntry entry)
- {
- if (entry == null || this.RootGridItem == null)
- return;
- bool rtl = RightToLeft == RightToLeft.Yes;
- int y = -vbar.Value * row_height;
- CalculateItemY(entry, this.RootGridItem.GridItems, ref y);
- int vbarWidth = vbar.Visible ? vbar.Width : 0;
- int pvWidth = ENTRY_SPACING;
- if (entry.PaintValueSupported)
- pvWidth += VALUE_PAINT_INDENT + (rtl ? ENTRY_SPACING : 0);
- if (entry.IsBool)
- pvWidth += BOOL_PAINT_INDENT + (rtl ? ENTRY_SPACING : 0);
- int x = rtl ? vbarWidth + 1 : SplitterLocation + pvWidth;
- int width = rtl ? SplitterLocation - x - pvWidth : Width - x - vbarWidth - 1;
- int height = row_height - 1;
- if (y == 0 && DeviceDpi > 120)
- {
- y = 1;
- height -= 1;
- }
- grid_textbox.SetBounds(x, y + 1, width, height);
- }
- // Calculates the sum of the heights of all items before the one
- //
- private bool CalculateItemY(GridEntry entry, GridItemCollection items, ref int y)
- {
- foreach (GridItem item in items)
- {
- if (item == entry)
- return true;
- y += row_height;
- if (item.Expandable && item.Expanded)
- if (CalculateItemY(entry, item.GridItems, ref y))
- return true;
- }
- return false;
- }
- private void ScrollToItem(GridEntry item)
- {
- if (item == null || this.RootGridItem == null)
- return;
- int itemY = -vbar.Value * row_height;
- int value = vbar.Value; ;
- CalculateItemY(item, this.RootGridItem.GridItems, ref itemY);
- if (itemY < 0) // the new item is above the viewable area
- value += itemY / row_height;
- else if (itemY + row_height > Height) // the new item is below the viewable area
- value += ((itemY + row_height) - Height) / row_height + 1;
- if (value >= vbar.Minimum && value <= vbar.Maximum)
- vbar.Value = value;
- }
- internal void SelectItem(GridEntry oldItem, GridEntry newItem)
- {
- if (oldItem != null)
- {
- InvalidateItemLabel(oldItem);
- }
- if (newItem != null)
- {
- UpdateItem(newItem);
- ScrollToItem(newItem);
- }
- else
- {
- grid_textbox.Visible = false;
- vbar.Visible = false;
- }
- }
- internal void UpdateView()
- {
- UpdateScrollBar();
- Invalidate();
- Update();
- UpdateItem(this.SelectedGridItem);
- }
- internal void ExpandItem(GridEntry item)
- {
- UpdateItem(this.SelectedGridItem);
- Invalidate(new Rectangle(0, item.Top, Width, Height - item.Top));
- }
- internal void CollapseItem(GridEntry item)
- {
- UpdateItem(this.SelectedGridItem);
- Invalidate(new Rectangle(0, item.Top, Width, Height - item.Top));
- }
- private void ShowDropDownControl(Control control, bool resizeable)
- {
- float rescale = (float)control.DeviceDpi / this.DeviceDpi;
- control.Width = (int)(Math.Max(grid_textbox.Width * rescale, control.Width));
- control.Font = new Font(Font.FontFamily, Font.Size * rescale, Font.Style);
- control.RightToLeft = RightToLeft;
- dropdown = new ToolStripDropDown();
- dropdown.Items.Add(new ToolStripControlHost(control));
- if (resizeable)
- {
- dropdown.Items.Add(new ToolStripControlHost(new DropDownResizer(control)));
- }
- int x = 0;
- if (RightToLeft == RightToLeft.Yes)
- {
- x = SystemInformation.MenuDropAlignment ? 0 : control.Width + _dpi(ENTRY_SPACING + 1);
- }
- else
- {
- x = SystemInformation.MenuDropAlignment ? grid_textbox.Width : (grid_textbox.Width - (int)(control.Width / rescale)) - _dpi(ENTRY_SPACING);
- }
- dropdown.Show(grid_textbox, x, row_height - 2);
- dropdown.Closed += (s, e) =>
- {
- // control is reused so we need to detach it from parent
- (s as ToolStripDropDown).Items.Clear();
- // SWF consistency: return correct size to the calling code (in case we need to save the control size)
- if (resizeable)
- control.Size = new Drawing.Size((int)(control.Width * rescale), (int)(control.Height * rescale));
- };
- // return to the calling method when dropdown is closed
- while (dropdown != null && dropdown.Visible)
- {
- Application.DoEvents();
- }
- dropdown = null;
- }
- #endregion
- #region IWindowsFormsEditorService Members
- public void CloseDropDown()
- {
- dropdown?.Close();
- dropdown = null;
- }
- public void DropDownControl(Control control)
- {
- bool resizeable = this.SelectedGridItem != null ? SelectedGridItem.EditorResizeable : false;
- ShowDropDownControl(control, resizeable);
- }
- public System.Windows.Forms.DialogResult ShowDialog(Form dialog)
- {
- return dialog.ShowDialog();
- }
- #endregion
- private class DropDownResizer : UserControl
- {
- private Control otherControl;
- protected override void OnMouseMove(MouseEventArgs e)
- {
- base.OnMouseMove(e);
- int _16 = _dpi(16);
- bool rtl = RightToLeft == RightToLeft.Yes;
-
- if (e.Button == MouseButtons.None)
- {
- if (e.X < _16 && !rtl)
- Cursor = Cursors.SizeNESW;
- else if (e.X > Width - _16 && rtl)
- Cursor = Cursors.SizeNWSE;
- else
- Cursor = Cursors.Default;
- }
- if (e.Button == MouseButtons.Left)
- {
- var popup = WpfHelper.FindParent<System.Windows.Controls.Primitives.Popup>(this.control);
- if (Cursor == Cursors.SizeNESW)
- {
- if (!SystemInformation.MenuDropAlignment)
- popup.HorizontalOffset += e.X / DpiScale;
- Width -= e.X;
- }
- else if (Cursor == Cursors.SizeNWSE)
- {
- if (!SystemInformation.MenuDropAlignment)
- popup.HorizontalOffset += (Width - e.X) / DpiScale;
- Width = e.X;
- }
- otherControl.Width = Width;
- otherControl.Height += e.Y;
- }
- }
- protected override void OnPaint(PaintEventArgs e)
- {
- Graphics g = e.Graphics;
- Pen p = Pens.Gray;
- int _4 = _dpi(4);
- int _8 = _dpi(8);
- int _12 = _dpi(12);
- int _16 = _dpi(16);
- g.DrawLine(p, 0, 0, Width, 0);
- if (RightToLeft == RightToLeft.Yes)
- {
- g.DrawLine(p, Width, _8, Width - _8, _16);
- g.DrawLine(p, Width, _12, Width - _4, _16);
- }
- else
- {
- g.DrawLine(p, 0, _8, _8, _16);
- g.DrawLine(p, 0, _12, _4, _16);
- }
- }
- public DropDownResizer(Control otherControl)
- {
- this.otherControl = otherControl;
- RightToLeft = otherControl.RightToLeft;
- Height = _dpi(16);
- Width = otherControl.Width;
- }
- }
- }
- }
|