From 7e43827beecfb86e97d2ab79683fa315533f5b63 Mon Sep 17 00:00:00 2001 From: Robin Date: Sat, 2 Jan 2016 06:52:48 +0000 Subject: [PATCH] Can now drag tool windows between groups. --- DarkUI/DarkUI.csproj | 5 +- DarkUI/Docking/DarkDockGroup.cs | 2 + DarkUI/Docking/DarkDockPanel.cs | 27 +++- DarkUI/Docking/DarkDockRegion.cs | 13 ++ DarkUI/Docking/DarkToolWindow.cs | 26 +++ ...ScrollFilter.cs => ControlScrollFilter.cs} | 2 +- DarkUI/Win32/DockContentDragFilter.cs | 149 ++++++++++++++++++ ...ockResizeFilter.cs => DockResizeFilter.cs} | 4 +- Example/Forms/MainForm.cs | 7 +- todo.txt | 9 +- 10 files changed, 233 insertions(+), 11 deletions(-) rename DarkUI/Win32/{DarkControlScrollFilter.cs => ControlScrollFilter.cs} (91%) create mode 100644 DarkUI/Win32/DockContentDragFilter.cs rename DarkUI/Win32/{DarkDockResizeFilter.cs => DockResizeFilter.cs} (97%) diff --git a/DarkUI/DarkUI.csproj b/DarkUI/DarkUI.csproj index cc238b4..0b9b31a 100644 --- a/DarkUI/DarkUI.csproj +++ b/DarkUI/DarkUI.csproj @@ -178,11 +178,12 @@ True TreeViewIcons.resx - + - + + diff --git a/DarkUI/Docking/DarkDockGroup.cs b/DarkUI/Docking/DarkDockGroup.cs index 8ed27f6..1d48689 100644 --- a/DarkUI/Docking/DarkDockGroup.cs +++ b/DarkUI/Docking/DarkDockGroup.cs @@ -529,7 +529,9 @@ namespace DarkUI.Docking { DockPanel.ActiveContent = tab.DockContent; EnsureVisible(); + _dragTab = tab; + return; } } diff --git a/DarkUI/Docking/DarkDockPanel.cs b/DarkUI/Docking/DarkDockPanel.cs index 6cc0513..d551e26 100644 --- a/DarkUI/Docking/DarkDockPanel.cs +++ b/DarkUI/Docking/DarkDockPanel.cs @@ -78,7 +78,11 @@ namespace DarkUI.Docking [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public IMessageFilter MessageFilter { get; private set; } + public DockContentDragFilter DockContentDragFilter { get; private set; } + + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public DockResizeFilter DockResizeFilter { get; private set; } [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] @@ -95,6 +99,16 @@ namespace DarkUI.Docking } } + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public List Regions + { + get + { + return _regions.Values.ToList(); + } + } + #endregion #region Constructor Region @@ -102,7 +116,8 @@ namespace DarkUI.Docking public DarkDockPanel() { Splitters = new List(); - MessageFilter = new DarkDockResizeFilter(this); + DockContentDragFilter = new DockContentDragFilter(this); + DockResizeFilter = new DockResizeFilter(this); _regions = new Dictionary(); _contents = new List(); @@ -129,6 +144,9 @@ namespace DarkUI.Docking dockContent.DockPanel = this; _contents.Add(dockContent); + if (dockGroup != null) + dockContent.DockArea = dockGroup.DockArea; + if (dockContent.DockArea == DarkDockArea.None) dockContent.DockArea = dockContent.DefaultDockArea; @@ -194,6 +212,11 @@ namespace DarkUI.Docking leftRegion.TabIndex = 3; } + public void DragContent(DarkDockContent content) + { + DockContentDragFilter.StartDrag(content); + } + #endregion #region Serialization Region diff --git a/DarkUI/Docking/DarkDockRegion.cs b/DarkUI/Docking/DarkDockRegion.cs index d89bc8c..09cf836 100644 --- a/DarkUI/Docking/DarkDockRegion.cs +++ b/DarkUI/Docking/DarkDockRegion.cs @@ -37,6 +37,14 @@ namespace DarkUI.Docking } } + public List Groups + { + get + { + return _groups.ToList(); + } + } + #endregion #region Constructor Region @@ -92,6 +100,8 @@ namespace DarkUI.Docking var group = dockContent.DockGroup; group.RemoveContent(dockContent); + dockContent.DockArea = DarkDockArea.None; + // If that was the final content in the group then remove the group if (group.ContentCount == 0) RemoveGroup(group); @@ -250,6 +260,9 @@ namespace DarkUI.Docking private void CreateSplitter() { + if (_splitter != null && DockPanel.Splitters.Contains(_splitter)) + DockPanel.Splitters.Remove(_splitter); + switch (DockArea) { case DarkDockArea.Left: diff --git a/DarkUI/Docking/DarkToolWindow.cs b/DarkUI/Docking/DarkToolWindow.cs index b18201b..5d7c783 100644 --- a/DarkUI/Docking/DarkToolWindow.cs +++ b/DarkUI/Docking/DarkToolWindow.cs @@ -15,6 +15,9 @@ namespace DarkUI.Docking private bool _closeButtonHot = false; private bool _closeButtonPressed = false; + private Rectangle _headerRect; + private bool _shouldDrag; + #endregion #region Property Region @@ -56,6 +59,14 @@ namespace DarkUI.Docking private void UpdateCloseButton() { + _headerRect = new Rectangle + { + X = ClientRectangle.Left, + Y = ClientRectangle.Top, + Width = ClientRectangle.Width, + Height = Consts.ToolWindowHeaderSize + }; + _closeButtonRect = new Rectangle { X = ClientRectangle.Right - DockIcons.tw_close.Width - 5 - 3, @@ -95,6 +106,12 @@ namespace DarkUI.Docking _closeButtonHot = false; Invalidate(); } + + if (_shouldDrag) + { + DockPanel.DragContent(this); + return; + } } } @@ -107,6 +124,13 @@ namespace DarkUI.Docking _closeButtonPressed = true; _closeButtonHot = true; Invalidate(); + return; + } + + if (_headerRect.Contains(e.Location)) + { + _shouldDrag = true; + return; } } @@ -120,6 +144,8 @@ namespace DarkUI.Docking _closeButtonPressed = false; _closeButtonHot = false; + _shouldDrag = false; + Invalidate(); } diff --git a/DarkUI/Win32/DarkControlScrollFilter.cs b/DarkUI/Win32/ControlScrollFilter.cs similarity index 91% rename from DarkUI/Win32/DarkControlScrollFilter.cs rename to DarkUI/Win32/ControlScrollFilter.cs index 8c07a4d..191bdf9 100644 --- a/DarkUI/Win32/DarkControlScrollFilter.cs +++ b/DarkUI/Win32/ControlScrollFilter.cs @@ -3,7 +3,7 @@ using System.Windows.Forms; namespace DarkUI.Win32 { - public class DarkControlScrollFilter : IMessageFilter + public class ControlScrollFilter : IMessageFilter { public bool PreFilterMessage(ref Message m) { diff --git a/DarkUI/Win32/DockContentDragFilter.cs b/DarkUI/Win32/DockContentDragFilter.cs new file mode 100644 index 0000000..35cfdaa --- /dev/null +++ b/DarkUI/Win32/DockContentDragFilter.cs @@ -0,0 +1,149 @@ +using DarkUI.Config; +using DarkUI.Docking; +using DarkUI.Forms; +using System.Collections.Generic; +using System.Drawing; +using System.Windows.Forms; + +namespace DarkUI.Win32 +{ + public class DockContentDragFilter : IMessageFilter + { + #region Field Region + + private DarkDockPanel _dockPanel; + + private DarkDockContent _dragContent; + + private DarkTranslucentForm _highlightForm; + + private DarkDockGroup _targetGroup; + + private Dictionary _groupDropAreas = new Dictionary(); + + #endregion + + #region Constructor Region + + public DockContentDragFilter(DarkDockPanel dockPanel) + { + _dockPanel = dockPanel; + + _highlightForm = new DarkTranslucentForm(Colors.BlueSelection); + } + + #endregion + + #region IMessageFilter Region + + public bool PreFilterMessage(ref Message m) + { + // Exit out early if we're not dragging any content + if (_dragContent == null) + return false; + + // We only care about mouse events + if (!(m.Msg == (int)WM.MOUSEMOVE || + m.Msg == (int)WM.LBUTTONDOWN || m.Msg == (int)WM.LBUTTONUP || m.Msg == (int)WM.LBUTTONDBLCLK || + m.Msg == (int)WM.RBUTTONDOWN || m.Msg == (int)WM.RBUTTONUP || m.Msg == (int)WM.RBUTTONDBLCLK)) + return false; + + // Move content + if (m.Msg == (int)WM.MOUSEMOVE) + { + HandleDrag(); + return false; + } + + // Drop content + if (m.Msg == (int)WM.LBUTTONUP) + { + if (_targetGroup != null) + _dockPanel.AddContent(_dragContent, _targetGroup); + + StopDrag(); + return false; + } + + return true; + } + + #endregion + + #region Method Region + + public void StartDrag(DarkDockContent content) + { + _groupDropAreas = new Dictionary(); + + foreach (var region in _dockPanel.Regions) + { + foreach (var group in region.Groups) + { + var rect = new Rectangle + { + X = group.PointToScreen(Point.Empty).X, + Y = group.PointToScreen(Point.Empty).Y, + Width = group.Width, + Height = group.Height + }; + + _groupDropAreas.Add(group, rect); + } + } + + _dragContent = content; + } + + private void StopDrag() + { + _highlightForm.Hide(); + _dragContent = null; + } + + private void HandleDrag() + { + var location = Cursor.Position; + + _targetGroup = null; + + foreach (var keyValuePair in _groupDropAreas) + { + var group = keyValuePair.Key; + var rect = keyValuePair.Value; + + if (group == _dragContent.DockGroup) + continue; + + if (group.DockArea == DarkDockArea.Document) + continue; + + if (rect.Contains(location)) + { + _targetGroup = group; + + _highlightForm.Location = new Point(rect.X, rect.Y); + _highlightForm.Size = new Size(rect.Width, rect.Height); + } + } + + if (_targetGroup == null) + { + if (_highlightForm.Visible) + { + _highlightForm.Hide(); + } + } + else + { + if (!_highlightForm.Visible) + { + _highlightForm.Show(); + _highlightForm.BringToFront(); + } + } + } + + #endregion + } +} diff --git a/DarkUI/Win32/DarkDockResizeFilter.cs b/DarkUI/Win32/DockResizeFilter.cs similarity index 97% rename from DarkUI/Win32/DarkDockResizeFilter.cs rename to DarkUI/Win32/DockResizeFilter.cs index 0c5be57..2954c43 100644 --- a/DarkUI/Win32/DarkDockResizeFilter.cs +++ b/DarkUI/Win32/DockResizeFilter.cs @@ -5,7 +5,7 @@ using System.Windows.Forms; namespace DarkUI.Win32 { - public class DarkDockResizeFilter : IMessageFilter + public class DockResizeFilter : IMessageFilter { #region Field Region @@ -20,7 +20,7 @@ namespace DarkUI.Win32 #region Constructor Region - public DarkDockResizeFilter(DarkDockPanel dockPanel) + public DockResizeFilter(DarkDockPanel dockPanel) { _dockPanel = dockPanel; diff --git a/Example/Forms/MainForm.cs b/Example/Forms/MainForm.cs index 4d717cd..0f9402d 100644 --- a/Example/Forms/MainForm.cs +++ b/Example/Forms/MainForm.cs @@ -30,11 +30,14 @@ namespace Example // Add the control scroll message filter to re-route all mousewheel events // to the control the user is currently hovering over with their cursor. - Application.AddMessageFilter(new DarkControlScrollFilter()); + Application.AddMessageFilter(new ControlScrollFilter()); + + // Add the dock content drag message filter to handle moving dock content around. + Application.AddMessageFilter(DockPanel.DockContentDragFilter); // Add the dock panel message filter to filter through for dock panel splitter // input before letting events pass through to the rest of the application. - Application.AddMessageFilter(DockPanel.MessageFilter); + Application.AddMessageFilter(DockPanel.DockResizeFilter); // Hook in all the UI events manually for clarity. HookEvents(); diff --git a/todo.txt b/todo.txt index 62d9e15..5e3f80e 100644 --- a/todo.txt +++ b/todo.txt @@ -14,9 +14,14 @@ DarkUI -- standardise the amount you scroll through with the mousewheel. Basing it on the pixels makes it weird. -- ScrollView not taking in to account size WITHOUT scrollbars causing you to have to overshoot when re-sizing to get rid of them -- if the final node in a treeview has been previous expanded, pressing 'down' will cause it to re-open +-- create click-through panel Dock panel --- drag tabs and toolwindows to re-order or change region +-- make it so highlight form doesn't steal focus -- add splitters between region groups -- fix max position of splitters --- serialise the visible content for groups and the active content \ No newline at end of file +-- serialise the visible content for groups and the active content +-- right click tab menu. close all, close all but this etc. etc. +-- stop dragging tabs instantly going to the end of the row +-- stop differently sized toolwindow tabs from vibrating when dragging +-- fix regions being visible with no groups on load \ No newline at end of file