/// <summary> /// Anchor a dockable pane (<see cref="DockablePane"/>) to a border of a document pane /// </summary> /// <param name="paneToAnchor">Pane to anchor</param> /// <param name="relativePane">Pane relative</param> /// <param name="anchor"></param> public void Anchor(DockablePane paneToAnchor, DocumentPane relativePane, AnchorStyle anchor) { //ensure that content property is not empty EnsureContentNotEmpty(); if (anchor == AnchorStyle.None) anchor = AnchorStyle.Right; //get a reference to the resizingpanel container of relativePane ResizingPanel relativePaneContainer = LogicalTreeHelper.GetParent(relativePane) as ResizingPanel; DocumentPaneResizingPanel relativeDocumentPaneContainer = relativePane.GetParentDocumentPaneResizingPanel(); Orientation requestedOrientation = (anchor == AnchorStyle.Bottom || anchor == AnchorStyle.Top) ? Orientation.Vertical : Orientation.Horizontal; if (relativePaneContainer == null) { Debug.Assert(relativePane.Parent == this); this.Content = null; relativeDocumentPaneContainer = new DocumentPaneResizingPanel(); relativeDocumentPaneContainer.Children.Add(relativePane); relativePaneContainer = new ResizingPanel(); relativePaneContainer.Orientation = requestedOrientation; this.Content = relativePaneContainer; relativePaneContainer.Children.Add(relativeDocumentPaneContainer); } if (relativeDocumentPaneContainer == null) { relativeDocumentPaneContainer = new DocumentPaneResizingPanel(); relativeDocumentPaneContainer.Orientation = requestedOrientation; int indexOfPaneToReplace = relativePaneContainer.Children.IndexOf(relativePane); relativePaneContainer.Children.RemoveAt(indexOfPaneToReplace); relativeDocumentPaneContainer.Children.Add(relativePane); relativePaneContainer.Children.Insert(indexOfPaneToReplace, relativeDocumentPaneContainer); } relativePaneContainer = LogicalTreeHelper.GetParent(relativeDocumentPaneContainer) as ResizingPanel; //Debug.Assert(relativePaneContainer is DocumentPaneResizingPanel, "By now we can't have a pane without a resizing panel containing it"); if (relativePaneContainer == null) { Debug.Assert(relativeDocumentPaneContainer.Parent == this); this.Content = null; relativePaneContainer = new ResizingPanel(); relativePaneContainer.Orientation = requestedOrientation; this.Content = relativePaneContainer; relativePaneContainer.Children.Add(relativeDocumentPaneContainer); } #region Create and setup container panel if (relativePaneContainer != null) { //check if orientation is right if (relativePaneContainer.Orientation != requestedOrientation) { //if the existing panel is not oriented as we want //create a new one ResizingPanel newPanel = new ResizingPanel(); newPanel.Orientation = requestedOrientation; if (newPanel.Orientation == Orientation.Horizontal) ResizingPanel.SetResizeHeight(newPanel, ResizingPanel.GetResizeHeight(relativePane)); else ResizingPanel.SetResizeWidth(newPanel, ResizingPanel.GetResizeWidth(relativePane)); //replace relative pane in its' container panel //with this new panel int indexofRelativePane = relativePaneContainer.Children.IndexOf(relativeDocumentPaneContainer); relativePaneContainer.Children.Remove(relativeDocumentPaneContainer); relativePaneContainer.Children.Insert(indexofRelativePane, newPanel); //now we have a panel correctly placed in the tree newPanel.Children.Add(relativeDocumentPaneContainer); //use InsertChildRelativeTo function to add a resizingsplitter between //the two children newPanel.InsertChildRelativeTo( paneToAnchor, relativeDocumentPaneContainer, anchor == AnchorStyle.Right || anchor == AnchorStyle.Bottom); } else { if (anchor == AnchorStyle.Left || anchor == AnchorStyle.Top) { //add new child before first (prepend) relativePaneContainer.InsertChildRelativeTo(paneToAnchor, relativeDocumentPaneContainer, false); } else { //add new child after last (append) relativePaneContainer.InsertChildRelativeTo(paneToAnchor, relativeDocumentPaneContainer, true); } } } relativePaneContainer.InvalidateMeasure(); #endregion if (anchor == AnchorStyle.Left || anchor == AnchorStyle.Right) { double w = Math.Min( ResizingPanel.GetEffectiveSize(relativePane).Width / 2.0, ResizingPanel.GetEffectiveSize(paneToAnchor).Width); ResizingPanel.SetResizeWidth(paneToAnchor, new GridLength(w, GridUnitType.Pixel)); ResizingPanel.SetResizeHeight(paneToAnchor, new GridLength(1.0, GridUnitType.Star)); } else { double h = Math.Min( ResizingPanel.GetEffectiveSize(relativePane).Height / 2.0, ResizingPanel.GetEffectiveSize(paneToAnchor).Height); ResizingPanel.SetResizeWidth(paneToAnchor, new GridLength(1.0, GridUnitType.Star)); ResizingPanel.SetResizeHeight(paneToAnchor, new GridLength(h, GridUnitType.Pixel)); } //refresh contents state foreach (DockableContent draggedContent in paneToAnchor.Items) { draggedContent.SetStateToDock(); } //than set the new anchor style for the pane paneToAnchor.Anchor = anchor; //paneToAnchor.Focus(); }
/// <summary> /// Anchor a document pane (<see cref="DocumentPane"/>) to a border of an other document pane /// </summary> /// <param name="paneToAnchor">Pane to anchor</param> /// <param name="relativePane">Pane relative</param> /// <param name="anchor"></param> public void Anchor(DocumentPane paneToAnchor, DocumentPane relativePane, AnchorStyle anchor) { //ensure that content property is not empty EnsureContentNotEmpty(); if (anchor == AnchorStyle.None) anchor = AnchorStyle.Right; //get a reference to the resizingpanel container of relativePane ResizingPanel relativePaneContainer = LogicalTreeHelper.GetParent(relativePane) as ResizingPanel; DocumentPaneResizingPanel relativeDocumentPaneContainer = relativePane.GetParentDocumentPaneResizingPanel(); Orientation requestedOrientation = (anchor == AnchorStyle.Bottom || anchor == AnchorStyle.Top) ? Orientation.Vertical : Orientation.Horizontal; if (relativePaneContainer == null) { Debug.Assert(relativePane.Parent == this); relativeDocumentPaneContainer = new DocumentPaneResizingPanel(); relativePaneContainer = relativeDocumentPaneContainer; relativeDocumentPaneContainer.Orientation = requestedOrientation; this.Content = relativePaneContainer; relativePaneContainer.Children.Add(relativePane); } if (relativeDocumentPaneContainer == null) { relativeDocumentPaneContainer = new DocumentPaneResizingPanel(); relativeDocumentPaneContainer.Orientation = requestedOrientation; int indexOfPaneToReplace = relativePaneContainer.Children.IndexOf(relativePane); relativePaneContainer.Children.RemoveAt(indexOfPaneToReplace); relativeDocumentPaneContainer.Children.Add(relativePane); relativePaneContainer.Children.Insert(indexOfPaneToReplace, relativeDocumentPaneContainer); relativePaneContainer = relativeDocumentPaneContainer; } Debug.Assert(relativePaneContainer != null, "By now we can't have a pane without a resizing panel containing it"); #region Create and setup container panel if (relativePaneContainer != null) { //check if orientation is right if (relativePaneContainer.Orientation != requestedOrientation) { //if the existing panel is not oriented as we want //create a new one DocumentPaneResizingPanel newPanel = new DocumentPaneResizingPanel(); newPanel.Orientation = requestedOrientation; //replace relative pane in its' container panel //with this new panel int indexofRelativePane = relativePaneContainer.Children.IndexOf(relativePane); relativePaneContainer.Children.Remove(relativePane); relativePaneContainer.Children.Insert(indexofRelativePane, newPanel); //now we have a panel correctly placed in the tree newPanel.Children.Add(relativePane); //use InsertChildRelativeTo function to add a resizingsplitter between //the two children newPanel.InsertChildRelativeTo( paneToAnchor, relativePane, anchor == AnchorStyle.Right || anchor == AnchorStyle.Bottom); relativePaneContainer = newPanel; } else { if (anchor == AnchorStyle.Left || anchor == AnchorStyle.Top) { //add new child before first (prepend) relativePaneContainer.InsertChildRelativeTo(paneToAnchor, relativePane, false); } else { //add new child after last (append) relativePaneContainer.InsertChildRelativeTo(paneToAnchor, relativePane, true); } //if (relativePaneContainer.Orientation == Orientation.Horizontal) //{ // Size desideredSize = ResizingPanel.GetEffectiveSize(paneToAnchor); // double approxStarForNewPane = desideredSize.Width / relativePaneContainer.ActualWidth; // approxStarForNewPane = Math.Min(approxStarForNewPane, 1.0); // paneToAnchor.SetValue(ResizingPanel.ResizeWidthProperty, new GridLength(approxStarForNewPane, GridUnitType.Star)); //} } relativePaneContainer.InvalidateMeasure(); } #endregion //paneToAnchor.Focus(); //(paneToAnchor.SelectedItem as ManagedContent).Activate(); //if (paneToAnchor.SelectedItem is DocumentContent) // ActiveDocument = paneToAnchor.SelectedItem as DocumentContent; paneToAnchor.SelectedIndex = 0; }
ResizingPanel RestoreResizingPanel(XmlElement mainElement, DockableContent[] actualContents, DocumentContent[] actualDocuments, ref DocumentPane mainDocumentPane) { ResizingPanel panel = null; if (mainElement.Name == "DocumentPaneResizingPanel") panel = new DocumentPaneResizingPanel(); else panel = new ResizingPanel(); if (mainElement.HasAttribute("Orientation")) panel.Orientation = (Orientation)Enum.Parse(typeof(Orientation), mainElement.GetAttribute("Orientation")); if (mainElement.HasAttribute("ResizeWidth")) ResizingPanel.SetResizeWidth(panel, (GridLength)GLConverter.ConvertFromInvariantString(mainElement.GetAttribute("ResizeWidth"))); if (mainElement.HasAttribute("ResizeHeight")) ResizingPanel.SetResizeHeight(panel, (GridLength)GLConverter.ConvertFromInvariantString(mainElement.GetAttribute("ResizeHeight"))); if (mainElement.HasAttribute("EffectiveSize")) ResizingPanel.SetEffectiveSize(panel, (Size)(new SizeConverter()).ConvertFromInvariantString(mainElement.GetAttribute("EffectiveSize"))); foreach (XmlElement childElement in mainElement.ChildNodes) { if (childElement.Name == "ResizingPanel" || childElement.Name == "DocumentPaneResizingPanel") { var childPanel = RestoreResizingPanel(childElement, actualContents, actualDocuments, ref mainDocumentPane); if (childPanel.Children.Count > 0) { panel.Children.Add(childPanel); } else { Debug.WriteLine("Found empty ResizingPanel in stored layout, it will be discarded."); } } #region Restore DockablePane else if (childElement.Name == "DockablePane") { var pane = RestoreDockablePaneLayout(childElement, actualContents, actualDocuments); //restore dockable panes even if no contents are inside (an hidden content could refer this pane in SaveStateAndPosition) panel.Children.Add(pane); } #endregion #region Restore Contents inside a DocumentPane else if (childElement.Name == "DocumentPane") { var documentPane = RestoreDocumentPaneLayout(childElement, actualContents, actualDocuments); bool isMainDocumentPane = false; if (childElement.HasAttribute("IsMain")) isMainDocumentPane = XmlConvert.ToBoolean(childElement.GetAttribute("IsMain")); if (documentPane.Items.Count > 0 || isMainDocumentPane) panel.Children.Add(documentPane); if (isMainDocumentPane) { if (mainDocumentPane != null) throw new InvalidOperationException("Main document pane is set more than one time"); mainDocumentPane = documentPane; } } #endregion } return panel; }