// EDITPANEL SHOW edit existing node public void editNode(Position currentPosition, Node editedNode) { if (!this.Visible) { int padding = Node.NodePadding; this.editedNode = editedNode; this.editedNode.visible = false; this.diagramView.diagram.InvalidateDiagram(); this.Left = currentPosition.x; this.Top = currentPosition.y; this.edit.Left = padding + 1; this.edit.Top = padding + 0; Font nodeFont = this.editedNode.font; Font font = new Font(nodeFont.FontFamily, nodeFont.Size / this.diagramView.scale, nodeFont.Style); this.edit.Font = font; this.edit.Text = this.editedNode.link; // add first character this.setPanelSize(); this.BackColor = this.editedNode.color.get(); this.edit.BackColor = this.editedNode.color.get(); this.editing = true; this.Show(); this.edit.Show(); this.edit.Focus(); this.edit.SelectionStart = edit.Text.Length; } }
public string type = ""; // type of undo operation (delete, create, edit, move, changeLineColor, changeLineWidth, changeNodeColor) #endregion Fields #region Constructors /*************************************************************************************************************************/ // CONSTRUCTORS public UndoOperation( string type, Nodes nodes = null, Lines lines = null, int group = 0, Position position = null, int layer = 0 ) { this.type = type; this.group = group; this.position.set(position); this.layer = layer; if (nodes != null) { foreach (Node node in nodes) { this.nodes.Add(new Node(node)); } } if (lines != null) { foreach (Line line in lines) { this.lines.Add(new Line(line)); } } }
/// <summary> /// Constructor</summary> public Position(Position p) { if (p != null) { this.x = p.x; this.y = p.y; } else { this.x = 0; this.y = 0; } }
// [KEYBOARD] [DOWN] [EVENT] // EVENT Key down public void DiagramApp_KeyDown(object sender, KeyEventArgs e) { #if DEBUG this.logEvent("KeyDown"); #endif if (this.isEditing() || this.stateSearching) { return; } if (e.Shift) { this.keyshift = true; } if (e.Control) { this.keyctrl = true; } if (e.Alt) { this.keyalt = true; } if (this.isEditing()) { return; } if (e.KeyCode == Keys.Space && !this.stateZooming) // KEY [SPACE] [SPACEBAR] [zoom] zoom preview { this.stateSelectingNodes = false; this.MoveTimer.Enabled = false; this.zoomTimer.Enabled = false; this.stateZooming = true; Position tmp = new Position(this.shift); tmp.add( (int)(-(this.ClientSize.Width / 2 - this.ClientSize.Width / 2 / this.scale) * this.scale), (int)(-(this.ClientSize.Height / 2 - this.ClientSize.Height / 2 / this.scale) * this.scale) ); this.currentScale = this.scale; this.scale = this.zoomingScale; tmp.add( (int)(+(this.ClientSize.Width / 2 - this.ClientSize.Width / 2 / this.scale) * this.scale), (int)(+(this.ClientSize.Height / 2 - this.ClientSize.Height / 2 / this.scale) * this.scale) ); this.shift.set(tmp); this.diagram.InvalidateDiagram(); } }
public void add(string type, Line line, Position position = null, int layer = 0) { Lines lines = new Lines(); if (line != null) { lines.Add(new Line(line)); } this.add(type, null, lines, position, layer); }
// EDITPANEL SHOW add new node public void showEditPanel(Position currentPosition, char FirstKey = ' ', bool addKey = true) { if (!this.Visible) { int padding = Node.NodePadding; this.Left = currentPosition.x; this.Top = currentPosition.y; this.edit.Left = padding + 1; this.edit.Top = padding + 0; Font defaultFont = this.diagramView.diagram.FontDefault; Font font = new Font(defaultFont.FontFamily, defaultFont.Size / this.diagramView.scale, defaultFont.Style); this.edit.Font = font; this.edit.Text = ""; if (addKey) { this.edit.Text += (FirstKey).ToString(); // add first character } this.setPanelSize(); this.BackColor = System.Drawing.ColorTranslator.FromHtml("#FFFFB8"); this.edit.BackColor = System.Drawing.ColorTranslator.FromHtml("#FFFFB8"); this.editing = true; this.Show(); this.edit.Show(); this.edit.Focus(); this.edit.SelectionStart = edit.Text.Length; } }
// <summary> /// set </summary> public Position set(Position p) { if (p != null) { this.x = p.x; this.y = p.y; } else { this.x = 0; this.y = 0; } return this; }
// <summary> /// Copy position to current position</summary> public Position copy(Position b) { this.x = b.x; this.y = b.y; return this; }
// EVENT MOVE TIMER for move view when node is draged to window edge public void MoveTimer_Tick(object sender, EventArgs e) { #if DEBUG this.logEvent("MoveTimer_Tick"); #endif if (this.stateDragSelection || this.stateSelectingNodes || this.stateAddingNode) { bool changed = false; if (this.ClientSize.Width - 20 < this.actualMousePos.x) { this.shift.x -= (int)(10 * this.scale); changed = true; } if (this.actualMousePos.x < 20) { this.shift.x += (int)(10 * this.scale); changed = true; } if (this.ClientSize.Height - 50 < this.actualMousePos.y) { this.shift.y -= (int)(10 * this.scale); changed = true; } if (this.actualMousePos.y < 10) { this.shift.y += (int)(10 * this.scale); changed = true; } if (this.stateDragSelection) // drag selected nodes { if (this.sourceNode != null && this.sourceNode.selected) { Position vector = new Position(); if (this.stateCoping) { // calculate shift between start node position and current sourceNode position vector .set(this.actualMousePos) .scale(this.scale) .subtract(this.vmouse) .subtract(this.shift) .subtract(this.copySourceNode.position); foreach (Node node in this.copySelectedNodes) { node.position.add(vector); } } else if (this.selectedNodes.Count > 0) { // calculate shift between start node position and current sourceNode position vector .set(this.actualMousePos) .scale(this.scale) .subtract(this.vmouse) .subtract(this.shift) .subtract(this.sourceNode.position); foreach (Node node in this.selectedNodes) { node.position.add(vector); } } changed = true; } } if (changed) this.diagram.InvalidateDiagram(); } }
// NODE Check to shift public bool isOnPosition(Position shift, int layer) { if (shift.x == this.shift.x && shift.y == this.shift.y && this.currentLayer.id == layer) { return true; } return false; }
// NODE Go to shift public void goToShift(Position shift) { if (shift != null) { this.shift.set(shift); } }
// NODE Go to position public void goToPosition(Position position) { if (position != null) { this.shift.x = (int)(-position.x + this.ClientSize.Width / 2 * this.scale); this.shift.y = (int)(-position.y + this.ClientSize.Height / 2 * this.scale); } }
// NODE find node in mouse cursor position public Node findNodeInMousePosition(Position position, Node skipNode = null) { return this.diagram.findNodeInPosition( new Position( (int)(position.x * this.scale - this.shift.x), (int)(position.y * this.scale - this.shift.y) ), this.currentLayer.id, skipNode ); }
// NODE edit link public void editLink() { if (this.selectedNodes.Count() == 1) { Node rec = this.selectedNodes[0]; Position position = new Position( (int)((this.shift.x + rec.position.x) / this.scale), (int)((this.shift.y + rec.position.y) / this.scale) ); this.editLinkPanel.editNode(position, this.selectedNodes[0]); } }
// EVENT Mouse Up // [MOUSE] [UP] [EVENT] public void DiagramApp_MouseUp(object sender, MouseEventArgs e) { #if DEBUG this.logEvent("MouseUp"); #endif this.actualMousePos.set(e.X, e.Y); Position mouseTranslation = new Position(this.actualMousePos).subtract(this.startMousePos); // States bool mousemove = ((this.actualMousePos.x != this.startMousePos.x) || (this.actualMousePos.y != this.startMousePos.y)); // mouse change position bool buttonleft = e.Button == MouseButtons.Left; bool buttonright = e.Button == MouseButtons.Right; bool buttonmiddle = e.Button == MouseButtons.Middle; bool isreadonly = this.diagram.options.readOnly; bool keyalt = this.keyalt; bool keyctrl = this.keyctrl; bool keyshift = this.keyshift; bool dblclick = this.stateDblclick; bool finishdraging = this.stateDragSelection; bool finishadding = this.stateAddingNode; bool finishselecting = mousemove && this.stateSelectingNodes; MoveTimer.Enabled = false; if(dblclick) { this.stateSelectingNodes = false; } else // KEY DRAG if (finishdraging) // drag node { if (!this.diagram.options.readOnly) { if (this.sourceNode != null && !keyctrl) // return node to starting position after connection is created { Position translation = new Position(this.startNodePos) .subtract(sourceNode.position); if (this.selectedNodes.Count > 0) { foreach (Node node in this.selectedNodes) { node.position.add(translation); } } this.diagram.InvalidateDiagram(); } } } else // KEY DRAG-MMIDDLE if (finishadding) { this.diagram.InvalidateDiagram(); } else // KEY DRAG+MLEFT select nodes with selection rectangle if (finishselecting) { if (mousemove) { Position a = new Position(this.startMousePos) .scale(this.scale) .add(this.shift) .subtract(this.startShift); Position b = new Position(this.actualMousePos) .scale(this.scale); int temp; if (b.x < a.x) { temp = a.x; a.x = b.x; b.x = temp; } if (b.y < a.y) { temp = b.y; b.y = a.y; a.y = temp; } if (!this.keyshift) this.ClearSelection(); foreach (Node rec in this.currentLayer.nodes) { if ( (rec.layer == this.currentLayer.id || rec.id == this.currentLayer.id) && -this.shift.x + a.x <= rec.position.x && rec.position.x + rec.width <= -this.shift.x + b.x && -this.shift.y + a.y <= rec.position.y && rec.position.y + rec.height <= -this.shift.y + b.y) // get all nodes in selection rectangle { if (keyshift && !keyctrl && !keyalt) // KEY SHIFT+MLEFT Invert selection { if (rec.selected) { this.RemoveNodeFromSelection(rec); } else { this.SelectNode(rec); } } if (!keyshift && !keyctrl && !keyalt) // KEY MLEFT select nodes { this.SelectNode(rec); } } } this.diagram.InvalidateDiagram(); } } Node TargetNode = this.findNodeInMousePosition(new Position(e.X, e.Y)); if (buttonleft) // MLEFT { if (!keyalt && keyctrl && !keyshift && TargetNode != null && TargetNode.selected) // CTRL+CLICK add node to selection { this.RemoveNodeFromSelection(TargetNode); this.diagram.InvalidateDiagram(); } else if (!keyalt && keyctrl && !keyshift && TargetNode != null && !TargetNode.selected) // CTRL+CLICK remove node from selection { this.SelectNode(TargetNode); this.diagram.InvalidateDiagram(); } else if (this.stateCoping && mousemove) // CTRL+DRAG copy part of diagram { this.stateCoping = false; DiagramBlock newBlock = this.diagram.duplicatePartOfDiagram(this.selectedNodes, this.currentLayer.id); Position vector = new Position(this.actualMousePos) .scale(this.scale) .subtract(this.vmouse) .subtract(this.shift) .subtract(this.sourceNode.position); // filter only top nodes fromm all new created nodes. NewNodes containing sublayer nodes. Nodes topNodes = new Nodes(); foreach (Node node in newBlock.nodes) { if (node.layer == this.currentLayer.id) { topNodes.Add(node); } } foreach (Node node in topNodes) { node.position.add(vector); } this.diagram.unsave("create", newBlock.nodes, newBlock.lines); this.SelectNodes(topNodes); this.diagram.unsave(); this.diagram.InvalidateDiagram(); } else if (bottomScrollBar != null && rightScrollBar != null && (bottomScrollBar.MouseUp() || rightScrollBar.MouseUp())) { this.diagram.InvalidateDiagram(); } else // KEY MLEFT clear selection if (!mousemove && TargetNode == null && this.sourceNode == null && this.selectedNodes.Count() > 0 && !keyalt && !keyctrl && !keyshift) { this.ClearSelection(); this.diagram.InvalidateDiagram(); } else // KEY CTRL+ALT+DRAG create node and conect with existing node if (!isreadonly && !keyshift && keyctrl && keyalt && TargetNode == null && this.sourceNode != null) { var s = this.sourceNode; var node = this.CreateNode(new Position(e.X, e.Y)); node.shortcut = s.id; this.diagram.Connect(s, node); this.diagram.unsave("create", node, this.shift, this.currentLayer.id); this.diagram.InvalidateDiagram(); } else // KEY CTRL+ALT+DRAG create shortcut beetwen objects if (!isreadonly && !keyshift && keyctrl && keyalt && TargetNode != null && this.sourceNode != null && TargetNode != this.sourceNode) { this.diagram.unsave("edit", this.sourceNode, this.shift, this.currentLayer.id); this.sourceNode.link = "#" + TargetNode.id.ToString(); this.diagram.unsave(); this.diagram.InvalidateDiagram(); } else // KEY DRAG move node if ( !isreadonly && ( (TargetNode == null && this.sourceNode != null) || ( TargetNode != null && this.sourceNode != TargetNode && TargetNode.selected ) || (TargetNode != null && this.sourceNode == TargetNode) ) && Math.Sqrt(mouseTranslation.x * mouseTranslation.x + mouseTranslation.y * mouseTranslation.y) > 5 ) { Position vector = new Position(this.actualMousePos) .scale(this.scale) .subtract(this.vmouse) .subtract(this.shift) .subtract(this.sourceNode.position); if (this.selectedNodes.Count > 0) { this.diagram.undoOperations.add("edit", this.selectedNodes, null, this.shift, this.currentLayer.id); foreach (Node node in this.selectedNodes) { node.position.add(vector); } this.diagram.unsave(); } this.diagram.InvalidateDiagram(); } else // KEY DRAG+CTRL create node and conect with existing node if (!isreadonly && !keyshift && !keyctrl && keyalt && TargetNode != null && this.sourceNode == null) { Node node = this.CreateNode( new Position( +this.shift.x - startShift.x + this.startMousePos.x, +this.shift.y - startShift.y + this.startMousePos.y ) ); Line line = this.diagram.Connect( node, TargetNode ); this.diagram.unsave("create", node, line, this.shift, this.currentLayer.id); this.diagram.InvalidateDiagram(); } else // KEY CTRL+ALT+DRAG create node and make shortcut to target node if (!isreadonly && keyalt && keyctrl && !keyshift && TargetNode != null && this.sourceNode == null) { Node newrec = this.CreateNode( new Position(this.shift).subtract(startShift).add(this.startMousePos) ); newrec.link = "#" + TargetNode.id; this.diagram.unsave("create", newrec, this.shift, this.currentLayer.id); this.diagram.InvalidateDiagram(); } else // KEY DBLCLICK open link or edit window after double click on node [dblclick] [open] [edit] if (dblclick && this.sourceNode != null && !keyctrl && !keyalt && !keyshift) { this.resetStates(); this.OpenLinkAsync(this.sourceNode); } else // KEY SHIFT+DBLCLICK open node edit form if (dblclick && this.sourceNode != null && !keyctrl && !keyalt && keyshift) { this.diagram.EditNode(this.sourceNode); } else // KEY CTRL+DBLCLICK open link in node if (dblclick && this.sourceNode != null && keyctrl && !keyalt && !keyshift) { if (this.sourceNode.link != "") { Os.openPathInSystem(this.sourceNode.link); } } else // KEY DBLCLICK+SPACE change position in zoom view mode if (this.stateZooming && dblclick && !keyctrl && !keyalt && !keyshift) { this.shift .subtract( this.actualMousePos .clone() .scale(this.scale) ) .add( (this.ClientSize.Width * this.scale) / 2, (this.ClientSize.Height * this.scale) / 2 ); this.diagram.InvalidateDiagram(); } else // KEY CTRL+SHIFT+MLEFT conect with selected nodes new node or selected node if (!isreadonly && keyshift && keyctrl && this.selectedNodes.Count() > 0 && e.X == this.startMousePos.x && e.Y == this.startMousePos.y) { // TODO Still working this? Node newrec = TargetNode; Nodes newNodes = new Nodes(); if (newrec == null) { newrec = this.CreateNode(this.actualMousePos.clone().subtract(10), false); newNodes.Add(newrec); } Lines newLines = new Lines(); foreach (Node rec in this.selectedNodes) { Line line = this.diagram.Connect(rec, newrec); newLines.Add(line); } this.SelectOnlyOneNode(newrec); this.diagram.unsave("create", newNodes, newLines, this.shift, this.currentLayer.id); } else // KEY ALT+MLEFT // KEY DBLCLICK create new node if (!isreadonly && (dblclick || keyalt) && !keyshift && !keyctrl && TargetNode == null && this.sourceNode == null && e.X == this.startMousePos.x && e.Y == this.startMousePos.y) { Node newNode = this.CreateNode(this.actualMousePos.clone().subtract(10), false); this.diagram.unsave("create", newNode, this.shift, this.currentLayer.id); } else // KEY DRAG+ALT copy style from node to other node if (!isreadonly && !keyshift && !keyctrl && keyalt && TargetNode != null && this.sourceNode != null && this.sourceNode != TargetNode) { if (this.selectedNodes.Count() > 1) { this.diagram.undoOperations.add("edit", this.selectedNodes, null, this.shift, this.currentLayer.id); foreach (Node rec in this.selectedNodes) { rec.copyNodeStyle(TargetNode); } this.diagram.unsave(); } if (this.selectedNodes.Count() == 1 || (this.selectedNodes.Count() == 0 && this.sourceNode != null)) { this.diagram.undoOperations.add("edit", TargetNode, this.shift, this.currentLayer.id); TargetNode.copyNodeStyle(this.sourceNode); if (this.selectedNodes.Count() == 1 && this.selectedNodes[0] != this.sourceNode) { this.ClearSelection(); this.SelectNode(this.sourceNode); } this.diagram.unsave(); } } else // KEY DRAG make link between two nodes if (!isreadonly && !keyctrl && !keyalt && TargetNode != null && this.sourceNode != null && this.sourceNode != TargetNode) { bool arrow = false; if (keyshift) { arrow = true; } Lines newLines = new Lines(); Lines removeLines = new Lines(); if (this.selectedNodes.Count() > 0) { foreach (Node rec in this.selectedNodes) { if (rec != TargetNode) { if (this.diagram.hasConnection(rec, TargetNode)) { Line removeLine = this.diagram.getLine(rec, TargetNode); removeLines.Add(removeLine); this.diagram.Disconnect(rec, TargetNode); } else { Line newLine = this.diagram.Connect(rec, TargetNode, arrow, null); newLines.Add(newLine); } } } } if (newLines.Count() > 0 && removeLines.Count() > 0) { this.diagram.undoOperations.startGroup(); this.diagram.undoOperations.add("create", null, newLines, this.shift, this.currentLayer.id); this.diagram.undoOperations.add("delete", null, removeLines, this.shift, this.currentLayer.id); this.diagram.undoOperations.endGroup(); this.diagram.unsave(); } else if (newLines.Count() > 0) { this.diagram.undoOperations.add("create", null, newLines, this.shift, this.currentLayer.id); } else if (removeLines.Count() > 0) { this.diagram.undoOperations.add("delete", null, removeLines, this.shift, this.currentLayer.id); } this.diagram.InvalidateDiagram(); } // KEY SHIFT+MLEFT add node to selected nodes else if (!keyctrl && keyshift && !keyalt && this.sourceNode == TargetNode && TargetNode != null && !TargetNode.selected) { this.SelectNode(TargetNode); this.diagram.InvalidateDiagram(); } // KEY SHIFT+MLEFT remove node from selected nodes else if (!keyctrl && keyshift && !keyalt && TargetNode != null && (this.sourceNode == TargetNode || TargetNode.selected)) { this.RemoveNodeFromSelection(TargetNode); this.diagram.InvalidateDiagram(); } else if (this.sourceNode == TargetNode && this.stateSourceNodeAlreadySelected) { this.rename(); } } else if (buttonright) // KEY MRIGHT { this.stateMoveView = false; // show popup menu if (e.X == this.startMousePos.x && e.Y == this.startMousePos.y && this.startShift.x == this.shift.x && this.startShift.y == this.shift.y) { Node temp = this.findNodeInMousePosition(new Position(e.X, e.Y)); if (temp == null || (this.sourceNode != temp && !temp.selected)) { this.ClearSelection(); this.SelectOnlyOneNode(temp); } this.diagram.InvalidateDiagram(); PopupMenu.Show(this.Left + e.X, this.Top + e.Y); // [POPUP] show popup } else { // KEY DRAG+MRIGHT move view this.shift.x = (int)(this.startShift.x + (e.X - this.startMousePos.x) * this.scale); this.shift.y = (int)(this.startShift.y + (e.Y - this.startMousePos.y) * this.scale); this.diagram.InvalidateDiagram(); } } else if (buttonmiddle) // MMIDDLE { // KEY DRAG+MMIDDLE conect two existing nodes if (this.sourceNode != null && TargetNode != null) { Line newLine = this.diagram.Connect( sourceNode, TargetNode ); if (newLine != null) { this.diagram.unsave("create", newLine, this.shift, this.currentLayer.id); this.diagram.InvalidateDiagram(); } } else // KEY DRAG+MMIDDLE connect exixting node with new node if (this.sourceNode != null && TargetNode == null) { Node newNode = this.CreateNode(this.actualMousePos.clone().subtract(10)); Line newLine = this.diagram.Connect( sourceNode, newNode ); this.diagram.unsave("create", newNode, newLine, this.shift, this.currentLayer.id); this.diagram.InvalidateDiagram(); } else // KEY DRAG+MMIDDLE create new node and conect id with existing node if (!isreadonly && TargetNode != null) { Node newNode = this.CreateNode( (new Position(this.shift)).subtract(this.startShift).add(this.startMousePos) ); Line newLine = this.diagram.Connect( newNode, TargetNode ); this.diagram.unsave("create", newNode, newLine, this.shift, this.currentLayer.id); this.diagram.InvalidateDiagram(); } else // KEY DRAG+MMIDDLE create new node and conect with new node (create line) if (!isreadonly && TargetNode == null) { Nodes nodes = new Nodes(); Lines lines = new Lines(); Node node1 = this.CreateNode( (new Position(this.shift)).subtract(this.startShift).add(this.startMousePos), false ); nodes.Add(node1); Node node2 = this.CreateNode( this.actualMousePos.clone().subtract(10) ); nodes.Add(node2); lines.Add(this.diagram.Connect( node1, node2 )); this.diagram.unsave("create", nodes, lines, this.shift, this.currentLayer.id); this.diagram.InvalidateDiagram(); } } this.resetStates(); }
/*************************************************************************************************************************/ // NODE create public Node CreateNode(Position position, bool SelectAfterCreate = true) { var rec = this.diagram.createNode( position.clone().scale(this.scale).subtract(this.shift), "", this.currentLayer.id ); if (rec != null) { if (SelectAfterCreate) this.SelectOnlyOneNode(rec); } return rec; }
// create node with position object public Node create(Position p, string name = "", int layer = -1) { if (layer < 0) { layer = this.layer().id; } return this.script.diagram.createNode(p, name, layer); }
// NODE paste public bool paste(Position position) { DataObject retrievedData = (DataObject)Clipboard.GetDataObject(); if (retrievedData.GetDataPresent("DiagramXml")) // [PASTE] [DIAGRAM] [CLIPBOARD OBJECT] insert diagram { DiagramBlock newBlock = this.diagram.AddDiagramPart( retrievedData.GetData("DiagramXml") as string, position.clone().scale(this.scale).subtract(this.shift), this.currentLayer.id ); this.diagram.unsave("create", newBlock.nodes, newBlock.lines); // filter only top nodes fromm all new created nodes. NewNodes containing sublayer nodes. Nodes topNodes = new Nodes(); foreach (Node node in newBlock.nodes) { if (node.layer == this.currentLayer.id) { topNodes.Add(node); } } this.SelectNodes(topNodes); this.diagram.InvalidateDiagram(); } else if (retrievedData.GetDataPresent(DataFormats.StringFormat)) // [PASTE] [TEXT] insert text { Node newrec = this.CreateNode(position); string ClipText = retrievedData.GetData(DataFormats.StringFormat) as string; if (Patterns.isColor(ClipText)) { newrec.setName(ClipText); newrec.color.set(Media.getColor(ClipText)); this.diagram.unsave("create", newrec, this.shift, this.currentLayer.id); } else if (Patterns.isURL(ClipText)) // [PASTE] [URL] [LINK] paste link from clipboard { newrec.link = ClipText; newrec.setName(ClipText); this.setNodeNameByLink(newrec, ClipText); this.diagram.unsave("create", newrec, this.shift, this.currentLayer.id); } else { newrec.setName(ClipText); // set link to node as path to file if (Os.FileExists(ClipText)) { newrec.setName(Os.getFileName(ClipText)); newrec.link = Os.makeRelative(ClipText, this.diagram.FileName); newrec.color.set(Media.getColor(diagram.options.colorFile)); } // set link to node as path to directory if (Os.DirectoryExists(ClipText)) { newrec.setName(Os.getFileName(ClipText)); newrec.link = Os.makeRelative(ClipText, this.diagram.FileName); newrec.color.set(Media.getColor(diagram.options.colorDirectory)); } this.diagram.unsave("create", newrec, this.shift, this.currentLayer.id); } this.diagram.InvalidateDiagram(); } else if (Clipboard.ContainsFileDropList()) // [FILES] [PASTE] insert files from clipboard { StringCollection returnList = Clipboard.GetFileDropList(); Nodes nodes = new Nodes(); foreach (string file in returnList) { Node newrec = this.CreateNode(position); nodes.Add(newrec); newrec.setName(Os.getFileNameWithoutExtension(file)); string ext = Os.getExtension(file); if (ext == ".jpg" || ext == ".png" || ext == ".ico" || ext == ".bmp") // paste image file direct to diagram as image instead of link { this.diagram.setImage(newrec, file); } else if ( this.diagram.FileName != "" && Os.FileExists(this.diagram.FileName) && file.IndexOf(Os.getDirectoryName(this.diagram.FileName)) == 0 ) // [PASTE] [FILE] { // make path relative to saved diagram path int start = Os.getDirectoryName(this.diagram.FileName).Length; int finish = file.Length - start; newrec.link = "." + file.Substring(start, finish); } else if (this.diagram.FileName != "" && Os.DirectoryExists(this.diagram.FileName)) // [PASTE] [DIRECTORY] { // make path relative to saved diagram path int start = Os.getDirectoryName(this.diagram.FileName).Length; int finish = file.Length - start; newrec.link = "." + file.Substring(start, finish); } else { newrec.link = file; } } if (nodes.Count() > 0) { this.diagram.unsave("create", nodes, null, this.shift, this.currentLayer.id); this.diagram.InvalidateDiagram(); } } else if (Clipboard.GetDataObject() != null) // [PASTE] [IMAGE] [CLIPBOARD OBJECT] paste image { IDataObject data = Clipboard.GetDataObject(); if (data.GetDataPresent(DataFormats.Bitmap)) { // paste image as embedded data direct inside diagram try { Node newrec = this.CreateNode(position); newrec.image = (Bitmap)data.GetData(DataFormats.Bitmap, true); newrec.height = newrec.image.Height; newrec.width = newrec.image.Width; newrec.isimage = true; newrec.embeddedimage = true; this.diagram.unsave("create", newrec, this.shift, this.currentLayer.id); this.diagram.InvalidateDiagram(); } catch (Exception e) { Program.log.write("paste immage error: " + e.Message); } } } return true; }
/*************************************************************************************************************************/ // OPERATIONS // <summary> /// Count distance between two points</summary> public double distance(Position b) { return Math.Sqrt((b.x - this.x) * (b.x - this.x) + (b.y - this.y) * (b.y - this.y)); }
// NODE rename public void rename() { if (this.selectedNodes.Count() == 1) { Node rec = this.selectedNodes[0]; Position position = new Position(this.shift).add(rec.position).split(this.scale); this.editPanel.editNode(position, this.selectedNodes[0]); } }
/*************************************************************************************************************************/ // SUBSTRACT OPERATIONS // <summary> /// subtract vector</summary> public Position subtract(Position p) { this.x -= p.x; this.y -= p.y; return this; }
/// <summary> /// SEARCH FIRST /// /// Build array of search results and then select first Node. /// /// </summary> /// <param name="find">Search string</param> public void SearchFirst(string find) { Nodes foundNodes = new Nodes(); this.lastFound = -1; this.searchFor = find; foreach (Node node in this.diagram.getAllNodes()) { if (node.note.ToUpper().IndexOf(searchFor.ToUpper()) != -1 || node.name.ToUpper().IndexOf(searchFor.ToUpper()) != -1) { foundNodes.Add(node); } } this.searhPanel.highlight(foundNodes.Count() == 0); Position middle = new Position(); middle.copy(this.currentPosition); middle.x = middle.x - this.ClientSize.Width / 2; middle.y = middle.y - this.ClientSize.Height / 2; int currentLayerId = this.currentLayer.id; foundNodes.Sort((first, second) => { // sort by layers if (first.layer < second.layer) { // current layer first if (currentLayerId == second.layer) { return 1; } return -1; } // sort by layers if (first.layer > second.layer) { // current layer first if (currentLayerId == first.layer) { return -1; } return 1; } Node parent = this.diagram.layers.getLayer(first.layer).parentNode; Position m = (currentLayerId == first.layer) ? middle : (parent != null) ? parent.layerShift : firstLayereShift; double d1 = first.position.convertToStandard().distance(m); double d2 = second.position.convertToStandard().distance(m); // sort by distance if is same layer if (d1 < d2) { return -1; } else { if (d1 > d2) { return 1; } else { return 0; } } }); nodesSearchResult.Clear(); for (int i = 0; i < foundNodes.Count(); i++) { nodesSearchResult.Add(foundNodes[i].id); } this.SearchNext(); }
/*************************************************************************************************************************/ // ADD OPERATIONS // <summary> /// add vector</summary> public Position add(Position p) { this.x += p.x; this.y += p.y; return this; }
/*************************************************************************************************************************/ // DRAW // [DRAW] private void DrawDiagram(Graphics gfx, Position correction = null, bool export = false) { gfx.SmoothingMode = SmoothingMode.AntiAlias; if (this.diagram.options.grid && !export) { this.DrawGrid(gfx); } if (this.diagram.isLocked()) { return; } this.DrawLines(gfx, this.currentLayer.lines, correction, export); if (!export && this.stateCoping) { this.DrawLines(gfx, this.copySelectedLines, correction, export); } // DRAW addingnode if (!export && this.stateAddingNode && !this.stateZooming && (this.actualMousePos.x != this.startMousePos.x || this.actualMousePos.y != this.startMousePos.y)) { this.DrawAddNode(gfx); } this.DrawNodes(gfx, this.currentLayer.nodes, correction, export); if (!export && this.stateCoping) { this.DrawNodes(gfx, this.copySelectedNodes, correction, export); } // DRAW select - select nodes by mouse drag (blue rectangle - multiselect) if (!export && this.stateSelectingNodes && (this.actualMousePos.x != this.startMousePos.x || this.actualMousePos.y != this.startMousePos.y)) { this.DrawNodesSelectArea(gfx); } // PREVIEW draw zoom mini screen if (!export && this.stateZooming) { this.DrawMiniScreen(gfx); } // DRAW coordinates if (this.diagram.options.coordinates) { this.DrawCoordinates(gfx); } // DRAW addingnode if (!export) { this.breadcrumbs.Draw(gfx); } }
// DRAW lines private void DrawLines(Graphics gfx, Lines lines, Position correction = null, bool export = false) { bool isvisible = false; // drawonly visible elements float s = this.scale; // fix position for image file export int cx = 0; int cy = 0; if (correction != null) { cx = correction.x; cy = correction.y; } // DRAW lines foreach (Line lin in lines) // Loop through List with foreach { Node r1 = lin.startNode; Node r2 = lin.endNode; isvisible = false; if (export) { isvisible = true; } else if (0 + this.ClientSize.Width <= (this.shift.x + r1.position.x) / s && 0 + this.ClientSize.Width <= (this.shift.x + r2.position.x) / s) { isvisible = false; } else if ((this.shift.x + r1.position.x) / s <= 0 && (this.shift.x + r2.position.x) / s <= 0) { isvisible = false; } else if (0 + this.ClientSize.Height <= (this.shift.y + r1.position.y) / s && 0 + this.ClientSize.Height <= (this.shift.y + r2.position.y) / s) { isvisible = false; } else if ((this.shift.y + r1.position.y) / s <= 0 && (this.shift.y + r2.position.y) / s <= 0) { isvisible = false; } else { isvisible = true; } if (isvisible) { if (lin.arrow) // draw line as arrow { float x1 = (this.shift.x + cx + r1.position.x + r1.width / 2) / s; float y1 = (this.shift.y + cy + r1.position.y + r1.height / 2) / s; float x2 = (this.shift.x + cx + r2.position.x + r2.width / 2) / s; float y2 = (this.shift.y + cy + r2.position.y + r2.height / 2) / s; double nx1 = (Math.Cos(Math.PI / 2) * (x2 - x1) - Math.Sin(Math.PI / 2) * (y2 - y1) + x1); double ny1 = (Math.Sin(Math.PI / 2) * (x2 - x1) + Math.Cos(Math.PI / 2) * (y2 - y1) + y1); double nx2 = (Math.Cos(-Math.PI / 2) * (x2 - x1) - Math.Sin(-Math.PI / 2) * (y2 - y1) + x1); double ny2 = (Math.Sin(-Math.PI / 2) * (x2 - x1) + Math.Cos(-Math.PI / 2) * (y2 - y1) + y1); double size = Math.Sqrt((nx1 - x1) * (nx1 - x1) + (ny1 - y1) * (ny1 - y1)); nx1 = x1 + (((nx1 - x1) / size) * 7) / s; ny1 = y1 + (((ny1 - y1) / size) * 7) / s; nx2 = x1 + (((nx2 - x1) / size) * 7) / s; ny2 = y1 + (((ny2 - y1) / size) * 7) / s; // Create points that define polygon. PointF point1 = new PointF((float)nx1, (float)ny1); PointF point2 = new PointF((float)nx2, (float)ny2); PointF point3 = new PointF(x2, y2); PointF[] curvePoints = { point1, point2, point3 }; // Define fill mode. FillMode newFillMode = FillMode.Winding; // Fill polygon to screen. gfx.FillPolygon( new SolidBrush(lin.color.color), curvePoints, newFillMode ); } else { // draw line gfx.DrawLine( new Pen(lin.color.color, lin.width / s > 1 ? (int)lin.width / s : 1), (this.shift.x + cx + r1.position.x + r1.width / 2) / s, (this.shift.y + cy + r1.position.y + r1.height / 2) / s, (this.shift.x + cx + r2.position.x + r2.width / 2) / s, (this.shift.y + cy + r2.position.y + r2.height / 2) / s ); } } } }
// DRAW nodes private void DrawNodes(Graphics gfx, Nodes nodes, Position correction = null, bool export = false) { bool isvisible = false; // drawonly visible elements float s = this.scale; Pen nodeBorder = new Pen(Color.Black, 1); Pen nodeSelectBorder = new Pen(Color.Black, 3); Pen nodeLinkBorder = new Pen(Color.DarkRed, 3); Pen nodeMarkBorder = new Pen(Color.Navy, 3); // fix position for image file export int cx = 0; int cy = 0; if (correction != null) { cx = correction.x; cy = correction.y; } // DRAW nodes foreach (Node rec in nodes) // Loop through List with foreach { // exclude not visible nodes isvisible = false; if (export) { isvisible = true; } else if (0 + this.ClientSize.Width <= (this.shift.x + rec.position.x) / s) { isvisible = false; } else if ((this.shift.x + rec.position.x + rec.width) / s <= 0) { isvisible = false; } else if (0 + this.ClientSize.Height <= (this.shift.y + rec.position.y) / s) { isvisible = false; } else if ((this.shift.y + rec.position.y + rec.height) / s <= 0) { isvisible = false; } else { isvisible = true; } if (isvisible && rec.visible) { if (rec.isimage) { // DRAW Image gfx.DrawImage( rec.image, new Rectangle( (int)((this.shift.x + cx + rec.position.x) / s), (int)((this.shift.y + cy + rec.position.y) / s), (int)(rec.width / s), (int)(rec.height / s) ) ); if (rec.selected && !export) { gfx.DrawRectangle( nodeSelectBorder, new Rectangle( (int)((this.shift.x + cx + rec.position.x - 3) / s), (int)((this.shift.y + cy + rec.position.y - 3) / s), (int)((rec.width + 5) / s), (int)((rec.height + 5) / s) ) ); } } else { if (this.diagram.options.coordinates) // draw debug information { Font drawFont = new Font("Arial", 10 / s); SolidBrush drawBrush = new SolidBrush(Color.Black); gfx.DrawString( rec.id.ToString() + "i:" + (rec.position.x).ToString() + "x," + (rec.position.y).ToString()+"y", drawFont, drawBrush, (this.shift.x + rec.position.x) / s, (this.shift.y + rec.position.y - 20) / s ); } // DRAW rectangle Rectangle rect1 = new Rectangle( (int)((this.shift.x + cx + rec.position.x) / s), (int)((this.shift.y + cy + rec.position.y) / s), (int)((rec.width) / s), (int)((rec.height) / s) ); // DRAW border if (rec.name.Trim() == "") // draw empty point { if (!rec.transparent) // draw fill point { gfx.FillEllipse(new SolidBrush(rec.color.color), rect1); if (this.diagram.options.borders) gfx.DrawEllipse(nodeBorder, rect1); } if (rec.haslayer && !export) // draw layer indicator { gfx.DrawEllipse(nodeBorder, new Rectangle( (int)((this.shift.x + cx + rec.position.x - 2) / s), (int)((this.shift.y + cy + rec.position.y - 2) / s), (int)((rec.width + 4) / s), (int)((rec.height + 4) / s) ) ); } if (rec.selected && !export) { gfx.DrawEllipse( (rec.link != "") ? nodeLinkBorder : ((rec.mark) ? nodeMarkBorder : nodeSelectBorder), new Rectangle( (int)((this.shift.x + cx + rec.position.x - 2) / s), (int)((this.shift.y + cy + rec.position.y - 2) / s), (int)((rec.width + 4) / s), (int)((rec.height + 4) / s) ) ); } } else { // draw filled node rectangle if (!rec.transparent) { gfx.FillRectangle(new SolidBrush(rec.color.color), rect1); if (this.diagram.options.borders) gfx.DrawRectangle(nodeBorder, rect1); } // draw layer indicator if (rec.haslayer && !export) { gfx.DrawRectangle( nodeBorder, new Rectangle( (int)((this.shift.x + cx + rec.position.x - 2) / s), (int)((this.shift.y + cy + rec.position.y - 2) / s), (int)((rec.width + 4) / s), (int)((rec.height + 4) / s) ) ); } // draw selected node border if (rec.selected && !export) { gfx.DrawRectangle( (rec.link != "") ? nodeLinkBorder: ((rec.mark)? nodeMarkBorder : nodeSelectBorder), new Rectangle( (int)((this.shift.x + cx + rec.position.x - 2) / s), (int)((this.shift.y + cy + rec.position.y - 2) / s), (int)((rec.width + 4) / s), (int)((rec.height + 4) / s) ) ); } // DRAW text RectangleF rect2 = new RectangleF( (int)((this.shift.x + cx + rec.position.x + Node.NodePadding) / s), (int)((this.shift.y + cy + rec.position.y + Node.NodePadding) / s), (int)((rec.width - Node.NodePadding) / s), (int)((rec.height - Node.NodePadding) / s) ); gfx.DrawString( (rec.protect) ? Node.protectedName : rec.name, new Font( rec.font.FontFamily, rec.font.Size / s, rec.font.Style, GraphicsUnit.Point, ((byte)(0)) ), new SolidBrush(rec.fontcolor.color), rect2 ); } } } } }
public void add(string type, Nodes nodes = null, Lines lines = null, Position position = null, int layer = 0) { operations.Push( new UndoOperation( type, (nodes != null) ? new Nodes(nodes) : null, (lines != null) ? new Lines(lines) : null, (grouping) ? group : 0, // add multiple operations into one undo group position, layer ) ); this.saved++; // forgot undo operation if (reverseOperations.Count() > 0) { if (this.saved > 0) // save is in redo but if redo is cleared theh save is lost { this.saveLost = true; } reverseOperations.Clear(); } }
// NODE add file to diagram as attachment public void attachmentAddFile(Position position) { if (this.DSelectFileAttachment.ShowDialog() == DialogResult.OK) { string data = Compress.compress(this.DSelectFileAttachment.FileName); if (this.selectedNodes.Count() > 0) { this.diagram.undoOperations.add("edit", this.selectedNodes, null, this.shift, this.currentLayer.id); foreach (Node node in this.selectedNodes) { node.attachment = data; } this.diagram.unsave(); } else { Node newrec = this.CreateNode(position, true); newrec.attachment = data; newrec.color.set(diagram.options.colorAttachment); newrec.setName(Os.getFileName(this.DSelectFileAttachment.FileName)); this.diagram.unsave("create", newrec, this.shift, this.currentLayer.id); } this.diagram.InvalidateDiagram(); } }
/*************************************************************************************************************************/ // ADD UNDO OPERATIONS public void add(string type, Node node, Position position = null, int layer = 0) { Nodes nodes = new Nodes(); if (node != null) { nodes.Add(new Node(node)); } this.add(type, nodes, null, position, layer); }
/*************************************************************************************************************************/ // CLIPBOARD // paste part of diagram from clipboard public DiagramBlock AddDiagramPart(string DiagramXml, Position position, int layer) { Nodes NewNodes = new Nodes(); Lines NewLines = new Lines(); XmlReaderSettings xws = new XmlReaderSettings(); xws.CheckCharacters = false; string xml = DiagramXml; try { using (XmlReader xr = XmlReader.Create(new StringReader(xml), xws)) { XElement root = XElement.Load(xr); foreach (XElement diagram in root.Elements()) { if (diagram.HasElements) { if (diagram.Name.ToString() == "rectangles") { foreach (XElement block in diagram.Descendants()) { if (block.Name.ToString() == "rectangle") { Node R = new Node(); R.font = this.FontDefault; foreach (XElement el in block.Descendants()) { try { if (el.Name.ToString() == "id") { R.id = Int32.Parse(el.Value); } if (el.Name.ToString() == "text") { R.name = el.Value; } if (el.Name.ToString() == "note") { R.note = el.Value; } if (el.Name.ToString() == "x") { R.position.x = Int32.Parse(el.Value); } if (el.Name.ToString() == "y") { R.position.y = Int32.Parse(el.Value); } if (el.Name.ToString() == "color") { R.color.set(el.Value.ToString()); } if (el.Name.ToString() == "timecreate") { R.timecreate = el.Value; } if (el.Name.ToString() == "timemodify") { R.timemodify = el.Value; } if (el.Name.ToString() == "font") { R.font = Fonts.XmlToFont(el); } if (el.Name.ToString() == "fontcolor") { R.fontcolor.set(el.Value.ToString()); } if (el.Name.ToString() == "link") { R.link = el.Value; } if (el.Name.ToString() == "shortcut") { R.shortcut = Int32.Parse(el.Value); } if (el.Name.ToString() == "mark") { R.mark = bool.Parse(el.Value); } if (el.Name.ToString() == "transparent") { R.transparent = bool.Parse(el.Value); } if (el.Name.ToString() == "embeddedimage") { R.embeddedimage = bool.Parse(el.Value); } if (el.Name.ToString() == "imagedata") { R.image = new Bitmap(new MemoryStream(Convert.FromBase64String(el.Value))); R.height = R.image.Height; R.width = R.image.Width; R.isimage = true; } if (el.Name.ToString() == "image") { R.imagepath = el.Value.ToString(); if (Os.FileExists(R.imagepath)) { try { string ext = ""; ext = Os.getExtension(R.imagepath).ToLower(); if (ext == ".jpg" || ext == ".png" || ext == ".ico" || ext == ".bmp") // skratenie cesty k suboru { R.image = Media.getImage(R.imagepath); if (ext != ".ico") R.image.MakeTransparent(Color.White); R.height = R.image.Height; R.width = R.image.Width; R.isimage = true; } } catch (Exception ex) { Program.log.write("load image from xml error: " + ex.Message); } } else { R.imagepath = ""; } } if (el.Name.ToString() == "timecreate") { R.timecreate = el.Value; } if (el.Name.ToString() == "timemodify") { R.timemodify = el.Value; } if (el.Name.ToString() == "attachment") { R.attachment = el.Value; } if (el.Name.ToString() == "layer") { R.layer = Int32.Parse(el.Value); } if (el.Name.ToString() == "protect") { R.protect = bool.Parse(el.Value); } } catch (Exception ex) { Program.log.write("Data has wrong structure. : error: " + ex.Message); } } NewNodes.Add(R); } } } if (diagram.Name.ToString() == "lines") { foreach (XElement block in diagram.Descendants()) { if (block.Name.ToString() == "line") { Line L = new Line(); foreach (XElement el in block.Descendants()) { try { if (el.Name.ToString() == "start") { L.start = Int32.Parse(el.Value); } if (el.Name.ToString() == "end") { L.end = Int32.Parse(el.Value); } if (el.Name.ToString() == "arrow") { L.arrow = el.Value == "1" ? true : false; } if (el.Name.ToString() == "color") { L.color.set(el.Value.ToString()); } if (el.Name.ToString() == "width") { L.width = Int32.Parse(el.Value); } if (el.Name.ToString() == "layer") { L.layer = Int32.Parse(el.Value); } } catch (Exception ex) { Program.log.write("Data has wrong structure. : error: " + ex.Message); } } NewLines.Add(L); } } } } } } } catch (Exception ex) { Program.log.write("Data has wrong structure. : error: " + ex.Message); } List<MappedNode> maps = new List<MappedNode>(); Nodes NewReorderedNodes = new Nodes(); // order nodes parent first (layer must exist when sub node is created) this.nodesReorderNodes(0, null, NewNodes, NewReorderedNodes); int layerParent = 0; MappedNode mappedNode; Nodes createdNodes = new Nodes(); Node newNode = null; int oldId = 0; foreach (Node rec in NewReorderedNodes) { layerParent = 0; if (rec.layer == 0) { layerParent = layer; } else { foreach (MappedNode mapednode in maps) { if (rec.layer == mapednode.oldId) { layerParent = mapednode.newNode.id; break; } } } rec.layer = layerParent; rec.position.add(position); rec.resize(); oldId = rec.id; newNode = this.createNode(rec); if (newNode != null) { mappedNode = new MappedNode(); mappedNode.oldId = oldId; mappedNode.newNode = newNode; createdNodes.Add(newNode); maps.Add(mappedNode); } } // fix layers and shortcuts foreach (Node rec in NewNodes) { if (rec.shortcut != 0) { foreach (MappedNode mapednode in maps) { if (rec.shortcut == mapednode.oldId) { rec.shortcut = mapednode.newNode.id; break; } } } } Lines createdLines = new Lines(); Line newLine = null; foreach (Line line in NewLines) { foreach (MappedNode mapbegin in maps) { if (line.start == mapbegin.oldId) { foreach (MappedNode mapend in maps) { if (line.end == mapend.oldId) { newLine = this.Connect( mapbegin.newNode, mapend.newNode, line.arrow, line.color, line.width ); if (newLine != null) { createdLines.Add(newLine); } } } } } } return new DiagramBlock(NewNodes, createdLines); }