private void Button_Click(object sender, System.Windows.RoutedEventArgs e) { DockPane pane = new DockPane(); pane.MinHeight = 24; pane.MinWidth = 100; pane.Header = "Solution Explorer"; Grid g = new Grid(); g.Background = Brushes.White; TextBlock text = new TextBlock(); text.Text = "Some content - " + (i + 1); g.Children.Add(text); pane.Content = g; Dock direction = Dock.Top; if (i % 4 == 1) direction = Dock.Right; else if (i % 4 == 2) direction = Dock.Left; else if (i % 4 == 3) direction = Dock.Bottom; i++; pane.Tag = i; pane.MouseEnter += (a, b) => { var x = WindowsManager; System.Diagnostics.Debug.WriteLine((a as DockPane).Tag); }; WindowsManager.AddPinnedWindow(pane, direction); }
/// <summary> /// Called when dock pane drag has started /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param> private void OnPaneDragStarted(object sender, MouseButtonEventArgs e) { ActiveWindowsManager = this; DraggedPane = sender as DockPane; _dockPaneDragging = true; _dragStartPointOffset = (e != null) ? e.GetPosition(DraggedPane) : Mouse.GetPosition(this); // Show the visibility DockingPanel.Visibility = Visibility.Visible; RemoveCondencedDockPanel(DraggedPane.CondencedDockPanel); RemovePinnedWindow(DraggedPane); // Dim the dragged window DraggedPane.Opacity = 0.25; if (DraggedPane.DockPaneState != DockPaneState.Floating) { IgnoreStateChangeForDockPane(DraggedPane); Point panePosition = e != null ? e.GetPosition(this) : Mouse.GetPosition(this); Canvas.SetTop(DraggedPane, panePosition.Y); Canvas.SetLeft(DraggedPane, panePosition.X); FloatingPanel.Children.Add(DraggedPane); MonitorStateChangeForDockPane(DraggedPane); // Set this last since until the DraggedPane is not added // to the FloatingPanel it will not be in the visual tree // and hence things like adorner layer will not be present DraggedPane.DockPaneState = DockPaneState.Floating; } DraggedPane.IsHitTestVisible = false; // This is necessary or when tab items are floated again // mouse up event never fires Mouse.Capture(this, CaptureMode.SubTree); }
/// <summary> /// Removes the pinned window /// </summary> /// <param name="pane">Dock pane</param> private void RemovePinnedWindow(DockPane pane) { DockPanel logicalParentDockPanel = LogicalTreeHelper.GetParent(pane) as DockPanel; if (logicalParentDockPanel == null) { return; } int indexOfPane = logicalParentDockPanel.Children.IndexOf(pane); GridSplitter splitter = logicalParentDockPanel.Children[indexOfPane + 1] as GridSplitter; logicalParentDockPanel.Children.Remove(pane); logicalParentDockPanel.Children.Remove(splitter); }
/// <summary> /// Adds the floating window. /// </summary> /// <param name="pane">The pane.</param> public void AddFloatingWindow(DockPane pane) { DetachDockPaneEvents(pane); AttachDockPaneEvents(pane); if (Mouse.LeftButton == MouseButtonState.Pressed) { // Setting state to non-floating so that OnPaneDragStared can // set it to floating and execute related effects pane.DockPaneState = DockPaneState.Content; OnPaneDragStarted(pane, null); } else { pane.DockPaneState = DockPaneState.Floating; FloatingPanel.Children.Add(pane); MonitorStateChangeForDockPane(pane); } }
/// <summary> /// Monitors the state change for dock pane and ensures that /// only one instance of pane is monitored to prevent redundent events /// </summary> /// <param name="pane">Pane to monitor</param> private void MonitorStateChangeForDockPane(DockPane pane) { if ((pane != null) && (!_dockPaneStateMonitorList.Contains(pane))) { _dockPaneStateMonitorList.Add(pane); } }
/// <summary> /// Splits and adds document to the split window /// </summary> /// <param name="pane">The pane</param> /// <param name="dockPoint">The dock point</param> private void SplitAndAddDocument(DockPane pane, ContentDockPoint dockPoint) { DocumentContainer container = new DocumentContainer(); Grid splitGrid = null; switch (dockPoint) { case ContentDockPoint.Top: splitGrid = SplitVertically(false); Grid.SetRow(container, 0); break; case ContentDockPoint.Left: splitGrid = SplitHorizontally(false); Grid.SetColumn(container, 0); break; case ContentDockPoint.Right: splitGrid = SplitHorizontally(true); Grid.SetColumn(container, 2); break; case ContentDockPoint.Bottom: splitGrid = SplitVertically(true); Grid.SetRow(container, 2); break; case ContentDockPoint.Content: AddDocument(pane); return; default: break; } container.AddDocument(pane); splitGrid.Children.Add(container); }
/// <summary> /// Reads the dock pane from the xml element /// </summary> /// <param name="dockPaneElement">The dock pane xml element.</param> /// <returns>Newly constructed DockPane</returns> private DockPane ReadDockPane(XmlElement dockPaneElement) { DockPane dockPane = new DockPane(); _dockPaneReader(dockPane, dockPaneElement.GetAttribute("Data")); double height = double.Parse(dockPaneElement.GetAttribute("Height")); dockPane.Height = height; double width = double.Parse(dockPaneElement.GetAttribute("Width")); dockPane.Width = width; XmlAttribute topAttribute = dockPaneElement.Attributes.GetNamedItem("Top") as XmlAttribute; if (topAttribute != null) { Canvas.SetTop(dockPane, double.Parse(topAttribute.Value)); } XmlAttribute leftAttribute = dockPaneElement.Attributes.GetNamedItem("Left") as XmlAttribute; if (leftAttribute != null) { Canvas.SetLeft(dockPane, double.Parse(leftAttribute.Value)); } return dockPane; }
/// <summary> /// Adds the pinned window to top of content /// </summary> /// <param name="pane">Pane to add</param> private void AddPinnedWindowToTop(DockPane pane) { DockPanel.SetDock(pane, Dock.Top); pane.Width = double.NaN; TopPinnedWindows.Children.Add(pane); GridSplitter sizingThumb = new GridSplitter(); sizingThumb.Height = 4; sizingThumb.HorizontalAlignment = HorizontalAlignment.Stretch; sizingThumb.Background = Brushes.Transparent; sizingThumb.Cursor = Cursors.SizeNS; DockPanel.SetDock(sizingThumb, Dock.Top); TopPinnedWindows.Children.Add(sizingThumb); sizingThumb.DragDelta += (a, b) => { if (pane.Height.Equals(double.NaN)) { pane.Height = pane.DesiredSize.Height; } if (pane.Height + b.VerticalChange <= 0) { return; } pane.Height += b.VerticalChange; }; }
/// <summary> /// Attaches the events to dock pane /// </summary> /// <param name="pane">Dock pane</param> private void AttachDockPaneEvents(DockPane pane) { pane.Close += OnDockPaneClosed; MonitorStateChangeForDockPane(pane); pane.HeaderDrag += OnPaneDragStarted; }
/// <summary> /// Adds the pinned window without manipulating events /// </summary> /// <param name="pane">The pane.</param> /// <param name="dock">The dock.</param> private void AddPinnedWindowInner(DockPane pane, Dock dock) { switch (dock) { case Dock.Bottom: AddPinnedWindowToBottom(pane); break; case Dock.Left: AddPinnedWindowToLeft(pane); break; case Dock.Right: AddPinnedWindowToRight(pane); break; case Dock.Top: AddPinnedWindowToTop(pane); break; default: break; } pane.DockPaneState = DockPaneState.Docked; }
/// <summary> /// Adds the pinned window to right of content /// </summary> /// <param name="pane">Pane to add</param> private void AddPinnedWindowToRight(DockPane pane) { DockPanel.SetDock(pane, Dock.Right); pane.Height = double.NaN; RightPinnedWindows.Children.Add(pane); GridSplitter sizingThumb = new GridSplitter(); sizingThumb.Width = 4; sizingThumb.Background = Brushes.Transparent; sizingThumb.Cursor = Cursors.SizeWE; DockPanel.SetDock(sizingThumb, Dock.Right); RightPinnedWindows.Children.Add(sizingThumb); sizingThumb.DragDelta += (a, b) => { if (pane.Width.Equals(double.NaN)) { pane.Width = pane.DesiredSize.Width; } if (pane.Width - b.HorizontalChange <= 0) { return; } pane.Width -= b.HorizontalChange; }; }
/// <summary> /// Invoked when an unhandled <see cref="E:System.Windows.Input.Mouse.MouseUp"/> routed event /// reaches an element in its route that is derived from this class. Implement this method to add class /// handling for this event. /// </summary> /// <param name="e">The <see cref="T:System.Windows.Input.MouseButtonEventArgs"/> that contains the event data. /// The event data reports that the mouse button was released.</param> protected override void OnMouseUp(MouseButtonEventArgs e) { base.OnMouseUp(e); if (!_dockPaneDragging) { return; } ReleaseMouseCapture(); DraggedPane.Opacity = 1; _dockPaneDragging = false; DockingPanel.Visibility = Visibility.Collapsed; DraggedPane.IsHitTestVisible = true; DraggedPane = null; ActiveWindowsManager = null; }
/// <summary> /// Removes the dock pane from windows manager alltogether and unsubscribes from all events /// </summary> /// <param name="pane">The pane.</param> public void RemoveDockPane(DockPane pane) { DetachDockPaneEvents(pane); RemoveCondencedDockPanel(DraggedPane.CondencedDockPanel); RemovePinnedWindow(DraggedPane); FloatingPanel.Children.Remove(pane); }
/// <summary> /// Adds the dock pane. /// </summary> /// <param name="pane">The pane.</param> /// <param name="dock">The dock.</param> public void AddPinnedWindow(DockPane pane, Dock dock) { AddPinnedWindowInner(pane, dock); DetachDockPaneEvents(pane); AttachDockPaneEvents(pane); }
/// <summary> /// Adds the dock pane to the document container via splitting and docks it to the specified dock point /// </summary> /// <param name="pane">Pane to add</param> /// <param name="dockPoint">The dock point for content</param> public void AddDockPane(DockPane pane, ContentDockPoint dockPoint) { DocumentContainer targetContainer; if (CanMergeContent(dockPoint, out targetContainer)) { targetContainer.AddDocument(pane); } else { SplitAndAddDocument(pane, dockPoint); } }
/// <summary> /// Condences the dock panel /// </summary> /// <param name="pane">The pane.</param> /// <param name="dock">The dock.</param> private void CondenceDockPanel(DockPane pane, Dock dock) { FrameworkElement condencedDockPanel = pane.CondencedDockPanel; condencedDockPanel.LayoutTransform = (dock == Dock.Left) || (dock == Dock.Right) ? new RotateTransform(90) : null; switch (dock) { case Dock.Bottom: BottomWindowHeaders.Children.Add(condencedDockPanel); break; case Dock.Left: LeftWindowHeaders.Children.Add(condencedDockPanel); break; case Dock.Right: RightWindowHeaders.Children.Add(condencedDockPanel); break; case Dock.Top: TopWindowHeaders.Children.Add(condencedDockPanel); break; default: break; } DockPanel.SetDock(pane, dock); DetachEvents(condencedDockPanel); pane.DockPaneState = DockPaneState.AutoHide; AttachEvents(condencedDockPanel); }
/// <summary> /// Adds the dock panel as a document /// </summary> /// <param name="pane">The pane</param> public void AddDocument(DockPane pane) { DocumentContent documentContent = new DocumentContent(pane, RemoveDocumentCommand); pane.DockPaneState = DockPaneState.Content; Documents.Add(documentContent); if (DocumentsTab != null) { DocumentsTab.SelectedItem = documentContent; } State = DocumentContainerState.ContainsDocuments; }
/// <summary> /// Detaches the events from the dock pane /// </summary> /// <param name="pane">The pane.</param> private void DetachDockPaneEvents(DockPane pane) { pane.Close -= OnDockPaneClosed; IgnoreStateChangeForDockPane(pane); pane.HeaderDrag -= OnPaneDragStarted; }
/// <summary> /// Reads the documents for current document container /// </summary> /// <param name="documentContainer">The document container.</param> protected override void ReadDocuments(DocumentContainer documentContainer) { ValidateStackNotEmpty(); XmlElement documentContainerElement = _elementStack.Peek(); Validate.Assert<InvalidOperationException>(documentContainerElement.Name == "DocumentContainer"); foreach (XmlElement documentElement in documentContainerElement.SelectNodes(@"Document").OfType<XmlElement>()) { DockPane dockPane = new DockPane(); _dockPaneReader(dockPane, documentElement.GetAttribute("Data")); documentContainer.AddDocument(dockPane); } }
/// <summary> /// Ignores the state change for dock pane. /// </summary> /// <param name="pane">Dock pane to ignore state changes from</param> private void IgnoreStateChangeForDockPane(DockPane pane) { if (pane != null) { _dockPaneStateMonitorList.Remove(pane); } }
/// <summary> /// Called when dock pane state has changed /// </summary> /// <param name="pane">Dock pane.</param> /// <param name="state">New state (may not be current yet)</param> private static void OnDockPaneStateChange(DockPane pane, DockPaneState state) { switch (state) { case DockPaneState.Docked: pane.ClearAdornerLayer(); if (pane.PinButton != null) { pane.PinButton.Visibility = Visibility.Visible; pane.PinButton.IsChecked = false; } break; case DockPaneState.AutoHide: pane.ClearAdornerLayer(); if (pane.PinButton != null) { pane.PinButton.Visibility = Visibility.Visible; pane.PinButton.IsChecked = true; } break; case DockPaneState.Floating: pane.AddResizingAdorner(); if (pane.PinButton != null) { pane.PinButton.Visibility = Visibility.Collapsed; } break; case DockPaneState.Content: pane.ClearAdornerLayer(); break; default: break; } }
/// <summary> /// Adds the window in auto hide fashion /// </summary> /// <param name="pane">The pane.</param> /// <param name="dock">The dock.</param> public void AddAutoHideWindow(DockPane pane, Dock dock) { CondenceDockPanel(pane, dock); DetachDockPaneEvents(pane); AttachDockPaneEvents(pane); }