/// <summary>
/// Generate an implementation of the IDragPageNotify class that will be used to handle the drag/drop operation.
/// </summary>
/// <param name="screenPoint">Screen point of the mouse for the drag operation.</param>
/// <param name="elementOffset">Offset from top left of element causing the drag.</param>
/// <param name="c">Control that started the drag operation.</param>
/// <param name="pages">Set of pages requested to be dragged.</param>
public virtual void DoDragDrop(Point screenPoint, Point elementOffset, Control c, KryptonPageCollection pages)
{
// Cannot drag a null reference
if (pages == null)
throw new ArgumentNullException("pages");
// Cannot drag an empty collection
if (pages.Count == 0)
throw new ArgumentOutOfRangeException("pages", "collection cannot be empry");
// Create docking specific drag manager for moving the pages around
DockingDragManager dragManager = new DockingDragManager(this, c);
dragManager.FloatingWindowOffset = elementOffset;
bool atLeastOneFloating = false;
KryptonPage firstFloatingPage = null;
foreach (KryptonPage page in pages)
{
// You cannot drag a store page
if (!(page is KryptonStorePage))
{
// Cannot drag a null page reference
if (page == null)
throw new ArgumentNullException("pages collection contains a null page reference");
// Remember the first page that is allowed to be made floating
if (!atLeastOneFloating && page.AreFlagsSet(KryptonPageFlags.DockingAllowFloating))
{
// Use event to indicate the page is becoming floating and allow it to be cancelled
CancelUniqueNameEventArgs args = new CancelUniqueNameEventArgs(page.UniqueName, false);
OnPageFloatingRequest(args);
if (!args.Cancel)
{
firstFloatingPage = page;
atLeastOneFloating = true;
}
}
}
}
// If we have at least one page that is allowed to be floating
if (atLeastOneFloating)
{
// Can we find an existing floating store page...
KryptonDockingFloatspace floatspace = FindStorePageElement(DockingLocation.Floating, firstFloatingPage) as KryptonDockingFloatspace;
if (floatspace != null)
{
KryptonDockingFloatingWindow floatingWindow = floatspace.GetParentType(typeof(KryptonDockingFloatingWindow)) as KryptonDockingFloatingWindow;
if (floatingWindow != null)
{
// If the floating window is not currently visible...
if (!floatingWindow.FloatingWindow.Visible)
{
using (DockingMultiUpdate update = new DockingMultiUpdate(this))
{
//...then we can use it for dragging. We want the floating window to become visible and show just the set of pages
// that are allowed to be floating from the set of pages passed into this function. As the window is not currently
// visible it means all the contained pages are hidden and so we can make only the pages we are interested in visible
// and it will have the appearance we need.
dragManager.FloatingWindow = floatingWindow.FloatingWindow;
// Convert the existing page loaction, if any, to store and restore it in this floating window
KryptonPage[] firstFloatingPages = new KryptonPage[] { firstFloatingPage };
PropogateAction(DockingPropogateAction.StorePages, firstFloatingPages);
floatingWindow.PropogateAction(DockingPropogateAction.RestorePages, firstFloatingPages);
// Make a list of all pages that should be appended to the floating window
List<string> appendUniqueNames = new List<string>();
List<KryptonPage> appendPages = new List<KryptonPage>();
foreach (KryptonPage page in pages)
if (!(page is KryptonStorePage) && (page != firstFloatingPage) && page.AreFlagsSet(KryptonPageFlags.DockingAllowFloating))
{
appendUniqueNames.Add(page.UniqueName);
appendPages.Add(page);
}
// Set the window location before it is shown otherwise we see a brief flash as it appears at the
// existing location and then it moves to the correct location based on the screen mouse position
dragManager.FloatingWindow.Location = new Point(screenPoint.X - elementOffset.X, screenPoint.Y - elementOffset.Y);
// Convert the append pages to store pages and then append to the same cell as the just restore page above
PropogateAction(DockingPropogateAction.StorePages, appendUniqueNames.ToArray());
KryptonWorkspaceCell cell = floatingWindow.CellForPage(firstFloatingPage.UniqueName);
cell.Pages.AddRange(appendPages.ToArray());
}
}
}
}
// Do we need to create a new floating window?
if (dragManager.FloatingWindow == null)
{
// Get access to a floating element that allows a new floating window to be created
KryptonDockingFloating floating = FindDockingFloating(firstFloatingPage.UniqueName);
if (floating != null)
{
KryptonDockingFloatingWindow floatingWindow = floating.AddFloatingWindow();
if (floatingWindow != null)
{
using (DockingMultiUpdate update = new DockingMultiUpdate(this))
{
// This is the window that will be moved during the drag operation
dragManager.FloatingWindow = floatingWindow.FloatingWindow;
// Make a list of all pages that should be appended to the floating window
List<string> appendUniqueNames = new List<string>();
List<KryptonPage> appendPages = new List<KryptonPage>();
foreach (KryptonPage page in pages)
if (!(page is KryptonStorePage) && page.AreFlagsSet(KryptonPageFlags.DockingAllowFloating))
{
appendUniqueNames.Add(page.UniqueName);
appendPages.Add(page);
}
// Set the window location before it is shown otherwise we see a brief flash as it appears at the
// existing location and then it moves to the correct location based on the screen mouse position
dragManager.FloatingWindow.Location = new Point(screenPoint.X - elementOffset.X, screenPoint.Y - elementOffset.Y);
// Append the pages inside the new window, storing the current locations for later use
PropogateAction(DockingPropogateAction.StorePages, appendUniqueNames.ToArray());
floatingWindow.FloatspaceElement.Append(appendPages.ToArray());
floatingWindow.FloatingWindow.Show();
}
}
}
}
}
// Alow workspace controls to compact and update based on changes from above
Application.DoEvents();
// Add ourself as a source of drag targets and then begin the dragging process
dragManager.DragTargetProviders.Add(new DockingDragTargetProvider(this, dragManager.FloatingWindow, pages));
dragManager.DragStart(screenPoint, new PageDragEndData(this, pages));
}