private static void TabControl_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) { TabControl sourceTabControl = (TabControl)sender; sourceTabControl.PreviewMouseLeftButtonUp -= TabTearOffBehavior.TabControl_PreviewMouseLeftButtonUp; sourceTabControl.PreviewMouseMove -= TabTearOffBehavior.TabControl_PreviewMouseMove; sourceTabControl.MouseLeave -= TabTearOffBehavior.TabControl_MouseLeaveOrLostCapture; sourceTabControl.LostMouseCapture -= TabTearOffBehavior.TabControl_MouseLeaveOrLostCapture; if (sourceTabControl.IsMouseCaptured) { TabItem tabItem = TabTearOffBehavior._activeTabItem; Point dragWindowLocation = new Point { X = TabTearOffBehavior._dragWindow.Left, Y = TabTearOffBehavior._dragWindow.Top }; sourceTabControl.ReleaseMouseCapture(); if (TabTearOffBehavior._adorner != null) { TabTearOffBehavior._adorner.Detach(); TabTearOffBehavior._adorner = null; } TabTearOffBehavior._dragWindow.Close(); TabTearOffBehavior._dragWindow = null; TabTearOffBehavior._activeTabItem = null; object item = sourceTabControl.ItemContainerGenerator.ItemFromContainer(tabItem); int sourceIndex = sourceTabControl.ItemContainerGenerator.IndexFromContainer(tabItem); Window dropWindow = TabTearOffBehavior.GetWindowMouseIsOver(e); TabControl targetTabControl; Panel targetPanel; ITabTearOffHandler targetHandler; if (dropWindow != null && TabTearOffBehavior.IsMouseInDropLocation(e, targetTabControl = TabTearOffBehavior.FindTargetTabControl(dropWindow, out targetHandler), targetPanel = ControlMethods.GetPanel(targetTabControl))) { int insertionIndex = TabTearOffBehavior.DetermineInsertionIndex(targetTabControl, e, targetPanel.GetOrientation()); if (!object.ReferenceEquals(sourceTabControl, targetTabControl)) { if (targetHandler.AllowTargetedDrop(item, sourceTabControl, sourceIndex, targetTabControl, insertionIndex)) { targetHandler.HandleTargetedDrop(item, sourceTabControl, sourceIndex, targetTabControl, insertionIndex); } } else if (sourceTabControl.Items.Count != 1 && insertionIndex != sourceIndex && targetHandler.AllowReorder(item, sourceTabControl, sourceIndex, insertionIndex)) { targetHandler.HandleReorder(item, sourceTabControl, sourceIndex, insertionIndex); } } else { ITabTearOffHandler sourceHandler = TabTearOffBehavior.GetHandler(sourceTabControl); if (sourceHandler.AllowTargetlessDrop(item, sourceTabControl, sourceIndex, dragWindowLocation)) { sourceHandler.HandleTargetlessDrop(item, sourceTabControl, sourceIndex, dragWindowLocation); } } } e.Handled = true; }
private static void TabControl_Loaded(object sender, RoutedEventArgs e) { TabControl tabControl = (TabControl)sender; tabControl.Loaded -= TabTearOffBehavior.TabControl_Loaded; TabTearOffBehavior.SetWindowMaintainZIndex(tabControl, true); }
private static void HandlerProperty_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TabControl tabControl = d as TabControl; if (tabControl == null) { return; } if (e.NewValue == null && e.OldValue != null) { WeakEventManager <TabControl, MouseButtonEventArgs> .RemoveHandler(tabControl, nameof(TabControl.PreviewMouseLeftButtonDown), TabTearOffBehavior.TabControl_PreviewMouseLeftButtonDown); if (!tabControl.IsLoaded) { tabControl.Loaded -= TabTearOffBehavior.TabControl_Loaded; } else { TabTearOffBehavior.SetWindowMaintainZIndex(tabControl, false); } } else if (e.NewValue != null && e.OldValue == null) { WeakEventManager <TabControl, MouseButtonEventArgs> .AddHandler(tabControl, nameof(TabControl.PreviewMouseLeftButtonDown), TabTearOffBehavior.TabControl_PreviewMouseLeftButtonDown); if (!tabControl.IsLoaded) { tabControl.Loaded += TabTearOffBehavior.TabControl_Loaded; } else { TabTearOffBehavior.SetWindowMaintainZIndex(tabControl, true); } } }
private static Window GetWindowMouseIsOver(MouseEventArgs args) { return(Application.Current.Windows .Cast <Window>() .Where(window => window.WindowState != WindowState.Minimized && TabTearOffBehavior.GetMaintainZIndex(window)) .OrderBy(TabTearOffBehavior.GetZIndex) .FirstOrDefault(window => VisualTreeHelper.GetDescendantBounds(window).Contains(args.GetPosition(window)))); }
private static void SetWindowMaintainZIndex(DependencyObject d, bool maintainZIndex) { Window window = Window.GetWindow(d); if (window == null) { throw new ArgumentException("TabControl is not in a window"); } TabTearOffBehavior.SetMaintainZIndex(window, maintainZIndex); }
public void Detach() { TabTearOffBehavior.SetIsDraggingOver(this.AdornedElement, false); this.AdornedElement.Loaded -= this.AdornedElement_Loaded; this.AdornedElement.Unloaded -= this.AdornedElement_Unloaded; if (this._adornerLayer == null) { return; } this._adornerLayer.Remove(this); this._adornerLayer = null; }
private static TabControl FindTargetTabControl(Window dropWindow, out ITabTearOffHandler handler) { handler = null; foreach (TabControl tabControl in dropWindow.GetVisualTreeDescendents <TabControl>()) { if ((handler = TabTearOffBehavior.GetHandler(tabControl)) != null) { return(tabControl); } } return(null); }
private static void Window_Activated(object sender, EventArgs e) { Window window = (Window)sender; int index = TabTearOffBehavior._windows.IndexOf(window); if (index == 0) { return; } TabTearOffBehavior._windows.RemoveAt(index); TabTearOffBehavior._windows.Insert(0, window); TabTearOffBehavior.AssignZIndices(); }
protected override void OnRender(DrawingContext drawingContext) { int insertionIndex = TabTearOffBehavior.DetermineInsertionIndex(this.AdornedElement, this._mouseEventArgs, this._orientation); ITabTearOffHandler handler = TabTearOffBehavior.GetHandler(this.AdornedElement); TabControl activeTabControl = TabTearOffBehavior._activeTabItem == null ? null : (TabControl)ItemsControl.ItemsControlFromItemContainer(TabTearOffBehavior._activeTabItem); if (activeTabControl == null || !this.AdornedElement.Equals(activeTabControl) && !handler.AllowTargetedDrop(activeTabControl.ItemContainerGenerator.ItemFromContainer(TabTearOffBehavior._activeTabItem), activeTabControl, activeTabControl.ItemContainerGenerator.IndexFromContainer(TabTearOffBehavior._activeTabItem), this.AdornedElement, insertionIndex) || this.AdornedElement.Equals(activeTabControl) && !handler.AllowReorder(activeTabControl.ItemContainerGenerator.ItemFromContainer(TabTearOffBehavior._activeTabItem), activeTabControl, activeTabControl.ItemContainerGenerator.IndexFromContainer(TabTearOffBehavior._activeTabItem), insertionIndex)) { return; } int index = Math.Min(insertionIndex, this.AdornedElement.Items.Count - 1); UIElement container; if ((container = (UIElement)this.AdornedElement.ItemContainerGenerator.ContainerFromIndex(index)) == null) { return; } Rect itemRect = new Rect(container.TranslatePoint(default(Point), this.AdornedElement), container.RenderSize); Point point1, point2; double rotation; if (this._orientation == Orientation.Vertical) { if (insertionIndex == this.AdornedElement.Items.Count) { itemRect.Y += container.RenderSize.Height; } point1 = new Point(itemRect.X - InsertionAdorner.Size, itemRect.Y); point2 = new Point(itemRect.Right + InsertionAdorner.Size, itemRect.Y); rotation = 0; } else { if (insertionIndex == this.AdornedElement.Items.Count) { itemRect.X += container.RenderSize.Width; } point1 = new Point(itemRect.X, itemRect.Y - InsertionAdorner.Size); point2 = new Point(itemRect.X, itemRect.Bottom + InsertionAdorner.Size); rotation = 90d; } InsertionAdorner.DrawArrow(drawingContext, point1, rotation); InsertionAdorner.DrawArrow(drawingContext, point2, 180d + rotation); }
public InsertionAdorner(TabControl adornedElement, Orientation orientation) : base(adornedElement) { if (!adornedElement.IsLoaded) { adornedElement.Loaded += this.AdornedElement_Loaded; } else { if ((this._adornerLayer = AdornerLayer.GetAdornerLayer(adornedElement)) != null) { this._adornerLayer.Add(this); } adornedElement.Unloaded += this.AdornedElement_Unloaded; } this._orientation = orientation; TabTearOffBehavior.SetIsDraggingOver(adornedElement, true); this.IsHitTestVisible = false; }
/// <summary> /// Handles the PreviewMouseLeftButtonDown event of the TabControl. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param> private static void TabControl_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { TabControl tabControl = (TabControl)sender; TabTearOffBehavior._activeTabItem = null; TabTearOffBehavior._dragStartPosition = default(Point); Point position = e.GetPosition(tabControl); HitTestResult result = VisualTreeHelper.HitTest(tabControl, position); if (result == null) { return; } TabItem tabItem = null; for (DependencyObject obj = result.VisualHit; obj != null; obj = VisualTreeHelper.GetParent(obj)) { ButtonBase button = obj as ButtonBase; if (button != null) { return; } if ((tabItem = obj as TabItem) != null) { break; } } if (tabItem == null || !tabControl.Equals(ItemsControl.ItemsControlFromItemContainer(tabItem)) || !TabTearOffBehavior.GetHandler(tabControl).IsDragAllowed(tabControl.ItemContainerGenerator.ItemFromContainer(tabItem), tabControl, tabControl.ItemContainerGenerator.IndexFromContainer(tabItem))) { return; } TabTearOffBehavior._activeTabItem = tabItem; TabTearOffBehavior._dragStartPosition = position; tabControl.PreviewMouseMove += TabTearOffBehavior.TabControl_PreviewMouseMove; tabControl.PreviewMouseLeftButtonUp += TabTearOffBehavior.TabControl_PreviewMouseLeftButtonUp; tabControl.MouseLeave += TabTearOffBehavior.TabControl_MouseLeaveOrLostCapture; tabControl.LostMouseCapture += TabTearOffBehavior.TabControl_MouseLeaveOrLostCapture; }
private static void MaintainZIndexProperty_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { Window window = d as Window; if (window == null) { return; } if ((bool)e.NewValue) { window.Activated += TabTearOffBehavior.Window_Activated; window.Closed += TabTearOffBehavior.Window_Closed; TabTearOffBehavior._windows.Add(window); } else if (TabTearOffBehavior._windows.Remove(window)) { window.ClearValue(TabTearOffBehavior._zIndexProperty); window.Activated -= TabTearOffBehavior.Window_Activated; window.Closed -= TabTearOffBehavior.Window_Closed; } TabTearOffBehavior.AssignZIndices(); }
private static void Window_Closed(object sender, EventArgs e) { TabTearOffBehavior.SetMaintainZIndex((Window)sender, false); }
private static void TabControl_PreviewMouseMove(object sender, MouseEventArgs e) { TabControl tabControl = (TabControl)sender; Point point = e.GetPosition(tabControl); if (tabControl.IsMouseCaptured) { TabTearOffBehavior.UpdateDragWindowLocation(tabControl); Window dropWindow = TabTearOffBehavior.GetWindowMouseIsOver(e); if (dropWindow == null) { return; } if (!dropWindow.IsActive) { dropWindow.Activate(); } ITabTearOffHandler targetHandler; TabControl targetTabControl = TabTearOffBehavior.FindTargetTabControl(dropWindow, out targetHandler); Panel panel = ControlMethods.GetPanel(targetTabControl); if (TabTearOffBehavior.IsMouseInDropLocation(e, targetTabControl, panel)) { if (TabTearOffBehavior._adorner == null || !TabTearOffBehavior._adorner.AdornedElement.Equals(targetTabControl)) { if (TabTearOffBehavior._adorner != null) { TabTearOffBehavior._adorner.Detach(); } TabTearOffBehavior._adorner = new InsertionAdorner(targetTabControl, panel.GetOrientation()); } TabTearOffBehavior._adorner.UpdateLocation(e); } else if (TabTearOffBehavior._adorner != null) { TabTearOffBehavior._adorner.Detach(); TabTearOffBehavior._adorner = null; } } else if (TabTearOffBehavior.IsSufficientDragMove(point)) { Rectangle contentRectangle = TabTearOffBehavior.CreateRectangle((Visual)TabTearOffBehavior.GetContent(tabControl)); Rectangle tabItemRectangle = TabTearOffBehavior.CreateRectangle(TabTearOffBehavior._activeTabItem); Panel.SetZIndex(tabItemRectangle, 10); StackPanel stackPanel = new StackPanel { Orientation = tabControl.TabStripPlacement == Dock.Right || tabControl.TabStripPlacement == Dock.Left ? Orientation.Horizontal : Orientation.Vertical, Children = { tabItemRectangle } }; stackPanel.Children.Insert(tabControl.TabStripPlacement == Dock.Right || tabControl.TabStripPlacement == Dock.Bottom ? 0 : 1, contentRectangle); TranslateTransform translateTransform = new TranslateTransform(); switch (tabControl.TabStripPlacement) { case Dock.Bottom: translateTransform.Y = -1d; break; case Dock.Left: translateTransform.X = 1d; break; case Dock.Right: translateTransform.X = -1d; break; case Dock.Top: translateTransform.Y = 1d; break; } tabItemRectangle.RenderTransform = translateTransform; TabTearOffBehavior._dragWindow = new Window { Topmost = true, AllowsTransparency = true, WindowStyle = WindowStyle.None, IsHitTestVisible = false, SizeToContent = SizeToContent.WidthAndHeight, Background = Brushes.Transparent, Content = new Border { Child = stackPanel, Opacity = 0.75 } }; TabTearOffBehavior.UpdateDragWindowLocation(tabControl); TabTearOffBehavior._dragWindow.Show(); tabControl.MouseLeave -= TabTearOffBehavior.TabControl_MouseLeaveOrLostCapture; tabControl.CaptureMouse(); e.Handled = true; } }