📄 draghandler.cs
字号:
#region Fireball License
// Copyright (C) 2005 Sebastian Faltoni sebastian{at}dotnetfireball{dot}net
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#endregion
#region Original License
// *****************************************************************************
//
// Copyright 2004, Weifen Luo
// All rights reserved. The software and associated documentation
// supplied hereunder are the proprietary information of Weifen Luo
// and are supplied subject to licence terms.
//
// WinFormsUI Library Version 1.0
// *****************************************************************************
#endregion
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Fireball.Docking
{
/// <summary>
/// Summary description for DragHandler.
/// </summary>
internal sealed class DragHandler : DragHandlerBase
{
internal enum DragSource
{
Content,
Pane,
FloatWindow,
PaneSplitter,
DockWindowSplitter,
AutoHideWindowSplitter
}
private Point m_splitterLocation;
private Point m_mouseOffset = Point.Empty;
public DragHandler(DockContainer dockPanel)
{
m_dockPanel = dockPanel;
}
private DragSource m_source;
internal DragSource Source
{
get { return m_source; }
}
private DockContainer m_dockPanel;
public DockContainer DockPanel
{
get { return m_dockPanel; }
}
private DockOutlineBase m_dockOutline;
internal DockOutlineBase DockOutline
{
get { return m_dockOutline; }
}
private SplitterOutline m_splitterOutline;
private SplitterOutline SplitterOutline
{
get { return m_splitterOutline; }
}
private DockIndicator m_dockIndicator;
private DockIndicator DockIndicator
{
get { return m_dockIndicator; }
}
public void BeginDragContent(IDockableWindow content)
{
if (!InitDrag(content as Control, DragSource.Content))
return;
Content_BeginDrag(content);
}
public void BeginDragPane(DockPane pane)
{
if (!InitDrag(pane, DragSource.Pane))
return;
Pane_BeginDrag();
}
public void BeginDragPaneSplitter(DockPaneSplitter splitter)
{
if (!InitDrag(splitter, DragSource.PaneSplitter))
return;
PaneSplitter_BeginDrag(splitter.Location);
}
public void BeginDragAutoHideWindowSplitter(AutoHideWindow autoHideWindow, Point splitterLocation)
{
if (!InitDrag(autoHideWindow, DragSource.AutoHideWindowSplitter))
return;
autoHideWindow.FlagDragging = true;
AutoHideWindowSplitter_BeginDrag(splitterLocation);
}
public void BeginDragDockWindowSplitter(DockWindow dockWindow, Point splitterLocation)
{
if (!InitDrag(dockWindow, DragSource.DockWindowSplitter))
return;
DockWindowSplitter_BeginDrag(splitterLocation);
}
public void BeginDragFloatWindow(FloatWindow floatWindow)
{
if (!InitDrag(floatWindow, DragSource.FloatWindow))
return;
FloatWindow_BeginDrag();
}
private bool InitDrag(Control c, DragSource source)
{
if (!base.BeginDrag(c))
return false;
m_source = source;
if (Source == DragSource.Content ||
Source == DragSource.Pane ||
Source == DragSource.FloatWindow)
{
m_dockOutline = new DockOutline();
m_dockIndicator = new DockIndicator(this);
DockIndicator.Show(false);
}
else if (Source == DragSource.AutoHideWindowSplitter ||
Source == DragSource.DockWindowSplitter ||
Source == DragSource.PaneSplitter)
m_splitterOutline = new SplitterOutline();
else
return false;
return true;
}
protected override void OnDragging()
{
if (Source == DragSource.Content ||
Source == DragSource.Pane ||
Source == DragSource.FloatWindow)
TestDrop();
else if (Source == DragSource.PaneSplitter)
SplitterOutline.Show(GetPaneSplitterDragRectangle());
else if (Source == DragSource.DockWindowSplitter)
SplitterOutline.Show(GetWindowSplitterDragRectangle());
else if (Source == DragSource.AutoHideWindowSplitter)
SplitterOutline.Show(GetWindowSplitterDragRectangle());
}
protected override void OnEndDrag(bool abort)
{
if (Source == DragSource.Content ||
Source == DragSource.Pane ||
Source == DragSource.FloatWindow)
{
DockOutline.Close();
DockIndicator.Close();
}
else if (Source == DragSource.AutoHideWindowSplitter ||
Source == DragSource.DockWindowSplitter ||
Source == DragSource.PaneSplitter)
SplitterOutline.Close();
if (Source == DragSource.Content)
Content_OnEndDrag(abort);
else if (Source == DragSource.Pane)
Pane_OnEndDrag(abort);
else if (Source == DragSource.PaneSplitter)
PaneSplitter_OnEndDrag(abort);
else if (Source == DragSource.DockWindowSplitter)
DockWindowSplitter_OnEndDrag(abort);
else if (Source == DragSource.AutoHideWindowSplitter)
AutoHideWindowSplitter_OnEndDrag(abort);
else if (Source == DragSource.FloatWindow)
FloatWindow_OnEndDrag(abort);
}
private void Content_BeginDrag(IDockableWindow content)
{
DockPane pane = content.DockHandler.Pane;
Rectangle rectPane = pane.ClientRectangle;
Point pt;
if (pane.DockState == DockState.Document)
pt = new Point(rectPane.Left, rectPane.Top);
else
pt = new Point(rectPane.Left, rectPane.Bottom);
pt = pane.PointToScreen(pt);
m_mouseOffset.X = pt.X - StartMousePosition.X;
m_mouseOffset.Y = pt.Y - StartMousePosition.Y;
}
private void Content_OnEndDrag(bool abort)
{
User32.SetCursor(DragControl.Cursor.Handle);
if (abort)
return;
IDockableWindow content = DragControl as IDockableWindow;
if (!DockOutline.FloatWindowBounds.IsEmpty)
{
DockPane pane = content.DockHandler.DockPanel.DockPaneFactory.CreateDockPane(content, DockOutline.FloatWindowBounds, true);
pane.Activate();
}
else if (DockOutline.DockTo is DockPane)
{
DockPane paneTo = DockOutline.DockTo as DockPane;
if (DockOutline.Dock == DockStyle.Fill)
{
bool samePane = (content.DockHandler.Pane == paneTo);
if (!samePane)
content.DockHandler.Pane = paneTo;
if (DockOutline.ContentIndex == -1 || !samePane)
paneTo.SetContentIndex(content, DockOutline.ContentIndex);
else
{
DockContentCollection contents = paneTo.Contents;
int oldIndex = contents.IndexOf(content);
int newIndex = DockOutline.ContentIndex;
if (oldIndex < newIndex)
{
newIndex += 1;
if (newIndex > contents.Count -1)
newIndex = -1;
}
paneTo.SetContentIndex(content, newIndex);
}
content.DockHandler.Activate();
}
else
{
DockPane pane = content.DockHandler.DockPanel.DockPaneFactory.CreateDockPane(content, paneTo.DockState, true);
IDockListContainer container = paneTo.DockListContainer;
if (DockOutline.Dock == DockStyle.Left)
pane.AddToDockList(container, paneTo, DockAlignment.Left, 0.5);
else if (DockOutline.Dock == DockStyle.Right)
pane.AddToDockList(container, paneTo, DockAlignment.Right, 0.5);
else if (DockOutline.Dock == DockStyle.Top)
pane.AddToDockList(container, paneTo, DockAlignment.Top, 0.5);
else if (DockOutline.Dock == DockStyle.Bottom)
pane.AddToDockList(container, paneTo, DockAlignment.Bottom, 0.5);
pane.DockState = paneTo.DockState;
pane.Activate();
}
}
else if (DockOutline.DockTo is DockContainer)
{
DockPane pane;
DockContainer dockPanel = content.DockHandler.DockPanel;
SetDockWindow();
if (DockOutline.Dock == DockStyle.Top)
pane = dockPanel.DockPaneFactory.CreateDockPane(content, DockState.DockTop, true);
else if (DockOutline.Dock == DockStyle.Bottom)
pane = dockPanel.DockPaneFactory.CreateDockPane(content, DockState.DockBottom, true);
else if (DockOutline.Dock == DockStyle.Left)
pane = dockPanel.DockPaneFactory.CreateDockPane(content, DockState.DockLeft, true);
else if (DockOutline.Dock == DockStyle.Right)
pane = dockPanel.DockPaneFactory.CreateDockPane(content, DockState.DockRight, true);
else if (DockOutline.Dock == DockStyle.Fill)
pane = dockPanel.DockPaneFactory.CreateDockPane(content, DockState.Document, true);
else
return;
pane.Activate();
}
}
private void Pane_BeginDrag()
{
Point pt = new Point(0, 0);
pt = DragControl.PointToScreen(pt);
m_mouseOffset.X = pt.X - StartMousePosition.X;
m_mouseOffset.Y = pt.Y - StartMousePosition.Y;
}
private void Pane_OnEndDrag(bool abort)
{
User32.SetCursor(DragControl.Cursor.Handle);
if (abort)
return;
DockPane pane = (DockPane)DragControl;
if (!DockOutline.FloatWindowBounds.IsEmpty)
{
if (pane.FloatWindow == null || pane.FloatWindow.DockList.Count != 1)
pane.FloatWindow = pane.DockPanel.FloatWindowFactory.CreateFloatWindow(pane.DockPanel, pane, DockOutline.FloatWindowBounds);
else
pane.FloatWindow.Bounds = DockOutline.FloatWindowBounds;
pane.DockState = DockState.Float;
pane.Activate();
}
else if (DockOutline.DockTo is DockPane)
{
DockPane paneTo = DockOutline.DockTo as DockPane;
if (DockOutline.Dock == DockStyle.Fill)
{
for (int i=pane.Contents.Count - 1; i>=0; i--)
{
IDockableWindow c = pane.Contents[i];
c.DockHandler.Pane = paneTo;
if (DockOutline.ContentIndex != -1)
paneTo.SetContentIndex(c, DockOutline.ContentIndex);
c.DockHandler.Activate();
}
}
else
{
if (DockOutline.Dock == DockStyle.Left)
pane.AddToDockList(paneTo.DockListContainer, paneTo, DockAlignment.Left, 0.5);
else if (DockOutline.Dock == DockStyle.Right)
pane.AddToDockList(paneTo.DockListContainer, paneTo, DockAlignment.Right, 0.5);
else if (DockOutline.Dock == DockStyle.Top)
pane.AddToDockList(paneTo.DockListContainer, paneTo, DockAlignment.Top, 0.5);
else if (DockOutline.Dock == DockStyle.Bottom)
pane.AddToDockList(paneTo.DockListContainer, paneTo, DockAlignment.Bottom, 0.5);
pane.DockState = paneTo.DockState;
pane.Activate();
}
}
else if (DockOutline.DockTo is DockContainer)
{
SetDockWindow();
if (DockOutline.Dock == DockStyle.Top)
pane.DockState = DockState.DockTop;
else if (DockOutline.Dock == DockStyle.Bottom)
pane.DockState = DockState.DockBottom;
else if (DockOutline.Dock == DockStyle.Left)
pane.DockState = DockState.DockLeft;
else if (DockOutline.Dock == DockStyle.Right)
pane.DockState = DockState.DockRight;
else if (DockOutline.Dock == DockStyle.Fill)
pane.DockState = DockState.Document;
pane.Activate();
}
}
private void DockWindowSplitter_BeginDrag(Point ptSplitter)
{
m_splitterLocation = DragControl.PointToScreen(ptSplitter);
Point ptMouse = StartMousePosition;
m_mouseOffset.X = m_splitterLocation.X - ptMouse.X;
m_mouseOffset.Y = m_splitterLocation.Y - ptMouse.Y;
Rectangle rect = GetWindowSplitterDragRectangle();
SplitterOutline.Show(rect);
}
private void DockWindowSplitter_OnEndDrag(bool abort)
{
if (abort)
return;
DockWindow dockWindow = DragControl as DockWindow;
if (dockWindow == null)
return;
DockContainer dockPanel = dockWindow.DockPanel;
DockState state = dockWindow.DockState;
if ((Control.ModifierKeys & Keys.Shift) != 0)
dockWindow.SendToBack();
Point pt = m_splitterLocation;
Rectangle rect = GetWindowSplitterDragRectangle();
Rectangle rectDockArea = dockPanel.DockArea;
if (state == DockState.DockLeft && rectDockArea.Width > 0)
dockPanel.DockLeftPortion += ((double)rect.X - (double)pt.X) / (double)rectDockArea.Width;
else if (state == DockState.DockRight && rectDockArea.Width > 0)
dockPanel.DockRightPortion += ((double)pt.X - (double)rect.X) / (double)rectDockArea.Width;
else if (state == DockState.DockBottom && rectDockArea.Height > 0)
dockPanel.DockBottomPortion += ((double)pt.Y - (double)rect.Y) / (double)rectDockArea.Height;
else if (state == DockState.DockTop && rectDockArea.Height > 0)
dockPanel.DockTopPortion += ((double)rect.Y - (double)pt.Y) / (double)rectDockArea.Height;
}
private void AutoHideWindowSplitter_BeginDrag(Point ptSplitter)
{
m_splitterLocation = DragControl.PointToScreen(ptSplitter);
Point ptMouse = StartMousePosition;
m_mouseOffset.X = m_splitterLocation.X - ptMouse.X;
m_mouseOffset.Y = m_splitterLocation.Y - ptMouse.Y;
Rectangle rect = GetWindowSplitterDragRectangle();
SplitterOutline.Show(rect);
}
private void AutoHideWindowSplitter_OnEndDrag(bool abort)
{
AutoHideWindow autoHideWindow = DragControl as AutoHideWindow;
if (autoHideWindow == null || abort)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -