/// <summary> /// Checking if the source item can be dropped into the target item /// </summary> /// <param name="sourceItem"></param> /// <param name="targetItem"></param> /// <returns></returns> private bool CheckDropTarget(MRecipeBaseNode sourceItem, MRecipeBaseNode targetItem) { return( sourceItem.GetType() == targetItem.GetType() || sourceItem.Parent?.GetType() == targetItem.GetType() ); }
public void SelectNode(MRecipeBaseNode node) { if ( node != null && _lastSelectedNode != node ) { _lastSelectedNode = node; RecipeItemSelectedCommand?.Execute(node); } }
/// <summary> /// This event occurs when mouse is moved.Here first we check whether /// left mouse button is pressed or not.Then check the distance mouse /// moved if it moves outside the selected treeview item, then check /// the drop effect if it's dragged (move) and then dropped over a /// TreeViewItem (i.e. target is not null) then copy the selected /// item in dropped item. In this event, you can put your desired /// condition for dropping treeviewItem. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void TreeView_MouseMove(object sender, MouseEventArgs e) { try { if (e.LeftButton == MouseButtonState.Pressed) { Point currentPosition = e.GetPosition(RecipeTreeView); if ( (Math.Abs(currentPosition.X - _lastMouseDown.X) > 10.0) || (Math.Abs(currentPosition.Y - _lastMouseDown.Y) > 10.0) ) { _draggedItem = (MRecipeBaseNode)RecipeTreeView.SelectedItem; if (RecipeTreeView != null) { var finalDropEffect = DragDrop.DoDragDrop( RecipeTreeView, RecipeTreeView.SelectedValue, DragDropEffects.Move ); //Checking target is not null and item is dragging(moving) if ( (finalDropEffect == DragDropEffects.Move) && (_target != null) ) { // A Move drop was accepted - prevent drop on itself if (_draggedItem != _target) { // handle drop CopyItem(_draggedItem, _target); _target = null; _draggedItem = null; } } } } } } catch (Exception) { } }
public virtual void AddRecipeNode(MRecipe recipe, MRecipeBaseNode recipeNode) { if (recipe == null || recipeNode == null) { return; } var extents = GeometryExtents <double> .CreateDefaultDouble(); MRecipe.BeginGetAllLayers_Parallel(recipeNode, (layer) => { extents = GeometryExtents <double> .Combine( extents, AddLayer(recipe, layer) ); }); // calculate size of fiducial relative to the node var fiducialSize = 0.025 * extents.Hypotenuse; // generate fiducial pattern GenerateFiducialPattern(fiducialSize); // get node's transform var parentsTransform = (recipeNode.Parent as MRecipeBaseNode)?.TransformInfo.ToMatrix4x4() ?? GeometricArithmeticModule.GetDefaultTransformationMatrix(); // render fiducials in parent's reference frame foreach (var fiducial in recipeNode.Fiducials) { var transform = GeometricArithmeticModule.CombineTransformations( GeometricArithmeticModule.GetTranslationTransformationMatrix( fiducial.X, fiducial.Y, fiducial.Z ), parentsTransform ); foreach (var geometry in _fiducialPattern) { var clone = (IMarkGeometry)geometry.Clone(); clone.Transform(transform); AddDefault(clone, FiducialColor); } } }
/// <summary> /// This event occurs when an object is dropped on the drop target. /// Here we check whether the dropped item is dropped on a /// TreeViewItem or not. If yes, then set drop effect to none /// and the target item into a variable. And then MouseMove /// event completes the drag and drop operation. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void TreeView_Drop(object sender, DragEventArgs e) { try { e.Effects = DragDropEffects.None; e.Handled = true; // Verify that this is a valid drop and then store the drop target var targetItem = GetNearestContainer(e.OriginalSource); if (targetItem != null && _draggedItem != null) { _target = targetItem; e.Effects = DragDropEffects.Move; } } catch (Exception) { } }
public void UpdateItemsSource() { if (RecipeItemsSource != null) { _lastSelectedNode = null; _mRecipe = RecipeItemsSource; if (_undoRedoHelper?.IsPaused != true) { _undoRedoHelper = new UndoRedoHelper <MRecipe>(ref _mRecipe); MRecipe.BeginGetNodes(_mRecipe, (baseNode) => { _undoRedoHelper.SaveStateOnPropertyChange(baseNode); }); _undoRedoHelper.SaveState(); } NotifyPropertyChanged(nameof(MRecipe)); } }
public IProcessConfigurationTasksHandler GetClosestConfigurationTasksHandler(MRecipeBaseNode startNode) { if (startNode is MRecipePlate plate) { return(_model.GetProcessConfigurationTaskHandler( plate.Devices.FirstOrDefault()?.Layers.FirstOrDefault()?.TargetProcessMode )); } else if (startNode is MRecipeDevice device) { return(_model.GetProcessConfigurationTaskHandler( device.Layers.FirstOrDefault()?.TargetProcessMode )); } else if (startNode is MRecipeDeviceLayer layer) { return(_model.GetProcessConfigurationTaskHandler( layer.TargetProcessMode )); } return(_model.GetProcessConfigurationTaskHandler((string)null)); }
public async Task <Matrix4x4> GetAbsoluteTransformFromStageOrigin( IProcessConfigurationTasksHandler taskHandler, ICamToBeam cam2Beam, MRecipe recipe, MRecipeBaseNode recipeNode, CancellationToken ctIn ) { // firstly, find closest parent with fiducials var parent = recipeNode; while ( parent != null && parent.Fiducials.Count <= 0 ) { parent = parent.Parent as MRecipeBaseNode; } if (parent != null) { // recursion - get it's parent's transform var baseTransform = await GetAbsoluteTransformFromStageOrigin( taskHandler, cam2Beam, recipe, parent.Parent as MRecipeBaseNode, ctIn ); var fiducialPoints = new List <MarkGeometryPoint>(); var measuredPoints = new List <MarkGeometryPoint>(); for (int i = 0; i < parent.Fiducials.Count; i++) { var fiducial = parent.Fiducials[i]; if (!_cachedFiducials.ContainsKey(fiducial)) { // estimate stage position var stageLocation = new MarkGeometryPoint( fiducial.X, fiducial.Y, fiducial.Z ); stageLocation.Transform(baseTransform); // goto estimated position if (!await taskHandler.GotoXY( stageLocation.X, stageLocation.Y, ctIn )) { throw new Exception($"Failed to goto the estimated position; origin: {await taskHandler.GetStageOrigin(ctIn)}, fiducial: {(fiducial.X, fiducial.Y)} est: {stageLocation}"); } // find and centre { if (!await cam2Beam.MoveBeamToCamOffset(ctIn)) { throw new Exception($"Failed to move beam to cam offset"); } if (!await taskHandler.MovetoCameraFocus(ctIn)) { throw new Exception($"Failed to move camera to focus"); } await taskHandler.SwitchCameraLedOn(ctIn); // attempt to centre on fiducial if (!await taskHandler.CentreOnVisibleObject(ctIn)) { _logger.Info($"Failed to centre on fiducial"); // ask user to locate fiducials Application.Current.Dispatcher.Invoke( () => { var fidVm = taskHandler.GetNewFidFindViewModel(); var inspectionDialog = new InspectionWindow(fidVm, Application.Current.MainWindow); inspectionDialog.Owner = Application.Current.MainWindow; if (inspectionDialog.ShowDialog() != true) { throw new Exception("Failed to find fiducial"); } // TODO : think about updating the machine's origin } ); } if (!await cam2Beam.MoveCamToBeamOffset(ctIn)) { throw new Exception($"Failed to move camera to beam offset"); } } // read fiducial position var(stgX, stgY, success) = await taskHandler.GetStageXY(ctIn); if (!success) { throw new Exception("Failed to read the current stage position"); } // update cache _cachedFiducials[fiducial] = new MarkGeometryPoint(stgX, stgY); } // update measured points fiducialPoints.Add(new MarkGeometryPoint(fiducial.X, fiducial.Y)); measuredPoints.Add(_cachedFiducials[fiducial]); } // calculate transform from measured fiducials var parentTransform = GeometricArithmeticModule.EstimateTransformationMatrixFromPoints( fiducialPoints, measuredPoints ); return(GeometricArithmeticModule.CombineTransformations( parentTransform, await InvertTransform( taskHandler, parentTransform, MRecipe.GetRelativeTransformFromParent( parent, recipeNode ), ctIn ) )); } var origin = await taskHandler.GetStageOrigin(ctIn); var stageOrigin = GeometricArithmeticModule.GetTranslationTransformationMatrix( origin.X, origin.Y ); return(GeometricArithmeticModule.CombineTransformations( stageOrigin, await InvertTransform( taskHandler, stageOrigin, MRecipe.GetRelativeTransform( recipe, recipeNode ), ctIn ) )); }
/// <summary> /// Insert source item into target /// </summary> /// <param name="sourceItem"></param> /// <param name="targetItem"></param> private void CopyItem(MRecipeBaseNode sourceItem, MRecipeBaseNode targetItem, bool deleteSource = true) { if ( (sourceItem.GetType() == targetItem.GetType()) && targetItem.Parent != null && sourceItem.Parent != null ) { if (targetItem.Parent is MRecipePlate) { var data = (sourceItem as MRecipeDevice); var targetParent = (targetItem.Parent as MRecipePlate); var sourceParent = (sourceItem.Parent as MRecipePlate); int targetIndex = targetParent.Devices.IndexOf(targetItem as MRecipeDevice); // remove data from source and insert data into target if (deleteSource) { sourceParent.Devices.Remove(data); } targetParent.Devices.Insert(targetIndex, data); // update source's parent sourceItem.Parent = targetItem.Parent; lock (_undoRedoHelper) _undoRedoHelper.SaveState(); } else if (sourceItem.Parent is MRecipeDevice) { var data = (sourceItem as MRecipeDeviceLayer); var targetParent = (targetItem.Parent as MRecipeDevice); var sourceParent = (sourceItem.Parent as MRecipeDevice); int targetIndex = targetParent.Layers.IndexOf(targetItem as MRecipeDeviceLayer); // remove data from source and insert data into target if (deleteSource) { sourceParent.Layers.Remove(data); } targetParent.Layers.Insert(targetIndex, data); // update source's parent sourceItem.Parent = targetItem.Parent; lock (_undoRedoHelper) _undoRedoHelper.SaveState(); } else if (sourceItem is MRecipePlate) { var data = (sourceItem as MRecipePlate); var targetParent = (targetItem.Parent as MRecipe); var sourceParent = (sourceItem.Parent as MRecipe); int targetIndex = targetParent.Plates.IndexOf(targetItem as MRecipePlate); // remove data from source and insert data into target if (deleteSource) { sourceParent.Plates.Remove(data); } targetParent.Plates.Insert(targetIndex, data); // update source's parent sourceItem.Parent = targetItem.Parent; lock (_undoRedoHelper) _undoRedoHelper.SaveState(); } //var response = MessageBox.Show( // $"Would you like to move {sourceItem.Tag} into position" + + "", "", MessageBoxButton.YesNo //); } else if ( (sourceItem.Parent?.GetType() == targetItem.GetType()) ) { if (targetItem is MRecipePlate) { var data = (sourceItem as MRecipeDevice); var targetParent = (targetItem as MRecipePlate); var sourceParent = (sourceItem.Parent as MRecipePlate); // remove data from source and add data to target if (deleteSource) { sourceParent.Devices.Remove(data); } targetParent.Devices.Add(data); // update source's parent sourceItem.Parent = targetParent; lock (_undoRedoHelper) _undoRedoHelper.SaveState(); } else if (targetItem is MRecipeDevice) { var data = (sourceItem as MRecipeDeviceLayer); var targetParent = (targetItem as MRecipeDevice); var sourceParent = (sourceItem.Parent as MRecipeDevice); // remove data from source and add data to target if (deleteSource) { sourceParent.Layers.Remove(data); } targetParent.Layers.Add(data); // update source's parent sourceItem.Parent = targetParent; lock (_undoRedoHelper) _undoRedoHelper.SaveState(); } } }
public MRecipeTreeViewUserControl() { InitializeComponent(); UndoCommand = new DelegateCommand( () => { Undo(); } ); RedoCommand = new DelegateCommand( () => { Redo(); } ); //ItemSelectedCommand = new DelegateCommand<MRecipeBaseNode>( // (selectedItem)=> { // NotifyPropertyChanged(nameof(CanPasteItem)); // NotifyPropertyChanged(nameof(CanCreateChild)); // // run receipe selected callback on a different thread // SelectNode(selectedItem); // } //); RightClickContextMenuCommand = new DelegateCommand <MRecipeBaseNode>( (selectedItem) => { _lastSelectedNode = selectedItem; NotifyPropertyChanged(nameof(CanPasteItem)); NotifyPropertyChanged(nameof(CanCreateChild)); } ); NewItemCommand = new DelegateCommand <MRecipeBaseNode>( (node) => { if (node is MRecipePlate plate) { (node.Parent as MRecipe).Plates.Add( new MRecipePlate() { Parent = node.Parent } ); } else if (node is MRecipeDevice device) { (node.Parent as MRecipePlate).Devices.Add( new MRecipeDevice() { Parent = node.Parent } ); } else if (node is MRecipeDeviceLayer layer) { (node.Parent as MRecipeDevice).Layers.Add( new MRecipeDeviceLayer() { Parent = node.Parent } ); } else { return; } lock (_undoRedoHelper) _undoRedoHelper.SaveState(); SelectNode(node); } ); CreateChildItemCommand = new DelegateCommand <MRecipeBaseNode>( (node) => { if (node is MRecipePlate plate) { plate.Devices.Add( new MRecipeDevice() { Parent = node } ); } else if (node is MRecipeDevice device) { device.Layers.Add( new MRecipeDeviceLayer() { Parent = node } ); } else { return; } lock (_undoRedoHelper) _undoRedoHelper.SaveState(); SelectNode(node); } ); DuplicateItemCommand = new DelegateCommand <MRecipeBaseNode>( (node) => { CopyItem((MRecipeBaseNode)node.Clone(), (MRecipeBaseNode)node, false); lock (_undoRedoHelper) _undoRedoHelper.SaveState(); SelectNode(node); } ); DuplicateItemAsArrayCommand = new DelegateCommand <MRecipeBaseNode>( (node) => { var dialog = new PasteAsArrayDialog(); dialog.Owner = Application.Current.MainWindow; if (dialog.ShowDialog() != true) { return; } try { lock (_undoRedoHelper) _undoRedoHelper?.Pause(); MArrayInfo.BeginGetAll(dialog.ArrayInfo, (positionInfo) => { var clone = (MRecipeBaseNode)node.Clone(); clone.TransformInfo.OffsetX += positionInfo.XInfo.Offset; clone.TransformInfo.OffsetY += positionInfo.XInfo.Offset; clone.TransformInfo.OffsetZ += positionInfo.XInfo.Offset; CopyItem(clone, node, false); }); } finally { lock (_undoRedoHelper) { _undoRedoHelper?.Resume(); _undoRedoHelper.SaveState(); } } SelectNode(node); } ); CopyItemCommand = new DelegateCommand <MRecipeBaseNode>( (node) => { if (node != null) { _copiedItem = node; } } ); PasteItemCommand = new DelegateCommand <MRecipeBaseNode>( (node) => { if (node == null) { return; } // update selected node _lastSelectedNode = node; if (CanPasteItem == false) { return; } CopyItem((MRecipeBaseNode)_copiedItem.Clone(), _lastSelectedNode, false); SelectNode(node); } ); PasteItemAsArrayCommand = new DelegateCommand <MRecipeBaseNode>( (node) => { if (node == null) { return; } // update selected node _lastSelectedNode = node; if (CanPasteItem == false) { return; } var dialog = new PasteAsArrayDialog(); dialog.Owner = Application.Current.MainWindow; if (dialog.ShowDialog() != true) { return; } var selectedNode = _lastSelectedNode; try { lock (_undoRedoHelper) _undoRedoHelper?.Pause(); for (int x = 0; x < dialog.ArrayInfo.NumX; x++) { for (int y = 0; y < dialog.ArrayInfo.NumY; y++) { for (int z = 0; z < dialog.ArrayInfo.NumZ; z++) { var clone = (MRecipeBaseNode)_copiedItem.Clone(); clone.TransformInfo.OffsetX += x * dialog.ArrayInfo.PitchX; clone.TransformInfo.OffsetY += y * dialog.ArrayInfo.PitchY; clone.TransformInfo.OffsetZ += z * dialog.ArrayInfo.PitchZ; CopyItem(clone, selectedNode, false); } } } } finally { lock (_undoRedoHelper) { _undoRedoHelper?.Resume(); _undoRedoHelper.SaveState(); } } SelectNode(node); } ); DeleteItemCommand = new DelegateCommand <MRecipeBaseNode>( (node) => { if (node is MRecipePlate plate) { (node.Parent as MRecipe).Plates.Remove( plate ); } else if (node is MRecipeDevice device) { (node.Parent as MRecipePlate).Devices.Remove( device ); } else if (node is MRecipeDeviceLayer layer) { (node.Parent as MRecipeDevice).Layers.Remove( layer ); } else { return; } lock (_undoRedoHelper) _undoRedoHelper.SaveState(); SelectNode(node); } ); }
public async Task <Matrix4x4> GetAbsoluteTransform(MRecipeBaseNode node, Matrix4x4 parentTransform, CancellationToken ctIn) { if (parentTransform == null) { parentTransform = GeometricArithmeticModule.GetDefaultTransformationMatrix(); } // node has no fiducials, hences it's position // is relative to its parent if (node.Fiducials.Count <= 0) { return(GeometricArithmeticModule.CombineTransformations( parentTransform, node.TransformInfo.ToMatrix4x4() )); } // attempt to retrieve tasksHandler; handles process specific stage motion // camera, find n centre, etc. IProcessConfigurationTasksHandler tasksHandler = GetClosestConfigurationTasksHandler(node); if (tasksHandler == null) { throw new Exception("Failed to retrieve a Task Handler for the closest process mode"); } // buffer to store estimated and measured fiducials var estimatedPoints = new List <MarkGeometryPoint>(); var measuredPoints = new List <MarkGeometryPoint>(); for (int i = 0; i < node.Fiducials.Count; i++) { var estimatedPosition = new MarkGeometryPoint( node.Fiducials[i].X, node.Fiducials[i].Y ); // transform to parents space estimatedPosition.Transform(parentTransform); estimatedPoints.Add(estimatedPosition); // move camera to position await tasksHandler.FocusCameraAtXY( estimatedPosition.X, estimatedPosition.Y, ctIn ); // get measured position var results = await tasksHandler.TakeMeasurement(); // handle results not found if (!results.Found) { throw new Exception("Failed to find fiducial"); } // store measured point measuredPoints.Add( new MarkGeometryPoint( results.Position.X, results.Position.Y ) ); } return(GeometricArithmeticModule.CombineTransformations( parentTransform, MAlignmentCalculator.GetAlignmentTransform( node.AlignmentType, estimatedPoints, measuredPoints ) )); }