moel@345: using System; moel@345: using System.Collections.Generic; moel@345: using System.Text; moel@345: using System.Windows.Forms; moel@345: using System.Drawing; moel@345: using Aga.Controls.Tree.NodeControls; moel@345: using System.Drawing.Imaging; moel@345: using System.Threading; moel@345: moel@345: namespace Aga.Controls.Tree moel@345: { moel@345: public partial class TreeViewAdv moel@345: { moel@345: #region Keys moel@345: moel@345: protected override bool IsInputChar(char charCode) moel@345: { moel@345: return true; moel@345: } moel@345: moel@345: protected override bool IsInputKey(Keys keyData) moel@345: { moel@345: if (((keyData & Keys.Up) == Keys.Up) moel@345: || ((keyData & Keys.Down) == Keys.Down) moel@345: || ((keyData & Keys.Left) == Keys.Left) moel@345: || ((keyData & Keys.Right) == Keys.Right)) moel@345: return true; moel@345: else moel@345: return base.IsInputKey(keyData); moel@345: } moel@345: moel@345: internal void ChangeInput() moel@345: { moel@345: if ((ModifierKeys & Keys.Shift) == Keys.Shift) moel@345: { moel@345: if (!(Input is InputWithShift)) moel@345: Input = new InputWithShift(this); moel@345: } moel@345: else if ((ModifierKeys & Keys.Control) == Keys.Control) moel@345: { moel@345: if (!(Input is InputWithControl)) moel@345: Input = new InputWithControl(this); moel@345: } moel@345: else moel@345: { moel@345: if (!(Input.GetType() == typeof(NormalInputState))) moel@345: Input = new NormalInputState(this); moel@345: } moel@345: } moel@345: moel@345: protected override void OnKeyDown(KeyEventArgs e) moel@345: { moel@345: base.OnKeyDown(e); moel@345: if (!e.Handled) moel@345: { moel@345: if (e.KeyCode == Keys.ShiftKey || e.KeyCode == Keys.ControlKey) moel@345: ChangeInput(); moel@345: Input.KeyDown(e); moel@345: if (!e.Handled) moel@345: { moel@345: foreach (NodeControlInfo item in GetNodeControls(CurrentNode)) moel@345: { moel@345: item.Control.KeyDown(e); moel@345: if (e.Handled) moel@345: break; moel@345: } moel@345: } moel@345: } moel@345: } moel@345: moel@345: protected override void OnKeyUp(KeyEventArgs e) moel@345: { moel@345: base.OnKeyUp(e); moel@345: if (!e.Handled) moel@345: { moel@345: if (e.KeyCode == Keys.ShiftKey || e.KeyCode == Keys.ControlKey) moel@345: ChangeInput(); moel@345: if (!e.Handled) moel@345: { moel@345: foreach (NodeControlInfo item in GetNodeControls(CurrentNode)) moel@345: { moel@345: item.Control.KeyUp(e); moel@345: if (e.Handled) moel@345: return; moel@345: } moel@345: } moel@345: } moel@345: } moel@345: moel@345: protected override void OnKeyPress(KeyPressEventArgs e) moel@345: { moel@345: base.OnKeyPress(e); moel@345: if (!e.Handled) moel@345: _search.Search(e.KeyChar); moel@345: } moel@345: moel@345: #endregion moel@345: moel@345: #region Mouse moel@345: moel@345: private TreeNodeAdvMouseEventArgs CreateMouseArgs(MouseEventArgs e) moel@345: { moel@345: TreeNodeAdvMouseEventArgs args = new TreeNodeAdvMouseEventArgs(e); moel@345: args.ViewLocation = new Point(e.X + OffsetX, moel@345: e.Y + _rowLayout.GetRowBounds(FirstVisibleRow).Y - ColumnHeaderHeight); moel@345: args.ModifierKeys = ModifierKeys; moel@345: args.Node = GetNodeAt(e.Location); moel@345: NodeControlInfo info = GetNodeControlInfoAt(args.Node, e.Location); moel@345: args.ControlBounds = info.Bounds; moel@345: args.Control = info.Control; moel@345: return args; moel@345: } moel@345: moel@345: protected override void OnMouseWheel(MouseEventArgs e) moel@345: { moel@345: _search.EndSearch(); moel@345: if (SystemInformation.MouseWheelScrollLines > 0) moel@345: { moel@345: int lines = e.Delta / 120 * SystemInformation.MouseWheelScrollLines; moel@345: int newValue = _vScrollBar.Value - lines; moel@345: newValue = Math.Min(_vScrollBar.Maximum - _vScrollBar.LargeChange + 1, newValue); moel@345: newValue = Math.Min(_vScrollBar.Maximum, newValue); moel@345: _vScrollBar.Value = Math.Max(_vScrollBar.Minimum, newValue); moel@345: } moel@345: base.OnMouseWheel(e); moel@345: } moel@345: moel@345: protected override void OnMouseDown(MouseEventArgs e) moel@345: { moel@345: if (CurrentEditorOwner != null) moel@345: { moel@345: CurrentEditorOwner.EndEdit(true); moel@345: return; moel@345: } moel@345: moel@345: if (!Focused) moel@345: Focus(); moel@345: moel@345: _search.EndSearch(); moel@345: if (e.Button == MouseButtons.Left) moel@345: { moel@345: TreeColumn c; moel@345: c = GetColumnDividerAt(e.Location); moel@345: if (c != null) moel@345: { moel@345: Input = new ResizeColumnState(this, c, e.Location); moel@345: return; moel@345: } moel@345: c = GetColumnAt(e.Location); moel@345: if (c != null) moel@345: { moel@345: Input = new ClickColumnState(this, c, e.Location); moel@345: UpdateView(); moel@345: return; moel@345: } moel@345: } moel@345: moel@345: ChangeInput(); moel@345: TreeNodeAdvMouseEventArgs args = CreateMouseArgs(e); moel@345: moel@345: if (args.Node != null && args.Control != null) moel@345: args.Control.MouseDown(args); moel@345: moel@345: if (!args.Handled) moel@345: Input.MouseDown(args); moel@345: moel@345: base.OnMouseDown(e); moel@345: } moel@345: moel@345: protected override void OnMouseClick(MouseEventArgs e) moel@345: { moel@345: //TODO: Disable when click on plusminus icon moel@345: TreeNodeAdvMouseEventArgs args = CreateMouseArgs(e); moel@345: if (args.Node != null) moel@345: OnNodeMouseClick(args); moel@345: moel@345: base.OnMouseClick(e); moel@345: } moel@345: moel@345: protected override void OnMouseDoubleClick(MouseEventArgs e) moel@345: { moel@345: TreeNodeAdvMouseEventArgs args = CreateMouseArgs(e); moel@345: moel@345: if (args.Node != null && args.Control != null) moel@345: args.Control.MouseDoubleClick(args); moel@345: moel@345: if (!args.Handled) moel@345: { moel@345: if (args.Node != null) moel@345: OnNodeMouseDoubleClick(args); moel@345: else moel@345: Input.MouseDoubleClick(args); moel@345: moel@345: if (!args.Handled) moel@345: { moel@345: if (args.Node != null && args.Button == MouseButtons.Left) moel@345: args.Node.IsExpanded = !args.Node.IsExpanded; moel@345: } moel@345: } moel@345: moel@345: base.OnMouseDoubleClick(e); moel@345: } moel@345: moel@345: protected override void OnMouseUp(MouseEventArgs e) moel@345: { moel@345: TreeNodeAdvMouseEventArgs args = CreateMouseArgs(e); moel@345: if (Input is ResizeColumnState) moel@345: Input.MouseUp(args); moel@345: else moel@345: { moel@345: if (args.Node != null && args.Control != null) moel@345: args.Control.MouseUp(args); moel@345: if (!args.Handled) moel@345: Input.MouseUp(args); moel@345: moel@345: base.OnMouseUp(e); moel@345: } moel@345: } moel@345: moel@345: protected override void OnMouseMove(MouseEventArgs e) moel@345: { moel@345: if (Input.MouseMove(e)) moel@345: return; moel@345: moel@345: base.OnMouseMove(e); moel@345: SetCursor(e); moel@345: UpdateToolTip(e); moel@345: if (ItemDragMode && Dist(e.Location, ItemDragStart) > ItemDragSensivity moel@345: && CurrentNode != null && CurrentNode.IsSelected) moel@345: { moel@345: ItemDragMode = false; moel@345: _toolTip.Active = false; moel@345: OnItemDrag(e.Button, Selection.ToArray()); moel@345: } moel@345: } moel@345: moel@345: protected override void OnMouseLeave(EventArgs e) moel@345: { moel@345: _hotColumn = null; moel@345: UpdateHeaders(); moel@345: base.OnMouseLeave(e); moel@345: } moel@345: moel@345: private void SetCursor(MouseEventArgs e) moel@345: { moel@345: TreeColumn col; moel@345: col = GetColumnDividerAt(e.Location); moel@345: if (col == null) moel@345: _innerCursor = null; moel@345: else moel@345: { moel@345: if (col.Width == 0) moel@345: _innerCursor = ResourceHelper.DVSplitCursor; moel@345: else moel@345: _innerCursor = Cursors.VSplit; moel@345: } moel@345: moel@345: col = GetColumnAt(e.Location); moel@345: if (col != _hotColumn) moel@345: { moel@345: _hotColumn = col; moel@345: UpdateHeaders(); moel@345: } moel@345: } moel@345: moel@345: internal TreeColumn GetColumnAt(Point p) moel@345: { moel@345: if (p.Y > ColumnHeaderHeight) moel@345: return null; moel@345: moel@345: int x = -OffsetX; moel@345: foreach (TreeColumn col in Columns) moel@345: { moel@345: if (col.IsVisible) moel@345: { moel@345: Rectangle rect = new Rectangle(x, 0, col.Width, ColumnHeaderHeight); moel@345: x += col.Width; moel@345: if (rect.Contains(p)) moel@345: return col; moel@345: } moel@345: } moel@345: return null; moel@345: } moel@345: moel@345: internal int GetColumnX(TreeColumn column) moel@345: { moel@345: int x = -OffsetX; moel@345: foreach (TreeColumn col in Columns) moel@345: { moel@345: if (col.IsVisible) moel@345: { moel@345: if (column == col) moel@345: return x; moel@345: else moel@345: x += col.Width; moel@345: } moel@345: } moel@345: return x; moel@345: } moel@345: moel@345: internal TreeColumn GetColumnDividerAt(Point p) moel@345: { moel@345: if (p.Y > ColumnHeaderHeight) moel@345: return null; moel@345: moel@345: int x = -OffsetX; moel@345: TreeColumn prevCol = null; moel@345: Rectangle left, right; moel@345: foreach (TreeColumn col in Columns) moel@345: { moel@345: if (col.IsVisible) moel@345: { moel@345: if (col.Width > 0) moel@345: { moel@345: left = new Rectangle(x, 0, DividerWidth / 2, ColumnHeaderHeight); moel@345: right = new Rectangle(x + col.Width - (DividerWidth / 2), 0, DividerWidth / 2, ColumnHeaderHeight); moel@345: if (left.Contains(p) && prevCol != null) moel@345: return prevCol; moel@345: else if (right.Contains(p)) moel@345: return col; moel@345: } moel@345: prevCol = col; moel@345: x += col.Width; moel@345: } moel@345: } moel@345: moel@345: left = new Rectangle(x, 0, DividerWidth / 2, ColumnHeaderHeight); moel@345: if (left.Contains(p) && prevCol != null) moel@345: return prevCol; moel@345: moel@345: return null; moel@345: } moel@345: moel@345: TreeColumn _tooltipColumn; moel@345: private void UpdateToolTip(MouseEventArgs e) moel@345: { moel@345: TreeColumn col = GetColumnAt(e.Location); moel@345: if (col != null) moel@345: { moel@345: if (col != _tooltipColumn) moel@345: SetTooltip(col.TooltipText); moel@345: } moel@345: else moel@345: DisplayNodesTooltip(e); moel@345: _tooltipColumn = col; moel@345: } moel@345: moel@345: TreeNodeAdv _hotNode; moel@345: NodeControl _hotControl; moel@345: private void DisplayNodesTooltip(MouseEventArgs e) moel@345: { moel@345: if (ShowNodeToolTips) moel@345: { moel@345: TreeNodeAdvMouseEventArgs args = CreateMouseArgs(e); moel@345: if (args.Node != null && args.Control != null) moel@345: { moel@345: if (args.Node != _hotNode || args.Control != _hotControl) moel@345: SetTooltip(GetNodeToolTip(args)); moel@345: } moel@345: else moel@345: _toolTip.SetToolTip(this, null); moel@345: moel@345: _hotControl = args.Control; moel@345: _hotNode = args.Node; moel@345: } moel@345: else moel@345: _toolTip.SetToolTip(this, null); moel@345: } moel@345: moel@345: private void SetTooltip(string text) moel@345: { moel@345: if (!String.IsNullOrEmpty(text)) moel@345: { moel@345: _toolTip.Active = false; moel@345: _toolTip.SetToolTip(this, text); moel@345: _toolTip.Active = true; moel@345: } moel@345: else moel@345: _toolTip.SetToolTip(this, null); moel@345: } moel@345: moel@345: private string GetNodeToolTip(TreeNodeAdvMouseEventArgs args) moel@345: { moel@345: string msg = args.Control.GetToolTip(args.Node); moel@345: moel@345: BaseTextControl btc = args.Control as BaseTextControl; moel@345: if (btc != null && btc.DisplayHiddenContentInToolTip && String.IsNullOrEmpty(msg)) moel@345: { moel@345: Size ms = btc.GetActualSize(args.Node, _measureContext); moel@345: if (ms.Width > args.ControlBounds.Size.Width || ms.Height > args.ControlBounds.Size.Height moel@345: || args.ControlBounds.Right - OffsetX > DisplayRectangle.Width) moel@345: msg = btc.GetLabel(args.Node); moel@345: } moel@345: moel@345: if (String.IsNullOrEmpty(msg) && DefaultToolTipProvider != null) moel@345: msg = DefaultToolTipProvider.GetToolTip(args.Node, args.Control); moel@345: moel@345: return msg; moel@345: } moel@345: moel@345: #endregion moel@345: moel@345: #region DragDrop moel@345: moel@345: private bool _dragAutoScrollFlag = false; moel@345: private Bitmap _dragBitmap = null; moel@345: private System.Threading.Timer _dragTimer; moel@345: moel@345: private void StartDragTimer() moel@345: { moel@345: if (_dragTimer == null) moel@345: _dragTimer = new System.Threading.Timer(new TimerCallback(DragTimerTick), null, 0, 100); moel@345: } moel@345: moel@345: private void StopDragTimer() moel@345: { moel@345: if (_dragTimer != null) moel@345: { moel@345: _dragTimer.Dispose(); moel@345: _dragTimer = null; moel@345: } moel@345: } moel@345: moel@345: private void SetDropPosition(Point pt) moel@345: { moel@345: TreeNodeAdv node = GetNodeAt(pt); moel@345: OnDropNodeValidating(pt, ref node); moel@345: _dropPosition.Node = node; moel@345: if (node != null) moel@345: { moel@345: Rectangle first = _rowLayout.GetRowBounds(FirstVisibleRow); moel@345: Rectangle bounds = _rowLayout.GetRowBounds(node.Row); moel@345: float pos = (pt.Y + first.Y - ColumnHeaderHeight - bounds.Y) / (float)bounds.Height; moel@345: if (pos < TopEdgeSensivity) moel@345: _dropPosition.Position = NodePosition.Before; moel@345: else if (pos > (1 - BottomEdgeSensivity)) moel@345: _dropPosition.Position = NodePosition.After; moel@345: else moel@345: _dropPosition.Position = NodePosition.Inside; moel@345: } moel@345: } moel@345: moel@345: private void DragTimerTick(object state) moel@345: { moel@345: _dragAutoScrollFlag = true; moel@345: } moel@345: moel@345: private void DragAutoScroll() moel@345: { moel@345: _dragAutoScrollFlag = false; moel@345: Point pt = PointToClient(MousePosition); moel@345: if (pt.Y < 20 && _vScrollBar.Value > 0) moel@345: _vScrollBar.Value--; moel@345: else if (pt.Y > Height - 20 && _vScrollBar.Value <= _vScrollBar.Maximum - _vScrollBar.LargeChange) moel@345: _vScrollBar.Value++; moel@345: } moel@345: moel@345: public void DoDragDropSelectedNodes(DragDropEffects allowedEffects) moel@345: { moel@345: if (SelectedNodes.Count > 0) moel@345: { moel@345: TreeNodeAdv[] nodes = new TreeNodeAdv[SelectedNodes.Count]; moel@345: SelectedNodes.CopyTo(nodes, 0); moel@345: DoDragDrop(nodes, allowedEffects); moel@345: } moel@345: } moel@345: moel@345: private void CreateDragBitmap(IDataObject data) moel@345: { moel@345: if (UseColumns || !DisplayDraggingNodes) moel@345: return; moel@345: moel@345: TreeNodeAdv[] nodes = data.GetData(typeof(TreeNodeAdv[])) as TreeNodeAdv[]; moel@345: if (nodes != null && nodes.Length > 0) moel@345: { moel@345: Rectangle rect = DisplayRectangle; moel@345: Bitmap bitmap = new Bitmap(rect.Width, rect.Height); moel@345: using (Graphics gr = Graphics.FromImage(bitmap)) moel@345: { moel@345: gr.Clear(BackColor); moel@345: DrawContext context = new DrawContext(); moel@345: context.Graphics = gr; moel@345: context.Font = Font; moel@345: context.Enabled = true; moel@345: int y = 0; moel@345: int maxWidth = 0; moel@345: foreach (TreeNodeAdv node in nodes) moel@345: { moel@345: if (node.Tree == this) moel@345: { moel@345: int x = 0; moel@345: int height = _rowLayout.GetRowBounds(node.Row).Height; moel@345: foreach (NodeControl c in NodeControls) moel@345: { moel@345: Size s = c.GetActualSize(node, context); moel@345: if (!s.IsEmpty) moel@345: { moel@345: int width = s.Width; moel@345: rect = new Rectangle(x, y, width, height); moel@345: x += (width + 1); moel@345: context.Bounds = rect; moel@345: c.Draw(node, context); moel@345: } moel@345: } moel@345: y += height; moel@345: maxWidth = Math.Max(maxWidth, x); moel@345: } moel@345: } moel@345: moel@345: if (maxWidth > 0 && y > 0) moel@345: { moel@345: _dragBitmap = new Bitmap(maxWidth, y, PixelFormat.Format32bppArgb); moel@345: using (Graphics tgr = Graphics.FromImage(_dragBitmap)) moel@345: tgr.DrawImage(bitmap, Point.Empty); moel@345: BitmapHelper.SetAlphaChanelValue(_dragBitmap, 150); moel@345: } moel@345: else moel@345: _dragBitmap = null; moel@345: } moel@345: } moel@345: } moel@345: moel@345: protected override void OnDragOver(DragEventArgs drgevent) moel@345: { moel@345: ItemDragMode = false; moel@345: Point pt = PointToClient(new Point(drgevent.X, drgevent.Y)); moel@345: if (_dragAutoScrollFlag) moel@345: DragAutoScroll(); moel@345: SetDropPosition(pt); moel@345: UpdateView(); moel@345: base.OnDragOver(drgevent); moel@345: } moel@345: moel@345: protected override void OnDragEnter(DragEventArgs drgevent) moel@345: { moel@345: _search.EndSearch(); moel@345: DragMode = true; moel@345: CreateDragBitmap(drgevent.Data); moel@345: base.OnDragEnter(drgevent); moel@345: } moel@345: moel@345: protected override void OnDragLeave(EventArgs e) moel@345: { moel@345: DragMode = false; moel@345: UpdateView(); moel@345: base.OnDragLeave(e); moel@345: } moel@345: moel@345: protected override void OnDragDrop(DragEventArgs drgevent) moel@345: { moel@345: DragMode = false; moel@345: UpdateView(); moel@345: base.OnDragDrop(drgevent); moel@345: } moel@345: moel@345: #endregion moel@345: } moel@345: }