/// <summary> /// Resets all fields. /// </summary> private void Reset() { Debug.Assert(Mouse.Captured == null); Debug.Assert(_borderDockIndicators == null); Debug.Assert(_paneDockIndicators == null); Debug.Assert( _dockStrategy == null || !_dockStrategy.DockControl.GetDockElements().OfType <DockTabItemProxy>().Any(), "All item proxies should have been removed."); _dockStrategy = null; _draggedItems.Clear(); _activeItem = null; _floatWindow = null; _targetDockTabPane = null; _layoutChanged = false; _initialMousePosition = new Point(double.NaN, double.NaN); _dragDeltaExceeded = false; _mouseOffset = new Vector(double.NaN, double.NaN); _initialSize = new Size(double.NaN, double.NaN); _canFloat = true; _originalDockState = DockState.Hide; _originalFloatWindow = null; _originalFloatLeft = 0; _originalFloatTop = 0; }
/// <summary> /// Loads the docking layout. /// </summary> /// <param name="storedLayout">The stored layout.</param> /// <inheritdoc cref="DockSerializer.Load"/> public void LoadLayout(XElement storedLayout) { try { DockStrategy.Begin(); var oldItems = Items.ToList(); DockSerializer.Load(this, storedLayout); var newItems = Items.ToList(); // Screen conduction for items closed in Load(). foreach (var dockTabItem in oldItems.Except(newItems)) { // IActivatable (dockTabItem as IActivatable)?.OnDeactivate(true); // IScreen var screen = dockTabItem as IScreen; if (screen != null) { screen.Conductor = null; } } } finally { DockStrategy.End(); } }
///// <summary> ///// Called when <see cref="IDockControl.ActiveDockTabPane"/> changed. ///// </summary> ///// <param name="sender">The sender.</param> ///// <param name="eventArgs"> ///// The <see cref="PropertyChangedEventArgs"/> instance containing the event data. ///// </param> //private void OnActivePaneChanged(object sender, PropertyChangedEventArgs eventArgs) //{ //} /// <summary> /// Called when <see cref="IDockControl.ActiveDockTabItem"/> changed. /// </summary> /// <param name="sender">The sender.</param> /// <param name="eventArgs"> /// The <see cref="PropertyChangedEventArgs"/> instance containing the event data. /// </param> private void OnActiveItemChanged(object sender, PropertyChangedEventArgs eventArgs) { Debug.Assert(DockStrategy != null); Debug.Assert(DockStrategy.DockControl.ActiveDockTabItem == null || DockStrategy.DockControl.ActiveDockTabPane != null, "IDockControl.ActiveDockTabPane needs to be set before IDockControl.ActiveDockTabItem."); Debug.Assert(DockStrategy.DockControl.ActiveDockTabPane == null || DockStrategy.DockControl.ActiveDockTabPane.SelectedItem == DockStrategy.DockControl.ActiveDockTabItem, "IDockControl.ActiveDockTabPane.SelectedItem needs to match IDockControl.ActiveDockTabItem."); var dockTabPaneVM = DockStrategy.DockControl.ActiveDockTabPane; var dockTabItemVM = DockStrategy.DockControl.ActiveDockTabItem; if (dockTabPaneVM == null || dockTabItemVM == null) { CloseAutoHidePanes(); return; } if (dockTabItemVM.DockState == DockState.Dock) { CloseAutoHidePanes(); } else if (dockTabItemVM.DockState == DockState.Float) { CloseAutoHidePanes(); var floatWindowVM = DockStrategy?.GetFloatWindow(dockTabItemVM); GetView(floatWindowVM)?.Activate(); } else if (dockTabItemVM.DockState == DockState.AutoHide) { ShowAutoHidePane(dockTabPaneVM, dockTabItemVM); } GetView(dockTabItemVM)?.Activate(); }
/// <inheritdoc/> public void ActivateItem(object item) { if (item == null) { throw new ArgumentNullException(nameof(item)); } var dockTabItem = item as IDockTabItem; if (dockTabItem == null) { throw new ArgumentException("Item needs to implement IDockTabItem"); } DockStrategy.Show(dockTabItem); // Validation var activatable = dockTabItem as IActivatable; if (activatable != null) { Debug.Assert(activatable.IsOpen); Debug.Assert(activatable.IsActive); Debug.Assert(GetItems(true).Contains(item)); } var screen = dockTabItem as IScreen; if (screen != null) { Debug.Assert(screen.Conductor == this); } }
/// <inheritdoc/> public Task <bool> DeactivateItemAsync(object item, bool close) { var dockTabItem = item as IDockTabItem; if (dockTabItem == null || !close || // Temporary deactivation is not supported. !DockStrategy.CanClose(dockTabItem)) { return(TaskHelper.FromResult(false)); } DockStrategy.Close(dockTabItem); // Validation var activatable = dockTabItem as IActivatable; if (activatable != null) { Debug.Assert(!activatable.IsActive); Debug.Assert(!activatable.IsOpen); Debug.Assert(!GetItems(false).Contains(item)); } var screen = dockTabItem as IScreen; if (screen != null) { Debug.Assert(screen.Conductor == null); } return(TaskHelper.FromResult(true)); }
/// <summary> /// Saves the docking layout. /// </summary> /// <param name="excludeNonPersistentItems"> /// <see langword="true"/> to exclude non-persistent <see cref="IDockTabItem"/>s. /// <see langword="false"/> to store the layout of all (persistent and non-persistent) /// <see cref="IDockTabItem"/>s. /// </param> /// <returns>The <see cref="XElement"/> with the serialized layout.</returns> /// <inheritdoc cref="DockSerializer.Save(IDockControl,bool)"/> public XElement SaveLayout(bool excludeNonPersistentItems = false) { try { DockStrategy.Begin(); return(DockSerializer.Save(this, excludeNonPersistentItems)); } finally { DockStrategy.End(); } }
public MainViewModel() { Themes = new List <string> { "Default", "System", "Light", "Gray", "Dark", }; SelectedThemeIndex = 3; // Build dock layout directly. //var dockTabPaneViewModel = new DockTabPaneViewModel(); //dockTabPaneViewModel.Items.Add(new SystemViewModel { DockState = DockState.Dock }); //dockTabPaneViewModel.Items.Add(new SystemViewModel { DockState = DockState.Dock }); //dockTabPaneViewModel.Items.Add(new DigitalRuneViewModel { DockState = DockState.Dock }); //dockTabPaneViewModel.Items.Add(new DigitalRuneViewModel { DockState = DockState.Dock }); //dockTabPaneViewModel.Items.Add(new PropertyGridViewModel { DockState = DockState.Dock }); //dockTabPaneViewModel.Items.Add(new PropertyGridViewModel { DockState = DockState.Dock }); //dockTabPaneViewModel.Items.Add(new ICSharpDevelopViewModel { DockState = DockState.Dock }); //dockTabPaneViewModel.Items.Add(new ICSharpDevelopViewModel { DockState = DockState.Dock }); //var dockAnchorPaneViewModel = new DockAnchorPaneViewModel //{ // ChildPane = dockTabPaneViewModel //}; //DockControlViewModel = new DockControlViewModel(new DockStrategy()) //{ // RootPane = dockAnchorPaneViewModel //}; // Or use DockStrategy to do the same. var dockStrategy = new DockStrategy(); DockControlViewModel = new DockControlViewModel(dockStrategy) { RootPane = new DockAnchorPaneViewModel(), }; dockStrategy.Begin(); dockStrategy.Dock(new SystemViewModel()); dockStrategy.Dock(new SystemViewModel()); dockStrategy.Dock(new DigitalRuneViewModel()); dockStrategy.Dock(new DigitalRuneViewModel()); dockStrategy.Dock(new PropertyGridViewModel()); dockStrategy.Dock(new PropertyGridViewModel()); dockStrategy.Dock(new ICSharpDevelopViewModel()); dockStrategy.Dock(new ICSharpDevelopViewModel()); dockStrategy.End(); }
public MainViewModel() { Themes = new List<string> { "Default", "System", "Light", "Gray", "Dark", }; SelectedThemeIndex = 3; // Build dock layout directly. //var dockTabPaneViewModel = new DockTabPaneViewModel(); //dockTabPaneViewModel.Items.Add(new SystemViewModel { DockState = DockState.Dock }); //dockTabPaneViewModel.Items.Add(new SystemViewModel { DockState = DockState.Dock }); //dockTabPaneViewModel.Items.Add(new DigitalRuneViewModel { DockState = DockState.Dock }); //dockTabPaneViewModel.Items.Add(new DigitalRuneViewModel { DockState = DockState.Dock }); //dockTabPaneViewModel.Items.Add(new PropertyGridViewModel { DockState = DockState.Dock }); //dockTabPaneViewModel.Items.Add(new PropertyGridViewModel { DockState = DockState.Dock }); //dockTabPaneViewModel.Items.Add(new ICSharpDevelopViewModel { DockState = DockState.Dock }); //dockTabPaneViewModel.Items.Add(new ICSharpDevelopViewModel { DockState = DockState.Dock }); //var dockAnchorPaneViewModel = new DockAnchorPaneViewModel //{ // ChildPane = dockTabPaneViewModel //}; //DockControlViewModel = new DockControlViewModel(new DockStrategy()) //{ // RootPane = dockAnchorPaneViewModel //}; // Or use DockStrategy to do the same. var dockStrategy = new DockStrategy(); DockControlViewModel = new DockControlViewModel(dockStrategy) { RootPane = new DockAnchorPaneViewModel(), }; dockStrategy.Begin(); dockStrategy.Dock(new SystemViewModel()); dockStrategy.Dock(new SystemViewModel()); dockStrategy.Dock(new DigitalRuneViewModel()); dockStrategy.Dock(new DigitalRuneViewModel()); dockStrategy.Dock(new PropertyGridViewModel()); dockStrategy.Dock(new PropertyGridViewModel()); dockStrategy.Dock(new ICSharpDevelopViewModel()); dockStrategy.Dock(new ICSharpDevelopViewModel()); dockStrategy.End(); }
internal void UpdateFloatWindows() { if (DockStrategy == null) { return; } var owner = Window.GetWindow(this); // Close obsolete FloatWindows. for (int i = _floatWindows.Count - 1; i >= 0; i--) { var floatWindow = _floatWindows[i]; var floatWindowVM = floatWindow.GetViewModel(); if (floatWindowVM == null || !DockStrategy.DockControl.FloatWindows.Contains(floatWindowVM) || !DockStrategy.IsVisible(floatWindowVM)) { // ----- Close FloatWindow. floatWindow.Close(); _floatWindows.RemoveAt(i); } } // Open new FloatWindows. for (int i = 0; i < DockStrategy.DockControl.FloatWindows.Count; i++) { var floatWindowVM = DockStrategy.DockControl.FloatWindows[i]; if (DockStrategy.IsVisible(floatWindowVM) && GetView(floatWindowVM) == null) { // ----- Open FloatWindow. // Make sure that the floating window stays on the screen. // At least 30 pixels must be visible. const double safety = 30; double screenLeft = SystemParameters.VirtualScreenLeft; double screenTop = SystemParameters.VirtualScreenTop; double screenRight = screenLeft + SystemParameters.VirtualScreenWidth; double screenBottom = screenTop + SystemParameters.VirtualScreenHeight; floatWindowVM.Left = Math.Min(Math.Max(floatWindowVM.Left, screenLeft), screenRight - safety); floatWindowVM.Top = Math.Min(Math.Max(floatWindowVM.Top, screenTop), screenBottom - safety); var floatWindow = new FloatWindow(this) { DataContext = floatWindowVM, Owner = owner, }; bool autoWidth = Numeric.IsNaN(floatWindowVM.Width); bool autoHeight = Numeric.IsNaN(floatWindowVM.Height); if (autoWidth && autoHeight) { floatWindow.SizeToContent = SizeToContent.WidthAndHeight; } else if (autoWidth) { floatWindow.SizeToContent = SizeToContent.Width; } else if (autoHeight) { floatWindow.SizeToContent = SizeToContent.Height; } else { floatWindow.SizeToContent = SizeToContent.Manual; } floatWindow.SetBinding(ContentProperty, new Binding(nameof(IFloatWindow.RootPane))); floatWindow.SetBinding(WidthProperty, new Binding(nameof(IFloatWindow.Width)) { Mode = BindingMode.TwoWay }); floatWindow.SetBinding(HeightProperty, new Binding(nameof(IFloatWindow.Height)) { Mode = BindingMode.TwoWay }); floatWindow.SetBinding(Window.LeftProperty, new Binding(nameof(IFloatWindow.Left)) { Mode = BindingMode.TwoWay }); floatWindow.SetBinding(Window.TopProperty, new Binding(nameof(IFloatWindow.Top)) { Mode = BindingMode.TwoWay }); floatWindow.Show(); // Bind WindowState after showing the window. Otherwise, it could be maximized // on the wrong screen. floatWindow.SetBinding(Window.WindowStateProperty, new Binding(nameof(IFloatWindow.WindowState)) { Mode = BindingMode.TwoWay }); _floatWindows.Add(floatWindow); } } }
/// <summary> /// Initializes a new instance of the <see cref="DockControlViewModel" /> class with the /// specified <see cref="Docking.DockStrategy"/>. /// </summary> /// <param name="dockStrategy">The<see cref="Docking.DockStrategy"/>.</param> public DockControlViewModel(DockStrategy dockStrategy) { DockStrategy = dockStrategy; }
/// <summary> /// Starts a drag operation. /// </summary> /// <param name="floatWindow">The <see cref="FloatWindow"/> to be dragged.</param> /// <param name="dockTabPane">The <see cref="DockTabPane"/> to be dragged.</param> /// <param name="dockTabItem">The <see cref="DockTabItem"/> to be dragged.</param> /// <returns> /// <see langword="true" /> if the drag operation has been started; otherwise, /// <see langword="false" /> if the drag operation could not be started (e.g. because the /// mouse could not be captured). /// </returns> private bool BeginDrag(FloatWindow floatWindow, DockTabPane dockTabPane, DockTabItem dockTabItem) { _dockStrategy = _dockControl.GetViewModel()?.DockStrategy; if (_dockStrategy == null || _dockStrategy.DockControl.IsLocked) { Reset(); return(false); } FrameworkElement element = null; IDockTabPane draggedPane = null; IDockTabItem draggedItem = null; if (floatWindow != null) { // User is dragging a FloatWindow. // (Note: Dragging of FloatWindows with nested layouts is not supported.) draggedPane = floatWindow.GetViewModel()?.RootPane as IDockTabPane; element = floatWindow; _floatWindow = floatWindow; _initialSize = floatWindow.RenderSize; // Start dragging immediately. _dragDeltaExceeded = true; } else if (dockTabItem != null) { // User is dragging a DockTabItem in a DockTabPanel. draggedItem = dockTabItem.GetViewModel(); element = dockTabItem; _targetDockTabPane = dockTabPane; _initialSize = dockTabPane.RenderSize; // Start dragging when threshold is exceeded. _initialMousePosition = WindowsHelper.GetMousePosition(_dockControl); _dragDeltaExceeded = false; } else if (dockTabPane != null) { // User is dragging a DockTabPane. draggedPane = dockTabPane.GetViewModel(); element = dockTabPane; _initialSize = dockTabPane.RenderSize; _initialMousePosition = WindowsHelper.GetMousePosition(_dockControl); // Start dragging when threshold is exceeded. _initialMousePosition = WindowsHelper.GetMousePosition(_dockControl); _dragDeltaExceeded = false; } if (draggedPane == null && draggedItem == null) { Reset(); return(false); } // When the user is dragging the FloatWindow, the mouse is captured by Win32 move window // loop. When dragging a DockTabPane or DockTabItem, the mouse needs to be // captured to receive mouse events. if (_floatWindow == null) { if (!_dockControl.CaptureMouse()) { // Failed to capture the mouse. Reset(); return(false); } _dockControl.LostMouseCapture += OnLostMouseCapture; _dockControl.MouseLeftButtonUp += OnMouseLeftButtonUp; _dockControl.MouseMove += OnMouseMove; _dockControl.PreviewKeyDown += OnPreviewKeyDown; if (_targetDockTabPane != null) { _targetDockTabPane.PreviewKeyDown += OnPreviewKeyDown; } } _dockStrategy.Begin(); if (draggedPane != null) { _dockStrategy.Activate(draggedPane); _activeItem = draggedPane.SelectedItem; foreach (var item in draggedPane.Items) { if (item.DockState == draggedPane.DockState) { _draggedItems.Add(item); } } } else { Debug.Assert(draggedItem != null); _dockStrategy.Activate(draggedItem); _activeItem = draggedItem; _draggedItems.Add(draggedItem); } Debug.Assert(_draggedItems.Count > 0); // Determine whether dragged items may end in a FloatWindow. _canFloat = CanFloat(); // Store the mouse offset relative to the dragged element. _mouseOffset = (Vector)WindowsHelper.GetMousePosition(element); // Remember information needed for a rollback. ReplaceItemsWithProxies(draggedPane ?? _targetDockTabPane.GetViewModel()); _originalDockState = _draggedItems[0].DockState; BackupFloatWindowPosition(); // Override mouse cursors. (Mouse cursor should not change to caret over text editor.) Mouse.OverrideCursor = Cursors.Arrow; return(true); }
//-------------------------------------------------------------- /// <summary> /// Resets all fields. /// </summary> private void Reset() { Debug.Assert(Mouse.Captured == null); Debug.Assert(_borderDockIndicators == null); Debug.Assert(_paneDockIndicators == null); Debug.Assert( _dockStrategy == null || !_dockStrategy.DockControl.GetDockElements().OfType<DockTabItemProxy>().Any(), "All item proxies should have been removed."); _dockStrategy = null; _draggedItems.Clear(); _activeItem = null; _floatWindow = null; _targetDockTabPane = null; _layoutChanged = false; _initialMousePosition = new Point(double.NaN, double.NaN); _dragDeltaExceeded = false; _mouseOffset = new Vector(double.NaN, double.NaN); _initialSize = new Size(double.NaN, double.NaN); _canFloat = true; _originalDockState = DockState.Hide; _originalFloatWindow = null; _originalFloatLeft = 0; _originalFloatTop = 0; }
/// <summary> /// Starts a drag operation. /// </summary> /// <param name="floatWindow">The <see cref="FloatWindow"/> to be dragged.</param> /// <param name="dockTabPane">The <see cref="DockTabPane"/> to be dragged.</param> /// <param name="dockTabItem">The <see cref="DockTabItem"/> to be dragged.</param> /// <returns> /// <see langword="true" /> if the drag operation has been started; otherwise, /// <see langword="false" /> if the drag operation could not be started (e.g. because the /// mouse could not be captured). /// </returns> private bool BeginDrag(FloatWindow floatWindow, DockTabPane dockTabPane, DockTabItem dockTabItem) { _dockStrategy = _dockControl.GetViewModel()?.DockStrategy; if (_dockStrategy == null || _dockStrategy.DockControl.IsLocked) { Reset(); return false; } FrameworkElement element = null; IDockTabPane draggedPane = null; IDockTabItem draggedItem = null; if (floatWindow != null) { // User is dragging a FloatWindow. // (Note: Dragging of FloatWindows with nested layouts is not supported.) draggedPane = floatWindow.GetViewModel()?.RootPane as IDockTabPane; element = floatWindow; _floatWindow = floatWindow; _initialSize = floatWindow.RenderSize; // Start dragging immediately. _dragDeltaExceeded = true; } else if (dockTabItem != null) { // User is dragging a DockTabItem in a DockTabPanel. draggedItem = dockTabItem.GetViewModel(); element = dockTabItem; _targetDockTabPane = dockTabPane; _initialSize = dockTabPane.RenderSize; // Start dragging when threshold is exceeded. _initialMousePosition = WindowsHelper.GetMousePosition(_dockControl); _dragDeltaExceeded = false; } else if (dockTabPane != null) { // User is dragging a DockTabPane. draggedPane = dockTabPane.GetViewModel(); element = dockTabPane; _initialSize = dockTabPane.RenderSize; _initialMousePosition = WindowsHelper.GetMousePosition(_dockControl); // Start dragging when threshold is exceeded. _initialMousePosition = WindowsHelper.GetMousePosition(_dockControl); _dragDeltaExceeded = false; } if (draggedPane == null && draggedItem == null) { Reset(); return false; } // When the user is dragging the FloatWindow, the mouse is captured by Win32 move window // loop. When dragging a DockTabPane or DockTabItem, the mouse needs to be // captured to receive mouse events. if (_floatWindow == null) { if (!_dockControl.CaptureMouse()) { // Failed to capture the mouse. Reset(); return false; } _dockControl.LostMouseCapture += OnLostMouseCapture; _dockControl.MouseLeftButtonUp += OnMouseLeftButtonUp; _dockControl.MouseMove += OnMouseMove; _dockControl.PreviewKeyDown += OnPreviewKeyDown; if (_targetDockTabPane != null) _targetDockTabPane.PreviewKeyDown += OnPreviewKeyDown; } _dockStrategy.Begin(); if (draggedPane != null) { _dockStrategy.Activate(draggedPane); _activeItem = draggedPane.SelectedItem; foreach (var item in draggedPane.Items) if (item.DockState == draggedPane.DockState) _draggedItems.Add(item); } else { Debug.Assert(draggedItem != null); _dockStrategy.Activate(draggedItem); _activeItem = draggedItem; _draggedItems.Add(draggedItem); } Debug.Assert(_draggedItems.Count > 0); // Determine whether dragged items may end in a FloatWindow. _canFloat = CanFloat(); // Store the mouse offset relative to the dragged element. _mouseOffset = (Vector)WindowsHelper.GetMousePosition(element); // Remember information needed for a rollback. ReplaceItemsWithProxies(draggedPane ?? _targetDockTabPane.GetViewModel()); _originalDockState = _draggedItems[0].DockState; BackupFloatWindowPosition(); // Override mouse cursors. (Mouse cursor should not change to caret over text editor.) Mouse.OverrideCursor = Cursors.Arrow; return true; }