/// <summary> /// Read the layout from XML file and apply it to dockpanel</summary> /// <param name="reader">Source XML file</param> public void ApplyLayout(XmlReader reader) { try { if (reader == null) { PerformDefaultLayout(); } else { if (!m_templateApplied) { CacheLayout(reader); return; } if (m_layoutApplied) { ((IDockLayout)this).Close(); } if (reader.ReadToFollowing(this.GetType().Name, this.GetType().Namespace)) { reader.ReadStartElement(); if (reader.LocalName == "Contents") { if (reader.ReadToDescendant("Content")) { do { String ucid = reader.GetAttribute("UCID"); DockContent content = GetContent(ucid); if (content != null) { content.Settings.DockState = (DockState)Enum.Parse(typeof(DockState), reader.GetAttribute(typeof(DockState).Name)); try { var str = reader.GetAttribute("Location"); content.Settings.Location = Point.Parse(str); } catch (FormatException) { } try { var str = reader.GetAttribute("Size"); content.Settings.Size = Size.Parse(str); } catch (FormatException) { } } } while (reader.ReadToNextSibling("Content")); // there will only be an end element if "Content" entries were listed reader.ReadEndElement(); } else { if (reader.IsEmptyElement) { reader.Read(); } } // else, the "Contents" element was self-contained, and there is no end element to parse } if (reader.LocalName == typeof(GridLayout).Name) { GridLayout gridLayout = new GridLayout(this, reader.ReadSubtree()); GridLayout = gridLayout.Layouts.Count > 0 ? gridLayout : null; reader.ReadEndElement(); } if (reader.LocalName == typeof(FloatingWindow).Name) { do { FloatingWindow window = new FloatingWindow(this, reader.ReadSubtree()); if (window.DockedContent.Children.Count > 0) { window.Closing += ChildWindowClosing; m_windows.Add(window); window.Owner = Window.GetWindow(this); window.Show(); window.Left = window.Left; window.Top = window.Top; } else { // To-do: create "dummy content" like in DockPanelSuite, so that if the // window were to be created later, we could apply the layout. For now, // just set the owner. This ties the FloatingWindow to the main window, and // allows the app to shut down properly with the default Application.ShutdownMode // of OnLastWindowClose. window.Owner = Window.GetWindow(this); } } while (reader.ReadToNextSibling(typeof(FloatingWindow).Name)); reader.ReadEndElement(); } if (reader.LocalName == typeof(SidePopup).Name) { do { Dock dockSide = (Dock)Enum.Parse(typeof(Dock), reader.GetAttribute("Side")); switch (dockSide) { case System.Windows.Controls.Dock.Left: PART_LeftCollapsePanel.ReadXml(reader.ReadSubtree()); break; case System.Windows.Controls.Dock.Top: PART_TopCollapsePanel.ReadXml(reader.ReadSubtree()); break; case System.Windows.Controls.Dock.Right: PART_RightCollapsePanel.ReadXml(reader.ReadSubtree()); break; case System.Windows.Controls.Dock.Bottom: PART_BottomCollapsePanel.ReadXml(reader.ReadSubtree()); break; } } while (reader.ReadToNextSibling(typeof(SidePopup).Name)); reader.ReadEndElement(); } m_layoutApplied = true; } } } catch (Exception ex) { ((IDockLayout)this).Close(); PerformDefaultLayout(); throw ex; } }
/// <summary> /// Start dragging the given content. This includes undocking it from the UI, /// creating new window with the content, and then start dragging it.</summary> /// <param name="source"></param> /// <param name="content">Content to drag</param> internal void Drag(IDockLayout source, IDockContent content) { FrameworkElement sourceElement = (FrameworkElement)source; ContentSettings settings = (content is TabLayout) ? ((TabLayout)content).Children[0].Settings : ((DockContent)content).Settings; Size size = new Size(sourceElement.ActualWidth, sourceElement.ActualHeight); Point offset = new Point(settings.Size.Width / 2, 3); Point position = Mouse.GetPosition(this); position = PointToScreen(position); Matrix m = PresentationSource.FromVisual(Window.GetWindow(this)).CompositionTarget.TransformToDevice; if (m != Matrix.Identity) { m.Invert(); position = m.Transform(position); } offset = Mouse.GetPosition(sourceElement); offset.Y = offset.Y > 20 ? 10 : offset.Y; position = (Point)(position - offset); if (Mouse.LeftButton == MouseButtonState.Pressed) { source.Undock(content); FloatingWindow wnd = new FloatingWindow(this, content, position, size); wnd.Closing += ChildWindowClosing; m_windows.Add(wnd); wnd.Owner = Window.GetWindow(this); wnd.Show(); wnd.DragMove(); } }
/// <summary> /// Display dock content. If the content is not docked in main panel, collapsible panels or windows, /// then it is opened in its last position when it was closed</summary> /// <param name="content">Content to show</param> public void ShowContent(IDockContent content) { DockContent dockContent; if (IsLoaded && (dockContent = content as DockContent) != null) { if (!m_registeredContents.ContainsValue(dockContent)) { throw new ArgumentOutOfRangeException("Given content is not registered!"); } if (!((IDockLayout)this).HasDescendant(content)) { ContentSettings contentSettings = dockContent.Settings; if (contentSettings.Size == new Size(0, 0)) { double ratio = contentSettings.DefaultDock == DockTo.Center ? 0.8 : 0.2; contentSettings.Size = new Size(ActualWidth * ratio, ActualHeight * ratio); } switch (contentSettings.DockState) { case DockState.Docked: { if (GridLayout == null) { ((IDockLayout)this).Dock(null, content, DockTo.Center); } else { Point position = new Point(ActualWidth / 2, ActualHeight / 2); DockTo dockTo = contentSettings.DefaultDock; switch (dockTo) { case DockTo.Left: position.X = 1; break; case DockTo.Right: position.X = ActualWidth - 2; break; case DockTo.Top: position.Y = 1; break; case DockTo.Bottom: position.Y = ActualHeight - 2; break; case DockTo.Center: // no modification necessary break; } position = PointToScreen(position); DockContent target = ((IDockLayout)this).HitTest(position); if (target != null) { DockTo targetDock = target.Settings.DefaultDock; if (targetDock == dockTo) { ((IDockLayout)this).Dock(target, content, DockTo.Center); } else { if (dockTo == DockTo.Center && (targetDock == DockTo.Right) || dockTo == DockTo.Left && (targetDock == DockTo.Center || targetDock == DockTo.Right)) { ((IDockLayout)this).Dock(target, content, DockTo.Left); } else if (dockTo == DockTo.Center && (targetDock == DockTo.Left) || dockTo == DockTo.Right && (targetDock == DockTo.Center || targetDock == DockTo.Left)) { ((IDockLayout)this).Dock(target, content, DockTo.Right); } else if (dockTo == DockTo.Center && (targetDock == DockTo.Bottom) || dockTo == DockTo.Top && (targetDock == DockTo.Center || targetDock == DockTo.Bottom)) { ((IDockLayout)this).Dock(target, content, DockTo.Top); } else if (dockTo == DockTo.Center && (targetDock == DockTo.Top) || dockTo == DockTo.Bottom && (targetDock == DockTo.Center || targetDock == DockTo.Top)) { ((IDockLayout)this).Dock(target, content, DockTo.Bottom); } else { ((IDockLayout)this).Dock(null, content, dockTo); } } } else { ((IDockLayout)this).Dock(null, content, dockTo); } } UpdateLayout(); } break; case DockState.Floating: { FloatingWindow wnd = new FloatingWindow(this, content, contentSettings.Location, contentSettings.Size); wnd.Closing += ChildWindowClosing; m_windows.Add(wnd); wnd.Owner = Window.GetWindow(this); wnd.Show(); } break; case DockState.Collapsed: Collapse(content); break; } } Focus(content); } }