You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
552 lines
22 KiB
552 lines
22 KiB
/*************************************************************************************
|
|
|
|
Extended WPF Toolkit
|
|
|
|
Copyright (C) 2007-2013 Xceed Software Inc.
|
|
|
|
This program is provided to you under the terms of the Microsoft Public
|
|
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
|
|
|
|
For more features, controls, and fast professional support,
|
|
pick up the Plus Edition at http://xceed.com/wpf_toolkit
|
|
|
|
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
|
|
|
|
***********************************************************************************/
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Windows.Interop;
|
|
using System.Windows.Controls;
|
|
using System.Runtime.InteropServices;
|
|
using System.Windows;
|
|
using System.Windows.Input;
|
|
using System.Windows.Data;
|
|
using System.Windows.Media;
|
|
using Xceed.Wpf.AvalonDock.Layout;
|
|
using System.Diagnostics;
|
|
using System.Windows.Threading;
|
|
|
|
namespace Xceed.Wpf.AvalonDock.Controls
|
|
{
|
|
public class LayoutAutoHideWindowControl : HwndHost, ILayoutControl
|
|
{
|
|
static LayoutAutoHideWindowControl()
|
|
{
|
|
DefaultStyleKeyProperty.OverrideMetadata(typeof(LayoutAutoHideWindowControl), new FrameworkPropertyMetadata(typeof(LayoutAutoHideWindowControl)));
|
|
UIElement.FocusableProperty.OverrideMetadata(typeof(LayoutAutoHideWindowControl), new FrameworkPropertyMetadata(true));
|
|
Control.IsTabStopProperty.OverrideMetadata(typeof(LayoutAutoHideWindowControl), new FrameworkPropertyMetadata(true));
|
|
VisibilityProperty.OverrideMetadata(typeof(LayoutAutoHideWindowControl), new FrameworkPropertyMetadata(Visibility.Hidden));
|
|
}
|
|
|
|
internal LayoutAutoHideWindowControl()
|
|
{
|
|
}
|
|
|
|
internal void Show(LayoutAnchorControl anchor)
|
|
{
|
|
if (_model != null)
|
|
throw new InvalidOperationException();
|
|
|
|
_anchor = anchor;
|
|
_model = anchor.Model as LayoutAnchorable;
|
|
_side = (anchor.Model.Parent.Parent as LayoutAnchorSide).Side;
|
|
_manager = _model.Root.Manager;
|
|
CreateInternalGrid();
|
|
|
|
_model.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(_model_PropertyChanged);
|
|
|
|
Visibility = System.Windows.Visibility.Visible;
|
|
InvalidateMeasure();
|
|
UpdateWindowPos();
|
|
}
|
|
|
|
internal void Hide()
|
|
{
|
|
if (_model == null)
|
|
return;
|
|
|
|
_model.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler(_model_PropertyChanged);
|
|
|
|
RemoveInternalGrid();
|
|
_anchor = null;
|
|
_model = null;
|
|
_manager = null;
|
|
Visibility = System.Windows.Visibility.Hidden;
|
|
}
|
|
|
|
LayoutAnchorControl _anchor;
|
|
|
|
LayoutAnchorable _model;
|
|
|
|
public ILayoutElement Model
|
|
{
|
|
get { return _model; }
|
|
}
|
|
|
|
HwndSource _internalHwndSource = null;
|
|
IntPtr parentWindowHandle;
|
|
protected override System.Runtime.InteropServices.HandleRef BuildWindowCore(System.Runtime.InteropServices.HandleRef hwndParent)
|
|
{
|
|
parentWindowHandle = hwndParent.Handle;
|
|
_internalHwndSource = new HwndSource(new HwndSourceParameters()
|
|
{
|
|
ParentWindow = hwndParent.Handle,
|
|
WindowStyle = Win32Helper.WS_CHILD | Win32Helper.WS_VISIBLE | Win32Helper.WS_CLIPSIBLINGS | Win32Helper.WS_CLIPCHILDREN,
|
|
Width = 0,
|
|
Height = 0,
|
|
});
|
|
|
|
//_internalHost_ContentRendered = false;
|
|
_internalHwndSource.ContentRendered += _internalHwndSource_ContentRendered;
|
|
_internalHwndSource.RootVisual = _internalHostPresenter;
|
|
AddLogicalChild(_internalHostPresenter);
|
|
Win32Helper.BringWindowToTop(_internalHwndSource.Handle);
|
|
return new HandleRef(this, _internalHwndSource.Handle);
|
|
}
|
|
|
|
// private bool _internalHost_ContentRendered = false;
|
|
|
|
void _internalHwndSource_ContentRendered(object sender, EventArgs e)
|
|
{
|
|
// _internalHost_ContentRendered = true;
|
|
}
|
|
|
|
|
|
//protected override IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
|
|
//{
|
|
// if (msg == Win32Helper.WM_WINDOWPOSCHANGING)
|
|
// {
|
|
// if (_internalHost_ContentRendered)
|
|
// Win32Helper.SetWindowPos(_internalHwndSource.Handle, Win32Helper.HWND_TOP, 0, 0, 0, 0, Win32Helper.SetWindowPosFlags.IgnoreMove | Win32Helper.SetWindowPosFlags.IgnoreResize);
|
|
// }
|
|
// return base.WndProc(hwnd, msg, wParam, lParam, ref handled);
|
|
//}
|
|
|
|
protected override void DestroyWindowCore(System.Runtime.InteropServices.HandleRef hwnd)
|
|
{
|
|
if (_internalHwndSource != null)
|
|
{
|
|
_internalHwndSource.ContentRendered -= _internalHwndSource_ContentRendered;
|
|
_internalHwndSource.Dispose();
|
|
_internalHwndSource = null;
|
|
}
|
|
}
|
|
|
|
public override void OnApplyTemplate()
|
|
{
|
|
base.OnApplyTemplate();
|
|
|
|
|
|
}
|
|
|
|
ContentPresenter _internalHostPresenter = new ContentPresenter();
|
|
Grid _internalGrid = null;
|
|
LayoutAnchorableControl _internalHost = null;
|
|
AnchorSide _side;
|
|
LayoutGridResizerControl _resizer = null;
|
|
DockingManager _manager;
|
|
|
|
void _model_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
|
{
|
|
if (e.PropertyName == "IsAutoHidden")
|
|
{
|
|
if (!_model.IsAutoHidden)
|
|
{
|
|
_manager.HideAutoHideWindow(_anchor);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CreateInternalGrid()
|
|
{
|
|
_internalGrid = new Grid() { FlowDirection = System.Windows.FlowDirection.LeftToRight};
|
|
_internalGrid.SetBinding(Grid.BackgroundProperty, new Binding("Background") { Source = this });
|
|
|
|
|
|
_internalHost = new LayoutAnchorableControl() { Model = _model, Style = AnchorableStyle };
|
|
_internalHost.SetBinding(FlowDirectionProperty, new Binding("Model.Root.Manager.FlowDirection") { Source = this });
|
|
|
|
KeyboardNavigation.SetTabNavigation(_internalGrid, KeyboardNavigationMode.Cycle);
|
|
|
|
_resizer = new LayoutGridResizerControl();
|
|
|
|
_resizer.DragStarted += new System.Windows.Controls.Primitives.DragStartedEventHandler(OnResizerDragStarted);
|
|
_resizer.DragDelta += new System.Windows.Controls.Primitives.DragDeltaEventHandler(OnResizerDragDelta);
|
|
_resizer.DragCompleted += new System.Windows.Controls.Primitives.DragCompletedEventHandler(OnResizerDragCompleted);
|
|
|
|
if (_side == AnchorSide.Right)
|
|
{
|
|
_internalGrid.ColumnDefinitions.Add(new ColumnDefinition(){ Width = new GridLength(_manager.GridSplitterWidth)});
|
|
_internalGrid.ColumnDefinitions.Add(new ColumnDefinition(){
|
|
Width = _model.AutoHideWidth == 0.0 ? new GridLength(_model.AutoHideMinWidth) : new GridLength(_model.AutoHideWidth, GridUnitType.Pixel)});
|
|
|
|
Grid.SetColumn(_resizer, 0);
|
|
Grid.SetColumn(_internalHost, 1);
|
|
|
|
_resizer.Cursor = Cursors.SizeWE;
|
|
|
|
HorizontalAlignment = System.Windows.HorizontalAlignment.Right;
|
|
VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
|
|
}
|
|
else if (_side == AnchorSide.Left)
|
|
{
|
|
_internalGrid.ColumnDefinitions.Add(new ColumnDefinition()
|
|
{
|
|
Width = _model.AutoHideWidth == 0.0 ? new GridLength(_model.AutoHideMinWidth) : new GridLength(_model.AutoHideWidth, GridUnitType.Pixel),
|
|
});
|
|
_internalGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(_manager.GridSplitterWidth) });
|
|
|
|
Grid.SetColumn(_internalHost, 0);
|
|
Grid.SetColumn(_resizer, 1);
|
|
|
|
_resizer.Cursor = Cursors.SizeWE;
|
|
|
|
HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
|
|
VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
|
|
}
|
|
else if (_side == AnchorSide.Top)
|
|
{
|
|
_internalGrid.RowDefinitions.Add(new RowDefinition()
|
|
{
|
|
Height = _model.AutoHideHeight == 0.0 ? new GridLength(_model.AutoHideMinHeight) : new GridLength(_model.AutoHideHeight, GridUnitType.Pixel),
|
|
});
|
|
_internalGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(_manager.GridSplitterHeight) });
|
|
|
|
Grid.SetRow(_internalHost, 0);
|
|
Grid.SetRow(_resizer, 1);
|
|
|
|
_resizer.Cursor = Cursors.SizeNS;
|
|
|
|
VerticalAlignment = System.Windows.VerticalAlignment.Top;
|
|
HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
|
|
|
|
}
|
|
else if (_side == AnchorSide.Bottom)
|
|
{
|
|
_internalGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(_manager.GridSplitterHeight) });
|
|
_internalGrid.RowDefinitions.Add(new RowDefinition()
|
|
{
|
|
Height = _model.AutoHideHeight == 0.0 ? new GridLength(_model.AutoHideMinHeight) : new GridLength(_model.AutoHideHeight, GridUnitType.Pixel),
|
|
});
|
|
|
|
Grid.SetRow(_resizer, 0);
|
|
Grid.SetRow(_internalHost, 1);
|
|
|
|
_resizer.Cursor = Cursors.SizeNS;
|
|
|
|
VerticalAlignment = System.Windows.VerticalAlignment.Bottom;
|
|
HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
|
|
}
|
|
|
|
|
|
_internalGrid.Children.Add(_resizer);
|
|
_internalGrid.Children.Add(_internalHost);
|
|
_internalHostPresenter.Content = _internalGrid;
|
|
}
|
|
|
|
void RemoveInternalGrid()
|
|
{
|
|
_resizer.DragStarted -= new System.Windows.Controls.Primitives.DragStartedEventHandler(OnResizerDragStarted);
|
|
_resizer.DragDelta -= new System.Windows.Controls.Primitives.DragDeltaEventHandler(OnResizerDragDelta);
|
|
_resizer.DragCompleted -= new System.Windows.Controls.Primitives.DragCompletedEventHandler(OnResizerDragCompleted);
|
|
|
|
_internalHostPresenter.Content = null;
|
|
}
|
|
|
|
|
|
protected override bool HasFocusWithinCore()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
#region Resizer
|
|
|
|
Border _resizerGhost = null;
|
|
Window _resizerWindowHost = null;
|
|
Vector _initialStartPoint;
|
|
|
|
void ShowResizerOverlayWindow(LayoutGridResizerControl splitter)
|
|
{
|
|
_resizerGhost = new Border()
|
|
{
|
|
Background = splitter.BackgroundWhileDragging,
|
|
Opacity = splitter.OpacityWhileDragging
|
|
};
|
|
|
|
var areaElement = _manager.GetAutoHideAreaElement();
|
|
var modelControlActualSize = this._internalHost.TransformActualSizeToAncestor();
|
|
|
|
Point ptTopLeftScreen = areaElement.PointToScreenDPIWithoutFlowDirection(new Point());
|
|
|
|
var managerSize = areaElement.TransformActualSizeToAncestor();
|
|
|
|
Size windowSize;
|
|
|
|
if (_side == AnchorSide.Right || _side == AnchorSide.Left)
|
|
{
|
|
windowSize = new Size(
|
|
managerSize.Width - 25.0 + splitter.ActualWidth,
|
|
managerSize.Height);
|
|
|
|
_resizerGhost.Width = splitter.ActualWidth;
|
|
_resizerGhost.Height = windowSize.Height;
|
|
ptTopLeftScreen.Offset(25, 0.0);
|
|
}
|
|
else
|
|
{
|
|
windowSize = new Size(
|
|
managerSize.Width,
|
|
managerSize.Height - _model.AutoHideMinHeight - 25.0 + splitter.ActualHeight);
|
|
|
|
_resizerGhost.Height = splitter.ActualHeight;
|
|
_resizerGhost.Width = windowSize.Width;
|
|
ptTopLeftScreen.Offset(0.0, 25.0);
|
|
}
|
|
|
|
_initialStartPoint = splitter.PointToScreenDPIWithoutFlowDirection(new Point()) - ptTopLeftScreen;
|
|
|
|
if (_side == AnchorSide.Right || _side == AnchorSide.Left)
|
|
{
|
|
Canvas.SetLeft(_resizerGhost, _initialStartPoint.X);
|
|
}
|
|
else
|
|
{
|
|
Canvas.SetTop(_resizerGhost, _initialStartPoint.Y);
|
|
}
|
|
|
|
Canvas panelHostResizer = new Canvas()
|
|
{
|
|
HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch,
|
|
VerticalAlignment = System.Windows.VerticalAlignment.Stretch
|
|
};
|
|
|
|
panelHostResizer.Children.Add(_resizerGhost);
|
|
|
|
|
|
_resizerWindowHost = new Window()
|
|
{
|
|
ResizeMode = ResizeMode.NoResize,
|
|
WindowStyle = System.Windows.WindowStyle.None,
|
|
ShowInTaskbar = false,
|
|
AllowsTransparency = true,
|
|
Background = null,
|
|
Width = windowSize.Width,
|
|
Height = windowSize.Height,
|
|
Left = ptTopLeftScreen.X,
|
|
Top = ptTopLeftScreen.Y,
|
|
ShowActivated = false,
|
|
Owner = Window.GetWindow(this),
|
|
Content = panelHostResizer
|
|
};
|
|
|
|
_resizerWindowHost.Show();
|
|
}
|
|
|
|
void HideResizerOverlayWindow()
|
|
{
|
|
if (_resizerWindowHost != null)
|
|
{
|
|
_resizerWindowHost.Close();
|
|
_resizerWindowHost = null;
|
|
}
|
|
}
|
|
|
|
internal bool IsResizing
|
|
{
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
void OnResizerDragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
|
|
{
|
|
LayoutGridResizerControl splitter = sender as LayoutGridResizerControl;
|
|
var rootVisual = this.FindVisualTreeRoot() as Visual;
|
|
|
|
var trToWnd = TransformToAncestor(rootVisual);
|
|
Vector transformedDelta = trToWnd.Transform(new Point(e.HorizontalChange, e.VerticalChange)) -
|
|
trToWnd.Transform(new Point());
|
|
|
|
double delta;
|
|
if (_side == AnchorSide.Right || _side == AnchorSide.Left)
|
|
delta = Canvas.GetLeft(_resizerGhost) - _initialStartPoint.X;
|
|
else
|
|
delta = Canvas.GetTop(_resizerGhost) - _initialStartPoint.Y;
|
|
|
|
if (_side == AnchorSide.Right)
|
|
{
|
|
if (_model.AutoHideWidth == 0.0)
|
|
_model.AutoHideWidth = _internalHost.ActualWidth - delta;
|
|
else
|
|
_model.AutoHideWidth -= delta;
|
|
|
|
_internalGrid.ColumnDefinitions[1].Width = new GridLength(_model.AutoHideWidth, GridUnitType.Pixel);
|
|
}
|
|
else if (_side == AnchorSide.Left)
|
|
{
|
|
if (_model.AutoHideWidth == 0.0)
|
|
_model.AutoHideWidth = _internalHost.ActualWidth + delta;
|
|
else
|
|
_model.AutoHideWidth += delta;
|
|
|
|
_internalGrid.ColumnDefinitions[0].Width = new GridLength(_model.AutoHideWidth, GridUnitType.Pixel);
|
|
}
|
|
else if (_side == AnchorSide.Top)
|
|
{
|
|
if (_model.AutoHideHeight == 0.0)
|
|
_model.AutoHideHeight = _internalHost.ActualHeight + delta;
|
|
else
|
|
_model.AutoHideHeight += delta;
|
|
|
|
_internalGrid.RowDefinitions[0].Height = new GridLength(_model.AutoHideHeight, GridUnitType.Pixel);
|
|
}
|
|
else if (_side == AnchorSide.Bottom)
|
|
{
|
|
if (_model.AutoHideHeight == 0.0)
|
|
_model.AutoHideHeight = _internalHost.ActualHeight - delta;
|
|
else
|
|
_model.AutoHideHeight -= delta;
|
|
|
|
_internalGrid.RowDefinitions[1].Height = new GridLength(_model.AutoHideHeight, GridUnitType.Pixel);
|
|
}
|
|
|
|
HideResizerOverlayWindow();
|
|
|
|
IsResizing = false;
|
|
InvalidateMeasure();
|
|
}
|
|
|
|
void OnResizerDragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
|
|
{
|
|
LayoutGridResizerControl splitter = sender as LayoutGridResizerControl;
|
|
var rootVisual = this.FindVisualTreeRoot() as Visual;
|
|
|
|
var trToWnd = TransformToAncestor(rootVisual);
|
|
Vector transformedDelta = trToWnd.Transform(new Point(e.HorizontalChange, e.VerticalChange)) -
|
|
trToWnd.Transform(new Point());
|
|
|
|
if (_side == AnchorSide.Right || _side == AnchorSide.Left)
|
|
{
|
|
if (FrameworkElement.GetFlowDirection(_internalHost) == System.Windows.FlowDirection.RightToLeft)
|
|
transformedDelta.X = -transformedDelta.X;
|
|
Canvas.SetLeft(_resizerGhost, MathHelper.MinMax(_initialStartPoint.X + transformedDelta.X, 0.0, _resizerWindowHost.Width - _resizerGhost.Width));
|
|
}
|
|
else
|
|
{
|
|
Canvas.SetTop(_resizerGhost, MathHelper.MinMax(_initialStartPoint.Y + transformedDelta.Y, 0.0, _resizerWindowHost.Height - _resizerGhost.Height));
|
|
}
|
|
}
|
|
|
|
void OnResizerDragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e)
|
|
{
|
|
var resizer = sender as LayoutGridResizerControl;
|
|
ShowResizerOverlayWindow(resizer);
|
|
IsResizing = true;
|
|
}
|
|
#endregion
|
|
|
|
protected override System.Collections.IEnumerator LogicalChildren
|
|
{
|
|
get
|
|
{
|
|
if (_internalHostPresenter == null)
|
|
return new UIElement[] { }.GetEnumerator();
|
|
return new UIElement[] { _internalHostPresenter }.GetEnumerator();
|
|
}
|
|
}
|
|
|
|
protected override Size MeasureOverride(Size constraint)
|
|
{
|
|
if (_internalHostPresenter == null)
|
|
return base.MeasureOverride(constraint);
|
|
|
|
_internalHostPresenter.Measure(constraint);
|
|
//return base.MeasureOverride(constraint);
|
|
return _internalHostPresenter.DesiredSize;
|
|
}
|
|
|
|
protected override Size ArrangeOverride(Size finalSize)
|
|
{
|
|
if (_internalHostPresenter == null)
|
|
return base.ArrangeOverride(finalSize);
|
|
|
|
_internalHostPresenter.Arrange(new Rect(finalSize));
|
|
return base.ArrangeOverride(finalSize);// new Size(_internalHostPresenter.ActualWidth, _internalHostPresenter.ActualHeight);
|
|
}
|
|
|
|
#region Background
|
|
|
|
/// <summary>
|
|
/// Background Dependency Property
|
|
/// </summary>
|
|
public static readonly DependencyProperty BackgroundProperty =
|
|
DependencyProperty.Register("Background", typeof(Brush), typeof(LayoutAutoHideWindowControl),
|
|
new FrameworkPropertyMetadata((Brush)null));
|
|
|
|
/// <summary>
|
|
/// Gets or sets the Background property. This dependency property
|
|
/// indicates background of the autohide childwindow.
|
|
/// </summary>
|
|
public Brush Background
|
|
{
|
|
get { return (Brush)GetValue(BackgroundProperty); }
|
|
set { SetValue(BackgroundProperty, value); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
internal bool IsWin32MouseOver
|
|
{
|
|
get
|
|
{
|
|
var ptMouse = new Win32Helper.Win32Point();
|
|
if (!Win32Helper.GetCursorPos(ref ptMouse))
|
|
return false;
|
|
|
|
Point location = this.PointToScreenDPI(new Point());
|
|
|
|
Rect rectWindow = this.GetScreenArea();
|
|
if (rectWindow.Contains(new Point(ptMouse.X, ptMouse.Y)))
|
|
return true;
|
|
|
|
var manager = Model.Root.Manager;
|
|
var anchor = manager.FindVisualChildren<LayoutAnchorControl>().Where(c => c.Model == Model).FirstOrDefault();
|
|
|
|
if (anchor == null)
|
|
return false;
|
|
|
|
location = anchor.PointToScreenDPI(new Point());
|
|
|
|
if (anchor.IsMouseOver)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
#region AnchorableStyle
|
|
|
|
/// <summary>
|
|
/// AnchorableStyle Dependency Property
|
|
/// </summary>
|
|
public static readonly DependencyProperty AnchorableStyleProperty =
|
|
DependencyProperty.Register("AnchorableStyle", typeof(Style), typeof(LayoutAutoHideWindowControl),
|
|
new FrameworkPropertyMetadata((Style)null));
|
|
|
|
/// <summary>
|
|
/// Gets or sets the AnchorableStyle property. This dependency property
|
|
/// indicates the style to apply to the LayoutAnchorableControl hosted in this auto hide window.
|
|
/// </summary>
|
|
public Style AnchorableStyle
|
|
{
|
|
get { return (Style)GetValue(AnchorableStyleProperty); }
|
|
set { SetValue(AnchorableStyleProperty, value); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
|
|
}
|
|
}
|
|
|