/// <summary> /// Prepares a panel for the UI. Override for hooking custom events. /// </summary> /// <param name="panel">The panel to prepare.</param> protected virtual void PreparePanel(DragDockPanel panel) { // Hook up panel events panel.DragStarted += new DragEventHander(DragDockPanel_DragStarted); panel.DragFinished += new DragEventHander(DragDockPanel_DragFinished); panel.DragMoved += new DragEventHander(DragDockPanel_DragMoved); panel.Maximized += new EventHandler(DragDockPanel_Maximized); panel.Restored += new EventHandler(DragDockPanel_Restored); if (panel.PanelState == PanelState.Maximized) { maximizedPanel = panel; foreach (DragDockPanel dragDockPanel in panels) { if (panel != dragDockPanel) { dragDockPanel.Minimize(); } } } }
/// <summary> /// Maximises a panel. /// </summary> /// <param name="sender">the panel to maximise.</param> /// <param name="e">Event args.</param> private void DragDockPanel_Maximized(object sender, EventArgs e) { DragDockPanel maximizedPanel = sender as DragDockPanel; // Store max'ed panel this.maximizedPanel = maximizedPanel; // Loop through children to disable dragging foreach (UIElement child in panels) { DragDockPanel panel = child as DragDockPanel; panel.DraggingEnabled = false; if (panel != maximizedPanel) { panel.Minimize(); } } // Update sizes and layout AnimatePanelSizes(); AnimatePanelLayout(); }
/// <summary> /// Keeps a reference to the dragging panel. /// </summary> /// <param name="sender">The dragging panel.</param> /// <param name="args">Drag event args.</param> private void DragDockPanel_DragStarted(object sender, DragEventArgs args) { DragDockPanel panel = sender as DragDockPanel; // Keep reference to dragging panel draggingPanel = panel; }
/// <summary> /// Drops the dragging panel. /// </summary> /// <param name="sender">The dragging panel.</param> /// <param name="args">Drag event args.</param> private void DragDockPanel_DragFinished(object sender, DragEventArgs args) { // Set dragging panel back to null draggingPanel = null; // Update the layout (to reset all panel positions) UpdatePanelLayout(); }
/// <summary> /// Unprepares a drag dock panel. /// </summary> /// <param name="element">The source drag dock panel.</param> /// <param name="item">The source item.</param> protected override void ClearContainerForItemOverride(DependencyObject element, object item) { base.ClearContainerForItemOverride(element, item); DragDockPanel panel = element as DragDockPanel; UnpreparePanel(panel); panels.Remove(panel); SetRowsAndColumns(GetOrderedPanels()); AnimatePanelSizes(); AnimatePanelLayout(); }
/// <summary> /// Shuffles the panels around. /// </summary> /// <param name="sender">The dragging panel.</param> /// <param name="args">Drag event args.</param> private void DragDockPanel_DragMoved(object sender, DragEventArgs args) { Point mousePosInHost = args.MouseEventArgs.GetPosition(this); int currentRow = (int)Math.Floor(mousePosInHost.Y / (ActualHeight / (double)rows)); int currentColumn = (int)Math.Floor(mousePosInHost.X / (ActualWidth / (double)columns)); // Stores the panel we will swap with DragDockPanel swapPanel = null; // Loop through children to see if there is a panel to swap with foreach (UIElement child in panels) { DragDockPanel panel = child as DragDockPanel; // If the panel is not the dragging panel and is in the current row // or current column... mark it as the panel to swap with if (panel != draggingPanel && Grid.GetColumn(panel) == currentColumn && Grid.GetRow(panel) == currentRow) { swapPanel = panel; break; } } // If there is a panel to swap with if (swapPanel != null) { // Store the new row and column int draggingPanelNewColumn = Grid.GetColumn(swapPanel); int draggingPanelNewRow = Grid.GetRow(swapPanel); // Update the swapping panel row and column Grid.SetColumn(swapPanel, Grid.GetColumn(draggingPanel)); Grid.SetRow(swapPanel, Grid.GetRow(draggingPanel)); // Update the dragging panel row and column Grid.SetColumn(draggingPanel, draggingPanelNewColumn); Grid.SetRow(draggingPanel, draggingPanelNewRow); // Animate the layout to the new positions AnimatePanelLayout(); } }
/// <summary> /// Puts all of the panel back to a grid view. /// </summary> /// <param name="sender">The minimising panel.</param> /// <param name="e">Event args.</param> private void DragDockPanel_Restored(object sender, EventArgs e) { // Set max'ed panel to null maximizedPanel = null; // Loop through children to disable dragging foreach (UIElement child in panels) { DragDockPanel panel = child as DragDockPanel; panel.Restore(); panel.DraggingEnabled = true; } // Update sizes and layout AnimatePanelSizes(); AnimatePanelLayout(); }
/// <summary> /// Updates the layout when in design mode. /// </summary> /// <param name="sender">The drag dock panel host.</param> /// <param name="e">Event Args.</param> private void DragDockPanelHost_LayoutUpdated(object sender, EventArgs e) { if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(this)) { Dictionary <int, DragDockPanel> orderedPanels = new Dictionary <int, DragDockPanel>(); for (int i = 0; i < panels.Count; i++) { if (panels[i].GetType() == typeof(DragDockPanel)) { DragDockPanel panel = (DragDockPanel)panels[i]; orderedPanels.Add(i, panel); } } SetRowsAndColumns(orderedPanels); UpdatePanelLayout(); } }
/// <summary> /// Unprepares a panel for the UI. Override for hooking custom events. /// </summary> /// <param name="panel">The panel to prepare.</param> protected virtual void UnpreparePanel(DragDockPanel panel) { if (panel.PanelState == PanelState.Maximized) { DragDockPanel_Restored(null, null); } // Hook up panel events panel.DragStarted -= new DragEventHander(DragDockPanel_DragStarted); panel.DragFinished -= new DragEventHander(DragDockPanel_DragFinished); panel.DragMoved -= new DragEventHander(DragDockPanel_DragMoved); panel.Maximized -= new EventHandler(DragDockPanel_Maximized); panel.Restored -= new EventHandler(DragDockPanel_Restored); }
/// <summary> /// Pepares a drag dock panel. /// </summary> /// <param name="element">The drag dock panel.</param> /// <param name="item">The source item.</param> protected override void PrepareContainerForItemOverride(DependencyObject element, object item) { base.PrepareContainerForItemOverride(element, item); DragDockPanel panel = element as DragDockPanel; if (panel.Style == null && DefaultPanelStyle != null) { panel.Style = DefaultPanelStyle; } Dictionary <int, DragDockPanel> orderedPanels = GetOrderedPanels(); orderedPanels.Add(panels.Count, panel); panels.Add(panel); PreparePanel(panel); SetRowsAndColumns(orderedPanels); AnimatePanelSizes(); AnimatePanelLayout(); }
/// <summary> /// Gets the panels in order. /// </summary> /// <returns>The ordered panels.</returns> private Dictionary <int, DragDockPanel> GetOrderedPanels() { Dictionary <int, DragDockPanel> orderedPanels = new Dictionary <int, DragDockPanel>(); List <DragDockPanel> addedPanels = new List <DragDockPanel>(); for (int i = 0; i < panels.Count; i++) { DragDockPanel lowestPanel = null; foreach (DragDockPanel panel in panels) { if (!addedPanels.Contains(panel) && (lowestPanel == null || ((Grid.GetRow(panel) * columns) + Grid.GetColumn(panel) < (Grid.GetRow(lowestPanel) * columns) + Grid.GetColumn(lowestPanel)))) { lowestPanel = panel; } } addedPanels.Add(lowestPanel); orderedPanels.Add(i, lowestPanel); } return(orderedPanels); }
/// <summary> /// Animate the panel positions /// </summary> private void AnimatePanelLayout() { if (double.IsInfinity(ActualWidth) || double.IsNaN(ActualWidth) || ActualWidth == 0) { return; } // If we are not in max'ed panel mode... if (maximizedPanel == null) { // Loop through children and size to row and columns foreach (UIElement child in panels) { DragDockPanel panel = (DragDockPanel)child; if (panel != draggingPanel) { panel.AnimatePosition( (Grid.GetColumn(panel) * (ActualWidth / (double)columns)), (Grid.GetRow(panel) * (ActualHeight / (double)rows))); } } } else { Dictionary <int, DragDockPanel> orderedPanels = new Dictionary <int, DragDockPanel>(); // Loop through children to order them according to their // current row and column... foreach (UIElement child in panels) { DragDockPanel panel = (DragDockPanel)child; orderedPanels.Add( (Grid.GetRow(panel) * columns) + Grid.GetColumn(panel), panel); } // Set initial top of minimized panels to 0 double currentOffset = 0.0; // For each of the panels (as ordered in the grid) for (int i = 0; i < orderedPanels.Count; i++) { // If the current panel is not the maximized panel if (orderedPanels[i] != maximizedPanel) { double newX = 0; double newY = currentOffset; #region determin new docking coordinates if (minimizedPosition.Equals(MinimizedPositions.Right)) { newX = ActualWidth - minimizedColumnWidth; newY = currentOffset; } else if (minimizedPosition.Equals(MinimizedPositions.Left)) { newX = 0; newY = currentOffset; } else if (minimizedPosition.Equals(MinimizedPositions.Bottom)) { newX = currentOffset; newY = ActualHeight - minimizedRowHeight; } else if (minimizedPosition.Equals(MinimizedPositions.Top)) { newX = currentOffset; newY = 0; } else if (minimizedPosition.Equals(MinimizedPositions.None)) { newX = ActualWidth / 2; newY = ActualHeight / 2; } #endregion // Animate the position orderedPanels[i].AnimatePosition( newX, newY); if (minimizedPosition.Equals(MinimizedPositions.Left) || minimizedPosition.Equals(MinimizedPositions.Right)) { // Increment current top currentOffset += ActualHeight / (double)(panels.Count - 1); } else { // Increment current left currentOffset += ActualWidth / (double)(panels.Count - 1); } } else { #region determine new docking position double newX = 0; double newY = 0; if (minimizedPosition.Equals(MinimizedPositions.Right)) { newX = 0; newY = 0; } else if (minimizedPosition.Equals(MinimizedPositions.Left)) { newX = minimizedColumnWidth; newY = 0; } else if (minimizedPosition.Equals(MinimizedPositions.Bottom)) { newX = 0; newY = 0; } else if (minimizedPosition.Equals(MinimizedPositions.Top)) { newX = 0; newY = minimizedRowHeight; } else if (minimizedPosition.Equals(MinimizedPositions.None)) { newX = 0; newY = 0; } #endregion // Animate maximized panel orderedPanels[i].AnimatePosition(newX, newY); } } } }
/// <summary> /// Animates the panel sizes /// </summary> private void AnimatePanelSizes() { if (double.IsInfinity(ActualWidth) || double.IsNaN(ActualWidth) || ActualWidth == 0) { return; } // If there is not a maxmized panel... if (maximizedPanel == null) { // Animate the panel sizes to row / column sizes foreach (UIElement child in panels) { DragDockPanel panel = (DragDockPanel)child; double width = (ActualWidth / (double)columns) - panel.Margin.Left - panel.Margin.Right; double height = (ActualHeight / (double)rows) - panel.Margin.Top - panel.Margin.Bottom; if (width < 0) { width = 0; } if (height < 0) { height = 0; } panel.AnimateSize( width, height); } } else { // Loop through the children foreach (UIElement child in panels) { DragDockPanel panel = (DragDockPanel)child; // Set the size of the non // maximized children if (panel != maximizedPanel) { #region determine new width & height depending on docking axis double newWidth = minimizedColumnWidth - panel.Margin.Left - panel.Margin.Right; double newHeight = (ActualHeight / (double)(panels.Count - 1)) - panel.Margin.Top - panel.Margin.Bottom; if (minimizedPosition.Equals(MinimizedPositions.Bottom) || minimizedPosition.Equals(MinimizedPositions.Top)) { newWidth = (ActualWidth / (double)(panels.Count - 1)) - panel.Margin.Left - panel.Margin.Right; newHeight = minimizedRowHeight - panel.Margin.Top - panel.Margin.Bottom; } else if (minimizedPosition.Equals(MinimizedPositions.None)) { newWidth = newHeight = 0; } #endregion if (newHeight < 0) { newHeight = 0; } if (newWidth < 0) { newWidth = 0; } panel.AnimateSize( newWidth, newHeight); } else { #region determine new width & height depending on docking axis double newWidth = ActualWidth - minimizedColumnWidth - panel.Margin.Left - panel.Margin.Right; double newHeight = ActualHeight - panel.Margin.Top - panel.Margin.Bottom; if (minimizedPosition.Equals(MinimizedPositions.Bottom) || minimizedPosition.Equals(MinimizedPositions.Top)) { newWidth = ActualWidth - panel.Margin.Left - panel.Margin.Right; newHeight = ActualHeight - minimizedRowHeight - panel.Margin.Top - panel.Margin.Bottom; } else if (minimizedPosition.Equals(MinimizedPositions.None)) { newWidth = ActualWidth - panel.Margin.Right - panel.Margin.Left; newHeight = ActualHeight - panel.Margin.Bottom - panel.Margin.Top; } #endregion if (newHeight < 0) { newHeight = 0; } if (newWidth < 0) { newWidth = 0; } panel.AnimateSize( newWidth, newHeight); } } } }
/// <summary> /// Updates the panel layout without animation /// This does size and position without animation /// </summary> private void UpdatePanelLayout() { if (double.IsInfinity(ActualWidth) || double.IsNaN(ActualWidth) || ActualWidth == 0) { return; } // If we are not in max'ed panel mode... if (maximizedPanel == null) { // Layout children as per rows and columns foreach (UIElement child in panels) { DragDockPanel panel = (DragDockPanel)child; Canvas.SetLeft( panel, (Grid.GetColumn(panel) * (ActualWidth / (double)columns))); Canvas.SetTop( panel, (Grid.GetRow(panel) * (ActualHeight / (double)rows))); double width = (ActualWidth / (double)columns) - panel.Margin.Left - panel.Margin.Right; double height = (ActualHeight / (double)rows) - panel.Margin.Top - panel.Margin.Bottom; if (width < 0) { width = 0; } if (height < 0) { height = 0; } panel.Width = width; panel.Height = height; } } else { Dictionary <int, DragDockPanel> orderedPanels = new Dictionary <int, DragDockPanel>(); // Loop through children to order them according to their // current row and column... foreach (UIElement child in panels) { DragDockPanel panel = (DragDockPanel)child; orderedPanels.Add( (Grid.GetRow(panel) * columns) + Grid.GetColumn(panel), panel); } // Set initial top of minimized panels to 0 double currentOffset = 0.0; // For each of the panels (as ordered in the grid) for (int i = 0; i < orderedPanels.Count; i++) { // If the current panel is not the maximized panel if (orderedPanels[i] != maximizedPanel) { #region determine new width & height depending on docking axis double newWidth = minimizedColumnWidth - orderedPanels[i].Margin.Left - orderedPanels[i].Margin.Right; double newHeight = (ActualHeight / (double)(panels.Count - 1)) - orderedPanels[i].Margin.Top - orderedPanels[i].Margin.Bottom; if (minimizedPosition.Equals(MinimizedPositions.Bottom) || minimizedPosition.Equals(MinimizedPositions.Top)) { newWidth = (ActualWidth / (double)(panels.Count - 1)) - orderedPanels[i].Margin.Left - orderedPanels[i].Margin.Right; newHeight = minimizedRowHeight - orderedPanels[i].Margin.Top - orderedPanels[i].Margin.Bottom; } else if (minimizedPosition.Equals(MinimizedPositions.None)) { newWidth = 0; newHeight = 0; } #endregion if (newHeight < 0) { newHeight = 0; } if (newWidth < 0) { newWidth = 0; } // Set the size of the panel orderedPanels[i].Width = newWidth; orderedPanels[i].Height = newHeight; double newX = 0; double newY = currentOffset; #region determin new docking coordinates if (minimizedPosition.Equals(MinimizedPositions.Right)) { newX = ActualWidth - minimizedColumnWidth; newY = currentOffset; } else if (minimizedPosition.Equals(MinimizedPositions.Left)) { newX = 0; newY = currentOffset; } else if (minimizedPosition.Equals(MinimizedPositions.Bottom)) { newX = currentOffset; newY = ActualHeight - minimizedRowHeight; } else if (minimizedPosition.Equals(MinimizedPositions.Top)) { newX = currentOffset; newY = 0; } else if (minimizedPosition.Equals(MinimizedPositions.None)) { newX = ActualWidth / 2; newY = ActualHeight / 2; } #endregion // Set the position of the panel Canvas.SetLeft(orderedPanels[i], newX); Canvas.SetTop(orderedPanels[i], newY); if (minimizedPosition.Equals(MinimizedPositions.Left) || minimizedPosition.Equals(MinimizedPositions.Right)) { // Increment current top currentOffset += ActualHeight / (double)(panels.Count - 1); } else { // Increment current left currentOffset += ActualWidth / (double)(panels.Count - 1); } } else { #region determine new width & height depending on docking axis double newWidth = ActualWidth - minimizedColumnWidth - orderedPanels[i].Margin.Left - orderedPanels[i].Margin.Right; double newHeight = ActualHeight - orderedPanels[i].Margin.Top - orderedPanels[i].Margin.Bottom; if (minimizedPosition.Equals(MinimizedPositions.Bottom) || minimizedPosition.Equals(MinimizedPositions.Top)) { newWidth = ActualWidth - orderedPanels[i].Margin.Left - orderedPanels[i].Margin.Right; newHeight = ActualHeight - minimizedRowHeight - orderedPanels[i].Margin.Top - orderedPanels[i].Margin.Bottom; } else if (minimizedPosition.Equals(MinimizedPositions.None)) { newWidth = ActualWidth - orderedPanels[i].Margin.Right - orderedPanels[i].Margin.Left; newHeight = ActualHeight - orderedPanels[i].Margin.Bottom - orderedPanels[i].Margin.Top; } #endregion if (newHeight < 0) { newHeight = 0; } if (newWidth < 0) { newWidth = 0; } // Set the size of the panel orderedPanels[i].Width = newWidth; orderedPanels[i].Height = newHeight; #region determine new docking position double newX = 0; double newY = 0; if (minimizedPosition.Equals(MinimizedPositions.Right)) { newX = 0; newY = 0; } else if (minimizedPosition.Equals(MinimizedPositions.Left)) { newX = minimizedColumnWidth; newY = 0; } else if (minimizedPosition.Equals(MinimizedPositions.Bottom)) { newX = 0; newY = 0; } else if (minimizedPosition.Equals(MinimizedPositions.Top)) { newX = 0; newY = minimizedRowHeight; } else if (minimizedPosition.Equals(MinimizedPositions.None)) { newX = 0; newY = 0; } #endregion // Set the position of the panel Canvas.SetLeft(orderedPanels[i], newX); Canvas.SetTop(orderedPanels[i], newY); } } } }