예제 #1
0
        /// <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;
        }
예제 #2
0
 private void UpdateDockPaneContent()
 {
     if (IsSelected)
     {
         // DockTabItem is visible: Show new content in parent DockTabPane.
         DockTabPane?.UpdateSelectedContent();
     }
 }
예제 #3
0
        /// <summary>
        /// Registers the specified <see cref="DockTabPane"/>.
        /// </summary>
        /// <param name="dockTabPane">The <see cref="DockTabPane"/> to add.</param>
        internal void Register(DockTabPane dockTabPane)
        {
            Debug.Assert(dockTabPane != null);

            if (!_dockTabPanes.Contains(dockTabPane))
            {
                _dockTabPanes.Add(dockTabPane);
            }
        }
예제 #4
0
        protected internal virtual void OnDeactivated(RoutedEventArgs eventArgs)
        {
            Debug.Assert(IsActive, "DockTabItem.OnDeactivated should only be called when item is active.");

            IsActive = false;

            // Raise Deactivated event.
            Debug.Assert(eventArgs.RoutedEvent == DeactivatedEvent, "Invalid arguments for DockTabItem.OnDeactivated.");
            RaiseEvent(eventArgs);

            // Update visual states.
            UpdateVisualStates(true);
            DockTabPane?.UpdateVisualStates(true);
        }
예제 #5
0
        /// <summary>
        /// Gets the <see cref="DockTabItem"/> at the mouse position by testing against the
        /// <see cref="DockTabItem"/> tabs in the specified pane.
        /// </summary>
        /// <param name="dockTabPane">The <see cref="DockTabPane"/>.</param>
        /// <param name="verticalTolerance">
        /// The tolerance (margin at top and bottom) in pixels.
        /// </param>
        /// <returns>The <see cref="DockTabItem"/> under the mouse cursor.</returns>
        private static DockTabItem GetDockTabItemAtMouse(DockTabPane dockTabPane, double verticalTolerance = 0)
        {
            Debug.Assert(dockTabPane != null);

            if (dockTabPane.Items.Count == 0)
            {
                return(null);    // Empty DockTabPane.
            }
            var itemsPanel = dockTabPane.GetItemsPanel();

            if (itemsPanel == null)
            {
                return(null);    // ItemsPanel missing.
            }
            Point mousePosition = WindowsHelper.GetMousePosition(itemsPanel);

            Rect bounds = new Rect(itemsPanel.RenderSize);

            bounds.Inflate(0, verticalTolerance);
            if (!bounds.Contains(mousePosition))
            {
                return(null);    // Mouse position outside ItemsPanel.
            }
            // Test mouse position against DockTabItems bounds.
            double height = itemsPanel.RenderSize.Height;
            double x      = 0;

            for (int i = 0; i < dockTabPane.Items.Count; i++)
            {
                var dockTabItem = dockTabPane.ItemContainerGenerator.ContainerFromIndex(i) as DockTabItem;
                if (dockTabItem == null)
                {
                    break;
                }

                bounds = new Rect(new Point(x, 0), new Size(dockTabItem.RenderSize.Width, height));
                bounds.Inflate(0, verticalTolerance);
                if (bounds.Contains(mousePosition))
                {
                    return(dockTabItem);
                }

                x += bounds.Width;
            }

            return(null);
        }
예제 #6
0
        protected internal virtual void OnActivated(RoutedEventArgs eventArgs)
        {
            Debug.Assert(!IsActive, "DockTabItem.OnActivated should not be called when item is active.");

            // Set DockControl.ActiveDockTabPane/ActiveDockTabItem.
            SetActiveItem();

            IsActive = true;

            // Deactivate other DockTabItems and raise Deactivated event.
            DeactivateOtherItems();

            // Raise Activated event.
            Debug.Assert(eventArgs.RoutedEvent == ActivatedEvent, "Invalid arguments for DockTabItem.OnActivated.");
            RaiseEvent(eventArgs);

            // Update visual states.
            UpdateVisualStates(true);
            DockTabPane?.UpdateVisualStates(true);
        }
예제 #7
0
        /// <summary>
        /// Tries to move the dragged items from the <see cref="FloatWindow"/> into a
        /// <see cref="DockTabPanel"/>.
        /// </summary>
        private void DragFloatWindowIntoDockTabPanel()
        {
            Debug.Assert(_targetDockTabPane == null);
            Debug.Assert(_floatWindow != null);

            var dockTabPane = GetTargetPane() as DockTabPane;

            if (dockTabPane == null)
            {
                return; // No DockTabPane (view).
            }
            var dockTabPaneVM = dockTabPane.GetViewModel();

            if (dockTabPaneVM == null)
            {
                return; // No IDockTabPane (view-model).
            }
            if (GetDockTabItemAtMouse(dockTabPane) == null)
            {
                return; // No DockTabItem hit.
            }
            if (!CanDock(dockTabPaneVM, DockPosition.Inside))
            {
                return; // Docking not allowed.
            }
            // Remove currently dragged FloatWindow.
            var floatWindowVM = _floatWindow.GetViewModel();

            foreach (var item in _draggedItems)
            {
                DockHelper.Remove(floatWindowVM, item);
            }

            _floatWindow = null;
            Win32.ReleaseCapture(); // Exit Win32 move window loop.

            // Add items into target DockTabPane.
            _targetDockTabPane = dockTabPane;
            foreach (var item in _draggedItems)
            {
                item.DockState = dockTabPaneVM.DockState;
                dockTabPaneVM.Items.Add(item);
            }

            // Make sure the current item is selected in DockTabPane.
            _dockStrategy.Activate(_activeItem);

            // When the Win32 move window loop exits, the DockControl receives a LostMouseCapture
            // event. --> Defer dragging of the DockTabItems.
            _dockControl.Dispatcher.BeginInvoke(new Action(() =>
            {
                if (!_dockControl.IsMouseCaptured)
                {
                    if (!_dockControl.CaptureMouse())
                    {
                        // Failed to capture the mouse.
                        EndDrag(false);
                        return;
                    }
                    _dockControl.LostMouseCapture  += OnLostMouseCapture;
                    _dockControl.MouseMove         += OnMouseMove;
                    _dockControl.MouseLeftButtonUp += OnMouseLeftButtonUp;
                    _dockControl.PreviewKeyDown    += OnPreviewKeyDown;

                    _targetDockTabPane.PreviewKeyDown += OnPreviewKeyDown;

                    DragDockTabItems();
                }
            }));

            HideBorderDockIndicators();
            HidePaneIndicators();

            _dockControl.UpdateFloatWindows();

            _layoutChanged = true;
        }
예제 #8
0
        private void DragDockTabItemsIntoFloatWindow()
        {
            Debug.Assert(_floatWindow == null);

            if (_targetDockTabPane != null)
            {
                ClearTranslateTransform();

                _targetDockTabPane.PreviewKeyDown -= OnPreviewKeyDown;
                _targetDockTabPane = null;
            }

            _dockControl.LostMouseCapture  -= OnLostMouseCapture;
            _dockControl.MouseLeftButtonUp -= OnMouseLeftButtonUp;
            _dockControl.MouseMove         -= OnMouseMove;
            _dockControl.PreviewKeyDown    -= OnPreviewKeyDown;

            _dockControl.ReleaseMouseCapture();

            // Remove the dragged items from their current location.
            foreach (var item in _draggedItems)
            {
                DockHelper.Remove(_dockStrategy.DockControl.RootPane, item);

                foreach (var floatWindow in _dockStrategy.DockControl.FloatWindows)
                {
                    DockHelper.Remove(floatWindow, item);
                }

                DockHelper.Remove(_dockStrategy.DockControl.AutoHideLeft, item);
                DockHelper.Remove(_dockStrategy.DockControl.AutoHideRight, item);
                DockHelper.Remove(_dockStrategy.DockControl.AutoHideTop, item);
                DockHelper.Remove(_dockStrategy.DockControl.AutoHideBottom, item);
            }

            // Move items into a new FloatWindow.
            foreach (var item in _draggedItems)
            {
                item.DockState = DockState.Float;
            }

            var newPaneVM = _dockStrategy.CreateDockTabPane(_draggedItems[0], DockState.Float);

            for (int i = 1; i < _draggedItems.Count; i++)
            {
                newPaneVM.Items.Add(_draggedItems[i]);
            }

            var floatWindowVM = _dockStrategy.CreateFloatWindow();

            floatWindowVM.RootPane = newPaneVM;
            _dockStrategy.DockControl.FloatWindows.Add(floatWindowVM);
            _dockStrategy.Activate(_activeItem);
            _dockStrategy.Cleanup();

            // Get the newly created FloatWindow (view) from the DockControl.
            _floatWindow = GetFloatWindow(floatWindowVM);

            Debug.Assert(_floatWindow != null);

            LimitFloatWindowSize(_floatWindow, _initialSize);

            // Limit mouse offset to FloatWindow size.
            double actualWidth = _floatWindow.ActualWidth;

            if (actualWidth > 0)
            {
                _mouseOffset.X = Math.Min(_mouseOffset.X, actualWidth / 2);
            }

            Point position = GetFloatWindowPosition();

            _floatWindow.Left = position.X;
            _floatWindow.Top  = position.Y;

            // Wait until FloatWindow is loaded, initiate the Win32 move window loop.
            _floatWindow.Dispatcher.BeginInvoke(new Action(() =>
            {
                if (_floatWindow != null)
                {
                    LimitFloatWindowSize(_floatWindow, _initialSize);

                    // Limit mouse offset to FloatWindow size.
                    _mouseOffset.X = Math.Min(_mouseOffset.X, _floatWindow.ActualWidth / 2);
                    _mouseOffset.Y = Math.Max(_mouseOffset.Y, 8);

                    Point pos         = GetFloatWindowPosition();
                    _floatWindow.Left = pos.X;
                    _floatWindow.Top  = pos.Y;

                    if (Mouse.LeftButton == MouseButtonState.Pressed)
                    {
                        _floatWindow.DragMove();
                    }
                    else
                    {
                        EndDrag(true);
                    }
                }
            }), DispatcherPriority.Loaded); // Important: Action needs to be invoked before input.
        }
예제 #9
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);
        }
예제 #10
0
 /// <summary>
 /// Unregisters the specified <see cref="DockTabPane"/>.
 /// </summary>
 /// <param name="dockTabPane">The <see cref="DockTabPane"/> to remove.</param>
 internal void Unregister(DockTabPane dockTabPane)
 {
     _dockTabPanes.Remove(dockTabPane);
 }
예제 #11
0
        //internal static IDockAnchorPane GetViewModel(this DockAnchorPane view)
        //{
        //    return GetViewModel<IDockAnchorPane>(view);
        //}


        //internal static IDockSplitPane GetViewModel(this DockSplitPane view)
        //{
        //    return GetViewModel<IDockSplitPane>(view);
        //}


        internal static IDockTabPane GetViewModel(this DockTabPane view)
        {
            return(GetViewModel <IDockTabPane>(view));
        }