private void AvailableControls_MouseMove(object sender, MouseEventArgs e) { Point mousePos = e.GetPosition(null); Vector motion = controlDragStartPoint - mousePos; if (e.LeftButton == MouseButtonState.Pressed && (Math.Abs(motion.X) > SystemParameters.MinimumHorizontalDragDistance || Math.Abs(motion.Y) > SystemParameters.MinimumVerticalDragDistance)) { Border source = ((DependencyObject)e.OriginalSource).FindAncestor <Border>(); if (source == null) { return; } StackPanel p = source.Child as StackPanel; //the first child is the label, the second is a separator, and the third is the tilegrid TileGrid tileGrid = p.Children.Cast <UIElement>().Last() as TileGrid; //the tilegrid's only child is the control! SourcedControl c = tileGrid.Children.Cast <UIElement>().Last() as SourcedControl; //get the source control type info to pass to the dragdrop Type controlType = c.GetType(); DataObject dragInfo = new DataObject(NetworkDataFormats.SourcedControl, controlType); DragDrop.DoDragDrop(source, dragInfo, DragDropEffects.Copy | DragDropEffects.Move); tray.Show(); } }
private void DashboardRoot_Drop(object sender, DragEventArgs e) { if (e.KeyStates.HasFlag(DragDropKeyStates.ControlKey) && e.Data.GetDataPresent(NetworkDataFormats.NetworkElement)) { //offer to create the bound control here NetworkElement dataSource = (NetworkElement)e.Data.GetData(NetworkDataFormats.NetworkElement); //all available types IEnumerable <Type> controlTypes = PluginLoader.GetControls(); IEnumerable <Type> allowedControls; //check whether this is a primitive or complex data and filter the controls appropriately if (dataSource.Type == typeof(NetworkTree)) { //get the expected type of the element NetworkTable table = NetworkTable.GetTable(dataSource.FullPath); string dataType = table.GetString("type", null); allowedControls = controlTypes .Where((t) => SourcedControl.GetAllowedComplexTypes(t).Contains(dataType)); } else { allowedControls = controlTypes .Where((t) => SourcedControl.GetAllowedPrimitiveTypes(t).Contains(dataSource.Type)); } if (allowedControls.Count() != 0) { ControlPreviewDialog previewDialog = new ControlPreviewDialog(); PopulateControlPreviewWrapPanel(previewDialog.availableControls, allowedControls); if (previewDialog.ShowDialog() == true) { Type controlType = previewDialog.SelectedType; if (controlType != null) { SourcedControl c = (SourcedControl)controlType.GetConstructor(Type.EmptyTypes).Invoke(null); PlaceAtDropPoint(c, e); dashboardRoot.Children.Add(c); c.Source = dataSource.FullPath.Replace("/SmartDashboard/", ""); } } } else { MessageBox.Show("There are no controls that can display this entry!", "Error", MessageBoxButton.OK, MessageBoxImage.Exclamation); } } else if (e.Data.GetDataPresent(NetworkDataFormats.SourcedControl)) { //create the control here Type controlType = (Type)e.Data.GetData(NetworkDataFormats.SourcedControl); SourcedControl c = (SourcedControl)controlType.GetConstructor(Type.EmptyTypes).Invoke(null); PlaceAtDropPoint(c, e); dashboardRoot.Children.Add(c); } e.Handled = true; }
private void PopulateControlPreviewWrapPanel(WrapPanel wp, IEnumerable <Type> controlTypes) { wp.Children.Clear(); foreach (Type controlType in controlTypes) { //do some fancy arranging. what we need: //size-to-fit border (plus some extra space) with transparent background to register the hits. //label the extra space with the name of the control SourcedControl c = (SourcedControl)controlType.GetConstructor(Type.EmptyTypes).Invoke(null); c.IsEnabled = false; double expectedWidth = TileGrid.GetColumnSpan(c) * 50; double expectedHeight = TileGrid.GetRowSpan(c) * 50; TileGrid container = new TileGrid() { ShowGridlines = false, IsEditable = false, TileSizingMode = TileSizingMode.Uniform, Width = expectedWidth, Height = expectedHeight, Background = new SolidColorBrush(Colors.Transparent) }; container.Children.Add(c); Border outline = new Border() { Background = new SolidColorBrush(Colors.Transparent), BorderBrush = new SolidColorBrush(Colors.Black), BorderThickness = new Thickness(1), Margin = new Thickness(5) }; StackPanel p = new StackPanel(); outline.Child = p; TextBlock label = new TextBlock() { Text = Util.ToTitleCase(controlType.Name), Margin = new Thickness(2) }; p.Children.Add(label); p.Children.Add(new Separator()); p.Children.Add(container); wp.Children.Add(outline); } }
private void PlaceAtDropPoint(SourcedControl c, DragEventArgs e) { Point dropPoint = e.GetPosition(dashboardRoot); //centering. goal: if there span is even, we want to center on nearest line, //if span is odd, center the nearest full tile //for even, rounding works because the division causes the control to tend towards the left int colSpan = TileGrid.GetColumnSpan(c); int rowSpan = TileGrid.GetRowSpan(c); double preciseCol = dropPoint.X / dashboardRoot.GetColumnWidth(); double preciseRow = dropPoint.Y / dashboardRoot.GetRowHeight(); int col = colSpan % 2 == 0 ? (int)Math.Round(preciseCol) : (int)Math.Floor(preciseCol); int row = rowSpan % 2 == 0 ? (int)Math.Round(preciseRow) : (int)Math.Floor(preciseRow); int colOffset = colSpan / 2; int rowOffset = rowSpan / 2; col = Math.Max(col - colOffset, 0); row = Math.Max(row - rowOffset, 0); TileGrid.SetColumn(c, col); TileGrid.SetRow(c, row); }