private PropertyGridTextBox grid_textbox;
private PropertyGrid property_grid;
private bool resizing_grid;
- private int open_grid_item_count = -1;
- private int skipped_grid_items;
private PropertyGridDropDown dropdown_form;
private Form dialog_form;
private ImplicitVScrollBar vbar;
private StringFormat string_format;
private Font bold_font;
+ private Brush inactive_text_brush;
#endregion
#region Contructors
dialog_form.FormBorderStyle = FormBorderStyle.None;
dialog_form.ShowInTaskbar = false;
- skipped_grid_items = 0;
row_height = Font.Height + font_height_padding;
grid_textbox.Visible = false;
grid_textbox.Font = this.Font;
grid_textbox.BackColor = SystemColors.Window;
// Not working at all, used to??
- grid_textbox.Validating += new CancelEventHandler (TextBoxValidating);
+ // grid_textbox.Validating += new CancelEventHandler (TextBoxValidating);
grid_textbox.ToggleValue+=new EventHandler (grid_textbox_ToggleValue);
this.Controls.Add (grid_textbox);
vbar = new ImplicitVScrollBar ();
vbar.Visible = false;
+ vbar.Value = 0;
vbar.ValueChanged+=new EventHandler (VScrollBar_HandleValueChanged);
vbar.Dock = DockStyle.Right;
this.Controls.AddImplicit (vbar);
resizing_grid = false;
bold_font = new Font (this.Font, FontStyle.Bold);
+ inactive_text_brush = new SolidBrush (ThemeEngine.Current.ColorGrayText);
ForeColorChanged+=new EventHandler (RedrawEvent);
BackColorChanged+=new System.EventHandler (RedrawEvent);
private void InvalidateItem (GridEntry item)
{
+ if (item == null)
+ return;
+
Rectangle rect = new Rectangle (0, item.Top, Width, row_height);
Invalidate (rect);
protected override void OnDoubleClick (EventArgs e)
{
- if (property_grid.SelectedGridItem.Expandable)
+ if (property_grid.SelectedGridItem != null && property_grid.SelectedGridItem.Expandable)
property_grid.SelectedGridItem.Expanded = !property_grid.SelectedGridItem.Expanded;
else
ToggleValue ((GridEntry)property_grid.SelectedGridItem);
}
- protected override void OnPaint (PaintEventArgs e) {
- // Decide if we need a scrollbar
- open_grid_item_count = 0;
-
+ protected override void OnPaint (PaintEventArgs e)
+ {
// Background
e.Graphics.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (BackColor), ClientRectangle);
if (vbar == null || !vbar.Visible)
return;
if (e.Delta < 0)
- vbar.Value = Math.Min (vbar.Value + SystemInformation.MouseWheelScrollLines, vbar.Maximum);
+ vbar.Value = Math.Min (vbar.Value + SystemInformation.MouseWheelScrollLines, vbar.Maximum - vbar.SmallChange);
else
vbar.Value = Math.Max (0, vbar.Value - SystemInformation.MouseWheelScrollLines);
base.OnMouseWheel (e);
protected override void OnMouseDown (MouseEventArgs e)
{
+ base.OnMouseDown (e);
if (property_grid.RootGridItem == null)
return;
+ if (!TrySetEntry ((GridEntry)property_grid.SelectedGridItem, grid_textbox.Text)) {
+ FocusSelection ();
+ return;
+ }
+
if (e.X > SplitterLocation - RESIZE_WIDTH && e.X < SplitterLocation + RESIZE_WIDTH) {
resizing_grid = true;
}
if (foundItem != null) {
if (foundItem.Expandable && ((GridEntry)foundItem).PlusMinusBounds.Contains (e.X, e.Y))
- foundItem.Expanded = !foundItem.Expanded;
-
+ foundItem.Expanded = !foundItem.Expanded;
+
this.property_grid.SelectedGridItem = foundItem;
- if (!GridLabelHitTest (e.X))
- FocusSelection ();
+ if (!GridLabelHitTest (e.X)) {
+ // send mouse down so we get the carret under cursor
+ grid_textbox.SendMouseDown (PointToScreen (e.Location));
+ }
}
-
- base.OnMouseDown (e);
}
}
protected override void OnResize (EventArgs e) {
base.OnResize (e);
if (property_grid.SelectedGridItem != null) { // initialized already
- SuspendLayout ();
UpdateView ();
// MS scrolls to the currently selected item on resize, even
// when it's not in the visible area.
//
- EnsureItemIsVisible ((GridEntry)property_grid.SelectedGridItem);
- ResumeLayout (false);
+ ScrollToItem ((GridEntry)property_grid.SelectedGridItem);
}
}
&& grid_textbox.Visible) {
switch (keyData) {
case Keys.Enter:
- selectedItem.SetValue (grid_textbox.Text);
- UnfocusSelection ();
+ if (TrySetEntry (selectedItem, grid_textbox.Text))
+ UnfocusSelection ();
return true;
case Keys.Escape:
if (selectedItem.IsEditable)
- grid_textbox.Text = selectedItem.ValueString;
+ UpdateItem (selectedItem); // reset value
UnfocusSelection ();
return true;
case Keys.Tab:
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
+ else
+ return false;
+ }
+ }
+ return true;
+ }
protected override bool IsInputKey (Keys keyData) {
switch (keyData) {
return item;
}
- protected override void OnKeyDown (KeyEventArgs e) {
+ protected override void OnKeyDown (KeyEventArgs e)
+ {
GridEntry selectedItem = (GridEntry)property_grid.SelectedGridItem;
if (selectedItem == null) {
return;
}
+ if (!TrySetEntry (selectedItem, grid_textbox.Text)) {
+ FocusSelection ();
+ return;
+ }
+
switch (e.KeyData & Keys.KeyCode) {
case Keys.Left:
if (e.Control) {
#region Private Helper Methods
- private int SplitterLocation{
+ private int SplitterLocation {
get {
return (int)(splitter_percent*Width);
}
return null;
}
- private void UpdateScrollBar () {
- int visible_rows = this.ClientRectangle.Height/row_height;
- if (open_grid_item_count > visible_rows) {
+ 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 ()
+ {
+ return this.Height / row_height;
+ }
+
+ private void UpdateScrollBar ()
+ {
+ if (property_grid.RootGridItem == null)
+ return;
+
+ int visibleRows = GetVisibleRowsCount ();
+ int openedItems = GetVisibleItemsCount ((GridEntry)property_grid.RootGridItem);
+ if (openedItems > visibleRows) {
vbar.Visible = true;
vbar.SmallChange = 1;
vbar.Minimum = 0;
- vbar.Maximum = open_grid_item_count-1;
- vbar.LargeChange = visible_rows;
- }
- else {
+ vbar.Maximum = openedItems - 1;
+ vbar.LargeChange = visibleRows;
+ } else {
+ vbar.Value = 0;
vbar.Visible = false;
}
-
+ UpdateGridTextBoxBounds ((GridEntry)property_grid.SelectedGridItem);
}
+ // private bool GetScrollBarVisible ()
+ // {
+ // if (property_grid.RootGridItem == null)
+ // return false;
+ //
+ // int visibleRows = GetVisibleRowsCount ();
+ // int openedItems = GetVisibleItemsCount ((GridEntry)property_grid.RootGridItem);
+ // if (openedItems > visibleRows)
+ // return true;
+ // return false;
+ // }
#region Drawing Code
private void DrawGridItems (GridItemCollection grid_items, PaintEventArgs pevent, int depth, ref int yLoc) {
if (grid_item.GridItemType == GridItemType.Category) {
font = bold_font;
- brush = SystemBrushes.ControlDark;
+ brush = SystemBrushes.ControlText;
pevent.Graphics.DrawString (grid_item.Label, font, brush, rect.X + 1, rect.Y + ENTRY_SPACING);
if (grid_item == property_grid.SelectedGridItem) {
brush = SystemBrushes.HighlightText;
}
else {
- brush = SystemBrushes.WindowText;
- if (grid_item.PropertyDescriptor.IsReadOnly
- && !grid_item.Expandable)
- brush = SystemBrushes.InactiveCaption;
+ brush = grid_item.IsReadOnly ? 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);
if (grid_item.PropertyDescriptor == null)
return;
- int xLoc = SplitterLocation+1;
+ int xLoc = SplitterLocation+ENTRY_SPACING;
if (grid_item.PaintValueSupported) {
pevent.Graphics.DrawRectangle (Pens.Black, SplitterLocation + ENTRY_SPACING,
rect.Y + 2, VALUE_PAINT_WIDTH + 1, row_height - ENTRY_SPACING*2);
grid_item.PaintValue (pevent.Graphics,
new Rectangle (SplitterLocation + ENTRY_SPACING + 1,
rect.Y + ENTRY_SPACING + 1,
- VALUE_PAINT_WIDTH, row_height - (ENTRY_SPACING*2 + 1)));
+ VALUE_PAINT_WIDTH, row_height - (ENTRY_SPACING*2 +1)));
xLoc += VALUE_PAINT_INDENT;
}
Font font = this.Font;
- if (grid_item.IsResetable)
+ if (grid_item.IsResetable || !grid_item.HasDefaultValue)
font = bold_font;
- pevent.Graphics.DrawString (grid_item.ValueString, font,
- SystemBrushes.WindowText,
- new RectangleF (xLoc, rect.Y + ENTRY_SPACING,
- ClientRectangle.Width-(xLoc), row_height),string_format);
+ Brush brush = grid_item.IsReadOnly ? inactive_text_brush : SystemBrushes.ControlText;
+ string valueText = grid_item.IsMerged && !grid_item.HasMergedValue ? String.Empty : grid_item.ValueText;
+ pevent.Graphics.DrawString (valueText, font,
+ brush,
+ new RectangleF (xLoc + ENTRY_SPACING, rect.Y + ENTRY_SPACING,
+ ClientRectangle.Width-(xLoc), row_height - ENTRY_SPACING*2),
+ string_format);
}
private void DrawGridItem (GridEntry grid_item, PaintEventArgs pevent, int depth, ref int yLoc) {
}
grid_item.Top = yLoc;
yLoc += row_height;
- open_grid_item_count++;
}
private Rectangle DrawPlusMinus (Graphics g, int x, int y, bool expanded, bool category) {
Refresh ();
}
- private void TextBoxValidating (object sender, CancelEventArgs e)
- {
- if (this.property_grid.SelectedGridItem != null)
- ((GridEntry) property_grid.SelectedGridItem).SetValue (grid_textbox.Text);
- }
+ // private void TextBoxValidating (object sender, CancelEventArgs e)
+ // {
+ // GridEntry entry = (GridEntry) property_grid.SelectedGridItem;
+ // if (entry != null && entry.IsEditable)
+ // TrySetEntry (entry, grid_textbox.Text);
+ // }
#endregion
void AcceptListBoxSelection (object sender)
{
GridEntry entry = this.property_grid.SelectedGridItem as GridEntry;
- if (entry != null)
- entry.SetValue ((string) ((ListBox) sender).SelectedItem);
+ if (entry != null) {
+ grid_textbox.Text = (string) ((ListBox) sender).SelectedItem;
+ if (TrySetEntry (entry, (string) ((ListBox) sender).SelectedItem))
+ UnfocusSelection ();
+ }
CloseDropDown ();
}
int i = 0;
foreach (object obj in std_values) {
listBox.Items.Add (obj);
- if (entry.ValueString != null && entry.ValueString.Equals (obj))
+ if (entry.ValueText != null && entry.ValueText.Equals (obj))
selected_index = i;
i++;
}
listBox.Height = row_height * Math.Min (listBox.Items.Count, 15);
+ listBox.Width = ClientRectangle.Width - SplitterLocation - (vbar.Visible ? vbar.Width : 0);
listBox.KeyDown += new KeyEventHandler (listBox_KeyDown);
listBox.MouseUp+=new MouseEventHandler (listBox_MouseUp);
if (std_values.Count > 0)
private void VScrollBar_HandleValueChanged (object sender, EventArgs e)
{
- if (vbar.Value <= 0)
- vbar.Value = 0;
- if (vbar.Value > vbar.Maximum-ClientRectangle.Height/row_height)
- vbar.Value = vbar.Maximum-ClientRectangle.Height/row_height+1;
-
- int scroll_amount = (skipped_grid_items-vbar.Value)*row_height;
-
- if (scroll_amount == 0)
- return;
-
- skipped_grid_items = vbar.Value;
- XplatUI.ScrollWindow (Handle, 0, scroll_amount, false);
UpdateView ();
}
internal void UpdateItem (GridEntry entry)
{
- if (entry == null || entry.GridItemType != GridItemType.Property) {
+ if (entry == null || entry.GridItemType == GridItemType.Category ||
+ entry.GridItemType == GridItemType.Root) {
grid_textbox.Visible = false;
+ InvalidateItem (entry);
return;
}
if (property_grid.SelectedGridItem == entry) {
SuspendLayout ();
grid_textbox.Visible = false;
- if (entry.IsResetable)
+ if (entry.IsResetable || !entry.HasDefaultValue)
grid_textbox.Font = bold_font;
else
grid_textbox.Font = this.Font;
-
- grid_textbox.DropDownButtonVisible = entry.AcceptedValues != null ||
- entry.EditorStyle == UITypeEditorEditStyle.DropDown;
- grid_textbox.DialogButtonVisible = entry.EditorStyle == UITypeEditorEditStyle.Modal;
- grid_textbox.ReadOnly = !entry.IsEditable;
-
- int y = -vbar.Value*row_height;
- CalculateItemY (entry, property_grid.RootGridItem.GridItems, ref y);
- int x = SplitterLocation + 1 + (entry.PaintValueSupported ? 27 : 0);
- grid_textbox.SetBounds (x, y + ENTRY_SPACING,
- ClientRectangle.Width - x - (vbar.Visible ? vbar.Width : 0),
- row_height - ENTRY_SPACING);
- grid_textbox.Text = entry.ValueString != null ? entry.ValueString : "";
+
+ if (entry.IsReadOnly) {
+ grid_textbox.DropDownButtonVisible = false;
+ grid_textbox.DialogButtonVisible = false;
+ grid_textbox.ReadOnly = true;
+ grid_textbox.ForeColor = SystemColors.GrayText;
+ } else {
+ grid_textbox.DropDownButtonVisible = entry.AcceptedValues != null ||
+ entry.EditorStyle == UITypeEditorEditStyle.DropDown;
+ grid_textbox.DialogButtonVisible = entry.EditorStyle == UITypeEditorEditStyle.Modal;
+ grid_textbox.ForeColor = SystemColors.ControlText;
+ grid_textbox.ReadOnly = !entry.IsEditable;
+ }
+ UpdateGridTextBoxBounds (entry);
+ grid_textbox.Text = entry.IsMerged && !entry.HasMergedValue ? String.Empty : entry.ValueText;
grid_textbox.Visible = true;
InvalidateItem (entry);
ResumeLayout (false);
}
}
+ private void UpdateGridTextBoxBounds (GridEntry entry)
+ {
+ int y = -vbar.Value*row_height;
+ CalculateItemY (entry, property_grid.RootGridItem.GridItems, ref y);
+ int x = SplitterLocation + ENTRY_SPACING + (entry.PaintValueSupported ? VALUE_PAINT_INDENT : 0);
+ grid_textbox.SetBounds (x + ENTRY_SPACING, y + ENTRY_SPACING,
+ ClientRectangle.Width - ENTRY_SPACING - x - (vbar.Visible ? vbar.Width : 0),
+ row_height - ENTRY_SPACING);
+ }
+
// Calculates the sum of the heights of all items before the one
//
private bool CalculateItemY (GridEntry entry, GridItemCollection items, ref int y)
return false;
}
- private void EnsureItemIsVisible (GridEntry item)
+ private void ScrollToItem (GridEntry item)
{
if (item == null)
return;
int itemY = -vbar.Value*row_height;
+ int value = vbar.Value;;
CalculateItemY (item, property_grid.RootGridItem.GridItems, ref itemY);
if (itemY < 0) // the new item is above the viewable area
- vbar.Value += itemY / row_height;
+ value += itemY / row_height;
else if (itemY + row_height > Height) // the new item is below the viewable area
- vbar.Value += ((itemY + row_height) - Height) / row_height + 1;
+ value += ((itemY + row_height) - Height) / row_height + 1;
+ if (value >= vbar.Minimum && value <= vbar.Maximum)
+ vbar.Value = value;
}
- internal void SelectItem (GridItem oldItem, GridItem newItem)
+ internal void SelectItem (GridEntry oldItem, GridEntry newItem)
{
if (oldItem != null)
- InvalidateItemLabel ((GridEntry)oldItem);
+ InvalidateItemLabel (oldItem);
if (newItem != null) {
- UpdateItem ((GridEntry) newItem);
- EnsureItemIsVisible ((GridEntry) newItem);
+ UpdateItem (newItem);
+ ScrollToItem (newItem);
} else
grid_textbox.Visible = false;
}
internal void UpdateView ()
{
+ UpdateScrollBar ();
UpdateItem ((GridEntry)property_grid.SelectedGridItem);
Invalidate ();
Update ();
internal void ExpandItem (GridEntry item)
{
+ UpdateItem ((GridEntry)property_grid.SelectedGridItem);
Invalidate (new Rectangle (0, item.Top, Width, Height - item.Top));
}
internal void CollapseItem (GridEntry item)
{
+ UpdateItem ((GridEntry)property_grid.SelectedGridItem);
Invalidate (new Rectangle (0, item.Top, Width, Height - item.Top));
}
- private void ShowDropDownControl (Control control, bool block) {
+ private void ShowDropDownControl (Control control, bool block)
+ {
Object queue_id;
Form owner = FindForm ();
Point location;
dropdown_form.Size = control.Size;
control.Dock = DockStyle.Fill;
- dropdown_form.Controls.Clear ();
dropdown_form.Controls.Add (control);
- dropdown_form.Location = PointToScreen (new Point (SplitterLocation, grid_textbox.Location.Y + row_height));
+ dropdown_form.Width = Math.Max (ClientRectangle.Width - SplitterLocation - (vbar.Visible ? vbar.Width : 0),
+ control.Width);
+ dropdown_form.Location = PointToScreen (new Point (grid_textbox.Right - control.Width, grid_textbox.Location.Y + row_height));
+ RepositionInScreenWorkingArea (dropdown_form);
location = dropdown_form.Location;
- dropdown_form.Width = ClientRectangle.Width - SplitterLocation - (vbar.Visible ? vbar.Width : 0);
-
owner.AddOwnedForm (dropdown_form);
dropdown_form.Show ();
System.Windows.Forms.MSG msg = new MSG ();
queue_id = XplatUI.StartLoop (Thread.CurrentThread);
while (dropdown_form.Visible && XplatUI.GetMessage (queue_id, ref msg, IntPtr.Zero, 0, 0)) {
-
- if ((msg.message == Msg.WM_NCLBUTTONDOWN ||
- msg.message == Msg.WM_NCMBUTTONDOWN ||
- msg.message == Msg.WM_NCRBUTTONDOWN ||
- msg.message == Msg.WM_LBUTTONDOWN ||
- msg.message == Msg.WM_MBUTTONDOWN ||
- msg.message == Msg.WM_RBUTTONDOWN)
- && !HwndInControl (dropdown_form, msg.hwnd)) {
- CloseDropDown ();
+ switch (msg.message) {
+ case Msg.WM_NCLBUTTONDOWN:
+ case Msg.WM_NCMBUTTONDOWN:
+ case Msg.WM_NCRBUTTONDOWN:
+ case Msg.WM_LBUTTONDOWN:
+ case Msg.WM_MBUTTONDOWN:
+ case Msg.WM_RBUTTONDOWN:
+ if (!HwndInControl (dropdown_form, msg.hwnd))
+ CloseDropDown ();
break;
+ case Msg.WM_ACTIVATE:
+ case Msg.WM_NCPAINT:
+ if (owner.window.Handle == msg.hwnd)
+ CloseDropDown ();
+ break;
}
XplatUI.TranslateMessage (ref msg);
XplatUI.DispatchMessage (ref msg);
}
+ XplatUI.EndLoop (Thread.CurrentThread);
+ }
+ }
+
+ private void RepositionInScreenWorkingArea (Form form)
+ {
+ Rectangle workingArea = Screen.FromControl (form).WorkingArea;
+ if (!workingArea.Contains (form.Bounds)) {
+ int x, y;
+ x = form.Location.X;
+ y = form.Location.Y;
+
+ if (form.Location.X < workingArea.X)
+ x = workingArea.X;
+
+ if (form.Location.Y + form.Size.Height > workingArea.Height) {
+ Point aboveTextBox = PointToScreen (new Point (grid_textbox.Right - form.Width, grid_textbox.Location.Y));
+ y = aboveTextBox.Y - form.Size.Height;
+ }
+
+ form.Location = new Point (x, y);
}
}
{
if (hwnd == c.window.Handle)
return true;
- foreach (Control cc in c.Controls.GetAllControls ())
+ foreach (Control cc in c.Controls.GetAllControls ()) {
if (HwndInControl (cc, hwnd))
return true;
+ }
return false;
}
#endregion
Control c = dropdown_form.Controls[0];
c.Capture = false;
dropdown_form.Hide ();
+ dropdown_form.Controls.Clear ();
}
public void DropDownControl (Control control) {