{"id":1225,"date":"2015-06-24T08:51:27","date_gmt":"2015-06-24T08:51:27","guid":{"rendered":"http:\/\/mindfusion.eu\/blog\/?p=1225"},"modified":"2021-01-15T15:47:06","modified_gmt":"2021-01-15T15:47:06","slug":"create-a-dialogue-editor-using-mindfusion-diagram","status":"publish","type":"post","link":"https:\/\/mindfusion.dev\/blog\/create-a-dialogue-editor-using-mindfusion-diagram\/","title":{"rendered":"Create a Dialogue Editor using MindFusion Diagram"},"content":{"rendered":"<p>In this post we&#8217;ll demonstrate how to create a graphical interface for editing dialogues using MindFusion diagramming API. The sample could be used as a module in different kinds of applications, such as software for creating and conducting surveys, editing interactive voice response systems, designing NPC dialogues in game development tools. You can download the complete project here:<\/p>\n<p><a href=\"https:\/\/mindfusion.dev\/_samples\/DialogueEditor.zip\">DialogueEditor.zip<\/a><\/p>\n<p>The sample code will show several features of Diagram control:<\/p>\n<ul>\n<li>TableNode API<\/li>\n<li>in-place edit<\/li>\n<li>work with groups<\/li>\n<li>graph traversal<\/li>\n<\/ul>\n<p>Questions or IVR messages and their possible answers \/ responses will be displayed respectively in caption area and cells of TableNode objects. Helper nodes at table bottom will let users add or remove rows. DiagramLink objects connecting table rows to other tables will define the dialogue flow, i.e. what next question \/ message to display after user selects option from current message.<\/p>\n<p>Let&#8217;s start by creating a new .NET Windows Forms project. If you have installed MindFusion diagram control and selected toolbox integration from setup wizard screen, you should now see a Diagram component and DiagramView control in the toolbox. If they are not available, right click and select Choose Items, navigate to installation folder and select the mindfusion.diagramming and mindfusion.diagramming.winforms assemblies. Now drag a Diagram component to the form, and set its name to &#8220;diagram&#8221;. This automatically adds a diagramming.dll reference to the project. Drag a DiagramView (which add diagramming.winforms reference) and name it diagramView. Set its Diagram property to &#8220;diagram&#8221;, selecting it from the drop-down in property grid.<\/p>\n<p>We will allow creation only of tables and links, so let&#8217;s set DiagramView.Behavior property to LinkTables. Now if users draw on the diagram canvas, the component will create TableNode if the mouse pointer is over unoccupied part of the diagram, or a DiagramLink if the mouse points a table. If we wanted to support more type of nodes, we could add their prototypes to a NodeListView instance and let users create new instances via drag-and-drop.<\/p>\n<p>Add the following fields and constructor code to set up appearance and behavior of diagram elements.<\/p>\n<pre>public MainForm()\n{\n\tInitializeComponent();\n\n\t\/\/ set up initial table appearance\n\tdiagram.TableNodeStyle.Brush = new MindFusion.Drawing.SolidBrush(Color.LightGray);\n\tdiagram.TableRowCount = 1;\n\tdiagram.TableColumnCount = 1;\n\tdiagram.TableCaption = \"question\";\n\tdiagram.NodeEffects.Add(new GlassEffect());\n\n\t\/\/ highlight a row when clicked\n\tdiagram.AutoHighlightRows = true;\n\n\t\/\/ find link routes automatically\n\tdiagram.RouteLinks = true;\n\n\t\/\/ allow edit texts by double click\n\tdiagramView.AllowInplaceEdit = true;\n\n\t\/\/ row anchor points\n\trightOutput = new AnchorPattern(\"Right\");\n\trightOutput.Points.Add(new AnchorPoint(100, 50, false, true));\n\n\t\/\/ table anchor points\n\tinput = new AnchorPattern(\"Input\");\n\tinput.Points.Add(new AnchorPoint(50, 0, true, false));\n\tinput.Points.Add(new AnchorPoint(50, 100, true, true));\n}\n\nAnchorPattern rightOutput;\nAnchorPattern input;\n<\/pre>\n<p>Select the diagram component in form editor and double click its NodeCreated event to add event handler. NodeCreated is raised when the user draws a new node. Add following code to associate a question \/ IVR message with the table, and initialize some default texts. The BeginEdit method automatically opens in-place editor to let user edit caption text immediately after drawing. We also create + and &#8211; ShapeNodes that will act as button widgets attached to the table&#8217;s bottom-right corner.<\/p>\n<pre>private void OnNodeCreated(object sender, MindFusion.Diagramming.NodeEventArgs e)\n{\n\tvar table = e.Node as TableNode;\n\tif (table != null)\n\t{\n\t\tint tableId = (1 + diagram.Nodes.Count \/ 3);\n\t\ttable.Id = tableId;\n\t\ttable.RowAnchorPattern = rightOutput;\n\t\ttable.AnchorPattern = input;\n\t\ttable.ConnectionStyle = TableConnectionStyle.Both;\n\t\ttable[0, 0].Text = \"option 1\";\n\t\ttable.Caption = \"question \" + tableId;\n\t\tdiagramView.BeginEdit(table);\n\n\t\t\/\/ create + button for adding new rows\n\t\tvar r = table.Bounds;\n\t\tvar p = new PointF(r.Right - 14, r.Bottom - 8);\n\t\tvar s = new SizeF(6, 6);\n\t\tvar plus = diagram.Factory.CreateShapeNode(p, s, Shapes.Cross);\n\t\tplus.Brush = new MindFusion.Drawing.SolidBrush(Color.Green);\n\t\tplus.AttachTo(table, AttachToNode.BottomRight);\n\t\tplus.Tag = \"+\";\n\n\t\t\/\/ create - button for deleting selected row\n\t\tp.X += 7;\n\t\tp.Y += 2;\n\t\ts.Height -= 4;\n\t\tvar minus = diagram.Factory.CreateShapeNode(p, s, Shapes.Rectangle);\n\t\tminus.Brush = new MindFusion.Drawing.SolidBrush(Color.Red);\n\t\tminus.AttachTo(table, AttachToNode.BottomRight);\n\t\tminus.Tag = \"-\";\n\n\t\tplus.Locked = minus.Locked = true;\n\t\ttable.SubordinateGroup.AutoDeleteItems = true;\n\t}\n}\n<\/pre>\n<p>Now add a NodeClicked handler that adds or deletes rows. If the + button is clicked, the code inserts a new row before current highlighted row. If the &#8211; button is clicked, the handler deletes current highlighted row.<\/p>\n<pre>private void OnNodeClicked(object sender, NodeEventArgs e)\n{\n\tif (\"+\".Equals(e.Node.Tag))\n\t{\n\t\tvar table = (TableNode)e.Node.MasterGroup.MainItem;\n\t\tif (table.HighlightedRow == -1)\n\t\t\ttable.RowCount++;\n\t\telse\n\t\t\ttable.InsertRow(table.HighlightedRow);\n\t}\n\n\tif (\"-\".Equals(e.Node.Tag))\n\t{\n\t\tvar table = (TableNode)e.Node.MasterGroup.MainItem;\n\t\tif (table.HighlightedRow != -1)\n\t\t\ttable.DeleteRow(table.HighlightedRow);\n\t}\n}\n<\/pre>\n<p>Finally, lets create export function that will traverse the dialogue graph and export it to a custom-format XML file, which could then be passed on to a system processing the dialogues, such as IVR service.<\/p>\n<pre>private void btnExport_Click(object sender, EventArgs e)\n{\n\tvar fileDlg = new SaveFileDialog();\n\tif (fileDlg.ShowDialog() == DialogResult.OK)\n\t{\n\t\tvar doc = new XmlDocument();\n\t\tvar root = doc.CreateElement(\"Dialogue\");\n\t\tdoc.AppendChild(root);\n\n\t\tforeach (var node in diagram.Nodes)\n\t\t{\n\t\t\tvar table = node as TableNode;\n\t\t\tif (table != null)\n\t\t\t{\n\t\t\t\tvar questionElement = doc.CreateElement(\"Question\");\n\t\t\t\troot.AppendChild(questionElement);\n\n\t\t\t\tint id = (int)table.Id;\n\t\t\t\tquestionElement.SetAttribute(\"Id\", table.Id.ToString());\n\t\t\t\tquestionElement.SetAttribute(\"Text\", table.Caption);\n\n\t\t\t\tfor (int r = 0; r &lt; table.Rows.Count; r++)\n\t\t\t\t{\n\t\t\t\t\tstring answer = table[0, r].Text;\n\t\t\t\t\tvar answerElement = doc.CreateElement(\"Answer\");\n\t\t\t\t\tquestionElement.AppendChild(answerElement);\n\t\t\t\t\tanswerElement.SetAttribute(\"Text\", answer);\n\t\t\t\t\tif (table.Rows[r].OutgoingLinks.Count &gt; 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tvar link = table.Rows[r].OutgoingLinks[0];\n\t\t\t\t\t\tvar nextQuestion = (TableNode)link.Destination;\n\t\t\t\t\t\tanswerElement.SetAttribute(\"Text\", answer);\n\t\t\t\t\t\tanswerElement.SetAttribute(\"NextId\", nextQuestion.Id.ToString());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tdoc.Save(fileDlg.FileName);\n\t}\n}\n<\/pre>\n<p>If you run the application now and draw several tables and links, you should see a similar screen:<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/mindfusion.dev\/_samples\/dialogue_editor.png\" alt=\"dialogue editor created with mindfusion diagram control for .NET\" \/><\/p>\n<p>The code above uses MindFusion\u2019s .NET API and can be used with Windows Forms, WPF, Silverlight and ASP.NET diagramming components. The Java API for Android and desktop Swing application will look similar, with setter method calls instead of property assignments.<\/p>\n<p>You can download the trial version of any MindFusion.Diagramming component from <a href=\"http:\/\/mindfusion.dev\/download-diagramming-pack.html\">this page<\/a>.<\/p>\n<p>Enjoy!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this post we&#8217;ll demonstrate how to create a graphical interface for editing dialogues using MindFusion diagramming API. The sample could be used as a module in different kinds of applications, such as software for creating and conducting surveys, editing &hellip; <a href=\"https:\/\/mindfusion.dev\/blog\/create-a-dialogue-editor-using-mindfusion-diagram\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[95,74],"tags":[],"class_list":["post-1225","post","type-post","status-publish","format-standard","hentry","category-diagramming-2","category-sample-code"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p3RlKs-jL","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/posts\/1225","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/comments?post=1225"}],"version-history":[{"count":2,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/posts\/1225\/revisions"}],"predecessor-version":[{"id":2548,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/posts\/1225\/revisions\/2548"}],"wp:attachment":[{"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/media?parent=1225"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/categories?post=1225"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mindfusion.dev\/blog\/wp-json\/wp\/v2\/tags?post=1225"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}