private void CreateAnnotationImpl(CreateAnnotationCommand command) { AnnotationModel annotationModel = currentWorkspace.AddAnnotation( command.AnnotationText, command.AnnotationDescriptionText, command.ModelGuid); CurrentWorkspace.RecordCreatedModel(annotationModel); }
/// <summary> /// Paste ISelectable objects from the clipboard to the workspace. /// </summary> public void Paste() { //clear the selection so we can put the //paste contents in DynamoSelection.Instance.ClearSelection(); //make a lookup table to store the guids of the //old models and the guids of their pasted versions var modelLookup = new Dictionary<Guid, ModelBase>(); //make a list of all newly created models so that their //creations can be recorded in the undo recorder. var createdModels = new List<ModelBase>(); var nodes = ClipBoard.OfType<NodeModel>(); var connectors = ClipBoard.OfType<ConnectorModel>(); var notes = ClipBoard.OfType<NoteModel>(); var annotations = ClipBoard.OfType<AnnotationModel>(); var minX = Double.MaxValue; var minY = Double.MaxValue; // Create the new NoteModel's var newNoteModels = new List<NoteModel>(); foreach (var note in notes) { var noteModel = new NoteModel(note.X, note.Y, note.Text, Guid.NewGuid()); //Store the old note as Key and newnote as value. modelLookup.Add(note.GUID,noteModel); newNoteModels.Add(noteModel); minX = Math.Min(note.X, minX); minY = Math.Min(note.Y, minY); } var xmlDoc = new XmlDocument(); // Create the new NodeModel's var newNodeModels = new List<NodeModel>(); foreach (var node in nodes) { NodeModel newNode; if (CurrentWorkspace is HomeWorkspaceModel && (node is Symbol || node is Output)) { var symbol = (node is Symbol ? (node as Symbol).InputSymbol : (node as Output).Symbol); var code = (string.IsNullOrEmpty(symbol) ? "x" : symbol) + ";"; newNode = new CodeBlockNodeModel(code, node.X, node.Y, LibraryServices, CurrentWorkspace.ElementResolver); } else { var dynEl = node.Serialize(xmlDoc, SaveContext.Copy); newNode = NodeFactory.CreateNodeFromXml(dynEl, SaveContext.Copy, CurrentWorkspace.ElementResolver); } var lacing = node.ArgumentLacing.ToString(); newNode.UpdateValue(new UpdateValueParams("ArgumentLacing", lacing)); if (!string.IsNullOrEmpty(node.NickName)) newNode.NickName = node.NickName; modelLookup.Add(node.GUID, newNode); newNodeModels.Add( newNode ); minX = Math.Min(node.X, minX); minY = Math.Min(node.Y, minY); } // Move all of the notes and nodes such that they are aligned with // the top left of the workspace var workspaceX = -CurrentWorkspace.X / CurrentWorkspace.Zoom; var workspaceY = -CurrentWorkspace.Y / CurrentWorkspace.Zoom; // Provide a small offset when pasting so duplicate pastes aren't directly on top of each other CurrentWorkspace.IncrementPasteOffset(); var shiftX = workspaceX - minX + CurrentWorkspace.CurrentPasteOffset; var shiftY = workspaceY - minY + CurrentWorkspace.CurrentPasteOffset; foreach (var model in newNodeModels.Concat<ModelBase>(newNoteModels)) { model.X = model.X + shiftX; model.Y = model.Y + shiftY; } // Add the new NodeModel's to the Workspace foreach (var newNode in newNodeModels) { CurrentWorkspace.AddAndRegisterNode(newNode, false); createdModels.Add(newNode); AddToSelection(newNode); } // TODO: is this required? OnRequestLayoutUpdate(this, EventArgs.Empty); // Add the new NoteModel's to the Workspace foreach (var newNote in newNoteModels) { CurrentWorkspace.AddNote(newNote, false); createdModels.Add(newNote); AddToSelection(newNote); } ModelBase start; ModelBase end; var newConnectors = from c in connectors // If the guid is in nodeLookup, then we connect to the new pasted node. Otherwise we // re-connect to the original. let startNode = modelLookup.TryGetValue(c.Start.Owner.GUID, out start) ? start as NodeModel : CurrentWorkspace.Nodes.FirstOrDefault(x => x.GUID == c.Start.Owner.GUID) let endNode = modelLookup.TryGetValue(c.End.Owner.GUID, out end) ? end as NodeModel : CurrentWorkspace.Nodes.FirstOrDefault(x => x.GUID == c.End.Owner.GUID) // Don't make a connector if either end is null. where startNode != null && endNode != null select ConnectorModel.Make(startNode, endNode, c.Start.Index, c.End.Index); createdModels.AddRange(newConnectors); //Grouping depends on the selected node models. //so adding the group after nodes / notes are added to workspace. //select only those nodes that are part of a group. var newAnnotations = new List<AnnotationModel>(); foreach (var annotation in annotations) { var annotationNodeModel = new List<NodeModel>(); var annotationNoteModel = new List<NoteModel>(); //checked condition here that supports pasting of multiple groups foreach (var models in annotation.SelectedModels) { ModelBase mbase; modelLookup.TryGetValue(models.GUID, out mbase); if (mbase is NodeModel) { annotationNodeModel.Add(mbase as NodeModel); } if (mbase is NoteModel) { annotationNoteModel.Add(mbase as NoteModel); } } var annotationModel = new AnnotationModel(annotationNodeModel, annotationNoteModel) { GUID = Guid.NewGuid(), AnnotationText = annotation.AnnotationText, Background = annotation.Background, FontSize = annotation.FontSize }; newAnnotations.Add(annotationModel); } // Add the new Annotation's to the Workspace foreach (var newAnnotation in newAnnotations) { CurrentWorkspace.AddAnnotation(newAnnotation); createdModels.Add(newAnnotation); AddToSelection(newAnnotation); } // Record models that are created as part of the command. CurrentWorkspace.RecordCreatedModels(createdModels); }
public AnnotationModel AddAnnotation(string text, Guid id) { var selectedNodes = this.Nodes == null ? null:this.Nodes.Where(s => s.IsSelected); var selectedNotes = this.Notes == null ? null: this.Notes.Where(s => s.IsSelected); if (!CheckIfModelExistsInSameGroup(selectedNodes, selectedNotes)) { var annotationModel = new AnnotationModel(selectedNodes, selectedNotes) { GUID = id, AnnotationText = text }; annotationModel.ModelBaseRequested += annotationModel_GetModelBase; annotationModel.Disposed += (_) => annotationModel.ModelBaseRequested -= annotationModel_GetModelBase; Annotations.Add(annotationModel); HasUnsavedChanges = true; return annotationModel; } return null; }
public void AddAnnotation(AnnotationModel annotationModel) { annotationModel.ModelBaseRequested += annotationModel_GetModelBase; annotationModel.Disposed += (_) => annotationModel.ModelBaseRequested -= annotationModel_GetModelBase; Annotations.Add(annotationModel); }
public void CreateModel(XmlElement modelData) { var helper = new XmlElementHelper(modelData); string typeName = helper.ReadString("type", String.Empty); if (string.IsNullOrEmpty(typeName)) { // If there wasn't a "type" attribute, then we fall-back onto // the name of the XmlElement itself, which is usually the type // name. typeName = modelData.Name; if (string.IsNullOrEmpty(typeName)) { string guid = helper.ReadString("guid"); throw new InvalidOperationException( string.Format("No type information: {0}", guid)); } } /* if (typeName.Equals("Dynamo.Nodes.DSFunction") || typeName.Equals("Dynamo.Nodes.DSVarArgFunction")) { // For DSFunction and DSVarArgFunction node types, the type name // is actually embedded within "name" attribute (for an example, // "UV.ByCoordinates@double,double"). // typeName = modelData.Attributes["name"].Value; } */ if (typeName.StartsWith("Dynamo.Models.ConnectorModel")) { var connector = NodeGraph.LoadConnectorFromXml(modelData, Nodes.ToDictionary(node => node.GUID)); OnConnectorAdded(connector); // Update view-model and view. } else if (typeName.StartsWith("Dynamo.Models.NoteModel")) { var noteModel = NodeGraph.LoadNoteFromXml(modelData); Notes.Add(noteModel); //check whether this note belongs to a group foreach (var annotation in Annotations) { //this note "was" in a group if (annotation.DeletedModelBases.Any(m => m.GUID == noteModel.GUID)) { annotation.AddToSelectedModels(noteModel); } } } else if (typeName.StartsWith("Dynamo.Models.AnnotationModel")) { var selectedNodes = this.Nodes == null ? null : this.Nodes.Where(s => s.IsSelected); var selectedNotes = this.Notes == null ? null : this.Notes.Where(s => s.IsSelected); var annotationModel = new AnnotationModel(selectedNodes, selectedNotes); annotationModel.ModelBaseRequested += annotationModel_GetModelBase; annotationModel.Disposed += (_) => annotationModel.ModelBaseRequested -= annotationModel_GetModelBase; annotationModel.Deserialize(modelData, SaveContext.Undo); Annotations.Add(annotationModel); } else // Other node types. { NodeModel nodeModel = NodeFactory.CreateNodeFromXml(modelData, SaveContext.Undo); Nodes.Add(nodeModel); RegisterNode(nodeModel); //check whether this node belongs to a group foreach (var annotation in Annotations) { //this node "was" in a group if (annotation.DeletedModelBases.Any(m=>m.GUID == nodeModel.GUID)) { annotation.AddToSelectedModels(nodeModel); } } } }
internal void RecordGroupModelBeforeUngroup(AnnotationModel annotation) { using (undoRecorder.BeginActionGroup()) // Start a new action group. { undoRecorder.RecordModificationForUndo(annotation); } }
internal static AnnotationModel LoadAnnotationFromXml(XmlNode annotation, IEnumerable<NodeModel> nodes, IEnumerable<NoteModel> notes) { var instance = new AnnotationModel(nodes,notes); instance.Deserialize(annotation as XmlElement, SaveContext.File); return instance; }
private void AddNewAnnotation(AnnotationModel annotation) { lock (annotations) { annotations.Add(annotation); } OnAnnotationAdded(annotation); }
private void RemoveAnnotation(AnnotationModel annotation) { lock (annotations) { if (!annotations.Remove(annotation)) return; } OnAnnotationRemoved(annotation); }
protected virtual void OnAnnotationRemoved(AnnotationModel annotation) { var handler = AnnotationRemoved; if (handler != null) handler(annotation); }
public void CreateModel(XmlElement modelData) { var helper = new XmlElementHelper(modelData); string typeName = helper.ReadString("type", String.Empty); if (string.IsNullOrEmpty(typeName)) { // If there wasn't a "type" attribute, then we fall-back onto // the name of the XmlElement itself, which is usually the type // name. typeName = modelData.Name; if (string.IsNullOrEmpty(typeName)) { string guid = helper.ReadString("guid"); throw new InvalidOperationException( string.Format("No type information: {0}", guid)); } } /* if (typeName.Equals("Dynamo.Nodes.DSFunction") || typeName.Equals("Dynamo.Nodes.DSVarArgFunction")) { // For DSFunction and DSVarArgFunction node types, the type name // is actually embedded within "name" attribute (for an example, // "UV.ByCoordinates@double,double"). // typeName = modelData.Attributes["name"].Value; } */ if (typeName.StartsWith("Dynamo.Models.ConnectorModel")) { var connector = NodeGraph.LoadConnectorFromXml(modelData, Nodes.ToDictionary(node => node.GUID)); // It is possible that in some cases connector can't be created, // for example, connector connects to a custom node instance // whose input ports have been changed, so connector can't find // its end port owner. if (connector == null) { var guidAttribute = modelData.Attributes["guid"]; if (guidAttribute == null) { throw new InvalidOperationException("'guid' field missing from recorded model"); } undoRecorder.RecordModelAsOffTrack(Guid.Parse(guidAttribute.Value)); } else { OnConnectorAdded(connector); // Update view-model and view. } } else if (typeName.StartsWith("Dynamo.Models.NoteModel")) { var noteModel = NodeGraph.LoadNoteFromXml(modelData); AddNote(noteModel); //check whether this note belongs to a group foreach (var annotation in Annotations) { //this note "was" in a group if (annotation.DeletedModelBases.Any(m => m.GUID == noteModel.GUID)) { annotation.AddToSelectedModels(noteModel); } } } else if (typeName.StartsWith("Dynamo.Models.AnnotationModel")) { var selectedNodes = this.Nodes == null ? null : this.Nodes.Where(s => s.IsSelected); var selectedNotes = this.Notes == null ? null : this.Notes.Where(s => s.IsSelected); var annotationModel = new AnnotationModel(selectedNodes, selectedNotes); annotationModel.ModelBaseRequested += annotationModel_GetModelBase; annotationModel.Disposed += (_) => annotationModel.ModelBaseRequested -= annotationModel_GetModelBase; annotationModel.Deserialize(modelData, SaveContext.Undo); AddNewAnnotation(annotationModel); } else if (typeName.Contains("PresetModel")) { var preset = new PresetModel(this.Nodes); preset.Deserialize(modelData, SaveContext.Undo); presets.Add(preset); //we raise this property change here so that this event bubbles up through //the model and to the DynamoViewModel so that presets show in the UI menu if our undo/redo //created the first preset RaisePropertyChanged("EnablePresetOptions"); } else // Other node types. { NodeModel nodeModel = NodeFactory.CreateNodeFromXml(modelData, SaveContext.Undo, ElementResolver); AddAndRegisterNode(nodeModel); //check whether this node belongs to a group foreach (var annotation in Annotations) { //this node "was" in a group if (annotation.DeletedModelBases.Any(m=>m.GUID == nodeModel.GUID)) { annotation.AddToSelectedModels(nodeModel); } } } }
private void Model_AnnotationRemoved(AnnotationModel annotation) { _annotations.Remove(_annotations.First(x => x.AnnotationModel == annotation)); }
private void Model_AnnotationAdded(AnnotationModel annotation) { var viewModel = new AnnotationViewModel(this, annotation); _annotations.Add(viewModel); }
public AnnotationViewModel(WorkspaceViewModel workspaceViewModel, AnnotationModel model) { annotationModel = model; this.WorkspaceViewModel = workspaceViewModel; model.PropertyChanged += model_PropertyChanged; // Group is created already.So just populate it. var selectNothing = new DynamoModel.SelectModelCommand(Guid.Empty, System.Windows.Input.ModifierKeys.None.AsDynamoType()); WorkspaceViewModel.DynamoViewModel.ExecuteCommand(selectNothing); }