Sfall-ScriptEditor

Форк
0
1460 строк · 56.7 Кб
1
using System;
2
using System.Collections.Generic;
3
using System.Drawing;
4
using System.IO;
5
using System.Linq;
6
using System.Windows.Forms;
7

8
using System.Xml;
9
using System.Xml.XPath;
10

11
using ICSharpCode.ClassDiagram;
12
using ICSharpCode.Diagrams.Drawables;
13
using ICSharpCode.TextEditor.Document;
14

15
using ScriptEditor.CodeTranslation;
16
using ScriptEditor.TextEditorUI;
17
using ScriptEditor.TextEditorUI.ToolTips;
18
using ScriptEditor.TextEditorUI.Nodes;
19
using ScriptEditor.TextEditorUtilities;
20

21
namespace ScriptEditor
22
{
23
    public partial class NodeDiagram : Form
24
    {
25
        public event EventHandler ChangeNodes; // event for parse script editor
26

27
        private ClassCanvas nodesCanvas = new ClassCanvas();
28

29
        // List of names of all used nodes in script
30
        private List<string> nodesProcedureName = new List<string>();
31
        // List of hidden nodes
32
        private Dictionary<string, NodeCanvasItem> HideNodes = new Dictionary<string, NodeCanvasItem>();
33
        // List of all used nodes with parser data
34
        private Dictionary<string, List<DialogueParser>> NodesData = new Dictionary<string, List<DialogueParser>>();
35

36
        private List<ContentBody> NodeBody;
37
        private List<string> linkFrom;
38
        private List<LinkTo> linkToList;
39

40
        private string[] MessagesData;
41

42
        private TabInfo sourceTab;
43
        private IDocument scriptText;
44
        private Procedure[] scriptProc;
45

46
        private string fcdFilePath = null;   // путь и файл для сохранения
47

48
        private string scriptName;
49
        private bool shiftDown;
50
        private bool needUpdate;
51
        private bool autoUpdate;        // save setting
52
        private bool woExitNode;        // save setting
53
        private bool fсClosed;          // закрытие основной формы диаграмм
54

55
        private bool shouldUpdate = true; // нужно ли обновление холста после изменения в коде скрипта, используетя для предотвращения не нужного обновления.
56

57
        public bool NeedUpdate
58
        {
59
            private get { return needUpdate; }
60
            set {
61
                    if (shouldUpdate) needUpdate = value;
62
                    shouldUpdate = true;
63
                    UpdateProceduresInfo();
64
                }
65
        }
66

67
        #region Form Initialize
68

69
        private const string help = "Управление:\n" +
70
                                    "Shift + Левый Щелчек на строке текта сообщения - Быстрое редактирования сообщения.\n" +
71
                                    "Ctrl + Левый Щелчек - Добавляет или снимает выделение ноды.\n" +
72
                                    "Средняя кнопка Мыши - Премещение хоста.\n" +
73
                                    "Колесеко Мышки - Увеличить/Уменьшить маштаб.\n" +
74
                                    "Правая кнопка Мышки - Вызвать контекстное меню.";
75

76
        public NodeDiagram(TabInfo tabInfo)
77
        {
78
            InitializeComponent();
79

80
            if (Settings.hintsLang != 0) HelptoolStripButton.ToolTipText = help;
81

82
            // set settings
83
            autoUpdate = autoUpdateNodesToolStripMenuItem.Checked = Settings.autoUpdate;
84
            woExitNode =  ShowExitNodeToolStripMenuItem.Checked = Settings.woExitNode;
85
            autoArrangeToolStripMenuItem.Checked = Settings.autoArrange;
86
            autoSaveOnExitToolStripMenuItem.Checked = Settings.autoSaveChart;
87
            autoHideNodesToolStripMenuItem.Checked = Settings.autoHideNodes;
88

89
            this.Text += tabInfo.filename;
90

91
            this.sourceTab = tabInfo;
92
            this.scriptText = tabInfo.textEditor.Document;
93
            this.scriptProc = tabInfo.parseInfo.procs;
94

95
            nodesCanvas.KeyDown += NodeDiagram_KeyDown;
96
            nodesCanvas.KeyUp += NodeDiagram_KeyUp;
97

98
            this.Controls.Add(nodesCanvas);
99
            toolStrip.SendToBack();
100
            nodesCanvas.Dock = DockStyle.Fill;
101
            nodesCanvas.ContextMenuStrip = contextMenuStrip;
102

103
            // Canvas Events
104
            nodesCanvas.CanvasItemHover += CanvasItemHover;
105
            nodesCanvas.CanvasItemSelected += CanvasItemSelected;
106
            nodesCanvas.CanvasItemUnSelected += CanvasItemUnSelected;
107
            nodesCanvas.LayoutChanged += LayoutChanged;
108
            nodesCanvas.Scroll += ScrollChanged;
109
            nodesCanvas.CanvasMouseWheel += CanvasMouseWheel;
110
            nodesCanvas.ZoomChanged += new EventHandler(CanvasZoomChanged);
111
            //nodesCanvas.ContextMenuStrip.Closed
112

113
            scriptName = scriptProc[tabInfo.parseInfo.GetProcedureIndex("talk_p_proc")].filename;
114

115
            InitData();
116
        }
117

118
        private void NodeDiagram_Shown(object sender, EventArgs e)
119
        {
120
            nodesCanvas.Visible = false;
121

122
            string ext = "." + saveFileDialog.DefaultExt;
123
            string fcd = Path.ChangeExtension(sourceTab.filepath, ext);
124
            if (File.Exists(fcd)) {
125
                fcdFilePath = fcd;
126
                LoadFlowchartDiagram();
127
            } else { // fcd sub folder
128
                fcd = Path.Combine(Path.GetDirectoryName(sourceTab.filepath), saveFileDialog.DefaultExt,
129
                                   Path.GetFileNameWithoutExtension(sourceTab.filepath) + ext);
130
                if (File.Exists(fcd)) {
131
                    fcdFilePath = fcd;
132
                    LoadFlowchartDiagram();
133
                } else {
134
                    #if DEBUG
135
                        CreateCanvasNodes();
136
                    #endif
137
                }
138
            }
139
        }
140
        #endregion
141

142
        #region Create Nodes
143
        /// <summary>
144
        /// Main Init
145
        /// </summary>
146
        private void InitData()
147
        {
148
            // получить имена всех Node процедур из скрипта
149
            nodesProcedureName = DialogueParser.GetAllNodesName(scriptProc);
150
            if (nodesProcedureName.Count == 0)
151
                return;
152

153
            ReadMessageData(sourceTab.msgFilePath);
154

155
            // распарсить полученный блок Node процедуры, проанализировав связи, получить тексты сообщений.
156
            foreach (var name in nodesProcedureName)
157
            {
158
                if (woExitNode && name.Equals("node999", StringComparison.OrdinalIgnoreCase))
159
                    continue;
160

161
                int index = sourceTab.parseInfo.GetProcedureIndex(name, scriptProc);
162
                string nodeCode = Utilities.GetProcedureCode(scriptText, scriptProc[index]);
163
                if (nodeCode == null)
164
                    continue;
165

166
                ParseNodeCode(name, nodeCode);
167
            }
168
        }
169

170
        private List<DialogueParser> ParseNodeCode(string nodeName, string nodeCode)
171
        {
172
            List<DialogueParser> DialogNode = new List<DialogueParser>();
173
            DialogueParser.PrepareNodeCode(nodeCode, DialogNode, sourceTab.parseInfo, !tsbShowCommentCode.Checked);
174

175
            // Имя ноды и данные
176
            NodesData.Add(nodeName, DialogNode);
177

178
            return DialogNode;
179
        }
180

181
        /// <summary>
182
        /// Добавление для отображения нод на холсте, из подготовленных данных NodesData
183
        /// </summary>
184
        private void CreateCanvasNodes()
185
        {
186
            int shiftY = 0;
187
            int shiftX = 0;
188

189
            foreach (var node in NodesData)
190
                AddNodeToCanvas(node, ref shiftY, ref shiftX);
191

192
            nodesCanvas.Visible = true;
193
            nodesCanvas.Refresh();
194
            MessageFile.ShowMissingFiles();
195
        }
196

197
        private void AddNodeToCanvas(KeyValuePair<string, List<DialogueParser>> node, ref int shiftY, ref int shiftX)
198
        {
199
            INode nodeData; // this not used
200
            NodeCanvasItem nodeItem = CreateNodeItem(node, out nodeData);
201

202
            if (!nodeData.ShowCodeNodeButton) nodeItem.RemoveItemContex(); // удаляет строки с кодом
203

204
            if (Settings.autoHideNodes && nodeItem.GetNodeData.NodeType == NodesType.Unused) {
205
                nodeItem.Hidden = true;
206
                HideNodes.Add(node.Key, nodeItem);
207
            } else {
208
                nodeItem.X = 25 + shiftX;
209
                nodeItem.Y = 25 + shiftY;
210
                nodesCanvas.AddCanvasItem(nodeItem);
211

212
                int height = (int)nodeItem.Height;
213
                if (height > 500) {
214
                    shiftX += 50 + (int)nodeItem.Width;
215
                } else {
216
                    shiftY += 25 + height;
217
                    shiftX += 25 + ((int)nodeItem.Width / 2);
218
                }
219
            }
220
        }
221

222
        /// <summary>
223
        /// 
224
        /// </summary>
225
        /// <param name="node"></param>
226
        /// <param name="nodeData"></param>
227
        /// <returns></returns>
228
        private NodeCanvasItem CreateNodeItem(KeyValuePair<string, List<DialogueParser>> node, out INode nodeData)
229
        {
230
            nodeData = GetNodeData(node);
231

232
            nodeData.ShowCodeNodeButton = tsbShowAllCode.Checked;
233

234
            // создать ноду для отображения из сформированных данных DataNode
235
            NodeCanvasItem nodeItem = ClassCanvas.CreateItemFromType(nodeData);
236

237
            nodeItem.ContentClick += ClickContentText;
238
            nodeItem.ShowCodeButtonClick += nodeItem_ShowCodeButtonClick;
239

240
            return nodeItem;
241
        }
242

243
        void nodeItem_ShowCodeButtonClick(NodeCanvasItem item)
244
        {
245
            UpdateAllNodes();
246
        }
247

248
        /// <summary>
249
        /// Подготовить и получить данные для дальнейшего отображения ноды на холсте
250
        /// </summary>
251
        /// <param name="node"></param>
252
        /// <returns></returns>
253
        private INode GetNodeData(KeyValuePair<string, List<DialogueParser>> node)
254
        {
255
            List<DialogueParser> value = node.Value;
256
            NodeBody = new List<ContentBody>();
257

258
            // node link to node, and message text
259
            linkToList = new List<LinkTo>();
260

261
            for (int n = 0; n < value.Count; n++)
262
            {
263
                if (value[n].opcode == OpcodeType.Option || value[n].opcode == OpcodeType.giq_option ||
264
                    value[n].opcode == OpcodeType.gsay_option || value[n].opcode == OpcodeType.call)
265
                {
266
                    linkToList.Add(new LinkTo(value[n].toNode, n + 1));
267
                }
268

269
                string msgText = (value[n].opcode != OpcodeType.None && value[n].opcode != OpcodeType.call)
270
                               ? GetMessageText(value[n].numberMsgFile, value[n].numberMsgLine)
271
                               : null;
272

273
                //поместить распарсенные данные из Node процедуры в List<ContentBody>
274
                NodeBody.Add(new ContentBody((value[n].code.StartsWith(new string(' ', Settings.tabSize))) ? value[n].code.Remove(0, Settings.tabSize): value[n].code,
275
                                             msgText, value[n].opcode, value[n].numberMsgLine, value[n].numberMsgFile, n));
276
            }
277

278
            // получить список имен: link from nodes
279
            List<string> linklist = new List<string>();
280

281
            foreach (var data in NodesData)
282
            {
283
                foreach (var nd in data.Value)
284
                {
285
                    if (nd.toNode == null || linklist.Contains(data.Key)) continue;
286

287
                    if (nd.toNode.Equals(node.Key, StringComparison.OrdinalIgnoreCase)) linklist.Add(data.Key);
288
                }
289
            }
290

291
            int i = 0;
292
            linkFrom = new List<string>() { String.Empty, String.Empty };
293
            foreach (var link in linklist)
294
            {
295
                linkFrom[i] += ((linkFrom[i].Length > 0) ? " : " : String.Empty) + link;
296
                i = 1 - i;
297
            }
298

299
            NodesType type = NodesType.Default;
300
            if (node.Key.Equals("talk_p_proc", StringComparison.OrdinalIgnoreCase))
301
                type = NodesType.DialogStart;
302
            else if (linkToList.Count == 0 && linklist.Count > 0)
303
                type = NodesType.DialogEnd;
304
            else if (linkToList.Count > 0 && linklist.Count == 0)
305
                type = NodesType.NoFromLink;
306
            else if (linkToList.Count == 0 && linklist.Count == 0)
307
                type = NodesType.Unused;
308

309
            return new DataNode(node.Key, linkToList, linkFrom, NodeBody, type);
310
        }
311

312
        /// <summary>
313
        /// Получить и подготовить данные для указанной ноды
314
        /// (метод используется при загрузке сохраненных данных из XML файла)
315
        /// </summary>
316
        /// <param name="nodeName">Имя ноды</param>
317
        private INode GetNodeData(string nodeName)
318
        {
319
            if (NodesData.ContainsKey(nodeName))
320
                return GetNodeData(new KeyValuePair<string, List<DialogueParser>>(nodeName, NodesData[nodeName]));
321
            else
322
                return null;
323
        }
324

325
        // UNDONE:
326
        /*private void UpdateNode(string name)
327
        {
328
            if (!NodesData.ContainsKey(name))
329
                return;
330

331
            //UpdateProceduresInfo();
332

333
            ///
334
            int index = sourceTab.parseInfo.GetProcedureIndex(name, scriptProc);
335
            string nodeProcedureText = Utilities.GetProcedureCode(scriptText, scriptProc[index]);
336
            if (nodeProcedureText == null)
337
                return;
338

339
            List<DialogueParser> DialogNode = new List<DialogueParser>();
340
            DialogueParser.PrepareNodeCode(nodeProcedureText, DialogNode, sourceTab.parseInfo, !tsbShowCommentCode.Checked);
341
            //
342

343
            NodesData.Remove(name); // удалить данные существующей ноды
344

345
            // Имя ноды и данные
346
            NodesData.Add(name, DialogNode);
347

348
            int dummy = 0;
349
            var node = new KeyValuePair<string, List<DialogueParser>>(name, NodesData[name]);
350
            ReCreateNodeCanvas(node, ref dummy);
351
        }*/
352

353
        /// <summary>
354
        /// Обновить данные для всех созданных нод на холсте
355
        /// </summary>
356
        private void UpdateAllNodes()
357
        {
358
            NodesData.Clear();
359
            nodesProcedureName.Clear();
360

361
            UpdateProceduresInfo();
362

363
            InitData();
364

365
            bool focused = (nodesCanvas.GetLastFocusItem() != null);
366
            int shift = 0;
367

368
            List<INode> Nodes = new List<INode>();
369
            foreach (var node in NodesData)
370
                Nodes.Add(ReCreateNodeCanvas(node, ref shift));
371

372
            //
373
            nodesCanvas.RemoveUnusedNodes(Nodes);
374

375
            if (focused)
376
                nodesCanvas.SetJustLastFocus();
377
        }
378

379
        /// <summary>
380
        /// Пересоздание уже существующей ноды на холсте
381
        /// </summary>
382
        /// <param name="node"></param>
383
        /// <returns></returns>
384
        private INode ReCreateNodeCanvas(KeyValuePair<string, List<DialogueParser>> node, ref int shift)
385
        {
386
            // проверить не скрыта ли нода стаким именем
387
            bool IsHide = HideNodes.ContainsKey(node.Key);
388

389
            INode nodeData;
390
            NodeCanvasItem newNodeItem = CreateNodeItem(node, out nodeData);
391

392
            CanvasItem existNodeItem;
393
            //получить данные из уже созданной ноды
394
            if (IsHide)
395
                existNodeItem = HideNodes[node.Key];
396
            else
397
                existNodeItem = nodesCanvas.GetNodeCanvasItem(nodeData.Name);
398

399
            if (existNodeItem != null) {
400
                // установить расположение и размеры ноды на холсте
401
                newNodeItem.X = existNodeItem.X;
402
                newNodeItem.Y = existNodeItem.Y;
403
                newNodeItem.Width = existNodeItem.Width;
404

405
                // установить cостояния
406
                newNodeItem.Collapsed = ((NodeCanvasItem)existNodeItem).Collapsed;
407

408
                INode _nodeData = ((NodeCanvasItem)existNodeItem).GetNodeData;
409
                if (_nodeData.GetStateShowNodeCodeButton()) {
410
                    nodeData.SetStateShowNodeCodeButton();
411
                    nodeData.ShowCodeNodeButton = _nodeData.ShowCodeNodeButton;
412
                    newNodeItem.ViewAllNodeCode = _nodeData.ShowCodeNodeButton;
413
                }
414

415
                for (int l = 0; l < newNodeItem.NodeContentsCount; l++)
416
                    newNodeItem.SetContentCollapsed(l.ToString(), ((NodeCanvasItem)existNodeItem).ContentIsCollapsed(l.ToString()));
417

418
            } else if (!IsHide) {
419
                //уст. позицию вслучае если ноды на холсте несуществует
420
                newNodeItem.X = 100 + shift;
421
                newNodeItem.Y = 100;
422

423
                shift += 350;
424
            }
425

426
            if (nodeData.GetStateShowNodeCodeButton()) {
427
                if (!nodeData.ShowCodeNodeButton)
428
                    newNodeItem.RemoveItemContex();
429
            } else if (!tsbShowAllCode.Checked) {
430
                newNodeItem.RemoveItemContex();
431
            }
432

433
            //добавляем обновленную и удаляем существующую ноду
434
            if (IsHide) {
435
                HideNodes.Remove(node.Key);
436
                newNodeItem.Hidden = true;
437
                HideNodes.Add(node.Key, newNodeItem);
438
            } else {
439
                nodesCanvas.AddCanvasItem(newNodeItem, existNodeItem);
440
                nodesCanvas.RemoveCanvasItem(existNodeItem);
441
            }
442
            return nodeData;
443
        }
444

445
        /// <summary>
446
        ///  Создать новую ноду на холсте
447
        /// </summary>
448
        /// <param name="nodeName"></param>
449
        /// <param name="nodeCode"></param>
450
        private void CreateNewNode(string nodeName, string nodeCode)
451
        {
452
            nodesProcedureName.Add(nodeName);
453

454
            INode nodeData;
455
            List<DialogueParser> DialogNode = ParseNodeCode(nodeName, nodeCode);
456
            NodeCanvasItem nodeItem = CreateNodeItem(new KeyValuePair<string, List<DialogueParser>>(nodeName, DialogNode), out nodeData);
457

458
            // Установить позицию для новой ноды
459
            int x = nodesCanvas.HorizontalScroll.Value + (nodesCanvas.Width / 2);
460
            int y = nodesCanvas.VerticalScroll.Value + (nodesCanvas.Height / 2);
461
            nodeItem.X = (x - (nodeItem.Width / 2)) / nodesCanvas.Zoom;
462
            nodeItem.Y = (y - (nodeItem.Height / 2)) / nodesCanvas.Zoom;
463

464
            nodeItem.Collapsed = false;
465

466
            if (!nodeData.ShowCodeNodeButton) nodeItem.RemoveItemContex(); // удаляет строки с кодом
467

468
            nodesCanvas.AddCanvasItem(nodeItem);
469
            nodesCanvas.SetFocusedCanvasItem(nodeItem);
470

471
            #region Simple example add new node
472
            /*
473
            * List<LinkTo> linkList;
474
            * List<ContentBody> ProcedureBody;
475
            * List<string> linkfrom = new List<string>();
476
            * linkList = new List<LinkTo>();
477
            * 
478
            * linkfrom.Add("Start");
479
            * linkfrom.Add("End");
480
            * linkList.Add(new LinkTo("Node001",4));
481
            * linkList.Add(new LinkTo("Node002",6));
482
            * 
483
            * ProcedureBody = new List<ContentBody>();
484
            * ProcedureBody.Add(new ContentBody("If <condition>", null, OpcodeType.None));
485
            * ProcedureBody.Add(new ContentBody("reply", "Я только прошу не трогать ее и, э-э, не фотографировать со вспышкой.", OpcodeType.Reply));
486
            * ProcedureBody.Add(new ContentBody("else", null, OpcodeType.None));
487
            * ProcedureBody.Add(new ContentBody("options", "Как твое имя?", OpcodeType.Option));
488
            * ProcedureBody.Add(new ContentBody("end", null, OpcodeType.None));
489
            * ProcedureBody.Add(new ContentBody("options", "Проваливай!", OpcodeType.Option));
490
            * NodeCanvasItem item = ClassCanvas.CreateItemFromType(new DataNode(nodeName, linkList, linkfrom, ProcedureBody, NodesType.Unused));
491
            */
492
            #endregion
493
        }
494
        #endregion
495

496
        #region Hide/Unhide nodes
497
        private void HideNode(NodeCanvasItem node)
498
        {
499
            string key = node.GetNodeData.Name;
500
            node.Hidden = true;
501
            HideNodes.Add(key, node);
502
            nodesCanvas.RemoveCanvasItem(node);
503
        }
504

505
        private void UnHideNode(string key)
506
        {
507
            NodeCanvasItem item = HideNodes[key];
508
            if (item.X == 0 && item.Y == 0)
509
                    item.Y = item.X = 25;
510
            item.Hidden = false;
511
            nodesCanvas.ReAddedCanvasItem(item);
512
            HideNodes.Remove(key);
513

514
            //nodesCanvas.ClearAllItemsFocus();
515
            nodesCanvas.Refresh();
516
        }
517

518
        private void UnHideAll()
519
        {
520
            int shift = 20;
521
            foreach (NodeCanvasItem item in HideNodes.Values) {
522
                if (item.X == 0 && item.Y == 0) {
523
                    item.Y = 20;
524
                    item.X = shift;
525
                    shift += (int)item.Width + 20;
526
                }
527
                item.Hidden = false;
528
                nodesCanvas.ReAddedCanvasItem(item);
529
            }
530
            HideNodes.Clear();
531

532
            nodesCanvas.ClearAllItemsFocus();
533
            nodesCanvas.Refresh();
534
        }
535
        #endregion
536

537
        // Update data procedures
538
        private void UpdateProceduresInfo()
539
        {
540
            scriptProc = ParserInternal.GetProcsData(scriptText.TextContent, sourceTab.filepath);
541
        }
542

543
        private void ReadMessageData(string msgfilePath)
544
        {
545
            MessagesData = File.ReadAllLines(msgfilePath, Settings.EncCodePage);
546
            if (msgfilePath == sourceTab.msgFilePath)
547
                MessageFile.ParseMessages(sourceTab, MessagesData);
548
        }
549

550
        private string GetMessageText(int msgNum, int msgLineNum)
551
        {
552
            string msg = null;
553
            if (msgLineNum > 0) {
554
                if (msgNum > 0) {
555
                    string path;
556
                    if (MessageFile.GetPath(sourceTab, msgNum, out path, true)) {
557
                        string[] MsgData = File.ReadAllLines(path, Settings.EncCodePage);
558
                        msg = MessageFile.GetMessages(MsgData, msgLineNum);
559
                    } else
560
                        msg = String.Format(MessageFile.msgfileError, msgNum);
561
                }
562
                else if (sourceTab.messages.ContainsKey(msgLineNum)) {
563
                        msg = sourceTab.messages[msgLineNum];
564
                }
565
                if (msg == null) msg = MessageFile.messageError;
566
            } else
567
                msg = "ParseCode: <Could not get line number of this code>";
568

569
            return msg;
570
        }
571

572
        private bool NodeIsEditing(NodeCanvasItem node)
573
        {
574
            if (node.IsEditing) return true;
575

576
            foreach (var fcTE in sourceTab.nodeFlowchartTE)
577
            {
578
                if (fcTE.NodeName == node.GetNodeData.Name) return true;
579
            }
580
            return false;
581
        }
582

583
        private void CanvasItemHover(object sender, CanvasItemEventArgs e)
584
        {
585
            if (e.CanvasItem is NodeCanvasItem) {
586
                editNodeToolStripMenuItem.Enabled = true;
587
                editNodeToolStripMenuItem.Tag = e.CanvasItem;
588
                editNodeToolStripMenuItem.Text = "Edit Node: " + e.CanvasItem.ToString();
589

590
                if (((NodeCanvasItem)e.CanvasItem).GetNodeData.Name.Equals("talk_p_proc", StringComparison.OrdinalIgnoreCase) == false) {
591
                    renameNodeToolStripMenuItem.Enabled = !NodeIsEditing(((NodeCanvasItem)e.CanvasItem));
592
                    renameNodeToolStripMenuItem.Tag = e.CanvasItem;
593
                } else
594
                    renameNodeToolStripMenuItem.Enabled = false;
595
                renameNodeToolStripMenuItem.Text = "Rename Node: " + e.CanvasItem.ToString();
596
            } else {
597
                editNodeToolStripMenuItem.Enabled = false;
598
                editNodeToolStripMenuItem.Tag = null;
599
                editNodeToolStripMenuItem.Text = "Edit Node";
600

601
                renameNodeToolStripMenuItem.Enabled = false;
602
                renameNodeToolStripMenuItem.Tag = null;
603
                renameNodeToolStripMenuItem.Text = "Rename Node";
604
            }
605
        }
606

607
        private void CanvasItemSelected(object sender, CanvasItemEventArgs e)
608
        {
609
            if (e.CanvasItem is NodeCanvasItem) {
610
                NodeCanvasItem NodeItem = (NodeCanvasItem)e.CanvasItem;
611
                contextMenuStrip.Tag = e.CanvasItem;
612

613
                hideNodeToolStripMenuItem.Enabled = true;
614
                deleteNoteToolStripMenuItem.Enabled = !NodeIsEditing(NodeItem); //!NodeItem.IsEditing;
615

616
                JumpNodeToolStripMenuItem.Enabled = true;
617
                JumpNodeToolStripMenuItem.Text = "Jump from: " + NodeItem.ToString() + " to";
618

619
                if (JumpNodeToolStripMenuItem.Tag != e.CanvasItem) {
620
                    JumpNodeToolStripMenuItem.DropDownItems.Clear();
621
                    if (NodeItem.GetNodeData.LinkedToNodes.Count > 0) {
622
                        JumpNodeToolStripMenuItem.DropDownItems.Add("-- Link To --");
623
                        JumpNodeToolStripMenuItem.DropDownItems[0].Enabled = false;
624
                    }
625
                }
626
                else if (JumpNodeToolStripMenuItem.Tag != null)
627
                         return;
628

629
                JumpNodeToolStripMenuItem.Tag = e.CanvasItem;
630

631
                foreach (var linkTo in NodeItem.GetNodeData.LinkedToNodes)
632
                {
633
                    JumpNodeToolStripMenuItem.DropDownItems.Add(linkTo.NameTo, null, new EventHandler(JumpClick));
634
                    int count = JumpNodeToolStripMenuItem.DropDownItems.Count - 1;
635

636
                    JumpNodeToolStripMenuItem.DropDownItems[count].ForeColor = (HideNodes.ContainsKey(linkTo.NameTo))
637
                                                                             ? Color.Gray : Color.OrangeRed;
638
                }
639

640
                string linkLine = String.Join(":", NodeItem.GetNodeData.LinkedFromNodes);
641
                string[] linkFrom = linkLine.Split(new char[] {':'}, StringSplitOptions.RemoveEmptyEntries);
642
                if (linkFrom.Length > 0) {
643
                    JumpNodeToolStripMenuItem.DropDownItems.Add("-- Link From --");
644
                    JumpNodeToolStripMenuItem.DropDownItems[
645
                        JumpNodeToolStripMenuItem.DropDownItems.Count - 1].Enabled = false;
646

647
                    foreach (var link in linkFrom)
648
                    {
649
                        JumpNodeToolStripMenuItem.DropDownItems.Add(link.Trim(), null, new EventHandler(JumpClick));
650
                        int count = JumpNodeToolStripMenuItem.DropDownItems.Count - 1;
651
                        JumpNodeToolStripMenuItem.DropDownItems[count].ForeColor = (HideNodes.ContainsKey(link.Trim()))
652
                                                                                    ? Color.Gray : Color.Blue;
653
                    }
654
                }
655
            } else {
656
                CanvasItemUnSelected(null, e);
657
                if (e.CanvasItem is NoteCanvasItem)
658
                    deleteNoteToolStripMenuItem.Enabled = true;
659
            }
660
        }
661

662
        private void CanvasItemUnSelected(object sender, EventArgs e)
663
        {
664
            JumpNodeToolStripMenuItem.Enabled = false;
665
            JumpNodeToolStripMenuItem.Text = "Jump from: --- to";
666
            JumpNodeToolStripMenuItem.DropDownItems.Clear();
667
            JumpNodeToolStripMenuItem.DropDownItems.Add("-- Link To --");
668
            JumpNodeToolStripMenuItem.DropDownItems[0].Enabled = false;
669
            JumpNodeToolStripMenuItem.Tag = contextMenuStrip.Tag = null;
670

671
            hideNodeToolStripMenuItem.Enabled = false;
672
            deleteNoteToolStripMenuItem.Enabled = false;
673
        }
674

675
        private void JumpClick(object sender, EventArgs e)
676
        {
677
            string name = ((ToolStripItem)sender).Text;
678

679
            if (HideNodes.ContainsKey(name))
680
                UnHideNode(name);
681

682
            NodeCanvasItem NodeItem = (NodeCanvasItem)nodesCanvas.GetNodeCanvasItem(name);
683
            if (NodeItem == null)
684
                return;
685

686
            JumpToNode(NodeItem);
687
            nodesCanvas.SetFocusedCanvasItem(NodeItem);
688
        }
689

690
        private void JumpToNode(NodeCanvasItem NodeItem)
691
        {
692
            float zoom = nodesCanvas.Zoom;
693
            Point position = new Point((int)(NodeItem.X * zoom), (int)(NodeItem.Y * zoom));
694

695
            // центрируем положение
696
            int w = ((int)(NodeItem.Width * zoom)) / 2;
697
            int h = ((int)(NodeItem.Height * zoom)) / 2;
698
            Size cs = nodesCanvas.ClientSize;
699
            position.Offset(-(cs.Width / 2) + w, -(cs.Height / 2) + h);
700

701
            nodesCanvas.SetCanvasScrollPosition = position;
702
        }
703

704
        private void ClickContentText(object sender, TextSegment ts)
705
        {
706
            if (ts.IndexContent == -1) return;
707

708
            if (shiftDown) {
709
                ContentBody cbData = ((NodeCanvasItem)sender).GetNodeData.NodeContent[ts.IndexContent];
710
                if (cbData.msgNum == -1)
711
                    return;
712
                EditContenText(cbData.msgNum, cbData.msgFileNum, ts);
713
            } else
714
                ShowContentText(ts);
715
        }
716

717
        private void EditContenText(int msgNum, int msgFileNum, TextSegment ts)
718
        {
719
            string msgfile = null;
720
            string message = null;
721
            shiftDown = false;
722

723
            if (msgFileNum != -1) {
724
                if (!MessageFile.GetPath(sourceTab, msgFileNum, out msgfile)) {
725
                    MessageBox.Show("The requested message file: " + msgfile + "\ncould not be found.", "Missing messages file");
726
                    return;
727
                }
728
            } else
729
                msgfile = sourceTab.msgFilePath;
730

731
            ReadMessageData(msgfile);
732

733
            if (msgFileNum != -1)
734
                message = MessageFile.GetMessages(MessagesData, msgNum);
735
            else if (sourceTab.messages.ContainsKey(msgNum))
736
                message = sourceTab.messages[msgNum];
737

738
            if (message == null) {
739
                MessageBox.Show("The requested message line number in: " + msgfile + "\nfile, could not be found.", "Message missing");
740
                return;
741
            }
742

743
            if (InputBox.ShowDialog("Message file: " + msgfile, ref message) == DialogResult.OK) {
744
                if (MessageFile.SaveToMessageFile(ref MessagesData, msgfile, message, msgNum)) {
745
                    if (msgFileNum == -1)
746
                        sourceTab.messages[msgNum] = message;
747
                    ts.Text = "\"" + message + "\"";
748
                }
749
            }
750
        }
751

752
        private void ShowContentText(TextSegment ts)
753
        {
754
            int x = (int)(ts.AbsoluteX * nodesCanvas.Zoom) - nodesCanvas.HorizontalScroll.Value;
755
            int y = (int)(ts.AbsoluteY * nodesCanvas.Zoom) - nodesCanvas.VerticalScroll.Value;
756

757
            int lines = ts.GetTextLines();
758
            switch (lines) {
759
                case 3:
760
                    y += 2;
761
                    break;
762
                case 2:
763
                    y += (int)(ts.TextHeight * nodesCanvas.Zoom) - 5;
764
                    break;
765
                case 1:
766
                    y += (int)(ts.TextHeight * nodesCanvas.Zoom);
767
                    break;
768
                default:
769
                    y -= 2;
770
                    break;
771
            }
772

773
            string message = ts.Text;
774
            int len = message.Length;
775
            if ((lines > 0 && ts.TextWidth > ts.ActualWidth) ||
776
                (lines == 0 && len > 100 && (ts.TextWidth > ts.ActualWidth))) {
777
                int loop = 1;         // количество частей: 1 - строка поделена на две части
778
                int divPos = len / 2; // делим строку пополам
779

780
                if (divPos > 75) {
781
                    loop++;
782
                    divPos = len / 3;
783
                    if (divPos > 75) {
784
                        loop++;
785
                        divPos = len / 4;
786
                    }
787
                }
788

789
                int incPos = divPos;
790
                int i, j;
791

792
                for (int l = loop; l > 0; l--)
793
                {
794
                    int insertPos = i = j = divPos;
795
                    while (j > 0 && i < len)
796
                    {
797
                        if (Char.IsWhiteSpace(message[--j])) { // назад
798
                            insertPos = j;
799
                            divPos -= (divPos - j);
800
                            break;
801
                        }
802
                        else if (Char.IsWhiteSpace(message[i])) { // вперед
803
                            insertPos = i;
804
                            divPos += (i - divPos);
805
                            break;
806
                        }
807
                        i++;
808
                    }
809
                    message = message.Insert(insertPos, Environment.NewLine);
810
                    divPos += incPos; // следующая позиция вставки
811
                }
812
            }
813
            // popup show
814
            msgPopup.RemoveAll();
815
            msgPopup.Tag = message;
816
            msgPopup.Show(message, nodesCanvas, x, y, 1000 + (len * 50));
817
        }
818

819
        private void CreatetoolStripButton_Click(object sender, EventArgs e)
820
        {
821
            if (nodesCanvas.NodesTotalCount > 0)
822
                if (MessageBox.Show("Do you want to clean up the existing flowchart and create a new one?", "Create New",
823
                    MessageBoxButtons.YesNo) == DialogResult.No)
824
                    return;
825

826
            nodesCanvas.ClearCanvas();
827
            HideNodes.Clear();
828
            CreateCanvasNodes();
829

830
            if (autoArrangeToolStripMenuItem.Checked)
831
                nodesCanvas.AutoArrange();
832
            else
833
                nodesCanvas.Refresh();
834

835
            HelpTip.Show(@"NOTE: Save the flowchart file to the folder (or subfolder \fcd) of the source script, so that the editor next time automatically opens the flowchart file.", nodesCanvas, 10, 10, 10000);
836

837
            nodesCanvas.Select();
838
        }
839

840
        private void renameNodeToolStripMenuItem_Click(object sender, EventArgs e)
841
        {
842
            string nName = ((NodeCanvasItem)(renameNodeToolStripMenuItem.Tag)).GetNodeData.Name;
843
            nName = Refactor.RenameProcedure(nName, scriptText, sourceTab);
844
            if (nName != null) {
845
                if (nName.IndexOf("node", StringComparison.OrdinalIgnoreCase) == -1) {
846
                    MessageBox.Show("The name of the procedure must contain the word 'Node'");
847
                    scriptText.UndoStack.Undo();
848
                    scriptText.UndoStack.ClearRedoStack();
849
                    return;
850
                }
851
                ((NodeCanvasItem)(renameNodeToolStripMenuItem.Tag)).GetNodeData.Name = nName;
852
                UpdateAllNodes();
853
            }
854
        }
855

856
        private void deleteNoteToolStripMenuItem_Click(object sender, EventArgs e)
857
        {
858
            if (nodesCanvas.ActiveControl is TextBox) {
859
                // удаление текста в TextBox
860
                TextBox editBox = nodesCanvas.ActiveControl as TextBox;
861
                if (editBox.Text.Length > 0) {
862
                    int posCaret = editBox.SelectionStart;
863
                    if (posCaret >= editBox.Text.Length) return;
864

865
                    editBox.Text = editBox.Text.Remove(posCaret, 1);
866
                    editBox.SelectionStart = posCaret;
867
                }
868
                return;
869
            }
870
            if (MessageBox.Show("Are you sure you want to delete the all selected nodes/notes?\n(When delete a node, the corresponding procedure in the script will be deleted).", "Deleting",
871
                MessageBoxButtons.YesNo) == DialogResult.No)
872
                return;
873

874
            List<string> removeProcName = new List<string>();
875

876
            do {
877
                CanvasItem item = nodesCanvas.GetLastFocusItem();
878
                if (item == null)
879
                    break;
880

881
                if (item is NoteCanvasItem) {
882
                    nodesCanvas.RemoveCanvasItem(item);
883
                    continue;
884
                }
885

886
                string name = ((NodeCanvasItem)item).GetNodeData.Name;
887
                if (name.Equals("talk_p_proc", StringComparison.OrdinalIgnoreCase)) {
888
                    MessageBox.Show("You cannot delete the procedural handler 'talk_p_proc' from the flowchart editor.");
889
                    break; //don't delete talk_p_proc
890
                }
891

892
                if (NodeIsEditing((NodeCanvasItem)item)) {
893
                    MessageBox.Show("You cannot delete a node procedure: " + name + " that is edited at the current time.");
894
                    break;
895
                }
896

897
                nodesCanvas.RemoveCanvasItem(item);
898
                NodesData.Remove(name);
899
                nodesProcedureName.Remove(name);
900
                removeProcName.Add(name);
901

902
            } while (true);
903

904
            if (removeProcName.Count > 0) {
905
                Utilities.DeleteProcedure(removeProcName, scriptText);
906

907
                if (ChangeNodes != null)
908
                    ChangeNodes(this, EventArgs.Empty); //event
909
            }
910

911
            nodesCanvas.ClearDragItems();
912

913
            CanvasItemUnSelected(null, EventArgs.Empty);
914
            UpdateAllNodes();
915

916
            nodesCanvas.Refresh();
917
        }
918

919
        private void addNodeToolStripMenuItem_Click(object sender, EventArgs e)
920
        {
921
            TemplateNode tNode = new TemplateNode();
922
            tNode.CreateClick += new TemplateNode.CreateClickHandler(CreateClick);
923
            tNode.ShowForm();
924
        }
925

926
        private bool CreateClick(object sender, string nodeName, string nodeCode)
927
        {
928
            string defName = "Node";
929
            if (nodeName.IndexOf(defName, StringComparison.OrdinalIgnoreCase) < 0)
930
                nodeName = defName + nodeName;
931

932
            if (sourceTab.parseInfo.CheckExistsName(nodeName, NameType.Proc)) {
933
                MessageBox.Show("The procedure/variable or declared macro with this name already exists.", "Unable to rename");
934
                return false;
935
            }
936

937
            CreateNewNode(nodeName, nodeCode);
938

939
            shouldUpdate = false; // не обновлять другие ноды на холсте
940

941
            //Создать процедуру в скрипте
942
            int dummy = 0;
943
            ParserInternal.UpdateParseBuffer(scriptText.TextContent);
944
            int declrLine = ParserInternal.GetEndLineProcDeclaration();
945
            int procLine = scriptText.TotalNumberOfLines - 1;
946
            string procblock = "\r\nprocedure " + nodeName + " begin\r\n" + nodeCode + "\r\nend\r\n";
947
            Utilities.InsertProcedure(sourceTab.textEditor.ActiveTextAreaControl,
948
                                      nodeName, procblock, declrLine, procLine, ref dummy);
949

950
            nodesCanvas.Refresh();
951

952
            if (ChangeNodes != null)
953
                ChangeNodes(this, EventArgs.Empty); //event
954

955
            return true; //close dialog
956
        }
957

958
        private void addNoteToolStripMenuItem_Click(object sender, EventArgs e)
959
        {
960
            NoteCanvasItem note = new NoteCanvasItem();
961
            note.X = (40 + nodesCanvas.HorizontalScroll.Value) / nodesCanvas.Zoom;
962
            note.Y = (40 + nodesCanvas.VerticalScroll.Value) / nodesCanvas.Zoom;
963
            note.Width = 200;
964
            note.Height = 50;
965
            nodesCanvas.AddCanvasItem(note);
966

967
            nodesCanvas.Refresh();
968
        }
969

970
        private void CanvasZoomChanged(object sender, EventArgs e)
971
        {
972
            int zoom = (int)Math.Round(nodesCanvas.Zoom * 100f);
973
            if (e == null) {
974
                Zoom.Value = zoom; // не изменять маштаб
975
                return;
976
            }
977
            PercentLabel.Text = zoom + "%";
978
            if (Zoom.Value != zoom)
979
                Zoom.Value = zoom;
980
        }
981

982
        private void Zoom_ValueChanged(object sender, EventArgs e)
983
        {
984
            nodesCanvas.Zoom = Zoom.Value / 100.0f;
985
        }
986

987
        private void CanvasMouseWheel(object sender, MouseEventArgs e)
988
        {
989
            int value = 2; //inc/dec zoom value
990

991
            int zm = Zoom.Value;
992

993
            if (e.Delta > 0)
994
                zm += value;
995
            else
996
                zm -= value;
997

998
            if (zm < 5)
999
                zm = 5;
1000
            else if (zm > 200)
1001
                zm = 200;
1002

1003
            Zoom.Value = zm;
1004

1005
            #if DEBUG
1006
                //ZoomLabel.Text = string.Format("X:{0}% : Y:{1}%", nodesCanvas.Percent.X, nodesCanvas.Percent.Y);
1007
            #endif
1008
        }
1009

1010
        private void editNodeToolStripMenuItem_Click(object sender, EventArgs e)
1011
        {
1012
            NodeCanvasItem node = (CanvasItem)editNodeToolStripMenuItem.Tag as NodeCanvasItem;
1013
            if (node == null)
1014
                return;
1015

1016
            foreach (var fcTE in sourceTab.nodeFlowchartTE)
1017
            {
1018
                if (fcTE.NodeName.Equals(node.GetNodeData.Name, StringComparison.OrdinalIgnoreCase)) {
1019
                    fcTE.Activate();
1020
                    return;
1021
                }
1022
            }
1023

1024
            ((NodeCanvasItem)editNodeToolStripMenuItem.Tag).StartEditingNode(); //set node edit status
1025

1026
            int index = sourceTab.parseInfo.GetProcedureIndex(node.GetNodeData.Name, scriptProc);
1027
            if (index == -1)
1028
                return;
1029
            FlowchartTE nodeEditor = new FlowchartTE(scriptProc[index], sourceTab, nodesProcedureName, true);
1030
            sourceTab.nodeFlowchartTE.Add(nodeEditor);
1031

1032
            nodeEditor.ApplyCode += nodeEditor_ApplyCode;
1033
            nodeEditor.Disposed += new EventHandler(nodeEditor_Disposed);
1034
            nodeEditor.ShowEditor(this, nodeEditLink: (NodeCanvasItem)editNodeToolStripMenuItem.Tag);
1035

1036
            renameNodeToolStripMenuItem.Enabled = deleteNoteToolStripMenuItem.Enabled = false;
1037
        }
1038

1039
        void nodeEditor_Disposed(object sender, EventArgs e)
1040
        {
1041
            if (fсClosed)
1042
                return;
1043

1044
            foreach (var fcTE in sourceTab.nodeFlowchartTE)
1045
            {
1046
                if (fcTE.NodeName.Equals(((FlowchartTE)sender).NodeName, StringComparison.OrdinalIgnoreCase)) {
1047
                    sourceTab.nodeFlowchartTE.Remove(fcTE);
1048
                    break;
1049
                }
1050
            }
1051
        }
1052

1053
        void nodeEditor_ApplyCode(object sender, FlowchartTE.CodeArgs e)
1054
        {
1055
            if (e.Change) {
1056
                if (Utilities.ReplaceProcedureCode(scriptText, sourceTab.parseInfo, e.Name, e.Code)) {
1057
                    MessageBox.Show("In the source script, there is no dialog node with this name.", "Apply error");
1058
                    return;
1059
                }
1060

1061
                if (ChangeNodes != null)
1062
                    ChangeNodes(this, EventArgs.Empty); //event
1063

1064
                if (!fсClosed)
1065
                    UpdateAllNodes();
1066
                //else
1067
                //    UpdateProceduresInfo();
1068

1069
                e.Change = false;
1070
            }
1071
            if (!fсClosed)
1072
                e.Close = true;
1073
        }
1074

1075
        private void CollapsetoolStripButton_Click(object sender, EventArgs e)
1076
        {
1077
            nodesCanvas.CollapseAll(shiftDown);
1078
        }
1079

1080
        private void ExpandtoolStripButton_Click(object sender, EventArgs e)
1081
        {
1082
            nodesCanvas.ExpandAll(shiftDown);
1083
        }
1084

1085
        private void ShrinkAlltoolStripButton_Click(object sender, EventArgs e)
1086
        {
1087
            nodesCanvas.ShrinkAllWidths();
1088
        }
1089

1090
        private void MatchAlltoolStripButton_Click(object sender, EventArgs e)
1091
        {
1092
            nodesCanvas.MatchAllWidths();
1093
        }
1094

1095
        private void HidePopUp()
1096
        {
1097
            msgPopup.Hide(nodesCanvas);
1098
            HelpTip.Hide(nodesCanvas);
1099
        }
1100

1101
        void ScrollChanged(object sender, EventArgs e)
1102
        {
1103
            HidePopUp();
1104
        }
1105

1106
        void LayoutChanged(object sender, EventArgs e)
1107
        {
1108
            HidePopUp();
1109
        }
1110

1111
        void NodeDiagram_KeyUp(object sender, KeyEventArgs e)
1112
        {
1113
            if (e.KeyCode == Keys.ShiftKey)
1114
                shiftDown = false;
1115
        }
1116

1117
        void NodeDiagram_KeyDown(object sender, KeyEventArgs e)
1118
        {
1119
            if (e.KeyCode == Keys.ShiftKey)
1120
                shiftDown = true;
1121
        }
1122

1123
        private void highQualityToolStripMenuItem_Click(object sender, EventArgs e)
1124
        {
1125
            nodesCanvas.HighQuality = highQualityToolStripMenuItem.Checked;
1126
            nodesCanvas.Refresh();
1127
        }
1128

1129
        private void ArrangetoolStripButton_Click(object sender, EventArgs e)
1130
        {
1131
           nodesCanvas.AutoArrange();
1132
        }
1133

1134
        private void UpdatetoolStripButton_Click(object sender, EventArgs e)
1135
        {
1136
            UpdateNodes();
1137
        }
1138

1139
        private void UpdateNodes()
1140
        {
1141
            NeedUpdate = false;
1142
            UpdateAllNodes();
1143
            nodesCanvas.Refresh();
1144
        }
1145

1146
        private void NodeDiagram_FormClosing(object sender, FormClosingEventArgs e)
1147
        {
1148
            fсClosed = true;
1149
            foreach (FlowchartTE fcTE in sourceTab.nodeFlowchartTE)
1150
            {
1151
                if (fcTE.OpenFromDiagram)
1152
                    fcTE.CloseEditor(true);
1153
            }
1154

1155
            if (autoSaveOnExitToolStripMenuItem.Checked && fcdFilePath != null)
1156
                WriteToXml().Save(fcdFilePath);
1157
        }
1158

1159
        private void NodeDiagram_Activated(object sender, EventArgs e)
1160
        {
1161
            if (autoUpdate && NeedUpdate) {
1162
                UpdateAllNodes();
1163
                NeedUpdate = false;
1164
            } else if (NeedUpdate) {
1165
                HelpTip.Show("You need to update the nodes. The script source code has been changed.", nodesCanvas, 10, 10, 5000);
1166
            }
1167
        }
1168

1169
        private void toolStripButton1_Click(object sender, EventArgs e)
1170
        {
1171
            nodesCanvas.WireOnlySelect = toolStripButton1.Checked;
1172
            nodesCanvas.Refresh();
1173
        }
1174

1175
        private void autoUpdateNodesToolStripMenuItem_Click(object sender, EventArgs e)
1176
        {
1177
            autoUpdate = Settings.autoUpdate = autoUpdateNodesToolStripMenuItem.Checked;
1178
        }
1179

1180
        private void ShowExitNodeToolStripMenuItem_Click(object sender, EventArgs e)
1181
        {
1182
            woExitNode = Settings.woExitNode = ShowExitNodeToolStripMenuItem.Checked;
1183
        }
1184

1185
        private void Zoom_MouseLeave(object sender, EventArgs e)
1186
        {
1187
            if (Zoom.Focused)
1188
                nodesCanvas.Focus();
1189
        }
1190

1191
        private void Zoom_MouseEnter(object sender, EventArgs e)
1192
        {
1193
            if (nodesCanvas.Focused && !Zoom.Focused)
1194
                Zoom.Focus();
1195
        }
1196

1197
        private void autoArrangeToolStripMenuItem_Click(object sender, EventArgs e)
1198
        {
1199
            Settings.autoArrange = autoArrangeToolStripMenuItem.Checked;
1200
        }
1201

1202
        private void autoSaveOnExitToolStripMenuItem_Click(object sender, EventArgs e)
1203
        {
1204
            Settings.autoSaveChart = autoSaveOnExitToolStripMenuItem.Checked;
1205
        }
1206

1207
        private void lowDetailsToolStripMenuItem_Click(object sender, EventArgs e)
1208
        {
1209
            ClassCanvas.NodeLowDetails = lowDetailsToolStripMenuItem.Checked;
1210
            UpdateNodes();
1211
        }
1212

1213
        private void tsbShowCommentCode_Click(object sender, EventArgs e)
1214
        {
1215
            if (tsbShowCommentCode.Checked)
1216
                tsbShowCommentCode.ForeColor = Color.Red;
1217
            else
1218
                tsbShowCommentCode.ForeColor = SystemColors.ControlText;
1219
            UpdateAllNodes();
1220
            nodesCanvas.Refresh();
1221
        }
1222

1223
        private void HelptoolStripButton_Click(object sender, EventArgs e)
1224
        {
1225
            HelpTip.Show(HelptoolStripButton.ToolTipText, nodesCanvas, nodesCanvas.Width - 300, 10, 10000);
1226
        }
1227

1228
        private void contextMenuStrip_Closed(object sender, ToolStripDropDownClosedEventArgs e)
1229
        {
1230
            if (!Program.KeyHook(Keys.ControlKey))
1231
                nodesCanvas.CtrlDown = false;
1232
        }
1233

1234
        private void autoHideNodesToolStripMenuItem_Click(object sender, EventArgs e)
1235
        {
1236
            Settings.autoHideNodes = autoHideNodesToolStripMenuItem.Checked;
1237
        }
1238

1239
        private void contextMenuStrip_Opening(object sender, System.ComponentModel.CancelEventArgs e)
1240
        {
1241
            if (unhideNodeToolStripMenuItem.HasDropDownItems)
1242
                return;
1243

1244
            foreach (var key in HideNodes.Keys)
1245
                unhideNodeToolStripMenuItem.DropDownItems.Add(key, null, new EventHandler(UnHideNode_Click));
1246
        }
1247

1248
        private void UnHideNode_Click(object sender, EventArgs e)
1249
        {
1250
            UnHideNode(((ToolStripItem)sender).Text);
1251
            unhideNodeToolStripMenuItem.DropDownItems.Clear();
1252
        }
1253

1254
        private void unhideAllToolStripMenuItem_Click(object sender, EventArgs e)
1255
        {
1256
            UnHideAll();
1257
            unhideNodeToolStripMenuItem.DropDownItems.Clear();
1258
        }
1259

1260
        private void hideToolStripMenuItem_Click(object sender, EventArgs e)
1261
        {
1262
            NodeCanvasItem item = (NodeCanvasItem)contextMenuStrip.Tag;
1263
            do {
1264
                HideNode(item);
1265
                item = (NodeCanvasItem)nodesCanvas.GetLastFocusItem();
1266
            } while (item != null);
1267

1268
            CanvasItemUnSelected(null, EventArgs.Empty);
1269
            nodesCanvas.Refresh();
1270
            unhideNodeToolStripMenuItem.DropDownItems.Clear();
1271
        }
1272

1273
        private void closeToolStripMenuItem_Click(object sender, EventArgs e)
1274
        {
1275
            this.Close();
1276
        }
1277

1278
        private void addEditRulesToolStripMenuItem_Click(object sender, EventArgs e)
1279
        {
1280
            new ScriptEditor.TextEditorUI.Function.FunctionsRules().ShowDialog(this);
1281
        }
1282

1283
        private void showAllCode_Click(object sender, EventArgs e)
1284
        {
1285
            tsbShowAllCode.Checked = !tsbShowAllCode.Checked;
1286
            UpdateNodes();
1287
        }
1288

1289
        #region Save/Load Diagram
1290
        private void openDiagramToolStripMenuItem_Click(object sender, EventArgs e)
1291
        {
1292
            string path = fcdFilePath ?? sourceTab.filepath;
1293
            openFileDialog.InitialDirectory = Path.GetDirectoryName(path);
1294

1295
            if (openFileDialog.ShowDialog() == DialogResult.OK) {
1296
                fcdFilePath = openFileDialog.FileName;
1297
                LoadFlowchartDiagram();
1298
            }
1299
        }
1300

1301
        private void saveDiagramToolStripMenuItem_Click(object sender, EventArgs e)
1302
        {
1303
            if (fcdFilePath == null) {
1304
                saveFileDialog.InitialDirectory = Path.GetDirectoryName(sourceTab.filepath);
1305
                saveFileDialog.FileName = Path.ChangeExtension(scriptName, saveFileDialog.DefaultExt);
1306
                if (saveFileDialog.ShowDialog() == DialogResult.OK)
1307
                    fcdFilePath = saveFileDialog.FileName;
1308
                else
1309
                    return;
1310
            }
1311
            WriteToXml().Save(fcdFilePath);
1312
        }
1313

1314
        private void saveImageToolStripMenuItem_Click(object sender, EventArgs e)
1315
        {
1316
            SaveFileDialog sfd = new SaveFileDialog();
1317
            sfd.DefaultExt = "png";
1318
            sfd.AddExtension = true;
1319
            sfd.Filter = "PNG Image (.png)|*.png";
1320
            if (sfd.ShowDialog() == DialogResult.OK)
1321
                nodesCanvas.SaveToImage(sfd.FileName);
1322
        }
1323

1324
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1059:MembersShouldNotExposeCertainConcreteTypes", MessageId = "System.Xml.XmlNode")]
1325
        private XmlDocument WriteToXml ()
1326
        {
1327
            XmlDocument doc = new XmlDocument();
1328
            doc.LoadXml("<NodesDiagram/>");
1329

1330
            XmlDeclaration decl = doc.CreateXmlDeclaration("1.0", "utf-8", "yes");
1331
            doc.InsertBefore(decl, doc.FirstChild);
1332

1333
            XmlAttribute script = doc.CreateAttribute("ScriptName");
1334
            script.Value = scriptName;
1335
            doc.DocumentElement.Attributes.Append(script);
1336

1337
            XmlAttribute zoom = doc.CreateAttribute("Zoom");
1338
            zoom.Value = nodesCanvas.Zoom.ToString(System.Globalization.CultureInfo.InvariantCulture);
1339
            doc.DocumentElement.Attributes.Append(zoom);
1340

1341
            XmlAttribute positionX = doc.CreateAttribute("PositionX");
1342
            positionX.Value = nodesCanvas.HorizontalScroll.Value.ToString(System.Globalization.CultureInfo.InvariantCulture);
1343
            doc.DocumentElement.Attributes.Append(positionX);
1344

1345
            XmlAttribute positionY = doc.CreateAttribute("PositionY");
1346
            positionY.Value = nodesCanvas.VerticalScroll.Value.ToString(System.Globalization.CultureInfo.InvariantCulture);
1347
            doc.DocumentElement.Attributes.Append(positionY);
1348

1349
            //Save hidden nodes
1350
            foreach (var item in HideNodes)
1351
                item.Value.WriteToXml(doc);
1352

1353
            return nodesCanvas.WriteToXml(doc);
1354
        }
1355

1356
        private void LoadFlowchartDiagram()
1357
        {
1358
            XmlDocument doc = new XmlDocument();
1359
            doc.Load(fcdFilePath);
1360
            LoadFromXml(doc);
1361

1362
            // Check and create new node
1363
            int shiftX = 0;
1364
            foreach (var item in NodesData)
1365
            {
1366
                int shiftY = 0;
1367
                if (!HideNodes.ContainsKey(item.Key) && !nodesCanvas.Contains(item.Key)) {
1368
                    MessageBox.Show("Added new node from the script: " + item.Key, "Loading...");
1369
                    AddNodeToCanvas(item, ref shiftY, ref shiftX);
1370
                }
1371
            }
1372

1373
            nodesCanvas.Visible = true;
1374
            nodesCanvas.Refresh();
1375
            MessageFile.ShowMissingFiles();
1376
            nodesCanvas.Select();
1377
        }
1378

1379
        private void LoadFromXml (IXPathNavigable doc)
1380
        {
1381
            XPathNavigator nav = doc.CreateNavigator();
1382

1383
            XPathNodeIterator ni = nav.Select(@"/NodesDiagram");
1384
            ni.MoveNext();
1385
            string nameScript = ni.Current.GetAttribute("ScriptName", "");
1386
            if (!scriptName.Equals(nameScript, StringComparison.OrdinalIgnoreCase)) {
1387
                MessageBox.Show("This flowchart file was saved for another script file.", "Wrong Flowchart: " + nameScript);
1388
                return;
1389
            }
1390

1391
            float zoom = float.Parse(ni.Current.GetAttribute("Zoom", ""), System.Globalization.CultureInfo.InvariantCulture);
1392
            int positionX = int.Parse(ni.Current.GetAttribute("PositionX", ""), System.Globalization.CultureInfo.InvariantCulture);
1393
            int positionY = int.Parse(ni.Current.GetAttribute("PositionY", ""), System.Globalization.CultureInfo.InvariantCulture);
1394

1395
            nodesCanvas.ClearCanvas();
1396
            HideNodes.Clear();
1397

1398
            ni = nav.Select(@"/NodesDiagram/Node");
1399
            while (ni.MoveNext())
1400
            {
1401
                string nodeName = ni.Current.GetAttribute("Name", "");
1402
                INode nd = GetNodeData(nodeName);
1403

1404
                NodeCanvasItem canvasitem = ClassCanvas.CreateItemFromType(nd);
1405
                if (canvasitem != null) {
1406
                    canvasitem.LoadFromXml(ni.Current);
1407
                    canvasitem.ContentClick += ClickContentText;
1408
                    canvasitem.ShowCodeButtonClick += nodeItem_ShowCodeButtonClick;
1409

1410
                    // установить сохраненное значение кнопки ShowCode для ноды
1411
                    if (NodeCanvasItem.showCode != -1) {
1412
                        nd.SetStateShowNodeCodeButton();
1413
                        nd.ShowCodeNodeButton = (NodeCanvasItem.showCode != 0);
1414
                    } else {
1415
                        nd.ShowCodeNodeButton = tsbShowAllCode.Checked;
1416
                    }
1417
                    canvasitem.ViewAllNodeCode = nd.ShowCodeNodeButton;
1418
                    if (!nd.ShowCodeNodeButton) {
1419
                        canvasitem.RemoveItemContex();
1420
                    }
1421

1422
                    if (!canvasitem.Hidden)
1423
                        nodesCanvas.AddCanvasItem(canvasitem);
1424
                    else
1425
                        HideNodes.Add(nodeName, canvasitem);
1426
                } else
1427
                    MessageBox.Show("Deleted existing dialog node: " + nodeName + ", that does not exist in the script code.", "Loading...");
1428
            }
1429

1430
            ni = nav.Select(@"/NodesDiagram/Note");
1431
            while (ni.MoveNext())
1432
            {
1433
                NoteCanvasItem note = new NoteCanvasItem();
1434
                note.LoadFromXml(ni.Current);
1435
                nodesCanvas.AddCanvasItem(note);
1436
            }
1437

1438
            nodesCanvas.Zoom = zoom;
1439
            nodesCanvas.SetCanvasScrollPosition = new Point(positionX, positionY);
1440
        }
1441
        #endregion
1442

1443
        #region Handles drawing for ToolTip
1444
        private void toolTip_Draw(object sender, DrawToolTipEventArgs e)
1445
        {
1446
            if (((ToolTip)sender).Tag != null) {
1447
                TipPainter.DrawSizeMessage(e);
1448
            } else {
1449
                TipPainter.DrawMessage(e);
1450
            }
1451
        }
1452

1453
        private void msgPopup_Popup(object sender, PopupEventArgs e) {
1454
            Size sz = TextRenderer.MeasureText((string)msgPopup.Tag, new Font("Arial", 12.0f, FontStyle.Regular, GraphicsUnit.Point));;
1455
            sz.Height += 6;
1456
            e.ToolTipSize = sz;
1457
        }
1458
        #endregion
1459
    }
1460
}
1461

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.