/// <summary> /// Remove the named pages. /// </summary> /// <param name="uniqueNames">Array of unique names of the pages that should be removed.</param> /// <param name="disposePage">Should the page be disposed when removed.</param> public void RemovePages(string[] uniqueNames, bool disposePage) { // Cannot remove a null reference if (uniqueNames == null) { throw new ArgumentNullException(nameof(uniqueNames)); } if (uniqueNames.Length > 0) { // Cannot remove a null or zero length unique name foreach (string uniqueName in uniqueNames) { if (uniqueName == null) { throw new ArgumentNullException(nameof(uniqueNames), @"uniqueNames array contains a null string reference"); } if (uniqueName.Length == 0) { throw new ArgumentException(@"uniqueNames array contains a zero length string", nameof(uniqueNames)); } } // Remove page details from all parts of the hierarchy using (DockingMultiUpdate update = new DockingMultiUpdate(this)) { base.PropogateAction(disposePage ? DockingPropogateAction.RemoveAndDisposePages : DockingPropogateAction.RemovePages, uniqueNames); } } }
/// <summary> /// Hide all display elements of the provided pages. /// </summary> /// <param name="uniqueNames">Array of unique names of the pages that should be hidden.</param> public void HidePages(string[] uniqueNames) { // Cannot hide a null reference if (uniqueNames == null) { throw new ArgumentNullException(nameof(uniqueNames)); } if (uniqueNames.Length > 0) { // Cannot hide a null or zero length unique name foreach (string uniqueName in uniqueNames) { if (uniqueName == null) { throw new ArgumentNullException(nameof(uniqueNames), @"uniqueNames array contains a null string reference"); } if (uniqueName.Length == 0) { throw new ArgumentException(@"uniqueNames array contains a zero length string", nameof(uniqueNames)); } } using (DockingMultiUpdate update = new DockingMultiUpdate(this)) { base.PropogateAction(DockingPropogateAction.HidePages, uniqueNames); } } }
/// <summary> /// Hide all display elements of all pages. /// </summary> public void HideAllPages() { using (DockingMultiUpdate update = new DockingMultiUpdate(this)) { base.PropogateAction(DockingPropogateAction.HideAllPages, (string[])null); } }
/// <summary> /// Remove all pages. /// </summary> /// <param name="disposePage">Should the page be disposed when removed.</param> public void RemoveAllPages(bool disposePage) { // Remove all details about all pages from all parts of the hierarchy using (DockingMultiUpdate update = new DockingMultiUpdate(this)) { base.PropogateAction(disposePage ? DockingPropogateAction.RemoveAndDisposeAllPages : DockingPropogateAction.RemoveAllPages, (string[])null); } }
/// <summary> /// Remove all pages. /// </summary> /// <param name="disposePage">Should the page be disposed when removed.</param> public void RemoveAllPages(bool disposePage) { // Remove all details about all pages from all parts of the hierarchy using (DockingMultiUpdate update = new DockingMultiUpdate(this)) base.PropogateAction(disposePage ? DockingPropogateAction.RemoveAndDisposeAllPages : DockingPropogateAction.RemoveAllPages, (string[])null); }
/// <summary> /// Remove the named pages. /// </summary> /// <param name="uniqueNames">Array of unique names of the pages that should be removed.</param> /// <param name="disposePage">Should the page be disposed when removed.</param> public void RemovePages(string[] uniqueNames, bool disposePage) { // Cannot remove a null reference if (uniqueNames == null) throw new ArgumentNullException("uniqueNames"); if (uniqueNames.Length > 0) { // Cannot remove a null or zero length unique name foreach (string uniqueName in uniqueNames) { if (uniqueName == null) throw new ArgumentNullException("uniqueNames array contains a null string reference"); if (uniqueName.Length == 0) throw new ArgumentException("uniqueNames array contains a zero length string"); } // Remove page details from all parts of the hierarchy using (DockingMultiUpdate update = new DockingMultiUpdate(this)) base.PropogateAction(disposePage ? DockingPropogateAction.RemoveAndDisposePages : DockingPropogateAction.RemovePages, uniqueNames); } }
/// <summary> /// Perform the close request for a set of named pages. /// </summary> /// <param name="uniqueNames">Array of unique names that need action performed.</param> public virtual void CloseRequest(string[] uniqueNames) { // Cannot action a null reference if (uniqueNames == null) throw new ArgumentNullException("uniqueNames"); // Cannot action an empty array if (uniqueNames.Length == 0) throw new ArgumentOutOfRangeException("uniqueNames", "array cannot be empry"); // Cannot action a null or zero length unique name foreach (string uniqueName in uniqueNames) { if (uniqueName == null) throw new ArgumentNullException("uniqueNames array contains a null string reference"); if (uniqueName.Length == 0) throw new ArgumentException("uniqueNames array contains a zero length string"); } using (DockingMultiUpdate update = new DockingMultiUpdate(this)) { CloseRequestEventArgs e; foreach (string uniqueName in uniqueNames) { // Raise event that allows the action to be defined by handlers e = new CloseRequestEventArgs(uniqueName, DefaultCloseRequest); OnPageCloseRequest(e); switch (e.CloseRequest) { case DockingCloseRequest.None: // Nothing to do! break; case DockingCloseRequest.RemovePage: case DockingCloseRequest.RemovePageAndDispose: PropogateAction(e.CloseRequest == DockingCloseRequest.RemovePageAndDispose ? DockingPropogateAction.RemoveAndDisposePages : DockingPropogateAction.RemovePages, new string[] { uniqueName }); break; case DockingCloseRequest.HidePage: PropogateAction(DockingPropogateAction.HidePages, new string[] { uniqueName }); break; } } } }
/// <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)); }
/// <summary> /// Make the named page workspace tabbed. /// </summary> /// <param name="uniqueName">Unique name of page to become workspace tabbed.</param> public virtual void MakeWorkspaceRequest(string uniqueName) { // Cannot process a null reference if (uniqueName == null) throw new ArgumentNullException("uniqueName"); // Unique names cannot be zero length if (uniqueName.Length == 0) throw new ArgumentException("uniqueName cannot be zero length"); // If the named page exists and is not already workspace tabbed if (ContainsPage(uniqueName) && (FindPageLocation(uniqueName) != DockingLocation.Workspace)) { // If we can find a workspace element appropriate for the named page KryptonDockingWorkspace workspaceElement = FindDockingWorkspace(uniqueName); if (workspaceElement != null) { KryptonPage page = PageForUniqueName(uniqueName); if (page != null) { // Ensure all docking controls have been layed out before the change is processed Application.DoEvents(); CancelUniqueNameEventArgs args = new CancelUniqueNameEventArgs(uniqueName, !page.AreFlagsSet(KryptonPageFlags.DockingAllowWorkspace)); OnPageWorkspaceRequest(args); if (args.Cancel) return; using (DockingMultiUpdate update = new DockingMultiUpdate(this)) { // Convert the page to a placeholder so it can be returned to the same location PropogateAction(DockingPropogateAction.StorePages, new string[] { uniqueName }); // Find the target cell, if there is one, that contains a store page KryptonWorkspaceCell cell = workspaceElement.CellForPage(uniqueName); if (cell != null) { // Insert the page at the same index as the restore page int pageIndex = cell.Pages.IndexOf(cell.Pages[uniqueName]); workspaceElement.CellInsert(cell, pageIndex, new KryptonPage[] { page }); workspaceElement.SelectPage(uniqueName); workspaceElement.DockableWorkspaceControl.Select(); } else { // No existing store page so just append to the worksapce workspaceElement.Append(new KryptonPage[] { page }); workspaceElement.SelectPage(uniqueName); workspaceElement.DockableWorkspaceControl.Select(); } } } } } }
/// <summary> /// Clear away any store pages for the provided unique named pages. /// </summary> /// <param name="uniqueNames">Array of unique names of the pages that should have store pages removed.</param> public void ClearStoredPages(string[] uniqueNames) { // Cannot clear a null reference if (uniqueNames == null) throw new ArgumentNullException("uniqueNames"); // Cannot clear an empty array if (uniqueNames.Length == 0) throw new ArgumentOutOfRangeException("uniqueNames", "array cannot be empry"); // Cannot clear a null or zero length unique name foreach (string uniqueName in uniqueNames) { if (uniqueName == null) throw new ArgumentNullException("uniqueNames array contains a null string reference"); if (uniqueName.Length == 0) throw new ArgumentException("uniqueNames array contains a zero length string"); } using (DockingMultiUpdate update = new DockingMultiUpdate(this)) PropogateAction(DockingPropogateAction.ClearStoredPages, uniqueNames); }
/// <summary> /// Make the named page floating. /// </summary> /// <param name="uniqueName">Unique name of page to become floating.</param> public virtual void MakeFloatingRequest(string uniqueName) { // Cannot process a null reference if (uniqueName == null) throw new ArgumentNullException("uniqueName"); // Unique names cannot be zero length if (uniqueName.Length == 0) throw new ArgumentException("uniqueName cannot be zero length"); // If the named page exists and is not already floating if (ContainsPage(uniqueName) && (FindPageLocation(uniqueName) != DockingLocation.Floating)) { // If we can find a floating element appropriate for the named page KryptonDockingFloating floating = FindDockingFloating(uniqueName); if (floating != null) { KryptonPage page = PageForUniqueName(uniqueName); if (page != null) { // Ensure all docking controls have been layed out before the change is processed Application.DoEvents(); CancelUniqueNameEventArgs args = new CancelUniqueNameEventArgs(uniqueName, !page.AreFlagsSet(KryptonPageFlags.DockingAllowFloating)); OnPageFloatingRequest(args); if (args.Cancel) return; using (DockingMultiUpdate update = new DockingMultiUpdate(this)) { // Convert the page to a placeholder so it can be returned to the same location PropogateAction(DockingPropogateAction.StorePages, new string[] { uniqueName }); // Is there a floating window with a restore page for the named page? KryptonDockingFloatingWindow restoreElement = floating.FloatingWindowForStorePage(uniqueName); if (restoreElement != null) { // Find the target cell and the index of the restore page KryptonWorkspaceCell cell = restoreElement.CellForPage(uniqueName); int pageIndex = cell.Pages.IndexOf(cell.Pages[uniqueName]); // Insert the page at the same index as the restore page restoreElement.FloatspaceElement.CellInsert(cell, pageIndex, new KryptonPage[] { page }); restoreElement.SelectPage(uniqueName); restoreElement.FloatingWindow.Select(); } else { // No floating window found to restore into, so create a new window KryptonDockingFloatingWindow floatingElement = floating.AddFloatingWindow(); floatingElement.FloatspaceElement.Append(new KryptonPage[] { page }); floatingElement.SelectPage(uniqueName); floatingElement.FloatingWindow.Show(); } } } } } }
/// <summary> /// Make the named page auto hidden. /// </summary> /// <param name="uniqueName">Unique name of page to become auto hidden.</param> public virtual void MakeAutoHiddenRequest(string uniqueName) { // Cannot process a null reference if (uniqueName == null) throw new ArgumentNullException("uniqueName"); // Unique names cannot be zero length if (uniqueName.Length == 0) throw new ArgumentException("uniqueName cannot be zero length"); // If the named page exists and is not already auto hidden if (ContainsPage(uniqueName) && (FindPageLocation(uniqueName) != DockingLocation.AutoHidden)) { // If we can find an auto hidden edge element appropriate for the named page KryptonDockingEdgeAutoHidden autoHidden = FindDockingEdgeAutoHidden(uniqueName); if (autoHidden != null) { KryptonPage page = PageForUniqueName(uniqueName); if (page != null) { // Ensure all docking controls have been layed out before the change is processed Application.DoEvents(); CancelUniqueNameEventArgs args = new CancelUniqueNameEventArgs(uniqueName, !page.AreFlagsSet(KryptonPageFlags.DockingAllowAutoHidden)); OnPageAutoHiddenRequest(args); if (args.Cancel) return; using (DockingMultiUpdate update = new DockingMultiUpdate(this)) { // Convert the page to a placeholder so it can be returned to the same location PropogateAction(DockingPropogateAction.StorePages, new string[] { uniqueName }); // Is there a auto hidden group with a restore page for the named page? KryptonDockingAutoHiddenGroup restoreElement = autoHidden.FindStorePageElement(DockingLocation.AutoHidden, uniqueName) as KryptonDockingAutoHiddenGroup; if (restoreElement != null) { // Find the target index of the restore page KryptonAutoHiddenGroup control = restoreElement.AutoHiddenGroupControl; int pageIndex = control.Pages.IndexOf(control.Pages[uniqueName]); // Insert the page at the same index as the restore page control.Pages.Insert(pageIndex, new KryptonAutoHiddenProxyPage(page)); } else { // No existing store page so add as a new group restoreElement = autoHidden.AppendAutoHiddenGroup(); restoreElement.Append(new KryptonPage[] { page }); } } } } } }
/// <summary> /// Perform a switch from floating to docked for the named pages. /// </summary> /// <param name="uniqueNames">Unique name of floating pages that need switching.</param> /// <returns>KryptonDockingDockspace reference if a new dockspace needed to be created; otherwise false.</returns> public virtual KryptonDockingDockspace SwitchFloatingToDockedRequest(string[] uniqueNames) { // Cannot action a null reference if (uniqueNames == null) throw new ArgumentNullException("uniqueNames"); // Cannot action an empty array if (uniqueNames.Length == 0) throw new ArgumentOutOfRangeException("uniqueNames", "array cannot be empry"); // Cannot action a null or zero length unique name foreach (string uniqueName in uniqueNames) { if (uniqueName == null) throw new ArgumentNullException("uniqueNames array contains a null string reference"); if (uniqueName.Length == 0) throw new ArgumentException("uniqueNames array contains a zero length string"); } // Use events to determine which pages should be switched List<string> switchUniqueNames = new List<string>(); List<KryptonPage> switchPages = new List<KryptonPage>(); string selectedPage = null; foreach (string uniqueName in uniqueNames) { // Does the provided unique name exist and is in the required 'floating' state if (FindPageLocation(uniqueName) == DockingLocation.Floating) { KryptonPage page = PageForUniqueName(uniqueName); if (page != null) { CancelUniqueNameEventArgs args = new CancelUniqueNameEventArgs(page.UniqueName, !page.AreFlagsSet(KryptonPageFlags.DockingAllowDocked)); OnPageDockedRequest(args); if (!args.Cancel) { switchUniqueNames.Add(page.UniqueName); switchPages.Add(page); // Navigate to the cell that holds the page KryptonDockingFloatspace floatspace = FindPageElement(page) as KryptonDockingFloatspace; if (floatspace != null) { KryptonWorkspaceCell cell = floatspace.CellForPage(uniqueName); if (cell != null) { // Remember the page that is active if (cell.SelectedPage == page) selectedPage = page.UniqueName; } } } } } } // Still any pages to be switched? if (switchUniqueNames.Count > 0) { using (DockingMultiUpdate update = new DockingMultiUpdate(this)) { // Convert the pages to placeholders so they can be returned to the same location PropogateAction(DockingPropogateAction.StorePages, switchUniqueNames.ToArray()); // Try and restore each page, but make a note of thos that failed to be restore List<string> defaultUniqueNames = new List<string>(); List<KryptonPage> defaultPages = new List<KryptonPage>(); KryptonPage defaultSelectedPage = null; for(int i=0; i<switchUniqueNames.Count; i++) { // Find any dockspace that contains a restore page for this named page string switchUniqueName = switchUniqueNames[i]; KryptonDockingDockspace restoreElement = DockingManager.FindStorePageElement(DockingLocation.Docked, switchUniqueName) as KryptonDockingDockspace; if (restoreElement != null) { // Find the target cell and the index of the restore page KryptonWorkspaceCell cell = restoreElement.CellForPage(switchUniqueName); int pageIndex = cell.Pages.IndexOf(cell.Pages[switchUniqueName]); // Insert the set of pages at the same index as the restore page restoreElement.CellInsert(cell, pageIndex, switchPages[i]); // Make sure the same page is selected as was selected in the floating source if (switchUniqueName == selectedPage) { restoreElement.SelectPage(selectedPage); restoreElement.DockspaceControl.UpdateVisible(true); } } else { defaultUniqueNames.Add(switchUniqueName); defaultPages.Add(switchPages[i]); // Note the default page that should become selected if (switchUniqueName == selectedPage) defaultSelectedPage = switchPages[i]; } } // Any pages that need default positioning because they could not be restored? if (defaultPages.Count > 0) { // Cannot switch to docked unless we can find a docked element as the target KryptonDockingEdgeDocked edgeDocked = FindDockingEdgeDocked(defaultSelectedPage != null ? defaultSelectedPage.UniqueName : defaultPages[0].UniqueName); if (edgeDocked != null) { KryptonDockingDockspace dockspace = edgeDocked.AppendDockspace(); dockspace.Append(defaultPages.ToArray()); // Make sure the same page is selected as was selected in the floating source if (defaultSelectedPage != null) { dockspace.SelectPage(defaultSelectedPage.UniqueName); dockspace.DockspaceControl.UpdateVisible(true); } } } } } return null; }
/// <summary> /// Perform a switch from floating to new floating window for the named pages. /// </summary> /// <param name="uniqueNames">Unique name of floating pages that need switching.</param> /// <returns>KryptonDockingFloatingWindow reference on success; otherwise false.</returns> public virtual KryptonDockingFloatingWindow SwitchFloatingToFloatingWindowRequest(string[] uniqueNames) { // Cannot action a null reference if (uniqueNames == null) throw new ArgumentNullException("uniqueNames"); // Cannot action an empty array if (uniqueNames.Length == 0) throw new ArgumentOutOfRangeException("uniqueNames", "array cannot be empry"); // Cannot action a null or zero length unique name foreach (string uniqueName in uniqueNames) { if (uniqueName == null) throw new ArgumentNullException("uniqueNames array contains a null string reference"); if (uniqueName.Length == 0) throw new ArgumentException("uniqueNames array contains a zero length string"); } // Use events to determine which pages should be switched List<string> switchUniqueNames = new List<string>(); List<KryptonPage> switchPages = new List<KryptonPage>(); string selectedPage = null; foreach (string uniqueName in uniqueNames) { // Does the provided unique name exist and is in the required 'floating' state if (FindPageLocation(uniqueName) == DockingLocation.Floating) { KryptonPage page = PageForUniqueName(uniqueName); if (page != null) { switchUniqueNames.Add(uniqueName); switchPages.Add(page); // Navigate to the cell that holds the page KryptonDockingFloatspace floatspace = FindPageElement(page) as KryptonDockingFloatspace; if (floatspace != null) { KryptonWorkspaceCell cell = floatspace.CellForPage(uniqueName); if (cell != null) { // Remember the page that is active if (cell.SelectedPage == page) selectedPage = page.UniqueName; } } } } } // Still any pages to be switched? if (switchUniqueNames.Count > 0) { // Find a floating element that is the target for the switching KryptonDockingFloating floating = FindDockingFloating(selectedPage != null ? selectedPage : switchUniqueNames[0]); if (floating != null) { using (DockingMultiUpdate update = new DockingMultiUpdate(this)) { // Grab the current element that contains one of the pages being moved KryptonDockingFloatspace currentElement = FindPageElement(switchPages[0]) as KryptonDockingFloatspace; // Remove the pages from the existing floating window PropogateAction(DockingPropogateAction.RemovePages, switchUniqueNames.ToArray()); // Create a new floating window and add the specified set of pages KryptonDockingFloatingWindow floatingElement = floating.AddFloatingWindow(); floatingElement.FloatspaceElement.Append(switchPages.ToArray()); // Make sure any seleted page is selected in the new floating window if (selectedPage != null) floatingElement.SelectPage(selectedPage); // Position the new floating window close to the existing one floatingElement.FloatingWindow.Location = currentElement.FloatspaceControl.PointToScreen(Point.Empty); floatingElement.FloatingWindow.Show(); return floatingElement; } } } return null; }
/// <summary> /// Perform a switch from docked pages to floating window for the named pages. /// </summary> /// <param name="uniqueNames">Unique name of pages inside a docked cell that needs switching.</param> /// <returns>KryptonDockingFloatingWindow reference on success; otherwise null.</returns> public virtual KryptonDockingFloatingWindow SwitchDockedToFloatingWindowRequest(string[] uniqueNames) { // Cannot action a null reference if (uniqueNames == null) throw new ArgumentNullException("uniqueNames"); // Cannot action an empty array if (uniqueNames.Length == 0) throw new ArgumentOutOfRangeException("uniqueNames", "array cannot be empry"); // Cannot action a null or zero length unique name foreach (string uniqueName in uniqueNames) { if (uniqueName == null) throw new ArgumentNullException("uniqueNames array contains a null string reference"); if (uniqueName.Length == 0) throw new ArgumentException("uniqueNames array contains a zero length string"); } // Use events to determine which pages should be switched List<string> switchUniqueNames = new List<string>(); List<KryptonPage> switchPages = new List<KryptonPage>(); string selectedPage = null; foreach (string uniqueName in uniqueNames) { // Does the provided unique name exist and is in the required 'docked' state if (FindPageLocation(uniqueName) == DockingLocation.Docked) { KryptonPage page = PageForUniqueName(uniqueName); if (page != null) { CancelUniqueNameEventArgs args = new CancelUniqueNameEventArgs(page.UniqueName, !page.AreFlagsSet(KryptonPageFlags.DockingAllowFloating)); OnPageFloatingRequest(args); if (!args.Cancel) { switchUniqueNames.Add(page.UniqueName); switchPages.Add(page); // Navigate to the cell that holds the page KryptonDockingDockspace dockspace = FindPageElement(page) as KryptonDockingDockspace; if (dockspace != null) { KryptonWorkspaceCell cell = dockspace.CellForPage(uniqueName); if (cell != null) { // Remember the page that is active if (cell.SelectedPage == page) selectedPage = page.UniqueName; } } } } } } // Still any pages to be switched? if (switchUniqueNames.Count > 0) { // Find a floating element that is the target for the switching KryptonDockingFloating floating = FindDockingFloating(selectedPage != null ? selectedPage : switchUniqueNames[0]); if (floating != null) { using (DockingMultiUpdate update = new DockingMultiUpdate(this)) { // Convert the pages to placeholders so they can be returned to the same location PropogateAction(DockingPropogateAction.StorePages, switchUniqueNames.ToArray()); KryptonWorkspaceCell cell = null; foreach (string switchUniqueName in switchUniqueNames) { // Is there a floating window with a restore page for this unique name? KryptonDockingFloatingWindow restoreElement = floating.FloatingWindowForStorePage(switchUniqueName); if (restoreElement != null) { // Find the target cell and the index of the restore page cell = restoreElement.CellForPage(switchUniqueName); int pageIndex = cell.Pages.IndexOf(cell.Pages[switchUniqueName]); // Insert the set of pages at the same index as the restore page restoreElement.FloatspaceElement.CellInsert(cell, pageIndex, switchPages.ToArray()); // Make sure the same page is selected as was selected in the docked source if (selectedPage != null) restoreElement.SelectPage(selectedPage); return restoreElement; } } // No floating window found to restore into, so create a new window KryptonDockingFloatingWindow floatingElement = floating.AddFloatingWindow(); floatingElement.FloatspaceElement.Append(switchPages.ToArray()); // Make sure the same page is selected as was selected in the docked source if (selectedPage != null) floatingElement.SelectPage(selectedPage); floatingElement.FloatingWindow.Show(); return floatingElement; } } } return null; }
/// <summary> /// Perform a switch from docked cell to auto hidden group for the visible pages inside the cell. /// </summary> /// <param name="uniqueName">Unique name of page inside docked cell that needs switching.</param> /// <returns>KryptonDockingAutoHiddenGroup reference on success; otherwise null.</returns> public virtual KryptonDockingAutoHiddenGroup SwitchDockedCellToAutoHiddenGroupRequest(string uniqueName) { // Cannot switch a null reference if (uniqueName == null) throw new ArgumentNullException("uniqueName"); // Unique names cannot be zero length if (uniqueName.Length == 0) throw new ArgumentException("uniqueName cannot be zero length"); // Does the provided unique name exist and is in the required 'docked' state if (FindPageLocation(uniqueName) == DockingLocation.Docked) { // Grab the dockspace element that we expect to contain the target unique name KryptonDockingDockspace dockspace = (KryptonDockingDockspace)ExpectPageElement(uniqueName, typeof(KryptonDockingDockspace)); if (dockspace != null) { // Does the dockspace currently have the focus? bool hadFocus = dockspace.DockspaceControl.ContainsFocus; // Find the sibling auto hidden edge so we can add a new auto hidden group to it later on KryptonDockingEdgeAutoHidden edgeAutoHidden = dockspace.EdgeAutoHiddenElement; if (edgeAutoHidden != null) { // Grab the set of visible pages in the same cell as the target unique name KryptonPage[] visiblePages = dockspace.CellVisiblePages(uniqueName); if (visiblePages.Length > 0) { // Use events to determine which pages in the cell should be switched List<string> switchUniqueNames = new List<string>(); List<KryptonPage> switchPages = new List<KryptonPage>(); foreach (KryptonPage page in visiblePages) { CancelUniqueNameEventArgs args = new CancelUniqueNameEventArgs(page.UniqueName, !page.AreFlagsSet(KryptonPageFlags.DockingAllowAutoHidden)); OnPageAutoHiddenRequest(args); if (!args.Cancel) { switchUniqueNames.Add(page.UniqueName); switchPages.Add(page); } } // Any pages that actually need to be switched? if (switchPages.Count > 0) { using (DockingMultiUpdate update = new DockingMultiUpdate(this)) { // Convert the pages to placeholders so they can be returned to the same location string[] uniqueNames = switchUniqueNames.ToArray(); dockspace.PropogateAction(DockingPropogateAction.StorePages, uniqueNames); // Create a new auto hidden group and add the switch pages into it KryptonDockingAutoHiddenGroup group = edgeAutoHidden.AppendAutoHiddenGroup(); group.Append(switchPages.ToArray()); // If we had the focus at the start of the process and the dockspace no longer has it... if (hadFocus && !dockspace.DockspaceControl.ContainsFocus) { // ...and focus has not moved to another part of the form... Form topForm = dockspace.DockspaceControl.FindForm(); if ((topForm != null) && !topForm.ContainsFocus) { // ...then shift focus to the auto hidden group placeholder, to ensure the form still has the // focus and so hovering the mouse over the auto hidden tabs will correctly get them to slide out KryptonDockingEdgeAutoHidden edge = group.GetParentType(typeof(KryptonDockingEdgeAutoHidden)) as KryptonDockingEdgeAutoHidden; if (edge != null) topForm.Focus(); } } return group; } } } } } } return null; }
/// <summary> /// Perform a switch from auto hidden group to docked cell for the visible pages inside the group. /// </summary> /// <param name="uniqueName">Unique name of page inside auto hidden group that needs switching.</param> /// <returns>KryptonDockingDockspace reference if a new dockspace needed to be created; otherwise false.</returns> public virtual KryptonDockingDockspace SwitchAutoHiddenGroupToDockedCellRequest(string uniqueName) { // Cannot switch a null reference if (uniqueName == null) throw new ArgumentNullException("uniqueName"); // Unique names cannot be zero length if (uniqueName.Length == 0) throw new ArgumentException("uniqueName cannot be zero length"); // Does the provided unique name exist and is in the required 'autohidden' state if (FindPageLocation(uniqueName) == DockingLocation.AutoHidden) { // Grab the auto hidden group docking element that we expect to contain the target unique name KryptonDockingAutoHiddenGroup autoHiddenGroup = (KryptonDockingAutoHiddenGroup)ExpectPageElement(uniqueName, typeof(KryptonDockingAutoHiddenGroup)); if (autoHiddenGroup != null) { // Find the sibling docked edge so we can add/restore pages KryptonDockingEdgeDocked edgeDocked = autoHiddenGroup.EdgeDockedElement; if (edgeDocked != null) { // Grab the set of visible pages in the auto hidden group KryptonPage[] visiblePages = autoHiddenGroup.VisiblePages(); if (visiblePages.Length > 0) { // Use events to determine which pages in the cell should be switched List<string> switchUniqueNames = new List<string>(); List<KryptonPage> switchPages = new List<KryptonPage>(); foreach (KryptonPage page in visiblePages) { CancelUniqueNameEventArgs args = new CancelUniqueNameEventArgs(page.UniqueName, !page.AreFlagsSet(KryptonPageFlags.DockingAllowDocked)); OnPageDockedRequest(args); if (!args.Cancel) { switchUniqueNames.Add(page.UniqueName); switchPages.Add(page); } } // Any pages that actually need to be switched? if (switchPages.Count > 0) { using (DockingMultiUpdate update = new DockingMultiUpdate(this)) { // Remove the pages from the auto hidden group string[] uniqueNames = switchUniqueNames.ToArray(); PropogateAction(DockingPropogateAction.RemovePages, uniqueNames); // Attempt to restore each page back to original location on the same edge List<KryptonPage> defaultPages = new List<KryptonPage>(); KryptonPage defaultSelectedPage = null; for(int i=0; i<switchPages.Count; i++) { // If we find a store page then we can simply restore straight back to that position bool? canRestore = edgeDocked.PropogateBoolState(DockingPropogateBoolState.ContainsStorePage, uniqueNames[i]); if (canRestore.HasValue && canRestore.Value) { // Restore page back into a dockspace edgeDocked.PropogateAction(DockingPropogateAction.RestorePages, new KryptonPage[] { switchPages[i] }); // Should this page become the selected and focused page? if (uniqueName == uniqueNames[i]) { // If this restored page was the selected page in the auto hidden group, make it selected in the dockspace KryptonDockingDockspace restoreElement = edgeDocked.FindPageElement(uniqueNames[i]) as KryptonDockingDockspace; if (restoreElement != null) { restoreElement.SelectPage(uniqueNames[i]); restoreElement.DockspaceControl.UpdateVisible(true); } } } else { defaultPages.Add(switchPages[i]); // Note the default page that should become selected if (uniqueName == uniqueNames[i]) defaultSelectedPage = switchPages[i]; } } // Remove any existing placeholders in all the docked edges RemoveControlStorePages(edgeDocked, uniqueNames, false, true); // Do we have some pages that still need adding? if (defaultPages.Count > 0) { // Place them all inside a new dockspace KryptonDockingDockspace newDockspace = edgeDocked.AppendDockspace(); newDockspace.Append(defaultPages.ToArray()); // Make sure the same page is selected as was selected in the auto hidden group if (defaultSelectedPage != null) { newDockspace.SelectPage(defaultSelectedPage.UniqueName); newDockspace.DockspaceControl.UpdateVisible(true); } return newDockspace; } } } } } } } return null; }
/// <summary> /// Show all display elements of all pages. /// </summary> public void ShowAllPages() { using (DockingMultiUpdate update = new DockingMultiUpdate(this)) base.PropogateAction(DockingPropogateAction.ShowAllPages, (string[])null); }
/// <summary> /// Loads docking configuration information using the provided xml reader. /// </summary> /// <param name="xmlReader">Xml reader object.</param> public void LoadConfigFromXml(XmlReader xmlReader) { // Remember the current culture setting CultureInfo culture = Thread.CurrentThread.CurrentCulture; try { // Double check this has the correct element name if (xmlReader.Name != "KD") throw new ArgumentException("Root element must be named 'KD'"); // Load the format version number string version = xmlReader.GetAttribute("V"); // Convert format version from string to double int formatVersion = (int)Convert.ToDouble(version); // We can only load 1 upward version formats if (formatVersion < 1) throw new ArgumentException("Can only load Version 1 and upwards of KryptonDockingManager persisted data."); using (DockingMultiUpdate update = new DockingMultiUpdate(this)) { // Create a list of all the existing pages KryptonPageCollection currentPages = new KryptonPageCollection(); PropogatePageList(DockingPropogatePageList.All, currentPages); // Reset docking hierarchy ready for the reload PropogateAction(DockingPropogateAction.Loading, (string[])null); try { // Read to custom data element if (!xmlReader.Read()) throw new ArgumentException("An element was expected but could not be read in."); if (xmlReader.Name != "DGD") throw new ArgumentException("Expected 'DGD' element was not found."); bool finished = xmlReader.IsEmptyElement; // Give handlers chance to reload custom saved data OnGlobalLoading(new DockGlobalLoadingEventArgs(this, xmlReader)); // Read everything until we get the end of custom data marker while (!finished) { // Check it has the expected name if (xmlReader.NodeType == XmlNodeType.EndElement) finished = (xmlReader.Name == "DGD"); if (!finished) { if (!xmlReader.Read()) throw new ArgumentException("An element was expected but could not be read in."); } } // Read the next well known element if (!xmlReader.Read()) throw new ArgumentException("An element was expected but could not be read in."); // Is it the expected element? if (xmlReader.Name != "DM") throw new ArgumentException("Element 'DM' was expected but not found."); // Reload the root sequence LoadElementFromXml(xmlReader, currentPages); // Move past the end element if (!xmlReader.Read()) throw new ArgumentException("Could not read in next expected node."); // Check it has the expected name if (xmlReader.NodeType != XmlNodeType.EndElement) throw new ArgumentException("EndElement expected but not found."); // Did we have any starting pages? if (currentPages.Count > 0) { // Create a list of all the pages present after loading KryptonPageCollection loadedPages = new KryptonPageCollection(); PropogatePageList(DockingPropogatePageList.All, loadedPages); // Remove the loaded pages from the current page list foreach (KryptonPage loadedPage in loadedPages) currentPages.Remove(loadedPage); // Did we any orphan pages? Those that existed at start of loading but // are not present in the docking hierarchy after loading. So they are // orphaned and we allow developers a chance to do something with them. if (currentPages.Count > 0) { // Generate event so the pages can be processed manually PagesEventArgs args = new PagesEventArgs(currentPages); OnOrphanedPages(args); // If there are pages not processed by the event if (args.Pages.Count > 0) { // Cleanup the no longer needed pages by disposing them foreach (KryptonPage page in args.Pages) page.Dispose(); } } } } finally { } } } finally { // Put back the old culture before exiting routine Thread.CurrentThread.CurrentCulture = culture; } }
/// <summary> /// Show all display elements of the provided pages. /// </summary> /// <param name="uniqueNames">Array of unique names of the pages that should be shown.</param> public void ShowPages(string[] uniqueNames) { // Cannot show a null reference if (uniqueNames == null) throw new ArgumentNullException("uniqueNames"); if (uniqueNames.Length > 0) { // Cannot show a null or zero length unique name foreach (string uniqueName in uniqueNames) { if (uniqueName == null) throw new ArgumentNullException("uniqueNames array contains a null string reference"); if (uniqueName.Length == 0) throw new ArgumentException("uniqueNames array contains a zero length string"); } using (DockingMultiUpdate update = new DockingMultiUpdate(this)) base.PropogateAction(DockingPropogateAction.ShowPages, uniqueNames); } }
/// <summary> /// Cleat away all store pages. /// </summary> public void ClearAllStoredPages() { using (DockingMultiUpdate update = new DockingMultiUpdate(this)) PropogateAction(DockingPropogateAction.ClearAllStoredPages, (string[])null); }
/// <summary> /// Add set of pages as a new auto hidden group to the specified edge of the specified control. /// </summary> /// <param name="path">Path for finding the target KryptonDockingControl.</param> /// <param name="edge">Target edge within the KryptonDockingControl.</param> /// <param name="pages">Array of pages to be added as an auto hidden group.</param> /// <param name="extraPages">Extra arrays of pages to be added as extra groups.</param> /// <returns>KryptonDockingAutoHiddenGroup reference.</returns> public virtual KryptonDockingAutoHiddenGroup AddAutoHiddenGroup(string path, DockingEdge edge, KryptonPage[] pages, params KryptonPage[][] extraPages) { // Cannot add a null array if (pages == null) throw new ArgumentNullException("pages"); // Array must contain some values if (pages.Length == 0) throw new ArgumentException("pages cannot be zero length"); // Cannot action a null page reference foreach (KryptonPage page in pages) if (page == null) throw new ArgumentNullException("pages array contains a null page reference"); // Resolve the given path to the expected docking control element KryptonDockingControl control = ResolvePath(path) as KryptonDockingControl; if (control == null) throw new ArgumentException("Path does not resolve to a KryptonDockingControl"); // Find the requested target edge KryptonDockingEdge edgeElement = control[edge.ToString()] as KryptonDockingEdge; if (edgeElement == null) throw new ArgumentException("KryptonDockingControl does not have the requested edge."); // Find the auto hidden edge KryptonDockingEdgeAutoHidden edgeAutoHidden = edgeElement["AutoHidden"] as KryptonDockingEdgeAutoHidden; if (edgeAutoHidden == null) throw new ArgumentException("KryptonDockingControl edge does not have an auto hidden element."); KryptonDockingAutoHiddenGroup autoHiddenGroup = null; using (DockingMultiUpdate update = new DockingMultiUpdate(this)) { // Create a new auto hidden group and add the provided array of pages autoHiddenGroup = edgeAutoHidden.AppendAutoHiddenGroup(); autoHiddenGroup.Append(pages); // If we have extra pages then we need to add extra auto hidden groups if ((extraPages != null) && (extraPages.Length > 0)) { // For each array of pages... foreach (KryptonPage[] pageArray in extraPages) if ((pageArray != null) && (pageArray.Length > 0)) { // Create a new auto hidden group and add the provided array of pages KryptonDockingAutoHiddenGroup extraAutoHiddenGroup = edgeAutoHidden.AppendAutoHiddenGroup(); extraAutoHiddenGroup.Append(pageArray); } } } return autoHiddenGroup; }
/// <summary> /// Make the named page navigator tabbed. /// </summary> /// <param name="uniqueName">Unique name of page to become navigator tabbed.</param> public virtual void MakeNavigatorRequest(string uniqueName) { // Cannot process a null reference if (uniqueName == null) throw new ArgumentNullException("uniqueName"); // Unique names cannot be zero length if (uniqueName.Length == 0) throw new ArgumentException("uniqueName cannot be zero length"); // If the named page exists and is not already navigator tabbed if (ContainsPage(uniqueName) && (FindPageLocation(uniqueName) != DockingLocation.Navigator)) { // If we can find a navigator element appropriate for the named page KryptonDockingNavigator navigatorElement = FindDockingNavigator(uniqueName); if (navigatorElement != null) { KryptonPage page = PageForUniqueName(uniqueName); if (page != null) { // Ensure all docking controls have been layed out before the change is processed Application.DoEvents(); CancelUniqueNameEventArgs args = new CancelUniqueNameEventArgs(uniqueName, !page.AreFlagsSet(KryptonPageFlags.DockingAllowNavigator)); OnPageNavigatorRequest(args); if (args.Cancel) return; using (DockingMultiUpdate update = new DockingMultiUpdate(this)) { // Convert the page to a placeholder so it can be returned to the same location PropogateAction(DockingPropogateAction.StorePages, new string[] { uniqueName }); // If we can find an existing page in the target navigator with the name we are inserting KryptonDockableNavigator navigatorControl = navigatorElement.DockableNavigatorControl; KryptonPage insertPage = navigatorControl.Pages[uniqueName]; if (insertPage != null) { int pageIndex = navigatorControl.Pages.IndexOf(insertPage); if (pageIndex >= 0) { // Insert the page at the same index as the restore page navigatorControl.Pages.Insert(pageIndex, page); navigatorElement.SelectPage(uniqueName); navigatorControl.Select(); } else { // Append at end of current page collection navigatorControl.Pages.Add(page); navigatorElement.SelectPage(uniqueName); navigatorControl.Select(); } } } } } } }
/// <summary> /// Add set of pages docked against a specified edge of the specified control. /// </summary> /// <param name="path">Path for finding the target KryptonDockingControl.</param> /// <param name="edge">Target edge within the KryptonDockingControl.</param> /// <param name="pages">Array of pages to be added as docked.</param> /// <param name="stackPages">Extra arrays of pages to be added in a stacked manner.</param> /// <returns>KryptonDockingDockspace reference.</returns> public virtual KryptonDockingDockspace AddDockspace(string path, DockingEdge edge, KryptonPage[] pages, params KryptonPage[][] stackPages) { // Cannot add a null array if (pages == null) throw new ArgumentNullException("pages"); // Array must contain some values if (pages.Length == 0) throw new ArgumentException("pages cannot be zero length"); // Cannot action a null page reference foreach (KryptonPage page in pages) if (page == null) throw new ArgumentNullException("pages array contains a null page reference"); // Resolve the given path to the expected docking control element KryptonDockingControl control = ResolvePath(path) as KryptonDockingControl; if (control == null) throw new ArgumentException("Path does not resolve to a KryptonDockingControl"); // Find the requested target edge KryptonDockingEdge edgeElement = control[edge.ToString()] as KryptonDockingEdge; if (edgeElement == null) throw new ArgumentException("KryptonDockingControl does not have the requested edge."); // Find the docked edge KryptonDockingEdgeDocked edgeDocked = edgeElement["Docked"] as KryptonDockingEdgeDocked; if (edgeDocked == null) throw new ArgumentException("KryptonDockingControl edge does not have a docked element."); KryptonDockingDockspace dockspace = null; using (DockingMultiUpdate update = new DockingMultiUpdate(this)) { // Create a new dockspace and add the provided array of pages dockspace = edgeDocked.AppendDockspace(); dockspace.Append(pages); // If we have extra pages then we need to add a stack of tabbed cells if ((stackPages != null) && (stackPages.Length > 0)) { // For each array of pages... foreach (KryptonPage[] pageArray in stackPages) if ((pageArray != null) && (pageArray.Length > 0)) { // We need a new cell with all the pages from the array KryptonWorkspaceCell cell = new KryptonWorkspaceCell(); cell.Pages.AddRange(pageArray); // Add into the root collection so the cells appear in a stack dockspace.DockspaceControl.Root.Children.Add(cell); } // Set the correct direction for the stacking of cells at the root switch (edge) { case DockingEdge.Left: case DockingEdge.Right: dockspace.DockspaceControl.Root.Orientation = Orientation.Vertical; break; case DockingEdge.Top: case DockingEdge.Bottom: dockspace.DockspaceControl.Root.Orientation = Orientation.Horizontal; break; } } } return dockspace; }
/// <summary> /// Hide all display elements of all pages. /// </summary> public void HideAllPages() { using (DockingMultiUpdate update = new DockingMultiUpdate(this)) PropogateAction(DockingPropogateAction.HideAllPages, (string[])null); }