/// <summary>Get the bounds of a dock site in parent (DockContainer or containing Branch) space</summary> public Rect ChildBounds(EDockSite location) { var display_rect = new Rect(RenderSize); display_rect.Width = Math.Max(0, display_rect.Width); display_rect.Height = Math.Max(0, display_rect.Height); return(DockContainer.DockSiteBounds(location, display_rect, DockedMask, DockSizes)); }
/// <summary>Add branches to the tree until 'rest' is empty.</summary> private Branch GrowBranches(IEnumerable <EDockSite> address, out EDockSite last_ds) { var ds = address.First(); var rest = address.Skip(1); Debug.Assert(ds >= EDockSite.Centre && ds < EDockSite.None, "Invalid dock site"); // Note: When rest is empty, the site at 'ds' does not have a branch added. // This is deliberate so that dock addresses (arrays of EDockSite) can be // used to grow the tree to the point where a dock pane should be added. if (!rest.Any()) { // If we've reached the end of the dock address, but there are still branches // keep going down the centre dock site until a null or dock pane is reached var b = this; for (; b.Descendants[ds].Item is Branch cb; b = cb, ds = EDockSite.Centre) { } Debug.Assert(ValidateTree()); last_ds = ds; return(b); } // No child at 'ds' add a branch if (Descendants[ds].Item == null) { var new_branch = new Branch(DockContainer, ds == EDockSite.Centre ? DockSizeData.Quarters : DockSizeData.Halves); Descendants[ds].Item = new_branch; return(new_branch.GrowBranches(rest, out last_ds)); } // If there's a dock pane at 'ds' swap it with a branch // containing that dock pane as the centre child if (Descendants[ds].Item is DockPane) { // Detach from the current location var existing = Descendants[ds].Item; Descendants[ds].Item = null; // Create a new branch with 'existing' in the centre var new_branch = new Branch(DockContainer, DockSizeData.Halves); new_branch.Descendants[EDockSite.Centre].Item = existing; // Replace in the current location Descendants[ds].Item = new_branch; return(new_branch.GrowBranches(rest, out last_ds)); } else { // Existing branch, recursive call into it var branch = (Branch?)Descendants[ds].Item ?? throw new Exception("Branch expected"); return(branch.GrowBranches(rest, out last_ds)); } }
public void ChildSize(EDockSite location, double value, EDockResizeMode resize_mode) { if (value < 0 || double.IsNaN(value)) { throw new Exception($"Invalid child size ({value}) for {location}"); } if (RenderSize.Width == 0 || RenderSize.Height == 0) { throw new Exception($"Invalid size for this branch, can't determine dock size for {location}"); } DockSizes.SetSize(location, DisplayRectangle, value, resize_mode); }
/// <summary>Convert an 'EDockSite' to a DockPanel dock location</summary> public static Dock ToDock(this EDockSite docksite) { switch (docksite) { default: throw new Exception($"Unknown dock site value {docksite}"); case EDockSite.Centre: case EDockSite.None: throw new Exception($"No equivalent of {docksite} for DockPanel.Dock values"); case EDockSite.Left: return(Dock.Left); case EDockSite.Top: return(Dock.Top); case EDockSite.Right: return(Dock.Right); case EDockSite.Bottom: return(Dock.Bottom); } }
/// <summary>True if this dock site is Top or Bottom</summary> public static bool IsHorizontal(this EDockSite ds) { return(ds == EDockSite.Top || ds == EDockSite.Bottom); }
/// <summary>True if this dock site is Left or Right</summary> public static bool IsVertical(this EDockSite ds) { return(ds == EDockSite.Left || ds == EDockSite.Right); }
/// <summary>True if this dock site is a edge</summary> public static bool IsEdge(this EDockSite ds) { return(ds == EDockSite.Left || ds == EDockSite.Top || ds == EDockSite.Right || ds == EDockSite.Bottom); }
/// <summary>Get/Set the size for a dock site in this branch (in pixels)</summary> public double ChildSize(EDockSite location) { return(DockSizes.GetSize(location, DisplayRectangle, DockedMask)); }
public DockPane DockPane(EDockSite ds) { return(DockPane(new[] { ds })); }
// Notes: // - An auto hide panel is a panel that pops out from the edges of the dock container. // - It is basically a root branch with a single centre dock pane. The tab strip from the // dock pane is used for the auto-hide tab strip displayed around the edges of the control. // Other behaviours: // - Click pin on the pane only pins the active content // - Clicking a tab makes that dockable the active content // - 'Root' only uses the centre dock site public AutoHidePanel(DockContainer dc, EDockSite ds) { InitializeComponent(); Visibility = Visibility.Collapsed; Canvas.SetZIndex(this, 1); DockContainer = dc; DockSite = ds; PoppedOut = false; var splitter_size = 5.0; var splitter = new GridSplitter { HorizontalAlignment = HorizontalAlignment.Stretch, VerticalAlignment = VerticalAlignment.Stretch, Background = SystemColors.ControlBrush, BorderBrush = new SolidColorBrush(Color.FromRgb(0xc0, 0xc0, 0xc0)), BorderThickness = DockSite.IsVertical() ? new Thickness(1, 0, 1, 0) : new Thickness(0, 1, 0, 1), }; // Create a grid to contain the root branch and the splitter switch (DockSite) { default: throw new Exception($"Auto hide panels cannot be docked to {ds}"); case EDockSite.Left: case EDockSite.Right: { // Vertical auto hide panel ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(DockSite == EDockSite.Left ? 1 : 2, GridUnitType.Star), MinWidth = 10 }); ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(0, GridUnitType.Auto) }); ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(DockSite == EDockSite.Right ? 1 : 2, GridUnitType.Star), MinWidth = 10 }); // Add the root branch to the appropriate column Root = Children.Add2(new Branch(dc, DockSizeData.Quarters)); Grid.SetColumn(Root, DockSite == EDockSite.Left ? 0 : 2); // Add the splitter to the centre column splitter.Width = splitter_size; Children.Add2(splitter); Grid.SetColumn(splitter, 1); break; } case EDockSite.Top: case EDockSite.Bottom: { // Horizontal auto hide panel RowDefinitions.Add(new RowDefinition { Height = new GridLength(DockSite == EDockSite.Top ? 1 : 2, GridUnitType.Star), MinHeight = 10 }); RowDefinitions.Add(new RowDefinition { Height = new GridLength(0, GridUnitType.Auto) }); RowDefinitions.Add(new RowDefinition { Height = new GridLength(DockSite == EDockSite.Bottom ? 1 : 2, GridUnitType.Star), MinHeight = 10 }); // Add the root branch to the appropriate row Root = Children.Add2(new Branch(dc, DockSizeData.Quarters)); Grid.SetRow(Root, DockSite == EDockSite.Top ? 0 : 2); // Add the splitter to the centre row splitter.Height = splitter_size; Children.Add2(splitter); Grid.SetRow(splitter, 1); break; } } // Remove the tab strip from the dock pane child so we can use // it as the auto hide tab strip for this auto hide panel TabStrip = DockPane.TabStrip; TabStrip.Detach(); TabStrip.AHPanel = this; }