using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; using DevComponents.DotNetBar.SuperGrid.Primitives; using DevComponents.DotNetBar.SuperGrid.Style; using DevComponents.SuperGrid.TextMarkup; namespace DevComponents.DotNetBar.SuperGrid { /// /// GridGroup /// public class GridGroup : GridContainer { #region Static data private static bool _dragSelection; private static bool _dragStarted; #endregion #region Private variables private GridCell _Cell; private string _Text; private Size _TextSize; private Rectangle _ExpandButtonBounds; private int _AnchorIndex; private GroupArea _HitArea; private GridContainer _HitItem; private GroupArea _LastHitArea; private GroupArea _MouseDownHitArea; private Point _MouseDownPoint; private GridContainer _MouseDownHitRow; private GroupHeaderVisualStyles _GroupHeaderVisualStyles; private GroupHeaderVisualStyles _EffectiveVisualStyles; private int _StyleUpdateCount; private BodyElement _GroupTextMarkup; private object _GroupId; #endregion #region Public properties #region Bounds /// /// Bounds /// public override Rectangle Bounds { get { GridPanel panel = GridPanel; if (panel != null) { Rectangle r = BoundsRelative; if (IsVFrozen == false) r.Y -= VScrollOffset; if (panel.IsSubPanel == true) r.X -= HScrollOffset; r.Height = FixedRowHeight; Rectangle t = ViewRect; if (r.Right > t.Right) r.Width -= (r.Right - t.Right); return (r); } return (Rectangle.Empty); } } #endregion #region Cell /// /// Gets the Group's associated grid cell. /// public GridCell Cell { get { return (_Cell); } internal set { _Cell = value; } } #endregion #region Column /// /// Gets the Group's associated grid Column. /// public GridColumn Column { get { return (_Cell != null ? _Cell.GridColumn : null); } } #endregion #region GroupHeaderVisualStyles /// /// Gets or sets the visual styles /// assigned to the element. Default value is null. /// [DefaultValue(null), Category("Style")] [Description("Indicates visual style assigned to the element")] public GroupHeaderVisualStyles GroupHeaderVisualStyles { get { if (_GroupHeaderVisualStyles == null) { _GroupHeaderVisualStyles = new GroupHeaderVisualStyles(); GroupHeaderStyleChangeHandler(null, _GroupHeaderVisualStyles); } return (_GroupHeaderVisualStyles); } set { if (_GroupHeaderVisualStyles != value) { GroupHeaderVisualStyles oldValue = _GroupHeaderVisualStyles; _GroupHeaderVisualStyles = value; OnCellStyleChanged("GroupHeaderVisualStyle", oldValue, value); } } } private void OnCellStyleChanged(string property, GroupHeaderVisualStyles oldValue, GroupHeaderVisualStyles newValue) { GroupHeaderStyleChangeHandler(oldValue, newValue); OnPropertyChanged(property); } #endregion #region GroupValue /// /// GroupValue /// public object GroupValue { get { return (_Cell != null ? _Cell.Value : 0); } } #endregion #region PlainText /// /// Gets the "Plain" header Text (MiniMarkup stripped) /// public string PlainText { get { if (_GroupTextMarkup != null) return (_GroupTextMarkup.PlainText); return (_Text); } } #endregion #region Text /// /// Text /// public string Text { get { return (_Text); } set { if (_Text != value) { _Text = value; MarkupGroupTextChanged(); OnPropertyChangedEx("Text", VisualChangeType.Layout); } } } #endregion #endregion #region Internal properties #region GroupId internal object GroupId { get { return (_GroupId); } set { _GroupId = value; } } #endregion #region GroupTextMarkup internal BodyElement GroupTextMarkup { get { return (_GroupTextMarkup); } set { _GroupTextMarkup = value; } } #endregion #endregion #region MeasureOverride #region MeasureOverride /// /// MeasureOverride /// /// /// /// protected override void MeasureOverride( GridLayoutInfo layoutInfo, GridLayoutStateInfo stateInfo, Size constraintSize) { Size sizeNeeded = Size.Empty; GridPanel panel = stateInfo.GridPanel; Graphics g = layoutInfo.Graphics; if (CanShowRowHeader(panel) == true) sizeNeeded.Width += panel.RowHeaderWidthEx; GroupHeaderVisualStyle style = GetSizingStyle(panel); Size size = MeasureGroupText(g, style, constraintSize); if (size.Height > 0) { size.Height += Dpi.Height8; size.Width += Dpi.Width(style.Padding.Horizontal); size.Height += Dpi.Height(style.Padding.Vertical); } size.Height = Math.Max(size.Height, Dpi.Height(panel.GroupHeaderHeight)); sizeNeeded.Width += size.Width; sizeNeeded.Height = Math.Max(size.Height, sizeNeeded.Height); if (panel.ShowGroupUnderline == true && size.Height > 0) sizeNeeded.Height += Dpi.Height4; FixedRowHeight = sizeNeeded.Height; if (Rows != null && Expanded == true) { if (panel.IndentGroups == true) { GridLayoutStateInfo itemStateInfo = new GridLayoutStateInfo(panel, stateInfo.IndentLevel + 1); size = MeasureSubItems(layoutInfo, itemStateInfo, constraintSize); } else { size = MeasureSubItems(layoutInfo, stateInfo, constraintSize); } sizeNeeded.Width = Math.Max(size.Width, sizeNeeded.Width); sizeNeeded.Height += size.Height; } Size = sizeNeeded; } #endregion #region MeasureGroupText private Size MeasureGroupText(Graphics g, GroupHeaderVisualStyle style, Size constraintSize) { _TextSize = Size.Empty; if (String.IsNullOrEmpty(Text) == false) { GridPanel panel = GridPanel; if (panel.IsSubPanel == false) { if (panel.ShowGroupExpand == true) { constraintSize.Width = SViewRect.Width; int n = panel.TreeButtonIndent + Dpi.Width(panel.LevelIndentSize.Width * IndentLevel); constraintSize.Width -= n; } } _TextSize = MeasureHeaderText(g, style, constraintSize); } return (_TextSize); } #region MeasureHeaderText private Size MeasureHeaderText(Graphics g, GroupHeaderVisualStyle style, Size constraintSize) { Size size = Size.Empty; string s = Text; if (string.IsNullOrEmpty(s) == false) { if (_GroupTextMarkup != null) { size = GetMarkupTextSize(g, _GroupTextMarkup, style, constraintSize.Width); } else { eTextFormat tf = style.GetTextFormatFlags(); size = (constraintSize.IsEmpty == true) ? TextHelper.MeasureText(g, s, style.Font) : TextHelper.MeasureText(g, s, style.Font, constraintSize, tf); } } return (size); } #region GetMarkupTextSize private Size GetMarkupTextSize(Graphics g, BodyElement textMarkup, GroupHeaderVisualStyle style, int width) { MarkupDrawContext d = new MarkupDrawContext(g, style.Font, style.TextColor, false); textMarkup.InvalidateElementsSize(); textMarkup.Measure(new Size(width, 0), d); return (textMarkup.Bounds.Size); } #endregion #endregion #endregion #endregion #region ArrangeOverride /// /// ArrangeOverride /// /// /// /// protected override void ArrangeOverride(GridLayoutInfo layoutInfo, GridLayoutStateInfo stateInfo, Rectangle layoutBounds) { Rectangle bounds = layoutBounds; bounds.Height = FixedRowHeight; GridPanel panel = stateInfo.GridPanel; IndentLevel = stateInfo.IndentLevel; if (panel.ShowGroupExpand == true) { GroupHeaderVisualStyle style = GetSizingStyle(panel); Rectangle r = bounds; r.Width = Dpi.Width(panel.LevelIndentSize.Width); r.Height -= Dpi.Height(style.Padding.Vertical); int n = Dpi.Height(panel.GroupHeaderHeight); if (r.Height < n) r.Height = n; if (CanShowRowHeader(panel) == true) r.X += panel.RowHeaderWidthEx; n = panel.TreeButtonIndent + Dpi.Width((panel.LevelIndentSize.Width * IndentLevel) - panel.LevelIndentSize.Width); r.X += n; if (r.Right > BoundsRelative.Right) r.Width -= r.Right - BoundsRelative.Right; r.X += Dpi.Width(style.Padding.Left); r.Y += Dpi.Height(style.Padding.Top); Size size = panel.GetTreeButtonSize(); r.X += (r.Width - size.Width) / 2; r.Y += (r.Height - size.Height) / 2 - 1; r.Size = size; _ExpandButtonBounds = r; } else { _ExpandButtonBounds = Rectangle.Empty; } if (Rows != null && Expanded == true) { bounds = layoutBounds; bounds.Y += FixedRowHeight; bounds.Height -= FixedRowHeight; if (panel.IndentGroups == true) { GridLayoutStateInfo itemStateInfo = new GridLayoutStateInfo(panel, stateInfo.IndentLevel + 1); ArrangeSubItems(layoutInfo, itemStateInfo, bounds); } else { ArrangeSubItems(layoutInfo, stateInfo, bounds); } } } #endregion #region RenderOverride /// /// RenderOverride /// /// protected override void RenderOverride(GridRenderInfo renderInfo) { GridPanel panel = GridPanel; if (panel != null) { Rectangle r = Bounds; if (r.IntersectsWith(renderInfo.ClipRectangle)) { Graphics g = renderInfo.Graphics; GroupHeaderVisualStyle style = GetEffectiveStyle(); if (SuperGrid.DoPreRenderGroupHeaderEvent(g, this, RenderParts.Background | RenderParts.RowHeader, r) == false) { RenderGroupBackground(g, style, r); RenderRowHeader(g, panel, style, r); SuperGrid.DoPostRenderGroupHeaderEvent(g, this, RenderParts.Background | RenderParts.RowHeader, r); } if (CanShowRowHeader(panel) == true) { r.X += panel.RowHeaderWidthEx; r.Width -= panel.RowHeaderWidthEx; } RenderHeaderExpand(g, panel, ref r); r = GetAdjustedBounds(style, r); int n = Dpi.Width(panel.GroupHeaderHeight); if (r.Height < n) r.Height = n; if (SuperGrid.DoPreRenderGroupHeaderEvent(g, this, RenderParts.Content, r) == false) { RenderHeaderText(g, style, r); RenderHeaderUnderline(g, panel, style, r); SuperGrid.DoPostRenderGroupHeaderEvent(g, this, RenderParts.Content, r); } } if (Rows != null && Expanded == true) { UpdateMergeFlags(); foreach (GridElement item in Rows) { if (item.Visible == true) item.Render(renderInfo); } } } } #region GetAdjustedBounds private Rectangle GetAdjustedBounds(GroupHeaderVisualStyle style, Rectangle r) { r.X += Dpi.Width(style.Padding.Left); r.Width -= Dpi.Width(style.Padding.Horizontal); r.Y += Dpi.Height(style.Padding.Top + 2); r.Height -= Dpi.Height(style.Padding.Vertical + 2); return (r); } #endregion #region RenderRowHeader private void RenderRowHeader(Graphics g, GridPanel panel, GroupHeaderVisualStyle style, Rectangle r) { if (CanShowRowHeader(panel) == true) { r.Width = panel.RowHeaderWidthEx; using (Brush br = style.RowHeaderStyle.Background.GetBrush(r)) g.FillRectangle(br, r); GridPanelVisualStyle pstyle = panel.GetEffectiveStyle(); if (Dpi.Height1 == Dpi.Width1) { using (Pen pen = new Pen(style.RowHeaderStyle.BorderHighlightColor, Dpi.Height1)) { g.DrawLine(pen, r.X + 1, r.Top, r.Right - 2, r.Top); g.DrawLine(pen, r.X + 1, r.Top, r.X + 1, r.Bottom - 1); } using (Pen pen = new Pen(pstyle.HeaderLineColor, Dpi.Height1)) { g.DrawLine(pen, r.X, r.Top - 1, r.Right - 1, r.Top - 1); g.DrawLine(pen, r.X, r.Bottom - 1, r.Right - 2, r.Bottom - 1); g.DrawLine(pen, r.Right - 1, r.Top, r.Right - 1, r.Bottom - 1); } } else { using (Pen pen = new Pen(style.RowHeaderStyle.BorderHighlightColor, Dpi.Height1)) g.DrawLine(pen, r.X + 1, r.Top, r.Right - 2, r.Top); using (Pen pen = new Pen(style.RowHeaderStyle.BorderHighlightColor, Dpi.Width1)) g.DrawLine(pen, r.X + 1, r.Top, r.X + 1, r.Bottom - 1); using (Pen pen = new Pen(pstyle.HeaderLineColor, Dpi.Height1)) { g.DrawLine(pen, r.X, r.Top - 1, r.Right - 1, r.Top - 1); g.DrawLine(pen, r.X, r.Bottom - 1, r.Right - 2, r.Bottom - 1); } using (Pen pen = new Pen(pstyle.HeaderLineColor, Dpi.Width1)) g.DrawLine(pen, r.Right - 1, r.Top, r.Right - 1, r.Bottom - 1); } r.X += Dpi.Width4; r.Width -= Dpi.Width4; int n = RenderIndicatorImage(g, panel, this, r); r.X += n; r.Width -= n; if (panel.ShowRowGridIndex == true) RenderGridIndex(g, this, style.RowHeaderStyle, r); } } #region RenderIndicatorImage private int RenderIndicatorImage(Graphics g, GridPanel panel, GridContainer row, Rectangle r) { RowHeaderVisualStyle style = GetEffectiveRowStyle().RowHeaderStyle; Image image = style.GetActiveRowImage(panel); if (image != null) { if (panel.ActiveRow == row) { if (panel.ActiveRowIndicatorStyle == ActiveRowIndicatorStyle.Image || panel.ActiveRowIndicatorStyle == ActiveRowIndicatorStyle.Both) { Rectangle u = r; u.Size = image.Size; if (r.Height > u.Height) u.Y += (r.Height - u.Height) / 2; u.Intersect(r); g.DrawImageUnscaledAndClipped(image, u); } } return (image.Width); } return (0); } #endregion #region RenderGridIndex private void RenderGridIndex(Graphics g, GridContainer row, RowHeaderVisualStyle style, Rectangle r) { string text = (row.GridIndex + row.GridPanel.RowHeaderIndexOffset).ToString(); Font font = style.Font ?? SystemFonts.DefaultFont; r.Inflate(-2, 0); TextDrawing.DrawString(g, text, font, style.TextColor, r, style.GetTextFormatFlags()); return; } #endregion #endregion #region CanShowRowHeader /// /// CanShowRowHeader /// /// /// protected virtual bool CanShowRowHeader(GridPanel panel) { switch (panel.GroupRowHeaderVisibility) { case RowHeaderVisibility.Always: return (true); case RowHeaderVisibility.PanelControlled: return (panel.ShowRowHeaders); } return (false); } #endregion #region RenderGroupBackground private void RenderGroupBackground( Graphics g, GroupHeaderVisualStyle style, Rectangle r) { if (style.Background != null && style.Background.IsEmpty == false) { using (Brush br = style.Background.GetBrush(r)) g.FillRectangle(br, r); } } #endregion #region RenderHeaderExpand private void RenderHeaderExpand( Graphics g, GridPanel panel, ref Rectangle r) { if (panel.ShowGroupExpand == true) { Rectangle bounds = _ExpandButtonBounds; if (IsVFrozen == false) bounds.Y -= VScrollOffset; if (panel.IsSubPanel == true) bounds.X -= HScrollOffset; bool hot = (_HitArea == GroupArea.ExpandButton); Image image = (Expanded == true) ? panel.GetCollapseButton(g, hot) : panel.GetExpandButton(g, hot); ExpandDisplay.RenderButton(g, image, bounds, r); int n = panel.TreeButtonIndent + Dpi.Width(panel.LevelIndentSize.Width * IndentLevel); r.X += n; r.Width -= n; } else { r.X += Dpi.Width3; r.Width -= Dpi.Width3; } } #endregion #region RenderHeaderText private void RenderHeaderText(Graphics g, GroupHeaderVisualStyle style, Rectangle r) { eTextFormat tf = style.GetTextFormatFlags(); if (style.Alignment == Alignment.BottomLeft || style.Alignment == Alignment.BottomCenter || style.Alignment == Alignment.BottomRight) { r.Height -= Dpi.Height4; } if (r.Width > 0 && r.Height > 0) { if (_GroupTextMarkup != null) RenderTextMarkup(g, _GroupTextMarkup, style, r); else TextDrawing.DrawString(g, Text, style.Font, style.TextColor, r, tf); } } #region RenderTextMarkup private void RenderTextMarkup(Graphics g, BodyElement textMarkup, GroupHeaderVisualStyle style, Rectangle r) { MarkupDrawContext d = new MarkupDrawContext(g, style.Font, style.TextColor, false); textMarkup.Arrange(new Rectangle(r.Location, r.Size), d); Size size = textMarkup.Bounds.Size; switch (style.Alignment) { case Alignment.MiddleLeft: case Alignment.MiddleCenter: case Alignment.MiddleRight: if (r.Height > size.Height) r.Y += (r.Height - size.Height) / 2; break; default: if (r.Height > size.Height) r.Y = r.Bottom - size.Height; break; } textMarkup.Bounds = new Rectangle(r.Location, size); Region oldClip = g.Clip; try { g.SetClip(r, CombineMode.Intersect); textMarkup.Render(d); } finally { g.Clip = oldClip; } } #endregion #endregion #region RenderHeaderUnderline private void RenderHeaderUnderline(Graphics g, GridPanel panel, GroupHeaderVisualStyle style, Rectangle r) { if (panel.ShowGroupUnderline == true && style.UnderlineColor.IsEmpty == false) { switch (style.Alignment) { case Alignment.MiddleLeft: case Alignment.MiddleCenter: case Alignment.MiddleRight: r.Y += (r.Height + _TextSize.Height) / 2 + Dpi.Height4; break; case Alignment.TopLeft: case Alignment.TopCenter: case Alignment.TopRight: r.Y += _TextSize.Height + Dpi.Height6; break; default: r.Y = r.Bottom - _TextSize.Height / 2; break; } if (r.Width > SViewRect.Width) r.Width = SViewRect.Width; int n = r.Width; r.Height = Dpi.Height1; r.Width = (int)(r.Width * .75); Rectangle t = r; Color color1 = style.UnderlineColor; Color color2 = Color.Transparent; switch (style.Alignment) { case Alignment.TopCenter: case Alignment.MiddleCenter: case Alignment.BottomCenter: r.X += (n - r.Width) / 2; r.Width /= 2; color1 = Color.Transparent; color2 = style.UnderlineColor; break; case Alignment.TopRight: case Alignment.MiddleRight: case Alignment.BottomRight: r.X += n - r.Width; color1 = Color.Transparent; color2 = style.UnderlineColor; break; } t.X = r.X; if ((r.Width > 0 && r.Height > 0) && (t.Width > 0 && t.Height > 0)) { using (LinearGradientBrush br = new LinearGradientBrush(r, color1, color2, 0f)) { br.WrapMode = WrapMode.TileFlipXY; g.FillRectangle(br, t); } } } } #endregion #endregion #region Mouse support #region InternalMouseEnter internal override void InternalMouseEnter(EventArgs e) { base.InternalMouseEnter(e); InvalidateRender(); } #endregion #region InternalMouseLeave internal override void InternalMouseLeave(EventArgs e) { base.InternalMouseLeave(e); InvalidateRender(); } #endregion #region InternalMouseMove internal override void InternalMouseMove(MouseEventArgs e) { GridPanel panel = GridPanel; if (panel != null) { if (IsMouseDown == true) ProcessMouseDownMove(e, panel); ProcessMouseMove(e, panel); } if (Capture == false) base.InternalMouseMove(e); } #region ProcessMouseDownMove private void ProcessMouseDownMove(MouseEventArgs e, GridPanel panel) { Rectangle r = ViewRect; if (MouseDownPoint.Y < r.Y) { int n = SuperGrid.PrimaryGrid.FixedRowHeight - SuperGrid.PrimaryGrid.FixedHeaderHeight; r.Y -= n; r.Height += n; } VScrollBarAdv vsb = SuperGrid.VScrollBar; if ((e.Y >= r.Y) && (e.Y < r.Bottom || (vsb.Value >= vsb.Maximum - vsb.LargeChange))) { SuperGrid.DisableAutoScrolling(); switch (_MouseDownHitArea) { case GroupArea.Content: case GroupArea.RowHeader: _HitItem = GetRowAt(panel, e.Location); if (_HitItem != null) { if (DragStarted(panel, e) == false) { if (panel.MultiSelect == true) { if (_HitItem != panel.LastProcessedItem) ProcessExtendSelection(panel, true); } } } break; } } else { SuperGrid.EnableAutoScrolling(AutoScrollEnable.Vertical, r); } } #endregion #region ProcessMouseMove internal void ProcessMouseMove(MouseEventArgs e, GridPanel panel) { _HitArea = GetGroupAreaAt(e); switch (_HitArea) { case GroupArea.ExpandButton: SuperGrid.GridCursor = Cursors.Hand; break; default: SuperGrid.GridCursor = Cursors.Default; break; } if (_LastHitArea != _HitArea) { _LastHitArea = _HitArea; InvalidateRender(); } } #endregion #region DragStarted private bool DragStarted(GridPanel panel, MouseEventArgs e) { if (_dragSelection == true && Capture == true) { if (_dragStarted == false) { if (DragDrop.DragStarted(_MouseDownPoint, e.Location) == true) { _dragStarted = true; if (SuperGrid.DoItemDragEvent(this, e) == true) { _dragSelection = false; Capture = true; InitExtendSelection(panel); } } } return (true); } return (false); } #endregion #endregion #region InternalMouseDown internal override void InternalMouseDown(MouseEventArgs e) { _MouseDownHitArea = _HitArea; _MouseDownHitRow = _HitItem; _MouseDownPoint = e.Location; GridPanel panel = GridPanel; if (panel != null) { GridCell ecell = SuperGrid.EditorCell; if (ecell != null) { if (ecell.EndEdit() == false) return; } _dragSelection = false; _dragStarted = false; if (_MouseDownHitArea != GroupArea.NoWhere) { if (_MouseDownHitArea == GroupArea.ExpandButton || panel.GroupHeaderClickBehavior == GroupHeaderClickBehavior.ExpandCollapse) { Expanded = !Expanded; } else { if (ShouldExtendSelection(panel) == true) { InitExtendSelection(panel); } else { if (IsMouseDown == true) { Capture = true; _dragSelection = true; } } } } } } #region ShouldExtendSelection private bool ShouldExtendSelection(GridPanel panel) { return (panel.SuperGrid.HasItemDragHandler == false || IsSelected == false || ((Control.ModifierKeys & (Keys.Control | Keys.Shift)) != Keys.None)); } #endregion #region InitExtendSelection private void InitExtendSelection(GridPanel panel) { if (IsMouseSelectable() == true) { Capture = true; ExtendSelectionEx(panel); } } #region IsMouseSelectable private bool IsMouseSelectable() { return (IsMouseSelectableEx(Control.MouseButtons)); } private bool IsMouseSelectableEx(MouseButtons mb) { if ((mb & MouseButtons.Left) == MouseButtons.Left) return (true); return (IsSelected == false); } #endregion #region ExtendSelectionEx private void ExtendSelectionEx(GridPanel panel) { if (_MouseDownHitRow != null && _HitItem != null) { _AnchorIndex = _MouseDownHitRow.GridIndex; if (panel.LastProcessedItem != this && panel.LastProcessedItem != null) panel.LastProcessedItem.InvalidateRender(); bool ckey = panel.MultiSelect == true ? ((Control.ModifierKeys & Keys.Control) == Keys.Control) : false; panel.LastProcessedItem = (ckey == true) ? _HitItem : this; ProcessExtendSelection(panel, false); } } #region ProcessExtendSelection internal void ProcessExtendSelection(GridPanel panel, bool extend) { bool ckey = panel.MultiSelect == true ? ((Control.ModifierKeys & Keys.Control) == Keys.Control) : false; if (ckey == true) ProcessControlExtend(panel, extend); else ProcessNonControlExtend(panel, extend); panel.LastProcessedItem = _HitItem; } #region ProcessControlExtend private void ProcessControlExtend(GridPanel panel, bool extend) { if (panel.LastProcessedItem == null) panel.LastProcessedItem = _MouseDownHitRow; GridContainer lastRow = panel.LastProcessedItem as GridContainer; if (lastRow != null) { int startIndex = lastRow.GridIndex; int endIndex = _HitItem.GridIndex; panel.NormalizeIndices(extend, _AnchorIndex, ref startIndex, ref endIndex); for (int i = startIndex; i <= endIndex; i++) { if (extend == false || i != _AnchorIndex) panel.SetSelectedRows(i, 1, !panel.IsRowSelected(i)); } InvalidateRows(panel, startIndex, endIndex, true); } } #endregion #region ProcessNonControlExtend private void ProcessNonControlExtend(GridPanel panel, bool extend) { bool skey = (panel.MultiSelect == true) ? ((Control.ModifierKeys & Keys.Shift) == Keys.Shift) : false; if (skey == false || panel.SelectionRowAnchor == null) panel.SelectionRowAnchor = _MouseDownHitRow; ExtendSelection(panel, _HitItem, extend); } #endregion #endregion #endregion #endregion #endregion #region InternalMouseUp /// /// InternalMouseUp /// /// internal override void InternalMouseUp(MouseEventArgs e) { SuperGrid.DisableAutoScrolling(); if (ExtendDragSelection(GridPanel, e) == false) { if (_MouseDownHitArea == _HitArea) { if (_MouseDownHitArea == GroupArea.Content || _MouseDownHitArea == GroupArea.RowHeader) { GridPanel panel = GridPanel; if (GridPanel.GroupHeaderClickBehavior == GroupHeaderClickBehavior.SelectAll) { bool ckey = panel.MultiSelect == true ? ((Control.ModifierKeys & Keys.Control) == Keys.Control) : false; ProcessSelectAll(panel, this, ckey); } } SuperGrid.DoGroupHeaderClickEvent(this, _MouseDownHitArea, e); } } } #region ExtendDragSelection private bool ExtendDragSelection(GridPanel panel, MouseEventArgs e) { if (_dragSelection == true && Capture == true) { if (IsMouseSelectableEx(e.Button) == true) { if (_MouseDownHitRow == _HitItem) { ExtendSelectionEx(panel); return (true); } } } return (false); } #endregion #region ProcessSelectAll private void ProcessSelectAll(GridPanel panel, GridContainer item, bool ckey) { if (item.Rows != null && item.Rows.Count > 0) { item.Expanded = true; foreach (GridContainer row in item.Rows) { if (row is GridGroup) { ProcessSelectAll(panel, row, ckey); } else { int startIndex = ((GridContainer)item.Rows[0]).GridIndex; int endIndex = ((GridContainer)item.Rows[item.Rows.Count - 1]).GridIndex; if (ckey == true) { for (int i = startIndex; i <= endIndex; i++) panel.SetSelectedRows(i, 1, !panel.IsRowSelected(i)); } else { panel.SetSelectedRows(startIndex, endIndex - startIndex + 1, true); } break; } } } } #endregion #endregion #region InternalMouseDoubleClick internal override void InternalMouseDoubleClick(MouseEventArgs e) { if (_HitArea == _MouseDownHitArea) SuperGrid.DoGroupHeaderDoubleClickEvent(this, _MouseDownHitArea, e); } #endregion #endregion #region GetGroupAreaAt /// /// Returns element at specified mouse coordinates /// /// Mouse event arguments /// Reference to child Group element or null /// if no element at specified coordinates protected virtual GroupArea GetGroupAreaAt(MouseEventArgs e) { return GetGroupAreaAt(e.X, e.Y); } /// /// Returns element at specified mouse coordinates /// /// Horizontal position /// Vertical position /// Reference to child element or null /// if no element at specified coordinates protected virtual GroupArea GetGroupAreaAt(int x, int y) { GridPanel panel = GridPanel; _HitItem = GetRowAt(panel, new Point(x, y)); Rectangle r = BoundsRelative; r.Height = FixedRowHeight; if (IsVFrozen == false) r.Y -= VScrollOffset; if (panel.IsSubPanel == true) r.X -= HScrollOffset; if (r.Contains(x, y) == true) { if (panel.ShowRowHeaders == true) { if (x >= r.X && x < r.X + panel.RowHeaderWidthEx) return (GroupArea.RowHeader); } r = _ExpandButtonBounds; if (IsVFrozen == false) r.Y -= VScrollOffset; if (GridPanel.IsSubPanel == true) r.X -= HScrollOffset; if (r.Contains(x, y) == true) return (GroupArea.ExpandButton); return (GroupArea.Content); } return (GroupArea.NoWhere); } #endregion #region GetRowAt private GridContainer GetRowAt(GridPanel panel, Point pt) { Rectangle r = panel.ContainerBounds; r.X -= HScrollOffset; if (pt.X < r.X) pt.X = r.X; GridContainer row = panel; GridElement item = row.InternalGetElementAt(pt.X, pt.Y); while (item != null) { row = item as GridContainer; if (row == null) break; if (row is GridRow) item = ((GridRow)row).GetRowElementAt(pt.X, pt.Y, false); else item = row.GetElementAt(pt.X, pt.Y); if (item is GridContainer == false) return (row); } return (null); } #endregion #region InvalidateRender /// /// InvalidateRender /// public override void InvalidateRender() { Rectangle bounds = BoundsRelative; if (IsVFrozen == false) bounds.Y -= VScrollOffset; SuperGridControl grid = SuperGrid; if (grid != null) grid.InvalidateRender(bounds); OnRenderInvalid(EventArgs.Empty); } #endregion #region Style support routines #region GroupHeaderStyleChangeHandler private void GroupHeaderStyleChangeHandler( GroupHeaderVisualStyles oldValue, GroupHeaderVisualStyles newValue) { if (oldValue != null) oldValue.PropertyChanged -= StyleChanged; if (newValue != null) newValue.PropertyChanged += StyleChanged; } #endregion #region GetEffectiveStyle /// /// GetEffectiveStyle /// /// public GroupHeaderVisualStyle GetEffectiveStyle() { StyleState state = GetState(); return (GetEffectiveStyle(state)); } internal GroupHeaderVisualStyle GetEffectiveStyle(StyleType styleType) { ValidateStyle(); return (GetStyle(styleType)); } internal GroupHeaderVisualStyle GetEffectiveStyle(StyleState state) { ValidateStyle(); switch (state) { case StyleState.MouseOver: return (GetStyle(StyleType.MouseOver)); case StyleState.Selected: return (GetStyle(StyleType.Selected)); case StyleState.Selected | StyleState.MouseOver: return (GetStyle(StyleType.SelectedMouseOver)); case StyleState.ReadOnly: return (GetStyle(StyleType.ReadOnly)); case StyleState.ReadOnly | StyleState.MouseOver: return (GetStyle(StyleType.ReadOnlyMouseOver)); case StyleState.ReadOnly | StyleState.Selected: return (GetStyle(StyleType.ReadOnlySelected)); case StyleState.ReadOnly | StyleState.MouseOver | StyleState.Selected: return (GetStyle(StyleType.ReadOnlySelectedMouseOver)); default: return (GetStyle(StyleType.Default)); } } #endregion #region GetStyle private GroupHeaderVisualStyle GetStyle(StyleType e) { if (_EffectiveVisualStyles.IsValid(e) == false) { GroupHeaderVisualStyle style = new GroupHeaderVisualStyle(); StyleType[] css = style.GetApplyStyleTypes(e); if (css != null) { foreach (StyleType cs in css) { style.ApplyStyle(SuperGrid.BaseVisualStyles.GroupHeaderStyles[cs]); style.ApplyStyle(SuperGrid.DefaultVisualStyles.GroupHeaderStyles[cs]); style.ApplyStyle(GridPanel.DefaultVisualStyles.GroupHeaderStyles[cs]); style.ApplyStyle(GroupHeaderVisualStyles[cs]); } } SuperGrid.DoGetGroupHeaderStyleEvent(this, e, ref style); if (style.Background == null || style.Background.IsEmpty == true) style.Background = new Background(Color.White); if (style.Font == null) style.Font = SystemFonts.DefaultFont; if (style.TextColor.IsEmpty) style.TextColor = Color.Black; _EffectiveVisualStyles[e] = style; } return (_EffectiveVisualStyles[e]); } #endregion #region ValidateStyle private void ValidateStyle() { if (_EffectiveVisualStyles == null || (_StyleUpdateCount != SuperGrid.StyleUpdateCount)) { _EffectiveVisualStyles = new GroupHeaderVisualStyles(); _StyleUpdateCount = SuperGrid.StyleUpdateCount; } } #endregion #region GetState internal StyleState GetState() { StyleState rowState = StyleState.Default; if (IsMouseOver == true) { Point pt = SuperGrid.PointToClient(Control.MousePosition); if (Bounds.Contains(pt) == true) rowState |= StyleState.MouseOver; } if (IsSelected == true) rowState |= StyleState.Selected; return (rowState); } #endregion #region GetSizingStyle private GroupHeaderVisualStyle GetSizingStyle(GridPanel panel) { StyleType styleType = panel.GetSizingStyle(); if (styleType == StyleType.NotSet) styleType = StyleType.Default; return (GetEffectiveStyle(styleType)); } #endregion #endregion #region CreateItemsCollection /// /// Creates the GridItemsCollection that hosts the items. /// /// New instance of GridItemsCollection. protected override GridItemsCollection CreateItemsCollection() { GridItemsCollection items = new GridItemsCollection(); items.CollectionChanged += ItemsCollectionChanged; return (items); } #endregion #region DisposeItemsCollection /// /// DisposeItemsCollection /// /// protected override void DisposeItemsCollection(GridItemsCollection items) { items.CollectionChanged -= ItemsCollectionChanged; } #endregion #region ItemsCollectionChanged void ItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { switch (e.Action) { case NotifyCollectionChangedAction.Add: case NotifyCollectionChangedAction.Replace: foreach (GridElement item in e.NewItems) item.Parent = this; break; } GridPanel panel = GridPanel; if (panel != null) panel.RowCollectionChanged(e); } #endregion #region Markup support private void MarkupGroupTextChanged() { _GroupTextMarkup = null; if (Column != null && Column.EnableGroupHeaderMarkup == true) { if (MarkupParser.IsMarkup(_Text) == true) _GroupTextMarkup = MarkupParser.Parse(_Text); } } #endregion #region IDisposable /// /// Dispose /// public override void Dispose() { GroupHeaderVisualStyles = null; Rows = null; base.Dispose(); } #endregion } #region enums #region GroupArea /// /// GroupArea /// public enum GroupArea { /// /// Content /// Content, /// /// ExpandButton /// ExpandButton, /// /// Row Header /// RowHeader, /// /// NoWhere /// NoWhere, } #endregion #endregion }