HitTestFilterBehavior HitTestFilter(DependencyObject potentialHit) { if (this.tabHitTesting) { TabItem item = potentialHit as TabItem; if (item != null && item.Visibility == Visibility.Visible && item.DataContext is LayoutDefinition) { this.hitTestTabItem = item; return(HitTestFilterBehavior.Stop); } return(HitTestFilterBehavior.Continue); } else { ViewDockSpot spot = potentialHit as ViewDockSpot; if (spot != null && spot.IsHitTestVisible) { this.hitTestSpot = spot; return(HitTestFilterBehavior.Stop); } return(HitTestFilterBehavior.Continue); } }
HitTestFilterBehavior HitTestFilter(DependencyObject potentialHit) { if (this.tabHitTesting) { TabItem item = potentialHit as TabItem; if (item != null && item.Visibility == Visibility.Visible && item.DataContext is LayoutDefinition) { this.hitTestTabItem = item; return HitTestFilterBehavior.Stop; } return HitTestFilterBehavior.Continue; } else { ViewDockSpot spot = potentialHit as ViewDockSpot; if (spot != null && spot.IsHitTestVisible) { this.hitTestSpot = spot; return HitTestFilterBehavior.Stop; } return HitTestFilterBehavior.Continue; } }
void UpdateHitState(Point pos) { LayoutControl targetLayout = this.CurrentLayout; bool ghostPositionSet = false; this.dockTargetSlot = null; this.dragGhostWindow.CancelReason = "To place the view, drag over an empty layout, an existing view, or a docking target."; if (targetLayout != null) { var posInLayout = Mouse.GetPosition(targetLayout); var rect = new Rect(0, 0, targetLayout.ActualWidth, targetLayout.ActualHeight); if (rect.Contains(posInLayout)) { this.dockTargetSlot = targetLayout.GetSlotUnderPoint(Mouse.GetPosition(targetLayout)); } else { targetLayout = null; } if (this.dockTargetSlot != null) { if (this.creatorBeingDragged != null) { if (this.creatorBeingDragged.Category.DocumentFactoryName != null && targetLayout.LayoutInstance.LayoutDefinition.DocumentFactoryName != this.creatorBeingDragged.Category.DocumentFactoryName) { // The creator being dragged is affinitized with a particular document type which is not the same type as the active // layout. Disallow the drop. this.dockTargetSlot = null; this.dragGhostWindow.CancelReason = string.Format(CultureInfo.InvariantCulture, "This view can only be placed in a {0} layout.", this.creatorBeingDragged.Category.DisplayName); } else if (this.creatorBeingDragged.Command.IsSingleInstancePerLayout && (targetLayout.LayoutInstance.LayoutDefinition.ViewSources.Any(vs => vs.ViewCreator == this.creatorBeingDragged.Command))) { // This is a single-instance-per-layout view that already exists in the layout. No dice. this.dockTargetSlot = null; this.dragGhostWindow.CancelReason = "Only one instance of this view type can exist in a layout."; } else if (this.creatorBeingDragged.Command.IsSingleInstance) { var existingSource = ToolsUIApplication.Instance.LayoutDefinitions.SelectMany(d => d.ViewSources).Where(vs => vs.ViewCreator == this.creatorBeingDragged.Command).FirstOrDefault(); if (existingSource != null) { // This is a single-instance view that already exists in a layout (perhaps not even this one). this.dockTargetSlot = null; this.dragGhostWindow.CancelReason = string.Format(CultureInfo.InvariantCulture, "This view already exists in the '{0}' layout. Only one instance of this view type can be created.", existingSource.Parent.Header); } } } } } if (this.dockTargetSlot != null) { this.layout = targetLayout; if (this.dockTargetWindow == null) { this.dockTargetWindow = new ViewDropTargetWindow(); } var rect = targetLayout.GetSlotScreenRect(this.dockTargetSlot); this.dockTargetWindow.Left = rect.X; this.dockTargetWindow.Top = rect.Y; this.dockTargetWindow.Width = rect.Width; this.dockTargetWindow.Height = rect.Height; this.dockTargetWindow.IsTabbedSpotVisible = true; this.dockTargetWindow.RootSlot = targetLayout.LayoutInstance.LayoutDefinition.SlotDefinition; this.dockTargetWindow.TargetSlot = this.dockTargetSlot; this.dockTargetWindow.AreDockSpotsVisible = targetLayout.LayoutInstance.LayoutDefinition.ViewSources.Count > 0; this.dockTargetWindow.Show(); this.hitTestSpot = null; this.tabHitTesting = false; VisualTreeHelper.HitTest(this.dockTargetWindow, this.HitTestFilter, this.HitTestResult, new PointHitTestParameters(Mouse.GetPosition(this.dockTargetWindow))); if (this.hitTestSpot != null) { var spot = this.hitTestSpot; if (spot != null && spot.DestinationSlot != null) { rect = targetLayout.GetSlotScreenRect(spot.DestinationSlot); this.dragGhostWindow.CancelMode = false; this.dragGhostWindow.CancelReason = null; if (spot.IsTabbed) { this.dragGhostWindow.Left = rect.X; this.dragGhostWindow.Top = rect.Y; this.dragGhostWindow.Width = rect.Width; this.dragGhostWindow.Height = rect.Height; } else { switch (spot.Dock) { case Dock.Top: this.dragGhostWindow.Left = rect.X; this.dragGhostWindow.Top = rect.Y; this.dragGhostWindow.Width = rect.Width; this.dragGhostWindow.Height = rect.Height / 2; break; case Dock.Bottom: this.dragGhostWindow.Width = rect.Width; this.dragGhostWindow.Height = rect.Height / 2; this.dragGhostWindow.Left = rect.X; this.dragGhostWindow.Top = rect.Y + this.dragGhostWindow.Height; break; case Dock.Left: this.dragGhostWindow.Left = rect.X; this.dragGhostWindow.Top = rect.Y; this.dragGhostWindow.Width = rect.Width / 2; this.dragGhostWindow.Height = rect.Height; break; case Dock.Right: this.dragGhostWindow.Width = rect.Width / 2; this.dragGhostWindow.Height = rect.Height; this.dragGhostWindow.Left = rect.X + this.dragGhostWindow.Width; this.dragGhostWindow.Top = rect.Y; break; } } ghostPositionSet = true; } } else { // Didn't even hit the tabbed spot (the transparent rect covering the whole slot), so must be in // the margin. Tear down the dock target window. (Won't flicker because it fades in...) this.dockTargetWindow.Close(); this.dockTargetWindow = null; this.dockTargetSlot = null; } } else { if (this.dockTargetWindow != null) { this.dockTargetWindow.Close(); this.dockTargetWindow = null; } this.layout = null; // See if the mouse is over a layout tab. If so, select it. this.tabHitTesting = true; this.hitTestTabItem = null; VisualTreeHelper.HitTest(this.tabControl, this.HitTestFilter, this.HitTestResult, new PointHitTestParameters(Mouse.GetPosition(this.tabControl))); if (this.hitTestTabItem != null) { var layoutDef = this.hitTestTabItem.DataContext as LayoutDefinition; if (layoutDef != null) { this.tabControl.SelectedItem = layoutDef; } } } if (!ghostPositionSet) { this.dragGhostWindow.Width = 200; this.dragGhostWindow.Height = 200; this.dragGhostWindow.Left = pos.X; this.dragGhostWindow.Top = pos.Y; this.dragGhostWindow.CancelMode = true; } }