/////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// /// <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> /// Deserialize layout. /// </summary> /// <param name="manager">Dock manager for initing objects.</param> /// <param name="rootNode">Node to parse.</param> /// <param name="handlerObject">Delegate used to get user defined dockable contents.</param> public void Deserialize(DockManager manager, XmlNode rootNode, GetContentFromTypeString handlerObject) { if (null != _root) { Debug.Assert(_root.Type == CompositionType.Terminal); _root.AttachedPane.Close(); _root = null; } if (0 == rootNode.ChildNodes.Count) _root = null; else { _root = new Composition(); _root.Deserialize(manager, rootNode.ChildNodes[0], handlerObject); _ArrangeLayout(); } }
/// <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 line composition /// </summary> private void _CreateLineComposition(Composition first, Composition second, Dock dockType) { _attachedPane = null; _type = _GetCompositionTypeByDock(dockType); _children.Add(first); _InsertElement2Line(second , dockType); }
/// <summary> /// Insert new composition element by dock /// </summary> private void _InsertElement2Line(Composition newElement, Dock dockType) { if ((Dock.Left == dockType) || (Dock.Top == dockType)) _children.Insert(0, newElement); else if ((Dock.Right == dockType) || (Dock.Bottom == dockType)) _children.Add(newElement); else { Debug.Assert(false); // NOTE: not supported } }
/// <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> /// Do copy of this composition /// </summary> private Composition _CreateCopy() { Composition obj = new Composition(); obj._children.AddRange(this._children); obj._type = this._type; obj._attachedPane = this._attachedPane; obj._isInited = this._isInited; return obj; }
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()); } }
/// <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; }
public Composition(Composition parent, DockablePane pane) { _attachedPane = pane; _type = CompositionType.Terminal; _isInited = true; }
public Composition(Composition parent, Composition first, Composition second, Dock dockType) { _CreateLineComposition(first, second, dockType); _isInited = true; }
/// <summary> /// Calculation space factors /// </summary> private void _CalculateSpaceFactors() { Size fullSize = _CalculateSpaceSize(); if ((fullSize.Height <= 0.0) && (fullSize.Height == fullSize.Width)) { return; // NOTE: exit } // minimal factor - page have min size double minFactor = (_type == CompositionType.Horizontal)? (DockablePane.MIN_PANE_SIZE / Math.Max(fullSize.Height, 1)) : (DockablePane.MIN_PANE_SIZE / Math.Max(fullSize.Width, 1)); double increaseFactorValue = 0; // pages with min size increase with this value for (int index = 0; index < _children.Count; ++index) { Composition child = _children[index]; Size childSize = child._CalculateSpaceSize(); double newScale = (_type == CompositionType.Horizontal) ? (childSize.Height / Math.Max(fullSize.Height, 1)) : (childSize.Width / Math.Max(fullSize.Width, 1)); // reset tinkle - 1% if (SPACE_FACTOR_TINKLE < Math.Abs(child.SpaceFactor - newScale)) { child.SpaceFactor = newScale; } if (child.SpaceFactor < minFactor) { increaseFactorValue += minFactor - child.SpaceFactor; child.SpaceFactor = minFactor; } } // normalize factors - sum probably SPACE_FACTOR_FULL double sumFactor = 0.0; if (0 < increaseFactorValue) { // find count of pages for decreasing int decreaseCount = 0; for (int index = 0; index < _children.Count; ++index) { if (minFactor + increaseFactorValue < _children[index].SpaceFactor) { ++decreaseCount; } } // decrease big pages double decreaseFactor = increaseFactorValue / decreaseCount; for (int index = 0; index < _children.Count; ++index) { Composition child = _children[index]; if (minFactor + decreaseFactor < child.SpaceFactor) { child.SpaceFactor -= decreaseFactor; } sumFactor += child.SpaceFactor; } } else { // callculate sum factors for (int index = 0; index < _children.Count; ++index) { sumFactor += _children[index].SpaceFactor; } } _NormalizeSpaceFactors(sumFactor); }
/// <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 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()); } }