/// <summary> /// Find last pane /// </summary> private void _FindLastPane(ref DockablePane largestPane) { for (int index = _children.Count - 1; 0 <= index; --index) { Composition child = _children[index]; if (child.Type != CompositionType.Terminal) { child._FindLastPane(ref largestPane); } else { largestPane = child.AttachedPane; } if (null != largestPane) { break; // result founded } } }
/// <summary> /// Find largest pane /// </summary> /// <remarks>largest by hypotenuse</remarks> private void _FindLargestPane(ref Size maxSize, ref DockablePane largestPane) { for (int index = 0; index < _children.Count; ++index) { Composition child = _children[index]; if (child.Type != CompositionType.Terminal) { child._FindLargestPane(ref maxSize, ref largestPane); } else { Size sz = child._CalculateSpaceSize(); if (_CalculateHypotenuse(maxSize) < _CalculateHypotenuse(sz)) { largestPane = child.AttachedPane; maxSize = sz; } } } }
/// <summary> /// Add pane to composition /// </summary> private void _Add(DockablePane pane, Dock dockType) { Composition newElement = new Composition(this, pane); if (CompositionType.Terminal == _type) { // change compostion from terminal to linear Debug.Assert(0 == _children.Count); Composition first = new Composition(this, _attachedPane); _CreateLineComposition(first, newElement, dockType); } else { if (_DoesAdding2Line(dockType)) { // add new element to linear composition // update children space factors // new child - requared 50% of all layout for (int index = 0; index < _children.Count; ++index) { _children[index].SpaceFactor /= 2; } _InsertElement2Line(newElement, dockType); } else { // do copy from current composition - it is linear composition Composition compositionCopy = _CreateCopy(); // remove old composition elements _children.Clear(); // do one linear composition: // add old elements as one linear composition and // add new element to linear composition _CreateLineComposition(compositionCopy, newElement, dockType); } } Debug.Assert(_IsNormalized()); }
/////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Add pane. /// </summary> /// <param name="pane">Inserted pane.</param> public void Add(DockablePane pane) { if (null == _root) { _root = new Composition(null, pane); // first creation _ArrangeLayout(); _RegisterDropService(pane); } else if (_root.IsInited && (null == _root.Find(pane))) { if (pane.UseSpecAllocation) _root.AddSpec(pane, pane.DockType); else _root.Add(pane, pane.DockType); _ArrangeLayout(); _RegisterDropService(pane); } }
/// <summary> /// Remove pane. /// </summary> /// <param name="pane">Pane for identification.</param> public void Remove(DockablePane pane) { if (null != _root) { Debug.Assert(_root.IsInited); if (null != _root.Find(pane)) { bool isRemoved = false; if (CompositionType.Terminal != _root.Type) { isRemoved = _root.Remove(pane); } else { if (_root.AttachedPane.Equals(pane)) { _root = null; isRemoved = true; } else { Debug.Assert(false); // not supported } } if (isRemoved) { _ArrangeLayout(); } _UnregisterDropService(pane); // clearing margins var margin = new Thickness(0); pane.SetValue(FrameworkElement.MarginProperty, margin); } } }
/// <summary> /// Create floating window /// </summary> /// <param name="pane">Relative pane</param> public FloatingWindow(DockablePane pane) { InitializeComponent(); _isTooltipEnabled = true; _paneHosted = pane; Content = _paneHosted; Title = _paneHosted.PaneContent.Title; // add code to update window header. _dpDescriptor = DependencyPropertyDescriptor.FromProperty(Window.TitleProperty, typeof(Window)); if (_dpDescriptor != null) { _dpDescriptor.AddValueChanged(_paneHosted.PaneContent, delegate { if (Content != null) { Title = ((DockablePane)Content).PaneContent.Title; } }); } _paneHosted.PaneContent.DockManager.RegisterFloatingWnd(this); }
/// <summary> /// Restore docking layout reading a xml string which is previously generated by a call /// to GetLayoutState. /// </summary> /// <param name="xml">Xml containing layout state.</param> /// <param name="getContentHandler">Delegate used by serializer to get user defined /// dockable contents.</param> public void RestoreLayoutFromXml(string xml, GetContentFromTypeString getContentHandler) { var doc = new XmlDocument(); doc.LoadXml(xml); _ResetInternalState(); foreach (XmlNode nodeChild in doc.ChildNodes[0]) { if (ELEMENT_NAME_ROOT == nodeChild.Name) { gridDocking.Deserialize(this, nodeChild, getContentHandler); } else if (ELEMENT_NAME_FLTWNDS == nodeChild.Name) { foreach (XmlNode node in nodeChild.ChildNodes) { var pane = new DockablePane(); pane.Deserialize(this, node, getContentHandler); } } } }
/// <summary> /// Add pane to composition /// </summary> private void _Add(DockablePane pane, Dock dockType) { Composition newElement = new Composition(this, pane); if (CompositionType.Terminal == _type) { // change compostion from terminal to linear Debug.Assert(0 == _children.Count); Composition first = new Composition(this, _attachedPane); _CreateLineComposition(first, newElement, dockType); } else { if (_DoesAdding2Line(dockType)) { // add new element to linear composition // update children space factors // new child - requared 50% of all layout for (int index = 0; index < _children.Count; ++index) _children[index].SpaceFactor /= 2; _InsertElement2Line(newElement, dockType); } else { // do copy from current composition - it is linear composition Composition compositionCopy = _CreateCopy(); // remove old composition elements _children.Clear(); // do one linear composition: // add old elements as one linear composition and // add new element to linear composition _CreateLineComposition(compositionCopy, newElement, dockType); } } Debug.Assert(_IsNormalized()); }
/// <summary> /// Remove pane /// </summary> public bool Remove(DockablePane pane) { if (!_isInited) return false; Debug.Assert(CompositionType.Terminal != _type); _CalculateSpaceFactors(); bool isRemoved = false; // find terminal element to deleting Composition terminalComposition2Delete = null; for (int index = 0; index < _children.Count; ++index) { Composition currentComposition = _children[index]; if (CompositionType.Terminal == currentComposition.Type) { if (currentComposition.AttachedPane.Equals(pane)) { terminalComposition2Delete = currentComposition; break; // NOTE: founded } } else { // remove from child composition if (currentComposition.Remove(pane)) { isRemoved = true; break; } } } // remove terminal element if (null != terminalComposition2Delete) { _children.Remove(terminalComposition2Delete); isRemoved = true; if (1 == _children.Count) { // change state to terminal Composition lastChield = _children[0]; _children.Clear(); if (CompositionType.Terminal == lastChield.Type) { _type = CompositionType.Terminal; _attachedPane = lastChield.AttachedPane; } else { _type = lastChield.Type; ICollection<Composition> children = lastChield.Children; foreach (Composition child in children) _children.Add(child); } } else { // recalculate new space factors Size sz = _CalculateSpaceSize(); double fullSize = (_type == CompositionType.Horizontal) ? sz.Height : sz.Width; fullSize += SPLITTER_SIZE; double splitterFree = SPLITTER_SIZE / _children.Count; Size freeSize = terminalComposition2Delete._CalculateSpaceSize(); for (int index = 0; index < _children.Count; ++index) { Composition child = _children[index]; Size childSize = child._CalculateSpaceSize(); child.SpaceFactor = (_type == CompositionType.Horizontal) ? ((childSize.Height + freeSize.Height * child.SpaceFactor + splitterFree) / Math.Max(fullSize, 1)) : ((childSize.Width + freeSize.Width * child.SpaceFactor + splitterFree) / Math.Max(fullSize, 1)); } } } else if (isRemoved) { // normalize composition - if child presented as one line for (int index = 0; index < _children.Count; ++index) { Composition currentChild = _children[index]; if (currentChild.Type == _type) { ICollection<Composition> children = currentChild.Children; Debug.Assert(currentChild.Type != CompositionType.Terminal); Debug.Assert(1 < currentChild.Children.Count); Collection<Composition> fromRemoved = new Collection<Composition> (); foreach (Composition child in children) fromRemoved.Add(child); _children.Remove(currentChild); _children.InsertRange(index, fromRemoved); } } _CalculateSpaceFactors(); } Debug.Assert(_IsNormalized()); return isRemoved; }
public Composition Find(DockablePane pane) { if (!_isInited) return null; Composition terminalComposition = null; if (CompositionType.Terminal == _type) { if (_attachedPane.Equals(pane)) terminalComposition = this; } else { // find relative terminal element index for (int index = 0; index < _children.Count; ++index) { Composition currentComposition = _children[index]; terminalComposition = currentComposition.Find(pane); if (null != terminalComposition) break; } } return terminalComposition; }
/// <summary> /// Deserialize layout /// </summary> /// <param name="manager">Dock manager for initing objects</param> /// <param name="node">Node to parse</param> /// <param name="handlerObject">Delegate used to get user defined dockable contents</param> public void Deserialize(DockManager manager, XmlNode node, GetContentFromTypeString handlerObject) { _type = (CompositionType)Enum.Parse(typeof(CompositionType), node.Attributes[ATTRIBUTE_NAME_TYPE].Value); _spaceFactor = double.Parse(node.Attributes[ATTRIBUTE_NAME_SFACTOR].Value, CultureInfo.GetCultureInfo(STORAGE_CULTURE)); if (_type == CompositionType.Terminal) { Debug.Assert(node.ChildNodes[0].Name == ELEMENT_NAME_DOCKPANE); DockablePane pane = new DockablePane(); pane.Deserialize(manager, node.ChildNodes[0], handlerObject); _attachedPane = pane; if (pane.IsDragSupported) manager.DragPaneServices.Register(pane); } else { Debug.Assert(node.ChildNodes[0].Name == ELEMENT_NAME_CHILDGROUPS); foreach (XmlNode nodeChild in node.ChildNodes[0].ChildNodes) { Composition composition = new Composition(); composition.Deserialize(manager, nodeChild, handlerObject); _children.Add(composition); } } _isInited = true; }
/// <summary> /// Handle dockable pane layout changing. /// </summary> /// <param name="sourcePane">Source pane to move.</param> /// <param name="destinationPane">Relative pane.</param> /// <param name="relativeDock">Dock type.</param> public void MoveTo(DockablePane sourcePane, DockablePane destinationPane, Dock relativeDock) { gridDocking.Add(sourcePane, destinationPane, relativeDock); }
/// <summary> /// Dock this pane to a destination pane border /// </summary> /// <param name="destinationPane"></param> /// <param name="relativeDock">Relative dock inside destination pane</param> public void MoveTo(DockablePane destinationPane, Dock relativeDock) { _useSpecAllocation = false; _CloseFloatingWindow(); DockablePane dockableDestPane = destinationPane as DockablePane; StoreSize(); State = PaneState.Docked; _dockType = relativeDock; ShowHeader = true; _content.DockManager.MoveTo(this, dockableDestPane, relativeDock); }
/// <summary> /// Find last pane /// </summary> private void _FindLastPane(ref DockablePane largestPane) { for (int index = _children.Count - 1; 0 <= index; --index) { Composition child = _children[index]; if (child.Type != CompositionType.Terminal) child._FindLastPane(ref largestPane); else largestPane = child.AttachedPane; if (null != largestPane) break; // result founded } }
/// <summary> /// Create floating window /// </summary> /// <param name="pane">Relative pane</param> public FloatingWindow(DockablePane pane) { InitializeComponent(); _isTooltipEnabled = true; _paneHosted = pane; Content = _paneHosted; Title = _paneHosted.PaneContent.Title; // add code to update window header. _dpDescriptor = DependencyPropertyDescriptor.FromProperty(Window.TitleProperty, typeof(Window)); if (_dpDescriptor != null) _dpDescriptor.AddValueChanged(_paneHosted.PaneContent, delegate { if (Content != null) Title = ((DockablePane)Content).PaneContent.Title; }); _paneHosted.PaneContent.DockManager.RegisterFloatingWnd(this); }
/// <summary> /// Add a dockapble to layout management. /// </summary> /// <param name="pane">Pane to manage.</param> public void Add(DockablePane pane) { gridDocking.Add(pane); }
/// <summary> /// Restore docking layout reading a xml string which is previously generated by a call /// to GetLayoutState. /// </summary> /// <param name="xml">Xml containing layout state.</param> /// <param name="getContentHandler">Delegate used by serializer to get user defined /// dockable contents.</param> public void RestoreLayoutFromXml(string xml, GetContentFromTypeString getContentHandler) { var doc = new XmlDocument(); doc.LoadXml(xml); _ResetInternalState(); foreach (XmlNode nodeChild in doc.ChildNodes[0]) { if (ELEMENT_NAME_ROOT == nodeChild.Name) gridDocking.Deserialize(this, nodeChild, getContentHandler); else if (ELEMENT_NAME_FLTWNDS == nodeChild.Name) { foreach (XmlNode node in nodeChild.ChildNodes) { var pane = new DockablePane(); pane.Deserialize(this, node, getContentHandler); } } } }
/// <summary> /// Remove a dockable pane from layout management. /// </summary> /// <param name="pane">Pane to remove.</param> public void Remove(DockablePane pane) { if (pane.IsDragSupported) DragPaneServices.Unregister(pane); gridDocking.Remove(pane); }
/// <summary> /// Create line composition /// </summary> private void _CreateLineComposition(Composition first, Composition second, Dock dockType) { _attachedPane = null; _type = _GetCompositionTypeByDock(dockType); _children.Add(first); _InsertElement2Line(second , dockType); }
/// <summary> /// Add pane relative. /// </summary> /// <param name="pane">Inserted pane.</param> /// <param name="relativePane">Relative pane.</param> /// <param name="relativeDock">Dock relative "relative" pane.</param> public void Add(DockablePane pane, DockablePane relativePane, Dock relativeDock) { Debug.Assert(null != _root); Debug.Assert(_root.IsInited); if (null == _root.Find(pane)) { Debug.Assert(null != _root.Find(relativePane)); _root.Add(pane, relativePane, relativeDock); _ArrangeLayout(); _RegisterDropService(pane); } }
/// <summary> /// Find largest pane /// </summary> /// <remarks>largest by hypotenuse</remarks> private void _FindLargestPane(ref Size maxSize, ref DockablePane largestPane) { for (int index = 0; index < _children.Count; ++index) { Composition child = _children[index]; if (child.Type != CompositionType.Terminal) child._FindLargestPane(ref maxSize, ref largestPane); else { Size sz = child._CalculateSpaceSize(); if (_CalculateHypotenuse(maxSize) < _CalculateHypotenuse(sz)) { largestPane = child.AttachedPane; maxSize = sz; } } } }
/// <summary> /// Unregistry pane as drop surface. /// </summary> /// <param name="pane">Pane to unregistry as drop surface.</param> private void _UnregisterDropService(DockablePane pane) { if (pane.IsDragSupported) pane.PaneContent.DockManager.DragPaneServices.Unregister(pane); }
public Composition(Composition parent, DockablePane pane) { _attachedPane = pane; _type = CompositionType.Terminal; _isInited = true; }
/// <summary> /// Remove pane /// </summary> public bool Remove(DockablePane pane) { if (!_isInited) { return(false); } Debug.Assert(CompositionType.Terminal != _type); _CalculateSpaceFactors(); bool isRemoved = false; // find terminal element to deleting Composition terminalComposition2Delete = null; for (int index = 0; index < _children.Count; ++index) { Composition currentComposition = _children[index]; if (CompositionType.Terminal == currentComposition.Type) { if (currentComposition.AttachedPane.Equals(pane)) { terminalComposition2Delete = currentComposition; break; // NOTE: founded } } else { // remove from child composition if (currentComposition.Remove(pane)) { isRemoved = true; break; } } } // remove terminal element if (null != terminalComposition2Delete) { _children.Remove(terminalComposition2Delete); isRemoved = true; if (1 == _children.Count) { // change state to terminal Composition lastChield = _children[0]; _children.Clear(); if (CompositionType.Terminal == lastChield.Type) { _type = CompositionType.Terminal; _attachedPane = lastChield.AttachedPane; } else { _type = lastChield.Type; ICollection <Composition> children = lastChield.Children; foreach (Composition child in children) { _children.Add(child); } } } else { // recalculate new space factors Size sz = _CalculateSpaceSize(); double fullSize = (_type == CompositionType.Horizontal) ? sz.Height : sz.Width; fullSize += SPLITTER_SIZE; double splitterFree = SPLITTER_SIZE / _children.Count; Size freeSize = terminalComposition2Delete._CalculateSpaceSize(); for (int index = 0; index < _children.Count; ++index) { Composition child = _children[index]; Size childSize = child._CalculateSpaceSize(); child.SpaceFactor = (_type == CompositionType.Horizontal) ? ((childSize.Height + freeSize.Height * child.SpaceFactor + splitterFree) / Math.Max(fullSize, 1)) : ((childSize.Width + freeSize.Width * child.SpaceFactor + splitterFree) / Math.Max(fullSize, 1)); } } } else if (isRemoved) { // normalize composition - if child presented as one line for (int index = 0; index < _children.Count; ++index) { Composition currentChild = _children[index]; if (currentChild.Type == _type) { ICollection <Composition> children = currentChild.Children; Debug.Assert(currentChild.Type != CompositionType.Terminal); Debug.Assert(1 < currentChild.Children.Count); Collection <Composition> fromRemoved = new Collection <Composition> (); foreach (Composition child in children) { fromRemoved.Add(child); } _children.Remove(currentChild); _children.InsertRange(index, fromRemoved); } } _CalculateSpaceFactors(); } Debug.Assert(_IsNormalized()); return(isRemoved); }
/// <summary> /// Handles window closing. /// </summary> protected override void OnClosing(CancelEventArgs e) { // Remove code to update window title. if (_dpDescriptor != null) { _dpDescriptor.RemoveValueChanged(_paneHosted.PaneContent, delegate { if (Content != null) Title = ((DockablePane)Content).PaneContent.Title; }); } _paneHosted.StoreFloatingWindowDimensions(this); _paneHosted.PaneContent.DockManager.UnregisterFloatingWnd(this); _paneHosted.FloatingWindow = null; _RemoveTooltip(); Content = null; _paneHosted = null; if (_hwndSource != null) _hwndSource.RemoveHook(_wndProcHandler); _hwndSource = null; base.OnClosing(e); }
public void Add(DockablePane pane, Dock dockType) { if (!_isInited) return; _CalculateSpaceFactors(); _Add(pane, dockType); }
/// <summary> /// Remove pane. /// </summary> /// <param name="pane">Pane for identification.</param> public void Remove(DockablePane pane) { if (null != _root) { Debug.Assert(_root.IsInited); if (null != _root.Find(pane)) { bool isRemoved = false; if (CompositionType.Terminal != _root.Type) isRemoved = _root.Remove(pane); else { if (_root.AttachedPane.Equals(pane)) { _root = null; isRemoved = true; } else { Debug.Assert(false); // not supported } } if (isRemoved) _ArrangeLayout(); _UnregisterDropService(pane); // clearing margins var margin = new Thickness(0); pane.SetValue(FrameworkElement.MarginProperty, margin); } } }
public void Add(DockablePane pane, DockablePane relativePane, Dock relativeDock) { if (!_isInited) return; _CalculateSpaceFactors(); if (CompositionType.Terminal == _type) { if (_attachedPane.Equals(relativePane)) _Add(pane, relativeDock); } else { // find relative terminal element index int relativeIndex = -1; for (int index = 0; index < _children.Count; ++index) { Composition currentComposition = _children[index]; if (CompositionType.Terminal == currentComposition.Type) { if (currentComposition.AttachedPane.Equals(relativePane)) { relativeIndex = index; break; // NOTE: founded } } else currentComposition.Add(pane, relativePane, relativeDock); } // add new item if (-1 != relativeIndex) { if (_DoesAdding2Line(relativeDock)) { // add new item to current linear composition // left\top insert to relative position, other - insert after relive Composition newComposition = new Composition(this, pane); _children[relativeIndex].SpaceFactor *= DEFAULT_SPACE_FACTOR; // new child requared part of relative pane newComposition.SpaceFactor = _children[relativeIndex].SpaceFactor; int insertIndex = ((Dock.Left == relativeDock) || (Dock.Top == relativeDock)) ? relativeIndex : relativeIndex + 1; _children.Insert(insertIndex, newComposition); } else { // add new pane to terminal composition _children[relativeIndex].Add(pane, relativeDock); } } Debug.Assert(_IsNormalized()); } }
/////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// public void AddSpec(DockablePane pane, Dock dockType) { if (!_isInited) return; if (CompositionType.Terminal == _type) _Add(pane, dockType); else { _CalculateSpaceFactors(); // find largest pane Size maxSize = new Size(0, 0); DockablePane largestPane = null; _FindLargestPane(ref maxSize, ref largestPane); if (null == largestPane) _FindLastPane(ref largestPane); Debug.Assert(null != largestPane); bool isVertical = (maxSize.Width <= maxSize.Height); Add(pane, largestPane, (isVertical) ? Dock.Bottom : Dock.Right); } }
public void Add(DockablePane pane, DockablePane relativePane, Dock relativeDock) { if (!_isInited) { return; } _CalculateSpaceFactors(); if (CompositionType.Terminal == _type) { if (_attachedPane.Equals(relativePane)) { _Add(pane, relativeDock); } } else { // find relative terminal element index int relativeIndex = -1; for (int index = 0; index < _children.Count; ++index) { Composition currentComposition = _children[index]; if (CompositionType.Terminal == currentComposition.Type) { if (currentComposition.AttachedPane.Equals(relativePane)) { relativeIndex = index; break; // NOTE: founded } } else { currentComposition.Add(pane, relativePane, relativeDock); } } // add new item if (-1 != relativeIndex) { if (_DoesAdding2Line(relativeDock)) { // add new item to current linear composition // left\top insert to relative position, other - insert after relive Composition newComposition = new Composition(this, pane); _children[relativeIndex].SpaceFactor *= DEFAULT_SPACE_FACTOR; // new child requared part of relative pane newComposition.SpaceFactor = _children[relativeIndex].SpaceFactor; int insertIndex = ((Dock.Left == relativeDock) || (Dock.Top == relativeDock)) ? relativeIndex : relativeIndex + 1; _children.Insert(insertIndex, newComposition); } else { // add new pane to terminal composition _children[relativeIndex].Add(pane, relativeDock); } } Debug.Assert(_IsNormalized()); } }