//Copyright (c) 2007-2009, Adolfo Marinucci
//All rights reserved.
//Redistribution and use in source and binary forms, with or without modification,
//are permitted provided that the following conditions are met:
//
//* Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//* Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//* Neither the name of Adolfo Marinucci nor the names of its contributors may
// be used to endorse or promote products derived from this software without
// specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
//AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
//IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
//HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
//OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
//EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Windows.Markup;
using System.Diagnostics;
using System.Windows.Threading;
using System.Windows.Media.Animation;
namespace AvalonDock
{
public enum OverlayButtonHover
{
None,
DropPaneInto,
DropPaneLeft,
DropPaneRight,
DropPaneTop,
DropPaneBottom,
DropBorderLeft,
DropBorderRight,
DropBorderTop,
DropBorderBottom,
}
public class OverlayWindow : Window, INotifyPropertyChanged
{
static OverlayWindow()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(OverlayWindow), new FrameworkPropertyMetadata(typeof(OverlayWindow)));
Window.AllowsTransparencyProperty.OverrideMetadata(typeof(OverlayWindow), new FrameworkPropertyMetadata(true));
Window.WindowStyleProperty.OverrideMetadata(typeof(OverlayWindow), new FrameworkPropertyMetadata(WindowStyle.None));
Window.ShowInTaskbarProperty.OverrideMetadata(typeof(OverlayWindow), new FrameworkPropertyMetadata(false));
}
public OverlayWindow()
{ }
DockingManager _manager = null;
public OverlayWindow(DockingManager manager)
{
_manager = manager;
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
gridPaneRelativeDockingOptions = GetTemplateChild("PART_gridPaneRelativeDockingOptions") as FrameworkElement;
selectionBox = GetTemplateChild("PART_SelectionBox") as FrameworkElement;
owdBottom = new OverlayWindowDockingButton(GetTemplateChild("PART_btnDockBottom") as FrameworkElement, this);
owdTop = new OverlayWindowDockingButton(GetTemplateChild("PART_btnDockTop") as FrameworkElement, this);
owdLeft = new OverlayWindowDockingButton(GetTemplateChild("PART_btnDockLeft") as FrameworkElement, this);
owdRight = new OverlayWindowDockingButton(GetTemplateChild("PART_btnDockRight") as FrameworkElement, this);
owdPaneBottom = new OverlayWindowDockingButton(GetTemplateChild("PART_btnDockPaneBottom") as FrameworkElement, this);
owdPaneTop = new OverlayWindowDockingButton(GetTemplateChild("PART_btnDockPaneTop") as FrameworkElement, this);
owdPaneLeft = new OverlayWindowDockingButton(GetTemplateChild("PART_btnDockPaneLeft") as FrameworkElement, this);
owdPaneRight = new OverlayWindowDockingButton(GetTemplateChild("PART_btnDockPaneRight") as FrameworkElement, this);
owdPaneInto = new OverlayWindowDockingButton(GetTemplateChild("PART_btnDockPaneInto") as FrameworkElement, this);
_manager.DragPaneServices.Register(owdBottom);
_manager.DragPaneServices.Register(owdTop);
_manager.DragPaneServices.Register(owdLeft);
_manager.DragPaneServices.Register(owdRight);
_manager.DragPaneServices.Register(owdPaneBottom);
_manager.DragPaneServices.Register(owdPaneTop);
_manager.DragPaneServices.Register(owdPaneLeft);
_manager.DragPaneServices.Register(owdPaneRight);
_manager.DragPaneServices.Register(owdPaneInto);
}
FrameworkElement gridPaneRelativeDockingOptions;
FrameworkElement selectionBox;
OverlayWindowDockingButton owdBottom;
OverlayWindowDockingButton owdTop;
OverlayWindowDockingButton owdLeft;
OverlayWindowDockingButton owdRight;
OverlayWindowDockingButton owdPaneBottom;
OverlayWindowDockingButton owdPaneTop;
OverlayWindowDockingButton owdPaneLeft;
OverlayWindowDockingButton owdPaneRight;
OverlayWindowDockingButton owdPaneInto;
internal bool OnDrop(OverlayWindowDockingButton owdDock, Point point)
{
//user has dropped the floating window over a anchor button
//create a new dockable pane to insert in the main layout
Pane paneToAnchor = _manager.DragPaneServices.FloatingWindow.ClonePane();
//floating window is going to be closed..
if (owdDock == owdBottom)
_manager.Anchor(paneToAnchor, AnchorStyle.Bottom);
else if (owdDock == owdLeft)
_manager.Anchor(paneToAnchor, AnchorStyle.Left);
else if (owdDock == owdRight)
_manager.Anchor(paneToAnchor, AnchorStyle.Right);
else if (owdDock == owdTop)
_manager.Anchor(paneToAnchor, AnchorStyle.Top);
else if (owdDock == owdPaneTop)
_manager.Anchor(paneToAnchor, CurrentDropPane, AnchorStyle.Top);
else if (owdDock == owdPaneBottom)
_manager.Anchor(paneToAnchor, CurrentDropPane, AnchorStyle.Bottom);
else if (owdDock == owdPaneLeft)
_manager.Anchor(paneToAnchor, CurrentDropPane, AnchorStyle.Left);
else if (owdDock == owdPaneRight)
_manager.Anchor(paneToAnchor, CurrentDropPane, AnchorStyle.Right);
else if (owdDock == owdPaneInto)
_manager.DropInto(paneToAnchor, CurrentDropPane);
selectionBox.Visibility = Visibility.Hidden;
return true;
}
Pane CurrentDropPane = null;
public void ShowOverlayPaneDockingOptions(Pane pane)
{
if (!IsVisible)
return;
HideOverlayPaneDockingOptions(pane);
//check if dockable on a document pane
DockableStyle currentPaneDockableStyle =
_manager.DragPaneServices.FloatingWindow.HostedPane.GetCumulativeDockableStyle();
//if current drop pane is a DocumentPane ...
if (pane is DocumentPane &&
(currentPaneDockableStyle & DockableStyle.Document) == 0)
return;
if (pane is DockablePane &&
(currentPaneDockableStyle & DockableStyle.Dockable) == 0)
return;
Rect rectPane = pane.SurfaceRectangle;
Point myScreenTopLeft = this.PointToScreenDPI(new Point(0, 0));
rectPane.Offset(-myScreenTopLeft.X, -myScreenTopLeft.Y);//relative to me
gridPaneRelativeDockingOptions.SetValue(Canvas.LeftProperty, rectPane.Left + rectPane.Width / 2 - gridPaneRelativeDockingOptions.Width / 2);
gridPaneRelativeDockingOptions.SetValue(Canvas.TopProperty, rectPane.Top + rectPane.Height / 2 - gridPaneRelativeDockingOptions.Height / 2);
if (pane is DocumentPane)
gridPaneRelativeDockingOptions.Visibility = Visibility.Visible;
else
{
gridPaneRelativeDockingOptions.Visibility = !(_manager.DragPaneServices.FloatingWindow is DocumentFloatingWindow) ? Visibility.Visible : Visibility.Hidden;
}
owdBottom.Enabled = ((currentPaneDockableStyle & DockableStyle.BottomBorder) > 0);
owdTop.Enabled = ((currentPaneDockableStyle & DockableStyle.TopBorder) > 0);
owdLeft.Enabled = ((currentPaneDockableStyle & DockableStyle.LeftBorder) > 0);
owdRight.Enabled = ((currentPaneDockableStyle & DockableStyle.RightBorder) > 0);
if (pane is DocumentPane)
owdPaneInto.Enabled = true;
else
owdPaneInto.Enabled = !(_manager.DragPaneServices.FloatingWindow is DocumentFloatingWindow);
int destPaneChildCount = pane.Items.Count;
owdPaneBottom.Enabled = owdPaneInto.Enabled && destPaneChildCount > 0;
owdPaneTop.Enabled = owdPaneInto.Enabled && destPaneChildCount > 0;
owdPaneLeft.Enabled = owdPaneInto.Enabled && destPaneChildCount > 0;
owdPaneRight.Enabled = owdPaneInto.Enabled && destPaneChildCount > 0;
CurrentDropPane = pane;
}
public void HideOverlayPaneDockingOptions(Pane surfaceElement)
{
if (!IsVisible)
return;
owdPaneBottom.Enabled = false;
owdPaneTop.Enabled = false;
owdPaneLeft.Enabled = false;
owdPaneRight.Enabled = false;
owdPaneInto.Enabled = false;
gridPaneRelativeDockingOptions.Visibility = Visibility.Collapsed;
CurrentDropPane = null;
OverlayButtonHover = OverlayButtonHover.None;
}
protected override void OnDeactivated(EventArgs e)
{
selectionBox.Visibility = Visibility.Hidden;
base.OnDeactivated(e);
}
protected override void OnActivated(EventArgs e)
{
base.OnActivated(e);
DockableStyle currentPaneDockableStyle =
_manager.DragPaneServices.FloatingWindow.HostedPane.GetCumulativeDockableStyle();
selectionBox.Visibility = Visibility.Hidden;
owdBottom.Enabled = (currentPaneDockableStyle & DockableStyle.BottomBorder) > 0;
owdTop.Enabled = (currentPaneDockableStyle & DockableStyle.TopBorder) > 0;
owdLeft.Enabled = (currentPaneDockableStyle & DockableStyle.LeftBorder) > 0;
owdRight.Enabled = (currentPaneDockableStyle & DockableStyle.RightBorder) > 0;
}
///
/// Shows a highlighting rectangle
///
///
///
///
internal void OnDragEnter(OverlayWindowDockingButton owdDock, Point point)
{
OnDragOver(owdDock, point);
}
///
/// Hides the highlighting rectangle
///
///
///
///
internal void OnDragLeave(OverlayWindowDockingButton owdDock, Point point)
{
selectionBox.Visibility = Visibility.Hidden;
_manager.DragPaneServices.FloatingWindow.OnHideSelectionBox();
OverlayButtonHover = OverlayButtonHover.None;
}
internal void OnDragOver(OverlayWindowDockingButton owdDock, Point point)
{
if (selectionBox == null)
return;
Rect rectPane;
if (owdDock == owdBottom ||
owdDock == owdLeft ||
owdDock == owdTop ||
owdDock == owdRight)
rectPane = _manager.SurfaceRectangle;
else
rectPane = CurrentDropPane.SurfaceRectangle;
double selectionBoxWidth = Math.Min(
rectPane.Width / 2.0,
ResizingPanel.GetEffectiveSize(_manager.DragPaneServices.FloatingWindow.HostedPane).Width);
double selectionBoxHeight = Math.Min(
rectPane.Height / 2.0,
ResizingPanel.GetEffectiveSize(_manager.DragPaneServices.FloatingWindow.HostedPane).Height);
Point myScreenTopLeft = this.PointToScreenDPI(new Point());
rectPane.Offset(-myScreenTopLeft.X, -myScreenTopLeft.Y);//relative to me
if (owdDock == owdBottom || owdDock == owdPaneBottom)
{
selectionBox.SetValue(Canvas.LeftProperty, rectPane.Left);
selectionBox.SetValue(Canvas.TopProperty, rectPane.Top + rectPane.Height - selectionBoxHeight);
selectionBox.Width = rectPane.Width;
selectionBox.Height = selectionBoxHeight;
}
if (owdDock == owdLeft || owdDock == owdPaneLeft)
{
selectionBox.SetValue(Canvas.LeftProperty, rectPane.Left);
selectionBox.SetValue(Canvas.TopProperty, rectPane.Top);
selectionBox.Width = selectionBoxWidth;
selectionBox.Height = rectPane.Height;
}
if (owdDock == owdRight || owdDock == owdPaneRight)
{
selectionBox.SetValue(Canvas.LeftProperty, rectPane.Left + rectPane.Width - selectionBoxWidth);
selectionBox.SetValue(Canvas.TopProperty, rectPane.Top);
selectionBox.Width = selectionBoxWidth;
selectionBox.Height = rectPane.Height;
}
if (owdDock == owdTop || owdDock == owdPaneTop)
{
selectionBox.SetValue(Canvas.LeftProperty, rectPane.Left);
selectionBox.SetValue(Canvas.TopProperty, rectPane.Top);
selectionBox.Width = rectPane.Width;
selectionBox.Height = selectionBoxHeight;
}
if (owdDock == owdPaneInto)
{
selectionBox.SetValue(Canvas.LeftProperty, rectPane.Left);
selectionBox.SetValue(Canvas.TopProperty, rectPane.Top);
selectionBox.Width = rectPane.Width;
selectionBox.Height = rectPane.Height;
}
if (owdDock == owdLeft)
OverlayButtonHover = OverlayButtonHover.DropBorderLeft;
else if (owdDock == owdRight)
OverlayButtonHover = OverlayButtonHover.DropBorderRight;
else if (owdDock == owdTop)
OverlayButtonHover = OverlayButtonHover.DropBorderTop;
else if (owdDock == owdBottom)
OverlayButtonHover = OverlayButtonHover.DropBorderBottom;
else if (owdDock == owdPaneInto)
OverlayButtonHover = OverlayButtonHover.DropPaneInto;
else if (owdDock == owdPaneRight)
OverlayButtonHover = OverlayButtonHover.DropPaneRight;
else if (owdDock == owdPaneTop)
OverlayButtonHover = OverlayButtonHover.DropPaneTop;
else if (owdDock == owdPaneLeft)
OverlayButtonHover = OverlayButtonHover.DropPaneLeft;
else if (owdDock == owdPaneBottom)
OverlayButtonHover = OverlayButtonHover.DropPaneBottom;
else
OverlayButtonHover = OverlayButtonHover.None;
selectionBox.Visibility = Visibility.Visible;
_manager.DragPaneServices.FloatingWindow.OnShowSelectionBox();
}
OverlayButtonHover _overlayButtonHover = OverlayButtonHover.None;
public OverlayButtonHover OverlayButtonHover
{
get
{ return _overlayButtonHover; }
set
{
_overlayButtonHover = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("OverlayButtonHover"));
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
}