All the controls missing in WPF. Over 1 million downloads.
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.

201 lines
6.0 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.Collections.Generic;
using System.Linq;
using System.Windows;
using Xceed.Wpf.AvalonDock.Layout;
namespace Xceed.Wpf.AvalonDock.Controls
{
internal class DragService
{
#region Members
private DockingManager _manager;
private LayoutFloatingWindowControl _floatingWindow;
private List<IOverlayWindowHost> _overlayWindowHosts = new List<IOverlayWindowHost>();
private IOverlayWindowHost _currentHost;
private IOverlayWindow _currentWindow;
private List<IDropArea> _currentWindowAreas = new List<IDropArea>();
private IDropTarget _currentDropTarget;
#endregion
#region Public Methods
public DragService( LayoutFloatingWindowControl floatingWindow )
{
_floatingWindow = floatingWindow;
_manager = floatingWindow.Model.Root.Manager;
GetOverlayWindowHosts();
}
public void UpdateMouseLocation( Point dragPosition )
{
var floatingWindowModel = _floatingWindow.Model as LayoutFloatingWindow;
var newHost = _overlayWindowHosts.FirstOrDefault( oh => oh.HitTest( dragPosition ) );
if( _currentHost != null || _currentHost != newHost )
{
//is mouse still inside current overlay window host?
if( ( _currentHost != null && !_currentHost.HitTest( dragPosition ) ) ||
_currentHost != newHost )
{
//esit drop target
if( _currentDropTarget != null )
_currentWindow.DragLeave( _currentDropTarget );
_currentDropTarget = null;
//exit area
_currentWindowAreas.ForEach( a =>
_currentWindow.DragLeave( a ) );
_currentWindowAreas.Clear();
//hide current overlay window
if( _currentWindow != null )
_currentWindow.DragLeave( _floatingWindow );
if( _currentHost != null )
_currentHost.HideOverlayWindow();
_currentHost = null;
}
if( _currentHost != newHost )
{
_currentHost = newHost;
_currentWindow = _currentHost.ShowOverlayWindow( _floatingWindow );
_currentWindow.DragEnter( _floatingWindow );
}
}
if( _currentHost == null )
return;
if( _currentDropTarget != null &&
!_currentDropTarget.HitTest( dragPosition ) )
{
_currentWindow.DragLeave( _currentDropTarget );
_currentDropTarget = null;
}
List<IDropArea> areasToRemove = new List<IDropArea>();
_currentWindowAreas.ForEach( a =>
{
//is mouse still inside this area?
if( !a.DetectionRect.Contains( dragPosition ) )
{
_currentWindow.DragLeave( a );
areasToRemove.Add( a );
}
} );
areasToRemove.ForEach( a =>
_currentWindowAreas.Remove( a ) );
var areasToAdd =
_currentHost.GetDropAreas( _floatingWindow ).Where( cw => !_currentWindowAreas.Contains( cw ) && cw.DetectionRect.Contains( dragPosition ) ).ToList();
_currentWindowAreas.AddRange( areasToAdd );
areasToAdd.ForEach( a =>
_currentWindow.DragEnter( a ) );
if( _currentDropTarget == null )
{
_currentWindowAreas.ForEach( wa =>
{
if( _currentDropTarget != null )
return;
_currentDropTarget = _currentWindow.GetTargets().FirstOrDefault( dt => dt.HitTest( dragPosition ) );
if( _currentDropTarget != null )
{
_currentWindow.DragEnter( _currentDropTarget );
return;
}
} );
}
}
public void Drop( Point dropLocation, out bool dropHandled )
{
dropHandled = false;
UpdateMouseLocation( dropLocation );
var floatingWindowModel = _floatingWindow.Model as LayoutFloatingWindow;
var root = floatingWindowModel.Root;
if( _currentHost != null )
_currentHost.HideOverlayWindow();
if( _currentDropTarget != null )
{
_currentWindow.DragDrop( _currentDropTarget );
root.CollectGarbage();
dropHandled = true;
}
_currentWindowAreas.ForEach( a => _currentWindow.DragLeave( a ) );
if( _currentDropTarget != null )
_currentWindow.DragLeave( _currentDropTarget );
if( _currentWindow != null )
_currentWindow.DragLeave( _floatingWindow );
_currentWindow = null;
_currentHost = null;
}
#endregion
#region Internal Methods
internal void Abort()
{
var floatingWindowModel = _floatingWindow.Model as LayoutFloatingWindow;
_currentWindowAreas.ForEach( a => _currentWindow.DragLeave( a ) );
if( _currentDropTarget != null )
_currentWindow.DragLeave( _currentDropTarget );
if( _currentWindow != null )
_currentWindow.DragLeave( _floatingWindow );
_currentWindow = null;
if( _currentHost != null )
_currentHost.HideOverlayWindow();
_currentHost = null;
}
#endregion
#region Private Methods
private void GetOverlayWindowHosts()
{
_overlayWindowHosts.AddRange( _manager.GetFloatingWindowsByZOrder().OfType<LayoutAnchorableFloatingWindowControl>().Where( fw => fw != _floatingWindow && fw.IsVisible ) );
_overlayWindowHosts.Add( _manager );
}
#endregion
}
}