/// <summary> /// Is this target a match for the provided screen position. /// </summary> /// <param name="screenPt">Position in screen coordinates.</param> /// <param name="dragEndData">Data to be dropped at destination.</param> /// <returns>True if a match; otherwise false.</returns> public override bool IsMatch(Point screenPt, PageDragEndData dragEndData) { // First time around... if (_visibleNotDraggedPages == -1) { // If pages are being dragged from this cell if (dragEndData.Navigator == Cell) { // Create list of all the visible pages in the cell KryptonPageCollection visiblePages = new KryptonPageCollection(); foreach (KryptonPage page in Cell.Pages) { if (page.LastVisibleSet) { visiblePages.Add(page); } } // Remove all those that are being dragged foreach (KryptonPage page in dragEndData.Pages) { visiblePages.Remove(page); } // Cache number of visible pages in target that are not part of the dragging set _visibleNotDraggedPages = visiblePages.Count; } else { // Pages not coming from this cell so we always allow the cell edge targets _visibleNotDraggedPages = int.MaxValue; } } // If the drop leaves at least 1 page in the navigator then allow drag to edge if (_visibleNotDraggedPages >= 1) { return(base.IsMatch(screenPt, dragEndData)); } else { return(false); } }
/// <summary> /// Loads docking configuration information using a provider xml reader. /// </summary> /// <param name="xmlReader">Xml reader object.</param> /// <param name="pages">Collection of available pages for adding.</param> public override void LoadElementFromXml(XmlReader xmlReader, KryptonPageCollection pages) { // Is it the expected xml element name? if (xmlReader.Name != XmlElementName) { throw new ArgumentException($@"Element name '{XmlElementName}' was expected but found '{xmlReader.Name}' instead."); } // Grab the element attributes string elementName = xmlReader.GetAttribute(@"N"); string elementCount = xmlReader.GetAttribute(@"C"); // Check the name matches up if (elementName != Name) { throw new ArgumentException($@"Attribute 'N' value '{Name}' was expected but found '{elementName}' instead."); } // Remove any existing pages in the navigator DockableNavigatorControl.Pages.Clear(); // If there are children then load them int count = int.Parse(elementCount); if (count > 0) { KryptonDockingManager manager = DockingManager; for (int i = 0; i < count; i++) { // Read past this element if (!xmlReader.Read()) { throw new ArgumentException(@"An element was expected but could not be read in."); } // Is it the expected xml element name? if (xmlReader.Name != @"KP") { throw new ArgumentException($@"Element name 'KP' was expected but found '{xmlReader.Name}' instead."); } // Get the unique name of the page string uniqueName = CommonHelper.XmlAttributeToText(xmlReader, @"UN"); bool boolStore = CommonHelper.StringToBool(CommonHelper.XmlAttributeToText(xmlReader, @"S")); bool boolVisible = CommonHelper.StringToBool(CommonHelper.XmlAttributeToText(xmlReader, @"V", @"True")); // If the entry is for just a placeholder... KryptonPage page; if (boolStore) { // Recreate the requested store page and append page = new KryptonStorePage(uniqueName, _storeName); DockableNavigatorControl.Pages.Add(page); } else { // Can we find a provided page to match the incoming layout? page = pages[uniqueName]; if (page == null) { // Generate event so developer can create and supply the page now RecreateLoadingPageEventArgs args = new RecreateLoadingPageEventArgs(uniqueName); manager.RaiseRecreateLoadingPage(args); if (!args.Cancel && (args.Page != null)) { page = args.Page; } } if (page != null) { // Use the loaded visible state page.Visible = boolVisible; // Remove from provided collection as we can only add it once to the docking hierarchy pages.Remove(page); // Add into the navigator DockableNavigatorControl.Pages.Add(page); } } if (!xmlReader.Read()) { throw new ArgumentException(@"An element was expected but could not be read in."); } if (xmlReader.Name != @"CPD") { throw new ArgumentException(@"Expected 'CPD' element was not found"); } bool finished = xmlReader.IsEmptyElement; // Generate event so custom data can be loaded and/or the page to be added can be modified DockPageLoadingEventArgs pageLoading = new DockPageLoadingEventArgs(manager, xmlReader, page); manager.RaisePageLoading(pageLoading); // 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 == @"CPD"); } if (!finished) { if (!xmlReader.Read()) { throw new ArgumentException(@"An element was expected but could not be read in."); } } } if (!xmlReader.Read()) { throw new ArgumentException(@"An element was expected but could not be read in."); } } } // Read past this element to the end element if (!xmlReader.Read()) { throw new ArgumentException(@"An element was expected but could not be read in."); } }
/// <summary> /// Is this target a match for the provided screen position. /// </summary> /// <param name="screenPt">Position in screen coordinates.</param> /// <param name="dragEndData">Data to be dropped at destination.</param> /// <returns>True if a match; otherwise false.</returns> public override bool IsMatch(Point screenPt, PageDragEndData dragEndData) { // First time around... if (_visibleNotDraggedPages == -1) { // If pages are being dragged from this cell if (dragEndData.Navigator == _cell) { // Create list of all the visible pages in the cell KryptonPageCollection visiblePages = new KryptonPageCollection(); foreach (KryptonPage page in _cell.Pages) if (page.LastVisibleSet) visiblePages.Add(page); // Remove all those that are being dragged foreach (KryptonPage page in dragEndData.Pages) visiblePages.Remove(page); // Cache number of visible pages in target that are not part of the dragging set _visibleNotDraggedPages = visiblePages.Count; } else { // Pages not coming from this cell so we always allow the cell edge targets _visibleNotDraggedPages = int.MaxValue; } } // If the drop leaves at least 1 page in the navigator then allow drag to edge if (_visibleNotDraggedPages >= 1) return base.IsMatch(screenPt, dragEndData); else return false; }
/// <summary> /// Propagates an action request down the hierarchy of docking elements. /// </summary> /// <param name="action">Action that is requested to be performed.</param> /// <param name="uniqueNames">Array of unique names of the pages the action relates to.</param> public override void PropogateAction(DockingPropogateAction action, string[] uniqueNames) { KryptonPageCollection pageCollection = DockableNavigatorControl.Pages; switch (action) { case DockingPropogateAction.Loading: // Remove all pages including store pages pageCollection.Clear(); return; case DockingPropogateAction.ShowAllPages: case DockingPropogateAction.HideAllPages: case DockingPropogateAction.RemoveAllPages: case DockingPropogateAction.RemoveAndDisposeAllPages: // Ignore some global actions return; case DockingPropogateAction.StorePages: foreach (string uniqueName in uniqueNames) { // Swap pages that are not placeholders to become placeholders KryptonPage page = pageCollection[uniqueName]; if ((page != null) && !(page is KryptonStorePage)) { // Replace the existing page with a placeholder that has the same unique name KryptonStorePage placeholder = new KryptonStorePage(uniqueName, _storeName); pageCollection.Insert(pageCollection.IndexOf(page), placeholder); pageCollection.Remove(page); } } break; case DockingPropogateAction.StoreAllPages: // Process each page inside the cell for (int i = pageCollection.Count - 1; i >= 0; i--) { // Swap pages that are not placeholders to become placeholders KryptonPage page = pageCollection[i]; if ((page != null) && !(page is KryptonStorePage)) { // Replace the existing page with a placeholder that has the same unique name KryptonStorePage placeholder = new KryptonStorePage(page.UniqueName, _storeName); pageCollection.Insert(pageCollection.IndexOf(page), placeholder); pageCollection.Remove(page); } } break; case DockingPropogateAction.ClearFillerStoredPages: case DockingPropogateAction.ClearStoredPages: foreach (string uniqueName in uniqueNames) { // Only remove a matching unique name if it is a placeholder page KryptonPage removePage = pageCollection[uniqueName]; if (removePage is KryptonStorePage) { pageCollection.Remove(removePage); } } break; case DockingPropogateAction.ClearAllStoredPages: { // Process each page inside the cell for (int i = pageCollection.Count - 1; i >= 0; i--) { // Remove all placeholders KryptonPage page = pageCollection[i]; if (page is KryptonStorePage) { pageCollection.Remove(page); } } } break; case DockingPropogateAction.DebugOutput: Console.WriteLine(GetType().ToString()); DockableNavigatorControl.DebugOutput(); break; } // Let base class perform standard processing base.PropogateAction(action, uniqueNames); }
/// <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; } }