/*************************************************************************************
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;
using System.Runtime.InteropServices;
using System.Windows.Interop;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Input;
using Xceed.Wpf.AvalonDock.Layout;
using Xceed.Wpf.AvalonDock.Converters;
using System.Diagnostics;
using System.Windows.Controls.Primitives;
using Xceed.Wpf.AvalonDock.Commands;
using Microsoft.Windows.Shell;
namespace Xceed.Wpf.AvalonDock.Controls
{
public class LayoutAnchorableFloatingWindowControl : LayoutFloatingWindowControl, IOverlayWindowHost
{
static LayoutAnchorableFloatingWindowControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(LayoutAnchorableFloatingWindowControl), new FrameworkPropertyMetadata(typeof(LayoutAnchorableFloatingWindowControl)));
}
internal LayoutAnchorableFloatingWindowControl(LayoutAnchorableFloatingWindow model)
:base(model)
{
_model = model;
HideWindowCommand = new RelayCommand((p) => OnExecuteHideWindowCommand(p), (p) => CanExecuteHideWindowCommand(p));
}
internal override void UpdateThemeResources( Xceed.Wpf.AvalonDock.Themes.Theme oldTheme = null )
{
base.UpdateThemeResources(oldTheme);
if (_overlayWindow != null)
_overlayWindow.UpdateThemeResources(oldTheme);
}
LayoutAnchorableFloatingWindow _model;
public override ILayoutElement Model
{
get { return _model; }
}
#region SingleContentLayoutItem
///
/// SingleContentLayoutItem Dependency Property
///
public static readonly DependencyProperty SingleContentLayoutItemProperty =
DependencyProperty.Register("SingleContentLayoutItem", typeof(LayoutItem), typeof(LayoutAnchorableFloatingWindowControl),
new FrameworkPropertyMetadata((LayoutItem)null,
new PropertyChangedCallback(OnSingleContentLayoutItemChanged)));
///
/// Gets or sets the SingleContentLayoutItem property. This dependency property
/// indicates the layout item of the selected content when is shown a single anchorable pane.
///
public LayoutItem SingleContentLayoutItem
{
get { return (LayoutItem)GetValue(SingleContentLayoutItemProperty); }
set { SetValue(SingleContentLayoutItemProperty, value); }
}
///
/// Handles changes to the SingleContentLayoutItem property.
///
private static void OnSingleContentLayoutItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((LayoutAnchorableFloatingWindowControl)d).OnSingleContentLayoutItemChanged(e);
}
///
/// Provides derived classes an opportunity to handle changes to the SingleContentLayoutItem property.
///
protected virtual void OnSingleContentLayoutItemChanged(DependencyPropertyChangedEventArgs e)
{
}
#endregion
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
var manager = _model.Root.Manager;
Content = manager.CreateUIElementForModel(_model.RootPanel);
//SetBinding(VisibilityProperty, new Binding("IsVisible") { Source = _model, Converter = new BoolToVisibilityConverter(), Mode = BindingMode.OneWay, ConverterParameter = Visibility.Hidden });
//Issue: http://avalondock.codeplex.com/workitem/15036
IsVisibleChanged += (s, args) =>
{
var visibilityBinding = GetBindingExpression(VisibilityProperty);
if (IsVisible && (visibilityBinding == null))
{
SetBinding(VisibilityProperty, new Binding("IsVisible") { Source = _model, Converter = new BoolToVisibilityConverter(), Mode = BindingMode.OneWay, ConverterParameter = Visibility.Hidden });
}
};
SetBinding(SingleContentLayoutItemProperty, new Binding("Model.SinglePane.SelectedContent") { Source = this, Converter = new LayoutItemFromLayoutModelConverter() });
_model.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(_model_PropertyChanged);
}
void _model_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == "RootPanel" &&
_model.RootPanel == null)
{
InternalClose();
}
}
bool IOverlayWindowHost.HitTest(Point dragPoint)
{
Rect detectionRect = new Rect(this.PointToScreenDPIWithoutFlowDirection(new Point()), this.TransformActualSizeToAncestor());
return detectionRect.Contains(dragPoint);
}
DockingManager IOverlayWindowHost.Manager
{
get { return _model.Root.Manager; }
}
OverlayWindow _overlayWindow = null;
void CreateOverlayWindow()
{
if (_overlayWindow == null)
_overlayWindow = new OverlayWindow(this);
Rect rectWindow = new Rect(this.PointToScreenDPIWithoutFlowDirection(new Point()), this.TransformActualSizeToAncestor());
_overlayWindow.Left = rectWindow.Left;
_overlayWindow.Top = rectWindow.Top;
_overlayWindow.Width = rectWindow.Width;
_overlayWindow.Height = rectWindow.Height;
}
IOverlayWindow IOverlayWindowHost.ShowOverlayWindow(LayoutFloatingWindowControl draggingWindow)
{
CreateOverlayWindow();
_overlayWindow.Owner = draggingWindow;
_overlayWindow.EnableDropTargets();
_overlayWindow.Show();
return _overlayWindow;
}
void IOverlayWindowHost.HideOverlayWindow()
{
_dropAreas = null;
_overlayWindow.Owner = null;
_overlayWindow.HideDropTargets();
}
List _dropAreas = null;
IEnumerable IOverlayWindowHost.GetDropAreas(LayoutFloatingWindowControl draggingWindow)
{
if (_dropAreas != null)
return _dropAreas;
_dropAreas = new List();
if (draggingWindow.Model is LayoutDocumentFloatingWindow)
return _dropAreas;
var rootVisual = (Content as FloatingWindowContentHost).RootVisual;
foreach (var areaHost in rootVisual.FindVisualChildren())
{
_dropAreas.Add(new DropArea(
areaHost,
DropAreaType.AnchorablePane));
}
foreach (var areaHost in rootVisual.FindVisualChildren())
{
_dropAreas.Add(new DropArea(
areaHost,
DropAreaType.DocumentPane));
}
return _dropAreas;
}
protected override void OnClosed(EventArgs e)
{
var root = Model.Root;
root.Manager.RemoveFloatingWindow(this);
root.CollectGarbage();
if (_overlayWindow != null)
{
_overlayWindow.Close();
_overlayWindow = null;
}
base.OnClosed(e);
if (!CloseInitiatedByUser)
{
root.FloatingWindows.Remove(_model);
}
_model.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler(_model_PropertyChanged);
}
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
if (CloseInitiatedByUser && !KeepContentVisibleOnClose)
{
e.Cancel = true;
_model.Descendents().OfType().ToArray().ForEach((a) => a.Hide());
}
base.OnClosing(e);
}
protected override IntPtr FilterMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
case Win32Helper.WM_NCLBUTTONDOWN: //Left button down on title -> start dragging over docking manager
if (wParam.ToInt32() == Win32Helper.HT_CAPTION)
{
_model.Descendents().OfType().First(p => p.ChildrenCount > 0 && p.SelectedContent != null).SelectedContent.IsActive = true;
handled = true;
}
break;
case Win32Helper.WM_NCRBUTTONUP:
if (wParam.ToInt32() == Win32Helper.HT_CAPTION)
{
if (OpenContextMenu())
handled = true;
if (_model.Root.Manager.ShowSystemMenu)
WindowChrome.GetWindowChrome(this).ShowSystemMenu = !handled;
else
WindowChrome.GetWindowChrome(this).ShowSystemMenu = false;
}
break;
}
return base.FilterMessage(hwnd, msg, wParam, lParam, ref handled);
}
bool OpenContextMenu()
{
var ctxMenu = _model.Root.Manager.AnchorableContextMenu;
if (ctxMenu != null && SingleContentLayoutItem != null)
{
ctxMenu.PlacementTarget = null;
ctxMenu.Placement = PlacementMode.MousePoint;
ctxMenu.DataContext = SingleContentLayoutItem;
ctxMenu.IsOpen = true;
return true;
}
return false;
}
bool IsContextMenuOpen()
{
var ctxMenu = _model.Root.Manager.AnchorableContextMenu;
if (ctxMenu != null && SingleContentLayoutItem != null)
{
return ctxMenu.IsOpen;
}
return false;
}
#region HideWindowCommand
public ICommand HideWindowCommand
{
get;
private set;
}
private bool CanExecuteHideWindowCommand(object parameter)
{
if (Model == null)
return false;
var root = Model.Root;
if (root == null)
return false;
var manager = root.Manager;
if (manager == null)
return false;
bool canExecute = false;
foreach (var anchorable in this.Model.Descendents().OfType().ToArray())
{
if (!anchorable.CanHide)
{
canExecute = false;
break;
}
var anchorableLayoutItem = manager.GetLayoutItemFromModel(anchorable) as LayoutAnchorableItem;
if (anchorableLayoutItem == null ||
anchorableLayoutItem.HideCommand == null ||
!anchorableLayoutItem.HideCommand.CanExecute(parameter))
{
canExecute = false;
break;
}
canExecute = true;
}
return canExecute;
}
private void OnExecuteHideWindowCommand(object parameter)
{
var manager = Model.Root.Manager;
foreach (var anchorable in this.Model.Descendents().OfType().ToArray())
{
var anchorableLayoutItem = manager.GetLayoutItemFromModel(anchorable) as LayoutAnchorableItem;
anchorableLayoutItem.HideCommand.Execute(parameter);
}
}
#endregion
}
}