private bool IsTileOnPageLeft(MetroStartPage targetPage, FrameworkElement tile) { var target = targetPage.MainContent != null ? targetPage.MainContent : targetPage; Point tileLeft = tile.TransformToAncestor(target).Transform(new Point(0, 0)); return(tileLeft.X <= tile.Margin.Left); }
private bool IsTileOnPageRight(MetroStartPage targetPage, FrameworkElement tile) { var target = targetPage.MainContent != null ? targetPage.MainContent : targetPage; Point tileRight = tile.TransformToAncestor(target).Transform(new Point(tile.Width, tile.Height)); return(tileRight.X >= target.ActualWidth - tile.Margin.Left); }
private bool IsTileOnPageBottom(MetroStartPage targetPage, FrameworkElement tile) { var target = targetPage.MainContent != null ? targetPage.MainContent : targetPage; Point tileBottom = tile.TransformToAncestor(target).Transform(new Point(tile.Width, tile.Height)); return(tileBottom.Y >= target.ActualHeight - tile.Margin.Bottom); }
private void CleanUpAfterDrag() { var window = Window.GetWindow(_MetroControl); window.ClearValue(Window.AllowDropProperty); window.DragEnter -= HandleDrag; window.DragOver -= HandleDrag; window.DragLeave -= HandleDrag; window.Drop -= HandleDrop; window.GiveFeedback -= HandleGiveFeedback; VisualStateManager.GoToState(_DragTile, "IsNotDragSource", true); if (_DragAdorner != null) { _DragAdorner.Detach(); } if (_ScrollHelper != null) { _ScrollHelper.Stop(); } _DragAdorner = null; _DragSourcePage = null; _DragTile = null; _DragData = null; _TileDropHelper = null; _ScrollHelper = null; _NewPageHelper = null; }
private void ClearSpreadPageStates() { if (_SpreadPageLeft != null) { VisualStateManager.GoToState(_SpreadPageLeft, "NoSpread", true); _SpreadPageLeft = null; } if (_SpreadPageRight != null) { VisualStateManager.GoToState(_SpreadPageRight, "NoSpread", true); _SpreadPageRight = null; } }
public bool UpdateView(Point hitPoint, bool clear) { if (clear) { Clear(); return(false); } Point testPoint = _DragHelper.TranslateHitPoint(hitPoint, _DragHelper._MetroControlPanel); _DropPage = _DragHelper._MetroControlPanel.HitTestForOne <MetroStartPage>(testPoint); if (_DropPage == null) { Clear(); return(false); } SetDropTargetTiles(_DragHelper.TranslateHitPoint(hitPoint, _DropPage), _DropPage); return(true); }
private Dock GetHitSide(MetroStartPage targetPage, MetroTile hitTile, MetroTile dragTile, Point pos) { // For vertically oriented pages, if dragging a small tile and the hit tile is also small, // treat as if horizontal oriented. if (targetPage.Orientation == Orientation.Vertical && !(hitTile.Type == MetroTileType.Small && dragTile.Type == MetroTileType.Small)) { double dY = (hitTile.RenderSize.Height / 2) - pos.Y; if (dY > 0) { return(Dock.Top); } return(Dock.Bottom); } else { double dX = (hitTile.RenderSize.Width / 2) - pos.X; if (dX > 0) { return(Dock.Left); } return(Dock.Right); } }
private void PrepareForDrag() { var window = Window.GetWindow(_MetroControl); window.AllowDrop = true; window.DragEnter += HandleDrag; window.DragOver += HandleDrag; window.DragLeave += HandleDrag; window.Drop += HandleDrop; window.GiveFeedback += HandleGiveFeedback; if (_MetroControlPanel == null) { _MetroControlPanel = _MetroControl.GetItemsHost(); } VisualStateManager.GoToState(_DragTile, "IsDragSource", true); _DragSourcePage = _DragTile.GetVisualParent <MetroStartPage>(); _DragData = _DragSourcePage != null?_DragSourcePage.ItemContainerGenerator.ItemFromContainer(_DragTile) : null; var adornerTemplate = (DataTemplate)_MetroControl.FindResource(MetroControl.DragAdornerDataTemplateKey); _DragAdorner = new TemplatedDragDropAdorner(_MetroControl, adornerTemplate, _DragData); _AdornerOffset = _MetroControl.TranslatePoint(_MouseDownPosition, _DragTile); _CenterOffset = new Point(); _CenterOffset.Offset((_DragTile.RenderSize.Width / 2) - _AdornerOffset.X, (_DragTile.RenderSize.Height / 2) - _AdornerOffset.Y); _TileDropHelper = new TileDropHelper(this); _ScrollHelper = new AutoScrollHelper(this); if (CanCreateNewPages()) { _NewPageHelper = new DragTileIntoNewPageHelper(this); } }
private bool DoDrop() { if (_SpreadPageLeft == null && _SpreadPageRight == null) { return(false); } // Can't rely on Parent Items.Count... int index = -1; if (_SpreadPageRight != null) { index = _DragHelper._MetroControl.ItemContainerGenerator.IndexFromContainer(_SpreadPageRight); } object newPageItem = null; if (_DragHelper._MetroControl.ItemsSource == null) { newPageItem = new MetroStartPage(); if (index >= 0) { _DragHelper._MetroControl.Items.Insert(index, newPageItem); } else { _DragHelper._MetroControl.Items.Add(newPageItem); } } else { // Can't insert into Items when ItemsSource is in use. Made check when setting up // MetroControl as drop target to ensure that the data type used for ItemsSource // has a default constructor. var pageDataType = _DragHelper._MetroControl.ItemContainerGenerator.ItemFromContainer(_DragHelper._DragSourcePage).GetType(); var constructor = pageDataType.GetConstructor(System.Type.EmptyTypes); dynamic page = constructor.Invoke(null); // Also made check that ItemsSource is a list, but it might be generic and might not be generic, // so use dynamic here so it won't matter when making call to insert. dynamic list = _DragHelper._MetroControl.ItemsSource; if (index >= 0) { list.Insert(index, page); } else { list.Add(page); } newPageItem = page; } _DragHelper._DragSourcePage.RemoveItem(_DragHelper._DragData); // Dispatch method call to add tile data to new page, so the new page has time to be created. _DragHelper._MetroControl.Dispatcher.BeginInvoke( new Action <MetroControl, object, object, int>(AddDraggedDataToNewPageDispatcherCallback), DispatcherPriority.ApplicationIdle, _DragHelper._MetroControl, newPageItem, _DragHelper._DragData, 0); return(true); }
private bool SpreadPages(Point hitPoint) { MetroStartPage pageLeft = null, pageRight = null; bool doSearch = true; var testPoint = _DragHelper.TranslateHitPoint(hitPoint, _DragHelper._MetroControlPanel); if (testPoint.Y < 0 || testPoint.Y > _DragHelper._MetroControlPanel.ActualHeight) { doSearch = false; } var hitPage = _DragHelper._MetroControlPanel.HitTestForOne <MetroStartPage>(testPoint); if (hitPage != null) { if (hitPage.MainContent != null) { var contentPos = _DragHelper.TranslateHitPoint(hitPoint, hitPage.MainContent); if (contentPos.X < 0) { pageRight = hitPage; } else if (contentPos.X > hitPage.MainContent.ActualWidth) { pageLeft = hitPage; } } } if (doSearch) { int leftIndex = 0; if (pageLeft != null) { leftIndex = _DragHelper._MetroControl.ItemContainerGenerator.IndexFromContainer(pageLeft) + 1; } int rightIndex = _DragHelper._MetroControl.Items.Count; if (pageRight != null) { rightIndex = _DragHelper._MetroControl.ItemContainerGenerator.IndexFromContainer(pageRight); } for (int i = leftIndex; i < rightIndex; i++) { var page = _DragHelper._MetroControlPanel.Children[i] as MetroStartPage; // Pages are separated by margins on grids defined in their templates. The // grids don't have background set so drag events make it through. Here we're // getting the visible portion of the page against which to test mouse position. var visible = page.MainContent; if (visible == null) { visible = page; } var hitPos = _DragHelper.TranslateHitPoint(hitPoint, visible); if (visible.IsPointWithin(hitPos)) { pageLeft = pageRight = null; break; } else if (hitPos.X < 0) { pageRight = page; break; } else if (hitPos.X > visible.ActualWidth) { pageLeft = page; } } if (_DragHelper._DragSourcePage.Items.Count == 1 && (pageLeft == _DragHelper._DragSourcePage || pageRight == _DragHelper._DragSourcePage)) { pageRight = pageLeft = null; } } if (pageLeft != _SpreadPageLeft) { if (_SpreadPageLeft != null) { VisualStateManager.GoToState(_SpreadPageLeft, "NoSpread", true); } if (pageLeft != null) { VisualStateManager.GoToState(pageLeft, "SpreadLeft", true); } _SpreadPageLeft = pageLeft; } if (pageRight != _SpreadPageRight) { if (_SpreadPageRight != null) { VisualStateManager.GoToState(_SpreadPageRight, "NoSpread", true); } if (pageRight != null) { VisualStateManager.GoToState(pageRight, "SpreadRight", true); } _SpreadPageRight = pageRight; } return(pageLeft != null || pageRight != null); }
private MetroTile FindSecondaryTargetTile(MetroStartPage targetPage, MetroTile targetTile, MetroTile dragTile, Dock hitSide, out int dropIndex) { int targetIndex = targetPage.ItemContainerGenerator.IndexFromContainer(targetTile); dropIndex = targetIndex; if (targetTile == _DragHelper._DragTile) { return(null); } int sourceIndex = targetPage.ItemContainerGenerator.IndexFromContainer(dragTile); if (sourceIndex < 0) { sourceIndex = int.MaxValue; } int secondaryIndex = -1; if (hitSide == Dock.Top) { if (!IsTileOnPageTop(targetPage, targetTile)) { secondaryIndex = targetIndex - 1; } if (sourceIndex < targetIndex) { dropIndex--; } } else if (hitSide == Dock.Bottom) { if (!IsTileOnPageBottom(targetPage, targetTile)) { secondaryIndex = targetIndex + 1; } if (sourceIndex > targetIndex) { dropIndex++; } } else if (hitSide == Dock.Left) { if (!IsTileOnPageLeft(targetPage, targetTile)) { secondaryIndex = targetIndex - 1; } if (sourceIndex < targetIndex) { dropIndex--; } } else if (hitSide == Dock.Right) { if (!IsTileOnPageRight(targetPage, targetTile)) { secondaryIndex = targetIndex + 1; } if (sourceIndex > targetIndex) { dropIndex++; } } MetroTile secondary = null; if (secondaryIndex >= 0 && secondaryIndex < targetPage.Items.Count) { secondary = targetPage.ItemContainerGenerator.ContainerFromIndex(secondaryIndex) as MetroTile; // special case handling for when dropping small tile into empty space beside another small tile, // in this situation there should be no secondary. if (secondary != null && secondary.Type != MetroTileType.Small && secondary != dragTile && targetTile.Type == MetroTileType.Small && dragTile.Type == MetroTileType.Small) { secondary = null; } } return(secondary); }
private void SetDropTargetTiles(Point position, MetroStartPage dropTargetPage) { var dragTile = _DragHelper._DragTile; bool suppressAnimation = false; MetroTile secondaryTarget = null, target2 = null, secondaryTarget2 = null; var target = dropTargetPage.HitTestForOne <MetroTile>(position, _DragHelper._DragTile.Margin); if (target == null && dragTile.Type == MetroTileType.Small) { target = dropTargetPage.HitTestForOne <MetroTile>(position, new Thickness(0, 0, dragTile.Width, 0)); if (target != null && target.Type == MetroTileType.Large) { target = null; } suppressAnimation = true; } Dock hitSide = Dock.Left; if (target != null) { hitSide = GetHitSide(dropTargetPage, target, dragTile, dropTargetPage.TranslatePoint(position, target)); // If vertical orientation, and hitting a small tile, there might be another small tile beside it which also needs to be animated. if (_DropPage.Orientation == Orientation.Vertical && target.Type == MetroTileType.Small && dragTile.Type == MetroTileType.Large) { int index, adjacentIndex; target2 = FindAdjacentSmallTile(target, out index, out adjacentIndex); if (target2 != null) { // Might need to switch target and target2 because target defines the insertion index. if ((hitSide == Dock.Top && adjacentIndex < index) || (hitSide == Dock.Bottom && adjacentIndex > index)) { var temp = target; target = target2; target2 = temp; } } } // Look for secondary drop target if not dropping onto self or not dropping one small tile onto another small tile. secondaryTarget = FindSecondaryTargetTile(dropTargetPage, target, dragTile, hitSide, out _DropIndex); if (secondaryTarget != null && _DropPage.Orientation == Orientation.Vertical && secondaryTarget.Type == MetroTileType.Small && dragTile.Type == MetroTileType.Large) { int index, adjacentIndex; secondaryTarget2 = FindAdjacentSmallTile(secondaryTarget, out index, out adjacentIndex); } } else { _DropIndex = _DropPage.Items.Count; if (_DragHelper._DragSourcePage == _DropPage) { _DropIndex--; } } if (!suppressAnimation) { UpdateDropTargetTiles(target, target2, secondaryTarget, secondaryTarget2, hitSide); } else { UpdateDropTargetTiles(null, null, null, null, Dock.Left); } }