From 43a4b44a22b0cbe3886f4f348fe9a1570e776c4c Mon Sep 17 00:00:00 2001 From: Oleg Sh Date: Mon, 6 Nov 2023 19:16:50 +0200 Subject: [PATCH] Change script location. Split js code. Added cache and changed loading mechanism for js sources. --- core/func/main.php | 12 +- lang/en/home.php | 2 + lang/ru/home.php | 2 + script/EventHandlers.js | 2501 ----------------- script/entities/edge/api/index.js | 9 + script/{ => entities/edge/model}/BaseEdge.js | 0 script/{ => entities/edge/model}/EdgeModel.js | 2 +- script/entities/graph/api/index.js | 11 + script/{ => entities/graph/model}/Graph.js | 0 script/entities/vertex/api/index.js | 8 + .../{ => entities/vertex/model}/BaseVertex.js | 0 .../vertex/model}/VertexModel.js | 2 +- script/features/add_vertices_handler/index.js | 59 + script/features/algorithm_handler/index.js | 131 + script/features/algorithms/api/index.js | 35 + .../algorithms/model}/Algorithms.js | 610 ++-- .../algorithms/model}/BaseTraversal.js | 0 .../algorithms/model}/plugins/BFS.js | 0 .../algorithms/model}/plugins/Coloring.js | 0 .../model}/plugins/ConnectedComponent.js | 0 .../algorithms/model}/plugins/DFS.js | 0 .../algorithms/model}/plugins/EulerianLoop.js | 0 .../algorithms/model}/plugins/EulerianPath.js | 0 .../model}/plugins/FindAllPatches.js | 0 .../model}/plugins/FindLongestPath.js | 0 .../model}/plugins/FindShortPatchsFromOne.js | 0 .../algorithms/model}/plugins/Floid.js | 0 .../algorithms/model}/plugins/GraphReorder.js | 0 .../model}/plugins/HamiltonianLoop.js | 0 .../model}/plugins/HamiltonianPath.js | 0 .../model}/plugins/IsomorphismCheck.js | 0 .../algorithms/model}/plugins/MaxClique.js | 0 .../algorithms/model}/plugins/MaxFlow.js | 0 .../model}/plugins/MinimumSpanningTree.js | 0 .../model}/plugins/ModernGraphStyle.js | 0 .../model}/plugins/RadiusAndDiameter.js | 0 .../algorithms/model}/plugins/ShortestPath.js | 0 .../model}/plugins/VerticesDegree.js | 0 .../model}/plugins/disable/NeedAlgorithm.js | 0 script/features/base_handler/index.js | 457 +++ .../connect_vertices_handler/index.js | 226 ++ script/features/default_handler/index.js | 431 +++ .../features/delete_objects_handler/index.js | 52 + script/features/draw_graph/api/index.js | 10 + .../draw_graph/model}/BaseBackgroundDrawer.js | 0 .../draw_graph/model}/BaseEdgeDrawer.js | 0 .../draw_graph/model}/BaseVertexDrawer.js | 0 .../enum_vertices}/EnumVertices.js | 402 +-- .../graphoffline}/Graphoffline.Emscripten.js | 0 .../Graphoffline.Emscripten.wasm | Bin script/features/group_rename_handler/index.js | 61 + script/features/saved_graph_handler/index.js | 52 + .../saved_graph_image_handler/index.js | 94 + script/features/serialization/api/index.js | 8 + .../serialization/model}/GraphMLCreator.js | 0 .../features/setup_background_style/index.js | 167 ++ script/features/setup_edge_style/index.js | 295 ++ script/features/setup_vertex_style/index.js | 299 ++ .../features/show_adjacency_matrix/index.js | 66 + script/features/show_distance_matrix/index.js | 77 + .../features/show_incidence_matrix/index.js | 61 + script/merge.php | 46 +- script/pack.php | 104 + .../create_graph_by_edge_list/api/index.js | 9 + .../api/index.js.cache | 594 ++++ .../api/index.js | 11 + .../api/index.js.cache | 594 ++++ .../pages/create_graph_by_matrix/api/index.js | 13 + .../create_graph_by_matrix/api/index.js.cache | 670 +++++ .../model}/createByMatrixMain.js | 0 .../create_graph_by_matrix/model/main.js | 272 ++ script/pages/editor/api/index.js | 55 + script/pages/editor/api/index.js.cache | 2031 +++++++++++++ .../{ => pages/editor/model}/Application.js | 0 script/{ => pages/editor/model}/texts.js | 8 +- script/{ => pages/editor/ui}/main.js | 41 +- script/{ => shared}/canvas2svg.js | 0 script/shared/config.js | 2 + script/shared/loader.js | 199 ++ script/{ => shared}/point.js | 0 script/{ => shared}/utils.js | 8 +- tpl/create_graph_by_edge_list.php | 5 +- tpl/create_graph_by_incidence_matrix.php | 8 +- tpl/create_graph_by_matrix.php | 290 +- tpl/graphs_examples.php | 2 +- tpl/home.php | 17 +- 86 files changed, 7738 insertions(+), 3383 deletions(-) delete mode 100644 script/EventHandlers.js create mode 100644 script/entities/edge/api/index.js rename script/{ => entities/edge/model}/BaseEdge.js (100%) mode change 100755 => 100644 rename script/{ => entities/edge/model}/EdgeModel.js (99%) mode change 100755 => 100644 create mode 100644 script/entities/graph/api/index.js rename script/{ => entities/graph/model}/Graph.js (100%) create mode 100644 script/entities/vertex/api/index.js rename script/{ => entities/vertex/model}/BaseVertex.js (100%) mode change 100755 => 100644 rename script/{ => entities/vertex/model}/VertexModel.js (81%) mode change 100755 => 100644 create mode 100644 script/features/add_vertices_handler/index.js create mode 100644 script/features/algorithm_handler/index.js create mode 100644 script/features/algorithms/api/index.js rename script/{ => features/algorithms/model}/Algorithms.js (96%) rename script/{ => features/algorithms/model}/BaseTraversal.js (100%) mode change 100755 => 100644 rename script/{ => features/algorithms/model}/plugins/BFS.js (100%) mode change 100755 => 100644 rename script/{ => features/algorithms/model}/plugins/Coloring.js (100%) mode change 100755 => 100644 rename script/{ => features/algorithms/model}/plugins/ConnectedComponent.js (100%) mode change 100755 => 100644 rename script/{ => features/algorithms/model}/plugins/DFS.js (100%) mode change 100755 => 100644 rename script/{ => features/algorithms/model}/plugins/EulerianLoop.js (100%) mode change 100755 => 100644 rename script/{ => features/algorithms/model}/plugins/EulerianPath.js (100%) mode change 100755 => 100644 rename script/{ => features/algorithms/model}/plugins/FindAllPatches.js (100%) rename script/{ => features/algorithms/model}/plugins/FindLongestPath.js (100%) rename script/{ => features/algorithms/model}/plugins/FindShortPatchsFromOne.js (100%) rename script/{ => features/algorithms/model}/plugins/Floid.js (100%) mode change 100755 => 100644 rename script/{ => features/algorithms/model}/plugins/GraphReorder.js (100%) mode change 100755 => 100644 rename script/{ => features/algorithms/model}/plugins/HamiltonianLoop.js (100%) mode change 100755 => 100644 rename script/{ => features/algorithms/model}/plugins/HamiltonianPath.js (100%) mode change 100755 => 100644 rename script/{ => features/algorithms/model}/plugins/IsomorphismCheck.js (100%) rename script/{ => features/algorithms/model}/plugins/MaxClique.js (100%) rename script/{ => features/algorithms/model}/plugins/MaxFlow.js (100%) mode change 100755 => 100644 rename script/{ => features/algorithms/model}/plugins/MinimumSpanningTree.js (100%) mode change 100755 => 100644 rename script/{ => features/algorithms/model}/plugins/ModernGraphStyle.js (100%) mode change 100755 => 100644 rename script/{ => features/algorithms/model}/plugins/RadiusAndDiameter.js (100%) mode change 100755 => 100644 rename script/{ => features/algorithms/model}/plugins/ShortestPath.js (100%) mode change 100755 => 100644 rename script/{ => features/algorithms/model}/plugins/VerticesDegree.js (100%) mode change 100755 => 100644 rename script/{ => features/algorithms/model}/plugins/disable/NeedAlgorithm.js (100%) create mode 100644 script/features/base_handler/index.js create mode 100644 script/features/connect_vertices_handler/index.js create mode 100644 script/features/default_handler/index.js create mode 100644 script/features/delete_objects_handler/index.js create mode 100644 script/features/draw_graph/api/index.js rename script/{ => features/draw_graph/model}/BaseBackgroundDrawer.js (100%) rename script/{ => features/draw_graph/model}/BaseEdgeDrawer.js (100%) rename script/{ => features/draw_graph/model}/BaseVertexDrawer.js (100%) rename script/{ => features/enum_vertices}/EnumVertices.js (95%) mode change 100755 => 100644 rename script/{ => features/graphoffline}/Graphoffline.Emscripten.js (100%) rename script/{ => features/graphoffline}/Graphoffline.Emscripten.wasm (100%) create mode 100644 script/features/group_rename_handler/index.js create mode 100644 script/features/saved_graph_handler/index.js create mode 100644 script/features/saved_graph_image_handler/index.js create mode 100644 script/features/serialization/api/index.js rename script/{ => features/serialization/model}/GraphMLCreator.js (100%) create mode 100644 script/features/setup_background_style/index.js create mode 100644 script/features/setup_edge_style/index.js create mode 100644 script/features/setup_vertex_style/index.js create mode 100644 script/features/show_adjacency_matrix/index.js create mode 100644 script/features/show_distance_matrix/index.js create mode 100644 script/features/show_incidence_matrix/index.js create mode 100644 script/pack.php create mode 100644 script/pages/create_graph_by_edge_list/api/index.js create mode 100644 script/pages/create_graph_by_edge_list/api/index.js.cache create mode 100644 script/pages/create_graph_by_incidence_matrix/api/index.js create mode 100644 script/pages/create_graph_by_incidence_matrix/api/index.js.cache create mode 100644 script/pages/create_graph_by_matrix/api/index.js create mode 100644 script/pages/create_graph_by_matrix/api/index.js.cache rename script/{ => pages/create_graph_by_matrix/model}/createByMatrixMain.js (100%) mode change 100755 => 100644 create mode 100644 script/pages/create_graph_by_matrix/model/main.js create mode 100644 script/pages/editor/api/index.js create mode 100644 script/pages/editor/api/index.js.cache rename script/{ => pages/editor/model}/Application.js (100%) rename script/{ => pages/editor/model}/texts.js (99%) rename script/{ => pages/editor/ui}/main.js (94%) rename script/{ => shared}/canvas2svg.js (100%) create mode 100644 script/shared/config.js create mode 100644 script/shared/loader.js rename script/{ => shared}/point.js (100%) mode change 100755 => 100644 rename script/{ => shared}/utils.js (82%) diff --git a/core/func/main.php b/core/func/main.php index 6d70b58..91fcf54 100755 --- a/core/func/main.php +++ b/core/func/main.php @@ -173,11 +173,15 @@ return SITE_ROOT . "{$dir}{$uri}"; } - function RootCacheJS($uri = '', $version = '') { + function RootCacheJS($uri = '') { global $g_config; - - return Root(($g_config['use_js_cache'] ? $uri . ".cache" : - $uri) . "?v=" . $version); + + $cacheFilePath = Root($uri . ".cache"); + $filePath = Root($uri); + $cacheExists = file_exists("." . $cacheFilePath); + $finalFileName = $cacheExists && $g_config['use_js_cache'] ? $cacheFilePath : $filePath; + + return $finalFileName . "?v=" . $g_config['engine_version']; } /** diff --git a/lang/en/home.php b/lang/en/home.php index 849143a..d279c55 100755 --- a/lang/en/home.php +++ b/lang/en/home.php @@ -145,6 +145,8 @@ $g_lang["opensource_message"] = "Our project is now open source. More details..."; + $g_lang["we_are_improving"] = "We are improving Graphonline, if you faced with any problem please let us know: admin@graphonline.ru"; + $g_lang["settings"] = "Settings"; $g_lang["common_vertex_settings"] = "Common vertices"; $g_lang["selected_vertex_settings"] = "Selected vertices"; diff --git a/lang/ru/home.php b/lang/ru/home.php index 1f0a34d..4bc1450 100755 --- a/lang/ru/home.php +++ b/lang/ru/home.php @@ -148,6 +148,8 @@ $g_lang["opensource_message"] = "Наш проект стал проектом с открытым исходным кодом. Подробнее..."; + $g_lang["we_are_improving"] = "Мы улучшаем Graphonline, если вы столкнулись с проблемами напишете нам: admin@graphonline.ru"; + $g_lang["settings"] = "Настройки"; $g_lang["common_vertex_settings"] = "Обычных вершин"; $g_lang["selected_vertex_settings"] = "Выделенных вершин"; diff --git a/script/EventHandlers.js b/script/EventHandlers.js deleted file mode 100644 index bef5e7f..0000000 --- a/script/EventHandlers.js +++ /dev/null @@ -1,2501 +0,0 @@ -/** - * - * This event handlers. - * - * - */ - -/** - * Base Handler. - * - */ - -function BaseHandler(app) -{ - this.app = app; - this.app.setRenderPath([]); - - if (this.removeStack) { - this.removeContextMenu(); - } - this.contextMenuObject = null; - this.contextMenuPoint = null; - //this.app.ClearUndoStack(); -} - -// Need redraw or nor. -BaseHandler.prototype.needRedraw = false; -BaseHandler.prototype.objects = []; -BaseHandler.prototype.message = ""; - - -BaseHandler.prototype.IsNeedRedraw = function(object) -{ - return this.needRedraw; -} - -BaseHandler.prototype.RestRedraw = function(object) -{ - this.needRedraw = false; -} - -BaseHandler.prototype.SetObjects = function(objects) -{ - this.objects = objects; -} - -BaseHandler.prototype.GetSelectedGraph = function(pos) -{ - // Selected Graph. - var res = null; - for (var i = 0; i < this.app.graph.vertices.length; i ++) - { - if (this.app.graph.vertices[i].HitTest(pos)) - { - // Select last of them. - res = this.app.graph.vertices[i]; - } - } - - - return res; -} - -BaseHandler.prototype.GetSelectedArc = function(pos) -{ - // Selected Arc. - for (var i = 0; i < this.app.graph.edges.length; i ++) - { - var edge = this.app.graph.edges[i]; - - if (edge.HitTest(new Point(pos.x, pos.y))) - return edge; - } - - return null; -} - -BaseHandler.prototype.GetSelectedObject = function(pos) -{ - var graphObject = this.GetSelectedGraph(pos); - if (graphObject) - { - return graphObject; - } - - var arcObject = this.GetSelectedArc(pos); - if (arcObject) - { - return arcObject; - } - - return null; -} - - -BaseHandler.prototype.GetUpText = function(object) -{ - return ""; -} - - -BaseHandler.prototype.GetMessage = function() -{ - return this.message; -} - - -BaseHandler.prototype.MouseMove = function(pos) {} - -BaseHandler.prototype.MouseDown = function(pos) {} - -BaseHandler.prototype.MouseUp = function(pos) {} - -BaseHandler.prototype.GetSelectedGroup = function(object) -{ - return 0; -} - -BaseHandler.prototype.InitControls = function() -{ - var vertex1Text = document.getElementById("Vertex1"); - if (vertex1Text) - { - var handler = this; - vertex1Text.onchange = function () { - for (var i = 0; i < handler.app.graph.vertices.length; i++) - { - if (handler.app.graph.vertices[i].mainText == vertex1Text.value) - { - handler.SelectFirstVertexMenu(vertex1Text, handler.app.graph.vertices[i]); - userAction("selectVertex1_menu"); - break; - } - } - }; - - this.UpdateFirstVertexMenu(vertex1Text); - } - - var vertex2Text = document.getElementById("Vertex2"); - if (vertex2Text) - { - var handler = this; - vertex2Text.onchange = function () { - for (var i = 0; i < handler.app.graph.vertices.length; i++) - { - if (handler.app.graph.vertices[i].mainText == vertex2Text.value) - { - handler.SelectSecondVertexMenu(vertex2Text, handler.app.graph.vertices[i]); - userAction("selectVertex2_menu"); - break; - } - } - }; - - this.UpdateSecondVertexMenu(vertex2Text); - } -} - -BaseHandler.prototype.GetNodesPath = function(array, start, count) -{ - var res = []; - for (var index = start; index < start + count; index++) - { - res.push(this.app.graph.FindVertex(array[index].value)); - } - return res; -} - -BaseHandler.prototype.RestoreAll = function() -{ -} - -BaseHandler.prototype.GetSelectVertexMenu = function(menuName) -{ - var res = "" + - ""; - - for (var i = 0; i < this.app.graph.vertices.length; i++) - { - res = res + ""; -} - -BaseHandler.prototype.GetSelect2VertexMenu = function() -{ - return "" + - this.GetSelectVertexMenu("Vertex1") + " → " + this.GetSelectVertexMenu("Vertex2") + ""; -} - -BaseHandler.prototype.SelectFirstVertexMenu = function(vertex1Text, vertex) -{} - -BaseHandler.prototype.UpdateFirstVertexMenu = function() -{} - -BaseHandler.prototype.SelectSecondVertexMenu = function(vertex2Text, vertex) -{} - -BaseHandler.prototype.UpdateSecondVertexMenu = function() -{} - -BaseHandler.prototype.GetSelectedVertex = function() -{ - return null; -} - -BaseHandler.prototype.addContextMenu = function() -{ - var $contextMenu = $("#contextMenu"); - - var handler = this; - - $("#Context_Delete").click(function() { - if (handler.contextMenuObject != null) { - handler.app.PushToStack("DeleteObject"); - handler.app.DeleteObject(handler.contextMenuObject); - handler.app.redrawGraph(); - userAction("DeleteObject_contextMenu"); - } - }); - - $("#Context_Rename").click(function() { - if (handler.contextMenuObject != null) { - var callback = function (enumType) { - handler.RenameVertex(enumType.GetVertexText(0), handler.contextMenuObject); - userAction("RenameVertex_contextMenu"); - }; - var customEnum = new TextEnumVerticesCustom(handler.app); - customEnum.ShowDialog(callback, g_rename, g_renameVertex, handler.contextMenuObject.mainText); - } - }); - - $("#Context_Connect").click(function() { - if (handler.contextMenuObject != null && handler.GetSelectedVertex() != null) { - var addFunc = function(firstVertex, secondVertex, direct) { - handler.app.CreateNewArc(firstVertex, secondVertex, direct, - document.getElementById('EdgeWeight').value, - $("#RadiosReplaceEdge").prop("checked"), - document.getElementById('EdgeLable').value); - handler.app.redrawGraph(); - } - handler.ShowCreateEdgeDialog(handler.GetSelectedVertex(), handler.contextMenuObject, addFunc); - } - }); - - $("#Context_Delete_Edge").click(function() { - if (handler.contextMenuObject != null) { - handler.app.PushToStack("DeleteObject"); - handler.app.DeleteObject(handler.contextMenuObject); - handler.app.redrawGraph(); - userAction("DeleteObject_contextMenu"); - } - }); - - $("#Context_Edit_Edge").click(function() { - if (handler.contextMenuObject != null) { - handler.ShowEditEdgeDialog(handler.contextMenuObject); - } - }); - - $("#Context_Add_Vertex").click(function() { - handler.app.PushToStack("Add"); - handler.app.CreateNewGraph(handler.contextMenuPoint.x, handler.contextMenuPoint.y); - handler.app.redrawGraph(); - }); - - $("#Context_Back_Color").click(function() { - var setupBackgroundStyle = new SetupBackgroundStyle(handler.app); - setupBackgroundStyle.show(); - }); - - $("body").on("contextmenu", "canvas", function(e) { - handler.contextMenuPoint = handler.app.getMousePos(handler.app.canvas, e); - handler.contextMenuObject = handler.GetSelectedObject(handler.contextMenuPoint); - if (handler.contextMenuObject instanceof BaseVertex) { - $("#edgeContextMenu").hide(); - $("#backgroundContextMenu").hide(); - $("#vertexContextMenu").show(); - if (handler.GetSelectedVertex() == null) { - $("#Context_Connect").hide(); - } else { - $("#Context_Connect").show(); - } - } else if (handler.contextMenuObject instanceof BaseEdge) { - $("#vertexContextMenu").hide(); - $("#backgroundContextMenu").hide(); - $("#edgeContextMenu").show(); - } else { - $("#vertexContextMenu").hide(); - $("#edgeContextMenu").hide(); - $("#backgroundContextMenu").show(); - } - - $contextMenu.css({ - display: "block", - left: e.offsetX, - top: e.offsetY - }); - return false; - }); - - $("body").click(function() { - $contextMenu.hide(); - }); -} - -BaseHandler.prototype.removeContextMenu = function() -{ - $("body").off("contextmenu"); - $("#Context_Delete").off("click"); - $("#Context_Rename").off("click"); - $("#Context_Connect").off("click"); - $("#Context_Delete_Edge").off("click"); - $("#Context_Edit_Edge").off("click"); - $("#Context_Add_Vertex").off("click"); - $("#Context_Back_Color").off("click"); -} - -BaseHandler.prototype.RenameVertex = function(text, object) -{ - if (object != null && (object instanceof BaseVertex)) - { - this.app.PushToStack("RenameVertex"); - object.mainText = text; - this.app.redrawGraph(); - } -} - -BaseHandler.prototype.ShowCreateEdgeDialog = function(firstVertex, secondVertex, addEdgeCallBack) { - if (!this.app.graph.isMulti()) - { - var hasEdge = this.app.graph.FindEdgeAny(firstVertex.id, secondVertex.id); - var hasReverseEdge = this.app.graph.FindEdgeAny(secondVertex.id, firstVertex.id); - - if (hasEdge == null && hasReverseEdge == null) - { - $("#RadiosReplaceEdge").prop("checked", true); - $("#NewEdgeAction" ).hide(); - } - else { - $( "#NewEdgeAction" ).show(); - } - } - else - { - $("#RadiosAddEdge").prop("checked", true); - $("#NewEdgeAction" ).hide(); - } - - var dialogButtons = {}; - var handler = this; - - $("#CheckSaveDefaultEdge").prop("checked", false); - $("#defaultEdgeDialogBlock").show(); - - dialogButtons[g_orintEdge] = function() { - handler.app.PushToStack("Connect"); - addEdgeCallBack(firstVertex, secondVertex, true); - //handler.AddNewEdge(selectedObject, true); - $( this ).dialog( "close" ); - }; - dialogButtons[g_notOrintEdge] = function() { - handler.app.PushToStack("Connect"); - addEdgeCallBack(firstVertex, secondVertex, false); - //handler.AddNewEdge(selectedObject, false); - $( this ).dialog( "close" ); - }; - - var edgePresets = this.app.GetEdgePresets(); - var presetsStr = "" + g_DefaultWeightPreset + ""; - - for(var i = 0; i < edgePresets.length; i ++) - { - var edgePreset = edgePresets[i]; - presetsStr += "" + edgePreset + ""; - } - document.getElementById("EdgesPresets").innerHTML = presetsStr; - document.getElementById('EdgeLable').value = ""; - - $( "#addEdge" ).dialog({ - resizable: false, - height: "auto", - width: "auto", - modal: true, - title: g_addEdge, - buttons: dialogButtons, - dialogClass: 'EdgeDialog', - open: function () { - $(this).off('submit').on('submit', function () { - return false; - }); - - // Focues weight - setTimeout(function(){ - const weightInput = document.getElementById('EdgeWeight'); - if(weightInput) - { - weightInput.focus(); - weightInput.select(); - } - },0); - } - }); -} - -BaseHandler.prototype.ShowEditEdgeDialog = function(edgeObject) { - var dialogButtons = {}; - - var handler = this; - - dialogButtons[g_save] = function() { - handler.app.PushToStack("ChangeEdge"); - - edgeObject.SetWeight(document.getElementById('EdgeWeight').value); - edgeObject.SetUpText(document.getElementById('EdgeLable').value); - - handler.needRedraw = true; - handler.app.redrawGraph(); - - userAction("ChangeWeight"); - $( this ).dialog( "close" ); - }; - - document.getElementById('EdgeWeight').value = edgeObject.useWeight ? edgeObject.weight : g_noWeight; - document.getElementById('EdgeWeightSlider').value = edgeObject.useWeight ? edgeObject.weight : 0; - - var edgePresets = handler.app.GetEdgePresets(); - var presetsStr = "" + g_DefaultWeightPreset + ""; - - for(var i = 0; i < edgePresets.length; i ++) - { - var edgePreset = edgePresets[i]; - presetsStr += "" + edgePreset + ""; - } - document.getElementById("EdgesPresets").innerHTML = presetsStr; - document.getElementById('EdgeLable').value = edgeObject.upText; - - $("#CheckSaveDefaultEdge").prop("checked", false); - - $("#defaultEdgeDialogBlock").hide(); - - $( "#addEdge" ).dialog({ - resizable: false, - height: "auto", - width: "auto", - modal: true, - title: g_editWeight, - buttons: dialogButtons, - dialogClass: 'EdgeDialog', - open: function () { - $(handler).off('submit').on('submit', function () { - return false; - }); - } - }); -} - -/** - * Default handler. - * Select using mouse, drag. - * - */ -function DefaultHandler(app) -{ - this.removeStack = true; - BaseHandler.apply(this, arguments); - this.message = g_textsSelectAndMove + " " + g_selectGroupText + "" + " " + g_useContextMenuText + ""; - this.selectedObjects = []; - this.dragObject = null; - this.selectedObject = null; - this.prevPosition = null; - this.groupingSelect = false; - this.selectedLogRect = false; - this.selectedLogCtrl = false; - this.saveUndo = false; - - this.addContextMenu(); -} - -// inheritance. -DefaultHandler.prototype = Object.create(BaseHandler.prototype); -// Is pressed -DefaultHandler.prototype.pressed = false; -// Curve change value. -DefaultHandler.prototype.curveValue = 0.1; - -DefaultHandler.prototype.GetSelectedVertex = function() -{ - return (this.selectedObject instanceof BaseVertex) ? this.selectedObject : null; -} - -DefaultHandler.prototype.MouseMove = function(pos) -{ - if (this.dragObject) - { - if (!this.saveUndo) - { - this.app.PushToStack("Move"); - this.saveUndo = true; - } - - this.dragObject.position.x = pos.x; - this.dragObject.position.y = pos.y; - this.needRedraw = true; - } - else if (this.selectedObjects.length > 0 && this.pressed && !this.groupingSelect) - { - if (!this.saveUndo) - { - this.app.PushToStack("Move"); - this.saveUndo = true; - } - - var offset = (new Point(pos.x, pos.y)).subtract(this.prevPosition); - for (var i = 0; i < this.selectedObjects.length; i ++) - { - var object = this.selectedObjects[i]; - if (object instanceof BaseVertex) - { - object.position = object.position.add(offset); - } - } - this.prevPosition = pos; - this.needRedraw = true; - } - else if (this.pressed) - { - if (this.groupingSelect) - { - // Rect select. - var newPos = new Point(pos.x, pos.y); - this.app.SetSelectionRect(new Rect(newPos.min(this.prevPosition), newPos.max(this.prevPosition))); - this.SelectObjectInRect(this.app.GetSelectionRect()); - this.needRedraw = true; - if (!this.selectedLogRect) - { - userAction("GroupSelected.SelectRect"); - this.selectedLogRect = true; - } - } - else - { - // Move work space - this.app.onCanvasMove((new Point(pos.x, pos.y)).subtract(this.prevPosition).multiply(this.app.canvasScale)); - this.needRedraw = true; - } - } -} - -DefaultHandler.prototype.MouseDown = function(pos) -{ - this.dragObject = null; - var selectedObject = this.GetSelectedObject(pos); - var severalSelect = g_ctrlPressed; - - if (selectedObject == null || (!severalSelect && !this.selectedObjects.includes(selectedObject))) - { - this.selectedObject = null; - this.selectedObjects = []; - this.groupingSelect = g_ctrlPressed; - } - - if ((severalSelect || this.selectedObjects.includes(selectedObject)) && (this.selectedObjects.length > 0 || this.selectedObject != null) && selectedObject != null) - { - if (this.selectedObjects.length == 0) - { - this.selectedObjects.push(this.selectedObject); - this.selectedObject = null; - this.selectedObjects.push(selectedObject); - } - else if (!this.selectedObjects.includes(selectedObject)) - { - this.selectedObjects.push(selectedObject); - } - else if (severalSelect && this.selectedObjects.includes(selectedObject)) - { - var index = this.selectedObjects.indexOf(selectedObject); - this.selectedObjects.splice(index, 1); - } - if (!this.selectedLogCtrl) - { - userAction("GroupSelected.SelectCtrl"); - this.selectedLogCtrl = true; - } - } - else - { - if (selectedObject != null) - { - this.selectedObject = selectedObject; - } - if ((selectedObject instanceof BaseVertex) && selectedObject != null) - { - this.dragObject = selectedObject; - this.message = g_moveCursorForMoving; - } - } - this.needRedraw = true; - this.pressed = true; - this.prevPosition = pos; - this.app.canvas.style.cursor = "move"; -} - -DefaultHandler.prototype.MouseUp = function(pos) -{ - this.saveUndo = false; - this.message = g_textsSelectAndMove + " " + g_selectGroupText + "" + " " + g_useContextMenuText + ""; - this.dragObject = null; - this.pressed = false; - this.app.canvas.style.cursor = "auto"; - - this.app.SetSelectionRect(null); - - this.groupingSelect = false; - if (this.selectedObject != null && (this.selectedObject instanceof BaseVertex)) - { - this.message = g_textsSelectAndMove - + "
" - + "" - + "" - + "
"; - - var handler = this; - var callback = function (enumType) { - handler.RenameVertex(enumType.GetVertexText(0), handler.selectedObject); - userAction("RenameVertex"); - }; - $('#message').unbind(); - $('#message').on('click', '#renameButton', function(){ - var customEnum = new TextEnumVerticesCustom(handler.app); - customEnum.ShowDialog(callback, g_rename, g_renameVertex, handler.selectedObject.mainText); - }); - $('#message').on('click', '#changeCommonStyle', function(){ - var selectedVertices = handler.app.GetSelectedVertices(); - var setupVertexStyle = new SetupVertexStyle(handler.app); - setupVertexStyle.show(0, selectedVertices); - }); - $('#message').on('click', '#changeSelectedStyle', function(){ - var selectedVertices = handler.app.GetSelectedVertices(); - var setupVertexStyle = new SetupVertexStyle(handler.app); - setupVertexStyle.show(1, selectedVertices); - }); - } - else if (this.selectedObject != null && (this.selectedObject instanceof BaseEdge)) - { - this.message = g_textsSelectAndMove - + "" - + " " + g_curveEdge + " " - + "   " - + "
" - + "" - + "" - + "
"; - - var handler = this; - $('#message').unbind(); - $('#message').on('click', '#editEdge', function(){ - handler.ShowEditEdgeDialog(handler.selectedObject); - }); - - $('#message').on('click', '#incCurvel', function(){ - handler.app.PushToStack("ChangeCurvelEdge"); - - handler.selectedObject.model.ChangeCurveValue(DefaultHandler.prototype.curveValue); - handler.needRedraw = true; - handler.app.redrawGraph(); - userAction("Edge.Bend"); - }); - $('#message').on('click', '#decCurvel', function(){ - handler.app.PushToStack("ChangeCurvelEdge"); - - handler.selectedObject.model.ChangeCurveValue(-DefaultHandler.prototype.curveValue); - handler.needRedraw = true; - handler.app.redrawGraph(); - userAction("Edge.Bend"); - }); - $('#message').on('click', '#changeCommonStyle', function(){ - var selectedEdges = handler.app.GetSelectedEdges(); - var setupVertexStyle = new SetupEdgeStyle(handler.app); - setupVertexStyle.show(0, selectedEdges); - }); - $('#message').on('click', '#changeSelectedStyle', function(){ - var selectedEdges = handler.app.GetSelectedEdges(); - var setupVertexStyle = new SetupEdgeStyle(handler.app); - setupVertexStyle.show(1, selectedEdges); - }); - } - else if (this.selectedObjects.length > 0) - { - this.message = g_dragGroupText + " " + g_selectGroupText + ""; - - var hasVertices = false; - var hasEdges = false; - for(var i = 0; i < this.selectedObjects.length; i ++) - { - var object = this.selectedObjects[i]; - if (object instanceof BaseVertex) - { - hasVertices = true; - } - else if (object instanceof BaseEdge) - { - hasEdges = true; - } - } - - this.message = this.message + ""; - - this.message = this.message - + "    " - + "" - - this.message = this.message - + "     " - + "" - + ""; - - var handler = this; - $('#message').unbind(); - - $('#message').on('click', '#DublicateSelected', function(){ - handler.app.PushToStack("DublicateSelection"); - - userAction("GroupSelected.Dublicate"); - - var newSelected = []; - var copyVertex = {}; - - // Copy vertex - for(var i = 0; i < handler.selectedObjects.length; i ++) - { - var object = handler.selectedObjects[i]; - if (object instanceof BaseVertex) - { - var newObject = new BaseVertex() - newObject.copyFrom(object); - newObject.vertexEnumType = null; - handler.app.AddNewVertex(newObject); - var vertex = newObject; - var diameter = (new VertexModel()).diameter; - vertex.position.offset(diameter, diameter); - newSelected.push(vertex); - copyVertex[object.id] = vertex; - } - } - - // Copy edge - for (var i = 0; i < handler.selectedObjects.length; i ++) - { - var object = handler.selectedObjects[i]; - if (object instanceof BaseEdge) - { - var newObject = new BaseEdge() - newObject.copyFrom(object); - - var toNewVertex = false; - if (newObject.vertex1.id in copyVertex) - { - newObject.vertex1 = copyVertex[newObject.vertex1.id]; - toNewVertex = true; - } - if (newObject.vertex2.id in copyVertex) - { - newObject.vertex2 = copyVertex[newObject.vertex2.id]; - toNewVertex = true; - } - - handler.app.AddNewEdge(newObject); - if (!toNewVertex) - { - var neighborEdges = handler.app.graph.getNeighborEdges(newObject); - if (neighborEdges.length >= 1) - { - var curve = handler.app.GetAvailableCurveValue(neighborEdges, newObject); - newObject.model.SetCurveValue(curve); - } - } - newSelected.push(newObject); - } - } - - handler.selectedObjects = newSelected; - handler.needRedraw = true; - handler.app.redrawGraph(); - }); - - $('#message').on('click', '#RemoveSelected', function(){ - handler.app.PushToStack("RemoveSelection"); - - userAction("GroupSelected.Remove"); - - for(var i = 0; i < handler.selectedObjects.length; i ++) - handler.app.DeleteObject(handler.selectedObjects[i]); - handler.selectedObjects = []; - handler.needRedraw = true; - handler.app.redrawGraph(); - handler.message = g_textsSelectAndMove + " " + g_selectGroupText + ""; - }); - - if (hasEdges) { - $('#message').on('click', '#changeCommonStyleEdge', function(){ - var selectedEdges = handler.app.GetSelectedEdges(); - var setupVertexStyle = new SetupEdgeStyle(handler.app); - setupVertexStyle.show(0, selectedEdges); - }); - $('#message').on('click', '#changeSelectedStyleEdge', function(){ - var selectedEdges = handler.app.GetSelectedEdges(); - var setupVertexStyle = new SetupEdgeStyle(handler.app); - setupVertexStyle.show(1, selectedEdges); - }); - } - - if (hasVertices) { - $('#message').on('click', '#changeCommonStyleVertex', function(){ - var selectedVertices = handler.app.GetSelectedVertices(); - var setupVertexStyle = new SetupVertexStyle(handler.app); - setupVertexStyle.show(0, selectedVertices); - }); - $('#message').on('click', '#changeSelectedStyleVertex', function(){ - var selectedVertices = handler.app.GetSelectedVertices(); - var setupVertexStyle = new SetupVertexStyle(handler.app); - setupVertexStyle.show(1, selectedVertices); - }); - } - } - - this.needRedraw = true; -} - -DefaultHandler.prototype.GetSelectedGroup = function(object) -{ - return (object == this.dragObject) || (object == this.selectedObject) ? 1 : 0 || this.selectedObjects.includes(object); -} - -DefaultHandler.prototype.SelectObjectInRect = function (rect) -{ - this.selectedObjects = []; - var vertices = this.app.graph.vertices; - for (var i = 0; i < vertices.length; i ++) - { - if (rect.isIn(vertices[i].position) && !this.selectedObjects.includes(vertices[i])) - this.selectedObjects.push(vertices[i]); - } - - // Selected Arc. - var edges = this.app.graph.edges; - for (var i = 0; i < edges.length; i ++) - { - var edge = edges[i]; - - if (rect.isIn(edge.vertex1.position) && rect.isIn(edge.vertex2.position) && !this.selectedObjects.includes(edge)) - this.selectedObjects.push(edge); - } -} - - -/** - * Add Graph handler. - * - */ -function AddGraphHandler(app) -{ - this.removeStack = true; - BaseHandler.apply(this, arguments); - this.message = g_clickToAddVertex; - this.addContextMenu(); -} - -// inheritance. -AddGraphHandler.prototype = Object.create(BaseHandler.prototype); - -AddGraphHandler.prototype.MouseDown = function(pos) -{ - this.app.PushToStack("Add"); - - this.app.CreateNewGraph(pos.x, pos.y); - this.needRedraw = true; - this.inited = false; -} - -AddGraphHandler.prototype.InitControls = function() -{ - var enumVertexsText = document.getElementById("enumVertexsText"); - if (enumVertexsText) - { - var enumsList = this.app.GetEnumVerticesList(); - for (var i = 0; i < enumsList.length; i ++) - { - var option = document.createElement('option'); - option.text = enumsList[i]["text"]; - option.value = enumsList[i]["value"]; - enumVertexsText.add(option, i); - if (enumsList[i]["select"]) - { - enumVertexsText.selectedIndex = i; - } - } - - var addGraphHandler = this; - enumVertexsText.onchange = function () { - addGraphHandler.ChangedType(); - }; - } -} - -AddGraphHandler.prototype.ChangedType = function() -{ - var enumVertexsText = document.getElementById("enumVertexsText"); - - this.app.SetEnumVerticesType(enumVertexsText.options[enumVertexsText.selectedIndex].value); -} - - - -/** - * Connection Graph handler. - * - */ -function ConnectionGraphHandler(app) -{ - this.removeStack = true; - BaseHandler.apply(this, arguments); - this.SelectFirst(); - this.addContextMenu(); -} - -// inheritance. -ConnectionGraphHandler.prototype = Object.create(BaseHandler.prototype); -// First selected. -ConnectionGraphHandler.prototype.firstObject = null; - -ConnectionGraphHandler.prototype.GetSelectedVertex = function() -{ - return (this.firstObject instanceof BaseVertex) ? this.firstObject : null; -} - -ConnectionGraphHandler.prototype.AddNewEdge = function(selectedObject, isDirect) -{ - let newEdge = this.app.CreateNewArc(this.firstObject, selectedObject, isDirect, - document.getElementById('EdgeWeight').value, - $("#RadiosReplaceEdge").prop("checked"), - document.getElementById('EdgeLable').value); - - if ($("#CheckSaveDefaultEdge").prop("checked")) { - let defaultEdge = new BaseEdge(); - defaultEdge.copyFrom(this.app.graph.edges[newEdge]); - this.app.setDefaultEdge(defaultEdge); - } - - this.SelectFirst(); - this.app.NeedRedraw(); -} - -ConnectionGraphHandler.prototype.AddDefaultEdge = function(selectedObject) -{ - let defaultEdge = this.app.getDefaultEdge(); - let newEdge = this.app.CreateNewArc(this.firstObject, selectedObject, defaultEdge.isDirect, - defaultEdge.weight, - false, - defaultEdge.upText); - this.app.graph.edges[newEdge].useWeight = defaultEdge.useWeight; - - this.SelectFirst(); - this.app.NeedRedraw(); - - userAction("CreateDefaultEdge"); -} - -ConnectionGraphHandler.prototype.SelectVertex = function(selectedObject) -{ - if (this.firstObject) - { - var direct = false; - var handler = this; - - if (!this.app.hasDefaultEdge() || !document.getElementById('useDefaultEdge').checked) { - this.ShowCreateEdgeDialog(this.firstObject, selectedObject, function (firstVertex, secondVertex, direct) { - handler.AddNewEdge(secondVertex, direct); - }); - } else { - handler.AddDefaultEdge(selectedObject); - } - } - else - { - this.SelectSecond(selectedObject); - } - this.needRedraw = true; -} - -ConnectionGraphHandler.prototype.MouseDown = function(pos) -{ - $('#message').unbind(); - - var selectedObject = this.GetSelectedGraph(pos); - if (selectedObject && (selectedObject instanceof BaseVertex)) - { - this.SelectVertex(selectedObject); - } - else - { - this.SelectFirst(); - this.needRedraw = true; - } -} - -ConnectionGraphHandler.prototype.GetSelectedGroup = function(object) -{ - return (object == this.firstObject) ? 1 : 0; -} - -ConnectionGraphHandler.prototype.SelectFirst = function() -{ - this.firstObject = null; - - this.message = g_selectFirstVertexToConnect + this.GetUseDefaultEdgeCheckBox() + - this.GetSelect2VertexMenu(); - this.message = this.AppendSpecialSctionsButton(this.message); -} - -ConnectionGraphHandler.prototype.SelectSecond = function(selectedObject) -{ - this.firstObject = selectedObject; - this.message = g_selectSecondVertexToConnect + this.GetUseDefaultEdgeCheckBox() + - this.GetSelect2VertexMenu(); - this.message = this.AppendSpecialSctionsButton(this.message); -} - -ConnectionGraphHandler.prototype.SelectFirstVertexMenu = function(vertex1Text, vertex) -{ - this.firstObject = null; - this.SelectVertex(vertex); -} - -ConnectionGraphHandler.prototype.UpdateFirstVertexMenu = function(vertex1Text) -{ - if (this.firstObject) - { - vertex1Text.value = this.firstObject.mainText; - } -} - -ConnectionGraphHandler.prototype.SelectSecondVertexMenu = function(vertex2Text, vertex) -{ - this.SelectVertex(vertex); -} - -ConnectionGraphHandler.prototype.UpdateSecondVertexMenu = function(vertex2Text) -{ - if (this.secondObject) - { - vertex2Text.value = this.secondObject.mainText; - } -} - -ConnectionGraphHandler.prototype.AppendSpecialSctionsButton = function(baseMessage) -{ - let hasEdges = this.app.graph.hasEdges(); - - if (!hasEdges) return baseMessage; - - let hasDirectedEdges = this.app.graph.hasDirectEdge(); - let hasUndirectedEdges = this.app.graph.hasUndirectEdge(); - - let handler = this; - - $('#message').on('click', '#reverseAll', function() { - handler.app.PushToStack("ReverseAllEdges"); - - handler.app.graph.reverseAllEdges(); - handler.app.redrawGraph(); - - userAction("ReverseAllEdges"); - }); - $('#message').on('click', '#makeAllUndirected', function(){ - handler.app.PushToStack("makeAllEdgesUndirected"); - - handler.app.graph.makeAllEdgesUndirected(); - handler.app.redrawGraph(); - - userAction("makeAllEdgesUndirected"); - }); - $('#message').on('click', '#makeAllDirected', function(){ - handler.app.PushToStack("makeAllEdgesDirected"); - - handler.app.graph.makeAllEdgesDirected(); - handler.app.redrawGraph(); - - userAction("makeAllEdgesDirected"); - }); - - return "
" - + " " - + "" - + "
" + baseMessage; -} - -ConnectionGraphHandler.checkUseDefaultEdge = function (elem, app) -{ - app.setUseDefaultEdge(elem.checked); - app.updateMessage(); -}; - -ConnectionGraphHandler.prototype.GetUseDefaultEdgeCheckBox = function() { - if (!this.app.hasDefaultEdge()) { - return ""; - } - - return "
" + - "" + - " " + - "
"; -} - -ConnectionGraphHandler.prototype.InitControls = function() { - BaseHandler.prototype.InitControls.call(this) - - if (!this.app.hasDefaultEdge()) { - return; - } - - let app = this.app; - - $('#useDefaultEdge').unbind(); - $('#useDefaultEdge').change(function() { - app.setUseDefaultEdge(this.checked); - }); - $("#useDefaultEdge").prop("checked", this.app.getUseDefaultEdge()); -} - - -/** - * Delete Graph handler. - * - */ -function DeleteGraphHandler(app) -{ - this.removeStack = true; - BaseHandler.apply(this, arguments); - this.message = g_selectObjectToDelete; - this.addContextMenu(); -} - -// inheritance. -DeleteGraphHandler.prototype = Object.create(BaseHandler.prototype); - -DeleteGraphHandler.prototype.MouseDown = function(pos) -{ - var selectedObject = this.GetSelectedObject(pos); - - if (!this.app.IsCorrectObject(selectedObject)) - return; - - this.app.PushToStack("Delete"); - this.app.DeleteObject(selectedObject); - this.needRedraw = true; -} - -/** - * Delete Graph handler. - * - */ -function DeleteAllHandler(app) -{ - BaseHandler.apply(this, arguments); -} - -// inheritance. -DeleteAllHandler.prototype = Object.create(BaseHandler.prototype); - -DeleteAllHandler.prototype.clear = function() -{ - this.app.PushToStack("DeleteAll"); - - // Selected Graph. - this.app.graph = new Graph(); - this.app.savedGraphName = ""; - this.needRedraw = true; -} - - -/** - * Save/Load graph from matrix. - * - */ -function ShowAdjacencyMatrix(app) -{ - BaseHandler.apply(this, arguments); - this.message = ""; -} - -// inheritance. -ShowAdjacencyMatrix.prototype = Object.create(BaseHandler.prototype); -// First selected. -ShowAdjacencyMatrix.prototype.firstObject = null; -// Path -ShowAdjacencyMatrix.prototype.pathObjects = null; - -ShowAdjacencyMatrix.prototype.show = function() -{ - var handler = this; - var dialogButtons = {}; - - $('#AdjacencyMatrixField').unbind(); - $( "#AdjacencyMatrixField" ).on('keyup change', function (eventObject) - { - if (!handler.app.TestAdjacencyMatrix($( "#AdjacencyMatrixField" ).val(), [], [])) - { - $( "#BadMatrixFormatMessage" ).show(); - } - else - { - $( "#BadMatrixFormatMessage" ).hide(); - } - }); - - dialogButtons[g_save] = function() { - handler.app.PushToStack("ChangeAdjacencyMatrix"); - handler.app.SetAdjacencyMatrixSmart($( "#AdjacencyMatrixField" ).val()); - $( this ).dialog( "close" ); - }; - dialogButtons[g_cancel] = function() { - $( this ).dialog( "close" ); - }; - - $( "#AdjacencyMatrixField" ).val(this.app.GetAdjacencyMatrix()); - $( "#BadMatrixFormatMessage" ).hide(); - - if (this.app.graph.isMulti()) - $( "#AdjacencyMatrixMultiGraphDesc").show(); - else - $( "#AdjacencyMatrixMultiGraphDesc").hide(); - - $( "#adjacencyMatrix" ).dialog({ - resizable: false, - height: "auto", - width: "auto", - modal: true, - title: g_adjacencyMatrixText, - buttons: dialogButtons, - dialogClass: 'EdgeDialog' - }); -} - - -/** - * Save/Load graph from Incidence matrix. - * - */ -function ShowIncidenceMatrix(app) -{ - BaseHandler.apply(this, arguments); - this.message = ""; -} - -// inheritance. -ShowIncidenceMatrix.prototype = Object.create(BaseHandler.prototype); -// First selected. -ShowIncidenceMatrix.prototype.firstObject = null; -// Path -ShowIncidenceMatrix.prototype.pathObjects = null; - -ShowIncidenceMatrix.prototype.show = function() -{ - var handler = this; - var dialogButtons = {}; - - $('#IncidenceMatrixField').unbind(); - $( "#IncidenceMatrixField" ).on('keyup change', function (eventObject) - { - if (!handler.app.TestIncidenceMatrix($( "#IncidenceMatrixField" ).val(), [], [])) - { - $( "#BadIncidenceMatrixFormatMessage" ).show(); - } - else - { - $( "#BadIncidenceMatrixFormatMessage" ).hide(); - } - }); - - dialogButtons[g_save] = function() { - handler.app.PushToStack("IncidenceMatrixChanged"); - handler.app.SetIncidenceMatrixSmart($( "#IncidenceMatrixField" ).val()); - $( this ).dialog( "close" ); - }; - dialogButtons[g_cancel] = function() { - $( this ).dialog( "close" ); - }; - - $( "#IncidenceMatrixField" ).val(this.app.GetIncidenceMatrix()); - $( "#BadIncidenceMatrixFormatMessage" ).hide(); - - $( "#incidenceMatrix" ).dialog({ - resizable: false, - height: "auto", - width: "auto", - modal: true, - title: g_incidenceMatrixText, - buttons: dialogButtons, - dialogClass: 'EdgeDialog' - }); -} - - -/** - * Show distance matrix. - * - */ -function ShowDistanceMatrix(app) -{ - BaseHandler.apply(this, arguments); - this.app = app; - this.message = ""; -} - -// inheritance. -ShowDistanceMatrix.prototype = Object.create(BaseHandler.prototype); -// First selected. -ShowDistanceMatrix.prototype.firstObject = null; -// Path -ShowDistanceMatrix.prototype.pathObjects = null; - -ShowDistanceMatrix.prototype.GetIncidenceMatrix = function (rawMatrix) -{ - var matrix = ""; - for (var i = 0; i < rawMatrix.length; i++) - { - for (var j = 0; j < rawMatrix[i].length; j++) - { - if (i == j) - { - matrix += "0"; - } - else if ((new Graph()).infinity == rawMatrix[i][j]) - { - matrix += '\u221E'; - } - else - { - matrix += rawMatrix[i][j]; - } - - if (j != rawMatrix[i].length - 1) - { - matrix += ", "; - } - - } - matrix = matrix + "\n"; - } - - return matrix; -} - -ShowDistanceMatrix.prototype.show = function() -{ - var handler = this; - var dialogButtons = {}; - - dialogButtons[g_close] = function() { - $( this ).dialog( "close" ); - }; - - var handler = g_Algorithms[g_AlgorithmIds.indexOf("OlegSh.FloidAlgorithm")](this.app.graph, this.app); - - $( "#FloidMatrixField" ).val(this.GetIncidenceMatrix(handler.resultMatrix())); - - $( "#floidMatrix" ).dialog({ - resizable: false, - height: "auto", - width: "auto", - modal: true, - title: g_minDistMatrixText, - buttons: dialogButtons, - dialogClass: 'EdgeDialog' - }); -} - -/** - * Save dialog Graph handler. - * - */ -function SavedDialogGraphHandler(app) -{ - BaseHandler.apply(this, arguments); - this.message = ""; -} - -// inheritance. -SavedDialogGraphHandler.prototype = Object.create(BaseHandler.prototype); -// First selected. -SavedDialogGraphHandler.prototype.firstObject = null; -// Path -SavedDialogGraphHandler.prototype.pathObjects = null; -// Objects. -SavedDialogGraphHandler.prototype.objects = null; - -SavedDialogGraphHandler.prototype.show = function(object) -{ - this.app.SaveGraphOnDisk(); - - var dialogButtons = {}; - - dialogButtons[g_close] = function() { - $( this ).dialog( "close" ); - }; - - document.getElementById('GraphName').value = "http://" + window.location.host + window.location.pathname + - "?graph=" + this.app.GetGraphName(); - - document.getElementById('GraphName').select(); - - document.getElementById("ShareSavedGraph").innerHTML = - document.getElementById("ShareSavedGraph").innerHTML.replace(/graph=([A-Za-z]*)/g, "graph=" + this.app.GetGraphName()); - - $( "#saveDialog" ).dialog({ - resizable: false, - height: "auto", - width: "auto", - modal: true, - title: g_save_dialog, - buttons: dialogButtons, - dialogClass: 'EdgeDialog' - }); - -} - -/** - * Save dialog Graph handler. - * - */ -function SavedDialogGraphImageHandler(app) -{ - BaseHandler.apply(this, arguments); - this.message = ""; - this.imageName = ""; -} - -// inheritance. -SavedDialogGraphImageHandler.prototype = Object.create(BaseHandler.prototype); -// First selected. -SavedDialogGraphImageHandler.prototype.firstObject = null; -// Path -SavedDialogGraphImageHandler.prototype.pathObjects = null; -// Objects. -SavedDialogGraphImageHandler.prototype.objects = null; - -SavedDialogGraphImageHandler.prototype.showDialogCallback = function (imageExtension) -{ - var dialogButtons = {}; - - dialogButtons[g_close] = function() { - $( this ).dialog( "close" ); - }; - - var fileLocation = "tmp/saved/" + this.imageName.substr(0, 2) + "/"+ this.imageName + "." + imageExtension - - document.getElementById("showSavedImageGraph").src = "/" + fileLocation; - document.getElementById("showSavedImageGraphRef").href = "/" + fileLocation; - //document.getElementById("showSavedImageGraph").src = document.getElementById("showSavedImageGraph").src.replace(/tmp\/saved\/([A-Za-z]*)\/([A-Za-z]*).png/g, fileLocation); - document.getElementById("ShareSavedImageGraph").innerHTML = - document.getElementById("ShareSavedImageGraph").innerHTML.replace(/tmp\/saved\/([A-Za-z]*)\/([A-Za-z]*).png/g, fileLocation); - - document.getElementById("SaveImageLinks").innerHTML = - document.getElementById("SaveImageLinks").innerHTML.replace(/tmp\/saved\/([A-Za-z]*)\/([A-Za-z]*).png/g, fileLocation); - - $( "#saveImageDialog" ).dialog({ - resizable: false, - height: "auto", - width: "auto", - modal: true, - title: g_save_image_dialog, - buttons: dialogButtons, - dialogClass: 'EdgeDialog' - }); - -} - -SavedDialogGraphImageHandler.prototype.showWorkspace = function() -{ - var object = this; - var callback = function() { - object.showDialogCallback("png"); - }; - - this.imageName = this.app.SaveGraphImageOnDisk(callback); -} - -SavedDialogGraphImageHandler.prototype.showFullgraph = function() -{ - var object = this; - var callback = function() { - object.showDialogCallback("png"); - }; - - this.imageName = this.app.SaveFullGraphImageOnDisk(callback, false); -} - -SavedDialogGraphImageHandler.prototype.showPrint = function() -{ - var object = this; - var callback = function() { - object.showDialogCallback("png"); - }; - - this.imageName = this.app.SaveFullGraphImageOnDisk(callback, true); -} - -SavedDialogGraphImageHandler.prototype.showSvg = function() -{ - var object = this; - var callback = function() { - object.showDialogCallback("svg"); - }; - - this.imageName = this.app.SaveSVGGraphOnDisk(callback); -} - -/** - * Algorithm Graph handler. - * - */ -function AlgorithmGraphHandler(app, algorithm) -{ - BaseHandler.apply(this, arguments); - this.algorithm = algorithm; - this.SaveUpText(); - - this.UpdateResultAndMessage(); -} - -// inheritance. -AlgorithmGraphHandler.prototype = Object.create(BaseHandler.prototype); - -// Rest this handler. -AlgorithmGraphHandler.prototype.MouseMove = function(pos) {} - -AlgorithmGraphHandler.prototype.MouseDown = function(pos) -{ - this.app.setRenderPath([]); - - if (this.algorithm.instance()) - { - this.app.SetDefaultHandler(); - } - else - { - var selectedObject = this.GetSelectedGraph(pos); - if (selectedObject && (selectedObject instanceof BaseVertex)) - { - if (this.algorithm.selectVertex(selectedObject)) - { - this.needRedraw = true; - } - - this.UpdateResultAndMessage(); - } - else if (selectedObject && (selectedObject instanceof BaseEdge)) - { - if (this.algorithm.selectEdge(selectedObject)) - { - this.needRedraw = true; - } - - this.UpdateResultAndMessage(); - } - else - { - if (this.algorithm.deselectAll()) - { - this.needRedraw = true; - this.UpdateResultAndMessage(); - } - } - } -} - -AlgorithmGraphHandler.prototype.MouseUp = function(pos) {} - -AlgorithmGraphHandler.prototype.GetSelectedGroup = function(object) -{ - return this.algorithm.getObjectSelectedGroup(object); -} - -AlgorithmGraphHandler.prototype.RestoreAll = function() -{ - this.app.setRenderPath([]); - - if (this.algorithm.needRestoreUpText()) - { - this.RestoreUpText(); - } - - if (this.algorithm.wantRestore()) - { - this.algorithm.restore(); - } -} - -AlgorithmGraphHandler.prototype.SaveUpText = function() -{ - this.vertexUpText = {}; - var graph = this.app.graph; - for (i = 0; i < graph.vertices.length; i ++) - { - this.vertexUpText[graph.vertices[i].id] = graph.vertices[i].upText; - } -} - -AlgorithmGraphHandler.prototype.RestoreUpText = function() -{ - var graph = this.app.graph; - - for (i = 0; i < graph.vertices.length; i ++) - { - if (graph.vertices[i].id in this.vertexUpText) - { - graph.vertices[i].upText = this.vertexUpText[graph.vertices[i].id]; - } - } -} - -AlgorithmGraphHandler.prototype.UpdateResultAndMessage = function() -{ - var self = this; - result = this.algorithm.result(function (result) - { - self.message = self.algorithm.getMessage(g_language); - self.app.resultCallback(result); - }); - - this.app.resultCallback(result); - - this.message = this.algorithm.getMessage(g_language); -} - -AlgorithmGraphHandler.prototype.InitControls = function() -{ - this.algorithm.messageWasChanged(); -} - -AlgorithmGraphHandler.prototype.GetMessage = function() -{ - return this.algorithm.getMessage(g_language); -} - - -/** - * Groupe rename vertices. - * - */ -function GroupRenameVertices(app) -{ - BaseHandler.apply(this, arguments); - this.message = ""; -} - -// inheritance. -GroupRenameVertices.prototype = Object.create(BaseHandler.prototype); -// First selected. -GroupRenameVertices.prototype.firstObject = null; -// Path -GroupRenameVertices.prototype.pathObjects = null; - -GroupRenameVertices.prototype.show = function() -{ - var handler = this; - var dialogButtons = {}; - var graph = this.app.graph; - var app = this.app; - - dialogButtons[g_save] = function() { - app.PushToStack("Rename"); - - var titlesList = $( "#VertextTitleList" ).val().split('\n'); - for (i = 0; i < Math.min(graph.vertices.length, titlesList.length); i ++) - { - graph.vertices[i].mainText = titlesList[i]; - } - app.redrawGraph(); - $( this ).dialog( "close" ); - }; - dialogButtons[g_cancel] = function() { - $( this ).dialog( "close" ); - }; - - var titleList = ""; - for (i = 0; i < graph.vertices.length; i ++) - { - titleList = titleList + graph.vertices[i].mainText + "\n"; - } - - $( "#VertextTitleList" ).val(titleList); - - $( "#GroupRenameDialog" ).dialog({ - resizable: false, - height: "auto", - width: "auto", - modal: true, - title: g_groupRename, - buttons: dialogButtons, - dialogClass: 'EdgeDialog' - }); -} - - -/** - * Setup Vertex Style rename vertices. - * - */ -function SetupVertexStyle(app) -{ - BaseHandler.apply(this, arguments); - this.message = ""; -} - -// inheritance. -SetupVertexStyle.prototype = Object.create(BaseHandler.prototype); - -SetupVertexStyle.prototype.show = function(index, selectedVertices) -{ - var handler = this; - var dialogButtons = {}; - var graph = this.app.graph; - var app = this.app; - this.forAll = selectedVertices == null; - var forAll = this.forAll; - var self = this; - - var applyIndex = function(index) - { - self.index = index; - self.originStyle = (self.index == 0 ? app.vertexCommonStyle : app.vertexSelectedVertexStyles[self.index - 1]); - if (!forAll) - { - self.originStyle = selectedVertices[0].getStyleFor(self.index); - } - self.style = FullObjectCopy(self.originStyle); - } - - applyIndex(index); - - var fillFields = function() - { - var fullStyle = self.style.GetStyle({}, forAll ? undefined : selectedVertices[0]); - - $( "#vertexFillColor" ).val(fullStyle.fillStyle); - $( "#vertexStrokeColor" ).val(fullStyle.strokeStyle); - $( "#vertexTextColor" ).val(fullStyle.mainTextColor); - $( "#upVertexTextColor" ).val(fullStyle.upTextColor); - $( "#vertexStrokeSize" ).val(fullStyle.lineWidth); - $( "#vertexShape" ).val(fullStyle.shape); - $( "#vertexSize" ).val(forAll ? app.GetDefaultVertexSize() : selectedVertices[0].model.diameter); - $( "#commonTextPosition" ).val(fullStyle.commonTextPosition); - - if (self.index > 0 || self.index == "all") - { - $( "#VertexSelectedIndexForm" ).show(); - $( "#vertexSelectedIndex" ).val(self.index); - } - else - { - $( "#VertexSelectedIndexForm" ).hide(); - } - - // Fill color presets. - var stylesArray = []; - stylesArray.push(app.vertexCommonStyle); - - for (i = 0; i < app.vertexSelectedVertexStyles.length; i ++) - stylesArray.push(app.vertexSelectedVertexStyles[i]); - - var colorSet = {}; - for (i = 0; i < stylesArray.length; i ++) - { - var style = stylesArray[i]; - if (style.hasOwnProperty('strokeStyle')) - colorSet[style.strokeStyle] = 1; - if (style.hasOwnProperty('fillStyle')) - colorSet[style.fillStyle] = 1; - if (style.hasOwnProperty('mainTextColor')) - colorSet[style.mainTextColor] = 1; - if (style.hasOwnProperty('upTextColor')) - colorSet[style.upTextColor] = 1; - } - - $("#vertexFillColorPreset").find('option').remove(); - $("#upVertexTextColorPreset").find('option').remove(); - $("#vertexTextColorPreset").find('option').remove(); - $("#vertexStrokeColorPreset").find('option').remove(); - for (const property in colorSet) - { - $("#vertexFillColorPreset").append(new Option(property)); - $("#upVertexTextColorPreset").append(new Option(property)); - $("#vertexTextColorPreset").append(new Option(property)); - $("#vertexStrokeColorPreset").append(new Option(property)); - } - } - - var redrawVertex = function() - { - var fullStyle = self.style.GetStyle({}, forAll ? undefined : selectedVertices[0]); - - if (fullStyle.fillStyle != $( "#vertexFillColor" ).val()) - self.style.fillStyle = $( "#vertexFillColor" ).val(); - - if (fullStyle.strokeStyle != $( "#vertexStrokeColor" ).val()) - self.style.strokeStyle = $( "#vertexStrokeColor" ).val(); - - if (fullStyle.mainTextColor != $( "#vertexTextColor" ).val()) - self.style.mainTextColor = $( "#vertexTextColor" ).val(); - - if (fullStyle.lineWidth != $( "#vertexStrokeSize" ).val()) - self.style.lineWidth = parseInt($( "#vertexStrokeSize" ).val()); - - if (fullStyle.shape != $( "#vertexShape" ).val()) - self.style.shape = parseInt($( "#vertexShape" ).val()); - - if (fullStyle.upTextColor != $( "#upVertexTextColor" ).val()) - self.style.upTextColor = $( "#upVertexTextColor" ).val(); - - if (fullStyle.commonTextPosition != $( "#commonTextPosition" ).val()) - self.style.commonTextPosition = $( "#commonTextPosition" ).val(); - - var diameter = parseInt($( "#vertexSize" ).val()); - - var canvas = document.getElementById( "VertexPreview" ); - var context = canvas.getContext('2d'); - - context.save(); - - var backgroundDrawer = new BaseBackgroundDrawer(context); - backgroundDrawer.Draw(app.backgroundCommonStyle, canvas.width, canvas.height, new Point(0, 0), 1.0); - - var graphDrawer = new BaseVertexDrawer(context); - var baseVertex = new BaseVertex(canvas.width / 2, canvas.height / 2, new BaseEnumVertices(this)); - baseVertex.mainText = "1"; - baseVertex.upText = "Up Text"; - baseVertex.model.diameter = diameter; - - if (!forAll) - baseVertex.ownStyles = selectedVertices[0].ownStyles; - - graphDrawer.Draw(baseVertex, self.style.GetStyle({}, baseVertex)); - - context.restore(); - } - - var changeIndex = function() - { - var val = $( "#vertexSelectedIndex" ).val(); - if (val == "all") - { - applyIndex(1); - self.index = "all"; - fillFields(); - } - else - { - var index = parseInt(val); - self.index = index; - applyIndex(index); - fillFields(); - } - redrawVertex(); - } - - var applyDiameter = function(diameter) - { - if (forAll) - { - app.SetDefaultVertexSize(diameter); - } - else - { - selectedVertices.forEach(function(vertex) { - vertex.model.diameter = diameter; - }); - } - }; - - dialogButtons[g_default] = - { - text : g_default, - class : "MarginLeft", - click : function() { - - app.PushToStack("ChangeStyle"); - - applyDiameter(forAll ? (new VertexModel()).diameter : app.GetDefaultVertexSize()); - - var indexes = []; - if (self.index == "all") - { - for (i = 0; i < app.vertexSelectedVertexStyles.length; i ++) - indexes.push(i + 1); - } - else - indexes.push(self.index); - - - if (forAll) - { - indexes.forEach(function(index) { - app.ResetVertexStyle(index); - }); - } - else - { - selectedVertices.forEach(function(vertex) { - indexes.forEach(function(index) { - vertex.resetOwnStyle(index); - }); - }); - } - app.redrawGraph(); - $( this ).dialog( "close" ); - } - }; - - dialogButtons[g_save] = function() { - - app.PushToStack("ChangeStyle"); - - applyDiameter(parseInt($( "#vertexSize" ).val())); - - var indexes = []; - if (self.index == "all") - { - indexes.push({index : 1, style : self.style}); - for (i = 1; i < app.vertexSelectedVertexStyles.length; i ++) - { - var style = (new BaseVertexStyle()); - style.baseStyles.push("selected"); - indexes.push({index : i + 1, style : style}); - } - - self.style.baseStyles = []; - self.style.baseStyles = self.style.baseStyles.concat((new SelectedVertexStyle0()).baseStyles); - } - else - indexes.push({index : self.index, style : self.style}); - - if (forAll) - { - indexes.forEach(function(index) { - app.SetVertexStyle(index.index, index.style); - }); - } - else - { - if (JSON.stringify(self.originStyle) !== JSON.stringify(self.style)) - { - selectedVertices.forEach(function(vertex) { - indexes.forEach(function(index) { - vertex.setOwnStyle(index.index, index.style); - }); - }); - } - } - app.redrawGraph(); - $( this ).dialog( "close" ); - }; - dialogButtons[g_cancel] = function() { - $( this ).dialog( "close" ); - }; - - fillFields(); - - $( "#SetupVertexStyleDialog" ).dialog({ - resizable: false, - height: "auto", - width: "auto", - modal: true, - title: g_vertexDraw, - buttons: dialogButtons, - dialogClass: 'EdgeDialog' - }); - - redrawVertex(); - - $( "#vertexFillColor" ).unbind(); - $( "#vertexStrokeColor" ).unbind(); - $( "#vertexTextColor" ).unbind(); - $( "#upVertexTextColor" ).unbind(); - $( "#vertexStrokeSize" ).unbind(); - $( "#vertexShape" ).unbind(); - $( "#vertexSize" ).unbind(); - $( "#commonTextPosition" ).unbind(); - $( "#vertexSelectedIndex" ).unbind(); - - $( "#vertexFillColor" ).change(redrawVertex); - $( "#vertexStrokeColor" ).change(redrawVertex); - $( "#vertexTextColor" ).change(redrawVertex); - $( "#vertexStrokeSize" ).change(redrawVertex); - $( "#vertexShape" ).change(redrawVertex); - $( "#vertexSize" ).change(redrawVertex); - $( "#upVertexTextColor" ).change(redrawVertex); - $( "#commonTextPosition" ).change(redrawVertex); - $( "#vertexSelectedIndex" ).change(changeIndex); -} - -/** - * Setup Vertex Style rename vertices. - * - */ -function SetupEdgeStyle(app) -{ - BaseHandler.apply(this, arguments); - this.message = ""; -} - -// inheritance. -SetupEdgeStyle.prototype = Object.create(BaseHandler.prototype); - -SetupEdgeStyle.prototype.show = function(index, selectedEdges) -{ - var handler = this; - var dialogButtons = {}; - var graph = this.app.graph; - var app = this.app; - this.forAll = selectedEdges == null; - var forAll = this.forAll; - - var self = this; - - var applyIndex = function(index) - { - self.index = index; - var originStyle = (self.index == 0 ? app.edgeCommonStyle : app.edgeSelectedStyles[self.index - 1]); - if (!forAll) - { - originStyle = selectedEdges[0].getStyleFor(self.index); - } - self.style = FullObjectCopy(originStyle); - } - - applyIndex(index); - - var fillFields = function() - { - var fullStyle = self.style.GetStyle({}, forAll ? undefined : selectedEdges[0]); - - $( "#edgeFillColor" ).val(fullStyle.fillStyle); - $( "#edgeStrokeColor" ).val(fullStyle.strokeStyle); - $( "#edgeTextColor" ).val(fullStyle.weightText); - $( "#edgeStyle" ).val(fullStyle.lineDash); - $( "#edgeWidth" ).val(forAll ? app.GetDefaultEdgeWidth() : selectedEdges[0].model.width); - - $( "#weightEdgeTextColor" ).val(fullStyle.additionalTextColor); - $( "#weightTextPosition" ).val(fullStyle.weightPosition); - - if (self.index > 0 || self.index == "all") - { - $( "#EdgeSelectedIndexForm" ).show(); - $( "#edgeSelectedIndex" ).val(self.index); - } - else - { - $( "#EdgeSelectedIndexForm" ).hide(); - } - - // Fill color presets. - var stylesArray = []; - stylesArray.push(app.edgeCommonStyle); - - for (i = 0; i < app.edgeSelectedStyles.length; i ++) - stylesArray.push(app.edgeSelectedStyles[i]); - - var colorSet = {}; - for (i = 0; i < stylesArray.length; i ++) - { - var style = stylesArray[i]; - if (style.hasOwnProperty('strokeStyle')) - colorSet[style.strokeStyle] = 1; - if (style.hasOwnProperty('fillStyle')) - colorSet[style.fillStyle] = 1; - if (style.hasOwnProperty('additionalTextColor')) - colorSet[style.additionalTextColor] = 1; - } - - $("#edgeFillColorPreset").find('option').remove(); - $("#weightEdgeTextColorPreset").find('option').remove(); - $("#edgeTextColorPreset").find('option').remove(); - $("#edgeStrokeColorPreset").find('option').remove(); - for (const property in colorSet) - { - $("#edgeFillColorPreset").append(new Option(property)); - $("#weightEdgeTextColorPreset").append(new Option(property)); - $("#edgeTextColorPreset").append(new Option(property)); - $("#edgeStrokeColorPreset").append(new Option(property)); - } - } - - var redrawVertex = function() - { - var fullStyle = self.style.GetStyle({}, forAll ? undefined : selectedEdges[0]); - - if (fullStyle.fillStyle != $( "#edgeFillColor" ).val()) - self.style.fillStyle = $( "#edgeFillColor" ).val(); - - if (fullStyle.strokeStyle != $( "#edgeStrokeColor" ).val()) - self.style.strokeStyle = $( "#edgeStrokeColor" ).val(); - - if (fullStyle.weightText != $( "#edgeTextColor" ).val()) - self.style.weightText = $( "#edgeTextColor" ).val(); - - if (fullStyle.lineDash != $( "#edgeStyle" ).val()) - self.style.lineDash = $( "#edgeStyle" ).val(); - - if (fullStyle.additionalTextColor != $( "#weightEdgeTextColor" ).val()) - self.style.additionalTextColor = $( "#weightEdgeTextColor" ).val(); - - if (fullStyle.weightPosition != $( "#weightTextPosition" ).val()) - self.style.weightPosition = $( "#weightTextPosition" ).val(); - - var edgeWidth = parseInt($( "#edgeWidth" ).val()); - - var canvas = document.getElementById( "EdgePreview" ); - var context = canvas.getContext('2d'); - - context.save(); - - var backgroundDrawer = new BaseBackgroundDrawer(context); - backgroundDrawer.Draw(app.backgroundCommonStyle, canvas.width, canvas.height, new Point(0, 0), 1.0); - - var graphDrawer = new BaseEdgeDrawer(context); - var baseVertex1 = new BaseVertex(0, canvas.height / 2, new BaseEnumVertices(this)); - var baseVertex2 = new BaseVertex(canvas.width, canvas.height / 2, new BaseEnumVertices(this)); - - baseVertex1.currentStyle = baseVertex1.getStyleFor(0); - baseVertex2.currentStyle = baseVertex2.getStyleFor(0); - - var baseEdge = new BaseEdge(baseVertex1, baseVertex2, true, 10, "Text"); - - if (!forAll) - baseEdge.ownStyles = selectedEdges[0].ownStyles; - - baseEdge.model.width = edgeWidth; - - graphDrawer.Draw(baseEdge, self.style.GetStyle({}, baseEdge)); - - context.restore(); - } - - var changeIndex = function() - { - var val = $( "#edgeSelectedIndex" ).val(); - if (val == "all") - { - applyIndex(1); - self.index = "all"; - fillFields(); - } - else - { - var index = parseInt(val); - self.index = index; - applyIndex(index); - fillFields(); - } - - redrawVertex(); - } - - var applyWidth = function(width) - { - if (forAll) - { - app.SetDefaultEdgeWidth(width); - } - else - { - selectedEdges.forEach(function(edge) { - edge.model.width = width; - }); - } - }; - - dialogButtons[g_default] = - { - text : g_default, - class : "MarginLeft", - click : function() { - app.PushToStack("ChangeStyle"); - - applyWidth(forAll ? (new EdgeModel()).width : app.GetDefaultEdgeWidth()); - var indexes = []; - if (self.index == "all") - { - for (i = 0; i < app.edgeSelectedStyles.length; i ++) - indexes.push(i + 1); - } - else - indexes.push(self.index); - - if (forAll) - { - indexes.forEach(function(index) { - app.ResetEdgeStyle(index); - }); - } - else - { - selectedEdges.forEach(function(edge) { - indexes.forEach(function(index) { - edge.resetOwnStyle(index); - }); - }); - } - - app.redrawGraph(); - $( this ).dialog( "close" ); - } - }; - - dialogButtons[g_save] = function() { - - app.PushToStack("ChangeStyle"); - - applyWidth(parseInt($( "#edgeWidth" ).val())); - - var indexes = []; - if (self.index == "all") - { - indexes.push({index : 1, style : self.style}); - - for (i = 1; i < app.edgeSelectedStyles.length; i ++) - { - var style = (new BaseEdgeStyle()); - style.baseStyles.push("selected"); - indexes.push({index : i + 1, style : style}); - } - - self.style.baseStyles = []; - self.style.baseStyles = self.style.baseStyles.concat((new SelectedEdgeStyle0()).baseStyles); - } - else - indexes.push({index : self.index, style : self.style}); - - if (forAll) - { - indexes.forEach(function(index) { - app.SetEdgeStyle(index.index, index.style); - }); - } - else - { - selectedEdges.forEach(function(edge) { - indexes.forEach(function(index) { - edge.setOwnStyle(index.index, index.style); - }); - }); - } - app.redrawGraph(); - $( this ).dialog( "close" ); - }; - dialogButtons[g_cancel] = function() { - $( this ).dialog( "close" ); - }; - - fillFields(); - - $( "#SetupEdgeStyleDialog" ).dialog({ - resizable: false, - height: "auto", - width: "auto", - modal: true, - title: g_edgeDraw, - buttons: dialogButtons, - dialogClass: 'EdgeDialog' - }); - - redrawVertex(); - - $( "#edgeFillColor" ).unbind(); - $( "#edgeStrokeColor" ).unbind(); - $( "#edgeTextColor" ).unbind(); - $( "#edgeStyle" ).unbind(); - $( "#edgeWidth" ).unbind(); - $( "#weightEdgeTextColor" ).unbind(); - $( "#weightTextPosition" ).unbind(); - $( "#edgeSelectedIndex" ).unbind(); - - $( "#edgeFillColor" ).change(redrawVertex); - $( "#edgeStrokeColor" ).change(redrawVertex); - $( "#edgeTextColor" ).change(redrawVertex); - $( "#edgeStyle" ).change(redrawVertex); - $( "#edgeWidth" ).change(redrawVertex); - $( "#weightEdgeTextColor" ).change(redrawVertex); - $( "#weightTextPosition" ).change(redrawVertex); - $( "#edgeSelectedIndex" ).change(changeIndex); -} - -/** - * Setup Background Style rename vertices. - * - */ -function SetupBackgroundStyle(app) -{ - BaseHandler.apply(this, arguments); - this.message = ""; - this.maxImageSize = 2048; -} - -// inheritance. -SetupBackgroundStyle.prototype = Object.create(BaseHandler.prototype); - - -SetupBackgroundStyle.prototype.handleImportBackgroundFile = function(files, updateBackgroundCallback) { - var graphFileToLoad = files[0]; - var re = /(?:\.([^.]+))?$/; - var imageExtension = re.exec(graphFileToLoad.name)[1].toLowerCase(); - - if (!(imageExtension == "png" || imageExtension == "jpg" || imageExtension == "jpeg")) { - $("#UploadBackgroundImageError").html(g_wrongImageFormatPNGAndJPEG); - $("#UploadBackgroundImageError").show(); - return; - } - - let self = this; - var fileReader = new FileReader(); - fileReader.onload = function(fileLoadedEvent){ - var textFromFileLoaded = fileLoadedEvent.target.result; - var image = new Image(); - image.onload = function() { - console.log(this.width + 'x' + this.height); - if (this.width > self.maxImageSize || this.height > self.maxImageSize) { - $("#UploadBackgroundImageError").html(formatString(g_wrongImageSizeP1, [self.maxImageSize])); - $("#UploadBackgroundImageError").show(); - return; - } - updateBackgroundCallback(image); - } - image.src = 'data:image/' + imageExtension + ';base64' + textFromFileLoaded; - ImportBackgroundImage.value = ""; - }; - - fileReader.readAsDataURL(graphFileToLoad); -} - -SetupBackgroundStyle.prototype.show = function() -{ - var handler = this; - var dialogButtons = {}; - var graph = this.app.graph; - var app = this.app; - var style = FullObjectCopy(app.backgroundCommonStyle); - - var fillFields = function() - { - $( "#backgroundColor" ).val(style.commonColor); - $( "#backgroundTransporent" ).val(style.commonOpacity); - } - - var redrawVertex = function() - { - style.commonColor = $( "#backgroundColor" ).val(); - style.commonOpacity = $( "#backgroundTransporent" ).val(); - - var canvas = document.getElementById( "BackgroundPreview" ); - var context = canvas.getContext('2d'); - - context.save(); - let bestScale = 1.0; - if (style.image != null) { - let wScale = canvas.width / style.image.width; - let hScale = canvas.height / style.image.height; - bestScale = Math.min(wScale, hScale); - context.scale(bestScale, bestScale); - } - var backgroundDrawer = new BaseBackgroundDrawer(context); - backgroundDrawer.Draw(style, canvas.width, canvas.height, new Point(0, 0), bestScale); - - context.restore(); - - if (style.image != null) { - $( "#RemoveBackgroundFile" ).show(); - } else { - $( "#RemoveBackgroundFile" ).hide(); - } - } - - var loadFile = function() { - userAction("background_loadFromFile"); - - if (ImportBackgroundImage) { - ImportBackgroundImage.click(); - } - } - - var updateBackgroundImage = function(image) { - style.image = image; - $("#UploadBackgroundImageError").hide(); - redrawVertex(); - } - - var clearBackgroundImage = function() { - style.image = null; - $("#UploadBackgroundImageError").hide(); - redrawVertex(); - } - - dialogButtons[g_default] = - { - text : g_default, - class : "MarginLeft", - click : function() { - - app.PushToStack("ChangeBackground"); - - app.ResetBackgroundStyle(); - app.redrawGraph(); - $( this ).dialog( "close" ); - } - }; - - dialogButtons[g_save] = function() { - app.PushToStack("ChangeBackground"); - app.SetBackgroundStyle(style); - app.redrawGraph(); - $( this ).dialog( "close" ); - }; - dialogButtons[g_cancel] = function() { - $( this ).dialog( "close" ); - }; - - fillFields(); - - $( "#SetupBackgroundStyleDialog" ).dialog({ - resizable: false, - height: "auto", - width: "auto", - modal: true, - title: g_backgroundStyle, - buttons: dialogButtons, - dialogClass: 'EdgeDialog' - }); - - try { - redrawVertex(); - } catch (error) { - console.error(error); - } - - $( "#backgroundColor" ).unbind(); - $( "#backgroundTransporent" ).unbind(); - $( "#LoadBackgroundFile" ).unbind(); - $( "#ImportBackgroundImage" ).unbind(); - $( "#RemoveBackgroundFile" ).unbind(); - - $( "#backgroundColor" ).change(redrawVertex); - $( "#backgroundTransporent" ).change(redrawVertex); - $( "#LoadBackgroundFile" ).click(loadFile); - $( "#ImportBackgroundImage" ).change( function () {handler.handleImportBackgroundFile(this.files, updateBackgroundImage);}); - $( "#RemoveBackgroundFile" ).click(clearBackgroundImage); -} diff --git a/script/entities/edge/api/index.js b/script/entities/edge/api/index.js new file mode 100644 index 0000000..4ac9016 --- /dev/null +++ b/script/entities/edge/api/index.js @@ -0,0 +1,9 @@ + +{ +let modulDir = "entities/edge/"; + +doInclude ([ + include ("model/BaseEdge.js", modulDir), + include ("model/EdgeModel.js", modulDir) +]) +} \ No newline at end of file diff --git a/script/BaseEdge.js b/script/entities/edge/model/BaseEdge.js old mode 100755 new mode 100644 similarity index 100% rename from script/BaseEdge.js rename to script/entities/edge/model/BaseEdge.js diff --git a/script/EdgeModel.js b/script/entities/edge/model/EdgeModel.js old mode 100755 new mode 100644 similarity index 99% rename from script/EdgeModel.js rename to script/entities/edge/model/EdgeModel.js index 88a5988..c67c5cb --- a/script/EdgeModel.js +++ b/script/entities/edge/model/EdgeModel.js @@ -31,7 +31,7 @@ EdgeModel.prototype.SaveToXML = function () { return "model_width=\"" + this.width + "\" " + "model_type=\"" + this.type + "\" " + - "model_curveValue=\"" + this.curveValue + "\" " + "model_curveValue=\"" + this.curveValue + "\" " + "model_default=\"" + this.default + "\" "; } diff --git a/script/entities/graph/api/index.js b/script/entities/graph/api/index.js new file mode 100644 index 0000000..0f7eb79 --- /dev/null +++ b/script/entities/graph/api/index.js @@ -0,0 +1,11 @@ + +{ +let modulDir = "entities/graph/"; + +doInclude ([ + include ("shared/point.js"), + include ("entities/edge/api/index.js"), + include ("entities/vertex/api/index.js"), + include ("model/Graph.js", modulDir) +]) +} \ No newline at end of file diff --git a/script/Graph.js b/script/entities/graph/model/Graph.js similarity index 100% rename from script/Graph.js rename to script/entities/graph/model/Graph.js diff --git a/script/entities/vertex/api/index.js b/script/entities/vertex/api/index.js new file mode 100644 index 0000000..fa308de --- /dev/null +++ b/script/entities/vertex/api/index.js @@ -0,0 +1,8 @@ +{ +let modulDir = "entities/vertex/"; + +doInclude ([ + include ("model/BaseVertex.js", modulDir), + include ("model/VertexModel.js", modulDir) +]) +} \ No newline at end of file diff --git a/script/BaseVertex.js b/script/entities/vertex/model/BaseVertex.js old mode 100755 new mode 100644 similarity index 100% rename from script/BaseVertex.js rename to script/entities/vertex/model/BaseVertex.js diff --git a/script/VertexModel.js b/script/entities/vertex/model/VertexModel.js old mode 100755 new mode 100644 similarity index 81% rename from script/VertexModel.js rename to script/entities/vertex/model/VertexModel.js index 68849fd..aa19b40 --- a/script/VertexModel.js +++ b/script/entities/vertex/model/VertexModel.js @@ -3,7 +3,7 @@ * */ - const defaultVertexDiameter = 30; +const defaultVertexDiameter = 30; function VertexModel() { diff --git a/script/features/add_vertices_handler/index.js b/script/features/add_vertices_handler/index.js new file mode 100644 index 0000000..95eebf5 --- /dev/null +++ b/script/features/add_vertices_handler/index.js @@ -0,0 +1,59 @@ +doInclude ([ + include ("features/base_handler/index.js") +]) + +/** + * Add Graph handler. + * + */ +function AddGraphHandler(app) +{ + this.removeStack = true; + BaseHandler.apply(this, arguments); + this.message = g_clickToAddVertex; + this.addContextMenu(); +} + +// inheritance. +AddGraphHandler.prototype = Object.create(BaseHandler.prototype); + +AddGraphHandler.prototype.MouseDown = function(pos) +{ + this.app.PushToStack("Add"); + + this.app.CreateNewGraph(pos.x, pos.y); + this.needRedraw = true; + this.inited = false; +} + +AddGraphHandler.prototype.InitControls = function() +{ + var enumVertexsText = document.getElementById("enumVertexsText"); + if (enumVertexsText) + { + var enumsList = this.app.GetEnumVerticesList(); + for (var i = 0; i < enumsList.length; i ++) + { + var option = document.createElement('option'); + option.text = enumsList[i]["text"]; + option.value = enumsList[i]["value"]; + enumVertexsText.add(option, i); + if (enumsList[i]["select"]) + { + enumVertexsText.selectedIndex = i; + } + } + + var addGraphHandler = this; + enumVertexsText.onchange = function () { + addGraphHandler.ChangedType(); + }; + } +} + +AddGraphHandler.prototype.ChangedType = function() +{ + var enumVertexsText = document.getElementById("enumVertexsText"); + + this.app.SetEnumVerticesType(enumVertexsText.options[enumVertexsText.selectedIndex].value); +} diff --git a/script/features/algorithm_handler/index.js b/script/features/algorithm_handler/index.js new file mode 100644 index 0000000..222267d --- /dev/null +++ b/script/features/algorithm_handler/index.js @@ -0,0 +1,131 @@ +doInclude ([ + include ("features/base_handler/index.js") +]) + +/** + * Algorithm Graph handler. + * + */ +function AlgorithmGraphHandler(app, algorithm) +{ + BaseHandler.apply(this, arguments); + this.algorithm = algorithm; + this.SaveUpText(); + + this.UpdateResultAndMessage(); +} + +// inheritance. +AlgorithmGraphHandler.prototype = Object.create(BaseHandler.prototype); + +// Rest this handler. +AlgorithmGraphHandler.prototype.MouseMove = function(pos) {} + +AlgorithmGraphHandler.prototype.MouseDown = function(pos) +{ + this.app.setRenderPath([]); + + if (this.algorithm.instance()) + { + this.app.SetDefaultHandler(); + } + else + { + var selectedObject = this.GetSelectedGraph(pos); + if (selectedObject && (selectedObject instanceof BaseVertex)) + { + if (this.algorithm.selectVertex(selectedObject)) + { + this.needRedraw = true; + } + + this.UpdateResultAndMessage(); + } + else if (selectedObject && (selectedObject instanceof BaseEdge)) + { + if (this.algorithm.selectEdge(selectedObject)) + { + this.needRedraw = true; + } + + this.UpdateResultAndMessage(); + } + else + { + if (this.algorithm.deselectAll()) + { + this.needRedraw = true; + this.UpdateResultAndMessage(); + } + } + } +} + +AlgorithmGraphHandler.prototype.MouseUp = function(pos) {} + +AlgorithmGraphHandler.prototype.GetSelectedGroup = function(object) +{ + return this.algorithm.getObjectSelectedGroup(object); +} + +AlgorithmGraphHandler.prototype.RestoreAll = function() +{ + this.app.setRenderPath([]); + + if (this.algorithm.needRestoreUpText()) + { + this.RestoreUpText(); + } + + if (this.algorithm.wantRestore()) + { + this.algorithm.restore(); + } +} + +AlgorithmGraphHandler.prototype.SaveUpText = function() +{ + this.vertexUpText = {}; + var graph = this.app.graph; + for (i = 0; i < graph.vertices.length; i ++) + { + this.vertexUpText[graph.vertices[i].id] = graph.vertices[i].upText; + } +} + +AlgorithmGraphHandler.prototype.RestoreUpText = function() +{ + var graph = this.app.graph; + + for (i = 0; i < graph.vertices.length; i ++) + { + if (graph.vertices[i].id in this.vertexUpText) + { + graph.vertices[i].upText = this.vertexUpText[graph.vertices[i].id]; + } + } +} + +AlgorithmGraphHandler.prototype.UpdateResultAndMessage = function() +{ + var self = this; + result = this.algorithm.result(function (result) + { + self.message = self.algorithm.getMessage(g_language); + self.app.resultCallback(result); + }); + + this.app.resultCallback(result); + + this.message = this.algorithm.getMessage(g_language); +} + +AlgorithmGraphHandler.prototype.InitControls = function() +{ + this.algorithm.messageWasChanged(); +} + +AlgorithmGraphHandler.prototype.GetMessage = function() +{ + return this.algorithm.getMessage(g_language); +} diff --git a/script/features/algorithms/api/index.js b/script/features/algorithms/api/index.js new file mode 100644 index 0000000..3fb8875 --- /dev/null +++ b/script/features/algorithms/api/index.js @@ -0,0 +1,35 @@ +{ +let modulDir = "features/algorithms/"; + +doInclude ([ + include ("model/Algorithms.js", modulDir), + include ("model/BaseTraversal.js", modulDir) +]) + +function loadAsyncAlgorithms(onFinish) { + let pluginsList = ["BFS.js", + "Coloring.js", + "ConnectedComponent.js", + "DFS.js", + "EulerianLoop.js", + "EulerianPath.js", + "FindAllPatches.js", + "FindLongestPath.js", + "FindShortPatchsFromOne.js", + "Floid.js", + "GraphReorder.js", + "HamiltonianLoop.js", + "HamiltonianPath.js", + "IsomorphismCheck.js", + "MaxClique.js", + "MaxFlow.js", + "MinimumSpanningTree.js", + "ModernGraphStyle.js", + "RadiusAndDiameter.js", + "ShortestPath.js", + "VerticesDegree.js"]; + + doIncludeAsync (pluginsList.map((plugin) => include ("model/plugins/" + plugin, modulDir)), onFinish); +} + +} \ No newline at end of file diff --git a/script/Algorithms.js b/script/features/algorithms/model/Algorithms.js similarity index 96% rename from script/Algorithms.js rename to script/features/algorithms/model/Algorithms.js index 76de20c..b4d3a43 100644 --- a/script/Algorithms.js +++ b/script/features/algorithms/model/Algorithms.js @@ -1,305 +1,305 @@ -/** - * File for algorithms. - * - */ - -// Return list of 'vertex = [connected vertices]' -function getVertexToVertexArray(graph, ignoreDirection) -{ - res = {}; - - for (var i = 0; i < graph.edges.length; i ++) - { - edge = graph.edges[i]; - if (!res.hasOwnProperty(edge.vertex1.id)) - { - res[edge.vertex1.id] = []; - } - res[edge.vertex1.id].push(edge.vertex2); - if (!edge.isDirect || ignoreDirection) - { - if (!res.hasOwnProperty(edge.vertex2.id)) - { - res[edge.vertex2.id] = []; - } - - res[edge.vertex2.id].push(edge.vertex1); - } - } - - return res; -} - -// Global array of all algorithms. -var g_Algorithms = []; -var g_AlgorithmIds = []; - -// Call this function to register your factory algorithm. -function RegisterAlgorithm (factory) -{ - g_Algorithms.push(factory); - g_AlgorithmIds.push(factory(null).getId()); -} - -// Base algorithm class. -function BaseAlgorithm (graph, app) -{ - this.graph = graph; - this.app = app; -} - -// @return name of algorithm. For now we supports only 2 locals: "ru" and "en" -BaseAlgorithm.prototype.getName = function(local) -{ - return "unknown_name_" + local; -} - -// @return id of algorithm. Please use format: "your id"."algorithm id". Ex. "OlegSh.ConnectedComponent" -BaseAlgorithm.prototype.getId = function() -{ - return "unknown.unknown"; -} - -// @return message for user. -BaseAlgorithm.prototype.getMessage = function(local) -{ - return "unknown_message_" + local; -} - -// calls when user select vertex. -// @return true if you allow to select this object or false. -BaseAlgorithm.prototype.selectVertex = function(vertex) -{ - return false; -} - -// calls when user select edge. -// @return true if you allow to select this object or false. -BaseAlgorithm.prototype.selectEdge = function(edge) -{ - return false; -} - -// user click to workspace. -// @return true if you allow to deselect all -BaseAlgorithm.prototype.deselectAll = function() -{ - return true; -} - -// get result of algorithm. -// If result if not ready, please return null. -// It will be called after each user action. -// Please return true, if you done. -BaseAlgorithm.prototype.result = function(resultCallback) -{ - return null; -} - -// If you no need to get feedback from user, return true. -// In this case result will calls once. -BaseAlgorithm.prototype.instance = function() -{ - return true; -} - -// @return false, if you change up text and do not want to restore it back. -BaseAlgorithm.prototype.needRestoreUpText = function() -{ - return true; -} - -// @return true, if you change restore graph after use. -BaseAlgorithm.prototype.wantRestore = function() -{ - return false; -} - -// calls this method if wantRestore return true. -BaseAlgorithm.prototype.restore = function() -{ -} - -// @return 0, if object is not selected, in other case return groupe of selection. -BaseAlgorithm.prototype.getObjectSelectedGroup = function(object) -{ - return 0; -} - -// This method is called, when messages was updated on html page. -BaseAlgorithm.prototype.messageWasChanged = function() {} - -// Algorithm priority in menu -BaseAlgorithm.prototype.getPriority = function() -{ - return 0; -} - -// Algorithm support multi graph -BaseAlgorithm.prototype.IsSupportMultiGraph = function() -{ - return false; -} - -BaseAlgorithm.prototype.getCategory = function() -{ - return 0; -} - -/** - * Default handler. - * Select using mouse, drag. - * - */ -function BaseAlgorithmEx(graph, app) -{ - BaseAlgorithm.apply(this, arguments); -} - -// inheritance. -BaseAlgorithmEx.prototype = Object.create(BaseAlgorithm.prototype); - -BaseAlgorithmEx.prototype.CalculateAlgorithm = function(algorithmName, otherParams, resultCallback, ignoreSeparateNodes = false) -{ - if (location.hostname === "localhost" || location.hostname === "127.0.0.1") - console.log(algorithmName + " " + otherParams); - - var graph = this.graph; - var ignoreNodes = {}; - - if (ignoreSeparateNodes) - for (var i = 0; i < graph.vertices.length; i++) - if (!graph.HasConnectedNodes(graph.vertices[i])) - ignoreNodes[graph.vertices[i].id] = 1; - - var creator = new GraphMLCreator(graph.vertices, graph.edges, ignoreNodes); - var pathObjects = []; - var properties = {}; - var result = []; - - var xml = creator.GetXMLString(); - console.log(xml); - - var processResult = function (msg) { - console.log(msg); - $('#debug').text(msg); - xmlDoc = $.parseXML( msg ); - var $xml = $( xmlDoc ); - - $results = $xml.find( "result" ); - - $results.each(function(){ - $values = $(this).find( "value" ); - - $values.each(function(){ - var type = $(this).attr('type'); - var value = $(this).text(); - var res = {}; - res.type = type; - res.value = value; - result.push(res); - }); - }); - - $nodes = $xml.find( "node" ); - - $nodes.each(function(){ - var id = $(this).attr('id'); - $data = $(this).find("data"); - $data.each(function(){ - if ("hightlightNode" == $(this).attr('key') && $(this).text() == "1") - { - pathObjects.push(graph.FindVertex(id)); - } - else - { - if (!properties[id]) - { - properties[id] = {}; - } - properties[id][$(this).attr('key')] = $(this).text(); - } - }); - }); - - $edges = $xml.find( "edge" ); - - $edges.each(function(){ - var source = $(this).attr('source'); - var target = $(this).attr('target'); - var edge = graph.FindEdge(source, target); - if (typeof $(this).attr('id') !== 'undefined') - { - edge = graph.FindEdgeById($(this).attr('id')); - } - pathObjects.push(edge); - - $data = $(this).find("data"); - $data.each(function(){ - if (!properties[edge.id]) - { - properties[edge.id] = {}; - } - properties[edge.id][$(this).attr('key')] = $(this).text(); - }); - }); - - console.log(result); - - resultCallback(pathObjects, properties, result); - }; - - if (this.app.isSupportEmscripten()) { - console.log("Use Emscripten"); - var delimiter = ""; - var processData = algorithmName + delimiter + xml + - delimiter + "report" + delimiter + "xml"; - otherParams.forEach ( (param) => processData += delimiter + param.name + delimiter + param.value); - var res = this.app.processEmscripten(processData); - processResult(res); - } else { - console.log("Use new CGI"); - var queryString = algorithmName + "=cgiInput&report=xml"; - otherParams.forEach ( (param) => queryString += "&" + param.name + "=" + param.value); - $.ajax({ - type: "POST", - url: "/" + SiteDir + "cgi-bin/GraphCGI.exe?" + queryString, - data: xml, - dataType: "text", - }) - .done(function( msg ) - { - processResult(msg); - }); - } - - return true; -} - -BaseAlgorithmEx.prototype.GetNodesPath = function(array, start, count) -{ - var res = []; - for (var index = start; index < start + count; index++) - { - if (array[index].type == 4) - { - res.push(array[index].value); - } - } - return res; -} - -BaseAlgorithmEx.prototype.GetNodesEdgesPath = function(array, start, count) -{ - var res = []; - for (var index = start; index < start + count; index++) - { - if (array[index].type == 4 || array[index].type == 5) - { - res.push(array[index].value); - } - } - return res; -} - - +/** + * File for algorithms. + * + */ + +// Return list of 'vertex = [connected vertices]' +function getVertexToVertexArray(graph, ignoreDirection) +{ + res = {}; + + for (var i = 0; i < graph.edges.length; i ++) + { + edge = graph.edges[i]; + if (!res.hasOwnProperty(edge.vertex1.id)) + { + res[edge.vertex1.id] = []; + } + res[edge.vertex1.id].push(edge.vertex2); + if (!edge.isDirect || ignoreDirection) + { + if (!res.hasOwnProperty(edge.vertex2.id)) + { + res[edge.vertex2.id] = []; + } + + res[edge.vertex2.id].push(edge.vertex1); + } + } + + return res; +} + +// Global array of all algorithms. +var g_Algorithms = []; +var g_AlgorithmIds = []; + +// Call this function to register your factory algorithm. +function RegisterAlgorithm (factory) +{ + g_Algorithms.push(factory); + g_AlgorithmIds.push(factory(null).getId()); +} + +// Base algorithm class. +function BaseAlgorithm (graph, app) +{ + this.graph = graph; + this.app = app; +} + +// @return name of algorithm. For now we supports only 2 locals: "ru" and "en" +BaseAlgorithm.prototype.getName = function(local) +{ + return "unknown_name_" + local; +} + +// @return id of algorithm. Please use format: "your id"."algorithm id". Ex. "OlegSh.ConnectedComponent" +BaseAlgorithm.prototype.getId = function() +{ + return "unknown.unknown"; +} + +// @return message for user. +BaseAlgorithm.prototype.getMessage = function(local) +{ + return "unknown_message_" + local; +} + +// calls when user select vertex. +// @return true if you allow to select this object or false. +BaseAlgorithm.prototype.selectVertex = function(vertex) +{ + return false; +} + +// calls when user select edge. +// @return true if you allow to select this object or false. +BaseAlgorithm.prototype.selectEdge = function(edge) +{ + return false; +} + +// user click to workspace. +// @return true if you allow to deselect all +BaseAlgorithm.prototype.deselectAll = function() +{ + return true; +} + +// get result of algorithm. +// If result if not ready, please return null. +// It will be called after each user action. +// Please return true, if you done. +BaseAlgorithm.prototype.result = function(resultCallback) +{ + return null; +} + +// If you no need to get feedback from user, return true. +// In this case result will calls once. +BaseAlgorithm.prototype.instance = function() +{ + return true; +} + +// @return false, if you change up text and do not want to restore it back. +BaseAlgorithm.prototype.needRestoreUpText = function() +{ + return true; +} + +// @return true, if you change restore graph after use. +BaseAlgorithm.prototype.wantRestore = function() +{ + return false; +} + +// calls this method if wantRestore return true. +BaseAlgorithm.prototype.restore = function() +{ +} + +// @return 0, if object is not selected, in other case return groupe of selection. +BaseAlgorithm.prototype.getObjectSelectedGroup = function(object) +{ + return 0; +} + +// This method is called, when messages was updated on html page. +BaseAlgorithm.prototype.messageWasChanged = function() {} + +// Algorithm priority in menu +BaseAlgorithm.prototype.getPriority = function() +{ + return 0; +} + +// Algorithm support multi graph +BaseAlgorithm.prototype.IsSupportMultiGraph = function() +{ + return false; +} + +BaseAlgorithm.prototype.getCategory = function() +{ + return 0; +} + +/** + * Default handler. + * Select using mouse, drag. + * + */ +function BaseAlgorithmEx(graph, app) +{ + BaseAlgorithm.apply(this, arguments); +} + +// inheritance. +BaseAlgorithmEx.prototype = Object.create(BaseAlgorithm.prototype); + +BaseAlgorithmEx.prototype.CalculateAlgorithm = function(algorithmName, otherParams, resultCallback, ignoreSeparateNodes = false) +{ + if (location.hostname === "localhost" || location.hostname === "127.0.0.1") + console.log(algorithmName + " " + otherParams); + + var graph = this.graph; + var ignoreNodes = {}; + + if (ignoreSeparateNodes) + for (var i = 0; i < graph.vertices.length; i++) + if (!graph.HasConnectedNodes(graph.vertices[i])) + ignoreNodes[graph.vertices[i].id] = 1; + + var creator = new GraphMLCreator(graph.vertices, graph.edges, ignoreNodes); + var pathObjects = []; + var properties = {}; + var result = []; + + var xml = creator.GetXMLString(); + console.log(xml); + + var processResult = function (msg) { + console.log(msg); + $('#debug').text(msg); + xmlDoc = $.parseXML( msg ); + var $xml = $( xmlDoc ); + + $results = $xml.find( "result" ); + + $results.each(function(){ + $values = $(this).find( "value" ); + + $values.each(function(){ + var type = $(this).attr('type'); + var value = $(this).text(); + var res = {}; + res.type = type; + res.value = value; + result.push(res); + }); + }); + + $nodes = $xml.find( "node" ); + + $nodes.each(function(){ + var id = $(this).attr('id'); + $data = $(this).find("data"); + $data.each(function(){ + if ("hightlightNode" == $(this).attr('key') && $(this).text() == "1") + { + pathObjects.push(graph.FindVertex(id)); + } + else + { + if (!properties[id]) + { + properties[id] = {}; + } + properties[id][$(this).attr('key')] = $(this).text(); + } + }); + }); + + $edges = $xml.find( "edge" ); + + $edges.each(function(){ + var source = $(this).attr('source'); + var target = $(this).attr('target'); + var edge = graph.FindEdge(source, target); + if (typeof $(this).attr('id') !== 'undefined') + { + edge = graph.FindEdgeById($(this).attr('id')); + } + pathObjects.push(edge); + + $data = $(this).find("data"); + $data.each(function(){ + if (!properties[edge.id]) + { + properties[edge.id] = {}; + } + properties[edge.id][$(this).attr('key')] = $(this).text(); + }); + }); + + console.log(result); + + resultCallback(pathObjects, properties, result); + }; + + if (this.app.isSupportEmscripten()) { + console.log("Use Emscripten"); + var delimiter = ""; + var processData = algorithmName + delimiter + xml + + delimiter + "report" + delimiter + "xml"; + otherParams.forEach ( (param) => processData += delimiter + param.name + delimiter + param.value); + var res = this.app.processEmscripten(processData); + processResult(res); + } else { + console.log("Use new CGI"); + var queryString = algorithmName + "=cgiInput&report=xml"; + otherParams.forEach ( (param) => queryString += "&" + param.name + "=" + param.value); + $.ajax({ + type: "POST", + url: "/" + SiteDir + "cgi-bin/GraphCGI.exe?" + queryString, + data: xml, + dataType: "text", + }) + .done(function( msg ) + { + processResult(msg); + }); + } + + return true; +} + +BaseAlgorithmEx.prototype.GetNodesPath = function(array, start, count) +{ + var res = []; + for (var index = start; index < start + count; index++) + { + if (array[index].type == 4) + { + res.push(array[index].value); + } + } + return res; +} + +BaseAlgorithmEx.prototype.GetNodesEdgesPath = function(array, start, count) +{ + var res = []; + for (var index = start; index < start + count; index++) + { + if (array[index].type == 4 || array[index].type == 5) + { + res.push(array[index].value); + } + } + return res; +} + + diff --git a/script/BaseTraversal.js b/script/features/algorithms/model/BaseTraversal.js old mode 100755 new mode 100644 similarity index 100% rename from script/BaseTraversal.js rename to script/features/algorithms/model/BaseTraversal.js diff --git a/script/plugins/BFS.js b/script/features/algorithms/model/plugins/BFS.js old mode 100755 new mode 100644 similarity index 100% rename from script/plugins/BFS.js rename to script/features/algorithms/model/plugins/BFS.js diff --git a/script/plugins/Coloring.js b/script/features/algorithms/model/plugins/Coloring.js old mode 100755 new mode 100644 similarity index 100% rename from script/plugins/Coloring.js rename to script/features/algorithms/model/plugins/Coloring.js diff --git a/script/plugins/ConnectedComponent.js b/script/features/algorithms/model/plugins/ConnectedComponent.js old mode 100755 new mode 100644 similarity index 100% rename from script/plugins/ConnectedComponent.js rename to script/features/algorithms/model/plugins/ConnectedComponent.js diff --git a/script/plugins/DFS.js b/script/features/algorithms/model/plugins/DFS.js old mode 100755 new mode 100644 similarity index 100% rename from script/plugins/DFS.js rename to script/features/algorithms/model/plugins/DFS.js diff --git a/script/plugins/EulerianLoop.js b/script/features/algorithms/model/plugins/EulerianLoop.js old mode 100755 new mode 100644 similarity index 100% rename from script/plugins/EulerianLoop.js rename to script/features/algorithms/model/plugins/EulerianLoop.js diff --git a/script/plugins/EulerianPath.js b/script/features/algorithms/model/plugins/EulerianPath.js old mode 100755 new mode 100644 similarity index 100% rename from script/plugins/EulerianPath.js rename to script/features/algorithms/model/plugins/EulerianPath.js diff --git a/script/plugins/FindAllPatches.js b/script/features/algorithms/model/plugins/FindAllPatches.js similarity index 100% rename from script/plugins/FindAllPatches.js rename to script/features/algorithms/model/plugins/FindAllPatches.js diff --git a/script/plugins/FindLongestPath.js b/script/features/algorithms/model/plugins/FindLongestPath.js similarity index 100% rename from script/plugins/FindLongestPath.js rename to script/features/algorithms/model/plugins/FindLongestPath.js diff --git a/script/plugins/FindShortPatchsFromOne.js b/script/features/algorithms/model/plugins/FindShortPatchsFromOne.js similarity index 100% rename from script/plugins/FindShortPatchsFromOne.js rename to script/features/algorithms/model/plugins/FindShortPatchsFromOne.js diff --git a/script/plugins/Floid.js b/script/features/algorithms/model/plugins/Floid.js old mode 100755 new mode 100644 similarity index 100% rename from script/plugins/Floid.js rename to script/features/algorithms/model/plugins/Floid.js diff --git a/script/plugins/GraphReorder.js b/script/features/algorithms/model/plugins/GraphReorder.js old mode 100755 new mode 100644 similarity index 100% rename from script/plugins/GraphReorder.js rename to script/features/algorithms/model/plugins/GraphReorder.js diff --git a/script/plugins/HamiltonianLoop.js b/script/features/algorithms/model/plugins/HamiltonianLoop.js old mode 100755 new mode 100644 similarity index 100% rename from script/plugins/HamiltonianLoop.js rename to script/features/algorithms/model/plugins/HamiltonianLoop.js diff --git a/script/plugins/HamiltonianPath.js b/script/features/algorithms/model/plugins/HamiltonianPath.js old mode 100755 new mode 100644 similarity index 100% rename from script/plugins/HamiltonianPath.js rename to script/features/algorithms/model/plugins/HamiltonianPath.js diff --git a/script/plugins/IsomorphismCheck.js b/script/features/algorithms/model/plugins/IsomorphismCheck.js similarity index 100% rename from script/plugins/IsomorphismCheck.js rename to script/features/algorithms/model/plugins/IsomorphismCheck.js diff --git a/script/plugins/MaxClique.js b/script/features/algorithms/model/plugins/MaxClique.js similarity index 100% rename from script/plugins/MaxClique.js rename to script/features/algorithms/model/plugins/MaxClique.js diff --git a/script/plugins/MaxFlow.js b/script/features/algorithms/model/plugins/MaxFlow.js old mode 100755 new mode 100644 similarity index 100% rename from script/plugins/MaxFlow.js rename to script/features/algorithms/model/plugins/MaxFlow.js diff --git a/script/plugins/MinimumSpanningTree.js b/script/features/algorithms/model/plugins/MinimumSpanningTree.js old mode 100755 new mode 100644 similarity index 100% rename from script/plugins/MinimumSpanningTree.js rename to script/features/algorithms/model/plugins/MinimumSpanningTree.js diff --git a/script/plugins/ModernGraphStyle.js b/script/features/algorithms/model/plugins/ModernGraphStyle.js old mode 100755 new mode 100644 similarity index 100% rename from script/plugins/ModernGraphStyle.js rename to script/features/algorithms/model/plugins/ModernGraphStyle.js diff --git a/script/plugins/RadiusAndDiameter.js b/script/features/algorithms/model/plugins/RadiusAndDiameter.js old mode 100755 new mode 100644 similarity index 100% rename from script/plugins/RadiusAndDiameter.js rename to script/features/algorithms/model/plugins/RadiusAndDiameter.js diff --git a/script/plugins/ShortestPath.js b/script/features/algorithms/model/plugins/ShortestPath.js old mode 100755 new mode 100644 similarity index 100% rename from script/plugins/ShortestPath.js rename to script/features/algorithms/model/plugins/ShortestPath.js diff --git a/script/plugins/VerticesDegree.js b/script/features/algorithms/model/plugins/VerticesDegree.js old mode 100755 new mode 100644 similarity index 100% rename from script/plugins/VerticesDegree.js rename to script/features/algorithms/model/plugins/VerticesDegree.js diff --git a/script/plugins/disable/NeedAlgorithm.js b/script/features/algorithms/model/plugins/disable/NeedAlgorithm.js similarity index 100% rename from script/plugins/disable/NeedAlgorithm.js rename to script/features/algorithms/model/plugins/disable/NeedAlgorithm.js diff --git a/script/features/base_handler/index.js b/script/features/base_handler/index.js new file mode 100644 index 0000000..7fe5224 --- /dev/null +++ b/script/features/base_handler/index.js @@ -0,0 +1,457 @@ +/** + * Base Handler. + * + */ +function BaseHandler(app) +{ + this.app = app; + this.app.setRenderPath([]); + + if (this.removeStack) { + this.removeContextMenu(); + } + this.contextMenuObject = null; + this.contextMenuPoint = null; + //this.app.ClearUndoStack(); +} + +// Need redraw or nor. +BaseHandler.prototype.needRedraw = false; +BaseHandler.prototype.objects = []; +BaseHandler.prototype.message = ""; + + +BaseHandler.prototype.IsNeedRedraw = function(object) +{ + return this.needRedraw; +} + +BaseHandler.prototype.RestRedraw = function(object) +{ + this.needRedraw = false; +} + +BaseHandler.prototype.SetObjects = function(objects) +{ + this.objects = objects; +} + +BaseHandler.prototype.GetSelectedGraph = function(pos) +{ + // Selected Graph. + var res = null; + for (var i = 0; i < this.app.graph.vertices.length; i ++) + { + if (this.app.graph.vertices[i].HitTest(pos)) + { + // Select last of them. + res = this.app.graph.vertices[i]; + } + } + + + return res; +} + +BaseHandler.prototype.GetSelectedArc = function(pos) +{ + // Selected Arc. + for (var i = 0; i < this.app.graph.edges.length; i ++) + { + var edge = this.app.graph.edges[i]; + + if (edge.HitTest(new Point(pos.x, pos.y))) + return edge; + } + + return null; +} + +BaseHandler.prototype.GetSelectedObject = function(pos) +{ + var graphObject = this.GetSelectedGraph(pos); + if (graphObject) + { + return graphObject; + } + + var arcObject = this.GetSelectedArc(pos); + if (arcObject) + { + return arcObject; + } + + return null; +} + + +BaseHandler.prototype.GetUpText = function(object) +{ + return ""; +} + + +BaseHandler.prototype.GetMessage = function() +{ + return this.message; +} + + +BaseHandler.prototype.MouseMove = function(pos) {} + +BaseHandler.prototype.MouseDown = function(pos) {} + +BaseHandler.prototype.MouseUp = function(pos) {} + +BaseHandler.prototype.GetSelectedGroup = function(object) +{ + return 0; +} + +BaseHandler.prototype.InitControls = function() +{ + var vertex1Text = document.getElementById("Vertex1"); + if (vertex1Text) + { + var handler = this; + vertex1Text.onchange = function () { + for (var i = 0; i < handler.app.graph.vertices.length; i++) + { + if (handler.app.graph.vertices[i].mainText == vertex1Text.value) + { + handler.SelectFirstVertexMenu(vertex1Text, handler.app.graph.vertices[i]); + userAction("selectVertex1_menu"); + break; + } + } + }; + + this.UpdateFirstVertexMenu(vertex1Text); + } + + var vertex2Text = document.getElementById("Vertex2"); + if (vertex2Text) + { + var handler = this; + vertex2Text.onchange = function () { + for (var i = 0; i < handler.app.graph.vertices.length; i++) + { + if (handler.app.graph.vertices[i].mainText == vertex2Text.value) + { + handler.SelectSecondVertexMenu(vertex2Text, handler.app.graph.vertices[i]); + userAction("selectVertex2_menu"); + break; + } + } + }; + + this.UpdateSecondVertexMenu(vertex2Text); + } +} + +BaseHandler.prototype.GetNodesPath = function(array, start, count) +{ + var res = []; + for (var index = start; index < start + count; index++) + { + res.push(this.app.graph.FindVertex(array[index].value)); + } + return res; +} + +BaseHandler.prototype.RestoreAll = function() +{ +} + +BaseHandler.prototype.GetSelectVertexMenu = function(menuName) +{ + var res = "" + + ""; + + for (var i = 0; i < this.app.graph.vertices.length; i++) + { + res = res + ""; +} + +BaseHandler.prototype.GetSelect2VertexMenu = function() +{ + return "" + + this.GetSelectVertexMenu("Vertex1") + " → " + this.GetSelectVertexMenu("Vertex2") + ""; +} + +BaseHandler.prototype.SelectFirstVertexMenu = function(vertex1Text, vertex) +{} + +BaseHandler.prototype.UpdateFirstVertexMenu = function() +{} + +BaseHandler.prototype.SelectSecondVertexMenu = function(vertex2Text, vertex) +{} + +BaseHandler.prototype.UpdateSecondVertexMenu = function() +{} + +BaseHandler.prototype.GetSelectedVertex = function() +{ + return null; +} + +BaseHandler.prototype.addContextMenu = function() +{ + var $contextMenu = $("#contextMenu"); + + var handler = this; + + $("#Context_Delete").click(function() { + if (handler.contextMenuObject != null) { + handler.app.PushToStack("DeleteObject"); + handler.app.DeleteObject(handler.contextMenuObject); + handler.app.redrawGraph(); + userAction("DeleteObject_contextMenu"); + } + }); + + $("#Context_Rename").click(function() { + if (handler.contextMenuObject != null) { + var callback = function (enumType) { + handler.RenameVertex(enumType.GetVertexText(0), handler.contextMenuObject); + userAction("RenameVertex_contextMenu"); + }; + var customEnum = new TextEnumVerticesCustom(handler.app); + customEnum.ShowDialog(callback, g_rename, g_renameVertex, handler.contextMenuObject.mainText); + } + }); + + $("#Context_Connect").click(function() { + if (handler.contextMenuObject != null && handler.GetSelectedVertex() != null) { + var addFunc = function(firstVertex, secondVertex, direct) { + handler.app.CreateNewArc(firstVertex, secondVertex, direct, + document.getElementById('EdgeWeight').value, + $("#RadiosReplaceEdge").prop("checked"), + document.getElementById('EdgeLable').value); + handler.app.redrawGraph(); + } + handler.ShowCreateEdgeDialog(handler.GetSelectedVertex(), handler.contextMenuObject, addFunc); + } + }); + + $("#Context_Delete_Edge").click(function() { + if (handler.contextMenuObject != null) { + handler.app.PushToStack("DeleteObject"); + handler.app.DeleteObject(handler.contextMenuObject); + handler.app.redrawGraph(); + userAction("DeleteObject_contextMenu"); + } + }); + + $("#Context_Edit_Edge").click(function() { + if (handler.contextMenuObject != null) { + handler.ShowEditEdgeDialog(handler.contextMenuObject); + } + }); + + $("#Context_Add_Vertex").click(function() { + handler.app.PushToStack("Add"); + handler.app.CreateNewGraph(handler.contextMenuPoint.x, handler.contextMenuPoint.y); + handler.app.redrawGraph(); + }); + + $("#Context_Back_Color").click(function() { + var setupBackgroundStyle = new SetupBackgroundStyle(handler.app); + setupBackgroundStyle.show(); + }); + + $("body").on("contextmenu", "canvas", function(e) { + handler.contextMenuPoint = handler.app.getMousePos(handler.app.canvas, e); + handler.contextMenuObject = handler.GetSelectedObject(handler.contextMenuPoint); + if (handler.contextMenuObject instanceof BaseVertex) { + $("#edgeContextMenu").hide(); + $("#backgroundContextMenu").hide(); + $("#vertexContextMenu").show(); + if (handler.GetSelectedVertex() == null) { + $("#Context_Connect").hide(); + } else { + $("#Context_Connect").show(); + } + } else if (handler.contextMenuObject instanceof BaseEdge) { + $("#vertexContextMenu").hide(); + $("#backgroundContextMenu").hide(); + $("#edgeContextMenu").show(); + } else { + $("#vertexContextMenu").hide(); + $("#edgeContextMenu").hide(); + $("#backgroundContextMenu").show(); + } + + $contextMenu.css({ + display: "block", + left: e.offsetX, + top: e.offsetY + }); + return false; + }); + + $("body").click(function() { + $contextMenu.hide(); + }); +} + +BaseHandler.prototype.removeContextMenu = function() +{ + $("body").off("contextmenu"); + $("#Context_Delete").off("click"); + $("#Context_Rename").off("click"); + $("#Context_Connect").off("click"); + $("#Context_Delete_Edge").off("click"); + $("#Context_Edit_Edge").off("click"); + $("#Context_Add_Vertex").off("click"); + $("#Context_Back_Color").off("click"); +} + +BaseHandler.prototype.RenameVertex = function(text, object) +{ + if (object != null && (object instanceof BaseVertex)) + { + this.app.PushToStack("RenameVertex"); + object.mainText = text; + this.app.redrawGraph(); + } +} + +BaseHandler.prototype.ShowCreateEdgeDialog = function(firstVertex, secondVertex, addEdgeCallBack) { + if (!this.app.graph.isMulti()) + { + var hasEdge = this.app.graph.FindEdgeAny(firstVertex.id, secondVertex.id); + var hasReverseEdge = this.app.graph.FindEdgeAny(secondVertex.id, firstVertex.id); + + if (hasEdge == null && hasReverseEdge == null) + { + $("#RadiosReplaceEdge").prop("checked", true); + $("#NewEdgeAction" ).hide(); + } + else { + $( "#NewEdgeAction" ).show(); + } + } + else + { + $("#RadiosAddEdge").prop("checked", true); + $("#NewEdgeAction" ).hide(); + } + + var dialogButtons = {}; + var handler = this; + + $("#CheckSaveDefaultEdge").prop("checked", false); + $("#defaultEdgeDialogBlock").show(); + + dialogButtons[g_orintEdge] = function() { + handler.app.PushToStack("Connect"); + addEdgeCallBack(firstVertex, secondVertex, true); + //handler.AddNewEdge(selectedObject, true); + $( this ).dialog( "close" ); + }; + dialogButtons[g_notOrintEdge] = function() { + handler.app.PushToStack("Connect"); + addEdgeCallBack(firstVertex, secondVertex, false); + //handler.AddNewEdge(selectedObject, false); + $( this ).dialog( "close" ); + }; + + var edgePresets = this.app.GetEdgePresets(); + var presetsStr = "" + g_DefaultWeightPreset + ""; + + for(var i = 0; i < edgePresets.length; i ++) + { + var edgePreset = edgePresets[i]; + presetsStr += "" + edgePreset + ""; + } + document.getElementById("EdgesPresets").innerHTML = presetsStr; + document.getElementById('EdgeLable').value = ""; + + $( "#addEdge" ).dialog({ + resizable: false, + height: "auto", + width: "auto", + modal: true, + title: g_addEdge, + buttons: dialogButtons, + dialogClass: 'EdgeDialog', + open: function () { + $(this).off('submit').on('submit', function () { + return false; + }); + + // Focues weight + setTimeout(function(){ + const weightInput = document.getElementById('EdgeWeight'); + if(weightInput) + { + weightInput.focus(); + weightInput.select(); + } + },0); + } + }); +} + +BaseHandler.prototype.ShowEditEdgeDialog = function(edgeObject) { + var dialogButtons = {}; + + var handler = this; + + dialogButtons[g_save] = function() { + handler.app.PushToStack("ChangeEdge"); + + edgeObject.SetWeight(document.getElementById('EdgeWeight').value); + edgeObject.SetUpText(document.getElementById('EdgeLable').value); + + handler.needRedraw = true; + handler.app.redrawGraph(); + + userAction("ChangeWeight"); + $( this ).dialog( "close" ); + }; + + document.getElementById('EdgeWeight').value = edgeObject.useWeight ? edgeObject.weight : g_noWeight; + document.getElementById('EdgeWeightSlider').value = edgeObject.useWeight ? edgeObject.weight : 0; + + var edgePresets = handler.app.GetEdgePresets(); + var presetsStr = "" + g_DefaultWeightPreset + ""; + + for(var i = 0; i < edgePresets.length; i ++) + { + var edgePreset = edgePresets[i]; + presetsStr += "" + edgePreset + ""; + } + document.getElementById("EdgesPresets").innerHTML = presetsStr; + document.getElementById('EdgeLable').value = edgeObject.upText; + + $("#CheckSaveDefaultEdge").prop("checked", false); + + $("#defaultEdgeDialogBlock").hide(); + + $( "#addEdge" ).dialog({ + resizable: false, + height: "auto", + width: "auto", + modal: true, + title: g_editWeight, + buttons: dialogButtons, + dialogClass: 'EdgeDialog', + open: function () { + $(handler).off('submit').on('submit', function () { + return false; + }); + } + }); +} diff --git a/script/features/connect_vertices_handler/index.js b/script/features/connect_vertices_handler/index.js new file mode 100644 index 0000000..198c994 --- /dev/null +++ b/script/features/connect_vertices_handler/index.js @@ -0,0 +1,226 @@ + +doInclude ([ + include ("features/base_handler/index.js") +]) + +/** + * Connection Graph handler. + * + */ +function ConnectionGraphHandler(app) +{ + this.removeStack = true; + BaseHandler.apply(this, arguments); + this.SelectFirst(); + this.addContextMenu(); +} + +// inheritance. +ConnectionGraphHandler.prototype = Object.create(BaseHandler.prototype); +// First selected. +ConnectionGraphHandler.prototype.firstObject = null; + +ConnectionGraphHandler.prototype.GetSelectedVertex = function() +{ + return (this.firstObject instanceof BaseVertex) ? this.firstObject : null; +} + +ConnectionGraphHandler.prototype.AddNewEdge = function(selectedObject, isDirect) +{ + let newEdge = this.app.CreateNewArc(this.firstObject, selectedObject, isDirect, + document.getElementById('EdgeWeight').value, + $("#RadiosReplaceEdge").prop("checked"), + document.getElementById('EdgeLable').value); + + if ($("#CheckSaveDefaultEdge").prop("checked")) { + let defaultEdge = new BaseEdge(); + defaultEdge.copyFrom(this.app.graph.edges[newEdge]); + this.app.setDefaultEdge(defaultEdge); + } + + this.SelectFirst(); + this.app.NeedRedraw(); +} + +ConnectionGraphHandler.prototype.AddDefaultEdge = function(selectedObject) +{ + let defaultEdge = this.app.getDefaultEdge(); + let newEdge = this.app.CreateNewArc(this.firstObject, selectedObject, defaultEdge.isDirect, + defaultEdge.weight, + false, + defaultEdge.upText); + this.app.graph.edges[newEdge].useWeight = defaultEdge.useWeight; + + this.SelectFirst(); + this.app.NeedRedraw(); + + userAction("CreateDefaultEdge"); +} + +ConnectionGraphHandler.prototype.SelectVertex = function(selectedObject) +{ + if (this.firstObject) + { + var direct = false; + var handler = this; + + if (!this.app.hasDefaultEdge() || !document.getElementById('useDefaultEdge').checked) { + this.ShowCreateEdgeDialog(this.firstObject, selectedObject, function (firstVertex, secondVertex, direct) { + handler.AddNewEdge(secondVertex, direct); + }); + } else { + handler.AddDefaultEdge(selectedObject); + } + } + else + { + this.SelectSecond(selectedObject); + } + this.needRedraw = true; +} + +ConnectionGraphHandler.prototype.MouseDown = function(pos) +{ + $('#message').unbind(); + + var selectedObject = this.GetSelectedGraph(pos); + if (selectedObject && (selectedObject instanceof BaseVertex)) + { + this.SelectVertex(selectedObject); + } + else + { + this.SelectFirst(); + this.needRedraw = true; + } +} + +ConnectionGraphHandler.prototype.GetSelectedGroup = function(object) +{ + return (object == this.firstObject) ? 1 : 0; +} + +ConnectionGraphHandler.prototype.SelectFirst = function() +{ + this.firstObject = null; + + this.message = g_selectFirstVertexToConnect + this.GetUseDefaultEdgeCheckBox() + + this.GetSelect2VertexMenu(); + this.message = this.AppendSpecialSctionsButton(this.message); +} + +ConnectionGraphHandler.prototype.SelectSecond = function(selectedObject) +{ + this.firstObject = selectedObject; + this.message = g_selectSecondVertexToConnect + this.GetUseDefaultEdgeCheckBox() + + this.GetSelect2VertexMenu(); + this.message = this.AppendSpecialSctionsButton(this.message); +} + +ConnectionGraphHandler.prototype.SelectFirstVertexMenu = function(vertex1Text, vertex) +{ + this.firstObject = null; + this.SelectVertex(vertex); +} + +ConnectionGraphHandler.prototype.UpdateFirstVertexMenu = function(vertex1Text) +{ + if (this.firstObject) + { + vertex1Text.value = this.firstObject.mainText; + } +} + +ConnectionGraphHandler.prototype.SelectSecondVertexMenu = function(vertex2Text, vertex) +{ + this.SelectVertex(vertex); +} + +ConnectionGraphHandler.prototype.UpdateSecondVertexMenu = function(vertex2Text) +{ + if (this.secondObject) + { + vertex2Text.value = this.secondObject.mainText; + } +} + +ConnectionGraphHandler.prototype.AppendSpecialSctionsButton = function(baseMessage) +{ + let hasEdges = this.app.graph.hasEdges(); + + if (!hasEdges) return baseMessage; + + let hasDirectedEdges = this.app.graph.hasDirectEdge(); + let hasUndirectedEdges = this.app.graph.hasUndirectEdge(); + + let handler = this; + + $('#message').on('click', '#reverseAll', function() { + handler.app.PushToStack("ReverseAllEdges"); + + handler.app.graph.reverseAllEdges(); + handler.app.redrawGraph(); + + userAction("ReverseAllEdges"); + }); + $('#message').on('click', '#makeAllUndirected', function(){ + handler.app.PushToStack("makeAllEdgesUndirected"); + + handler.app.graph.makeAllEdgesUndirected(); + handler.app.redrawGraph(); + + userAction("makeAllEdgesUndirected"); + }); + $('#message').on('click', '#makeAllDirected', function(){ + handler.app.PushToStack("makeAllEdgesDirected"); + + handler.app.graph.makeAllEdgesDirected(); + handler.app.redrawGraph(); + + userAction("makeAllEdgesDirected"); + }); + + return "
" + + " " + + "" + + "
" + baseMessage; +} + +ConnectionGraphHandler.checkUseDefaultEdge = function (elem, app) +{ + app.setUseDefaultEdge(elem.checked); + app.updateMessage(); +}; + +ConnectionGraphHandler.prototype.GetUseDefaultEdgeCheckBox = function() { + if (!this.app.hasDefaultEdge()) { + return ""; + } + + return "
" + + "" + + " " + + "
"; +} + +ConnectionGraphHandler.prototype.InitControls = function() { + BaseHandler.prototype.InitControls.call(this) + + if (!this.app.hasDefaultEdge()) { + return; + } + + let app = this.app; + + $('#useDefaultEdge').unbind(); + $('#useDefaultEdge').change(function() { + app.setUseDefaultEdge(this.checked); + }); + $("#useDefaultEdge").prop("checked", this.app.getUseDefaultEdge()); +} diff --git a/script/features/default_handler/index.js b/script/features/default_handler/index.js new file mode 100644 index 0000000..29b8ffa --- /dev/null +++ b/script/features/default_handler/index.js @@ -0,0 +1,431 @@ + +doInclude ([ + include ("features/base_handler/index.js") +]) + +/** + * Default handler. + * Select using mouse, drag. + * + */ +function DefaultHandler(app) +{ + this.removeStack = true; + BaseHandler.apply(this, arguments); + this.message = g_textsSelectAndMove + " " + g_selectGroupText + "" + " " + g_useContextMenuText + ""; + this.selectedObjects = []; + this.dragObject = null; + this.selectedObject = null; + this.prevPosition = null; + this.groupingSelect = false; + this.selectedLogRect = false; + this.selectedLogCtrl = false; + this.saveUndo = false; + + this.addContextMenu(); +} + +// inheritance. +DefaultHandler.prototype = Object.create(BaseHandler.prototype); +// Is pressed +DefaultHandler.prototype.pressed = false; +// Curve change value. +DefaultHandler.prototype.curveValue = 0.1; + +DefaultHandler.prototype.GetSelectedVertex = function() +{ + return (this.selectedObject instanceof BaseVertex) ? this.selectedObject : null; +} + +DefaultHandler.prototype.MouseMove = function(pos) +{ + if (this.dragObject) + { + if (!this.saveUndo) + { + this.app.PushToStack("Move"); + this.saveUndo = true; + } + + this.dragObject.position.x = pos.x; + this.dragObject.position.y = pos.y; + this.needRedraw = true; + } + else if (this.selectedObjects.length > 0 && this.pressed && !this.groupingSelect) + { + if (!this.saveUndo) + { + this.app.PushToStack("Move"); + this.saveUndo = true; + } + + var offset = (new Point(pos.x, pos.y)).subtract(this.prevPosition); + for (var i = 0; i < this.selectedObjects.length; i ++) + { + var object = this.selectedObjects[i]; + if (object instanceof BaseVertex) + { + object.position = object.position.add(offset); + } + } + this.prevPosition = pos; + this.needRedraw = true; + } + else if (this.pressed) + { + if (this.groupingSelect) + { + // Rect select. + var newPos = new Point(pos.x, pos.y); + this.app.SetSelectionRect(new Rect(newPos.min(this.prevPosition), newPos.max(this.prevPosition))); + this.SelectObjectInRect(this.app.GetSelectionRect()); + this.needRedraw = true; + if (!this.selectedLogRect) + { + userAction("GroupSelected.SelectRect"); + this.selectedLogRect = true; + } + } + else + { + // Move work space + this.app.onCanvasMove((new Point(pos.x, pos.y)).subtract(this.prevPosition).multiply(this.app.canvasScale)); + this.needRedraw = true; + } + } +} + +DefaultHandler.prototype.MouseDown = function(pos) +{ + this.dragObject = null; + var selectedObject = this.GetSelectedObject(pos); + var severalSelect = g_ctrlPressed; + + if (selectedObject == null || (!severalSelect && !this.selectedObjects.includes(selectedObject))) + { + this.selectedObject = null; + this.selectedObjects = []; + this.groupingSelect = g_ctrlPressed; + } + + if ((severalSelect || this.selectedObjects.includes(selectedObject)) && (this.selectedObjects.length > 0 || this.selectedObject != null) && selectedObject != null) + { + if (this.selectedObjects.length == 0) + { + this.selectedObjects.push(this.selectedObject); + this.selectedObject = null; + this.selectedObjects.push(selectedObject); + } + else if (!this.selectedObjects.includes(selectedObject)) + { + this.selectedObjects.push(selectedObject); + } + else if (severalSelect && this.selectedObjects.includes(selectedObject)) + { + var index = this.selectedObjects.indexOf(selectedObject); + this.selectedObjects.splice(index, 1); + } + if (!this.selectedLogCtrl) + { + userAction("GroupSelected.SelectCtrl"); + this.selectedLogCtrl = true; + } + } + else + { + if (selectedObject != null) + { + this.selectedObject = selectedObject; + } + if ((selectedObject instanceof BaseVertex) && selectedObject != null) + { + this.dragObject = selectedObject; + this.message = g_moveCursorForMoving; + } + } + this.needRedraw = true; + this.pressed = true; + this.prevPosition = pos; + this.app.canvas.style.cursor = "move"; +} + +DefaultHandler.prototype.MouseUp = function(pos) +{ + this.saveUndo = false; + this.message = g_textsSelectAndMove + " " + g_selectGroupText + "" + " " + g_useContextMenuText + ""; + this.dragObject = null; + this.pressed = false; + this.app.canvas.style.cursor = "auto"; + + this.app.SetSelectionRect(null); + + this.groupingSelect = false; + if (this.selectedObject != null && (this.selectedObject instanceof BaseVertex)) + { + this.message = g_textsSelectAndMove + + "
" + + "" + + "" + + "
"; + + var handler = this; + var callback = function (enumType) { + handler.RenameVertex(enumType.GetVertexText(0), handler.selectedObject); + userAction("RenameVertex"); + }; + $('#message').unbind(); + $('#message').on('click', '#renameButton', function(){ + var customEnum = new TextEnumVerticesCustom(handler.app); + customEnum.ShowDialog(callback, g_rename, g_renameVertex, handler.selectedObject.mainText); + }); + $('#message').on('click', '#changeCommonStyle', function(){ + var selectedVertices = handler.app.GetSelectedVertices(); + var setupVertexStyle = new SetupVertexStyle(handler.app); + setupVertexStyle.show(0, selectedVertices); + }); + $('#message').on('click', '#changeSelectedStyle', function(){ + var selectedVertices = handler.app.GetSelectedVertices(); + var setupVertexStyle = new SetupVertexStyle(handler.app); + setupVertexStyle.show(1, selectedVertices); + }); + } + else if (this.selectedObject != null && (this.selectedObject instanceof BaseEdge)) + { + this.message = g_textsSelectAndMove + + "" + + " " + g_curveEdge + " " + + "   " + + "
" + + "" + + "" + + "
"; + + var handler = this; + $('#message').unbind(); + $('#message').on('click', '#editEdge', function(){ + handler.ShowEditEdgeDialog(handler.selectedObject); + }); + + $('#message').on('click', '#incCurvel', function(){ + handler.app.PushToStack("ChangeCurvelEdge"); + + handler.selectedObject.model.ChangeCurveValue(DefaultHandler.prototype.curveValue); + handler.needRedraw = true; + handler.app.redrawGraph(); + userAction("Edge.Bend"); + }); + $('#message').on('click', '#decCurvel', function(){ + handler.app.PushToStack("ChangeCurvelEdge"); + + handler.selectedObject.model.ChangeCurveValue(-DefaultHandler.prototype.curveValue); + handler.needRedraw = true; + handler.app.redrawGraph(); + userAction("Edge.Bend"); + }); + $('#message').on('click', '#changeCommonStyle', function(){ + var selectedEdges = handler.app.GetSelectedEdges(); + var setupVertexStyle = new SetupEdgeStyle(handler.app); + setupVertexStyle.show(0, selectedEdges); + }); + $('#message').on('click', '#changeSelectedStyle', function(){ + var selectedEdges = handler.app.GetSelectedEdges(); + var setupVertexStyle = new SetupEdgeStyle(handler.app); + setupVertexStyle.show(1, selectedEdges); + }); + } + else if (this.selectedObjects.length > 0) + { + this.message = g_dragGroupText + " " + g_selectGroupText + ""; + + var hasVertices = false; + var hasEdges = false; + for(var i = 0; i < this.selectedObjects.length; i ++) + { + var object = this.selectedObjects[i]; + if (object instanceof BaseVertex) + { + hasVertices = true; + } + else if (object instanceof BaseEdge) + { + hasEdges = true; + } + } + + this.message = this.message + ""; + + this.message = this.message + + "    " + + "" + + this.message = this.message + + "     " + + "" + + ""; + + var handler = this; + $('#message').unbind(); + + $('#message').on('click', '#DublicateSelected', function(){ + handler.app.PushToStack("DublicateSelection"); + + userAction("GroupSelected.Dublicate"); + + var newSelected = []; + var copyVertex = {}; + + // Copy vertex + for(var i = 0; i < handler.selectedObjects.length; i ++) + { + var object = handler.selectedObjects[i]; + if (object instanceof BaseVertex) + { + var newObject = new BaseVertex() + newObject.copyFrom(object); + newObject.vertexEnumType = null; + handler.app.AddNewVertex(newObject); + var vertex = newObject; + var diameter = (new VertexModel()).diameter; + vertex.position.offset(diameter, diameter); + newSelected.push(vertex); + copyVertex[object.id] = vertex; + } + } + + // Copy edge + for (var i = 0; i < handler.selectedObjects.length; i ++) + { + var object = handler.selectedObjects[i]; + if (object instanceof BaseEdge) + { + var newObject = new BaseEdge() + newObject.copyFrom(object); + + var toNewVertex = false; + if (newObject.vertex1.id in copyVertex) + { + newObject.vertex1 = copyVertex[newObject.vertex1.id]; + toNewVertex = true; + } + if (newObject.vertex2.id in copyVertex) + { + newObject.vertex2 = copyVertex[newObject.vertex2.id]; + toNewVertex = true; + } + + handler.app.AddNewEdge(newObject); + if (!toNewVertex) + { + var neighborEdges = handler.app.graph.getNeighborEdges(newObject); + if (neighborEdges.length >= 1) + { + var curve = handler.app.GetAvailableCurveValue(neighborEdges, newObject); + newObject.model.SetCurveValue(curve); + } + } + newSelected.push(newObject); + } + } + + handler.selectedObjects = newSelected; + handler.needRedraw = true; + handler.app.redrawGraph(); + }); + + $('#message').on('click', '#RemoveSelected', function(){ + handler.app.PushToStack("RemoveSelection"); + + userAction("GroupSelected.Remove"); + + for(var i = 0; i < handler.selectedObjects.length; i ++) + handler.app.DeleteObject(handler.selectedObjects[i]); + handler.selectedObjects = []; + handler.needRedraw = true; + handler.app.redrawGraph(); + handler.message = g_textsSelectAndMove + " " + g_selectGroupText + ""; + }); + + if (hasEdges) { + $('#message').on('click', '#changeCommonStyleEdge', function(){ + var selectedEdges = handler.app.GetSelectedEdges(); + var setupVertexStyle = new SetupEdgeStyle(handler.app); + setupVertexStyle.show(0, selectedEdges); + }); + $('#message').on('click', '#changeSelectedStyleEdge', function(){ + var selectedEdges = handler.app.GetSelectedEdges(); + var setupVertexStyle = new SetupEdgeStyle(handler.app); + setupVertexStyle.show(1, selectedEdges); + }); + } + + if (hasVertices) { + $('#message').on('click', '#changeCommonStyleVertex', function(){ + var selectedVertices = handler.app.GetSelectedVertices(); + var setupVertexStyle = new SetupVertexStyle(handler.app); + setupVertexStyle.show(0, selectedVertices); + }); + $('#message').on('click', '#changeSelectedStyleVertex', function(){ + var selectedVertices = handler.app.GetSelectedVertices(); + var setupVertexStyle = new SetupVertexStyle(handler.app); + setupVertexStyle.show(1, selectedVertices); + }); + } + } + + this.needRedraw = true; +} + +DefaultHandler.prototype.GetSelectedGroup = function(object) +{ + return (object == this.dragObject) || (object == this.selectedObject) ? 1 : 0 || this.selectedObjects.includes(object); +} + +DefaultHandler.prototype.SelectObjectInRect = function (rect) +{ + this.selectedObjects = []; + var vertices = this.app.graph.vertices; + for (var i = 0; i < vertices.length; i ++) + { + if (rect.isIn(vertices[i].position) && !this.selectedObjects.includes(vertices[i])) + this.selectedObjects.push(vertices[i]); + } + + // Selected Arc. + var edges = this.app.graph.edges; + for (var i = 0; i < edges.length; i ++) + { + var edge = edges[i]; + + if (rect.isIn(edge.vertex1.position) && rect.isIn(edge.vertex2.position) && !this.selectedObjects.includes(edge)) + this.selectedObjects.push(edge); + } +} diff --git a/script/features/delete_objects_handler/index.js b/script/features/delete_objects_handler/index.js new file mode 100644 index 0000000..db6ceea --- /dev/null +++ b/script/features/delete_objects_handler/index.js @@ -0,0 +1,52 @@ +doInclude ([ + include ("features/base_handler/index.js") +]) + +/** + * Delete Graph handler. + * + */ +function DeleteGraphHandler(app) +{ + this.removeStack = true; + BaseHandler.apply(this, arguments); + this.message = g_selectObjectToDelete; + this.addContextMenu(); +} + +// inheritance. +DeleteGraphHandler.prototype = Object.create(BaseHandler.prototype); + +DeleteGraphHandler.prototype.MouseDown = function(pos) +{ + var selectedObject = this.GetSelectedObject(pos); + + if (!this.app.IsCorrectObject(selectedObject)) + return; + + this.app.PushToStack("Delete"); + this.app.DeleteObject(selectedObject); + this.needRedraw = true; +} + +/** + * Delete Graph handler. + * + */ +function DeleteAllHandler(app) +{ + BaseHandler.apply(this, arguments); +} + +// inheritance. +DeleteAllHandler.prototype = Object.create(BaseHandler.prototype); + +DeleteAllHandler.prototype.clear = function() +{ + this.app.PushToStack("DeleteAll"); + + // Selected Graph. + this.app.graph = new Graph(); + this.app.savedGraphName = ""; + this.needRedraw = true; +} diff --git a/script/features/draw_graph/api/index.js b/script/features/draw_graph/api/index.js new file mode 100644 index 0000000..2b94a2c --- /dev/null +++ b/script/features/draw_graph/api/index.js @@ -0,0 +1,10 @@ +{ +let modulDir = "features/draw_graph/"; + +doInclude ([ + include ("model/BaseBackgroundDrawer.js", modulDir), + include ("model/BaseEdgeDrawer.js", modulDir), + include ("model/BaseVertexDrawer.js", modulDir) +]) + +} \ No newline at end of file diff --git a/script/BaseBackgroundDrawer.js b/script/features/draw_graph/model/BaseBackgroundDrawer.js similarity index 100% rename from script/BaseBackgroundDrawer.js rename to script/features/draw_graph/model/BaseBackgroundDrawer.js diff --git a/script/BaseEdgeDrawer.js b/script/features/draw_graph/model/BaseEdgeDrawer.js similarity index 100% rename from script/BaseEdgeDrawer.js rename to script/features/draw_graph/model/BaseEdgeDrawer.js diff --git a/script/BaseVertexDrawer.js b/script/features/draw_graph/model/BaseVertexDrawer.js similarity index 100% rename from script/BaseVertexDrawer.js rename to script/features/draw_graph/model/BaseVertexDrawer.js diff --git a/script/EnumVertices.js b/script/features/enum_vertices/EnumVertices.js old mode 100755 new mode 100644 similarity index 95% rename from script/EnumVertices.js rename to script/features/enum_vertices/EnumVertices.js index 7395a98..bb2ac75 --- a/script/EnumVertices.js +++ b/script/features/enum_vertices/EnumVertices.js @@ -1,201 +1,201 @@ -/* - Classes for creating text for vertices. -*/ - - -/** - * Base Enum Vertices. - * - */ -function BaseEnumVertices(app, startNumber) -{ - this.app = app; - this.startNumber = startNumber; -} - -BaseEnumVertices.prototype.GetVertexText = function(id) -{ - return this.startNumber + id; -} - -BaseEnumVertices.prototype.GetVertexTextAsync = function(callback) -{ - callback (this); -} - -BaseEnumVertices.prototype.GetText = function() -{ - return this.startNumber + ", " + (this.startNumber + 1) + ", " + (this.startNumber + 2) + "..."; -} - -BaseEnumVertices.prototype.GetValue = function() -{ - return "Numbers" + this.startNumber; -} - -function TextEnumTitle(app, title) -{ - BaseEnumVertices.apply(this, arguments); - this.pattern = ""; - this.title = title; -} - - -// inheritance. -TextEnumTitle.prototype = Object.create(BaseEnumVertices.prototype); - -TextEnumTitle.prototype.GetVertexText = function(id) -{ - return this.title; -} - - - -/** - * Text Enum - * - */ -function TextEnumVertices(app) -{ - BaseEnumVertices.apply(this, arguments); - this.pattern = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; -} - - -// inheritance. -TextEnumVertices.prototype = Object.create(BaseEnumVertices.prototype); - -TextEnumVertices.prototype.GetVertexText = function(id) -{ - var res = ""; - - res = this.pattern[id % this.pattern.length] + res; - - while (id >= this.pattern.length) - { - id = Math.floor(id / this.pattern.length) - 1; - res = this.pattern[id % this.pattern.length] + res; - } - - return res; -} - - -TextEnumVertices.prototype.GetText = function() -{ - return "A, B, ... Z"; -} - -TextEnumVertices.prototype.GetValue = function() -{ - return "Latin"; -} - -/** - * Text Enum - * - */ -function TextEnumVerticesCyr(app) -{ - TextEnumVertices.apply(this, arguments); - this.pattern = "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"; -} - - -// inheritance. -TextEnumVerticesCyr.prototype = Object.create(TextEnumVertices.prototype); - -TextEnumVerticesCyr.prototype.GetText = function() -{ - return "А, Б, ... Я"; -} - -TextEnumVerticesCyr.prototype.GetValue = function() -{ - return "Cyrillic"; -} - - -/** - * Text Enum - * - */ -function TextEnumVerticesGreek(app) -{ - TextEnumVertices.apply(this, arguments); - this.pattern = "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ"; -} - - -// inheritance. -TextEnumVerticesGreek.prototype = Object.create(TextEnumVertices.prototype); - -TextEnumVerticesGreek.prototype.GetText = function() -{ - return "Α, Β, ... Ω"; -} - -TextEnumVerticesGreek.prototype.GetValue = function() -{ - return "Greek"; -} - -/** - * Text Enum - * - */ -function TextEnumVerticesCustom(app) -{ - BaseEnumVertices.apply(this, arguments); - this.pattern = ""; -} - - - -// inheritance. -TextEnumVerticesCustom.prototype = Object.create(BaseEnumVertices.prototype); - -TextEnumVerticesCustom.prototype.GetText = function() -{ - return g_customEnumVertex; -} - -TextEnumVerticesCustom.prototype.GetValue = function() -{ - return "Custom"; -} - -TextEnumVerticesCustom.prototype.GetVertexTextAsync = function(callback) -{ - this.ShowDialog(callback, g_addVertex, g_addVertex, "A"); -} - - -TextEnumVerticesCustom.prototype.ShowDialog = function(callback, buttonText, titleTitle, title) -{ - var dialogButtons = {}; - app = this.app; - dialogButtons[buttonText] = function() { - app.PushToStack("RenameVertex"); - - callback(new TextEnumTitle(app, $("#VertexTitle").val())); - $( this ).dialog( "close" ); - }; - - $( "#addVertex" ).dialog({ - resizable: false, - height: "auto", - width: "auto", - modal: true, - title: titleTitle, - buttons: dialogButtons, - dialogClass: 'EdgeDialog', - open: function () { - $(this).off('submit').on('submit', function () { - return false; - }); - $("#VertexTitle").val(title); - $("#VertexTitle").focus(); - } - }); -} +/* + Classes for creating text for vertices. +*/ + + +/** + * Base Enum Vertices. + * + */ +function BaseEnumVertices(app, startNumber) +{ + this.app = app; + this.startNumber = startNumber; +} + +BaseEnumVertices.prototype.GetVertexText = function(id) +{ + return this.startNumber + id; +} + +BaseEnumVertices.prototype.GetVertexTextAsync = function(callback) +{ + callback (this); +} + +BaseEnumVertices.prototype.GetText = function() +{ + return this.startNumber + ", " + (this.startNumber + 1) + ", " + (this.startNumber + 2) + "..."; +} + +BaseEnumVertices.prototype.GetValue = function() +{ + return "Numbers" + this.startNumber; +} + +function TextEnumTitle(app, title) +{ + BaseEnumVertices.apply(this, arguments); + this.pattern = ""; + this.title = title; +} + + +// inheritance. +TextEnumTitle.prototype = Object.create(BaseEnumVertices.prototype); + +TextEnumTitle.prototype.GetVertexText = function(id) +{ + return this.title; +} + + + +/** + * Text Enum + * + */ +function TextEnumVertices(app) +{ + BaseEnumVertices.apply(this, arguments); + this.pattern = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +} + + +// inheritance. +TextEnumVertices.prototype = Object.create(BaseEnumVertices.prototype); + +TextEnumVertices.prototype.GetVertexText = function(id) +{ + var res = ""; + + res = this.pattern[id % this.pattern.length] + res; + + while (id >= this.pattern.length) + { + id = Math.floor(id / this.pattern.length) - 1; + res = this.pattern[id % this.pattern.length] + res; + } + + return res; +} + + +TextEnumVertices.prototype.GetText = function() +{ + return "A, B, ... Z"; +} + +TextEnumVertices.prototype.GetValue = function() +{ + return "Latin"; +} + +/** + * Text Enum + * + */ +function TextEnumVerticesCyr(app) +{ + TextEnumVertices.apply(this, arguments); + this.pattern = "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"; +} + + +// inheritance. +TextEnumVerticesCyr.prototype = Object.create(TextEnumVertices.prototype); + +TextEnumVerticesCyr.prototype.GetText = function() +{ + return "А, Б, ... Я"; +} + +TextEnumVerticesCyr.prototype.GetValue = function() +{ + return "Cyrillic"; +} + + +/** + * Text Enum + * + */ +function TextEnumVerticesGreek(app) +{ + TextEnumVertices.apply(this, arguments); + this.pattern = "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ"; +} + + +// inheritance. +TextEnumVerticesGreek.prototype = Object.create(TextEnumVertices.prototype); + +TextEnumVerticesGreek.prototype.GetText = function() +{ + return "Α, Β, ... Ω"; +} + +TextEnumVerticesGreek.prototype.GetValue = function() +{ + return "Greek"; +} + +/** + * Text Enum + * + */ +function TextEnumVerticesCustom(app) +{ + BaseEnumVertices.apply(this, arguments); + this.pattern = ""; +} + + + +// inheritance. +TextEnumVerticesCustom.prototype = Object.create(BaseEnumVertices.prototype); + +TextEnumVerticesCustom.prototype.GetText = function() +{ + return g_customEnumVertex; +} + +TextEnumVerticesCustom.prototype.GetValue = function() +{ + return "Custom"; +} + +TextEnumVerticesCustom.prototype.GetVertexTextAsync = function(callback) +{ + this.ShowDialog(callback, g_addVertex, g_addVertex, "A"); +} + + +TextEnumVerticesCustom.prototype.ShowDialog = function(callback, buttonText, titleTitle, title) +{ + var dialogButtons = {}; + app = this.app; + dialogButtons[buttonText] = function() { + app.PushToStack("RenameVertex"); + + callback(new TextEnumTitle(app, $("#VertexTitle").val())); + $( this ).dialog( "close" ); + }; + + $( "#addVertex" ).dialog({ + resizable: false, + height: "auto", + width: "auto", + modal: true, + title: titleTitle, + buttons: dialogButtons, + dialogClass: 'EdgeDialog', + open: function () { + $(this).off('submit').on('submit', function () { + return false; + }); + $("#VertexTitle").val(title); + $("#VertexTitle").focus(); + } + }); +} diff --git a/script/Graphoffline.Emscripten.js b/script/features/graphoffline/Graphoffline.Emscripten.js similarity index 100% rename from script/Graphoffline.Emscripten.js rename to script/features/graphoffline/Graphoffline.Emscripten.js diff --git a/script/Graphoffline.Emscripten.wasm b/script/features/graphoffline/Graphoffline.Emscripten.wasm similarity index 100% rename from script/Graphoffline.Emscripten.wasm rename to script/features/graphoffline/Graphoffline.Emscripten.wasm diff --git a/script/features/group_rename_handler/index.js b/script/features/group_rename_handler/index.js new file mode 100644 index 0000000..9189a12 --- /dev/null +++ b/script/features/group_rename_handler/index.js @@ -0,0 +1,61 @@ +doInclude ([ + include ("features/base_handler/index.js") +]) + +/** + * Groupe rename vertices. + * + */ +function GroupRenameVertices(app) +{ + BaseHandler.apply(this, arguments); + this.message = ""; +} + +// inheritance. +GroupRenameVertices.prototype = Object.create(BaseHandler.prototype); +// First selected. +GroupRenameVertices.prototype.firstObject = null; +// Path +GroupRenameVertices.prototype.pathObjects = null; + +GroupRenameVertices.prototype.show = function() +{ + var handler = this; + var dialogButtons = {}; + var graph = this.app.graph; + var app = this.app; + + dialogButtons[g_save] = function() { + app.PushToStack("Rename"); + + var titlesList = $( "#VertextTitleList" ).val().split('\n'); + for (i = 0; i < Math.min(graph.vertices.length, titlesList.length); i ++) + { + graph.vertices[i].mainText = titlesList[i]; + } + app.redrawGraph(); + $( this ).dialog( "close" ); + }; + dialogButtons[g_cancel] = function() { + $( this ).dialog( "close" ); + }; + + var titleList = ""; + for (i = 0; i < graph.vertices.length; i ++) + { + titleList = titleList + graph.vertices[i].mainText + "\n"; + } + + $( "#VertextTitleList" ).val(titleList); + + $( "#GroupRenameDialog" ).dialog({ + resizable: false, + height: "auto", + width: "auto", + modal: true, + title: g_groupRename, + buttons: dialogButtons, + dialogClass: 'EdgeDialog' + }); +} diff --git a/script/features/saved_graph_handler/index.js b/script/features/saved_graph_handler/index.js new file mode 100644 index 0000000..891cf9f --- /dev/null +++ b/script/features/saved_graph_handler/index.js @@ -0,0 +1,52 @@ +doInclude ([ + include ("features/base_handler/index.js") +]) + +/** + * Save dialog Graph handler. + * + */ +function SavedDialogGraphHandler(app) +{ + BaseHandler.apply(this, arguments); + this.message = ""; +} + +// inheritance. +SavedDialogGraphHandler.prototype = Object.create(BaseHandler.prototype); +// First selected. +SavedDialogGraphHandler.prototype.firstObject = null; +// Path +SavedDialogGraphHandler.prototype.pathObjects = null; +// Objects. +SavedDialogGraphHandler.prototype.objects = null; + +SavedDialogGraphHandler.prototype.show = function(object) +{ + this.app.SaveGraphOnDisk(); + + var dialogButtons = {}; + + dialogButtons[g_close] = function() { + $( this ).dialog( "close" ); + }; + + document.getElementById('GraphName').value = "http://" + window.location.host + window.location.pathname + + "?graph=" + this.app.GetGraphName(); + + document.getElementById('GraphName').select(); + + document.getElementById("ShareSavedGraph").innerHTML = + document.getElementById("ShareSavedGraph").innerHTML.replace(/graph=([A-Za-z]*)/g, "graph=" + this.app.GetGraphName()); + + $( "#saveDialog" ).dialog({ + resizable: false, + height: "auto", + width: "auto", + modal: true, + title: g_save_dialog, + buttons: dialogButtons, + dialogClass: 'EdgeDialog' + }); + +} diff --git a/script/features/saved_graph_image_handler/index.js b/script/features/saved_graph_image_handler/index.js new file mode 100644 index 0000000..be82aea --- /dev/null +++ b/script/features/saved_graph_image_handler/index.js @@ -0,0 +1,94 @@ +doInclude ([ + include ("features/base_handler/index.js") +]) + +/** + * Save dialog Graph handler. + * + */ +function SavedDialogGraphImageHandler(app) +{ + BaseHandler.apply(this, arguments); + this.message = ""; + this.imageName = ""; +} + +// inheritance. +SavedDialogGraphImageHandler.prototype = Object.create(BaseHandler.prototype); +// First selected. +SavedDialogGraphImageHandler.prototype.firstObject = null; +// Path +SavedDialogGraphImageHandler.prototype.pathObjects = null; +// Objects. +SavedDialogGraphImageHandler.prototype.objects = null; + +SavedDialogGraphImageHandler.prototype.showDialogCallback = function (imageExtension) +{ + var dialogButtons = {}; + + dialogButtons[g_close] = function() { + $( this ).dialog( "close" ); + }; + + var fileLocation = "tmp/saved/" + this.imageName.substr(0, 2) + "/"+ this.imageName + "." + imageExtension + + document.getElementById("showSavedImageGraph").src = "/" + fileLocation; + document.getElementById("showSavedImageGraphRef").href = "/" + fileLocation; + //document.getElementById("showSavedImageGraph").src = document.getElementById("showSavedImageGraph").src.replace(/tmp\/saved\/([A-Za-z]*)\/([A-Za-z]*).png/g, fileLocation); + document.getElementById("ShareSavedImageGraph").innerHTML = + document.getElementById("ShareSavedImageGraph").innerHTML.replace(/tmp\/saved\/([A-Za-z]*)\/([A-Za-z]*).png/g, fileLocation); + + document.getElementById("SaveImageLinks").innerHTML = + document.getElementById("SaveImageLinks").innerHTML.replace(/tmp\/saved\/([A-Za-z]*)\/([A-Za-z]*).png/g, fileLocation); + + $( "#saveImageDialog" ).dialog({ + resizable: false, + height: "auto", + width: "auto", + modal: true, + title: g_save_image_dialog, + buttons: dialogButtons, + dialogClass: 'EdgeDialog' + }); + +} + +SavedDialogGraphImageHandler.prototype.showWorkspace = function() +{ + var object = this; + var callback = function() { + object.showDialogCallback("png"); + }; + + this.imageName = this.app.SaveGraphImageOnDisk(callback); +} + +SavedDialogGraphImageHandler.prototype.showFullgraph = function() +{ + var object = this; + var callback = function() { + object.showDialogCallback("png"); + }; + + this.imageName = this.app.SaveFullGraphImageOnDisk(callback, false); +} + +SavedDialogGraphImageHandler.prototype.showPrint = function() +{ + var object = this; + var callback = function() { + object.showDialogCallback("png"); + }; + + this.imageName = this.app.SaveFullGraphImageOnDisk(callback, true); +} + +SavedDialogGraphImageHandler.prototype.showSvg = function() +{ + var object = this; + var callback = function() { + object.showDialogCallback("svg"); + }; + + this.imageName = this.app.SaveSVGGraphOnDisk(callback); +} diff --git a/script/features/serialization/api/index.js b/script/features/serialization/api/index.js new file mode 100644 index 0000000..a41b9e0 --- /dev/null +++ b/script/features/serialization/api/index.js @@ -0,0 +1,8 @@ +{ +let modulDir = "features/serialization/"; + +doInclude ([ + include ("model/GraphMLCreator.js", modulDir) +]) + +} \ No newline at end of file diff --git a/script/GraphMLCreator.js b/script/features/serialization/model/GraphMLCreator.js similarity index 100% rename from script/GraphMLCreator.js rename to script/features/serialization/model/GraphMLCreator.js diff --git a/script/features/setup_background_style/index.js b/script/features/setup_background_style/index.js new file mode 100644 index 0000000..3511885 --- /dev/null +++ b/script/features/setup_background_style/index.js @@ -0,0 +1,167 @@ +doInclude ([ + include ("features/base_handler/index.js") +]) + +/** + * Setup Background Style rename vertices. + * + */ +function SetupBackgroundStyle(app) +{ + BaseHandler.apply(this, arguments); + this.message = ""; + this.maxImageSize = 2048; +} + +// inheritance. +SetupBackgroundStyle.prototype = Object.create(BaseHandler.prototype); + + +SetupBackgroundStyle.prototype.handleImportBackgroundFile = function(files, updateBackgroundCallback) { + var graphFileToLoad = files[0]; + var re = /(?:\.([^.]+))?$/; + var imageExtension = re.exec(graphFileToLoad.name)[1].toLowerCase(); + + if (!(imageExtension == "png" || imageExtension == "jpg" || imageExtension == "jpeg")) { + $("#UploadBackgroundImageError").html(g_wrongImageFormatPNGAndJPEG); + $("#UploadBackgroundImageError").show(); + return; + } + + let self = this; + var fileReader = new FileReader(); + fileReader.onload = function(fileLoadedEvent){ + var textFromFileLoaded = fileLoadedEvent.target.result; + var image = new Image(); + image.onload = function() { + console.log(this.width + 'x' + this.height); + if (this.width > self.maxImageSize || this.height > self.maxImageSize) { + $("#UploadBackgroundImageError").html(formatString(g_wrongImageSizeP1, [self.maxImageSize])); + $("#UploadBackgroundImageError").show(); + return; + } + updateBackgroundCallback(image); + } + image.src = 'data:image/' + imageExtension + ';base64' + textFromFileLoaded; + ImportBackgroundImage.value = ""; + }; + + fileReader.readAsDataURL(graphFileToLoad); +} + +SetupBackgroundStyle.prototype.show = function() +{ + var handler = this; + var dialogButtons = {}; + var graph = this.app.graph; + var app = this.app; + var style = FullObjectCopy(app.backgroundCommonStyle); + + var fillFields = function() + { + $( "#backgroundColor" ).val(style.commonColor); + $( "#backgroundTransporent" ).val(style.commonOpacity); + } + + var redrawVertex = function() + { + style.commonColor = $( "#backgroundColor" ).val(); + style.commonOpacity = $( "#backgroundTransporent" ).val(); + + var canvas = document.getElementById( "BackgroundPreview" ); + var context = canvas.getContext('2d'); + + context.save(); + let bestScale = 1.0; + if (style.image != null) { + let wScale = canvas.width / style.image.width; + let hScale = canvas.height / style.image.height; + bestScale = Math.min(wScale, hScale); + context.scale(bestScale, bestScale); + } + var backgroundDrawer = new BaseBackgroundDrawer(context); + backgroundDrawer.Draw(style, canvas.width, canvas.height, new Point(0, 0), bestScale); + + context.restore(); + + if (style.image != null) { + $( "#RemoveBackgroundFile" ).show(); + } else { + $( "#RemoveBackgroundFile" ).hide(); + } + } + + var loadFile = function() { + userAction("background_loadFromFile"); + + if (ImportBackgroundImage) { + ImportBackgroundImage.click(); + } + } + + var updateBackgroundImage = function(image) { + style.image = image; + $("#UploadBackgroundImageError").hide(); + redrawVertex(); + } + + var clearBackgroundImage = function() { + style.image = null; + $("#UploadBackgroundImageError").hide(); + redrawVertex(); + } + + dialogButtons[g_default] = + { + text : g_default, + class : "MarginLeft", + click : function() { + + app.PushToStack("ChangeBackground"); + + app.ResetBackgroundStyle(); + app.redrawGraph(); + $( this ).dialog( "close" ); + } + }; + + dialogButtons[g_save] = function() { + app.PushToStack("ChangeBackground"); + app.SetBackgroundStyle(style); + app.redrawGraph(); + $( this ).dialog( "close" ); + }; + dialogButtons[g_cancel] = function() { + $( this ).dialog( "close" ); + }; + + fillFields(); + + $( "#SetupBackgroundStyleDialog" ).dialog({ + resizable: false, + height: "auto", + width: "auto", + modal: true, + title: g_backgroundStyle, + buttons: dialogButtons, + dialogClass: 'EdgeDialog' + }); + + try { + redrawVertex(); + } catch (error) { + console.error(error); + } + + $( "#backgroundColor" ).unbind(); + $( "#backgroundTransporent" ).unbind(); + $( "#LoadBackgroundFile" ).unbind(); + $( "#ImportBackgroundImage" ).unbind(); + $( "#RemoveBackgroundFile" ).unbind(); + + $( "#backgroundColor" ).change(redrawVertex); + $( "#backgroundTransporent" ).change(redrawVertex); + $( "#LoadBackgroundFile" ).click(loadFile); + $( "#ImportBackgroundImage" ).change( function () {handler.handleImportBackgroundFile(this.files, updateBackgroundImage);}); + $( "#RemoveBackgroundFile" ).click(clearBackgroundImage); +} diff --git a/script/features/setup_edge_style/index.js b/script/features/setup_edge_style/index.js new file mode 100644 index 0000000..e324464 --- /dev/null +++ b/script/features/setup_edge_style/index.js @@ -0,0 +1,295 @@ +doInclude ([ + include ("features/base_handler/index.js") +]) + +/** + * Setup Vertex Style rename vertices. + * + */ +function SetupEdgeStyle(app) +{ + BaseHandler.apply(this, arguments); + this.message = ""; +} + +// inheritance. +SetupEdgeStyle.prototype = Object.create(BaseHandler.prototype); + +SetupEdgeStyle.prototype.show = function(index, selectedEdges) +{ + var handler = this; + var dialogButtons = {}; + var graph = this.app.graph; + var app = this.app; + this.forAll = selectedEdges == null; + var forAll = this.forAll; + + var self = this; + + var applyIndex = function(index) + { + self.index = index; + var originStyle = (self.index == 0 ? app.edgeCommonStyle : app.edgeSelectedStyles[self.index - 1]); + if (!forAll) + { + originStyle = selectedEdges[0].getStyleFor(self.index); + } + self.style = FullObjectCopy(originStyle); + } + + applyIndex(index); + + var fillFields = function() + { + var fullStyle = self.style.GetStyle({}, forAll ? undefined : selectedEdges[0]); + + $( "#edgeFillColor" ).val(fullStyle.fillStyle); + $( "#edgeStrokeColor" ).val(fullStyle.strokeStyle); + $( "#edgeTextColor" ).val(fullStyle.weightText); + $( "#edgeStyle" ).val(fullStyle.lineDash); + $( "#edgeWidth" ).val(forAll ? app.GetDefaultEdgeWidth() : selectedEdges[0].model.width); + + $( "#weightEdgeTextColor" ).val(fullStyle.additionalTextColor); + $( "#weightTextPosition" ).val(fullStyle.weightPosition); + + if (self.index > 0 || self.index == "all") + { + $( "#EdgeSelectedIndexForm" ).show(); + $( "#edgeSelectedIndex" ).val(self.index); + } + else + { + $( "#EdgeSelectedIndexForm" ).hide(); + } + + // Fill color presets. + var stylesArray = []; + stylesArray.push(app.edgeCommonStyle); + + for (i = 0; i < app.edgeSelectedStyles.length; i ++) + stylesArray.push(app.edgeSelectedStyles[i]); + + var colorSet = {}; + for (i = 0; i < stylesArray.length; i ++) + { + var style = stylesArray[i]; + if (style.hasOwnProperty('strokeStyle')) + colorSet[style.strokeStyle] = 1; + if (style.hasOwnProperty('fillStyle')) + colorSet[style.fillStyle] = 1; + if (style.hasOwnProperty('additionalTextColor')) + colorSet[style.additionalTextColor] = 1; + } + + $("#edgeFillColorPreset").find('option').remove(); + $("#weightEdgeTextColorPreset").find('option').remove(); + $("#edgeTextColorPreset").find('option').remove(); + $("#edgeStrokeColorPreset").find('option').remove(); + for (const property in colorSet) + { + $("#edgeFillColorPreset").append(new Option(property)); + $("#weightEdgeTextColorPreset").append(new Option(property)); + $("#edgeTextColorPreset").append(new Option(property)); + $("#edgeStrokeColorPreset").append(new Option(property)); + } + } + + var redrawVertex = function() + { + var fullStyle = self.style.GetStyle({}, forAll ? undefined : selectedEdges[0]); + + if (fullStyle.fillStyle != $( "#edgeFillColor" ).val()) + self.style.fillStyle = $( "#edgeFillColor" ).val(); + + if (fullStyle.strokeStyle != $( "#edgeStrokeColor" ).val()) + self.style.strokeStyle = $( "#edgeStrokeColor" ).val(); + + if (fullStyle.weightText != $( "#edgeTextColor" ).val()) + self.style.weightText = $( "#edgeTextColor" ).val(); + + if (fullStyle.lineDash != $( "#edgeStyle" ).val()) + self.style.lineDash = $( "#edgeStyle" ).val(); + + if (fullStyle.additionalTextColor != $( "#weightEdgeTextColor" ).val()) + self.style.additionalTextColor = $( "#weightEdgeTextColor" ).val(); + + if (fullStyle.weightPosition != $( "#weightTextPosition" ).val()) + self.style.weightPosition = $( "#weightTextPosition" ).val(); + + var edgeWidth = parseInt($( "#edgeWidth" ).val()); + + var canvas = document.getElementById( "EdgePreview" ); + var context = canvas.getContext('2d'); + + context.save(); + + var backgroundDrawer = new BaseBackgroundDrawer(context); + backgroundDrawer.Draw(app.backgroundCommonStyle, canvas.width, canvas.height, new Point(0, 0), 1.0); + + var graphDrawer = new BaseEdgeDrawer(context); + var baseVertex1 = new BaseVertex(0, canvas.height / 2, new BaseEnumVertices(this)); + var baseVertex2 = new BaseVertex(canvas.width, canvas.height / 2, new BaseEnumVertices(this)); + + baseVertex1.currentStyle = baseVertex1.getStyleFor(0); + baseVertex2.currentStyle = baseVertex2.getStyleFor(0); + + var baseEdge = new BaseEdge(baseVertex1, baseVertex2, true, 10, "Text"); + + if (!forAll) + baseEdge.ownStyles = selectedEdges[0].ownStyles; + + baseEdge.model.width = edgeWidth; + + graphDrawer.Draw(baseEdge, self.style.GetStyle({}, baseEdge)); + + context.restore(); + } + + var changeIndex = function() + { + var val = $( "#edgeSelectedIndex" ).val(); + if (val == "all") + { + applyIndex(1); + self.index = "all"; + fillFields(); + } + else + { + var index = parseInt(val); + self.index = index; + applyIndex(index); + fillFields(); + } + + redrawVertex(); + } + + var applyWidth = function(width) + { + if (forAll) + { + app.SetDefaultEdgeWidth(width); + } + else + { + selectedEdges.forEach(function(edge) { + edge.model.width = width; + }); + } + }; + + dialogButtons[g_default] = + { + text : g_default, + class : "MarginLeft", + click : function() { + app.PushToStack("ChangeStyle"); + + applyWidth(forAll ? (new EdgeModel()).width : app.GetDefaultEdgeWidth()); + var indexes = []; + if (self.index == "all") + { + for (i = 0; i < app.edgeSelectedStyles.length; i ++) + indexes.push(i + 1); + } + else + indexes.push(self.index); + + if (forAll) + { + indexes.forEach(function(index) { + app.ResetEdgeStyle(index); + }); + } + else + { + selectedEdges.forEach(function(edge) { + indexes.forEach(function(index) { + edge.resetOwnStyle(index); + }); + }); + } + + app.redrawGraph(); + $( this ).dialog( "close" ); + } + }; + + dialogButtons[g_save] = function() { + + app.PushToStack("ChangeStyle"); + + applyWidth(parseInt($( "#edgeWidth" ).val())); + + var indexes = []; + if (self.index == "all") + { + indexes.push({index : 1, style : self.style}); + + for (i = 1; i < app.edgeSelectedStyles.length; i ++) + { + var style = (new BaseEdgeStyle()); + style.baseStyles.push("selected"); + indexes.push({index : i + 1, style : style}); + } + + self.style.baseStyles = []; + self.style.baseStyles = self.style.baseStyles.concat((new SelectedEdgeStyle0()).baseStyles); + } + else + indexes.push({index : self.index, style : self.style}); + + if (forAll) + { + indexes.forEach(function(index) { + app.SetEdgeStyle(index.index, index.style); + }); + } + else + { + selectedEdges.forEach(function(edge) { + indexes.forEach(function(index) { + edge.setOwnStyle(index.index, index.style); + }); + }); + } + app.redrawGraph(); + $( this ).dialog( "close" ); + }; + dialogButtons[g_cancel] = function() { + $( this ).dialog( "close" ); + }; + + fillFields(); + + $( "#SetupEdgeStyleDialog" ).dialog({ + resizable: false, + height: "auto", + width: "auto", + modal: true, + title: g_edgeDraw, + buttons: dialogButtons, + dialogClass: 'EdgeDialog' + }); + + redrawVertex(); + + $( "#edgeFillColor" ).unbind(); + $( "#edgeStrokeColor" ).unbind(); + $( "#edgeTextColor" ).unbind(); + $( "#edgeStyle" ).unbind(); + $( "#edgeWidth" ).unbind(); + $( "#weightEdgeTextColor" ).unbind(); + $( "#weightTextPosition" ).unbind(); + $( "#edgeSelectedIndex" ).unbind(); + + $( "#edgeFillColor" ).change(redrawVertex); + $( "#edgeStrokeColor" ).change(redrawVertex); + $( "#edgeTextColor" ).change(redrawVertex); + $( "#edgeStyle" ).change(redrawVertex); + $( "#edgeWidth" ).change(redrawVertex); + $( "#weightEdgeTextColor" ).change(redrawVertex); + $( "#weightTextPosition" ).change(redrawVertex); + $( "#edgeSelectedIndex" ).change(changeIndex); +} diff --git a/script/features/setup_vertex_style/index.js b/script/features/setup_vertex_style/index.js new file mode 100644 index 0000000..ef5c1ca --- /dev/null +++ b/script/features/setup_vertex_style/index.js @@ -0,0 +1,299 @@ +doInclude ([ + include ("features/base_handler/index.js") +]) + +/** + * Setup Vertex Style rename vertices. + * + */ +function SetupVertexStyle(app) +{ + BaseHandler.apply(this, arguments); + this.message = ""; +} + +// inheritance. +SetupVertexStyle.prototype = Object.create(BaseHandler.prototype); + +SetupVertexStyle.prototype.show = function(index, selectedVertices) +{ + var handler = this; + var dialogButtons = {}; + var graph = this.app.graph; + var app = this.app; + this.forAll = selectedVertices == null; + var forAll = this.forAll; + var self = this; + + var applyIndex = function(index) + { + self.index = index; + self.originStyle = (self.index == 0 ? app.vertexCommonStyle : app.vertexSelectedVertexStyles[self.index - 1]); + if (!forAll) + { + self.originStyle = selectedVertices[0].getStyleFor(self.index); + } + self.style = FullObjectCopy(self.originStyle); + } + + applyIndex(index); + + var fillFields = function() + { + var fullStyle = self.style.GetStyle({}, forAll ? undefined : selectedVertices[0]); + + $( "#vertexFillColor" ).val(fullStyle.fillStyle); + $( "#vertexStrokeColor" ).val(fullStyle.strokeStyle); + $( "#vertexTextColor" ).val(fullStyle.mainTextColor); + $( "#upVertexTextColor" ).val(fullStyle.upTextColor); + $( "#vertexStrokeSize" ).val(fullStyle.lineWidth); + $( "#vertexShape" ).val(fullStyle.shape); + $( "#vertexSize" ).val(forAll ? app.GetDefaultVertexSize() : selectedVertices[0].model.diameter); + $( "#commonTextPosition" ).val(fullStyle.commonTextPosition); + + if (self.index > 0 || self.index == "all") + { + $( "#VertexSelectedIndexForm" ).show(); + $( "#vertexSelectedIndex" ).val(self.index); + } + else + { + $( "#VertexSelectedIndexForm" ).hide(); + } + + // Fill color presets. + var stylesArray = []; + stylesArray.push(app.vertexCommonStyle); + + for (i = 0; i < app.vertexSelectedVertexStyles.length; i ++) + stylesArray.push(app.vertexSelectedVertexStyles[i]); + + var colorSet = {}; + for (i = 0; i < stylesArray.length; i ++) + { + var style = stylesArray[i]; + if (style.hasOwnProperty('strokeStyle')) + colorSet[style.strokeStyle] = 1; + if (style.hasOwnProperty('fillStyle')) + colorSet[style.fillStyle] = 1; + if (style.hasOwnProperty('mainTextColor')) + colorSet[style.mainTextColor] = 1; + if (style.hasOwnProperty('upTextColor')) + colorSet[style.upTextColor] = 1; + } + + $("#vertexFillColorPreset").find('option').remove(); + $("#upVertexTextColorPreset").find('option').remove(); + $("#vertexTextColorPreset").find('option').remove(); + $("#vertexStrokeColorPreset").find('option').remove(); + for (const property in colorSet) + { + $("#vertexFillColorPreset").append(new Option(property)); + $("#upVertexTextColorPreset").append(new Option(property)); + $("#vertexTextColorPreset").append(new Option(property)); + $("#vertexStrokeColorPreset").append(new Option(property)); + } + } + + var redrawVertex = function() + { + var fullStyle = self.style.GetStyle({}, forAll ? undefined : selectedVertices[0]); + + if (fullStyle.fillStyle != $( "#vertexFillColor" ).val()) + self.style.fillStyle = $( "#vertexFillColor" ).val(); + + if (fullStyle.strokeStyle != $( "#vertexStrokeColor" ).val()) + self.style.strokeStyle = $( "#vertexStrokeColor" ).val(); + + if (fullStyle.mainTextColor != $( "#vertexTextColor" ).val()) + self.style.mainTextColor = $( "#vertexTextColor" ).val(); + + if (fullStyle.lineWidth != $( "#vertexStrokeSize" ).val()) + self.style.lineWidth = parseInt($( "#vertexStrokeSize" ).val()); + + if (fullStyle.shape != $( "#vertexShape" ).val()) + self.style.shape = parseInt($( "#vertexShape" ).val()); + + if (fullStyle.upTextColor != $( "#upVertexTextColor" ).val()) + self.style.upTextColor = $( "#upVertexTextColor" ).val(); + + if (fullStyle.commonTextPosition != $( "#commonTextPosition" ).val()) + self.style.commonTextPosition = $( "#commonTextPosition" ).val(); + + var diameter = parseInt($( "#vertexSize" ).val()); + + var canvas = document.getElementById( "VertexPreview" ); + var context = canvas.getContext('2d'); + + context.save(); + + var backgroundDrawer = new BaseBackgroundDrawer(context); + backgroundDrawer.Draw(app.backgroundCommonStyle, canvas.width, canvas.height, new Point(0, 0), 1.0); + + var graphDrawer = new BaseVertexDrawer(context); + var baseVertex = new BaseVertex(canvas.width / 2, canvas.height / 2, new BaseEnumVertices(this)); + baseVertex.mainText = "1"; + baseVertex.upText = "Up Text"; + baseVertex.model.diameter = diameter; + + if (!forAll) + baseVertex.ownStyles = selectedVertices[0].ownStyles; + + graphDrawer.Draw(baseVertex, self.style.GetStyle({}, baseVertex)); + + context.restore(); + } + + var changeIndex = function() + { + var val = $( "#vertexSelectedIndex" ).val(); + if (val == "all") + { + applyIndex(1); + self.index = "all"; + fillFields(); + } + else + { + var index = parseInt(val); + self.index = index; + applyIndex(index); + fillFields(); + } + redrawVertex(); + } + + var applyDiameter = function(diameter) + { + if (forAll) + { + app.SetDefaultVertexSize(diameter); + } + else + { + selectedVertices.forEach(function(vertex) { + vertex.model.diameter = diameter; + }); + } + }; + + dialogButtons[g_default] = + { + text : g_default, + class : "MarginLeft", + click : function() { + + app.PushToStack("ChangeStyle"); + + applyDiameter(forAll ? (new VertexModel()).diameter : app.GetDefaultVertexSize()); + + var indexes = []; + if (self.index == "all") + { + for (i = 0; i < app.vertexSelectedVertexStyles.length; i ++) + indexes.push(i + 1); + } + else + indexes.push(self.index); + + + if (forAll) + { + indexes.forEach(function(index) { + app.ResetVertexStyle(index); + }); + } + else + { + selectedVertices.forEach(function(vertex) { + indexes.forEach(function(index) { + vertex.resetOwnStyle(index); + }); + }); + } + app.redrawGraph(); + $( this ).dialog( "close" ); + } + }; + + dialogButtons[g_save] = function() { + + app.PushToStack("ChangeStyle"); + + applyDiameter(parseInt($( "#vertexSize" ).val())); + + var indexes = []; + if (self.index == "all") + { + indexes.push({index : 1, style : self.style}); + for (i = 1; i < app.vertexSelectedVertexStyles.length; i ++) + { + var style = (new BaseVertexStyle()); + style.baseStyles.push("selected"); + indexes.push({index : i + 1, style : style}); + } + + self.style.baseStyles = []; + self.style.baseStyles = self.style.baseStyles.concat((new SelectedVertexStyle0()).baseStyles); + } + else + indexes.push({index : self.index, style : self.style}); + + if (forAll) + { + indexes.forEach(function(index) { + app.SetVertexStyle(index.index, index.style); + }); + } + else + { + if (JSON.stringify(self.originStyle) !== JSON.stringify(self.style)) + { + selectedVertices.forEach(function(vertex) { + indexes.forEach(function(index) { + vertex.setOwnStyle(index.index, index.style); + }); + }); + } + } + app.redrawGraph(); + $( this ).dialog( "close" ); + }; + dialogButtons[g_cancel] = function() { + $( this ).dialog( "close" ); + }; + + fillFields(); + + $( "#SetupVertexStyleDialog" ).dialog({ + resizable: false, + height: "auto", + width: "auto", + modal: true, + title: g_vertexDraw, + buttons: dialogButtons, + dialogClass: 'EdgeDialog' + }); + + redrawVertex(); + + $( "#vertexFillColor" ).unbind(); + $( "#vertexStrokeColor" ).unbind(); + $( "#vertexTextColor" ).unbind(); + $( "#upVertexTextColor" ).unbind(); + $( "#vertexStrokeSize" ).unbind(); + $( "#vertexShape" ).unbind(); + $( "#vertexSize" ).unbind(); + $( "#commonTextPosition" ).unbind(); + $( "#vertexSelectedIndex" ).unbind(); + + $( "#vertexFillColor" ).change(redrawVertex); + $( "#vertexStrokeColor" ).change(redrawVertex); + $( "#vertexTextColor" ).change(redrawVertex); + $( "#vertexStrokeSize" ).change(redrawVertex); + $( "#vertexShape" ).change(redrawVertex); + $( "#vertexSize" ).change(redrawVertex); + $( "#upVertexTextColor" ).change(redrawVertex); + $( "#commonTextPosition" ).change(redrawVertex); + $( "#vertexSelectedIndex" ).change(changeIndex); +} diff --git a/script/features/show_adjacency_matrix/index.js b/script/features/show_adjacency_matrix/index.js new file mode 100644 index 0000000..a8653d7 --- /dev/null +++ b/script/features/show_adjacency_matrix/index.js @@ -0,0 +1,66 @@ +doInclude ([ + include ("features/base_handler/index.js") +]) + +/** + * Save/Load graph from matrix. + * + */ +function ShowAdjacencyMatrix(app) +{ + BaseHandler.apply(this, arguments); + this.message = ""; +} + +// inheritance. +ShowAdjacencyMatrix.prototype = Object.create(BaseHandler.prototype); +// First selected. +ShowAdjacencyMatrix.prototype.firstObject = null; +// Path +ShowAdjacencyMatrix.prototype.pathObjects = null; + +ShowAdjacencyMatrix.prototype.show = function() +{ + var handler = this; + var dialogButtons = {}; + + $('#AdjacencyMatrixField').unbind(); + $( "#AdjacencyMatrixField" ).on('keyup change', function (eventObject) + { + if (!handler.app.TestAdjacencyMatrix($( "#AdjacencyMatrixField" ).val(), [], [])) + { + $( "#BadMatrixFormatMessage" ).show(); + } + else + { + $( "#BadMatrixFormatMessage" ).hide(); + } + }); + + dialogButtons[g_save] = function() { + handler.app.PushToStack("ChangeAdjacencyMatrix"); + handler.app.SetAdjacencyMatrixSmart($( "#AdjacencyMatrixField" ).val()); + $( this ).dialog( "close" ); + }; + dialogButtons[g_cancel] = function() { + $( this ).dialog( "close" ); + }; + + $( "#AdjacencyMatrixField" ).val(this.app.GetAdjacencyMatrix()); + $( "#BadMatrixFormatMessage" ).hide(); + + if (this.app.graph.isMulti()) + $( "#AdjacencyMatrixMultiGraphDesc").show(); + else + $( "#AdjacencyMatrixMultiGraphDesc").hide(); + + $( "#adjacencyMatrix" ).dialog({ + resizable: false, + height: "auto", + width: "auto", + modal: true, + title: g_adjacencyMatrixText, + buttons: dialogButtons, + dialogClass: 'EdgeDialog' + }); +} diff --git a/script/features/show_distance_matrix/index.js b/script/features/show_distance_matrix/index.js new file mode 100644 index 0000000..2ce1c0b --- /dev/null +++ b/script/features/show_distance_matrix/index.js @@ -0,0 +1,77 @@ +doInclude ([ + include ("features/base_handler/index.js") +]) + +/** + * Show distance matrix. + * + */ +function ShowDistanceMatrix(app) +{ + BaseHandler.apply(this, arguments); + this.app = app; + this.message = ""; +} + +// inheritance. +ShowDistanceMatrix.prototype = Object.create(BaseHandler.prototype); +// First selected. +ShowDistanceMatrix.prototype.firstObject = null; +// Path +ShowDistanceMatrix.prototype.pathObjects = null; + +ShowDistanceMatrix.prototype.GetIncidenceMatrix = function (rawMatrix) +{ + var matrix = ""; + for (var i = 0; i < rawMatrix.length; i++) + { + for (var j = 0; j < rawMatrix[i].length; j++) + { + if (i == j) + { + matrix += "0"; + } + else if ((new Graph()).infinity == rawMatrix[i][j]) + { + matrix += '\u221E'; + } + else + { + matrix += rawMatrix[i][j]; + } + + if (j != rawMatrix[i].length - 1) + { + matrix += ", "; + } + + } + matrix = matrix + "\n"; + } + + return matrix; +} + +ShowDistanceMatrix.prototype.show = function() +{ + var handler = this; + var dialogButtons = {}; + + dialogButtons[g_close] = function() { + $( this ).dialog( "close" ); + }; + + var handler = g_Algorithms[g_AlgorithmIds.indexOf("OlegSh.FloidAlgorithm")](this.app.graph, this.app); + + $( "#FloidMatrixField" ).val(this.GetIncidenceMatrix(handler.resultMatrix())); + + $( "#floidMatrix" ).dialog({ + resizable: false, + height: "auto", + width: "auto", + modal: true, + title: g_minDistMatrixText, + buttons: dialogButtons, + dialogClass: 'EdgeDialog' + }); +} diff --git a/script/features/show_incidence_matrix/index.js b/script/features/show_incidence_matrix/index.js new file mode 100644 index 0000000..e4bd53c --- /dev/null +++ b/script/features/show_incidence_matrix/index.js @@ -0,0 +1,61 @@ +doInclude ([ + include ("features/base_handler/index.js") +]) + +/** + * Save/Load graph from Incidence matrix. + * + */ +function ShowIncidenceMatrix(app) +{ + BaseHandler.apply(this, arguments); + this.message = ""; +} + +// inheritance. +ShowIncidenceMatrix.prototype = Object.create(BaseHandler.prototype); +// First selected. +ShowIncidenceMatrix.prototype.firstObject = null; +// Path +ShowIncidenceMatrix.prototype.pathObjects = null; + +ShowIncidenceMatrix.prototype.show = function() +{ + var handler = this; + var dialogButtons = {}; + + $('#IncidenceMatrixField').unbind(); + $( "#IncidenceMatrixField" ).on('keyup change', function (eventObject) + { + if (!handler.app.TestIncidenceMatrix($( "#IncidenceMatrixField" ).val(), [], [])) + { + $( "#BadIncidenceMatrixFormatMessage" ).show(); + } + else + { + $( "#BadIncidenceMatrixFormatMessage" ).hide(); + } + }); + + dialogButtons[g_save] = function() { + handler.app.PushToStack("IncidenceMatrixChanged"); + handler.app.SetIncidenceMatrixSmart($( "#IncidenceMatrixField" ).val()); + $( this ).dialog( "close" ); + }; + dialogButtons[g_cancel] = function() { + $( this ).dialog( "close" ); + }; + + $( "#IncidenceMatrixField" ).val(this.app.GetIncidenceMatrix()); + $( "#BadIncidenceMatrixFormatMessage" ).hide(); + + $( "#incidenceMatrix" ).dialog({ + resizable: false, + height: "auto", + width: "auto", + modal: true, + title: g_incidenceMatrixText, + buttons: dialogButtons, + dialogClass: 'EdgeDialog' + }); +} diff --git a/script/merge.php b/script/merge.php index 26f6e05..66cba03 100755 --- a/script/merge.php +++ b/script/merge.php @@ -1,34 +1,18 @@ +

Update cache

+ "); + foreach ($cacheList as &$page) { + $date = date('d.m.Y H:i:s', filemtime("../$page.cache")); + echo ("
  • $page $date
  • "); + } + echo (""); +?> -file_put_contents($outputFilename, file_get_contents("utils.js"), FILE_APPEND); -file_put_contents($outputFilename, file_get_contents("texts.js"), FILE_APPEND); -file_put_contents($outputFilename, file_get_contents("point.js"), FILE_APPEND); -file_put_contents($outputFilename, file_get_contents("EdgeModel.js"), FILE_APPEND); -file_put_contents($outputFilename, file_get_contents("VertexModel.js"), FILE_APPEND); -file_put_contents($outputFilename, file_get_contents("BaseVertex.js"), FILE_APPEND); -file_put_contents($outputFilename, file_get_contents("BaseEdge.js"), FILE_APPEND); -file_put_contents($outputFilename, file_get_contents("BaseVertexDrawer.js"), FILE_APPEND); -file_put_contents($outputFilename, file_get_contents("BaseEdgeDrawer.js"), FILE_APPEND); -file_put_contents($outputFilename, file_get_contents("BaseBackgroundDrawer.js"), FILE_APPEND); -file_put_contents($outputFilename, file_get_contents("Algorithms.js"), FILE_APPEND); -file_put_contents($outputFilename, file_get_contents("EventHandlers.js"), FILE_APPEND); -file_put_contents($outputFilename, file_get_contents("GraphMLCreator.js"), FILE_APPEND); -file_put_contents($outputFilename, file_get_contents("Graph.js"), FILE_APPEND); -file_put_contents($outputFilename, file_get_contents("EnumVertices.js"), FILE_APPEND); -file_put_contents($outputFilename, file_get_contents("Application.js"), FILE_APPEND); -file_put_contents($outputFilename, file_get_contents("main.js"), FILE_APPEND); -file_put_contents($outputFilename, file_get_contents("BaseTraversal.js"), FILE_APPEND); - -if (file_exists($outputFilename)) -{ - echo ("File exists"); -} -else -{ - echo ("File not exists"); -} - -?> \ No newline at end of file diff --git a/script/pack.php b/script/pack.php new file mode 100644 index 0000000..1691b80 --- /dev/null +++ b/script/pack.php @@ -0,0 +1,104 @@ + + + + + + + + + + +
    +

    State:

    +

    Loading

    +
    + + + + + + + diff --git a/script/pages/create_graph_by_edge_list/api/index.js b/script/pages/create_graph_by_edge_list/api/index.js new file mode 100644 index 0000000..3faf481 --- /dev/null +++ b/script/pages/create_graph_by_edge_list/api/index.js @@ -0,0 +1,9 @@ +// Global version needs to force reload scripts from server. +globalVersion = 75; + +{ + let modulDir = "pages/create_graph_by_edge_list/"; + + doInclude ([ + include ("entities/graph/api/index.js")]); +} \ No newline at end of file diff --git a/script/pages/create_graph_by_edge_list/api/index.js.cache b/script/pages/create_graph_by_edge_list/api/index.js.cache new file mode 100644 index 0000000..932c582 --- /dev/null +++ b/script/pages/create_graph_by_edge_list/api/index.js.cache @@ -0,0 +1,594 @@ +moduleLoader.beginCacheLoading(["/script/entities/graph/api/index.js?v=75","/script/shared/point.js?v=75","/script/entities/edge/api/index.js?v=75","/script/entities/edge/model/BaseEdge.js?v=75","/script/entities/edge/model/EdgeModel.js?v=75","/script/entities/vertex/api/index.js?v=75","/script/entities/vertex/model/BaseVertex.js?v=75","/script/entities/vertex/model/VertexModel.js?v=75","/script/entities/graph/model/Graph.js?v=75",]);globalVersion=75;{let modulDir="pages/create_graph_by_edge_list/";doInclude([include("entities/graph/api/index.js")]);} +{let modulDir="entities/graph/";doInclude([include("shared/point.js"),include("entities/edge/api/index.js"),include("entities/vertex/api/index.js"),include("model/Graph.js",modulDir)])}function Point(x,y){this.x=x||0;this.y=y||0;};Point.prototype.x=null;Point.prototype.y=null;Point.prototype.add=function(v){return new Point(this.x+v.x,this.y+v.y);};Point.prototype.addValue=function(v){return new Point(this.x+v,this.y+v);};Point.prototype.clone=function(){return new Point(this.x,this.y);};Point.prototype.degreesTo=function(v){var dx=this.x-v.x;var dy=this.y-v.y;var angle=Math.atan2(dy,dx);return angle*(180/Math.PI);};Point.prototype.distance=function(v){return Math.sqrt(this.distanceSqr(v));};Point.prototype.distanceSqr=function(v){var x=this.x-v.x;var y=this.y-v.y;return x*x+y*y;};Point.prototype.equals=function(toCompare){return this.x==toCompare.x&&this.y==toCompare.y;};Point.prototype.interpolate=function(v,f){return new Point((this.x+v.x)*f,(this.y+v.y)*f);};Point.prototype.length=function(){return Math.sqrt(this.x*this.x+this.y*this.y);};Point.prototype.normalize=function(thickness){var l=this.length();this.x=this.x/l*thickness;this.y=this.y/l*thickness;return new Point(this.x,this.y);};Point.prototype.normalizeCopy=function(thickness){var l=this.length();return new Point(this.x/l*thickness,this.y/l*thickness);};Point.prototype.orbit=function(origin,arcWidth,arcHeight,degrees){var radians=degrees*(Math.PI/180);this.x=origin.x+arcWidth*Math.cos(radians);this.y=origin.y+arcHeight*Math.sin(radians);};Point.prototype.rotate=function(center,degrees){var radians=degrees*(Math.PI/180);offset=this.subtract(center);this.x=offset.x*Math.cos(radians)-offset.y*Math.sin(radians);this.y=offset.x*Math.sin(radians)+offset.y*Math.cos(radians);this.x=this.x+center.x;this.y=this.y+center.y;return this;};Point.prototype.offset=function(dx,dy){this.x+=dx;this.y+=dy;};Point.prototype.subtract=function(v){return new Point(this.x-v.x,this.y-v.y);};Point.prototype.subtractValue=function(value){return new Point(this.x-value,this.y-value);};Point.prototype.multiply=function(value){return new Point(this.x*value,this.y*value);};Point.prototype.toString=function(){return"(x="+this.x+", y="+this.y+")";};Point.prototype.normal=function(){return new Point(-this.y,this.x);};Point.prototype.min=function(point) +{return new Point(Math.min(this.x,point.x),Math.min(this.y,point.y));};Point.prototype.max=function(point) +{return new Point(Math.max(this.x,point.x),Math.max(this.y,point.y));};Point.prototype.inverse=function() +{return new Point(-this.x,-this.y);};Point.prototype.cross=function(point) +{return this.x*point.y-this.y*point.x;};Point.interpolate=function(pt1,pt2,f){return new Point(pt1.x*(1.0-f)+pt2.x*f,pt1.y*(1.0-f)+pt2.y*f);};Point.polar=function(len,angle){return new Point(len*Math.cos(angle),len*Math.sin(angle));};Point.distance=function(pt1,pt2){var x=pt1.x-pt2.x;var y=pt1.y-pt2.y;return Math.sqrt(x*x+y*y);};Point.center=function(pt1,pt2){return new Point((pt1.x+pt2.x)/2.0,(pt1.y+pt2.y)/2.0);};Point.toString=function(){return x+" "+y;} +Point.projection=function(point,line1,line2) +{var x=line2.y-line1.y;var y=line1.x-line2.x;var l=(line1.cross(line2)+line1.cross(point)+line2.cross(point))/(x*(line2.y-line1.y)+y*(line1.x-line2.x));var res=new Point(point.x+x*l,point.y+y*l);return res;} +Point.hitTest=function(pt11,pt12,pt21,pt22) +{var res=null;var n=0.0;var x1=pt11.x;var y1=pt11.y;var x2=pt12.x;var y2=pt12.y;var x3=pt21.x;var y3=pt21.y;var x4=pt22.x;var y4=pt22.y;if(y2-y1!=0.0) +{var q=(x2-x1)/(y1-y2);var sn=(x3-x4)+(y3-y4)*q;if(sn==0.0) +{return res;} +var fn=(x3-x1)+(y3-y1)*q;n=fn/sn;} +else +{if((y3-y4)==0.0) +{return res;} +n=(y3-y1)/(y3-y4);} +res=new Point(x3+(x4-x3)*n,y3+(y4-y3)*n);var epsilon=1E-5;if(!(res.x>=Math.min(x1,x2)-epsilon&&res.x>=Math.min(x3,x4)-epsilon&&res.x<=Math.max(x1,x2)+epsilon&&res.x<=Math.max(x3,x4)+epsilon&&res.y>=Math.min(y1,y2)-epsilon&&res.y>=Math.min(y3,y4)-epsilon&&res.y<=Math.max(y1,y2)+epsilon&&res.y<=Math.max(y3,y4)+epsilon)) +{res=null;} +return res;} +function Rect(minPoint,maxPoint){this.minPoint=minPoint;this.maxPoint=maxPoint;};Rect.prototype.center=function() +{return Point.center(this.minPoint,this.maxPoint);};Rect.prototype.size=function() +{return this.maxPoint.subtract(this.minPoint);};Rect.prototype.left=function() +{return this.minPoint.x;};Rect.prototype.top=function() +{return this.minPoint.y;};Rect.prototype.isIn=function(v) +{return this.minPoint.x<=v.x&&this.minPoint.y<=v.y&&this.maxPoint.x>v.x&&this.maxPoint.y>v.y;};{let modulDir="entities/edge/";doInclude([include("model/BaseEdge.js",modulDir),include("model/EdgeModel.js",modulDir)])} +function BaseEdge(vertex1,vertex2,isDirect,weight,upText) +{this.vertex1=vertex1;this.vertex2=vertex2;this.arrayStyleStart="";this.arrayStyleFinish="";this.isDirect=isDirect;this.weight=0;this.text="";this.useWeight=false;this.id=0;this.model=new EdgeModel();if(upText===undefined) +this.upText="";else +this.upText=upText;if(weight!==undefined) +this.SetWeight(weight);this.ownStyles={};} +BaseEdge.prototype.copyFrom=function(other) +{this.vertex1=other.vertex1;this.vertex2=other.vertex2;this.arrayStyleStart=other.arrayStyleStart;this.arrayStyleFinish=other.arrayStyleFinish;this.isDirect=other.isDirect;this.weight=other.weight;this.text=other.text;this.useWeight=other.useWeight;this.id=other.id;this.model=new EdgeModel();this.model.copyFrom(other.model);this.upText=other.upText;this.ownStyles=FullObjectCopy(other.ownStyles);} +BaseEdge.prototype.SaveToXML=function() +{return"0)?"ownStyles = \""+gEncodeToHTML(JSON.stringify(this.ownStyles))+"\" ":"")+ +this.model.SaveToXML()+">";} +BaseEdge.prototype.LoadFromXML=function(xml,graph) +{var attr=xml.attr('vertex1');if(typeof attr==='undefined') +{attr=xml.attr('source');} +this.vertex1=graph.FindVertex(typeof attr!=='undefined'?attr:xml.attr('graph1'));var attr=xml.attr('vertex2');if(typeof attr==='undefined') +{attr=xml.attr('target');} +this.vertex2=graph.FindVertex(typeof attr!=='undefined'?attr:xml.attr('graph2'));this.isDirect=xml.attr('isDirect')=="true";this.weight=parseFloat(xml.attr('weight'));if(isNaN(this.weight)) +{this.weight=1;} +this.hasPair=xml.attr('hasPair')=="true";this.useWeight=xml.attr('useWeight')=="true";this.id=xml.attr('id');this.text=xml.attr("text")==null?"":gDecodeFromHTML(xml.attr("text"));this.arrayStyleStart=xml.attr("arrayStyleStart")==null?"":xml.attr("arrayStyleStart");this.arrayStyleFinish=xml.attr("arrayStyleFinish")==null?"":xml.attr("arrayStyleFinish");this.upText=xml.attr('upText');if(typeof this.upText==='undefined') +{this.upText="";} +else +{this.upText=gDecodeFromHTML(this.upText);} +var ownStyle=xml.attr('ownStyles');if(typeof ownStyle!=='undefined') +{var parsedSave=gDecodeFromHTML(JSON.parse(ownStyle));for(var indexField in parsedSave) +{var index=parseInt(indexField);this.ownStyles[index]=FullObjectCopy(this.getStyleFor(index));for(var field in parsedSave[indexField]) +{if(this.ownStyles[index].ShouldLoad(field)) +this.ownStyles[index][field]=parsedSave[indexField][field];}}} +this.model.LoadFromXML(xml);} +BaseEdge.prototype.GetPixelLength=function() +{if(this.vertex1==this.vertex2) +{return this.model.GetLoopSize()*2*Math.PI;} +else +{return Point.distance(this.vertex1.position,this.vertex2.position);}} +BaseEdge.prototype.GetWeight=function() +{return this.useWeight?this.weight:1;} +BaseEdge.prototype.GetText=function() +{return this.text.length>0?this.text:(this.useWeight?this.weight.toString():"");} +BaseEdge.prototype.GetUpText=function() +{return this.upText;} +BaseEdge.prototype.GetStartEdgeStyle=function() +{return this.arrayStyleStart;} +BaseEdge.prototype.GetFinishEdgeStyle=function() +{return(this.arrayStyleFinish!=""?this.arrayStyleFinish:(this.isDirect?"arrow":""));} +BaseEdge.prototype.HitTest=function(pos) +{var positions=this.GetEdgePositionsShift();return this.model.HitTest(positions[0],positions[1],pos);} +BaseEdge.prototype.GetEdgePositionsShift=function() +{return this.GetEdgePositions();} +BaseEdge.prototype.GetEdgePositions=function() +{var res=[];if(this.vertex1==this.vertex2) +{res.push(this.vertex1.position);res.push(this.vertex2.position);return res;} +var position1=this.vertex1.position;var position2=this.vertex2.position;var diameter1=this.vertex1.model.diameter+parseInt(this.vertex1.currentStyle.GetStyle({},this.vertex1).lineWidth);var diameter2=this.vertex2.model.diameter+parseInt(this.vertex2.currentStyle.GetStyle({},this.vertex2).lineWidth);var direction=position1.subtract(position2);var direction1=direction;var direction2=direction;var d1=diameter1;var d2=diameter2;if(this.model.type==EdgeModels.curve) +{var dist=position1.distance(position2);var point1=this.model.GetCurvePoint(position1,position2,10.0/dist);direction1=position1.subtract(point1);var point2=this.model.GetCurvePoint(position1,position2,1.0-10.0/dist);direction2=position2.subtract(point2);d2=diameter2;} +else +{direction2=direction2.multiply(-1);} +direction1.normalize(1.0);direction2.normalize(1.0);var vertices=[];vertices.push({vertex:this.vertex1,direction:direction1,position:position1,diameter:d1});vertices.push({vertex:this.vertex2,direction:direction2,position:position2,diameter:d2});vertices.forEach(function(data) +{var shape=data.vertex.currentStyle.GetStyle({},data.vertex).shape;if(shape==VertexCircleShape) +{var direction=data.direction.multiply(0.5);res.push(data.position.subtract(direction.multiply(data.diameter)));} +else +{var lineFinish1=data.direction.multiply(-1).multiply(1000.0);var pointsVertex1=GetPointsForShape(shape,data.diameter,data.vertex.mainText);pointsVertex1.push(pointsVertex1[0]);for(var i=0;i=0)?weight:1;this.weight=Number(weight);this.useWeight=useWeight;} +BaseEdge.prototype.SetUpText=function(text) +{this.upText=text;} +BaseEdge.prototype.resetOwnStyle=function(index) +{if(this.ownStyles.hasOwnProperty(index)) +{delete this.ownStyles[index];}} +BaseEdge.prototype.setOwnStyle=function(index,style) +{this.ownStyles[index]=style;} +BaseEdge.prototype.getStyleFor=function(index) +{if(this.ownStyles.hasOwnProperty(index)) +{return this.ownStyles[index];} +else +{var style=null;if(index==0) +style=globalApplication.GetStyle("edge","common");else +style=globalApplication.GetStyle("edge","selected",undefined,index-1);return style;}} +BaseEdge.prototype.hasOwnStyleFor=function(index) +{return this.ownStyles.hasOwnProperty(index);} +var EdgeModels={"line":0,"curve":1};const defaultEdgeWidth=4;function EdgeModel() +{this.width=globalApplication.GetDefaultEdgeWidth();this.type=EdgeModels.line;this.curveValue=EdgeModel.prototype.defaultCurve;this.default=true;this.sizeOfLoop=24;this.loopShiftAngel=Math.PI/6;} +EdgeModel.prototype.defaultCurve=0.1;EdgeModel.prototype.copyFrom=function(other) +{this.width=other.width;this.type=other.type;this.curveValue=other.curveValue;this.default=other.default;} +EdgeModel.prototype.SaveToXML=function() +{return"model_width=\""+this.width+"\" "+"model_type=\""+this.type+"\" "+"model_curveValue=\""+this.curveValue+"\" "+"model_default=\""+this.default+"\" ";} +EdgeModel.prototype.LoadFromXML=function(xml,graph) +{this.width=xml.attr('model_width')==null?this.width:parseFloat(xml.attr("model_width"));this.type=xml.attr('model_type')==null?this.type:xml.attr("model_type");this.curveValue=xml.attr('model_curveValue')==null?this.curveValue:parseFloat(xml.attr("model_curveValue"));this.default=xml.attr('model_default')==null?this.default:parseFloat(xml.attr("model_default"));} +EdgeModel.prototype.GetCurvePoint=function(position1,position2,t) +{var points=this.GetBezierPoints(position1,position2);var firstBezierPoint=points[0];var secondBezierPoint=points[1];var B0_t=Math.pow(1-t,3);var B1_t=3*t*Math.pow(1-t,2);var B2_t=3*t*t*(1-t) +var B3_t=t*t*t;var ax=position1.x;var ay=position1.y;var dx=position2.x;var dy=position2.y;var bx=firstBezierPoint.x;var by=firstBezierPoint.y;var cx=secondBezierPoint.x;var cy=secondBezierPoint.y;var px_t=(B0_t*ax)+(B1_t*bx)+(B2_t*cx)+(B3_t*dx);var py_t=(B0_t*ay)+(B1_t*by)+(B2_t*cy)+(B3_t*dy);return new Point(px_t,py_t);} +EdgeModel.prototype.GetBezierPoints=function(position1,position2) +{var direction=position2.subtract(position1);var delta=direction.length();direction.normalize(1.0);var normal=direction.normal();var deltaOffsetPixels=delta*this.curveValue;var yOffset=normal.multiply(deltaOffsetPixels);var firstBezierPointShift=(direction.multiply(delta*0.2)).add(yOffset);var secondBezierPointShift=(direction.multiply(-delta*0.2)).add(yOffset);var firstBezierPoint=position1.add(firstBezierPointShift);var secondBezierPoint=position2.add(secondBezierPointShift);return[firstBezierPoint,secondBezierPoint];} +EdgeModel.prototype.HitTest=function(position1,position2,mousePos) +{if(this.type==EdgeModels.line) +return this.HitTestLine(position1,position2,mousePos);else if(this.type==EdgeModels.curve) +return this.HitTestCurve(position1,position2,mousePos);return false;} +EdgeModel.prototype.HitTestLine=function(position1,position2,mousePos,factor) +{if(factor===undefined) +{factor=1.0;} +var pos1=position1;var pos2=position2;var pos0=mousePos;if(pos1.equals(pos2)) +{var xCenter=pos1.x-Math.cos(this.GetLoopShiftAngel())*this.GetLoopSize();var yCenter=pos1.y-Math.sin(this.GetLoopShiftAngel())*this.GetLoopSize();return Math.abs((Point.distance(new Point(xCenter,yCenter),pos0))-this.GetLoopSize())<=this.width*1.5*factor;} +var r1=pos0.distance(pos1);var r2=pos0.distance(pos2);var r12=pos1.distance(pos2);if(r1>=(new Point(r2,r12)).length()||r2>=(new Point(r1,r12)).length()) +{} +else +{var distance=((pos1.y-pos2.y)*pos0.x+(pos2.x-pos1.x)*pos0.y+(pos1.x*pos2.y-pos2.x*pos1.y))/r12;if(Math.abs(distance)<=this.width*1.5*factor) +{return true;}} +return false;} +EdgeModel.prototype.HitTestCurve=function(position1,position2,mousePos) +{var pos1=position1;var pos2=position2;var pos0=mousePos;if(pos1.equals(pos2)) +{var xCenter=pos1.x-Math.cos(this.GetLoopShiftAngel())*this.GetLoopSize();var yCenter=pos1.y-Math.sin(this.GetLoopShiftAngel())*this.GetLoopSize();return Math.abs((Point.distance(new Point(xCenter,yCenter),pos0))-this.GetLoopSize())<=this.width*1.5;} +var interval_count=position1.distance(position2)/100*30;var start=position1;for(var i=0;i=0.0){normalCurve+=this.defaultCurve} +return this.sizeOfLoop*Math.abs(normalCurve)*(1/this.defaultCurve);}} +EdgeModel.prototype.GetLoopShiftAngel=function() +{if(this.type==EdgeModels.line||this.curveValue>=0.0) +{return this.loopShiftAngel;} +else +{return this.loopShiftAngel+Math.PI;}} +{let modulDir="entities/vertex/";doInclude([include("model/BaseVertex.js",modulDir),include("model/VertexModel.js",modulDir)])} +function BaseVertex(x,y,vertexEnumType) +{this.position=new Point(x,y);this.id=0;this.mainText="";this.upText="";this.vertexEnumType=vertexEnumType;this.model=new VertexModel();this.hasUndefinedPosition=false;this.ownStyles={};};BaseVertex.prototype.position=new Point(0,0);BaseVertex.prototype.copyFrom=function(other) +{this.position=new Point(other.position.x,other.position.y);this.id=other.id;this.mainText=other.mainText;this.upText=other.upText;this.vertexEnumType=other.vertexEnumType;this.model=new VertexModel();this.hasUndefinedPosition=other.hasUndefinedPosition;this.ownStyles=FullObjectCopy(other.ownStyles);} +BaseVertex.prototype.SaveToXML=function() +{return"0)?"ownStyles = \""+gEncodeToHTML(JSON.stringify(this.ownStyles))+"\" ":"")+"size=\""+this.model.diameter+"\" "+">";} +BaseVertex.prototype.LoadFromXML=function(xml) +{var xmlX=xml.attr('positionX');var xmlY=xml.attr('positionY');this.hasUndefinedPosition=(typeof xmlX==='undefined')||(typeof xmlY==='undefined');this.position=new Point(parseFloat(xmlX),parseFloat(xmlY));this.id=xml.attr('id');this.mainText=xml.attr('mainText');this.upText=xml.attr('upText');if(typeof this.mainText==='undefined') +this.mainText=this.id;else +this.mainText=gDecodeFromHTML(this.mainText);if(typeof this.upText==='undefined') +this.upText="";else +this.upText=gDecodeFromHTML(this.upText);var ownStyle=xml.attr('ownStyles');if(typeof ownStyle!=='undefined') +{var parsedSave=gDecodeFromHTML(JSON.parse(ownStyle));for(var indexField in parsedSave) +{var index=parseInt(indexField);this.ownStyles[index]=FullObjectCopy(this.getStyleFor(index));for(var field in parsedSave[indexField]) +{if(this.ownStyles[index].ShouldLoad(field)) +this.ownStyles[index][field]=parsedSave[indexField][field];}}} +var size=xml.attr('size');if(typeof size!=='undefined') +this.model.diameter=parseInt(size);} +BaseVertex.prototype.SetId=function(id) +{this.id=id;if(this.vertexEnumType!=null) +this.mainText=this.vertexEnumType.GetVertexText(id);} +BaseVertex.prototype.diameterFactor=function() +{return new Point(1.0+(this.mainText.length?this.mainText.length/8.0:0),1.5);} +BaseVertex.prototype.IsUndefinedPosition=function() +{return this.hasUndefinedPosition;} +BaseVertex.prototype.HitTest=function(pos) +{var shape=this.hasOwnProperty('currentStyle')?this.currentStyle.GetStyle({},this).shape:VertexCircleShape;var width=this.hasOwnProperty('currentStyle')?this.currentStyle.GetStyle({},this).lineWidth:0;if(shape==VertexCircleShape) +{return this.position.distance(pos)-1) +{this.edges.splice(index,1);} +this.isMultiGraph=this.checkMutiGraph();} +Graph.prototype.DeleteVertex=function(vertexObject) +{var index=this.vertices.indexOf(vertexObject);if(index>-1) +{for(var i=0;i-1) +{for(var i=0;imaxWeight) +{res=edge;maxWeight=edge.weight;}}} +return res;} +Graph.prototype.FindEdgeMinIgnoreDirection=function(id1,id2) +{var res=null;var minWeight=this.infinity;for(var i=0;i.+$/g,/^.+<.+$/g,/^.+-\(\d+\.?\d+\)-.+$/g,/^.+-\(\d+\.?\d+\)\>.+$/g,/^.+<\(\d+\.?\d+\)\-.+$/g];let res=true;for(let i=0;i0||cols[j][vertexIndex]>0)&&j!=vertexIndex) +{relatedVertex.push(this.vertices[j]);}} +var diameter=(new VertexModel()).diameter;if(relatedVertex.length>1) +{for(var j=0;jmaxDistance) +{var force=(otherVertex.position.subtract(currentVertex.object.position)).normalize(edgeGravityKof*(distance-maxDistance));currentVertex.net_force=currentVertex.net_force.add(force);}}} +var distanceToCenter=centerPoint.distance(currentVertex.object.position);var force=centerPoint.subtract(currentVertex.object.position).normalize(distanceToCenter*kCenterForce);currentVertex.net_force=currentVertex.net_force.add(force);currentVertex.velocity=currentVertex.velocity.add(currentVertex.net_force);} +bChanged=false;for(i=0;ivelocityMax) +{velocity=velocity.normalize(velocityMax);} +v.object.position=v.object.position.add(velocity);if(velocity.length()>=1) +{bChanged=true;}} +k++;} +var bbox=this.getGraphBBox();if(bbox.size().length()>viewportSize.length()*1000) +{for(i=0;i=this.vertices.length) +{var newPos=this.GetRandomPositionOfVertex(matrix,j,viewportSize);newVertices.push(new BaseVertex(newPos.x,newPos.y,currentEnumVerticesType));this.AddNewVertex(newVertices[newVertices.length-1]);} +if(cols[i][j]>0) +{var nEdgeIndex=this.AddNewEdgeSafe(this.vertices[i],this.vertices[j],cols[i][j]!=cols[j][i],cols[i][j],true);this.FixEdgeCurve(nEdgeIndex);if(nEdgeIndex>=0) +{bWeightGraph=bWeightGraph||this.edges[nEdgeIndex].weight!=1;}}}} +if(!bWeightGraph) +{this.edges.forEach(function(part,index,theArray){theArray[index].useWeight=false;});} +for(var i=rows.length;i(.+)$/g,/^(.+)<(.+)$/g,/^(.+)-\((\d+|\d+\.?\d+)\)-(.+)$/g,/^(.+)-\((\d+|\d+\.?\d+)\)\>(.+)$/g,/^(.+)<\((\d+|\d+\.?\d+)\)\-(.+)$/g,];let bWeightGraph=false;var newVertices=[];for(var i=0;i=0;--j){if(!line.match(regExp[j])){continue;} +let groupes=Array.from(line.matchAll(regExp[j]));let groupe=groupes[0];let vetext1Title=groupe[1];let vertex1=this.FindVertexByTitle(vetext1Title);if(vertex1==null){let newPosition=this.GetRandomPosition(viewportSize);vertex1=this.vertices[this.AddNewVertex(new BaseVertex(newPosition.x,newPosition.y,currentEnumVerticesType))];vertex1.mainText=vetext1Title;newVertices.push(vertex1);} +let vetext2Title=groupe[j<=2?2:3];let vertex2=this.FindVertexByTitle(vetext2Title);if(vertex2==null){let newPosition=this.GetRandomPosition(viewportSize);vertex2=this.vertices[this.AddNewVertex(new BaseVertex(newPosition.x,newPosition.y,currentEnumVerticesType))];vertex2.mainText=vetext2Title;newVertices.push(vertex2);} +let isDirect=j==1||j==2||j==4||j==5;let weight=1;if(j>2){weight=groupe[2];bWeightGraph=true;} +let isRevertEdge=j==2||j==5;let nEdgeIndex=this.AddNewEdgeSafe(isRevertEdge?vertex2:vertex1,isRevertEdge?vertex1:vertex2,isDirect,weight,false);this.FixEdgeCurve(nEdgeIndex);break;}} +if(!bWeightGraph) +{this.edges.forEach(function(part,index,theArray){theArray[index].useWeight=false;});} +this.VerticesReposition(viewportSize,newVertices);}} +Graph.prototype.TestIncidenceMatrix=function(matrix,rowsObj,colsObj,separator) +{if(separator===undefined) +{separator=",";} +var bGoodFormat=true;rowsObj.rows=[];rowsObj.rows=matrix.split("\n");for(j=0;j=this.vertices.length) +{var newPos=new Point(0,0);newVertices.push(new BaseVertex(newPos.x,newPos.y,currentEnumVerticesType));this.AddNewVertex(newVertices[newVertices.length-1]);} +if(cols[j][i]!=0) +{edgeValue.push(cols[j][i]);edgeIndex.push(j);}} +if(edgeIndex.length==1) +{edgeValue.push(edgeValue[0]);edgeIndex.push(edgeIndex[0]);} +if(edgeIndex.length==2) +{if(edgeValue[0]!=edgeValue[1]) +{if(edgeValue[1]>0) +{edgeValue=edgeValue.swap(0,1);edgeIndex=edgeIndex.swap(0,1);}} +var nEdgeIndex=this.AddNewEdgeSafe(this.vertices[edgeIndex[0]],this.vertices[edgeIndex[1]],edgeValue[0]!=edgeValue[1],Math.abs(edgeValue[1]),false);this.FixEdgeCurve(nEdgeIndex);if(nEdgeIndex>=0) +{bWeightGraph=bWeightGraph||this.edges[nEdgeIndex].weight!=1;}}} +if(!bWeightGraph) +{this.edges.forEach(function(part,index,theArray){theArray[index].useWeight=false;});} +for(var i=cols.length;i0) +{res.push(line.substr(0,i));} +if(i==0) +{i=1;} +line=line.substr(i,line.length-i);i=-1;}} +if(line.length>0) +{res.push(line);}} +else +{for(i=0;i";var header="";var xmlBody="";for(var i=0;i0) +{additionalField=""} +return mainHeader+header+xmlBody+""+additionalField+"";} +Graph.prototype.LoadFromXML=function(xmlText,additionalData) +{xmlDoc=$.parseXML(xmlText);var $xml=$(xmlDoc);$graphs=$xml.find("graph");var loadedGraphId=0;var loadedEdgeId=0;$graphs.each(function(){loadedGraphId=parseInt($(this).attr('uidGraph'));loadedEdgeId=parseInt($(this).attr('uidEdge'));});if(isNaN(loadedEdgeId)) +{loadedEdgeId=this.edgesOffset;}else if(loadedEdgeId0;} +Graph.prototype.clampPositions=function(viewportSize) +{var diameter=(new VertexModel()).diameter;for(i=0;i=2) +{var curve=this.GetAvailableCurveValue(neighborEdges,edgeObject);if(edgeObject.model.default) +{edgeObject.model.type=EdgeModels.curve;edgeObject.model.curveValue=curve;}}} +Graph.prototype.GetAvailableCurveValue=function(neighborEdges,originalEdge) +{var values=[];for(var i=0;i=Math.min(x1,x2)-epsilon&&res.x>=Math.min(x3,x4)-epsilon&&res.x<=Math.max(x1,x2)+epsilon&&res.x<=Math.max(x3,x4)+epsilon&&res.y>=Math.min(y1,y2)-epsilon&&res.y>=Math.min(y3,y4)-epsilon&&res.y<=Math.max(y1,y2)+epsilon&&res.y<=Math.max(y3,y4)+epsilon)) +{res=null;} +return res;} +function Rect(minPoint,maxPoint){this.minPoint=minPoint;this.maxPoint=maxPoint;};Rect.prototype.center=function() +{return Point.center(this.minPoint,this.maxPoint);};Rect.prototype.size=function() +{return this.maxPoint.subtract(this.minPoint);};Rect.prototype.left=function() +{return this.minPoint.x;};Rect.prototype.top=function() +{return this.minPoint.y;};Rect.prototype.isIn=function(v) +{return this.minPoint.x<=v.x&&this.minPoint.y<=v.y&&this.maxPoint.x>v.x&&this.maxPoint.y>v.y;};{let modulDir="entities/edge/";doInclude([include("model/BaseEdge.js",modulDir),include("model/EdgeModel.js",modulDir)])} +function BaseEdge(vertex1,vertex2,isDirect,weight,upText) +{this.vertex1=vertex1;this.vertex2=vertex2;this.arrayStyleStart="";this.arrayStyleFinish="";this.isDirect=isDirect;this.weight=0;this.text="";this.useWeight=false;this.id=0;this.model=new EdgeModel();if(upText===undefined) +this.upText="";else +this.upText=upText;if(weight!==undefined) +this.SetWeight(weight);this.ownStyles={};} +BaseEdge.prototype.copyFrom=function(other) +{this.vertex1=other.vertex1;this.vertex2=other.vertex2;this.arrayStyleStart=other.arrayStyleStart;this.arrayStyleFinish=other.arrayStyleFinish;this.isDirect=other.isDirect;this.weight=other.weight;this.text=other.text;this.useWeight=other.useWeight;this.id=other.id;this.model=new EdgeModel();this.model.copyFrom(other.model);this.upText=other.upText;this.ownStyles=FullObjectCopy(other.ownStyles);} +BaseEdge.prototype.SaveToXML=function() +{return"0)?"ownStyles = \""+gEncodeToHTML(JSON.stringify(this.ownStyles))+"\" ":"")+ +this.model.SaveToXML()+">";} +BaseEdge.prototype.LoadFromXML=function(xml,graph) +{var attr=xml.attr('vertex1');if(typeof attr==='undefined') +{attr=xml.attr('source');} +this.vertex1=graph.FindVertex(typeof attr!=='undefined'?attr:xml.attr('graph1'));var attr=xml.attr('vertex2');if(typeof attr==='undefined') +{attr=xml.attr('target');} +this.vertex2=graph.FindVertex(typeof attr!=='undefined'?attr:xml.attr('graph2'));this.isDirect=xml.attr('isDirect')=="true";this.weight=parseFloat(xml.attr('weight'));if(isNaN(this.weight)) +{this.weight=1;} +this.hasPair=xml.attr('hasPair')=="true";this.useWeight=xml.attr('useWeight')=="true";this.id=xml.attr('id');this.text=xml.attr("text")==null?"":gDecodeFromHTML(xml.attr("text"));this.arrayStyleStart=xml.attr("arrayStyleStart")==null?"":xml.attr("arrayStyleStart");this.arrayStyleFinish=xml.attr("arrayStyleFinish")==null?"":xml.attr("arrayStyleFinish");this.upText=xml.attr('upText');if(typeof this.upText==='undefined') +{this.upText="";} +else +{this.upText=gDecodeFromHTML(this.upText);} +var ownStyle=xml.attr('ownStyles');if(typeof ownStyle!=='undefined') +{var parsedSave=gDecodeFromHTML(JSON.parse(ownStyle));for(var indexField in parsedSave) +{var index=parseInt(indexField);this.ownStyles[index]=FullObjectCopy(this.getStyleFor(index));for(var field in parsedSave[indexField]) +{if(this.ownStyles[index].ShouldLoad(field)) +this.ownStyles[index][field]=parsedSave[indexField][field];}}} +this.model.LoadFromXML(xml);} +BaseEdge.prototype.GetPixelLength=function() +{if(this.vertex1==this.vertex2) +{return this.model.GetLoopSize()*2*Math.PI;} +else +{return Point.distance(this.vertex1.position,this.vertex2.position);}} +BaseEdge.prototype.GetWeight=function() +{return this.useWeight?this.weight:1;} +BaseEdge.prototype.GetText=function() +{return this.text.length>0?this.text:(this.useWeight?this.weight.toString():"");} +BaseEdge.prototype.GetUpText=function() +{return this.upText;} +BaseEdge.prototype.GetStartEdgeStyle=function() +{return this.arrayStyleStart;} +BaseEdge.prototype.GetFinishEdgeStyle=function() +{return(this.arrayStyleFinish!=""?this.arrayStyleFinish:(this.isDirect?"arrow":""));} +BaseEdge.prototype.HitTest=function(pos) +{var positions=this.GetEdgePositionsShift();return this.model.HitTest(positions[0],positions[1],pos);} +BaseEdge.prototype.GetEdgePositionsShift=function() +{return this.GetEdgePositions();} +BaseEdge.prototype.GetEdgePositions=function() +{var res=[];if(this.vertex1==this.vertex2) +{res.push(this.vertex1.position);res.push(this.vertex2.position);return res;} +var position1=this.vertex1.position;var position2=this.vertex2.position;var diameter1=this.vertex1.model.diameter+parseInt(this.vertex1.currentStyle.GetStyle({},this.vertex1).lineWidth);var diameter2=this.vertex2.model.diameter+parseInt(this.vertex2.currentStyle.GetStyle({},this.vertex2).lineWidth);var direction=position1.subtract(position2);var direction1=direction;var direction2=direction;var d1=diameter1;var d2=diameter2;if(this.model.type==EdgeModels.curve) +{var dist=position1.distance(position2);var point1=this.model.GetCurvePoint(position1,position2,10.0/dist);direction1=position1.subtract(point1);var point2=this.model.GetCurvePoint(position1,position2,1.0-10.0/dist);direction2=position2.subtract(point2);d2=diameter2;} +else +{direction2=direction2.multiply(-1);} +direction1.normalize(1.0);direction2.normalize(1.0);var vertices=[];vertices.push({vertex:this.vertex1,direction:direction1,position:position1,diameter:d1});vertices.push({vertex:this.vertex2,direction:direction2,position:position2,diameter:d2});vertices.forEach(function(data) +{var shape=data.vertex.currentStyle.GetStyle({},data.vertex).shape;if(shape==VertexCircleShape) +{var direction=data.direction.multiply(0.5);res.push(data.position.subtract(direction.multiply(data.diameter)));} +else +{var lineFinish1=data.direction.multiply(-1).multiply(1000.0);var pointsVertex1=GetPointsForShape(shape,data.diameter,data.vertex.mainText);pointsVertex1.push(pointsVertex1[0]);for(var i=0;i=0)?weight:1;this.weight=Number(weight);this.useWeight=useWeight;} +BaseEdge.prototype.SetUpText=function(text) +{this.upText=text;} +BaseEdge.prototype.resetOwnStyle=function(index) +{if(this.ownStyles.hasOwnProperty(index)) +{delete this.ownStyles[index];}} +BaseEdge.prototype.setOwnStyle=function(index,style) +{this.ownStyles[index]=style;} +BaseEdge.prototype.getStyleFor=function(index) +{if(this.ownStyles.hasOwnProperty(index)) +{return this.ownStyles[index];} +else +{var style=null;if(index==0) +style=globalApplication.GetStyle("edge","common");else +style=globalApplication.GetStyle("edge","selected",undefined,index-1);return style;}} +BaseEdge.prototype.hasOwnStyleFor=function(index) +{return this.ownStyles.hasOwnProperty(index);} +var EdgeModels={"line":0,"curve":1};const defaultEdgeWidth=4;function EdgeModel() +{this.width=globalApplication.GetDefaultEdgeWidth();this.type=EdgeModels.line;this.curveValue=EdgeModel.prototype.defaultCurve;this.default=true;this.sizeOfLoop=24;this.loopShiftAngel=Math.PI/6;} +EdgeModel.prototype.defaultCurve=0.1;EdgeModel.prototype.copyFrom=function(other) +{this.width=other.width;this.type=other.type;this.curveValue=other.curveValue;this.default=other.default;} +EdgeModel.prototype.SaveToXML=function() +{return"model_width=\""+this.width+"\" "+"model_type=\""+this.type+"\" "+"model_curveValue=\""+this.curveValue+"\" "+"model_default=\""+this.default+"\" ";} +EdgeModel.prototype.LoadFromXML=function(xml,graph) +{this.width=xml.attr('model_width')==null?this.width:parseFloat(xml.attr("model_width"));this.type=xml.attr('model_type')==null?this.type:xml.attr("model_type");this.curveValue=xml.attr('model_curveValue')==null?this.curveValue:parseFloat(xml.attr("model_curveValue"));this.default=xml.attr('model_default')==null?this.default:parseFloat(xml.attr("model_default"));} +EdgeModel.prototype.GetCurvePoint=function(position1,position2,t) +{var points=this.GetBezierPoints(position1,position2);var firstBezierPoint=points[0];var secondBezierPoint=points[1];var B0_t=Math.pow(1-t,3);var B1_t=3*t*Math.pow(1-t,2);var B2_t=3*t*t*(1-t) +var B3_t=t*t*t;var ax=position1.x;var ay=position1.y;var dx=position2.x;var dy=position2.y;var bx=firstBezierPoint.x;var by=firstBezierPoint.y;var cx=secondBezierPoint.x;var cy=secondBezierPoint.y;var px_t=(B0_t*ax)+(B1_t*bx)+(B2_t*cx)+(B3_t*dx);var py_t=(B0_t*ay)+(B1_t*by)+(B2_t*cy)+(B3_t*dy);return new Point(px_t,py_t);} +EdgeModel.prototype.GetBezierPoints=function(position1,position2) +{var direction=position2.subtract(position1);var delta=direction.length();direction.normalize(1.0);var normal=direction.normal();var deltaOffsetPixels=delta*this.curveValue;var yOffset=normal.multiply(deltaOffsetPixels);var firstBezierPointShift=(direction.multiply(delta*0.2)).add(yOffset);var secondBezierPointShift=(direction.multiply(-delta*0.2)).add(yOffset);var firstBezierPoint=position1.add(firstBezierPointShift);var secondBezierPoint=position2.add(secondBezierPointShift);return[firstBezierPoint,secondBezierPoint];} +EdgeModel.prototype.HitTest=function(position1,position2,mousePos) +{if(this.type==EdgeModels.line) +return this.HitTestLine(position1,position2,mousePos);else if(this.type==EdgeModels.curve) +return this.HitTestCurve(position1,position2,mousePos);return false;} +EdgeModel.prototype.HitTestLine=function(position1,position2,mousePos,factor) +{if(factor===undefined) +{factor=1.0;} +var pos1=position1;var pos2=position2;var pos0=mousePos;if(pos1.equals(pos2)) +{var xCenter=pos1.x-Math.cos(this.GetLoopShiftAngel())*this.GetLoopSize();var yCenter=pos1.y-Math.sin(this.GetLoopShiftAngel())*this.GetLoopSize();return Math.abs((Point.distance(new Point(xCenter,yCenter),pos0))-this.GetLoopSize())<=this.width*1.5*factor;} +var r1=pos0.distance(pos1);var r2=pos0.distance(pos2);var r12=pos1.distance(pos2);if(r1>=(new Point(r2,r12)).length()||r2>=(new Point(r1,r12)).length()) +{} +else +{var distance=((pos1.y-pos2.y)*pos0.x+(pos2.x-pos1.x)*pos0.y+(pos1.x*pos2.y-pos2.x*pos1.y))/r12;if(Math.abs(distance)<=this.width*1.5*factor) +{return true;}} +return false;} +EdgeModel.prototype.HitTestCurve=function(position1,position2,mousePos) +{var pos1=position1;var pos2=position2;var pos0=mousePos;if(pos1.equals(pos2)) +{var xCenter=pos1.x-Math.cos(this.GetLoopShiftAngel())*this.GetLoopSize();var yCenter=pos1.y-Math.sin(this.GetLoopShiftAngel())*this.GetLoopSize();return Math.abs((Point.distance(new Point(xCenter,yCenter),pos0))-this.GetLoopSize())<=this.width*1.5;} +var interval_count=position1.distance(position2)/100*30;var start=position1;for(var i=0;i=0.0){normalCurve+=this.defaultCurve} +return this.sizeOfLoop*Math.abs(normalCurve)*(1/this.defaultCurve);}} +EdgeModel.prototype.GetLoopShiftAngel=function() +{if(this.type==EdgeModels.line||this.curveValue>=0.0) +{return this.loopShiftAngel;} +else +{return this.loopShiftAngel+Math.PI;}} +{let modulDir="entities/vertex/";doInclude([include("model/BaseVertex.js",modulDir),include("model/VertexModel.js",modulDir)])} +function BaseVertex(x,y,vertexEnumType) +{this.position=new Point(x,y);this.id=0;this.mainText="";this.upText="";this.vertexEnumType=vertexEnumType;this.model=new VertexModel();this.hasUndefinedPosition=false;this.ownStyles={};};BaseVertex.prototype.position=new Point(0,0);BaseVertex.prototype.copyFrom=function(other) +{this.position=new Point(other.position.x,other.position.y);this.id=other.id;this.mainText=other.mainText;this.upText=other.upText;this.vertexEnumType=other.vertexEnumType;this.model=new VertexModel();this.hasUndefinedPosition=other.hasUndefinedPosition;this.ownStyles=FullObjectCopy(other.ownStyles);} +BaseVertex.prototype.SaveToXML=function() +{return"0)?"ownStyles = \""+gEncodeToHTML(JSON.stringify(this.ownStyles))+"\" ":"")+"size=\""+this.model.diameter+"\" "+">";} +BaseVertex.prototype.LoadFromXML=function(xml) +{var xmlX=xml.attr('positionX');var xmlY=xml.attr('positionY');this.hasUndefinedPosition=(typeof xmlX==='undefined')||(typeof xmlY==='undefined');this.position=new Point(parseFloat(xmlX),parseFloat(xmlY));this.id=xml.attr('id');this.mainText=xml.attr('mainText');this.upText=xml.attr('upText');if(typeof this.mainText==='undefined') +this.mainText=this.id;else +this.mainText=gDecodeFromHTML(this.mainText);if(typeof this.upText==='undefined') +this.upText="";else +this.upText=gDecodeFromHTML(this.upText);var ownStyle=xml.attr('ownStyles');if(typeof ownStyle!=='undefined') +{var parsedSave=gDecodeFromHTML(JSON.parse(ownStyle));for(var indexField in parsedSave) +{var index=parseInt(indexField);this.ownStyles[index]=FullObjectCopy(this.getStyleFor(index));for(var field in parsedSave[indexField]) +{if(this.ownStyles[index].ShouldLoad(field)) +this.ownStyles[index][field]=parsedSave[indexField][field];}}} +var size=xml.attr('size');if(typeof size!=='undefined') +this.model.diameter=parseInt(size);} +BaseVertex.prototype.SetId=function(id) +{this.id=id;if(this.vertexEnumType!=null) +this.mainText=this.vertexEnumType.GetVertexText(id);} +BaseVertex.prototype.diameterFactor=function() +{return new Point(1.0+(this.mainText.length?this.mainText.length/8.0:0),1.5);} +BaseVertex.prototype.IsUndefinedPosition=function() +{return this.hasUndefinedPosition;} +BaseVertex.prototype.HitTest=function(pos) +{var shape=this.hasOwnProperty('currentStyle')?this.currentStyle.GetStyle({},this).shape:VertexCircleShape;var width=this.hasOwnProperty('currentStyle')?this.currentStyle.GetStyle({},this).lineWidth:0;if(shape==VertexCircleShape) +{return this.position.distance(pos)-1) +{this.edges.splice(index,1);} +this.isMultiGraph=this.checkMutiGraph();} +Graph.prototype.DeleteVertex=function(vertexObject) +{var index=this.vertices.indexOf(vertexObject);if(index>-1) +{for(var i=0;i-1) +{for(var i=0;imaxWeight) +{res=edge;maxWeight=edge.weight;}}} +return res;} +Graph.prototype.FindEdgeMinIgnoreDirection=function(id1,id2) +{var res=null;var minWeight=this.infinity;for(var i=0;i.+$/g,/^.+<.+$/g,/^.+-\(\d+\.?\d+\)-.+$/g,/^.+-\(\d+\.?\d+\)\>.+$/g,/^.+<\(\d+\.?\d+\)\-.+$/g];let res=true;for(let i=0;i0||cols[j][vertexIndex]>0)&&j!=vertexIndex) +{relatedVertex.push(this.vertices[j]);}} +var diameter=(new VertexModel()).diameter;if(relatedVertex.length>1) +{for(var j=0;jmaxDistance) +{var force=(otherVertex.position.subtract(currentVertex.object.position)).normalize(edgeGravityKof*(distance-maxDistance));currentVertex.net_force=currentVertex.net_force.add(force);}}} +var distanceToCenter=centerPoint.distance(currentVertex.object.position);var force=centerPoint.subtract(currentVertex.object.position).normalize(distanceToCenter*kCenterForce);currentVertex.net_force=currentVertex.net_force.add(force);currentVertex.velocity=currentVertex.velocity.add(currentVertex.net_force);} +bChanged=false;for(i=0;ivelocityMax) +{velocity=velocity.normalize(velocityMax);} +v.object.position=v.object.position.add(velocity);if(velocity.length()>=1) +{bChanged=true;}} +k++;} +var bbox=this.getGraphBBox();if(bbox.size().length()>viewportSize.length()*1000) +{for(i=0;i=this.vertices.length) +{var newPos=this.GetRandomPositionOfVertex(matrix,j,viewportSize);newVertices.push(new BaseVertex(newPos.x,newPos.y,currentEnumVerticesType));this.AddNewVertex(newVertices[newVertices.length-1]);} +if(cols[i][j]>0) +{var nEdgeIndex=this.AddNewEdgeSafe(this.vertices[i],this.vertices[j],cols[i][j]!=cols[j][i],cols[i][j],true);this.FixEdgeCurve(nEdgeIndex);if(nEdgeIndex>=0) +{bWeightGraph=bWeightGraph||this.edges[nEdgeIndex].weight!=1;}}}} +if(!bWeightGraph) +{this.edges.forEach(function(part,index,theArray){theArray[index].useWeight=false;});} +for(var i=rows.length;i(.+)$/g,/^(.+)<(.+)$/g,/^(.+)-\((\d+|\d+\.?\d+)\)-(.+)$/g,/^(.+)-\((\d+|\d+\.?\d+)\)\>(.+)$/g,/^(.+)<\((\d+|\d+\.?\d+)\)\-(.+)$/g,];let bWeightGraph=false;var newVertices=[];for(var i=0;i=0;--j){if(!line.match(regExp[j])){continue;} +let groupes=Array.from(line.matchAll(regExp[j]));let groupe=groupes[0];let vetext1Title=groupe[1];let vertex1=this.FindVertexByTitle(vetext1Title);if(vertex1==null){let newPosition=this.GetRandomPosition(viewportSize);vertex1=this.vertices[this.AddNewVertex(new BaseVertex(newPosition.x,newPosition.y,currentEnumVerticesType))];vertex1.mainText=vetext1Title;newVertices.push(vertex1);} +let vetext2Title=groupe[j<=2?2:3];let vertex2=this.FindVertexByTitle(vetext2Title);if(vertex2==null){let newPosition=this.GetRandomPosition(viewportSize);vertex2=this.vertices[this.AddNewVertex(new BaseVertex(newPosition.x,newPosition.y,currentEnumVerticesType))];vertex2.mainText=vetext2Title;newVertices.push(vertex2);} +let isDirect=j==1||j==2||j==4||j==5;let weight=1;if(j>2){weight=groupe[2];bWeightGraph=true;} +let isRevertEdge=j==2||j==5;let nEdgeIndex=this.AddNewEdgeSafe(isRevertEdge?vertex2:vertex1,isRevertEdge?vertex1:vertex2,isDirect,weight,false);this.FixEdgeCurve(nEdgeIndex);break;}} +if(!bWeightGraph) +{this.edges.forEach(function(part,index,theArray){theArray[index].useWeight=false;});} +this.VerticesReposition(viewportSize,newVertices);}} +Graph.prototype.TestIncidenceMatrix=function(matrix,rowsObj,colsObj,separator) +{if(separator===undefined) +{separator=",";} +var bGoodFormat=true;rowsObj.rows=[];rowsObj.rows=matrix.split("\n");for(j=0;j=this.vertices.length) +{var newPos=new Point(0,0);newVertices.push(new BaseVertex(newPos.x,newPos.y,currentEnumVerticesType));this.AddNewVertex(newVertices[newVertices.length-1]);} +if(cols[j][i]!=0) +{edgeValue.push(cols[j][i]);edgeIndex.push(j);}} +if(edgeIndex.length==1) +{edgeValue.push(edgeValue[0]);edgeIndex.push(edgeIndex[0]);} +if(edgeIndex.length==2) +{if(edgeValue[0]!=edgeValue[1]) +{if(edgeValue[1]>0) +{edgeValue=edgeValue.swap(0,1);edgeIndex=edgeIndex.swap(0,1);}} +var nEdgeIndex=this.AddNewEdgeSafe(this.vertices[edgeIndex[0]],this.vertices[edgeIndex[1]],edgeValue[0]!=edgeValue[1],Math.abs(edgeValue[1]),false);this.FixEdgeCurve(nEdgeIndex);if(nEdgeIndex>=0) +{bWeightGraph=bWeightGraph||this.edges[nEdgeIndex].weight!=1;}}} +if(!bWeightGraph) +{this.edges.forEach(function(part,index,theArray){theArray[index].useWeight=false;});} +for(var i=cols.length;i0) +{res.push(line.substr(0,i));} +if(i==0) +{i=1;} +line=line.substr(i,line.length-i);i=-1;}} +if(line.length>0) +{res.push(line);}} +else +{for(i=0;i";var header="";var xmlBody="";for(var i=0;i0) +{additionalField=""} +return mainHeader+header+xmlBody+""+additionalField+"";} +Graph.prototype.LoadFromXML=function(xmlText,additionalData) +{xmlDoc=$.parseXML(xmlText);var $xml=$(xmlDoc);$graphs=$xml.find("graph");var loadedGraphId=0;var loadedEdgeId=0;$graphs.each(function(){loadedGraphId=parseInt($(this).attr('uidGraph'));loadedEdgeId=parseInt($(this).attr('uidEdge'));});if(isNaN(loadedEdgeId)) +{loadedEdgeId=this.edgesOffset;}else if(loadedEdgeId0;} +Graph.prototype.clampPositions=function(viewportSize) +{var diameter=(new VertexModel()).diameter;for(i=0;i=2) +{var curve=this.GetAvailableCurveValue(neighborEdges,edgeObject);if(edgeObject.model.default) +{edgeObject.model.type=EdgeModels.curve;edgeObject.model.curveValue=curve;}}} +Graph.prototype.GetAvailableCurveValue=function(neighborEdges,originalEdge) +{var values=[];for(var i=0;i=Math.min(x1,x2)-epsilon&&res.x>=Math.min(x3,x4)-epsilon&&res.x<=Math.max(x1,x2)+epsilon&&res.x<=Math.max(x3,x4)+epsilon&&res.y>=Math.min(y1,y2)-epsilon&&res.y>=Math.min(y3,y4)-epsilon&&res.y<=Math.max(y1,y2)+epsilon&&res.y<=Math.max(y3,y4)+epsilon)) +{res=null;} +return res;} +function Rect(minPoint,maxPoint){this.minPoint=minPoint;this.maxPoint=maxPoint;};Rect.prototype.center=function() +{return Point.center(this.minPoint,this.maxPoint);};Rect.prototype.size=function() +{return this.maxPoint.subtract(this.minPoint);};Rect.prototype.left=function() +{return this.minPoint.x;};Rect.prototype.top=function() +{return this.minPoint.y;};Rect.prototype.isIn=function(v) +{return this.minPoint.x<=v.x&&this.minPoint.y<=v.y&&this.maxPoint.x>v.x&&this.maxPoint.y>v.y;};{let modulDir="entities/edge/";doInclude([include("model/BaseEdge.js",modulDir),include("model/EdgeModel.js",modulDir)])} +function BaseEdge(vertex1,vertex2,isDirect,weight,upText) +{this.vertex1=vertex1;this.vertex2=vertex2;this.arrayStyleStart="";this.arrayStyleFinish="";this.isDirect=isDirect;this.weight=0;this.text="";this.useWeight=false;this.id=0;this.model=new EdgeModel();if(upText===undefined) +this.upText="";else +this.upText=upText;if(weight!==undefined) +this.SetWeight(weight);this.ownStyles={};} +BaseEdge.prototype.copyFrom=function(other) +{this.vertex1=other.vertex1;this.vertex2=other.vertex2;this.arrayStyleStart=other.arrayStyleStart;this.arrayStyleFinish=other.arrayStyleFinish;this.isDirect=other.isDirect;this.weight=other.weight;this.text=other.text;this.useWeight=other.useWeight;this.id=other.id;this.model=new EdgeModel();this.model.copyFrom(other.model);this.upText=other.upText;this.ownStyles=FullObjectCopy(other.ownStyles);} +BaseEdge.prototype.SaveToXML=function() +{return"0)?"ownStyles = \""+gEncodeToHTML(JSON.stringify(this.ownStyles))+"\" ":"")+ +this.model.SaveToXML()+">";} +BaseEdge.prototype.LoadFromXML=function(xml,graph) +{var attr=xml.attr('vertex1');if(typeof attr==='undefined') +{attr=xml.attr('source');} +this.vertex1=graph.FindVertex(typeof attr!=='undefined'?attr:xml.attr('graph1'));var attr=xml.attr('vertex2');if(typeof attr==='undefined') +{attr=xml.attr('target');} +this.vertex2=graph.FindVertex(typeof attr!=='undefined'?attr:xml.attr('graph2'));this.isDirect=xml.attr('isDirect')=="true";this.weight=parseFloat(xml.attr('weight'));if(isNaN(this.weight)) +{this.weight=1;} +this.hasPair=xml.attr('hasPair')=="true";this.useWeight=xml.attr('useWeight')=="true";this.id=xml.attr('id');this.text=xml.attr("text")==null?"":gDecodeFromHTML(xml.attr("text"));this.arrayStyleStart=xml.attr("arrayStyleStart")==null?"":xml.attr("arrayStyleStart");this.arrayStyleFinish=xml.attr("arrayStyleFinish")==null?"":xml.attr("arrayStyleFinish");this.upText=xml.attr('upText');if(typeof this.upText==='undefined') +{this.upText="";} +else +{this.upText=gDecodeFromHTML(this.upText);} +var ownStyle=xml.attr('ownStyles');if(typeof ownStyle!=='undefined') +{var parsedSave=gDecodeFromHTML(JSON.parse(ownStyle));for(var indexField in parsedSave) +{var index=parseInt(indexField);this.ownStyles[index]=FullObjectCopy(this.getStyleFor(index));for(var field in parsedSave[indexField]) +{if(this.ownStyles[index].ShouldLoad(field)) +this.ownStyles[index][field]=parsedSave[indexField][field];}}} +this.model.LoadFromXML(xml);} +BaseEdge.prototype.GetPixelLength=function() +{if(this.vertex1==this.vertex2) +{return this.model.GetLoopSize()*2*Math.PI;} +else +{return Point.distance(this.vertex1.position,this.vertex2.position);}} +BaseEdge.prototype.GetWeight=function() +{return this.useWeight?this.weight:1;} +BaseEdge.prototype.GetText=function() +{return this.text.length>0?this.text:(this.useWeight?this.weight.toString():"");} +BaseEdge.prototype.GetUpText=function() +{return this.upText;} +BaseEdge.prototype.GetStartEdgeStyle=function() +{return this.arrayStyleStart;} +BaseEdge.prototype.GetFinishEdgeStyle=function() +{return(this.arrayStyleFinish!=""?this.arrayStyleFinish:(this.isDirect?"arrow":""));} +BaseEdge.prototype.HitTest=function(pos) +{var positions=this.GetEdgePositionsShift();return this.model.HitTest(positions[0],positions[1],pos);} +BaseEdge.prototype.GetEdgePositionsShift=function() +{return this.GetEdgePositions();} +BaseEdge.prototype.GetEdgePositions=function() +{var res=[];if(this.vertex1==this.vertex2) +{res.push(this.vertex1.position);res.push(this.vertex2.position);return res;} +var position1=this.vertex1.position;var position2=this.vertex2.position;var diameter1=this.vertex1.model.diameter+parseInt(this.vertex1.currentStyle.GetStyle({},this.vertex1).lineWidth);var diameter2=this.vertex2.model.diameter+parseInt(this.vertex2.currentStyle.GetStyle({},this.vertex2).lineWidth);var direction=position1.subtract(position2);var direction1=direction;var direction2=direction;var d1=diameter1;var d2=diameter2;if(this.model.type==EdgeModels.curve) +{var dist=position1.distance(position2);var point1=this.model.GetCurvePoint(position1,position2,10.0/dist);direction1=position1.subtract(point1);var point2=this.model.GetCurvePoint(position1,position2,1.0-10.0/dist);direction2=position2.subtract(point2);d2=diameter2;} +else +{direction2=direction2.multiply(-1);} +direction1.normalize(1.0);direction2.normalize(1.0);var vertices=[];vertices.push({vertex:this.vertex1,direction:direction1,position:position1,diameter:d1});vertices.push({vertex:this.vertex2,direction:direction2,position:position2,diameter:d2});vertices.forEach(function(data) +{var shape=data.vertex.currentStyle.GetStyle({},data.vertex).shape;if(shape==VertexCircleShape) +{var direction=data.direction.multiply(0.5);res.push(data.position.subtract(direction.multiply(data.diameter)));} +else +{var lineFinish1=data.direction.multiply(-1).multiply(1000.0);var pointsVertex1=GetPointsForShape(shape,data.diameter,data.vertex.mainText);pointsVertex1.push(pointsVertex1[0]);for(var i=0;i=0)?weight:1;this.weight=Number(weight);this.useWeight=useWeight;} +BaseEdge.prototype.SetUpText=function(text) +{this.upText=text;} +BaseEdge.prototype.resetOwnStyle=function(index) +{if(this.ownStyles.hasOwnProperty(index)) +{delete this.ownStyles[index];}} +BaseEdge.prototype.setOwnStyle=function(index,style) +{this.ownStyles[index]=style;} +BaseEdge.prototype.getStyleFor=function(index) +{if(this.ownStyles.hasOwnProperty(index)) +{return this.ownStyles[index];} +else +{var style=null;if(index==0) +style=globalApplication.GetStyle("edge","common");else +style=globalApplication.GetStyle("edge","selected",undefined,index-1);return style;}} +BaseEdge.prototype.hasOwnStyleFor=function(index) +{return this.ownStyles.hasOwnProperty(index);} +var EdgeModels={"line":0,"curve":1};const defaultEdgeWidth=4;function EdgeModel() +{this.width=globalApplication.GetDefaultEdgeWidth();this.type=EdgeModels.line;this.curveValue=EdgeModel.prototype.defaultCurve;this.default=true;this.sizeOfLoop=24;this.loopShiftAngel=Math.PI/6;} +EdgeModel.prototype.defaultCurve=0.1;EdgeModel.prototype.copyFrom=function(other) +{this.width=other.width;this.type=other.type;this.curveValue=other.curveValue;this.default=other.default;} +EdgeModel.prototype.SaveToXML=function() +{return"model_width=\""+this.width+"\" "+"model_type=\""+this.type+"\" "+"model_curveValue=\""+this.curveValue+"\" "+"model_default=\""+this.default+"\" ";} +EdgeModel.prototype.LoadFromXML=function(xml,graph) +{this.width=xml.attr('model_width')==null?this.width:parseFloat(xml.attr("model_width"));this.type=xml.attr('model_type')==null?this.type:xml.attr("model_type");this.curveValue=xml.attr('model_curveValue')==null?this.curveValue:parseFloat(xml.attr("model_curveValue"));this.default=xml.attr('model_default')==null?this.default:parseFloat(xml.attr("model_default"));} +EdgeModel.prototype.GetCurvePoint=function(position1,position2,t) +{var points=this.GetBezierPoints(position1,position2);var firstBezierPoint=points[0];var secondBezierPoint=points[1];var B0_t=Math.pow(1-t,3);var B1_t=3*t*Math.pow(1-t,2);var B2_t=3*t*t*(1-t) +var B3_t=t*t*t;var ax=position1.x;var ay=position1.y;var dx=position2.x;var dy=position2.y;var bx=firstBezierPoint.x;var by=firstBezierPoint.y;var cx=secondBezierPoint.x;var cy=secondBezierPoint.y;var px_t=(B0_t*ax)+(B1_t*bx)+(B2_t*cx)+(B3_t*dx);var py_t=(B0_t*ay)+(B1_t*by)+(B2_t*cy)+(B3_t*dy);return new Point(px_t,py_t);} +EdgeModel.prototype.GetBezierPoints=function(position1,position2) +{var direction=position2.subtract(position1);var delta=direction.length();direction.normalize(1.0);var normal=direction.normal();var deltaOffsetPixels=delta*this.curveValue;var yOffset=normal.multiply(deltaOffsetPixels);var firstBezierPointShift=(direction.multiply(delta*0.2)).add(yOffset);var secondBezierPointShift=(direction.multiply(-delta*0.2)).add(yOffset);var firstBezierPoint=position1.add(firstBezierPointShift);var secondBezierPoint=position2.add(secondBezierPointShift);return[firstBezierPoint,secondBezierPoint];} +EdgeModel.prototype.HitTest=function(position1,position2,mousePos) +{if(this.type==EdgeModels.line) +return this.HitTestLine(position1,position2,mousePos);else if(this.type==EdgeModels.curve) +return this.HitTestCurve(position1,position2,mousePos);return false;} +EdgeModel.prototype.HitTestLine=function(position1,position2,mousePos,factor) +{if(factor===undefined) +{factor=1.0;} +var pos1=position1;var pos2=position2;var pos0=mousePos;if(pos1.equals(pos2)) +{var xCenter=pos1.x-Math.cos(this.GetLoopShiftAngel())*this.GetLoopSize();var yCenter=pos1.y-Math.sin(this.GetLoopShiftAngel())*this.GetLoopSize();return Math.abs((Point.distance(new Point(xCenter,yCenter),pos0))-this.GetLoopSize())<=this.width*1.5*factor;} +var r1=pos0.distance(pos1);var r2=pos0.distance(pos2);var r12=pos1.distance(pos2);if(r1>=(new Point(r2,r12)).length()||r2>=(new Point(r1,r12)).length()) +{} +else +{var distance=((pos1.y-pos2.y)*pos0.x+(pos2.x-pos1.x)*pos0.y+(pos1.x*pos2.y-pos2.x*pos1.y))/r12;if(Math.abs(distance)<=this.width*1.5*factor) +{return true;}} +return false;} +EdgeModel.prototype.HitTestCurve=function(position1,position2,mousePos) +{var pos1=position1;var pos2=position2;var pos0=mousePos;if(pos1.equals(pos2)) +{var xCenter=pos1.x-Math.cos(this.GetLoopShiftAngel())*this.GetLoopSize();var yCenter=pos1.y-Math.sin(this.GetLoopShiftAngel())*this.GetLoopSize();return Math.abs((Point.distance(new Point(xCenter,yCenter),pos0))-this.GetLoopSize())<=this.width*1.5;} +var interval_count=position1.distance(position2)/100*30;var start=position1;for(var i=0;i=0.0){normalCurve+=this.defaultCurve} +return this.sizeOfLoop*Math.abs(normalCurve)*(1/this.defaultCurve);}} +EdgeModel.prototype.GetLoopShiftAngel=function() +{if(this.type==EdgeModels.line||this.curveValue>=0.0) +{return this.loopShiftAngel;} +else +{return this.loopShiftAngel+Math.PI;}} +{let modulDir="entities/vertex/";doInclude([include("model/BaseVertex.js",modulDir),include("model/VertexModel.js",modulDir)])} +function BaseVertex(x,y,vertexEnumType) +{this.position=new Point(x,y);this.id=0;this.mainText="";this.upText="";this.vertexEnumType=vertexEnumType;this.model=new VertexModel();this.hasUndefinedPosition=false;this.ownStyles={};};BaseVertex.prototype.position=new Point(0,0);BaseVertex.prototype.copyFrom=function(other) +{this.position=new Point(other.position.x,other.position.y);this.id=other.id;this.mainText=other.mainText;this.upText=other.upText;this.vertexEnumType=other.vertexEnumType;this.model=new VertexModel();this.hasUndefinedPosition=other.hasUndefinedPosition;this.ownStyles=FullObjectCopy(other.ownStyles);} +BaseVertex.prototype.SaveToXML=function() +{return"0)?"ownStyles = \""+gEncodeToHTML(JSON.stringify(this.ownStyles))+"\" ":"")+"size=\""+this.model.diameter+"\" "+">";} +BaseVertex.prototype.LoadFromXML=function(xml) +{var xmlX=xml.attr('positionX');var xmlY=xml.attr('positionY');this.hasUndefinedPosition=(typeof xmlX==='undefined')||(typeof xmlY==='undefined');this.position=new Point(parseFloat(xmlX),parseFloat(xmlY));this.id=xml.attr('id');this.mainText=xml.attr('mainText');this.upText=xml.attr('upText');if(typeof this.mainText==='undefined') +this.mainText=this.id;else +this.mainText=gDecodeFromHTML(this.mainText);if(typeof this.upText==='undefined') +this.upText="";else +this.upText=gDecodeFromHTML(this.upText);var ownStyle=xml.attr('ownStyles');if(typeof ownStyle!=='undefined') +{var parsedSave=gDecodeFromHTML(JSON.parse(ownStyle));for(var indexField in parsedSave) +{var index=parseInt(indexField);this.ownStyles[index]=FullObjectCopy(this.getStyleFor(index));for(var field in parsedSave[indexField]) +{if(this.ownStyles[index].ShouldLoad(field)) +this.ownStyles[index][field]=parsedSave[indexField][field];}}} +var size=xml.attr('size');if(typeof size!=='undefined') +this.model.diameter=parseInt(size);} +BaseVertex.prototype.SetId=function(id) +{this.id=id;if(this.vertexEnumType!=null) +this.mainText=this.vertexEnumType.GetVertexText(id);} +BaseVertex.prototype.diameterFactor=function() +{return new Point(1.0+(this.mainText.length?this.mainText.length/8.0:0),1.5);} +BaseVertex.prototype.IsUndefinedPosition=function() +{return this.hasUndefinedPosition;} +BaseVertex.prototype.HitTest=function(pos) +{var shape=this.hasOwnProperty('currentStyle')?this.currentStyle.GetStyle({},this).shape:VertexCircleShape;var width=this.hasOwnProperty('currentStyle')?this.currentStyle.GetStyle({},this).lineWidth:0;if(shape==VertexCircleShape) +{return this.position.distance(pos)-1) +{this.edges.splice(index,1);} +this.isMultiGraph=this.checkMutiGraph();} +Graph.prototype.DeleteVertex=function(vertexObject) +{var index=this.vertices.indexOf(vertexObject);if(index>-1) +{for(var i=0;i-1) +{for(var i=0;imaxWeight) +{res=edge;maxWeight=edge.weight;}}} +return res;} +Graph.prototype.FindEdgeMinIgnoreDirection=function(id1,id2) +{var res=null;var minWeight=this.infinity;for(var i=0;i.+$/g,/^.+<.+$/g,/^.+-\(\d+\.?\d+\)-.+$/g,/^.+-\(\d+\.?\d+\)\>.+$/g,/^.+<\(\d+\.?\d+\)\-.+$/g];let res=true;for(let i=0;i0||cols[j][vertexIndex]>0)&&j!=vertexIndex) +{relatedVertex.push(this.vertices[j]);}} +var diameter=(new VertexModel()).diameter;if(relatedVertex.length>1) +{for(var j=0;jmaxDistance) +{var force=(otherVertex.position.subtract(currentVertex.object.position)).normalize(edgeGravityKof*(distance-maxDistance));currentVertex.net_force=currentVertex.net_force.add(force);}}} +var distanceToCenter=centerPoint.distance(currentVertex.object.position);var force=centerPoint.subtract(currentVertex.object.position).normalize(distanceToCenter*kCenterForce);currentVertex.net_force=currentVertex.net_force.add(force);currentVertex.velocity=currentVertex.velocity.add(currentVertex.net_force);} +bChanged=false;for(i=0;ivelocityMax) +{velocity=velocity.normalize(velocityMax);} +v.object.position=v.object.position.add(velocity);if(velocity.length()>=1) +{bChanged=true;}} +k++;} +var bbox=this.getGraphBBox();if(bbox.size().length()>viewportSize.length()*1000) +{for(i=0;i=this.vertices.length) +{var newPos=this.GetRandomPositionOfVertex(matrix,j,viewportSize);newVertices.push(new BaseVertex(newPos.x,newPos.y,currentEnumVerticesType));this.AddNewVertex(newVertices[newVertices.length-1]);} +if(cols[i][j]>0) +{var nEdgeIndex=this.AddNewEdgeSafe(this.vertices[i],this.vertices[j],cols[i][j]!=cols[j][i],cols[i][j],true);this.FixEdgeCurve(nEdgeIndex);if(nEdgeIndex>=0) +{bWeightGraph=bWeightGraph||this.edges[nEdgeIndex].weight!=1;}}}} +if(!bWeightGraph) +{this.edges.forEach(function(part,index,theArray){theArray[index].useWeight=false;});} +for(var i=rows.length;i(.+)$/g,/^(.+)<(.+)$/g,/^(.+)-\((\d+|\d+\.?\d+)\)-(.+)$/g,/^(.+)-\((\d+|\d+\.?\d+)\)\>(.+)$/g,/^(.+)<\((\d+|\d+\.?\d+)\)\-(.+)$/g,];let bWeightGraph=false;var newVertices=[];for(var i=0;i=0;--j){if(!line.match(regExp[j])){continue;} +let groupes=Array.from(line.matchAll(regExp[j]));let groupe=groupes[0];let vetext1Title=groupe[1];let vertex1=this.FindVertexByTitle(vetext1Title);if(vertex1==null){let newPosition=this.GetRandomPosition(viewportSize);vertex1=this.vertices[this.AddNewVertex(new BaseVertex(newPosition.x,newPosition.y,currentEnumVerticesType))];vertex1.mainText=vetext1Title;newVertices.push(vertex1);} +let vetext2Title=groupe[j<=2?2:3];let vertex2=this.FindVertexByTitle(vetext2Title);if(vertex2==null){let newPosition=this.GetRandomPosition(viewportSize);vertex2=this.vertices[this.AddNewVertex(new BaseVertex(newPosition.x,newPosition.y,currentEnumVerticesType))];vertex2.mainText=vetext2Title;newVertices.push(vertex2);} +let isDirect=j==1||j==2||j==4||j==5;let weight=1;if(j>2){weight=groupe[2];bWeightGraph=true;} +let isRevertEdge=j==2||j==5;let nEdgeIndex=this.AddNewEdgeSafe(isRevertEdge?vertex2:vertex1,isRevertEdge?vertex1:vertex2,isDirect,weight,false);this.FixEdgeCurve(nEdgeIndex);break;}} +if(!bWeightGraph) +{this.edges.forEach(function(part,index,theArray){theArray[index].useWeight=false;});} +this.VerticesReposition(viewportSize,newVertices);}} +Graph.prototype.TestIncidenceMatrix=function(matrix,rowsObj,colsObj,separator) +{if(separator===undefined) +{separator=",";} +var bGoodFormat=true;rowsObj.rows=[];rowsObj.rows=matrix.split("\n");for(j=0;j=this.vertices.length) +{var newPos=new Point(0,0);newVertices.push(new BaseVertex(newPos.x,newPos.y,currentEnumVerticesType));this.AddNewVertex(newVertices[newVertices.length-1]);} +if(cols[j][i]!=0) +{edgeValue.push(cols[j][i]);edgeIndex.push(j);}} +if(edgeIndex.length==1) +{edgeValue.push(edgeValue[0]);edgeIndex.push(edgeIndex[0]);} +if(edgeIndex.length==2) +{if(edgeValue[0]!=edgeValue[1]) +{if(edgeValue[1]>0) +{edgeValue=edgeValue.swap(0,1);edgeIndex=edgeIndex.swap(0,1);}} +var nEdgeIndex=this.AddNewEdgeSafe(this.vertices[edgeIndex[0]],this.vertices[edgeIndex[1]],edgeValue[0]!=edgeValue[1],Math.abs(edgeValue[1]),false);this.FixEdgeCurve(nEdgeIndex);if(nEdgeIndex>=0) +{bWeightGraph=bWeightGraph||this.edges[nEdgeIndex].weight!=1;}}} +if(!bWeightGraph) +{this.edges.forEach(function(part,index,theArray){theArray[index].useWeight=false;});} +for(var i=cols.length;i0) +{res.push(line.substr(0,i));} +if(i==0) +{i=1;} +line=line.substr(i,line.length-i);i=-1;}} +if(line.length>0) +{res.push(line);}} +else +{for(i=0;i";var header="";var xmlBody="";for(var i=0;i0) +{additionalField=""} +return mainHeader+header+xmlBody+""+additionalField+"";} +Graph.prototype.LoadFromXML=function(xmlText,additionalData) +{xmlDoc=$.parseXML(xmlText);var $xml=$(xmlDoc);$graphs=$xml.find("graph");var loadedGraphId=0;var loadedEdgeId=0;$graphs.each(function(){loadedGraphId=parseInt($(this).attr('uidGraph'));loadedEdgeId=parseInt($(this).attr('uidEdge'));});if(isNaN(loadedEdgeId)) +{loadedEdgeId=this.edgesOffset;}else if(loadedEdgeId0;} +Graph.prototype.clampPositions=function(viewportSize) +{var diameter=(new VertexModel()).diameter;for(i=0;i=2) +{var curve=this.GetAvailableCurveValue(neighborEdges,edgeObject);if(edgeObject.model.default) +{edgeObject.model.type=EdgeModels.curve;edgeObject.model.curveValue=curve;}}} +Graph.prototype.GetAvailableCurveValue=function(neighborEdges,originalEdge) +{var values=[];for(var i=0;i0?element.value:"0")+", ";} +matrix=matrix+"\n";} +return matrix;} +function getCharCode(event) +{if(event.which==null) +{return event.keyCode;} +if(event.which!=0) +{return event.which;} +return null;} +function getChar(event) +{var k=getCharCode(event) +return String.fromCharCode(k);} +function CopyMatrixToTextInput(event) +{document.getElementById("AdjacencyMatrixFieldPage").value=PackMatrix();if(event) +{var key=getChar(event);var code=getCharCode(event);console.log(key+" code="+code);if(g_ctrlPressed) +{var moveFocus=function(offsetX,offsetY) +{var focused_element=document.activeElement;if(focused_element&&focused_element.name.includes("field")) +{var name=focused_element.name;var coords=name.replace('field','').split("_");if(coords.length==2) +{var focusName="field"+(parseInt(coords[0])+offsetY)+"_"+(parseInt(coords[1])+offsetX) +var element=document.getElementsByName(focusName)[0];if(element) +{element.focus();}}}} +switch(code) +{case 38:{moveFocus(0,-1);break;} +case 40:{moveFocus(0,1);break;} +case 37:{moveFocus(-1,0);break;} +case 39:{moveFocus(1,0);break;}}}}} +function _ShowTextInput() +{$("#AdjacencyMatrixFieldPage").show();$("#MatrixForm").hide();$("#TextDescription").show();$("#MatrixDescription").hide();$("#idSeparatorList").show();} +function _ShowMatrixInput() +{$("#MatrixForm").show();$("#AdjacencyMatrixFieldPage").hide();$("#TextDescription").hide();$("#MatrixDescription").show();$("#idSeparatorList").hide();} +function ShowTextInput() +{_ShowTextInput();document.getElementById("showMatrix").className="btn btn-default";document.getElementById("showText").className="btn btn-default active";} +function ShowMatrixInput() +{_ShowMatrixInput();document.getElementById("showMatrix").className="btn btn-default active";document.getElementById("showText").className="btn btn-default";} +function CopyMatrixToMatrixInput() +{var graph=new Graph();var colsObj={};var rowsObj={};if(graph.TestAdjacencyMatrix($("#AdjacencyMatrixFieldPage").val(),rowsObj,colsObj)) +{var rows=rowsObj.rows;var cols=colsObj.cols;for(var i=g_MatrixSize;i 0 ? element.value : "0") + ", "; + } + matrix = matrix + "\n"; + } + return matrix; +} + +function getCharCode(event) +{ + if (event.which == null) + { // IE + return event.keyCode; + } + + if (event.which != 0) + { // ��� ����� IE + return event.which; // ��������� + } + + return null; // ����. ������ +} + +function getChar(event) +{ + var k = getCharCode(event) + return String.fromCharCode(k); // ��������� +} + +function CopyMatrixToTextInput(event) +{ + document.getElementById("AdjacencyMatrixFieldPage").value = PackMatrix(); + + // Move between cells. + if (event) + { + var key = getChar(event); + var code = getCharCode(event); + console.log(key + " code=" + code); + if (g_ctrlPressed) + { + var moveFocus = function(offsetX, offsetY) + { + var focused_element = document.activeElement; + + if (focused_element && focused_element.name.includes("field")) + { + var name = focused_element.name; + var coords = name.replace('field','').split("_"); + if (coords.length == 2) + { + var focusName = "field" + (parseInt(coords[0]) + offsetY) + "_" + (parseInt(coords[1]) + offsetX) + var element = document.getElementsByName(focusName)[0]; + if (element) + { + element.focus(); + } + } + } + } + switch (code) + { + case 38: // Up + { + moveFocus(0, -1); + break; + } + case 40: // Down + { + moveFocus(0, 1); + break; + } + case 37: // Left + { + moveFocus(-1, 0); + break; + } + case 39: // Right + { + moveFocus(1, 0); + break; + } + } + + } + } +} + +function _ShowTextInput() +{ + $( "#AdjacencyMatrixFieldPage" ).show(); + $( "#MatrixForm" ).hide(); + $( "#TextDescription").show(); + $( "#MatrixDescription").hide(); + $( "#idSeparatorList").show(); +} + +function _ShowMatrixInput() +{ + $( "#MatrixForm" ).show(); + $( "#AdjacencyMatrixFieldPage" ).hide(); + $( "#TextDescription").hide(); + $( "#MatrixDescription").show(); + $( "#idSeparatorList").hide(); +} + +function ShowTextInput() +{ + _ShowTextInput(); + document.getElementById("showMatrix").className = "btn btn-default"; + document.getElementById("showText").className = "btn btn-default active"; +} + +function ShowMatrixInput() +{ + _ShowMatrixInput(); + document.getElementById("showMatrix").className = "btn btn-default active"; + document.getElementById("showText").className = "btn btn-default"; +} + +function CopyMatrixToMatrixInput() +{ + var graph = new Graph(); + + var colsObj = {}; + var rowsObj = {}; + + if (graph.TestAdjacencyMatrix($( "#AdjacencyMatrixFieldPage" ).val(), rowsObj, colsObj)) + { + var rows = rowsObj.rows; + var cols = colsObj.cols; + + for (var i = g_MatrixSize; i < rows.length; i++) + { + IncSize(); + } + + for (var i = 0; i < rows.length; i++) + { + for (var j = 0; j < rows.length; j++) + { + var element = document.getElementsByName("field" + i + "_"+ j)[0]; + element.value = cols[i][j]; + } + } + } + else + { + ShowTextInput(); + } +} + +function CreateInputElement(col, row) +{ + var input = document.createElement("input"); + input.type = "text"; + input.size = 3; + input.name = "field" + col + "_" + row; + input.value = 0; + input.onkeyup = function(event) {CopyMatrixToTextInput(event);}; + + return input; +} + +function InsertBeforeElement(element, beforeName, space) +{ + var parent = document.getElementsByName(beforeName)[0].parentNode; + var beforeElement = document.getElementsByName(beforeName)[0]; + parent.insertBefore(element, beforeElement); + + if (space) + { + // Insert space + parent.insertBefore(document.createTextNode( '\u00A0' ), beforeElement); + } +} + +function IncSize() +{ + // End one more line: + for (var i = 0; i < g_MatrixSize; i ++) + { + var input = CreateInputElement(g_MatrixSize, i); + InsertBeforeElement(input, "matrixEnd", true); + } + var br = document.createElement("br"); + br.setAttribute("name", "row" + g_MatrixSize); + InsertBeforeElement(br, "matrixEnd", false); + + for (var i = 0; i < g_MatrixSize + 1; i ++) + { + var input = CreateInputElement(i, g_MatrixSize); + InsertBeforeElement(input, "row" + i, g_MatrixSize); + } + g_MatrixSize++; + CopyMatrixToTextInput(); +} + +function checkFormat() +{ + var graph = new Graph(); + var separator = $("#spaceSep").is(':checked') ? " " : ","; + + if (!graph.TestAdjacencyMatrix($( "#AdjacencyMatrixFieldPage" ).val(), [], [], separator)) + { + $( "#BadFormatMessage" ).show(); + } + else + { + $( "#BadFormatMessage" ).hide(); + } +} + +window.onload = function () +{ + + if (document.getElementById('CreateByAdjacencyMatrix')) + { + document.getElementById('CreateByAdjacencyMatrix').onclick = function () + { + $("#matrixForm").submit(); + //window.location = "./?matrix=" + $( "#AdjacencyMatrixFieldPage" ).val().replace(/\n/g,'%0A'); + } + } + + + $( "#AdjacencyMatrixFieldPage" ).on('keyup change', function (eventObject) + { + checkFormat(); + }); + + $( "#BadFormatMessage" ).hide(); + $( "#AdjacencyMatrixFieldPage" ).hide(); + + $( "#showMatrix" ).on('click', function (eventObject) + { + _ShowMatrixInput(); + }); + + $( "#showText" ).on('click', function (eventObject) + { + _ShowTextInput(); + }); + + $('input:radio[name="separator"]').change( function(){ + checkFormat() + }); + + CopyMatrixToMatrixInput(); + + $(document).keydown(function(event) { + if (event.which == "17" || event.which == "91") + g_ctrlPressed = true; + }); + + $(document).keyup(function(event) { + if (event.which == "17" || event.which == "91") + g_ctrlPressed = false; + }); +} \ No newline at end of file diff --git a/script/pages/editor/api/index.js b/script/pages/editor/api/index.js new file mode 100644 index 0000000..dfd1506 --- /dev/null +++ b/script/pages/editor/api/index.js @@ -0,0 +1,55 @@ + +// Global version needs to force reload scripts from server. +globalVersion = 75; + +{ + let asyncFilesLoad = null; + function onloadEditor() { + console.log("onload() call"); + asyncFilesLoad(); + preLoadPage(); + postLoadPage(); + } + + let modulDir = "pages/editor/"; + + doInclude ([ + include ("shared/utils.js"), + + include ("entities/graph/api/index.js"), + include ("features/draw_graph/api/index.js"), + include ("features/algorithms/api/index.js"), + + include ("features/base_handler/index.js"), + include ("features/default_handler/index.js"), + include ("features/add_vertices_handler/index.js"), + include ("features/connect_vertices_handler/index.js"), + include ("features/delete_objects_handler/index.js"), + include ("features/algorithm_handler/index.js"), + + include ("features/serialization/api/index.js"), + + include ("features/enum_vertices/EnumVertices.js"), + + include ("model/texts.js", modulDir), + include ("model/Application.js", modulDir), + include ("ui/main.js", modulDir)], + onloadEditor); + + + asyncFilesLoad = function () { + doIncludeAsync ([ + include ("shared/canvas2svg.js"), + include ("features/group_rename_handler/index.js"), + include ("features/saved_graph_handler/index.js"), + include ("features/saved_graph_image_handler/index.js"), + include ("features/show_adjacency_matrix/index.js"), + include ("features/show_distance_matrix/index.js"), + include ("features/show_incidence_matrix/index.js"), + include ("features/setup_background_style/index.js"), + include ("features/setup_edge_style/index.js"), + include ("features/setup_vertex_style/index.js"), + ]); + } + +} \ No newline at end of file diff --git a/script/pages/editor/api/index.js.cache b/script/pages/editor/api/index.js.cache new file mode 100644 index 0000000..71c29a0 --- /dev/null +++ b/script/pages/editor/api/index.js.cache @@ -0,0 +1,2031 @@ +moduleLoader.beginCacheLoading(["/script/shared/utils.js?v=75","/script/entities/graph/api/index.js?v=75","/script/shared/point.js?v=75","/script/entities/edge/api/index.js?v=75","/script/entities/edge/model/BaseEdge.js?v=75","/script/entities/edge/model/EdgeModel.js?v=75","/script/entities/vertex/api/index.js?v=75","/script/entities/vertex/model/BaseVertex.js?v=75","/script/entities/vertex/model/VertexModel.js?v=75","/script/entities/graph/model/Graph.js?v=75","/script/features/draw_graph/api/index.js?v=75","/script/features/draw_graph/model/BaseBackgroundDrawer.js?v=75","/script/features/draw_graph/model/BaseEdgeDrawer.js?v=75","/script/features/draw_graph/model/BaseVertexDrawer.js?v=75","/script/features/algorithms/api/index.js?v=75","/script/features/algorithms/model/Algorithms.js?v=75","/script/features/algorithms/model/BaseTraversal.js?v=75","/script/features/base_handler/index.js?v=75","/script/features/default_handler/index.js?v=75","/script/features/add_vertices_handler/index.js?v=75","/script/features/connect_vertices_handler/index.js?v=75","/script/features/delete_objects_handler/index.js?v=75","/script/features/algorithm_handler/index.js?v=75","/script/features/serialization/api/index.js?v=75","/script/features/serialization/model/GraphMLCreator.js?v=75","/script/features/enum_vertices/EnumVertices.js?v=75","/script/pages/editor/model/texts.js?v=75","/script/pages/editor/model/Application.js?v=75","/script/pages/editor/ui/main.js?v=75",]);globalVersion=75;{let asyncFilesLoad=null;function onloadEditor(){console.log("onload() call");asyncFilesLoad();preLoadPage();postLoadPage();} +let modulDir="pages/editor/";doInclude([include("shared/utils.js"),include("entities/graph/api/index.js"),include("features/draw_graph/api/index.js"),include("features/algorithms/api/index.js"),include("features/base_handler/index.js"),include("features/default_handler/index.js"),include("features/add_vertices_handler/index.js"),include("features/connect_vertices_handler/index.js"),include("features/delete_objects_handler/index.js"),include("features/algorithm_handler/index.js"),include("features/serialization/api/index.js"),include("features/enum_vertices/EnumVertices.js"),include("model/texts.js",modulDir),include("model/Application.js",modulDir),include("ui/main.js",modulDir)],onloadEditor);asyncFilesLoad=function(){doIncludeAsync([include("shared/canvas2svg.js"),include("features/group_rename_handler/index.js"),include("features/saved_graph_handler/index.js"),include("features/saved_graph_image_handler/index.js"),include("features/show_adjacency_matrix/index.js"),include("features/show_distance_matrix/index.js"),include("features/show_incidence_matrix/index.js"),include("features/setup_background_style/index.js"),include("features/setup_edge_style/index.js"),include("features/setup_vertex_style/index.js"),]);}} +function gEncodeToHTML(str) +{if(typeof str!=='string') +return str;return str.replace(/&/g,'&').replace(//g,'>').replace(/"/g,'"').replace(/'/g,''');} +function gDecodeFromHTML(str) +{if(typeof str!=='string') +return str;return str.replace(/'/g,"'").replace(/"/g,'"').replace(/>/g,'>').replace(/</g,'<').replace(/&/g,'&');} +function FullObjectCopy(obj) +{var newObj=Object.create(Object.getPrototypeOf(obj));return Object.assign(newObj,obj);} +function FullArrayCopy(arr) +{var res=[];arr.forEach(function(element){var copyElement=FullObjectCopy(element);res.push(copyElement);});return res;} +function formatString(string,params){return string.replace(/{(\d+)}/g,(match,index)=>{return typeof params[index]!=='undefined'?params[index]:match;});} +{let modulDir="entities/graph/";doInclude([include("shared/point.js"),include("entities/edge/api/index.js"),include("entities/vertex/api/index.js"),include("model/Graph.js",modulDir)])}function Point(x,y){this.x=x||0;this.y=y||0;};Point.prototype.x=null;Point.prototype.y=null;Point.prototype.add=function(v){return new Point(this.x+v.x,this.y+v.y);};Point.prototype.addValue=function(v){return new Point(this.x+v,this.y+v);};Point.prototype.clone=function(){return new Point(this.x,this.y);};Point.prototype.degreesTo=function(v){var dx=this.x-v.x;var dy=this.y-v.y;var angle=Math.atan2(dy,dx);return angle*(180/Math.PI);};Point.prototype.distance=function(v){return Math.sqrt(this.distanceSqr(v));};Point.prototype.distanceSqr=function(v){var x=this.x-v.x;var y=this.y-v.y;return x*x+y*y;};Point.prototype.equals=function(toCompare){return this.x==toCompare.x&&this.y==toCompare.y;};Point.prototype.interpolate=function(v,f){return new Point((this.x+v.x)*f,(this.y+v.y)*f);};Point.prototype.length=function(){return Math.sqrt(this.x*this.x+this.y*this.y);};Point.prototype.normalize=function(thickness){var l=this.length();this.x=this.x/l*thickness;this.y=this.y/l*thickness;return new Point(this.x,this.y);};Point.prototype.normalizeCopy=function(thickness){var l=this.length();return new Point(this.x/l*thickness,this.y/l*thickness);};Point.prototype.orbit=function(origin,arcWidth,arcHeight,degrees){var radians=degrees*(Math.PI/180);this.x=origin.x+arcWidth*Math.cos(radians);this.y=origin.y+arcHeight*Math.sin(radians);};Point.prototype.rotate=function(center,degrees){var radians=degrees*(Math.PI/180);offset=this.subtract(center);this.x=offset.x*Math.cos(radians)-offset.y*Math.sin(radians);this.y=offset.x*Math.sin(radians)+offset.y*Math.cos(radians);this.x=this.x+center.x;this.y=this.y+center.y;return this;};Point.prototype.offset=function(dx,dy){this.x+=dx;this.y+=dy;};Point.prototype.subtract=function(v){return new Point(this.x-v.x,this.y-v.y);};Point.prototype.subtractValue=function(value){return new Point(this.x-value,this.y-value);};Point.prototype.multiply=function(value){return new Point(this.x*value,this.y*value);};Point.prototype.toString=function(){return"(x="+this.x+", y="+this.y+")";};Point.prototype.normal=function(){return new Point(-this.y,this.x);};Point.prototype.min=function(point) +{return new Point(Math.min(this.x,point.x),Math.min(this.y,point.y));};Point.prototype.max=function(point) +{return new Point(Math.max(this.x,point.x),Math.max(this.y,point.y));};Point.prototype.inverse=function() +{return new Point(-this.x,-this.y);};Point.prototype.cross=function(point) +{return this.x*point.y-this.y*point.x;};Point.interpolate=function(pt1,pt2,f){return new Point(pt1.x*(1.0-f)+pt2.x*f,pt1.y*(1.0-f)+pt2.y*f);};Point.polar=function(len,angle){return new Point(len*Math.cos(angle),len*Math.sin(angle));};Point.distance=function(pt1,pt2){var x=pt1.x-pt2.x;var y=pt1.y-pt2.y;return Math.sqrt(x*x+y*y);};Point.center=function(pt1,pt2){return new Point((pt1.x+pt2.x)/2.0,(pt1.y+pt2.y)/2.0);};Point.toString=function(){return x+" "+y;} +Point.projection=function(point,line1,line2) +{var x=line2.y-line1.y;var y=line1.x-line2.x;var l=(line1.cross(line2)+line1.cross(point)+line2.cross(point))/(x*(line2.y-line1.y)+y*(line1.x-line2.x));var res=new Point(point.x+x*l,point.y+y*l);return res;} +Point.hitTest=function(pt11,pt12,pt21,pt22) +{var res=null;var n=0.0;var x1=pt11.x;var y1=pt11.y;var x2=pt12.x;var y2=pt12.y;var x3=pt21.x;var y3=pt21.y;var x4=pt22.x;var y4=pt22.y;if(y2-y1!=0.0) +{var q=(x2-x1)/(y1-y2);var sn=(x3-x4)+(y3-y4)*q;if(sn==0.0) +{return res;} +var fn=(x3-x1)+(y3-y1)*q;n=fn/sn;} +else +{if((y3-y4)==0.0) +{return res;} +n=(y3-y1)/(y3-y4);} +res=new Point(x3+(x4-x3)*n,y3+(y4-y3)*n);var epsilon=1E-5;if(!(res.x>=Math.min(x1,x2)-epsilon&&res.x>=Math.min(x3,x4)-epsilon&&res.x<=Math.max(x1,x2)+epsilon&&res.x<=Math.max(x3,x4)+epsilon&&res.y>=Math.min(y1,y2)-epsilon&&res.y>=Math.min(y3,y4)-epsilon&&res.y<=Math.max(y1,y2)+epsilon&&res.y<=Math.max(y3,y4)+epsilon)) +{res=null;} +return res;} +function Rect(minPoint,maxPoint){this.minPoint=minPoint;this.maxPoint=maxPoint;};Rect.prototype.center=function() +{return Point.center(this.minPoint,this.maxPoint);};Rect.prototype.size=function() +{return this.maxPoint.subtract(this.minPoint);};Rect.prototype.left=function() +{return this.minPoint.x;};Rect.prototype.top=function() +{return this.minPoint.y;};Rect.prototype.isIn=function(v) +{return this.minPoint.x<=v.x&&this.minPoint.y<=v.y&&this.maxPoint.x>v.x&&this.maxPoint.y>v.y;};{let modulDir="entities/edge/";doInclude([include("model/BaseEdge.js",modulDir),include("model/EdgeModel.js",modulDir)])} +function BaseEdge(vertex1,vertex2,isDirect,weight,upText) +{this.vertex1=vertex1;this.vertex2=vertex2;this.arrayStyleStart="";this.arrayStyleFinish="";this.isDirect=isDirect;this.weight=0;this.text="";this.useWeight=false;this.id=0;this.model=new EdgeModel();if(upText===undefined) +this.upText="";else +this.upText=upText;if(weight!==undefined) +this.SetWeight(weight);this.ownStyles={};} +BaseEdge.prototype.copyFrom=function(other) +{this.vertex1=other.vertex1;this.vertex2=other.vertex2;this.arrayStyleStart=other.arrayStyleStart;this.arrayStyleFinish=other.arrayStyleFinish;this.isDirect=other.isDirect;this.weight=other.weight;this.text=other.text;this.useWeight=other.useWeight;this.id=other.id;this.model=new EdgeModel();this.model.copyFrom(other.model);this.upText=other.upText;this.ownStyles=FullObjectCopy(other.ownStyles);} +BaseEdge.prototype.SaveToXML=function() +{return"0)?"ownStyles = \""+gEncodeToHTML(JSON.stringify(this.ownStyles))+"\" ":"")+ +this.model.SaveToXML()+">";} +BaseEdge.prototype.LoadFromXML=function(xml,graph) +{var attr=xml.attr('vertex1');if(typeof attr==='undefined') +{attr=xml.attr('source');} +this.vertex1=graph.FindVertex(typeof attr!=='undefined'?attr:xml.attr('graph1'));var attr=xml.attr('vertex2');if(typeof attr==='undefined') +{attr=xml.attr('target');} +this.vertex2=graph.FindVertex(typeof attr!=='undefined'?attr:xml.attr('graph2'));this.isDirect=xml.attr('isDirect')=="true";this.weight=parseFloat(xml.attr('weight'));if(isNaN(this.weight)) +{this.weight=1;} +this.hasPair=xml.attr('hasPair')=="true";this.useWeight=xml.attr('useWeight')=="true";this.id=xml.attr('id');this.text=xml.attr("text")==null?"":gDecodeFromHTML(xml.attr("text"));this.arrayStyleStart=xml.attr("arrayStyleStart")==null?"":xml.attr("arrayStyleStart");this.arrayStyleFinish=xml.attr("arrayStyleFinish")==null?"":xml.attr("arrayStyleFinish");this.upText=xml.attr('upText');if(typeof this.upText==='undefined') +{this.upText="";} +else +{this.upText=gDecodeFromHTML(this.upText);} +var ownStyle=xml.attr('ownStyles');if(typeof ownStyle!=='undefined') +{var parsedSave=gDecodeFromHTML(JSON.parse(ownStyle));for(var indexField in parsedSave) +{var index=parseInt(indexField);this.ownStyles[index]=FullObjectCopy(this.getStyleFor(index));for(var field in parsedSave[indexField]) +{if(this.ownStyles[index].ShouldLoad(field)) +this.ownStyles[index][field]=parsedSave[indexField][field];}}} +this.model.LoadFromXML(xml);} +BaseEdge.prototype.GetPixelLength=function() +{if(this.vertex1==this.vertex2) +{return this.model.GetLoopSize()*2*Math.PI;} +else +{return Point.distance(this.vertex1.position,this.vertex2.position);}} +BaseEdge.prototype.GetWeight=function() +{return this.useWeight?this.weight:1;} +BaseEdge.prototype.GetText=function() +{return this.text.length>0?this.text:(this.useWeight?this.weight.toString():"");} +BaseEdge.prototype.GetUpText=function() +{return this.upText;} +BaseEdge.prototype.GetStartEdgeStyle=function() +{return this.arrayStyleStart;} +BaseEdge.prototype.GetFinishEdgeStyle=function() +{return(this.arrayStyleFinish!=""?this.arrayStyleFinish:(this.isDirect?"arrow":""));} +BaseEdge.prototype.HitTest=function(pos) +{var positions=this.GetEdgePositionsShift();return this.model.HitTest(positions[0],positions[1],pos);} +BaseEdge.prototype.GetEdgePositionsShift=function() +{return this.GetEdgePositions();} +BaseEdge.prototype.GetEdgePositions=function() +{var res=[];if(this.vertex1==this.vertex2) +{res.push(this.vertex1.position);res.push(this.vertex2.position);return res;} +var position1=this.vertex1.position;var position2=this.vertex2.position;var diameter1=this.vertex1.model.diameter+parseInt(this.vertex1.currentStyle.GetStyle({},this.vertex1).lineWidth);var diameter2=this.vertex2.model.diameter+parseInt(this.vertex2.currentStyle.GetStyle({},this.vertex2).lineWidth);var direction=position1.subtract(position2);var direction1=direction;var direction2=direction;var d1=diameter1;var d2=diameter2;if(this.model.type==EdgeModels.curve) +{var dist=position1.distance(position2);var point1=this.model.GetCurvePoint(position1,position2,10.0/dist);direction1=position1.subtract(point1);var point2=this.model.GetCurvePoint(position1,position2,1.0-10.0/dist);direction2=position2.subtract(point2);d2=diameter2;} +else +{direction2=direction2.multiply(-1);} +direction1.normalize(1.0);direction2.normalize(1.0);var vertices=[];vertices.push({vertex:this.vertex1,direction:direction1,position:position1,diameter:d1});vertices.push({vertex:this.vertex2,direction:direction2,position:position2,diameter:d2});vertices.forEach(function(data) +{var shape=data.vertex.currentStyle.GetStyle({},data.vertex).shape;if(shape==VertexCircleShape) +{var direction=data.direction.multiply(0.5);res.push(data.position.subtract(direction.multiply(data.diameter)));} +else +{var lineFinish1=data.direction.multiply(-1).multiply(1000.0);var pointsVertex1=GetPointsForShape(shape,data.diameter,data.vertex.mainText);pointsVertex1.push(pointsVertex1[0]);for(var i=0;i=0)?weight:1;this.weight=Number(weight);this.useWeight=useWeight;} +BaseEdge.prototype.SetUpText=function(text) +{this.upText=text;} +BaseEdge.prototype.resetOwnStyle=function(index) +{if(this.ownStyles.hasOwnProperty(index)) +{delete this.ownStyles[index];}} +BaseEdge.prototype.setOwnStyle=function(index,style) +{this.ownStyles[index]=style;} +BaseEdge.prototype.getStyleFor=function(index) +{if(this.ownStyles.hasOwnProperty(index)) +{return this.ownStyles[index];} +else +{var style=null;if(index==0) +style=globalApplication.GetStyle("edge","common");else +style=globalApplication.GetStyle("edge","selected",undefined,index-1);return style;}} +BaseEdge.prototype.hasOwnStyleFor=function(index) +{return this.ownStyles.hasOwnProperty(index);} +var EdgeModels={"line":0,"curve":1};const defaultEdgeWidth=4;function EdgeModel() +{this.width=globalApplication.GetDefaultEdgeWidth();this.type=EdgeModels.line;this.curveValue=EdgeModel.prototype.defaultCurve;this.default=true;this.sizeOfLoop=24;this.loopShiftAngel=Math.PI/6;} +EdgeModel.prototype.defaultCurve=0.1;EdgeModel.prototype.copyFrom=function(other) +{this.width=other.width;this.type=other.type;this.curveValue=other.curveValue;this.default=other.default;} +EdgeModel.prototype.SaveToXML=function() +{return"model_width=\""+this.width+"\" "+"model_type=\""+this.type+"\" "+"model_curveValue=\""+this.curveValue+"\" "+"model_default=\""+this.default+"\" ";} +EdgeModel.prototype.LoadFromXML=function(xml,graph) +{this.width=xml.attr('model_width')==null?this.width:parseFloat(xml.attr("model_width"));this.type=xml.attr('model_type')==null?this.type:xml.attr("model_type");this.curveValue=xml.attr('model_curveValue')==null?this.curveValue:parseFloat(xml.attr("model_curveValue"));this.default=xml.attr('model_default')==null?this.default:parseFloat(xml.attr("model_default"));} +EdgeModel.prototype.GetCurvePoint=function(position1,position2,t) +{var points=this.GetBezierPoints(position1,position2);var firstBezierPoint=points[0];var secondBezierPoint=points[1];var B0_t=Math.pow(1-t,3);var B1_t=3*t*Math.pow(1-t,2);var B2_t=3*t*t*(1-t) +var B3_t=t*t*t;var ax=position1.x;var ay=position1.y;var dx=position2.x;var dy=position2.y;var bx=firstBezierPoint.x;var by=firstBezierPoint.y;var cx=secondBezierPoint.x;var cy=secondBezierPoint.y;var px_t=(B0_t*ax)+(B1_t*bx)+(B2_t*cx)+(B3_t*dx);var py_t=(B0_t*ay)+(B1_t*by)+(B2_t*cy)+(B3_t*dy);return new Point(px_t,py_t);} +EdgeModel.prototype.GetBezierPoints=function(position1,position2) +{var direction=position2.subtract(position1);var delta=direction.length();direction.normalize(1.0);var normal=direction.normal();var deltaOffsetPixels=delta*this.curveValue;var yOffset=normal.multiply(deltaOffsetPixels);var firstBezierPointShift=(direction.multiply(delta*0.2)).add(yOffset);var secondBezierPointShift=(direction.multiply(-delta*0.2)).add(yOffset);var firstBezierPoint=position1.add(firstBezierPointShift);var secondBezierPoint=position2.add(secondBezierPointShift);return[firstBezierPoint,secondBezierPoint];} +EdgeModel.prototype.HitTest=function(position1,position2,mousePos) +{if(this.type==EdgeModels.line) +return this.HitTestLine(position1,position2,mousePos);else if(this.type==EdgeModels.curve) +return this.HitTestCurve(position1,position2,mousePos);return false;} +EdgeModel.prototype.HitTestLine=function(position1,position2,mousePos,factor) +{if(factor===undefined) +{factor=1.0;} +var pos1=position1;var pos2=position2;var pos0=mousePos;if(pos1.equals(pos2)) +{var xCenter=pos1.x-Math.cos(this.GetLoopShiftAngel())*this.GetLoopSize();var yCenter=pos1.y-Math.sin(this.GetLoopShiftAngel())*this.GetLoopSize();return Math.abs((Point.distance(new Point(xCenter,yCenter),pos0))-this.GetLoopSize())<=this.width*1.5*factor;} +var r1=pos0.distance(pos1);var r2=pos0.distance(pos2);var r12=pos1.distance(pos2);if(r1>=(new Point(r2,r12)).length()||r2>=(new Point(r1,r12)).length()) +{} +else +{var distance=((pos1.y-pos2.y)*pos0.x+(pos2.x-pos1.x)*pos0.y+(pos1.x*pos2.y-pos2.x*pos1.y))/r12;if(Math.abs(distance)<=this.width*1.5*factor) +{return true;}} +return false;} +EdgeModel.prototype.HitTestCurve=function(position1,position2,mousePos) +{var pos1=position1;var pos2=position2;var pos0=mousePos;if(pos1.equals(pos2)) +{var xCenter=pos1.x-Math.cos(this.GetLoopShiftAngel())*this.GetLoopSize();var yCenter=pos1.y-Math.sin(this.GetLoopShiftAngel())*this.GetLoopSize();return Math.abs((Point.distance(new Point(xCenter,yCenter),pos0))-this.GetLoopSize())<=this.width*1.5;} +var interval_count=position1.distance(position2)/100*30;var start=position1;for(var i=0;i=0.0){normalCurve+=this.defaultCurve} +return this.sizeOfLoop*Math.abs(normalCurve)*(1/this.defaultCurve);}} +EdgeModel.prototype.GetLoopShiftAngel=function() +{if(this.type==EdgeModels.line||this.curveValue>=0.0) +{return this.loopShiftAngel;} +else +{return this.loopShiftAngel+Math.PI;}} +{let modulDir="entities/vertex/";doInclude([include("model/BaseVertex.js",modulDir),include("model/VertexModel.js",modulDir)])} +function BaseVertex(x,y,vertexEnumType) +{this.position=new Point(x,y);this.id=0;this.mainText="";this.upText="";this.vertexEnumType=vertexEnumType;this.model=new VertexModel();this.hasUndefinedPosition=false;this.ownStyles={};};BaseVertex.prototype.position=new Point(0,0);BaseVertex.prototype.copyFrom=function(other) +{this.position=new Point(other.position.x,other.position.y);this.id=other.id;this.mainText=other.mainText;this.upText=other.upText;this.vertexEnumType=other.vertexEnumType;this.model=new VertexModel();this.hasUndefinedPosition=other.hasUndefinedPosition;this.ownStyles=FullObjectCopy(other.ownStyles);} +BaseVertex.prototype.SaveToXML=function() +{return"0)?"ownStyles = \""+gEncodeToHTML(JSON.stringify(this.ownStyles))+"\" ":"")+"size=\""+this.model.diameter+"\" "+">";} +BaseVertex.prototype.LoadFromXML=function(xml) +{var xmlX=xml.attr('positionX');var xmlY=xml.attr('positionY');this.hasUndefinedPosition=(typeof xmlX==='undefined')||(typeof xmlY==='undefined');this.position=new Point(parseFloat(xmlX),parseFloat(xmlY));this.id=xml.attr('id');this.mainText=xml.attr('mainText');this.upText=xml.attr('upText');if(typeof this.mainText==='undefined') +this.mainText=this.id;else +this.mainText=gDecodeFromHTML(this.mainText);if(typeof this.upText==='undefined') +this.upText="";else +this.upText=gDecodeFromHTML(this.upText);var ownStyle=xml.attr('ownStyles');if(typeof ownStyle!=='undefined') +{var parsedSave=gDecodeFromHTML(JSON.parse(ownStyle));for(var indexField in parsedSave) +{var index=parseInt(indexField);this.ownStyles[index]=FullObjectCopy(this.getStyleFor(index));for(var field in parsedSave[indexField]) +{if(this.ownStyles[index].ShouldLoad(field)) +this.ownStyles[index][field]=parsedSave[indexField][field];}}} +var size=xml.attr('size');if(typeof size!=='undefined') +this.model.diameter=parseInt(size);} +BaseVertex.prototype.SetId=function(id) +{this.id=id;if(this.vertexEnumType!=null) +this.mainText=this.vertexEnumType.GetVertexText(id);} +BaseVertex.prototype.diameterFactor=function() +{return new Point(1.0+(this.mainText.length?this.mainText.length/8.0:0),1.5);} +BaseVertex.prototype.IsUndefinedPosition=function() +{return this.hasUndefinedPosition;} +BaseVertex.prototype.HitTest=function(pos) +{var shape=this.hasOwnProperty('currentStyle')?this.currentStyle.GetStyle({},this).shape:VertexCircleShape;var width=this.hasOwnProperty('currentStyle')?this.currentStyle.GetStyle({},this).lineWidth:0;if(shape==VertexCircleShape) +{return this.position.distance(pos)-1) +{this.edges.splice(index,1);} +this.isMultiGraph=this.checkMutiGraph();} +Graph.prototype.DeleteVertex=function(vertexObject) +{var index=this.vertices.indexOf(vertexObject);if(index>-1) +{for(var i=0;i-1) +{for(var i=0;imaxWeight) +{res=edge;maxWeight=edge.weight;}}} +return res;} +Graph.prototype.FindEdgeMinIgnoreDirection=function(id1,id2) +{var res=null;var minWeight=this.infinity;for(var i=0;i.+$/g,/^.+<.+$/g,/^.+-\(\d+\.?\d+\)-.+$/g,/^.+-\(\d+\.?\d+\)\>.+$/g,/^.+<\(\d+\.?\d+\)\-.+$/g];let res=true;for(let i=0;i0||cols[j][vertexIndex]>0)&&j!=vertexIndex) +{relatedVertex.push(this.vertices[j]);}} +var diameter=(new VertexModel()).diameter;if(relatedVertex.length>1) +{for(var j=0;jmaxDistance) +{var force=(otherVertex.position.subtract(currentVertex.object.position)).normalize(edgeGravityKof*(distance-maxDistance));currentVertex.net_force=currentVertex.net_force.add(force);}}} +var distanceToCenter=centerPoint.distance(currentVertex.object.position);var force=centerPoint.subtract(currentVertex.object.position).normalize(distanceToCenter*kCenterForce);currentVertex.net_force=currentVertex.net_force.add(force);currentVertex.velocity=currentVertex.velocity.add(currentVertex.net_force);} +bChanged=false;for(i=0;ivelocityMax) +{velocity=velocity.normalize(velocityMax);} +v.object.position=v.object.position.add(velocity);if(velocity.length()>=1) +{bChanged=true;}} +k++;} +var bbox=this.getGraphBBox();if(bbox.size().length()>viewportSize.length()*1000) +{for(i=0;i=this.vertices.length) +{var newPos=this.GetRandomPositionOfVertex(matrix,j,viewportSize);newVertices.push(new BaseVertex(newPos.x,newPos.y,currentEnumVerticesType));this.AddNewVertex(newVertices[newVertices.length-1]);} +if(cols[i][j]>0) +{var nEdgeIndex=this.AddNewEdgeSafe(this.vertices[i],this.vertices[j],cols[i][j]!=cols[j][i],cols[i][j],true);this.FixEdgeCurve(nEdgeIndex);if(nEdgeIndex>=0) +{bWeightGraph=bWeightGraph||this.edges[nEdgeIndex].weight!=1;}}}} +if(!bWeightGraph) +{this.edges.forEach(function(part,index,theArray){theArray[index].useWeight=false;});} +for(var i=rows.length;i(.+)$/g,/^(.+)<(.+)$/g,/^(.+)-\((\d+|\d+\.?\d+)\)-(.+)$/g,/^(.+)-\((\d+|\d+\.?\d+)\)\>(.+)$/g,/^(.+)<\((\d+|\d+\.?\d+)\)\-(.+)$/g,];let bWeightGraph=false;var newVertices=[];for(var i=0;i=0;--j){if(!line.match(regExp[j])){continue;} +let groupes=Array.from(line.matchAll(regExp[j]));let groupe=groupes[0];let vetext1Title=groupe[1];let vertex1=this.FindVertexByTitle(vetext1Title);if(vertex1==null){let newPosition=this.GetRandomPosition(viewportSize);vertex1=this.vertices[this.AddNewVertex(new BaseVertex(newPosition.x,newPosition.y,currentEnumVerticesType))];vertex1.mainText=vetext1Title;newVertices.push(vertex1);} +let vetext2Title=groupe[j<=2?2:3];let vertex2=this.FindVertexByTitle(vetext2Title);if(vertex2==null){let newPosition=this.GetRandomPosition(viewportSize);vertex2=this.vertices[this.AddNewVertex(new BaseVertex(newPosition.x,newPosition.y,currentEnumVerticesType))];vertex2.mainText=vetext2Title;newVertices.push(vertex2);} +let isDirect=j==1||j==2||j==4||j==5;let weight=1;if(j>2){weight=groupe[2];bWeightGraph=true;} +let isRevertEdge=j==2||j==5;let nEdgeIndex=this.AddNewEdgeSafe(isRevertEdge?vertex2:vertex1,isRevertEdge?vertex1:vertex2,isDirect,weight,false);this.FixEdgeCurve(nEdgeIndex);break;}} +if(!bWeightGraph) +{this.edges.forEach(function(part,index,theArray){theArray[index].useWeight=false;});} +this.VerticesReposition(viewportSize,newVertices);}} +Graph.prototype.TestIncidenceMatrix=function(matrix,rowsObj,colsObj,separator) +{if(separator===undefined) +{separator=",";} +var bGoodFormat=true;rowsObj.rows=[];rowsObj.rows=matrix.split("\n");for(j=0;j=this.vertices.length) +{var newPos=new Point(0,0);newVertices.push(new BaseVertex(newPos.x,newPos.y,currentEnumVerticesType));this.AddNewVertex(newVertices[newVertices.length-1]);} +if(cols[j][i]!=0) +{edgeValue.push(cols[j][i]);edgeIndex.push(j);}} +if(edgeIndex.length==1) +{edgeValue.push(edgeValue[0]);edgeIndex.push(edgeIndex[0]);} +if(edgeIndex.length==2) +{if(edgeValue[0]!=edgeValue[1]) +{if(edgeValue[1]>0) +{edgeValue=edgeValue.swap(0,1);edgeIndex=edgeIndex.swap(0,1);}} +var nEdgeIndex=this.AddNewEdgeSafe(this.vertices[edgeIndex[0]],this.vertices[edgeIndex[1]],edgeValue[0]!=edgeValue[1],Math.abs(edgeValue[1]),false);this.FixEdgeCurve(nEdgeIndex);if(nEdgeIndex>=0) +{bWeightGraph=bWeightGraph||this.edges[nEdgeIndex].weight!=1;}}} +if(!bWeightGraph) +{this.edges.forEach(function(part,index,theArray){theArray[index].useWeight=false;});} +for(var i=cols.length;i0) +{res.push(line.substr(0,i));} +if(i==0) +{i=1;} +line=line.substr(i,line.length-i);i=-1;}} +if(line.length>0) +{res.push(line);}} +else +{for(i=0;i";var header="";var xmlBody="";for(var i=0;i0) +{additionalField=""} +return mainHeader+header+xmlBody+""+additionalField+"";} +Graph.prototype.LoadFromXML=function(xmlText,additionalData) +{xmlDoc=$.parseXML(xmlText);var $xml=$(xmlDoc);$graphs=$xml.find("graph");var loadedGraphId=0;var loadedEdgeId=0;$graphs.each(function(){loadedGraphId=parseInt($(this).attr('uidGraph'));loadedEdgeId=parseInt($(this).attr('uidEdge'));});if(isNaN(loadedEdgeId)) +{loadedEdgeId=this.edgesOffset;}else if(loadedEdgeId0;} +Graph.prototype.clampPositions=function(viewportSize) +{var diameter=(new VertexModel()).diameter;for(i=0;i=2) +{var curve=this.GetAvailableCurveValue(neighborEdges,edgeObject);if(edgeObject.model.default) +{edgeObject.model.type=EdgeModels.curve;edgeObject.model.curveValue=curve;}}} +Graph.prototype.GetAvailableCurveValue=function(neighborEdges,originalEdge) +{var values=[];for(var i=0;i0.0) +{context.globalAlpha=style.commonOpacity;context.fillStyle=style.commonColor;context.fillRect(-rect.minPoint.x,-rect.minPoint.y,rect.size().x+1,rect.size().y+1);this.DrawImage(style,width,height,position,scale);} +context.globalAlpha=oldOpacity;} +BaseBackgroundDrawer.prototype.DrawImage=function(style,width,height,position,scale) +{if(style.image==null){return;} +var context=this.context;context.clearRect(0,0,style.image.width,style.image.height);context.drawImage(style.image,0,0)} +const lineDashTypes=[[],[4,4],[12,12],[16,4,4,4],];const WeightTextCenter=0,WeightTextUp=1;function BaseEdgeStyle() +{this.baseStyles=[];} +BaseEdgeStyle.prototype.GetStyle=function(baseStyle,object) +{this.baseStyles.forEach(function(element){var styleObject=globalApplication.GetStyle("edge",element,object);baseStyle=styleObject.GetStyle(baseStyle,object);});if(this.hasOwnProperty('weightText')) +baseStyle.weightText=this.weightText;if(this.hasOwnProperty('strokeStyle')) +baseStyle.strokeStyle=this.strokeStyle;if(this.hasOwnProperty('fillStyle')) +baseStyle.fillStyle=this.fillStyle;if(this.hasOwnProperty('textPadding')) +baseStyle.textPadding=this.textPadding;if(this.hasOwnProperty('textStrokeWidth')) +baseStyle.textStrokeWidth=this.textStrokeWidth;if(this.hasOwnProperty('lineDash')) +baseStyle.lineDash=this.lineDash;if(this.hasOwnProperty('additionalTextColor')) +baseStyle.additionalTextColor=this.additionalTextColor;if(this.hasOwnProperty('weightPosition')) +baseStyle.weightPosition=this.weightPosition;return this.FixNewFields(baseStyle);} +BaseEdgeStyle.prototype.FixNewFields=function(style) +{if(!style.hasOwnProperty('lineDash')) +style.lineDash=0;if(!style.hasOwnProperty('weightPosition')) +style.weightPosition=WeightTextCenter;return style;} +BaseEdgeStyle.prototype.Clear=function() +{delete this.weightText;delete this.strokeStyle;delete this.fillStyle;delete this.textPadding;delete this.textStrokeWidth;delete this.lineDash;delete this.additionalTextColor;delete this.weightPosition;} +BaseEdgeStyle.prototype.ShouldLoad=function(field) +{return field!="baseStyles";} +function CommonEdgeStyle() +{BaseEdgeStyle.apply(this,arguments);this.strokeStyle='#c7b7c7';this.weightText='#f0d543';this.fillStyle='#68aeba';this.textPadding=4;this.textStrokeWidth=2;this.lineDash=0;this.additionalTextColor='#c7b7c7';this.weightPosition=WeightTextCenter;} +CommonEdgeStyle.prototype=Object.create(BaseEdgeStyle.prototype);function CommonPrintEdgeStyle() +{BaseEdgeStyle.apply(this,arguments);this.strokeStyle='#000000';this.weightText='#000000';this.fillStyle='#FFFFFF';this.textPadding=4;this.textStrokeWidth=2;this.baseStyles.push("common");} +CommonPrintEdgeStyle.prototype=Object.create(BaseEdgeStyle.prototype);function SelectedEdgeStyle0() +{BaseEdgeStyle.apply(this,arguments);this.strokeStyle='#f0d543';this.weightText='#f0d543';this.fillStyle='#c7627a';this.baseStyles.push("common");} +SelectedEdgeStyle0.prototype=Object.create(BaseEdgeStyle.prototype);function SelectedEdgeStyle1() +{BaseEdgeStyle.apply(this,arguments);this.strokeStyle='#8FBF83';this.weightText='#8FBF83';this.fillStyle='#F9F9D5';this.baseStyles.push("selected");} +SelectedEdgeStyle1.prototype=Object.create(BaseEdgeStyle.prototype);function SelectedEdgeStyle2() +{BaseEdgeStyle.apply(this,arguments);this.strokeStyle='#8C4C86';this.weightText='#8C4C86';this.fillStyle='#253267';this.baseStyles.push("selected");} +SelectedEdgeStyle2.prototype=Object.create(BaseEdgeStyle.prototype);function SelectedEdgeStyle3() +{BaseEdgeStyle.apply(this,arguments);this.strokeStyle='#6188FF';this.weightText='#6188FF';this.fillStyle='#E97CF9';this.baseStyles.push("selected");} +SelectedEdgeStyle3.prototype=Object.create(BaseEdgeStyle.prototype);function SelectedEdgeStyle4() +{BaseEdgeStyle.apply(this,arguments);this.strokeStyle='#C6B484';this.weightText='#C6B484';this.fillStyle='#E0DEE1';this.baseStyles.push("selected");} +SelectedEdgeStyle4.prototype=Object.create(BaseEdgeStyle.prototype);function SelectedEdgePrintStyle() +{BaseEdgeStyle.apply(this,arguments);this.strokeStyle='#AAAAAA';this.weightText='#000000';this.fillStyle='#AAAAAA';this.baseStyles.push("printed");} +SelectedEdgePrintStyle.prototype=Object.create(BaseEdgeStyle.prototype);var DefaultSelectedEdgeStyles=[new SelectedEdgeStyle0(),new SelectedEdgeStyle1(),new SelectedEdgeStyle2(),new SelectedEdgeStyle3(),new SelectedEdgeStyle4()];var DefaultPrintSelectedEdgeStyles=[new SelectedEdgePrintStyle()];function BaseEdgeDrawer(context,drawObjects) +{if(drawObjects===undefined) +{drawObjects=null;} +this.context=context;this.drawObject=null;this.drawArc=null;this.startArrowDirection=null;this.finishArrowDirection=null;this.textCenterObject=null;this.getPointOnArc=null;if(drawObjects) +{if(drawObjects.hasOwnProperty("drawObject")) +this.drawObject=drawObjects.drawObject;if(drawObjects.hasOwnProperty("drawArc")) +this.drawArc=drawObjects.drawArc;if(drawObjects.hasOwnProperty("startArrowDirection")) +this.startArrowDirection=drawObjects.startArrowDirection;if(drawObjects.hasOwnProperty("finishArrowDirection")) +this.finishArrowDirection=drawObjects.finishArrowDirection;if(drawObjects.hasOwnProperty("textCenterObject")) +this.textCenterObject=drawObjects.textCenterObject;if(drawObjects.hasOwnProperty("getPointOnArc")) +this.getPointOnArc=drawObjects.getPointOnArc;}} +BaseEdgeDrawer.prototype.Draw=function(baseEdge,arcStyle) +{if(this.drawObject&&this.drawObject!=this) +{this.drawObject.Draw(baseEdge,arcStyle);return;} +this.SetupStyle(baseEdge,arcStyle);var lengthArrow=Math.max(baseEdge.model.width*4,8);var widthArrow=Math.max(baseEdge.model.width*2,4);var position1=baseEdge.vertex1.position;var position2=baseEdge.vertex2.position;var direction=position1.subtract(position2);direction.normalize(1.0);var positions=baseEdge.GetEdgePositionsShift();var hasStartStyle=!position1.equals(position2)&&baseEdge.GetStartEdgeStyle()!="";var hasFinishStyle=!position1.equals(position2)&&baseEdge.GetFinishEdgeStyle()!="";var arcPos1=positions[0];var arcPos2=positions[1];if(hasStartStyle) +{var dirArrow=this.GetStartArrowDirection(positions[0],positions[1],lengthArrow);arcPos1=arcPos1.add(dirArrow.multiply(lengthArrow/2));} +if(hasFinishStyle) +{var dirArrow=this.GetFinishArrowDirection(positions[0],positions[1],lengthArrow);arcPos2=arcPos2.add(dirArrow.multiply(-lengthArrow/2));} +this.DrawArc(arcPos1,arcPos2,arcStyle);this.context.fillStyle=this.context.strokeStyle;this.context.lineWidth=0;if(hasStartStyle) +{this.DrawArrow(positions[0],this.GetStartArrowDirection(positions[0],positions[1],lengthArrow),lengthArrow,widthArrow);} +if(hasFinishStyle) +{this.DrawArrow(positions[1],this.GetFinishArrowDirection(positions[0],positions[1],lengthArrow),lengthArrow,widthArrow);} +this.SetupStyle(baseEdge,arcStyle);if(arcStyle.weightPosition==WeightTextCenter) +{if(baseEdge.GetText().length>0) +{this.DrawWeight(positions[0],positions[1],baseEdge.GetText(),arcStyle,false);} +if(baseEdge.GetUpText().length>0) +{this.DrawUpText(positions[0],positions[1],baseEdge.GetUpText(),arcStyle,false,arcStyle.additionalTextColor,baseEdge.model.width/2+20,null);}} +else if(arcStyle.weightPosition==WeightTextUp) +{if(baseEdge.GetText().length>0) +{this.DrawUpText(positions[0],positions[1],baseEdge.GetText(),arcStyle,false,arcStyle.weightText,baseEdge.model.width/2+10,"16px");} +if(baseEdge.GetUpText().length>0) +{this.DrawUpText(positions[0],positions[1],baseEdge.GetUpText(),arcStyle,false,arcStyle.additionalTextColor,-baseEdge.model.width/2-15,null);}}} +BaseEdgeDrawer.prototype.SetupStyle=function(baseEdge,arcStyle) +{this.context.lineWidth=baseEdge.model.width;this.context.strokeStyle=arcStyle.strokeStyle;this.context.fillStyle=arcStyle.fillStyle;this.model=baseEdge.model;this.style=arcStyle;} +BaseEdgeDrawer.prototype.DrawArc=function(position1,position2,arcStyle) +{if(this.drawArc&&this.drawArc!=this) +{this.drawArc.DrawArc(position1,position2,arcStyle);return;} +this.context.setLineDash(lineDashTypes[arcStyle.lineDash]);if(position1.equals(position2)) +{this.context.beginPath();this.context.arc(position1.x-Math.cos(this.model.GetLoopShiftAngel())*this.model.GetLoopSize(),position1.y-Math.sin(this.model.GetLoopShiftAngel())*this.model.GetLoopSize(),this.model.GetLoopSize(),0,2*Math.PI);this.context.stroke();} +else +{this.context.beginPath();this.context.moveTo(position1.x,position1.y);this.context.lineTo(position2.x,position2.y);this.context.stroke();} +this.context.setLineDash([]);} +BaseEdgeDrawer.prototype.DrawWeight=function(position1,position2,text,arcStyle,hasPair) +{var centerPoint=this.GetTextCenterPoint(position1,position2,hasPair,arcStyle);this.context.font="bold 16px sans-serif";this.context.textBaseline="middle";this.context.lineWidth=arcStyle.textStrokeWidth;this.context.fillStyle=arcStyle.fillStyle;var widthText=this.context.measureText(text).width;this.context.beginPath();this.context.rect(centerPoint.x-widthText/2-arcStyle.textPadding/2,centerPoint.y-8-arcStyle.textPadding/2,widthText+arcStyle.textPadding,16+arcStyle.textPadding);this.context.closePath();this.context.fill();this.context.stroke();this.context.fillStyle=arcStyle.weightText;this.context.fillText(text,centerPoint.x-widthText/2,centerPoint.y);} +BaseEdgeDrawer.prototype.DrawUpText=function(position1,position2,text,arcStyle,hasPair,color,offset,fontSize) +{var centerPoint=this.GetTextCenterPoint(position1,position2,hasPair,arcStyle);this.context.font=fontSize==null?"bold 12px sans-serif":"bold "+fontSize+" sans-serif";this.context.textBaseline="middle";var widthText=this.context.measureText(text).width;this.context.fillStyle=color;var vectorEdge=new Point(position2.x-position1.x,position2.y-position1.y);var angleRadians=Math.atan2(vectorEdge.y,vectorEdge.x);if(angleRadians>Math.PI/2||angleRadians<-Math.PI/2) +{vectorEdge=new Point(position1.x-position2.x,position1.y-position2.y);angleRadians=Math.atan2(vectorEdge.y,vectorEdge.x);} +var normalize=vectorEdge.normal().normalizeCopy(offset);this.context.save();this.context.translate(centerPoint.x-normalize.x,centerPoint.y-normalize.y);this.context.rotate(angleRadians);this.context.textAlign="center";this.context.fillText(text,0,0);this.context.restore();} +BaseEdgeDrawer.prototype.DrawArrow=function(position,direction,length,width) +{var normal=direction.normal();var pointOnLine=position.subtract(direction.multiply(length));var point1=pointOnLine.add(normal.multiply(width));var point2=pointOnLine.add(normal.multiply(-width));this.context.beginPath();this.context.moveTo(position.x,position.y);this.context.lineTo(point1.x,point1.y);this.context.lineTo(point2.x,point2.y);this.context.lineTo(position.x,position.y);this.context.closePath();this.context.fill();} +BaseEdgeDrawer.prototype.GetStartArrowDirection=function(position1,position2,lengthArrow) +{if(this.startArrowDirection&&this.startArrowDirection!=this) +{return this.startArrowDirection.GetStartArrowDirection(position1,position2,lengthArrow);} +var direction=position1.subtract(position2);direction.normalize(1.0);return direction;} +BaseEdgeDrawer.prototype.GetFinishArrowDirection=function(position1,position2,lengthArrow) +{if(this.finishArrowDirection&&this.finishArrowDirection!=this) +{return this.finishArrowDirection.GetFinishArrowDirection(position1,position2,lengthArrow);} +var direction=position2.subtract(position1);direction.normalize(1.0);return direction;} +BaseEdgeDrawer.prototype.GetTextCenterPoint=function(position1,position2,hasPair,arcStyle) +{if(this.textCenterObject&&this.textCenterObject!=this) +{return this.textCenterObject.GetTextCenterPoint(position1,position2,hasPair,arcStyle);} +var textShift=Math.min(12/position1.subtract(position2).length(),0.4);var centerPoint=Point.interpolate(position1,position2,0.5);if(position1.equals(position2)) +{let sinVal=Math.sin(this.model.GetLoopShiftAngel());let cosVal=Math.cos(this.model.GetLoopShiftAngel());centerPoint.x=centerPoint.x-cosVal*this.model.GetLoopSize();centerPoint.y=centerPoint.y-(sinVal+Math.sign(sinVal)*1.0)*this.model.GetLoopSize();} +return centerPoint;} +BaseEdgeDrawer.prototype.GetPointOnArc=function(position1,position2,percent) +{if(this.getPointOnArc&&this.getPointOnArc!=this) +{return this.getPointOnArc.GetPointOnArc(position1,position2,percent);} +return Point.interpolate(position1,position2,percent);} +function ProgressArcDrawer(context,baseDrawer,progress) +{this.context=context;this.baseDrawer=baseDrawer;this.progress=progress;} +ProgressArcDrawer.prototype=Object.create(BaseEdgeDrawer.prototype);ProgressArcDrawer.prototype.Draw=function(baseEdge,arcStyle) +{this.baseDrawer.Draw(baseEdge,arcStyle);this.context.lineWidth=10;var positions=baseEdge.GetEdgePositionsShift();var progressSize=10;if(positions[0].equals(positions[1])) +{var sizeInRadian=progressSize/(2*Math.PI*this.baseDrawer.model.GetLoopSize())*6;this.context.beginPath();this.context.arc(positions[0].x-Math.cos(this.baseDrawer.model.GetLoopShiftAngel())*this.baseDrawer.model.GetLoopSize(),positions[0].y-Math.sin(this.baseDrawer.model.GetLoopShiftAngel())*this.baseDrawer.model.GetLoopSize(),this.baseDrawer.model.GetLoopSize(),this.progress*2*Math.PI,this.progress*2*Math.PI+sizeInRadian);this.context.stroke();} +else +{var startPosition=this.baseDrawer.GetPointOnArc(positions[0],positions[1],this.progress);var vectorOffset=positions[0].subtract(positions[1]).normalizeCopy(progressSize);var finishPosition=startPosition.add(vectorOffset);this.context.beginPath();this.context.moveTo(startPosition.x,startPosition.y);this.context.lineTo(finishPosition.x,finishPosition.y);this.context.stroke();}} +function CurvedArcDrawer(context,model) +{this.context=context;this.model=model;} +CurvedArcDrawer.prototype=Object.create(BaseEdgeDrawer.prototype);CurvedArcDrawer.prototype.DrawArc=function(position1,position2,arcStyle) +{this.context.setLineDash(lineDashTypes[arcStyle.lineDash]);if(position1.equals(position2)) +{this.context.beginPath();this.context.arc(position1.x-Math.cos(this.model.GetLoopShiftAngel())*this.model.GetLoopSize(),position1.y-Math.sin(this.model.GetLoopShiftAngel())*this.model.GetLoopSize(),this.model.GetLoopSize(),0,2*Math.PI);this.context.closePath();this.context.stroke();} +else +{var points=this.model.GetBezierPoints(position1,position2);var firstBezierPoint=points[0];var secondBezierPoint=points[1];this.context.beginPath();this.context.moveTo(position1.x,position1.y);this.context.bezierCurveTo(firstBezierPoint.x,firstBezierPoint.y,secondBezierPoint.x,secondBezierPoint.y,position2.x,position2.y);this.context.stroke();} +this.context.setLineDash([]);} +CurvedArcDrawer.prototype.GetStartArrowDirection=function(position1,position2,lengthArrow) +{var dist=position1.distance(position2);var direction=position1.subtract(this.model.GetCurvePoint(position1,position2,lengthArrow/dist));direction.normalize(1.0);return direction;} +CurvedArcDrawer.prototype.GetFinishArrowDirection=function(position1,position2,lengthArrow) +{var dist=position1.distance(position2);var direction=position2.subtract(this.model.GetCurvePoint(position1,position2,1.0-lengthArrow/dist));direction.normalize(1.0);return direction;} +CurvedArcDrawer.prototype.GetTextCenterPoint=function(position1,position2,hasPair,arcStyle) +{var centerPoint=this.model.GetCurvePoint(position1,position2,0.5) +if(position1.equals(position2)) +{let sinVal=Math.sin(this.model.GetLoopShiftAngel());let cosVal=Math.cos(this.model.GetLoopShiftAngel());centerPoint.x=centerPoint.x-cosVal*this.model.GetLoopSize();centerPoint.y=centerPoint.y-(sinVal+Math.sign(sinVal)*1.0)*this.model.GetLoopSize();} +return centerPoint;} +CurvedArcDrawer.prototype.GetPointOnArc=function(position1,position2,percent) +{return this.model.GetCurvePoint(position1,position2,percent);} +const VertexCircleShape=0,VertexSquareShape=1,VertexTriangleShape=2,VertexPentagonShape=3,VertexHomeShape=4,VertexTextboxShape=5;VertexSnowflakeShape=6;const CommonTextCenter=0,CommonTextUp=1;const DefaultFont="px sans-serif",MainTextFontSize=16,TopTextFontSize=12.0;function GetSquarePoints(diameter) +{var res=[];var a=diameter;res.push(new Point(-a/2,-a/2));res.push(new Point(a/2,-a/2));res.push(new Point(a/2,a/2));res.push(new Point(-a/2,a/2));return res;} +function GetTrianglePoints(diameter) +{var res=[];var effectiveDiameter=diameter*1.5;var upOffset=effectiveDiameter/2;var downOffset=effectiveDiameter/4;var lrOffset=effectiveDiameter*3/(Math.sqrt(3)*4);res.push(new Point(0,-upOffset));res.push(new Point(lrOffset,downOffset));res.push(new Point(-lrOffset,downOffset));return res;} +function GetPentagonPoints(diameter) +{var res=[];var baseValue=diameter/2*1.2;res.push(new Point(0,-baseValue));res.push((new Point(0,-baseValue)).rotate(new Point(0,0),72));res.push((new Point(0,-baseValue)).rotate(new Point(0,0),72*2));res.push((new Point(0,-baseValue)).rotate(new Point(0,0),72*3));res.push((new Point(0,-baseValue)).rotate(new Point(0,0),72*4));res.push((new Point(0,-baseValue)).rotate(new Point(0,0),72*5));return res;} +function GetTextboxPoints(diameter,text) +{var res=[];var width=diameter;var height=diameter;if(text) +{var tempContext=document.createElement('canvas').getContext('2d');tempContext.font="bold "+MainTextFontSize+DefaultFont;width=tempContext.measureText(text).width+diameter/2;} +res.push(new Point(-width/2,-height/2));res.push(new Point(width/2,-height/2));res.push(new Point(width/2,height/2));res.push(new Point(-width/2,height/2));return res;} +function GetShowflakePoints(diameter) +{var res=[];var superSmallRadius=diameter*0.8/2;var smallRadius=diameter*0.95/2;var bigRadius=diameter*1.5/2;let angel=8;res.push(new Point(superSmallRadius,0).rotate(new Point(0,0),-angel));res.push(new Point(smallRadius,0));res.push(new Point(superSmallRadius,0).rotate(new Point(0,0),angel));res.push(new Point(bigRadius,0).rotate(new Point(0,0),30));res.push(new Point(superSmallRadius,0).rotate(new Point(0,0),60-angel));res.push(new Point(smallRadius,0).rotate(new Point(0,0),60));res.push(new Point(superSmallRadius,0).rotate(new Point(0,0),60+angel));res.push(new Point(bigRadius,0).rotate(new Point(0,0),30+60));res.push(new Point(superSmallRadius,0).rotate(new Point(0,0),60+60-angel));res.push(new Point(smallRadius,0).rotate(new Point(0,0),60+60));res.push(new Point(superSmallRadius,0).rotate(new Point(0,0),60+60+angel));res.push(new Point(bigRadius,0).rotate(new Point(0,0),30+60+60));res.push(new Point(superSmallRadius,0).rotate(new Point(0,0),60+60+60-angel));res.push(new Point(smallRadius,0).rotate(new Point(0,0),60+60+60));res.push(new Point(superSmallRadius,0).rotate(new Point(0,0),60+60+60+angel));res.push(new Point(bigRadius,0).rotate(new Point(0,0),30+60+60+60));res.push(new Point(superSmallRadius,0).rotate(new Point(0,0),60+60+60+60-angel));res.push(new Point(smallRadius,0).rotate(new Point(0,0),60+60+60+60));res.push(new Point(superSmallRadius,0).rotate(new Point(0,0),60+60+60+60+angel));res.push(new Point(bigRadius,0).rotate(new Point(0,0),30+60+60+60+60));res.push(new Point(superSmallRadius,0).rotate(new Point(0,0),60+60+60+60+60-angel));res.push(new Point(smallRadius,0).rotate(new Point(0,0),60+60+60+60+60));res.push(new Point(superSmallRadius,0).rotate(new Point(0,0),60+60+60+60+60+angel));res.push(new Point(bigRadius,0).rotate(new Point(0,0),30+60+60+60+60+60));return res;} +function GetPointsForShape(shape,diameter,text=null) +{switch(parseInt(shape)) +{case VertexSquareShape:return GetSquarePoints(diameter);break;case VertexTriangleShape:return GetTrianglePoints(diameter);break;case VertexPentagonShape:return GetPentagonPoints(diameter);break;case VertexTextboxShape:return GetTextboxPoints(diameter,text);break;case VertexSnowflakeShape:return GetShowflakePoints(diameter);break;default:return null;break;}} +function GetSizeForShape(shape,diameter) +{switch(parseInt(shape)) +{case VertexSquareShape:return diameter;break;case VertexTriangleShape:return diameter*1.5;break;case VertexPentagonShape:return diameter*1.2;break;case VertexTextboxShape:return diameter;break;case VertexSnowflakeShape:return diameter*1.5;break;default:return diameter;break;}} +function BaseVertexStyle() +{this.baseStyles=[];} +BaseVertexStyle.prototype.GetStyle=function(baseStyle,object) +{this.baseStyles.forEach(function(element){var styleObject=globalApplication.GetStyle("vertex",element,object);baseStyle=styleObject.GetStyle(baseStyle,object);});if(this.hasOwnProperty('lineWidth')) +baseStyle.lineWidth=this.lineWidth;if(this.hasOwnProperty('strokeStyle')) +baseStyle.strokeStyle=this.strokeStyle;if(this.hasOwnProperty('fillStyle')) +baseStyle.fillStyle=this.fillStyle;if(this.hasOwnProperty('mainTextColor')) +baseStyle.mainTextColor=this.mainTextColor;if(this.hasOwnProperty('shape')) +baseStyle.shape=this.shape;if(this.hasOwnProperty('upTextColor')) +baseStyle.upTextColor=this.upTextColor;if(this.hasOwnProperty('commonTextPosition')) +baseStyle.commonTextPosition=this.commonTextPosition;baseStyle.lineWidth=parseInt(baseStyle.lineWidth);return this.FixNewFields(baseStyle);} +BaseVertexStyle.prototype.FixNewFields=function(style) +{if(!style.hasOwnProperty('shape')) +style.shape=VertexCircleShape;if(!style.hasOwnProperty('commonTextPosition')) +style.commonTextPosition=CommonTextCenter;return style;} +BaseVertexStyle.prototype.Clear=function() +{delete this.lineWidth;delete this.strokeStyle;delete this.fillStyle;delete this.mainTextColor;delete this.shape;delete this.upTextColor;delete this.commonTextPosition;delete this.lineWidth;} +BaseVertexStyle.prototype.ShouldLoad=function(field) +{return field!="baseStyles";} +function CommonVertexStyle() +{BaseVertexStyle.apply(this,arguments);this.lineWidth=2;this.strokeStyle='#c7b7c7';this.fillStyle='#68aeba';this.mainTextColor='#f0d543';this.shape=VertexCircleShape;this.upTextColor='#68aeba';this.commonTextPosition=CommonTextCenter;this.baseStyles=[];} +CommonVertexStyle.prototype=Object.create(BaseVertexStyle.prototype);function CommonPrintVertexStyle() +{BaseVertexStyle.apply(this,arguments);this.strokeStyle='#000000';this.fillStyle='#FFFFFF';this.mainTextColor='#000000';this.baseStyles.push("common");} +CommonPrintVertexStyle.prototype=Object.create(BaseVertexStyle.prototype);function SelectedVertexStyle0() +{BaseVertexStyle.apply(this,arguments);this.strokeStyle='#f0d543';this.mainTextColor='#f0d543';this.fillStyle='#c7627a';this.baseStyles.push("common");} +SelectedVertexStyle0.prototype=Object.create(BaseVertexStyle.prototype);function SelectedVertexStyle1() +{BaseVertexStyle.apply(this,arguments);this.strokeStyle='#7a9ba0';this.mainTextColor='#c3d2d5';this.fillStyle='#534641';this.baseStyles.push("selected");} +SelectedVertexStyle1.prototype=Object.create(BaseVertexStyle.prototype);function SelectedVertexStyle2() +{BaseVertexStyle.apply(this,arguments);this.strokeStyle='#8C4C86';this.mainTextColor='#dbbdd8';this.fillStyle='#253267';this.baseStyles.push("selected");} +SelectedVertexStyle2.prototype=Object.create(BaseVertexStyle.prototype);function SelectedVertexStyle3() +{BaseVertexStyle.apply(this,arguments);this.strokeStyle='#6188FF';this.mainTextColor='#6188FF';this.fillStyle='#E97CF9';this.baseStyles.push("selected");} +SelectedVertexStyle3.prototype=Object.create(BaseVertexStyle.prototype);function SelectedVertexStyle4() +{BaseVertexStyle.apply(this,arguments);this.strokeStyle='#C6B484';this.mainTextColor='#C6B484';this.fillStyle='#E0DEE1';this.baseStyles.push("selected");} +SelectedVertexStyle4.prototype=Object.create(BaseVertexStyle.prototype);function SelectedPrintVertexStyle() +{BaseVertexStyle.apply(this,arguments);this.strokeStyle='#000000';this.mainTextColor='#000000';this.fillStyle='#AAAAAA';this.baseStyles.push("printed");} +SelectedPrintVertexStyle.prototype=Object.create(BaseVertexStyle.prototype);var DefaultSelectedGraphStyles=[new SelectedVertexStyle0(),new SelectedVertexStyle1(),new SelectedVertexStyle2(),new SelectedVertexStyle3(),new SelectedVertexStyle4()];var DefaultPrintSelectedGraphStyles=[new SelectedPrintVertexStyle()];function BaseVertexDrawer(context) +{this.context=context;} +BaseVertexDrawer.prototype.Draw=function(baseGraph,graphStyle) +{this.SetupStyle(graphStyle);this.DrawShape(baseGraph);if(this.currentStyle.lineWidth!=0) +this.context.stroke();this.context.fill();var shapeSize=GetSizeForShape(graphStyle.shape,baseGraph.model.diameter+graphStyle.lineWidth);if(graphStyle.commonTextPosition==CommonTextCenter) +{this.DrawCenterText(baseGraph.position,baseGraph.mainText,graphStyle.mainTextColor,graphStyle.fillStyle,true,true,MainTextFontSize);this.DrawCenterText(baseGraph.position.add(new Point(0,-shapeSize/2.0-9.0)),baseGraph.upText,graphStyle.upTextColor,graphStyle.strokeStyle,false,false,TopTextFontSize);} +else if(graphStyle.commonTextPosition==CommonTextUp) +{this.DrawCenterText(baseGraph.position.add(new Point(0,-shapeSize/2.0-7.0)),baseGraph.mainText,graphStyle.mainTextColor,graphStyle.fillStyle,true,false,MainTextFontSize);this.DrawCenterText(baseGraph.position.add(new Point(0,shapeSize/2.0+9.0)),baseGraph.upText,graphStyle.upTextColor,graphStyle.strokeStyle,false,false,TopTextFontSize);}} +BaseVertexDrawer.prototype.SetupStyle=function(style) +{this.currentStyle=style;this.context.lineWidth=style.lineWidth;this.context.strokeStyle=style.strokeStyle;this.context.fillStyle=style.fillStyle;} +BaseVertexDrawer.prototype.DrawShape=function(baseGraph) +{this.context.beginPath();if(this.currentStyle.shape==VertexCircleShape) +{this.context.arc(baseGraph.position.x,baseGraph.position.y,baseGraph.model.diameter/2.0,0,2*Math.PI);} +else +{var points=GetPointsForShape(this.currentStyle.shape,baseGraph.model.diameter,baseGraph.mainText);this.context.moveTo(baseGraph.position.x+points[points.length-1].x,baseGraph.position.y+points[points.length-1].y);var context=this.context;points.forEach(function(point){context.lineTo(baseGraph.position.x+point.x,baseGraph.position.y+point.y);});} +this.context.closePath();} +BaseVertexDrawer.prototype.DrawText=function(position,text,color,outlineColor,outline,font) +{this.context.fillStyle=color;this.context.font=font;this.context.lineWidth=4;this.context.strokeStyle=outlineColor;if(outline) +{this.context.save();this.context.lineJoin='round';this.context.strokeText(text,position.x,position.y);this.context.restore();} +this.context.fillText(text,position.x,position.y);} +BaseVertexDrawer.prototype.DrawCenterText=function(position,text,color,outlineColor,bold,outline,size) +{this.context.textBaseline="middle";this.context.font=(bold?"bold ":"")+size+DefaultFont;var textWidth=this.context.measureText(text).width;this.DrawText(new Point(position.x-textWidth/2,position.y),text,color,outlineColor,outline,this.context.font);} +{let modulDir="features/algorithms/";doInclude([include("model/Algorithms.js",modulDir),include("model/BaseTraversal.js",modulDir)]) +function loadAsyncAlgorithms(onFinish){let pluginsList=["BFS.js","Coloring.js","ConnectedComponent.js","DFS.js","EulerianLoop.js","EulerianPath.js","FindAllPatches.js","FindLongestPath.js","FindShortPatchsFromOne.js","Floid.js","GraphReorder.js","HamiltonianLoop.js","HamiltonianPath.js","IsomorphismCheck.js","MaxClique.js","MaxFlow.js","MinimumSpanningTree.js","ModernGraphStyle.js","RadiusAndDiameter.js","ShortestPath.js","VerticesDegree.js"];doIncludeAsync(pluginsList.map((plugin)=>include("model/plugins/"+plugin,modulDir)),onFinish);}} +function getVertexToVertexArray(graph,ignoreDirection) +{res={};for(var i=0;iprocessData+=delimiter+param.name+delimiter+param.value);var res=this.app.processEmscripten(processData);processResult(res);}else{console.log("Use new CGI");var queryString=algorithmName+"=cgiInput&report=xml";otherParams.forEach((param)=>queryString+="&"+param.name+"="+param.value);$.ajax({type:"POST",url:"/"+SiteDir+"cgi-bin/GraphCGI.exe?"+queryString,data:xml,dataType:"text",}).done(function(msg) +{processResult(msg);});} +return true;} +BaseAlgorithmEx.prototype.GetNodesPath=function(array,start,count) +{var res=[];for(var index=start;index"+"";for(var i=0;i";} +return res+"";} +BaseHandler.prototype.GetSelect2VertexMenu=function() +{return""+ +this.GetSelectVertexMenu("Vertex1")+" → "+this.GetSelectVertexMenu("Vertex2")+"";} +BaseHandler.prototype.SelectFirstVertexMenu=function(vertex1Text,vertex) +{} +BaseHandler.prototype.UpdateFirstVertexMenu=function() +{} +BaseHandler.prototype.SelectSecondVertexMenu=function(vertex2Text,vertex) +{} +BaseHandler.prototype.UpdateSecondVertexMenu=function() +{} +BaseHandler.prototype.GetSelectedVertex=function() +{return null;} +BaseHandler.prototype.addContextMenu=function() +{var $contextMenu=$("#contextMenu");var handler=this;$("#Context_Delete").click(function(){if(handler.contextMenuObject!=null){handler.app.PushToStack("DeleteObject");handler.app.DeleteObject(handler.contextMenuObject);handler.app.redrawGraph();userAction("DeleteObject_contextMenu");}});$("#Context_Rename").click(function(){if(handler.contextMenuObject!=null){var callback=function(enumType){handler.RenameVertex(enumType.GetVertexText(0),handler.contextMenuObject);userAction("RenameVertex_contextMenu");};var customEnum=new TextEnumVerticesCustom(handler.app);customEnum.ShowDialog(callback,g_rename,g_renameVertex,handler.contextMenuObject.mainText);}});$("#Context_Connect").click(function(){if(handler.contextMenuObject!=null&&handler.GetSelectedVertex()!=null){var addFunc=function(firstVertex,secondVertex,direct){handler.app.CreateNewArc(firstVertex,secondVertex,direct,document.getElementById('EdgeWeight').value,$("#RadiosReplaceEdge").prop("checked"),document.getElementById('EdgeLable').value);handler.app.redrawGraph();} +handler.ShowCreateEdgeDialog(handler.GetSelectedVertex(),handler.contextMenuObject,addFunc);}});$("#Context_Delete_Edge").click(function(){if(handler.contextMenuObject!=null){handler.app.PushToStack("DeleteObject");handler.app.DeleteObject(handler.contextMenuObject);handler.app.redrawGraph();userAction("DeleteObject_contextMenu");}});$("#Context_Edit_Edge").click(function(){if(handler.contextMenuObject!=null){handler.ShowEditEdgeDialog(handler.contextMenuObject);}});$("#Context_Add_Vertex").click(function(){handler.app.PushToStack("Add");handler.app.CreateNewGraph(handler.contextMenuPoint.x,handler.contextMenuPoint.y);handler.app.redrawGraph();});$("#Context_Back_Color").click(function(){var setupBackgroundStyle=new SetupBackgroundStyle(handler.app);setupBackgroundStyle.show();});$("body").on("contextmenu","canvas",function(e){handler.contextMenuPoint=handler.app.getMousePos(handler.app.canvas,e);handler.contextMenuObject=handler.GetSelectedObject(handler.contextMenuPoint);if(handler.contextMenuObject instanceof BaseVertex){$("#edgeContextMenu").hide();$("#backgroundContextMenu").hide();$("#vertexContextMenu").show();if(handler.GetSelectedVertex()==null){$("#Context_Connect").hide();}else{$("#Context_Connect").show();}}else if(handler.contextMenuObject instanceof BaseEdge){$("#vertexContextMenu").hide();$("#backgroundContextMenu").hide();$("#edgeContextMenu").show();}else{$("#vertexContextMenu").hide();$("#edgeContextMenu").hide();$("#backgroundContextMenu").show();} +$contextMenu.css({display:"block",left:e.offsetX,top:e.offsetY});return false;});$("body").click(function(){$contextMenu.hide();});} +BaseHandler.prototype.removeContextMenu=function() +{$("body").off("contextmenu");$("#Context_Delete").off("click");$("#Context_Rename").off("click");$("#Context_Connect").off("click");$("#Context_Delete_Edge").off("click");$("#Context_Edit_Edge").off("click");$("#Context_Add_Vertex").off("click");$("#Context_Back_Color").off("click");} +BaseHandler.prototype.RenameVertex=function(text,object) +{if(object!=null&&(object instanceof BaseVertex)) +{this.app.PushToStack("RenameVertex");object.mainText=text;this.app.redrawGraph();}} +BaseHandler.prototype.ShowCreateEdgeDialog=function(firstVertex,secondVertex,addEdgeCallBack){if(!this.app.graph.isMulti()) +{var hasEdge=this.app.graph.FindEdgeAny(firstVertex.id,secondVertex.id);var hasReverseEdge=this.app.graph.FindEdgeAny(secondVertex.id,firstVertex.id);if(hasEdge==null&&hasReverseEdge==null) +{$("#RadiosReplaceEdge").prop("checked",true);$("#NewEdgeAction").hide();} +else{$("#NewEdgeAction").show();}} +else +{$("#RadiosAddEdge").prop("checked",true);$("#NewEdgeAction").hide();} +var dialogButtons={};var handler=this;$("#CheckSaveDefaultEdge").prop("checked",false);$("#defaultEdgeDialogBlock").show();dialogButtons[g_orintEdge]=function(){handler.app.PushToStack("Connect");addEdgeCallBack(firstVertex,secondVertex,true);$(this).dialog("close");};dialogButtons[g_notOrintEdge]=function(){handler.app.PushToStack("Connect");addEdgeCallBack(firstVertex,secondVertex,false);$(this).dialog("close");};var edgePresets=this.app.GetEdgePresets();var presetsStr=""+g_DefaultWeightPreset+"";for(var i=0;i"+edgePreset+"
    ";} +document.getElementById("EdgesPresets").innerHTML=presetsStr;document.getElementById('EdgeLable').value="";$("#addEdge").dialog({resizable:false,height:"auto",width:"auto",modal:true,title:g_addEdge,buttons:dialogButtons,dialogClass:'EdgeDialog',open:function(){$(this).off('submit').on('submit',function(){return false;});setTimeout(function(){const weightInput=document.getElementById('EdgeWeight');if(weightInput) +{weightInput.focus();weightInput.select();}},0);}});} +BaseHandler.prototype.ShowEditEdgeDialog=function(edgeObject){var dialogButtons={};var handler=this;dialogButtons[g_save]=function(){handler.app.PushToStack("ChangeEdge");edgeObject.SetWeight(document.getElementById('EdgeWeight').value);edgeObject.SetUpText(document.getElementById('EdgeLable').value);handler.needRedraw=true;handler.app.redrawGraph();userAction("ChangeWeight");$(this).dialog("close");};document.getElementById('EdgeWeight').value=edgeObject.useWeight?edgeObject.weight:g_noWeight;document.getElementById('EdgeWeightSlider').value=edgeObject.useWeight?edgeObject.weight:0;var edgePresets=handler.app.GetEdgePresets();var presetsStr=""+g_DefaultWeightPreset+"";for(var i=0;i"+edgePreset+"
    ";} +document.getElementById("EdgesPresets").innerHTML=presetsStr;document.getElementById('EdgeLable').value=edgeObject.upText;$("#CheckSaveDefaultEdge").prop("checked",false);$("#defaultEdgeDialogBlock").hide();$("#addEdge").dialog({resizable:false,height:"auto",width:"auto",modal:true,title:g_editWeight,buttons:dialogButtons,dialogClass:'EdgeDialog',open:function(){$(handler).off('submit').on('submit',function(){return false;});}});} +doInclude([include("features/base_handler/index.js")]) +function DefaultHandler(app) +{this.removeStack=true;BaseHandler.apply(this,arguments);this.message=g_textsSelectAndMove+" "+g_selectGroupText+""+" "+g_useContextMenuText+"";this.selectedObjects=[];this.dragObject=null;this.selectedObject=null;this.prevPosition=null;this.groupingSelect=false;this.selectedLogRect=false;this.selectedLogCtrl=false;this.saveUndo=false;this.addContextMenu();} +DefaultHandler.prototype=Object.create(BaseHandler.prototype);DefaultHandler.prototype.pressed=false;DefaultHandler.prototype.curveValue=0.1;DefaultHandler.prototype.GetSelectedVertex=function() +{return(this.selectedObject instanceof BaseVertex)?this.selectedObject:null;} +DefaultHandler.prototype.MouseMove=function(pos) +{if(this.dragObject) +{if(!this.saveUndo) +{this.app.PushToStack("Move");this.saveUndo=true;} +this.dragObject.position.x=pos.x;this.dragObject.position.y=pos.y;this.needRedraw=true;} +else if(this.selectedObjects.length>0&&this.pressed&&!this.groupingSelect) +{if(!this.saveUndo) +{this.app.PushToStack("Move");this.saveUndo=true;} +var offset=(new Point(pos.x,pos.y)).subtract(this.prevPosition);for(var i=0;i0||this.selectedObject!=null)&&selectedObject!=null) +{if(this.selectedObjects.length==0) +{this.selectedObjects.push(this.selectedObject);this.selectedObject=null;this.selectedObjects.push(selectedObject);} +else if(!this.selectedObjects.includes(selectedObject)) +{this.selectedObjects.push(selectedObject);} +else if(severalSelect&&this.selectedObjects.includes(selectedObject)) +{var index=this.selectedObjects.indexOf(selectedObject);this.selectedObjects.splice(index,1);} +if(!this.selectedLogCtrl) +{userAction("GroupSelected.SelectCtrl");this.selectedLogCtrl=true;}} +else +{if(selectedObject!=null) +{this.selectedObject=selectedObject;} +if((selectedObject instanceof BaseVertex)&&selectedObject!=null) +{this.dragObject=selectedObject;this.message=g_moveCursorForMoving;}} +this.needRedraw=true;this.pressed=true;this.prevPosition=pos;this.app.canvas.style.cursor="move";} +DefaultHandler.prototype.MouseUp=function(pos) +{this.saveUndo=false;this.message=g_textsSelectAndMove+" "+g_selectGroupText+""+" "+g_useContextMenuText+"";this.dragObject=null;this.pressed=false;this.app.canvas.style.cursor="auto";this.app.SetSelectionRect(null);this.groupingSelect=false;if(this.selectedObject!=null&&(this.selectedObject instanceof BaseVertex)) +{this.message=g_textsSelectAndMove ++"
    " ++"" ++"" ++"
    ";var handler=this;var callback=function(enumType){handler.RenameVertex(enumType.GetVertexText(0),handler.selectedObject);userAction("RenameVertex");};$('#message').unbind();$('#message').on('click','#renameButton',function(){var customEnum=new TextEnumVerticesCustom(handler.app);customEnum.ShowDialog(callback,g_rename,g_renameVertex,handler.selectedObject.mainText);});$('#message').on('click','#changeCommonStyle',function(){var selectedVertices=handler.app.GetSelectedVertices();var setupVertexStyle=new SetupVertexStyle(handler.app);setupVertexStyle.show(0,selectedVertices);});$('#message').on('click','#changeSelectedStyle',function(){var selectedVertices=handler.app.GetSelectedVertices();var setupVertexStyle=new SetupVertexStyle(handler.app);setupVertexStyle.show(1,selectedVertices);});} +else if(this.selectedObject!=null&&(this.selectedObject instanceof BaseEdge)) +{this.message=g_textsSelectAndMove ++"" ++" "+g_curveEdge+" " ++"   " ++"
    " ++"" ++"" ++"
    ";var handler=this;$('#message').unbind();$('#message').on('click','#editEdge',function(){handler.ShowEditEdgeDialog(handler.selectedObject);});$('#message').on('click','#incCurvel',function(){handler.app.PushToStack("ChangeCurvelEdge");handler.selectedObject.model.ChangeCurveValue(DefaultHandler.prototype.curveValue);handler.needRedraw=true;handler.app.redrawGraph();userAction("Edge.Bend");});$('#message').on('click','#decCurvel',function(){handler.app.PushToStack("ChangeCurvelEdge");handler.selectedObject.model.ChangeCurveValue(-DefaultHandler.prototype.curveValue);handler.needRedraw=true;handler.app.redrawGraph();userAction("Edge.Bend");});$('#message').on('click','#changeCommonStyle',function(){var selectedEdges=handler.app.GetSelectedEdges();var setupVertexStyle=new SetupEdgeStyle(handler.app);setupVertexStyle.show(0,selectedEdges);});$('#message').on('click','#changeSelectedStyle',function(){var selectedEdges=handler.app.GetSelectedEdges();var setupVertexStyle=new SetupEdgeStyle(handler.app);setupVertexStyle.show(1,selectedEdges);});} +else if(this.selectedObjects.length>0) +{this.message=g_dragGroupText+" "+g_selectGroupText+"";var hasVertices=false;var hasEdges=false;for(var i=0;i";this.message=this.message ++"    " ++"" +this.message=this.message ++"     " ++"" ++"
    ";var handler=this;$('#message').unbind();$('#message').on('click','#DublicateSelected',function(){handler.app.PushToStack("DublicateSelection");userAction("GroupSelected.Dublicate");var newSelected=[];var copyVertex={};for(var i=0;i=1) +{var curve=handler.app.GetAvailableCurveValue(neighborEdges,newObject);newObject.model.SetCurveValue(curve);}} +newSelected.push(newObject);}} +handler.selectedObjects=newSelected;handler.needRedraw=true;handler.app.redrawGraph();});$('#message').on('click','#RemoveSelected',function(){handler.app.PushToStack("RemoveSelection");userAction("GroupSelected.Remove");for(var i=0;i"+g_selectGroupText+"";});if(hasEdges){$('#message').on('click','#changeCommonStyleEdge',function(){var selectedEdges=handler.app.GetSelectedEdges();var setupVertexStyle=new SetupEdgeStyle(handler.app);setupVertexStyle.show(0,selectedEdges);});$('#message').on('click','#changeSelectedStyleEdge',function(){var selectedEdges=handler.app.GetSelectedEdges();var setupVertexStyle=new SetupEdgeStyle(handler.app);setupVertexStyle.show(1,selectedEdges);});} +if(hasVertices){$('#message').on('click','#changeCommonStyleVertex',function(){var selectedVertices=handler.app.GetSelectedVertices();var setupVertexStyle=new SetupVertexStyle(handler.app);setupVertexStyle.show(0,selectedVertices);});$('#message').on('click','#changeSelectedStyleVertex',function(){var selectedVertices=handler.app.GetSelectedVertices();var setupVertexStyle=new SetupVertexStyle(handler.app);setupVertexStyle.show(1,selectedVertices);});}} +this.needRedraw=true;} +DefaultHandler.prototype.GetSelectedGroup=function(object) +{return(object==this.dragObject)||(object==this.selectedObject)?1:0||this.selectedObjects.includes(object);} +DefaultHandler.prototype.SelectObjectInRect=function(rect) +{this.selectedObjects=[];var vertices=this.app.graph.vertices;for(var i=0;i" ++" " ++"" ++" "+baseMessage;} +ConnectionGraphHandler.checkUseDefaultEdge=function(elem,app) +{app.setUseDefaultEdge(elem.checked);app.updateMessage();};ConnectionGraphHandler.prototype.GetUseDefaultEdgeCheckBox=function(){if(!this.app.hasDefaultEdge()){return"";} +return"
    "+""+" "+"
    ";} +ConnectionGraphHandler.prototype.InitControls=function(){BaseHandler.prototype.InitControls.call(this) +if(!this.app.hasDefaultEdge()){return;} +let app=this.app;$('#useDefaultEdge').unbind();$('#useDefaultEdge').change(function(){app.setUseDefaultEdge(this.checked);});$("#useDefaultEdge").prop("checked",this.app.getUseDefaultEdge());} +doInclude([include("features/base_handler/index.js")]) +function DeleteGraphHandler(app) +{this.removeStack=true;BaseHandler.apply(this,arguments);this.message=g_selectObjectToDelete;this.addContextMenu();} +DeleteGraphHandler.prototype=Object.create(BaseHandler.prototype);DeleteGraphHandler.prototype.MouseDown=function(pos) +{var selectedObject=this.GetSelectedObject(pos);if(!this.app.IsCorrectObject(selectedObject)) +return;this.app.PushToStack("Delete");this.app.DeleteObject(selectedObject);this.needRedraw=true;} +function DeleteAllHandler(app) +{BaseHandler.apply(this,arguments);} +DeleteAllHandler.prototype=Object.create(BaseHandler.prototype);DeleteAllHandler.prototype.clear=function() +{this.app.PushToStack("DeleteAll");this.app.graph=new Graph();this.app.savedGraphName="";this.needRedraw=true;} +doInclude([include("features/base_handler/index.js")]) +function AlgorithmGraphHandler(app,algorithm) +{BaseHandler.apply(this,arguments);this.algorithm=algorithm;this.SaveUpText();this.UpdateResultAndMessage();} +AlgorithmGraphHandler.prototype=Object.create(BaseHandler.prototype);AlgorithmGraphHandler.prototype.MouseMove=function(pos){} +AlgorithmGraphHandler.prototype.MouseDown=function(pos) +{this.app.setRenderPath([]);if(this.algorithm.instance()) +{this.app.SetDefaultHandler();} +else +{var selectedObject=this.GetSelectedGraph(pos);if(selectedObject&&(selectedObject instanceof BaseVertex)) +{if(this.algorithm.selectVertex(selectedObject)) +{this.needRedraw=true;} +this.UpdateResultAndMessage();} +else if(selectedObject&&(selectedObject instanceof BaseEdge)) +{if(this.algorithm.selectEdge(selectedObject)) +{this.needRedraw=true;} +this.UpdateResultAndMessage();} +else +{if(this.algorithm.deselectAll()) +{this.needRedraw=true;this.UpdateResultAndMessage();}}}} +AlgorithmGraphHandler.prototype.MouseUp=function(pos){} +AlgorithmGraphHandler.prototype.GetSelectedGroup=function(object) +{return this.algorithm.getObjectSelectedGroup(object);} +AlgorithmGraphHandler.prototype.RestoreAll=function() +{this.app.setRenderPath([]);if(this.algorithm.needRestoreUpText()) +{this.RestoreUpText();} +if(this.algorithm.wantRestore()) +{this.algorithm.restore();}} +AlgorithmGraphHandler.prototype.SaveUpText=function() +{this.vertexUpText={};var graph=this.app.graph;for(i=0;i";var directedHeader="";var undirectedHeader="";var defaultWeight=1.0;var weightKeyId="\"d0\"";var weightNode=""+""+defaultWeight+""+"";var xmlBody="";for(var i=0;i";} +var hasDirected=false;for(var i=0;i"+arc.weight+"";} +xmlBody=xmlBody+""+weightData+"":"/>")} +xml=mainHeader+weightNode+(hasDirected?directedHeader:undirectedHeader)+xmlBody+"" +return xml;} +function BaseEnumVertices(app,startNumber) +{this.app=app;this.startNumber=startNumber;} +BaseEnumVertices.prototype.GetVertexText=function(id) +{return this.startNumber+id;} +BaseEnumVertices.prototype.GetVertexTextAsync=function(callback) +{callback(this);} +BaseEnumVertices.prototype.GetText=function() +{return this.startNumber+", "+(this.startNumber+1)+", "+(this.startNumber+2)+"...";} +BaseEnumVertices.prototype.GetValue=function() +{return"Numbers"+this.startNumber;} +function TextEnumTitle(app,title) +{BaseEnumVertices.apply(this,arguments);this.pattern="";this.title=title;} +TextEnumTitle.prototype=Object.create(BaseEnumVertices.prototype);TextEnumTitle.prototype.GetVertexText=function(id) +{return this.title;} +function TextEnumVertices(app) +{BaseEnumVertices.apply(this,arguments);this.pattern="ABCDEFGHIJKLMNOPQRSTUVWXYZ";} +TextEnumVertices.prototype=Object.create(BaseEnumVertices.prototype);TextEnumVertices.prototype.GetVertexText=function(id) +{var res="";res=this.pattern[id%this.pattern.length]+res;while(id>=this.pattern.length) +{id=Math.floor(id/this.pattern.length)-1;res=this.pattern[id%this.pattern.length]+res;} +return res;} +TextEnumVertices.prototype.GetText=function() +{return"A, B, ... Z";} +TextEnumVertices.prototype.GetValue=function() +{return"Latin";} +function TextEnumVerticesCyr(app) +{TextEnumVertices.apply(this,arguments);this.pattern="АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ";} +TextEnumVerticesCyr.prototype=Object.create(TextEnumVertices.prototype);TextEnumVerticesCyr.prototype.GetText=function() +{return"А, Б, ... Я";} +TextEnumVerticesCyr.prototype.GetValue=function() +{return"Cyrillic";} +function TextEnumVerticesGreek(app) +{TextEnumVertices.apply(this,arguments);this.pattern="ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ";} +TextEnumVerticesGreek.prototype=Object.create(TextEnumVertices.prototype);TextEnumVerticesGreek.prototype.GetText=function() +{return"Α, Β, ... Ω";} +TextEnumVerticesGreek.prototype.GetValue=function() +{return"Greek";} +function TextEnumVerticesCustom(app) +{BaseEnumVertices.apply(this,arguments);this.pattern="";} +TextEnumVerticesCustom.prototype=Object.create(BaseEnumVertices.prototype);TextEnumVerticesCustom.prototype.GetText=function() +{return g_customEnumVertex;} +TextEnumVerticesCustom.prototype.GetValue=function() +{return"Custom";} +TextEnumVerticesCustom.prototype.GetVertexTextAsync=function(callback) +{this.ShowDialog(callback,g_addVertex,g_addVertex,"A");} +TextEnumVerticesCustom.prototype.ShowDialog=function(callback,buttonText,titleTitle,title) +{var dialogButtons={};app=this.app;dialogButtons[buttonText]=function(){app.PushToStack("RenameVertex");callback(new TextEnumTitle(app,$("#VertexTitle").val()));$(this).dialog("close");};$("#addVertex").dialog({resizable:false,height:"auto",width:"auto",modal:true,title:titleTitle,buttons:dialogButtons,dialogClass:'EdgeDialog',open:function(){$(this).off('submit').on('submit',function(){return false;});$("#VertexTitle").val(title);$("#VertexTitle").focus();}});} +var g_textsSelectAndMove="Drag objects";var g_moveCursorForMoving="Move cursor";var g_clickToAddVertex="Click to add vertex";var g_selectFirstVertexToConnect="Select first vertex to connect";var g_selectSecondVertexToConnect="Select second vertex to connect";var g_selectStartVertexForShortPath="Select start vertex for shortest path";var g_selectFinishVertexForShortPath="Select finish vertex for shortest path";var g_shortestPathResult="Shortest path is %d";var g_pathNotExists="Path does not exists";var g_selectObjectToDelete="Select object to delete";var g_addEdge="Add edge";var g_orintEdge="Directed";var g_notOrintEdge="Undirected";var g_adjacencyMatrixText="Adjacency Matrix";var g_save="Save";var g_cancel="Cancel";var g_save_graph="Save Graph";var g_shortestDistance="lowest-distance is ";var g_incidenceMatrixText="Incidence Matrix";var g_save_dialog="Save dialog";var g_close="close";var g_sickConnectedComponent="Sick connected component is ";var g_connectedComponent="Connected component is ";var g_what_do_you_think="What do you think about site?";var g_name="Name";var g_feedback="Feedback";var g_send="Send";var g_write_to_us="Write to us";var g_fixMatrix="Fix matrix";var g_readMatrixHelp="Matrix format help";var g_matrixWrongFormat="Matrix is wrong";var g_pairWrongFormat="Edge List is wrong";var g_fix="Fix" +var g_save_image_dialog="Save graph image";var g_fullReport="Full report";var g_shortReport="Short report";var g_hasEulerianLoop="Graph has Eulerian Loop";var g_hasNotEulerianLoop="Graph has not Eulerian Loop";var g_hasEulerianPath="Graph has Eulerian Path";var g_hasNotEulerianPath="Graph has not Eulerian Path";var g_processing="Processing...";var g_customEnumVertex="Custom";var g_addVertex="Add vertex";var g_renameVertex="Rename vertex";var g_rename="Rename";var g_language="en";var g_editWeight="Edit weight";var g_noWeight="No weight";var g_groupRename="Group rename";var g_vote="Vote";var g_recommendAlgorithm="Recommend algorithm";var g_graphOfMinDist="Graph of minimal distances.";var g_checkToSave="Check to save";var g_showDistMatrix="Show Distance matrix";var g_minDistMatrixText="Minimal distances matrix";var g_selectStartVertexForMaxFlow="Select source vertex for max flow";var g_selectFinishVertexForMaxFlow="Select sink vertex for max flow";var g_maxFlowResult="Maximum flow from %2 to %3 is %1";var g_flowNotExists="Flow from %1 to %2 does not exists";var g_sourceVertex="Source";var g_sinkVertex="Sink";var g_hasHamiltonianLoop="Graph has Hamiltonian Loop";var g_hasNotHamiltonianLoop="Graph has not Hamiltonian Loop";var g_hasHamiltonianPath="Graph has Hamiltonian Path";var g_hasNotHamiltonianPath="Graph has not Hamiltonian Path";var g_startTraversal="Select start traversal vector";var g_traversalOrder="Traversal order: ";var g_curveEdge="Curved edge";var g_Undo="Undo";var g_default="default";var g_vertexDraw="Vertex draw style";var g_edgeDraw="Edge draw style";var g_backgroundStyle="Background style";var g_GraphIsMultiMessage="Graph is multigraph";var g_GraphIsGeneralMessage="";var g_DefaultWeightPreset="no weight";var g_dragGroupText="Drag group.";var g_selectGroupText="Select using ctrl";var g_copyGroupeButton="Duplicate";var g_removeGroupeButton="Remove objects";var g_BFSName="Breadth-first search";var g_ColoringName="Graph coloring";var g_findConnectedComponent="Find connected components";var g_DFSName="Depth-first search";var g_EulerinLoopName="Find Eulerian cycle";var g_EulerinPath="Find Eulerian path";var g_FloidName="Floyd–Warshall algorithm";var g_GraphReorder="Arrange the graph";var g_HamiltoianCycleName="Find Hamiltonian cycle";var g_HamiltonianPath="Find Hamiltonian path";var g_MaxFlowName="Find Maximum flow";var g_minimumSpanningTree="Search of minimum spanning tree";var g_modernGraphStyleName="Visualization based on weight";var g_RadiusAndDiameter="Search graph radius and diameter";var g_findShortPathName="Find shortest path using Dijkstra's algorithm";var g_VerticesDegreeName="Calculate vertices degree";var g_SpanningTreeResult="Min Spanning Tree is";var g_SpanningTreeIgnoreDir="We ignored edges direction for calculation";var g_SpanningTreeNotConnected="Graph is not connected";var g_selectFirstGraphIsomorphismCheck="Select first graph for isomorphic check. Click to any node of graph";var g_selectSecondGraphIsomorphismCheck="Select second graph for isomorphic check. Click to any node of graph";var g_selectFirstGraphPatternCheck="Select a template graph by clicking to any node of graph";var g_selectSecondGraphForSearchSubgraph="Choose a graph in which we will look for isomorphic subgraphs. Click to any node of this graph";var g_graphsIsomorph="Graphs are isomorphic";var g_graphsNotIsomorph="Graphs are not isomorphic";var g_numberOfIsomorphSubgraphIs="Number of isomorphic subgraphs are ";var g_graphHasNoIsomorphSubgraph="Graph don't contain isomorphic subgraphs";var g_searchIsomorphSubgraph="Search isomorphic subgraphs";var g_subgraphNo="Isomorphic subgraph # ";var g_graphHasNoAtleast2Graphs="To use the algorithm, you need to create 2 separate graphs";var g_IsomorphismCheck="Check Graphs Isomorphism";var g_graphIsDisconnected="Graph is disconnected";var g_graphIsTrivial="Graph contains only one vertex";var g_graphRadius="Graph radius";var g_graphDiameter="Graph diameter";var g_vertexCentral="Central";var g_vertexPeripheral="Peripheral";var g_maximumDegreeOfGraph="The maximum degree of a graph is";var g_colorNumber="Color number is";var g_done="Done";var g_action="Action";var g_commonEdgeStyle="Common Edge Style";var g_selectedEdgeStyle="Selected Edge Style";var g_commonVertexStyle="Common Vertex Style";var g_selectedVertexStyle="Selected Vertex Style";var g_findAllPathes="Find all paths";var g_numberOfPathesFrom="Number of paths from " +var g_to=" to ";var g_are=" are ";var g_pathN="Path #";var g_selectFinishVertex="Select finish vertex";var g_selectStartVertex="Select start vertex";var g_findAllPathesFromVertex="Find all shortest paths from vertex";var g_distanceFrom="Distance from ";var g_pathTo="Path to ";var g_useContextMenuText="Use context menu for addition actions." +var g_findLongestPath="Find the longest path";var g_LengthOfLongestPathFrom="Length of the longest path from ";var g_additionalActions="Additional actions";var g_reverseAllEdges="Reverse all edges";var g_makeAllUndirected="Make all edges undirected";var g_makeAllDirected="Make all edges directed";var g_reuseSavedEdge="Reuse saved edge";var g_MaxClique="Max Clique";var g_MaxCliqueNotFound="Max Clique is not found";var g_MaxCliqueSizeIs="Max Clique size is ";var g_MaxCliqueContains=". Clique contains these vertecies: ";var g_wrongImageFormatPNGAndJPEG="Wrong image format. We support only JPEG and PNG.";var g_wrongImageSizeP1="Image size is too big. Image size must be less than {0} pixels.";function loadTexts() +{g_textsSelectAndMove=document.getElementById("SelectAndMoveObject").innerHTML;g_moveCursorForMoving=document.getElementById("MoveCursorForMoving").innerHTML;g_clickToAddVertex=document.getElementById("clickToAddVertex").innerHTML;g_selectFirstVertexToConnect=document.getElementById("selectFisrtVertextToConnect").innerHTML;g_selectSecondVertexToConnect=document.getElementById("selectSecondVertextToConnect").innerHTML;g_selectStartVertexForShortPath=document.getElementById("selectStartShortPathVertex").innerHTML;g_selectFinishVertexForShortPath=document.getElementById("selectFinishShortPathVertex").innerHTML;g_shortestPathResult=document.getElementById("shortPathResult").innerHTML;g_pathNotExists=document.getElementById("pathNotExists").innerHTML;g_selectObjectToDelete=document.getElementById("selectObjectToDelete").innerHTML;g_addEdge=document.getElementById("AddEdge").innerHTML;g_orintEdge=document.getElementById("OrintEdge").innerHTML;g_notOrintEdge=document.getElementById("NotOrintdge").innerHTML;g_adjacencyMatrixText=document.getElementById("AdjacencyMatrixText").innerHTML;g_save=document.getElementById("Save").innerHTML;g_cancel=document.getElementById("Cancel").innerHTML;g_shortestDistance=document.getElementById("shortestDist").innerHTML;g_incidenceMatrixText=document.getElementById("IncidenceMatrixText").innerHTML;g_save_dialog=document.getElementById("saveDialogTitle").innerHTML;g_close=document.getElementById("closeButton").innerHTML;g_sickConnectedComponent=document.getElementById("sickConnectedComponentResult").innerHTML;g_connectedComponent=document.getElementById("connectedComponentResult").innerHTML;g_what_do_you_think=document.getElementById("whatDoYouThink").innerHTML;g_name=document.getElementById("name").innerHTML;g_feedback=document.getElementById("feedback").innerHTML;g_send=document.getElementById("send").innerHTML;g_write_to_us=document.getElementById("writeToUs").innerHTML;g_fixMatrix=document.getElementById("fixMatrixButton").innerHTML;g_readMatrixHelp=document.getElementById("matrixHelp").innerHTML;g_matrixWrongFormat=document.getElementById("wronMatrixTitle").innerHTML;g_save_image_dialog=document.getElementById("saveImageDialogTitle").innerHTML;g_fullReport=document.getElementById("fullReport").innerHTML;g_shortReport=document.getElementById("shortReport").innerHTML;g_hasEulerianLoop=document.getElementById("hasEulerianLoop").innerHTML;g_hasNotEulerianLoop=document.getElementById("hasNotEulerianLoop").innerHTML;g_processing=document.getElementById("processing").innerHTML;g_customEnumVertex=document.getElementById("customEnumVertex").innerHTML;g_addVertex=document.getElementById("addVertexText").innerHTML;g_renameVertex=document.getElementById("renameVertex").innerHTML;g_rename=document.getElementById("renameText").innerHTML;g_language=document.getElementById("currentLanguage").innerHTML;g_editWeight=document.getElementById("editWeight").innerHTML;g_noWeight=document.getElementById("noWeight").innerHTML;g_groupRename=document.getElementById("groupeRenameText").innerHTML;g_vote=document.getElementById("voteText").innerHTML;g_recommendAlgorithm=document.getElementById("recommend_algorithm").innerHTML;g_hasEulerianPath=document.getElementById("hasEulerianPath").innerHTML;g_hasNotEulerianPath=document.getElementById("hasNotEulerianPath").innerHTML;g_graphOfMinDist=document.getElementById("graphOfMinDist").innerHTML;g_checkToSave=document.getElementById("checkToSave").innerHTML;g_showDistMatrix=document.getElementById("showDistMatrix").innerHTML;g_minDistMatrixText=document.getElementById("distMatrixText").innerHTML;g_selectStartVertexForMaxFlow=document.getElementById("selectStartVertexForMaxFlow").innerHTML;g_selectFinishVertexForMaxFlow=document.getElementById("selectFinishVertexForMaxFlow").innerHTML;g_maxFlowResult=document.getElementById("maxFlowResult").innerHTML;g_flowNotExists=document.getElementById("flowNotExists").innerHTML;g_sourceVertex=document.getElementById("sourceVertex").innerHTML;g_sinkVertex=document.getElementById("sinkVertex").innerHTML;g_hasHamiltonianLoop=document.getElementById("hasHamiltonianLoop").innerHTML;g_hasNotHamiltonianLoop=document.getElementById("hasNotHamiltonianLoop").innerHTML;g_hasHamiltonianPath=document.getElementById("hasHamiltonianPath").innerHTML;g_hasNotHamiltonianPath=document.getElementById("hasNotHamiltonianPath").innerHTML;g_startTraversal=document.getElementById("startTraversal").innerHTML;g_traversalOrder=document.getElementById("traversalOrder").innerHTML;g_curveEdge=document.getElementById("curveEdge").innerHTML;g_Undo=document.getElementById("undoTranslate").innerHTML;g_save_graph=document.getElementById("saveGraph").innerHTML;g_default=document.getElementById("default").innerHTML;g_vertexDraw=document.getElementById("vertexDrawStyle").innerHTML;g_edgeDraw=document.getElementById("edgeDrawStyle").innerHTML;g_backgroundStyle=document.getElementById("backgroundStyle").innerHTML;g_GraphIsMultiMessage=document.getElementById("graphIsMultiMessage").innerHTML;g_GraphIsGeneralMessage=document.getElementById("graphIsGeneralMessage").innerHTML;g_DefaultWeightPreset=document.getElementById("defaultWeightPreset").innerHTML;var isMac=navigator.platform.toUpperCase().indexOf('MAC')>=0;if(isMac) +g_selectGroupText=document.getElementById("selectGroupMac").innerHTML;else +g_selectGroupText=document.getElementById("selectGroupWin").innerHTML;g_dragGroupText=document.getElementById("dragSelectedGroup").innerHTML;g_copyGroupeButton=document.getElementById("copySelectedGroup").innerHTML;g_removeGroupeButton=document.getElementById("removeSelectedGroup").innerHTML;g_BFSName=document.getElementById("BFSName").innerHTML;g_ColoringName=document.getElementById("ColoringName").innerHTML;g_findConnectedComponent=document.getElementById("findConnectedComponent").innerHTML;g_DFSName=document.getElementById("DFSName").innerHTML;g_EulerinLoopName=document.getElementById("EulerinLoopName").innerHTML;g_EulerinPath=document.getElementById("EulerinPath").innerHTML;g_FloidName=document.getElementById("FloidName").innerHTML;g_GraphReorder=document.getElementById("GraphReorder").innerHTML;g_HamiltoianCycleName=document.getElementById("HamiltoianCycleName").innerHTML;g_HamiltonianPath=document.getElementById("HamiltonianPath").innerHTML;g_MaxFlowName=document.getElementById("MaxFlowName").innerHTML;g_minimumSpanningTree=document.getElementById("minimumSpanningTree").innerHTML;g_modernGraphStyleName=document.getElementById("modernGraphStyleName").innerHTML;g_RadiusAndDiameter=document.getElementById("RadiusAndDiameter").innerHTML;g_findShortPathName=document.getElementById("findShortPathName").innerHTML;g_VerticesDegreeName=document.getElementById("VerticesDegreeName").innerHTML;g_SpanningTreeResult=document.getElementById("MinSpanningTreeResult").innerHTML;g_SpanningTreeIgnoreDir=document.getElementById("MinSpanningIgnoreDir").innerHTML;g_SpanningTreeNotConnected=document.getElementById("MinSpanningNotConnected").innerHTML;g_selectFirstGraphIsomorphismCheck=document.getElementById("SelectFirstGraphIsomorphismCheck").innerHTML;g_selectSecondGraphIsomorphismCheck=document.getElementById("SelectSecondGraphIsomorphismCheck").innerHTML;g_selectFirstGraphPatternCheck=document.getElementById("SelectFirstGraphPatternCheck").innerHTML;g_selectSecondGraphForSearchSubgraph=document.getElementById("SelectSecondGraphForSearchSubgraph").innerHTML;g_graphsIsomorph=document.getElementById("GraphsIsomorph").innerHTML;g_graphsNotIsomorph=document.getElementById("GraphsNotIsomorph").innerHTML;g_numberOfIsomorphSubgraphIs=document.getElementById("NumberOfIsomorphSubgraphIs").innerHTML;g_graphHasNoIsomorphSubgraph=document.getElementById("GraphHasNoIsomorphSubgraph").innerHTML;g_searchIsomorphSubgraph=document.getElementById("SearchIsomorphSubgraph").innerHTML;g_subgraphNo=document.getElementById("SubgraphNo").innerHTML;g_graphHasNoAtleast2Graphs=document.getElementById("GraphHasNoAtleast2Graphs").innerHTML;g_IsomorphismCheck=document.getElementById("IsomorphismCheck").innerHTML;g_graphIsDisconnected=document.getElementById("GraphIsDisconnected").innerHTML;g_graphIsTrivial=document.getElementById("GraphIsTrivial").innerHTML;g_graphRadius=document.getElementById("GraphRadius").innerHTML;g_graphDiameter=document.getElementById("GraphDiameter").innerHTML;g_vertexCentral=document.getElementById("VertexCentral").innerHTML;g_vertexPeripheral=document.getElementById("VertexPeripheral").innerHTML;g_maximumDegreeOfGraph=document.getElementById("MaximumDegreeOfGraph").innerHTML;g_colorNumber=document.getElementById("ColorNumber").innerHTML;g_done=document.getElementById("Done").innerHTML;g_action=document.getElementById("ActionText").innerHTML;g_commonEdgeStyle=document.getElementById("CommonEdgeStyleText").innerHTML;g_selectedEdgeStyle=document.getElementById("SelectedEdgeStyleText").innerHTML;g_commonVertexStyle=document.getElementById("CommonVertexStyleText").innerHTML;g_selectedVertexStyle=document.getElementById("SelectedVertexStyleText").innerHTML;g_findAllPathes=document.getElementById("FindAllPathes").innerHTML;g_numberOfPathesFrom=document.getElementById("NumberOfPathesFrom").innerHTML;g_to=document.getElementById("To").innerHTML;g_are=document.getElementById("Are").innerHTML;g_pathN=document.getElementById("PathN").innerHTML;g_selectFinishVertex=document.getElementById("SelectFinishVertex").innerHTML;g_selectStartVertex=document.getElementById("SelectStartVertex").innerHTML;g_findAllPathesFromVertex=document.getElementById("findAllPathsFromVertex").innerHTML;g_distanceFrom=document.getElementById("distanceFrom").innerHTML;g_pathTo=document.getElementById("pathTo").innerHTML;g_useContextMenuText=document.getElementById("UseContextMenuText").innerHTML;g_findLongestPath=document.getElementById("findLongestPath").innerHTML;g_LengthOfLongestPathFrom=document.getElementById("LengthOfLongestPathFrom").innerHTML;g_additionalActions=document.getElementById("additionlActions").innerHTML;g_reverseAllEdges=document.getElementById("reverseAllEdges").innerHTML;g_makeAllUndirected=document.getElementById("makeAllUndirected").innerHTML;g_makeAllDirected=document.getElementById("makeAllDirected").innerHTML;g_pairWrongFormat=document.getElementById("pairWrongFormat").innerHTML;g_fix=document.getElementById("fixButton").innerHTML;g_reuseSavedEdge=document.getElementById("reuseSavedEdge").innerHTML;g_MaxClique=document.getElementById("maxClique").innerHTML;g_MaxCliqueNotFound=document.getElementById("maxCliqueNotFound").innerHTML;g_MaxCliqueSizeIs=document.getElementById("maxCliqueSizeIs").innerHTML;g_MaxCliqueContains=document.getElementById("maxCliqueContains").innerHTML;g_wrongImageFormatPNGAndJPEG=document.getElementById("wrongImageFormatPNGAndJPEG").innerHTML;g_wrongImageSizeP1=document.getElementById("wrongImageSizeP1").innerHTML;} +var globalApplication=null;function Application(document,window) +{this.document=document;this.canvas=this.document.getElementById('canvas');this.handler=new DefaultHandler(this);this.savedGraphName="";this.currentEnumVerticesType=new BaseEnumVertices(this,1);this.findPathReport=1;this.isTimerRender=false;globalApplication=this;this.renderPath=[];this.renderTimer=0;this.renderPathLength=0;this.renderPathCounter=0;this.renderPathLoops=0;this.enumVerticesTextList=[new BaseEnumVertices(this,1),new BaseEnumVertices(this,0),new TextEnumVertices(this),new TextEnumVerticesCyr(this),new TextEnumVerticesGreek(this),new TextEnumVerticesCustom(this)];this.SetDefaultTransformations();this.algorithmsValues={};this.userAction=function(){};this.undoStack=[];this.edgeCommonStyle=new CommonEdgeStyle();this.isEdgeCommonStyleCustom=false;this.edgeSelectedStyles=FullArrayCopy(DefaultSelectedEdgeStyles);this.isEdgeSelectedStylesCustom=false;this.edgePrintCommonStyle=new CommonPrintEdgeStyle();this.edgePrintSelectedStyles=FullArrayCopy(DefaultPrintSelectedEdgeStyles);this.vertexCommonStyle=new CommonVertexStyle();this.isVertexCommonStyleCustom=false;this.vertexSelectedVertexStyles=FullArrayCopy(DefaultSelectedGraphStyles);this.isVertexSelectedVertexStylesCustom=false;this.vertexPrintCommonStyle=new CommonPrintVertexStyle();this.vertexPrintSelectedVertexStyles=FullArrayCopy(DefaultPrintSelectedGraphStyles);this.backgroundCommonStyle=new CommonBackgroundStyle();this.backgroundPrintStyle=new PrintBackgroundStyle();this.isBackgroundCommonStyleCustom=false;this.renderPathWithEdges=false;this.edgePresets=[1,3,5,7,11,42];this.maxEdgePresets=6;this.selectionRect=null;this.defaultVertexSize=null;this.defaultEdgeWidth=null;this.processEmscriptenFunction=null;this.defaultEdge=null;this.useDefaultEdge=false;};Application.prototype.graph=new Graph();Application.prototype.dragObject=-1;Application.prototype.handler=null;Application.prototype.status={};Application.prototype.graphNameLength=16;Application.prototype.maxUndoStackSize=8;Application.prototype.getMousePos=function(canvas,e) +{var rect=canvas.getBoundingClientRect();return{x:(e.clientX-rect.left)/this.canvasScale-this.canvasPosition.x,y:(e.clientY-rect.top)/this.canvasScale-this.canvasPosition.y};} +Application.prototype.redrawGraph=function() +{if(!this.isTimerRender) +{this._redrawGraphInWindow();this.GraphTypeChanged();}} +Application.prototype.redrawGraphTimer=function() +{if(this.isTimerRender) +{var context=this._redrawGraphInWindow();if(this.renderPath.length>1) +{context.save();context.scale(this.canvasScale,this.canvasScale);context.translate(this.canvasPosition.x,this.canvasPosition.y);var movePixelStep=16;var currentLength=0;var i=0 +for(i=0;ithis.renderPathCounter) +{currentLength-=edge.GetPixelLength();break;}} +if(i>=this.renderPath.length-1) +{i=0;if(this.renderPathWithEdges) +i=1;this.renderPathCounter=0;currentLength=0;this.renderPathLoops+=1;} +var edge=null;var currentVertexId=this.renderPath[i];if(this.renderPathWithEdges) +{edge=this.graph.FindEdgeById(this.renderPath[i]);currentVertexId=this.renderPath[i-1];} +else if(this.renderMinPath) +{edge=this.graph.FindEdgeMin(this.renderPath[i],this.renderPath[i+1]);} +else +{edge=this.graph.FindEdge(this.renderPath[i],this.renderPath[i+1]);} +var progress=(this.renderPathCounter-currentLength)/edge.GetPixelLength();this.RedrawEdgeProgress(context,edge,edge.vertex1.id==currentVertexId?progress:1.0-progress);this.renderPathCounter+=movePixelStep;context.restore();}} +if(this.renderPathLoops>=5) +{this.stopRenderTimer();}} +Application.prototype._redrawGraphInWindow=function() +{var context=this.canvas.getContext('2d');context.save();context.scale(this.canvasScale,this.canvasScale);context.translate(this.canvasPosition.x,this.canvasPosition.y);this._RedrawGraph(context,this.canvasPosition,this.backgroundCommonStyle,true);context.restore();return context;} +Application.prototype._OffscreenRedrawGraph=function() +{var bbox=this.graph.getGraphBBox();var canvas=document.createElement('canvas');canvas.width=bbox.size().x;canvas.height=bbox.size().y;var context=canvas.getContext('2d');context.save();context.translate(bbox.minPoint.inverse().x,bbox.minPoint.inverse().y);this._RedrawGraph(context,bbox.minPoint.inverse(),this.backgroundCommonStyle,false);context.restore();return canvas;} +Application.prototype._PrintRedrawGraph=function() +{var bbox=this.graph.getGraphBBox();var canvas=document.createElement('canvas');canvas.width=bbox.size().x;canvas.height=bbox.size().y;var context=canvas.getContext('2d');context.save();context.translate(bbox.minPoint.inverse().x,bbox.minPoint.inverse().y);this._RedrawGraph(context,bbox.minPoint.inverse(),this.backgroundPrintStyle,false,this.vertexPrintCommonStyle,this.vertexPrintSelectedVertexStyles,this.edgePrintCommonStyle,this.edgePrintSelectedStyles);context.restore();return canvas;} +Application.prototype._printToSVG=function() +{var bbox=this.graph.getGraphBBox();var context=new C2S(bbox.size().x,bbox.size().y);context.save();context.translate(bbox.minPoint.inverse().x,bbox.minPoint.inverse().y);this._RedrawGraph(context,bbox.minPoint.inverse(),this.backgroundCommonStyle,false);context.restore();return context.getSerializedSvg();} +Application.prototype.updateRenderPathLength=function() +{this.renderPathLength=0;this.renderPathCounter=0;if(this.renderPath.length>1) +{for(var i=0;i0) +{this.startRenderTimer();} +else +{this.stopRenderTimer();}} +Application.prototype.setRenderPathWithEdges=function(renderPath) +{this.renderPath=renderPath;this.renderMinPath=false;this.renderPathWithEdges=true;if(this.renderPath.length>0) +{this.startRenderTimer();} +else +{this.stopRenderTimer();}} +Application.prototype.GetBaseArcDrawer=function(context,edge) +{var arcDrawer=new BaseEdgeDrawer(context);if(edge.model.type==EdgeModels.curve) +{var curvedArcDrawer=new CurvedArcDrawer(context,edge.model);arcDrawer=new BaseEdgeDrawer(context,{drawArc:curvedArcDrawer,startArrowDirection:curvedArcDrawer,finishArrowDirection:curvedArcDrawer,textCenterObject:curvedArcDrawer,getPointOnArc:curvedArcDrawer});} +return arcDrawer;} +Application.prototype.UpdateEdgeCurrentStyle=function(edge,ForceCommonStyle,ForceSelectedStyle) +{var commonStyle=(ForceCommonStyle===undefined)?this.edgeCommonStyle:ForceCommonStyle;var selectedStyle=(ForceSelectedStyle===undefined)?this.edgeSelectedStyles:ForceSelectedStyle;var selectedGroup=this.handler.GetSelectedGroup(edge);var selected=false;if(selectedGroup>0) +{selectedGroup=(selectedGroup-1)%selectedStyle.length;selected=true;} +var currentStyle=null;if(edge.hasOwnStyleFor((selected?1:0)+selectedGroup)) +currentStyle=edge.getStyleFor((selected?1:0)+selectedGroup);else +currentStyle=selected?selectedStyle[selectedGroup]:commonStyle;edge.currentStyle=currentStyle;} +Application.prototype.RedrawEdge=function(context,edge) +{var curvedArcDrawer=new CurvedArcDrawer(context,edge.model) +var arcDrawer=this.GetBaseArcDrawer(context,edge);this._RedrawEdge(edge,arcDrawer);} +Application.prototype._RedrawEdge=function(edge,arcDrawer,commonStyle,selectedStyles) +{this._RedrawEdgeWithStyle(edge,edge.currentStyle,arcDrawer,commonStyle,selectedStyles);} +Application.prototype._RedrawEdgeWithStyle=function(edge,style,arcDrawer,commonStyle,selectedStyles) +{arcDrawer.Draw(edge,style.GetStyle({},edge));} +Application.prototype.RedrawEdgeProgress=function(context,edge,progress) +{var progressDraw=new ProgressArcDrawer(context,this.GetBaseArcDrawer(context,edge),progress);var arcDrawer=new BaseEdgeDrawer(context,{drawObject:progressDraw});this._RedrawEdge(edge,arcDrawer,this.edgeCommonStyle,this.edgeSelectedStyles);} +Application.prototype.UpdateEdgesCurrentStyle=function(ForceCommonStyle,ForceSelectedStyle) +{for(i=0;i0) +{selectedGroup=(selectedGroup-1)%selectedStyle.length;selected=true;} +var currentStyle=null;if(this.graph.vertices[i].hasOwnStyleFor((selected?1:0)+selectedGroup)&&!force) +currentStyle=this.graph.vertices[i].getStyleFor((selected?1:0)+selectedGroup);else +currentStyle=selected?selectedStyle[selectedGroup]:commonStyle;this.graph.vertices[i].currentStyle=currentStyle;}} +Application.prototype.RedrawSelectionRect=function(context) +{context.lineWidth=1.0/this.canvasScale;context.strokeStyle=this.edgeSelectedStyles[0].strokeStyle;context.setLineDash([6,3]);context.beginPath();context.rect(this.selectionRect.left(),this.selectionRect.top(),this.selectionRect.size().x,this.selectionRect.size().y);context.closePath();context.stroke();context.setLineDash([]);} +Application.prototype.updateMessage=function() +{this.document.getElementById('message').innerHTML=this.handler.GetMessage();this.handler.InitControls();} +Application.prototype.CanvasOnMouseMove=function(e) +{var pos=this.getMousePos(this.canvas,e);this.handler.MouseMove(pos);if(this.handler.IsNeedRedraw()) +{this.handler.RestRedraw();this.redrawGraph();} +this.updateMessage();} +Application.prototype.CanvasOnMouseDown=function(e) +{if(e.which!==1)return;var pos=this.getMousePos(this.canvas,e);this.handler.MouseDown(pos);if(this.handler.IsNeedRedraw()) +{this.handler.RestRedraw();this.redrawGraph();} +this.updateMessage();} +Application.prototype.CanvasOnMouseUp=function(e) +{if(e.which!==1)return;var pos=this.getMousePos(this.canvas,e);this.handler.MouseUp(pos);if(this.handler.IsNeedRedraw()) +{this.handler.RestRedraw();this.redrawGraph();} +this.updateMessage();} +Application.prototype.multCanvasScale=function(factor,zoom_to=null) +{if(zoom_to) +{var pos1=this.getMousePos(this.canvas,zoom_to);this.canvasScale*=factor;var pos2=this.getMousePos(this.canvas,zoom_to);this.canvasPosition=this.canvasPosition.add(new Point(pos2.x-pos1.x,pos2.y-pos1.y));} +else +{var oldRealWidth=this.GetRealWidth();var oldRealHeight=this.GetRealHeight();this.canvasScale*=factor;this.canvasPosition=this.canvasPosition.add(new Point((this.GetRealWidth()-oldRealWidth)/2.0,(this.GetRealHeight()-oldRealHeight)/2.0));} +this.redrawGraph();} +Application.prototype.setCanvasScale=function(factor) +{var oldRealWidth=this.GetRealWidth();var oldRealHeight=this.GetRealHeight();this.canvasScale=factor;this.canvasPosition=this.canvasPosition.add(new Point((this.GetRealWidth()-oldRealWidth)/2.0,(this.GetRealHeight()-oldRealHeight)/2.0));this.redrawGraph();} +Application.prototype.onCanvasMove=function(point) +{this.canvasPosition=this.canvasPosition.add(point.multiply(1/this.canvasScale));this.redrawGraph();} +Application.prototype.AddNewVertex=function(vertex) +{return this.graph.AddNewVertex(vertex);} +Application.prototype.AddNewEdge=function(edge,replaceIfExists) +{return this.graph.AddNewEdge(edge,replaceIfExists);} +Application.prototype.CreateNewGraph=function(x,y) +{var app=this;this.currentEnumVerticesType.GetVertexTextAsync(function(enumType) +{app.graph.AddNewVertex(new BaseVertex(x,y,enumType));app.redrawGraph();});} +Application.prototype.CreateNewGraphEx=function(x,y,vertexEnume) +{return this.graph.AddNewVertex(new BaseVertex(x,y,vertexEnume));} +Application.prototype.CreateNewArc=function(graph1,graph2,isDirect,weight,replaceIfExist,upText) +{var edge=this.AddNewEdge(new BaseEdge(graph1,graph2,isDirect,weight,upText),replaceIfExist);this.graph.FixEdgeCurve(edge);var edgeObject=this.graph.edges[edge];if(edgeObject.useWeight) +this.UpdateEdgePresets(edgeObject.weight);return edge;} +Application.prototype.DeleteEdge=function(edgeObject) +{var vertex1=edgeObject.vertex1;var vertex2=edgeObject.vertex2;var hasPair=this.graph.hasPair(edgeObject);this.graph.DeleteEdge(edgeObject);if(hasPair) +{var pairEdges=this.FindAllEdges(vertex2.id,vertex1.id);if(pairEdges.length==1&&pairEdges[0].model.default) +pairEdges[0].model.type=EdgeModels.line;}} +Application.prototype.DeleteVertex=function(graphObject) +{this.graph.DeleteVertex(graphObject);} +Application.prototype.DeleteObject=function(object) +{if(object instanceof BaseVertex) +{this.DeleteVertex(object);} +else if(object instanceof BaseEdge) +{this.DeleteEdge(object);}} +Application.prototype.IsCorrectObject=function(object) +{return(object instanceof BaseVertex)||(object instanceof BaseEdge);} +Application.prototype.FindVertex=function(id) +{return this.graph.FindVertex(id);} +Application.prototype.FindEdge=function(id1,id2) +{return this.graph.FindEdge(id1,id2);} +Application.prototype.FindEdgeAny=function(id1,id2) +{return this.graph.FindEdgeAny(id1,id2);} +Application.prototype.FindAllEdges=function(id1,id2) +{return this.graph.FindAllEdges(id1,id2);} +Application.prototype.SetHandlerMode=function(mode) +{var manipulationHandlers=["default","addGraph","addArc","delete","findPath","connectedComponent","eulerianLoop"];if(this.handler&&(g_AlgorithmIds.indexOf(mode)>=0||manipulationHandlers.indexOf(mode)>=0)) +{this.handler.RestoreAll();} +if(mode=="default") +{this.handler=new DefaultHandler(this);} +else if(mode=="addGraph") +{this.handler=new AddGraphHandler(this);} +else if(mode=="addArc") +{this.handler=new ConnectionGraphHandler(this);} +else if(mode=="delete") +{this.handler=new DeleteGraphHandler(this);} +else if(mode=="deleteAll") +{var removeAll=new DeleteAllHandler(this);removeAll.clear();} +else if(mode=="findPath") +{this.handler=new FindPathGraphHandler(this);} +else if(mode=="showAdjacencyMatrix") +{var showAdjacencyMatrix=new ShowAdjacencyMatrix(this);showAdjacencyMatrix.show();} +else if(mode=="showIncidenceMatrix") +{var showIncidenceMatrix=new ShowIncidenceMatrix(this);showIncidenceMatrix.show();} +else if(mode=="showDistanceMatrix") +{var showDistanceMatrix=new ShowDistanceMatrix(this);showDistanceMatrix.show();} +else if(mode=="connectedComponent") +{this.handler=new ConnectedComponentGraphHandler(this);} +else if(mode=="saveDialog") +{var savedDialogGraphHandler=new SavedDialogGraphHandler(this);savedDialogGraphHandler.show();} +else if(mode=="saveDialogImage") +{var savedDialogGraphImageHandler=new SavedDialogGraphImageHandler(this);savedDialogGraphImageHandler.showWorkspace();} +else if(mode=="saveDialogFullImage") +{var savedDialogGraphImageHandler=new SavedDialogGraphImageHandler(this);savedDialogGraphImageHandler.showFullgraph();} +else if(mode=="savePrintGraphImage") +{var savedDialogGraphImageHandler=new SavedDialogGraphImageHandler(this);savedDialogGraphImageHandler.showPrint();} +else if(mode=="saveSvgGraphImage") +{var savedDialogGraphImageHandler=new SavedDialogGraphImageHandler(this);savedDialogGraphImageHandler.showSvg();} +else if(mode=="eulerianLoop") +{this.handler=new EulerianLoopGraphHandler(this);} +else if(mode=="GroupRename") +{var groupRenameVertices=new GroupRenameVertices(this);groupRenameVertices.show();} +else if(mode=="setupVertexStyle") +{var setupVertexStyle=new SetupVertexStyle(this);setupVertexStyle.show(0);} +else if(mode=="setupVertexStyleSelected") +{var setupVertexStyle=new SetupVertexStyle(this);setupVertexStyle.show(1);} +else if(mode=="setupEdgeStyle") +{var setupEdgeStyle=new SetupEdgeStyle(this);setupEdgeStyle.show(0);} +else if(mode=="setupEdgeStyleSelected") +{var setupEdgeStyle=new SetupEdgeStyle(this);setupEdgeStyle.show(1);} +else if(mode=="setupBackgroundStyle") +{var setupBackgroundStyle=new SetupBackgroundStyle(this);setupBackgroundStyle.show();} +else if(mode=="graphUndo") +{if(!this.IsUndoStackEmpty()) +this.Undo();} +else if(g_AlgorithmIds.indexOf(mode)>=0) +{this.handler=new AlgorithmGraphHandler(this,g_Algorithms[g_AlgorithmIds.indexOf(mode)](this.graph,this));} +console.log(mode);this.setRenderPath([]);this.updateMessage();this.redrawGraph();} +Application.prototype.getParameterByName=function(name) +{name=name.replace(/[\[]/,"\\[").replace(/[\]]/,"\\]");var regex=new RegExp("[\\?&]"+name+"=([^&#]*)"),results=regex.exec(location.search);return results===null?"":decodeURIComponent(results[1].replace(/\+/g," "));} +Application.prototype.onPostLoadEvent=function() +{this.SetEnumVerticesType(document.cookie.replace(/(?:(?:^|.*;\s*)enumType\s*\=\s*([^;]*).*$)|^.*$/,"$1"));var wasLoad=false;var matrix=document.getElementById("inputMatrix").innerHTML;var separator=document.getElementById("separator").innerHTML=="space"?" ":",";console.log(matrix);console.log("separator: \""+separator+"\"");matrix=(matrix.length<=0)?this.getParameterByName("matrix"):matrix;if(matrix.length>0) +{if(!this.SetAdjacencyMatrixSmart(matrix,separator)) +{this.userAction("AdjacencyMatrix.Failed");this.ShowAdjacencyMatrixErrorDialog(matrix);} +else +{this.userAction("AdjacencyMatrix.Success");} +this.updateMessage();this.redrawGraph();wasLoad=true;} +var matrix=document.getElementById("inputIncidenceMatrix").innerHTML;matrix=(matrix.length<=0)?this.getParameterByName("incidenceMatrix"):matrix;if(matrix.length>0) +{if(!this.SetIncidenceMatrixSmart(matrix)) +{this.userAction("IncidenceMatrix.Failed");this.ShowIncidenceMatrixErrorDialog(matrix);} +else +{this.userAction("IncidenceMatrix.Success");} +this.updateMessage();this.redrawGraph();wasLoad=true;} +var pairs=document.getElementById("inputPair").innerHTML;if(pairs.length>0) +{pairs=pairs.replaceAll('>','>');pairs=pairs.replaceAll('<','<');if(!this.SetPairSmart(pairs)) +{this.userAction("Pair.Failed");this.ShowPairErrorDialog(pairs);} +else +{this.userAction("Pair.Success");} +this.updateMessage();this.redrawGraph();wasLoad=true;} +if(!wasLoad) +{var graphName=this.getParameterByName("graph");if(graphName.length<=0) +{graphName=document.cookie.replace(/(?:(?:^|.*;\s*)graphName\s*\=\s*([^;]*).*$)|^.*$/,"$1");} +if(graphName.length>0) +{this.userAction("LoadGraphFromDisk");this.LoadGraphFromDisk(graphName);}} +if(this.IsUndoStackEmpty()) +document.getElementById('GraphUndo').style.display='none';this.updateMessage();this.redrawGraph();} +Application.prototype.onLoad=function() +{this.canvas=this.document.getElementById('canvas');this.SetDefaultHandler() +this.updateMessage();this.redrawGraph();} +Application.prototype.NeedRedraw=function() +{this.updateMessage();this.redrawGraph();} +Application.prototype.SetStatus=function(name,value) +{this.status[name]=value;} +Application.prototype.GetStatus=function() +{return this.status[name];} +Application.prototype.GetAdjacencyMatrix=function() +{return this.graph.GetAdjacencyMatrixStr();} +Application.prototype.TestAdjacencyMatrix=function(matrix,rowsObj,colsObj,separator) +{if(separator===undefined) +{separator=",";} +return this.graph.TestAdjacencyMatrix(matrix,rowsObj,colsObj,separator);} +Application.prototype.SetAdjacencyMatrix=function(matrix,separator) +{if(separator===undefined) +{separator=",";} +var res=true;var r={};var c={};if(!this.TestAdjacencyMatrix(matrix,r,c,separator)) +{$.get("/"+SiteDir+"cgi-bin/addFailedMatrix.php?text=adjacency&matrix="+encodeURIComponent(matrix),function(data){;});res=false;} +this.graph.SetAdjacencyMatrix(matrix,new Point(this.GetRealWidth(),this.GetRealHeight()),this.currentEnumVerticesType,separator);this.AutoAdjustViewport();this.redrawGraph();return res;} +Application.prototype.SetPair=function(pair) +{var res=true;var r={};var c={};if(!this.TestPair(pair)) +{$.get("/"+SiteDir+"cgi-bin/addFailedMatrix.php?text=pair&matrix="+encodeURIComponent(pair),function(data){;});res=false;} +this.graph.SetPair(pair,new Point(this.GetRealWidth(),this.GetRealHeight()),this.currentEnumVerticesType);this.AutoAdjustViewport();this.redrawGraph();return res;} +Application.prototype.GetIncidenceMatrix=function() +{return this.graph.GetIncidenceMatrix();} +Application.prototype.TestIncidenceMatrix=function(matrix,rowsObj,colsObj) +{return this.graph.TestIncidenceMatrix(matrix,rowsObj,colsObj);} +Application.prototype.TestPair=function(pair) +{return this.graph.TestPair(pair);} +Application.prototype.SetIncidenceMatrix=function(matrix) +{var res=true;var r={};var c={};if(!this.TestIncidenceMatrix(matrix,r,c)) +{$.get("/"+SiteDir+"cgi-bin/addFailedMatrix.php?text=incidence&matrix="+encodeURIComponent(matrix),function(data){;});res=false;} +this.graph.SetIncidenceMatrix(matrix,new Point(this.GetRealWidth(),this.GetRealHeight()),this.currentEnumVerticesType);this.AutoAdjustViewport();this.redrawGraph();return res;} +Application.prototype.Test=function() +{this.graph.VerticesReposition(new Point(this.GetRealWidth(),this.GetRealHeight()),this.graph.vertices);this.redrawGraph();} +Application.prototype.SetAdjacencyMatrixSmart=function(matrix,separator) +{if(separator===undefined) +{separator=",";} +var res=false;if(this.TestAdjacencyMatrix(matrix,{},{},separator)) +{res=this.SetAdjacencyMatrix(matrix,separator);} +else if(this.TestIncidenceMatrix(matrix,{},{})) +{res=this.SetIncidenceMatrix(matrix);} +else +{res=this.SetAdjacencyMatrix(matrix);} +return res;} +Application.prototype.SetIncidenceMatrixSmart=function(matrix) +{var res=false;if(this.TestIncidenceMatrix(matrix,{},{})) +{res=this.SetIncidenceMatrix(matrix);} +else if(this.TestAdjacencyMatrix(matrix,{},{})) +{res=this.SetAdjacencyMatrix(matrix);} +else +{res=this.SetIncidenceMatrix(matrix);} +return res;} +Application.prototype.SetPairSmart=function(pair) +{var res=false;if(this.TestPair(pair)) +{res=this.SetPair(pair);} +else +{res=false;} +return res;} +Application.prototype.SaveGraphOnDisk=function() +{var graphAsString=this.graph.SaveToXML(this.SaveUserSettings());var styleSave=this.SaveUserSettings();if(this.savedGraphName.length<=0) +{this.savedGraphName=this.GetNewGraphName();} +var app=this;$.ajax({type:"POST",url:"/"+SiteDir+"cgi-bin/saveGraph.php?name="+this.savedGraphName,data:graphAsString,dataType:"text"}).done(function(msg) +{document.cookie="graphName="+app.savedGraphName;});} +Application.prototype.SaveGraphImageOnDisk=function(showDialogCallback) +{var imageName=this.GetNewName();this.stopRenderTimer();this.redrawGraph();var bbox=this.graph.getGraphBBox();var rectParams="";if(this.IsGraphFitOnViewport()) +{var canvasWidth=this.GetRealWidth();var canvasHeight=this.GetRealHeight();var canvasPositionInverse=this.canvasPosition.inverse();var pos=bbox.minPoint.subtract(canvasPositionInverse);rectParams="&x="+Math.round(pos.x*this.canvasScale)+"&y="+Math.round(pos.y*this.canvasScale) ++"&width="+Math.round(bbox.size().x*this.canvasScale)+"&height="+Math.round(bbox.size().y*this.canvasScale);} +var imageBase64Data=this.canvas.toDataURL();$.ajax({type:"POST",url:"/"+SiteDir+"cgi-bin/saveImage.php?name="+imageName+rectParams,data:{base64data:imageBase64Data},dataType:"text",success:function(data){showDialogCallback();}});return imageName;} +Application.prototype.SaveFullGraphImageOnDisk=function(showDialogCallback,forPrint) +{var imageName=this.GetNewName();this.stopRenderTimer();var canvas=forPrint?this._PrintRedrawGraph():this._OffscreenRedrawGraph();var bbox=this.graph.getGraphBBox();var rectParams="";rectParams="&x=0"+"&y=0"+"&width="+bbox.size().x+"&height="+bbox.size().y;var imageBase64Data=canvas.toDataURL();$.ajax({type:"POST",url:"/"+SiteDir+"cgi-bin/saveImage.php?name="+imageName+rectParams,data:{base64data:imageBase64Data},dataType:"text",success:function(data){showDialogCallback();}});return imageName;} +Application.prototype.SaveSVGGraphOnDisk=function(showDialogCallback) +{var imageName=this.GetNewName();this.stopRenderTimer();var svgText=this._printToSVG();var bbox=this.graph.getGraphBBox();var imageBase64Data=canvas.toDataURL();$.ajax({type:"POST",url:"/"+SiteDir+"cgi-bin/saveSvg.php?name="+imageName,data:{svgdata:svgText},dataType:"text",success:function(data){showDialogCallback();}});return imageName;} +Application.prototype.LoadGraphFromString=function(str) +{var graph=new Graph();var userSettings={};graph.LoadFromXML(str,userSettings);if(userSettings.hasOwnProperty("data")&&userSettings["data"].length>0) +this.LoadUserSettings(userSettings["data"]);this.SetDefaultTransformations();this.graph=graph;if(this.graph.isNeedReposition()) +{this.graph.VerticesReposition(new Point(this.GetRealWidth(),this.GetRealHeight()),this.graph.vertices);} +this.AutoAdjustViewport();this.updateMessage();this.redrawGraph();} +Application.prototype.LoadGraphFromDisk=function(graphName) +{var app=this;$.ajax({type:"GET",url:"/"+SiteDir+"cgi-bin/loadGraph.php?name="+graphName}).done(function(msg) +{app.LoadGraphFromString(msg);});} +Application.prototype.GetNewGraphName=function() +{var name=this.GetNewName();if(this.isVertexCommonStyleCustom||this.isVertexSelectedVertexStylesCustom||this.isBackgroundCommonStyleCustom||this.isEdgeCommonStyleCustom||this.isEdgeSelectedStylesCustom) +{name=name+"ZZcst";} +return name;} +Application.prototype.GetNewName=function() +{var name="";var possible="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";for(var i=0;i','>');pair=pair.replaceAll('<','<');dialogButtons[g_readMatrixHelp]=function(){window.location.assign(g_language=="ru"?"./wiki/Справка/СписокРебер":"./wiki/Help/EdgeList");};dialogButtons[g_fix]=function(){window.location.assign("./create_graph_by_edge_list?pair="+pair);};dialogButtons[g_close]=function(){$(this).dialog("close");};$("#pairErrorInc").dialog({resizable:false,title:g_pairWrongFormat,width:400,modal:true,dialogClass:'EdgeDialog',buttons:dialogButtons,});} +Application.prototype.SetFindPathReport=function(value) +{this.findPathReport=value;} +Application.prototype.GetFindPathReport=function() +{return this.findPathReport;} +Application.prototype.GetRealWidth=function() +{return this.canvas.width/this.canvasScale;} +Application.prototype.GetRealHeight=function() +{return this.canvas.height/this.canvasScale;} +Application.prototype.SetDefaultTransformations=function() +{this.canvasScale=1.0;this.canvasPosition=new Point(0,0);} +Application.prototype.AutoAdjustViewport=function() +{graphBBox=this.graph.getGraphBBox();bboxCenter=graphBBox.center();bboxSize=graphBBox.size();if(bboxSize.length()>0) +{if(bboxSize.x>this.GetRealWidth()||bboxSize.y>this.GetRealHeight()) +{this.canvasScale=Math.min(this.GetRealWidth()/bboxSize.x,this.GetRealHeight()/bboxSize.y);} +if(graphBBox.minPoint.x<0.0||graphBBox.minPoint.y<0.0||graphBBox.maxPoint.x>this.GetRealWidth()||graphBBox.maxPoint.y>this.GetRealHeight()) +{this.canvasPosition=graphBBox.minPoint.inverse();}}} +Application.prototype.OnAutoAdjustViewport=function() +{this.SetDefaultTransformations();this.AutoAdjustViewport();this.redrawGraph();} +Application.prototype.getAlgorithmNames=function() +{var res=[];for(var i=0;i=Math.floor(graphBBox.maxPoint.x)&&Math.floor(canvasPositionInverse.y+canvasHeight)>=Math.floor(graphBBox.maxPoint.y));} +Application.prototype.PushToStack=function(actionName) +{var object={};object.actionName=actionName;object.graphSave=this.graph.SaveToXML(this.SaveUserSettings());this.undoStack.push(object);while(this.undoStack.length>this.maxUndoStackSize) +{this.undoStack.shift();} +document.getElementById('GraphUndo').style.display='inline-block';} +Application.prototype.Undo=function() +{if(this.IsUndoStackEmpty()) +return;var state=this.undoStack.pop();this.graph=new Graph();var userSettings={};this.graph.LoadFromXML(state.graphSave,userSettings);if(userSettings.hasOwnProperty("data")&&userSettings["data"].length>0) +this.LoadUserSettings(userSettings["data"]);this.redrawGraph();if(this.IsUndoStackEmpty()) +document.getElementById('GraphUndo').style.display='none';} +Application.prototype.ClearUndoStack=function() +{this.undoStack=[];} +Application.prototype.IsUndoStackEmpty=function() +{return(this.undoStack.length<=0);} +Application.prototype.SaveUserSettings=function() +{var res="{";var needEnd=false;var checkValue=[];checkValue.push({field:"edgeCommonStyle",value:this.edgeCommonStyle,check:this.isEdgeCommonStyleCustom});checkValue.push({field:"edgeSelectedStyles",value:this.edgeSelectedStyles,check:this.isEdgeSelectedStylesCustom});checkValue.push({field:"vertexCommonStyle",value:this.vertexCommonStyle,check:this.isVertexCommonStyleCustom});checkValue.push({field:"vertexSelectedVertexStyles",value:this.vertexSelectedVertexStyles,check:this.isVertexSelectedVertexStylesCustom});checkValue.push({field:"backgroundCommonStyle",value:this.backgroundCommonStyle,check:this.isBackgroundCommonStyleCustom});checkValue.push({field:"defaultVertexSize",value:this.defaultVertexSize,check:this.defaultVertexSize!=null});checkValue.push({field:"defaultEdgeWidth",value:this.defaultEdgeWidth,check:this.defaultEdgeWidth!=null});checkValue.forEach(function(entry){if(!entry.check) +return;if(needEnd) +res=res+",";let valueJson="";if(typeof entry.value.saveToJson==="function"){valueJson=entry.value.saveToJson();}else{valueJson=JSON.stringify(entry.value);} +res=res+"\""+entry.field+"\""+":"+valueJson;needEnd=true;});res=res+"}";return this.EncodeToHTML(res);} +Application.prototype.LoadUserSettings=function(json) +{var checkValue=[];checkValue.push({field:"edgeCommonStyle",value:this.edgeCommonStyle,check:"isEdgeCommonStyleCustom",deep:false});checkValue.push({field:"edgeSelectedStyles",value:this.edgeSelectedStyles,check:"isEdgeSelectedStylesCustom",deep:true});checkValue.push({field:"vertexCommonStyle",value:this.vertexCommonStyle,check:"isVertexCommonStyleCustom",deep:false});checkValue.push({field:"vertexSelectedVertexStyles",value:this.vertexSelectedVertexStyles,check:"isVertexSelectedVertexStylesCustom",deep:true});checkValue.push({field:"defaultVertexSize",value:"defaultVertexSize",check:null,deep:false});checkValue.push({field:"defaultEdgeWidth",value:"defaultEdgeWidth",check:null,deep:false});checkValue.push({field:"backgroundCommonStyle",value:this.backgroundCommonStyle,check:this.isBackgroundCommonStyleCustom,deep:false});var decoderStr=this.DecodeFromHTML(json);var parsedSave=JSON.parse(decoderStr);var app=this;checkValue.forEach(function(entry){if(parsedSave.hasOwnProperty(entry.field)) +{if(typeof parsedSave[entry.field]==='number') +{app[entry.value]=parseInt(parsedSave[entry.field]);} +else +{if(typeof entry.value.loadFromJson==="function"){entry.value.loadFromJson(parsedSave[entry.field],function(){setTimeout(function(){app.redrawGraph()},1000);});return;} +if(!entry.deep) +entry.value.Clear();for(var k in parsedSave[entry.field]) +{if(!entry.deep) +{if(entry.value.ShouldLoad(k)) +{entry.value[k]=parsedSave[entry.field][k];}} +else +{if(k%1!=0) +continue;entry.value[k].Clear();for(var deepK in parsedSave[entry.field][k]) +{if(k=this.maxEdgePresets) +break;}} +Application.prototype.GetEdgePresets=function() +{return this.edgePresets;} +Application.prototype.SetSelectionRect=function(rect) +{this.selectionRect=rect;} +Application.prototype.GetSelectionRect=function(rect) +{return this.selectionRect;} +Application.prototype.GetStyle=function(type,styleName,object,index) +{var correctIndex=index;if(correctIndex==undefined) +correctIndex=0;if(type=="vertex") +{if(styleName=="common") +{return object!==undefined?object.getStyleFor(0):this.vertexCommonStyle;} +else if(styleName=="selected") +{return object!==undefined&&object.hasOwnStyleFor(correctIndex+1)?object.getStyleFor(correctIndex+1):this.vertexSelectedVertexStyles[correctIndex];} +else if(styleName=="printed") +{return this.vertexPrintCommonStyle;} +else if(styleName=="printedSelected") +{return this.vertexPrintSelectedVertexStyles[correctIndex];} +return null;} +else if(type=="edge") +{if(styleName=="common") +{return object!==undefined?object.getStyleFor(0):this.edgeCommonStyle;} +else if(styleName=="selected") +{return object!==undefined&&object.hasOwnStyleFor(correctIndex+1)?object.getStyleFor(correctIndex+1):this.edgeSelectedStyles[correctIndex];} +else if(styleName=="printed") +{return this.edgePrintCommonStyle;} +else if(styleName=="printedSelected") +{return this.edgePrintSelectedStyles[correctIndex];} +return null;} +return null;} +Application.prototype._RedrawGraph=function(context,backgroundPosition,backgroundStyle,bDrawSelectedRect,forceVertexCommon,forceVertexSelected,forceEdgeCommon,forceEdgeSelected) +{var backgroundDrawer=new BaseBackgroundDrawer(context);backgroundDrawer.Draw(backgroundStyle,Math.max(this.canvas.width,this.GetRealWidth()),Math.max(this.canvas.height,this.GetRealHeight()),backgroundPosition,this.canvasScale);this.UpdateEdgesCurrentStyle(forceEdgeCommon,forceEdgeSelected);this.UpdateNodesCurrentStyle(forceVertexCommon,forceVertexSelected);this.RedrawEdges(context);this.RedrawNodes(context);if(bDrawSelectedRect&&this.selectionRect!=null) +this.RedrawSelectionRect(context);} +Application.prototype.GetSelectedVertices=function() +{var res=[];for(i=0;i0) +{res.push(this.graph.vertices[i]);}} +return res;} +Application.prototype.GetSelectedEdges=function() +{var res=[];for(i=0;i0) +{res.push(this.graph.edges[i]);}} +return res;} +Application.prototype.SetDefaultVertexSize=function(diameter) +{var oldDefaultDiameter=this.GetDefaultVertexSize();this.defaultVertexSize=diameter;for(i=0;i0) +{application.multCanvasScale(1.3,e);} +else +{application.multCanvasScale(1.0/1.3,e);}} +function getCharCode(event){if(event.which==null){return event.keyCode;} +if(event.which!=0&&event.charCode!=0){return event.which;} +return null;} +function getChar(event){return String.fromCharCode(getCharCode(event));} +function selectHandler(buttonName,handlerName) +{userAction(buttonName+"_shortcut");restButtons(buttonName);application.SetHandlerMode(handlerName);} +document.onkeypress=function(e) +{if(event.defaultPrevented||($('#addVertex').hasClass('ui-dialog-content')&&$('#addVertex').dialog('isOpen'))||($('#adjacencyMatrix').hasClass('ui-dialog-content')&&$('#adjacencyMatrix').dialog('isOpen'))||($('#addEdge').hasClass('ui-dialog-content')&&$('#addEdge').dialog('isOpen'))||($('#incidenceMatrix').hasClass('ui-dialog-content')&&$('#incidenceMatrix').dialog('isOpen'))||($('#saveDialog').hasClass('ui-dialog-content')&&$('#saveDialog').dialog('isOpen'))||($('#saveImageDialog').hasClass('ui-dialog-content')&&$('#saveImageDialog').dialog('isOpen'))||($('#GroupRenameDialog').hasClass('ui-dialog-content')&&$('#GroupRenameDialog').dialog('isOpen'))||$('#developerTools').css("display")!="none"||($('#NeedAlgorithm').hasClass('ui-dialog-content')&&$('#NeedAlgorithm').dialog('isOpen'))) +{console.log("prevent");return;} +var key=getChar(event);var code=getCharCode(event);console.log(key+" code="+code);var evtobj=window.event?event:e;var isCtrl=evtobj?evtobj.ctrlKey:false;var moveValue=10;if(code==61||code==43) +{application.multCanvasScale(1.5);} +else if(code==45) +{application.multCanvasScale(1/1.5);} +else if(key=='w'||key=='ц') +{application.onCanvasMove(new Point(0,moveValue));} +else if(key=='s'||key=='ы') +{application.onCanvasMove(new Point(0,-moveValue));} +else if(key=='a'||key=='ф') +{application.onCanvasMove(new Point(moveValue,0));} +else if(key=='d'||key=='в') +{application.onCanvasMove(new Point(-moveValue,0));} +else if(key=='v'||key=='м') +{selectHandler('AddGraph','addGraph');} +else if(key=='e'||key=='у') +{selectHandler('ConnectGraphs','addArc');} +else if(key=='r'||key=='к') +{selectHandler('DeleteObject','delete');} +else if(key=='m'||key=='ь') +{selectHandler('Default','default');} +else if(code==26&&isCtrl) +{userAction("Key_GraphUndo");application.SetHandlerMode("graphUndo");}} +$(document).keydown(function(event){if(event.which=="17"||event.which=="91") +g_ctrlPressed=true;});$(document).keyup(function(){g_ctrlPressed=false;});document.getElementById('ShowAdjacencyMatrix').onclick=function() +{userAction(this.id);application.SetHandlerMode("showAdjacencyMatrix");} +document.getElementById('ShowIncidenceMatrix').onclick=function() +{userAction(this.id);application.SetHandlerMode("showIncidenceMatrix");} +document.getElementById('ShowDistanceMatrix').onclick=function() +{userAction(this.id);application.SetHandlerMode("showDistanceMatrix");} +document.getElementById('GroupRename').onclick=function() +{userAction(this.id);application.SetHandlerMode("GroupRename");} +document.getElementById('groupRenameButton').onclick=function() +{userAction(this.id);application.SetHandlerMode("GroupRename");} +document.getElementById('Default').onclick=function() +{userAction(this.id);restButtons('Default');application.SetHandlerMode("default");document.getElementById('Default').className="btn btn-primary btn-sm";} +document.getElementById('AddGraph').onclick=function() +{userAction(this.id);restButtons('AddGraph');application.SetHandlerMode(document.getElementById('AddGraph').className!=""?"addGraph":"default");} +document.getElementById('ConnectGraphs').onclick=function() +{userAction(this.id);restButtons('ConnectGraphs');application.SetHandlerMode(document.getElementById('ConnectGraphs').className!=""?"addArc":"default");} +document.getElementById('DeleteObject').onclick=function() +{userAction(this.id);restButtons('DeleteObject');application.SetHandlerMode(document.getElementById('DeleteObject').className!=""?"delete":"default");} +document.getElementById('DeleteAll').onclick=function() +{userAction(this.id);application.SetHandlerMode("deleteAll");} +document.getElementById('SaveGraph').onclick=function() +{userAction(this.id);application.SetHandlerMode("saveDialog");} +document.getElementById('NewGraph').onclick=function() +{userAction(this.id);application.SetHandlerMode("deleteAll");application.SetDefaultTransformations();} +document.getElementById('SaveGraphImage').onclick=function() +{userAction(this.id);application.SetHandlerMode("saveDialogImage");} +document.getElementById('SaveFullGraphImage').onclick=function() +{userAction(this.id);application.SetHandlerMode("saveDialogFullImage");} +document.getElementById('SavePrintGraphImage').onclick=function() +{userAction(this.id);application.SetHandlerMode("savePrintGraphImage");} +document.getElementById('SaveSvgGraphImage').onclick=function() +{userAction(this.id);application.SetHandlerMode("saveSvgGraphImage");} +document.getElementById('Zoom100').onclick=function() +{userAction(this.id);application.setCanvasScale(1.0);} +document.getElementById('Zoom50').onclick=function() +{userAction(this.id);application.setCanvasScale(50/100);} +document.getElementById('Zoom25').onclick=function() +{userAction(this.id);application.setCanvasScale(25/100);} +document.getElementById('ZoomFit').onclick=function() +{userAction(this.id);application.OnAutoAdjustViewport();} +document.getElementById('ZoomIn').onclick=function() +{userAction(this.id);application.multCanvasScale(1.5);} +document.getElementById('ZoomOut').onclick=function() +{userAction(this.id);application.multCanvasScale(1.0/1.5);} +document.getElementById('MoveWorspace').onclick=function() +{userAction(this.id);restButtons('Default');application.SetHandlerMode("default");document.getElementById('Default').className="btn btn-primary btn-sm";} +document.getElementById('SetupVertexStyle').onclick=function() +{userAction(this.id);application.SetHandlerMode("setupVertexStyle");} +document.getElementById('SetupVertexStyleSelected').onclick=function() +{userAction(this.id);application.SetHandlerMode("setupVertexStyleSelected");} +document.getElementById('SetupEdgeStyle').onclick=function() +{userAction(this.id);application.SetHandlerMode("setupEdgeStyle");} +document.getElementById('SetupEdgeStyleSelected').onclick=function() +{userAction(this.id);application.SetHandlerMode("setupEdgeStyleSelected");} +document.getElementById('SetupBackgroundStyle').onclick=function() +{userAction(this.id);application.SetHandlerMode("setupBackgroundStyle");} +document.getElementById('GraphUndo').onclick=function() +{userAction(this.id);application.SetHandlerMode("graphUndo");} +document.getElementById('runUserScript').onclick=function() +{var el=document.getElementById('userScript');var oldScript=document.getElementById("userScriptSource");if(oldScript) +{document.head.removeChild(oldScript);} +var script=document.createElement('script');script.type="text/javascript";script.innerHTML=el.value;script.id="userScriptSource";document.head.appendChild(script);application.SetHandlerMode("user.algorithm");} +document.getElementById('submitUserScript').onclick=function() +{var script=document.getElementById('userScript');var data="message="+script.value+"&";$.ajax({type:"POST",url:"/feedback",data:data});$("#sentAlgorithm").dialog({resizable:false,height:"auto",width:400,modal:true,dialogClass:'EdgeDialog'});} +document.getElementById('devToolsZoom').onclick=function() +{var devTools=document.getElementById('developerTools');if(devTools.hasOwnProperty("isMin")&&!devTools["isMin"]) +{devTools["isMin"]=true;devTools.style.width="30%";} +else +{devTools["isMin"]=false;devTools.style.width="100%";}} +document.getElementById('ExportGraph').onclick=function() +{userAction(this.id);var graphAsString=application.graph.SaveToXML("");var savedGraphName=application.GetNewGraphName();var element=document.createElement('a');element.setAttribute('href','data:text/plain;charset=utf-8,'+encodeURIComponent(graphAsString));element.setAttribute('download',"graph_"+savedGraphName+".graphml");element.style.display='none';document.body.appendChild(element);element.click();document.body.removeChild(element);} +document.getElementById('ImportGraph').onclick=function() +{userAction(this.id);if(ImportGraphFiles){ImportGraphFiles.click();}} +document.getElementById('openAlgorithmList').onclick=function() +{setTimeout(function() +{var button=document.getElementById('openAlgorithmList');var buttonRect=button.getBoundingClientRect();var algorithmList=document.getElementById('algorithmList');var delta=buttonRect.right-algorithmList.offsetWidth;if(delta<0) +{var value=(delta-4)+"px";algorithmList.style.right=value;} +else +{algorithmList.style.right="0";}},1);} +document.getElementById('Fullscreen').onclick=function() +{var idList=["h1Header","h1Text","navigation","footerContent","bottom_adv"];fullscreen=!fullscreen +userAction(fullscreen?"fullscreen_on":"fullscreen_off");for(var i=0;i{Module['onRuntimeInitialized']=onRuntimeInitialized;var process=Module.cwrap('ProcessAlgorithm','string',['string']);function onRuntimeInitialized(){application.setEmscripten(process);}})}});Array.prototype.swap=function(x,y){var b=this[x];this[x]=this[y];this[y]=b;return this;} +moduleLoader.endCacheLoading(); \ No newline at end of file diff --git a/script/Application.js b/script/pages/editor/model/Application.js similarity index 100% rename from script/Application.js rename to script/pages/editor/model/Application.js diff --git a/script/texts.js b/script/pages/editor/model/texts.js similarity index 99% rename from script/texts.js rename to script/pages/editor/model/texts.js index c0e6b1f..36ace26 100644 --- a/script/texts.js +++ b/script/pages/editor/model/texts.js @@ -420,10 +420,4 @@ function loadTexts() g_wrongImageFormatPNGAndJPEG = document.getElementById("wrongImageFormatPNGAndJPEG").innerHTML; g_wrongImageSizeP1 = document.getElementById("wrongImageSizeP1").innerHTML; -} - -function formatString(string, params) { - return string.replace(/{(\d+)}/g, (match, index) => { - return typeof params[index] !== 'undefined' ? params[index] : match; - }); - } \ No newline at end of file +} \ No newline at end of file diff --git a/script/main.js b/script/pages/editor/ui/main.js similarity index 94% rename from script/main.js rename to script/pages/editor/ui/main.js index fab0082..0bff681 100644 --- a/script/main.js +++ b/script/pages/editor/ui/main.js @@ -1,5 +1,4 @@ -var SiteDir = ""; var DisableEmscripten = false; var algorithmsVersion = 2; @@ -33,7 +32,7 @@ var g_ctrlPressed = false; function restButtons (me) { var needSetDefault = false; - for (var i = 0; i < buttonsList.length; i ++) + for (let i = 0; i < buttonsList.length; i ++) { if (buttonsList[i] != me) { @@ -49,7 +48,7 @@ function restButtons (me) } if (needSetDefault) { - document.getElementById(buttonsList[i]).className = "btn btn-primary btn-sm"; + document.getElementById(me).className = "btn btn-primary btn-sm"; } else { @@ -651,31 +650,7 @@ function postLoadPage() } // Get algorithms list and load it. - $.get( "/" + SiteDir + "cgi-bin/getPluginsList.php", - function( data ) - { - var scriptList = JSON.parse(data); - - var loadOneScript = function() - { - if (scriptList.length == 0) - { - createAlgorithmMenu(); - } - else - { - var script = document.createElement('script'); - script.src = "/" + SiteDir + "script/" + scriptList[0] + "?v=" + algorithmsVersion; - scriptList.shift(); - script.onload = loadOneScript; - script.onerror = loadOneScript; - document.head.appendChild(script); - } - } - - loadOneScript(); - - }); + loadAsyncAlgorithms(createAlgorithmMenu); var devTools = document.getElementById('developerTools'); devTools.style.left = 0; @@ -743,16 +718,16 @@ $(document).ready(function () // Try load emscripten implementation var isMobile = navigator.userAgent.match(/(iPad)|(iPhone)|(iPod)|(android)|(webOS)/i); if (!isMobile && !DisableEmscripten) { - const jsScript = document.createElement('script'); - jsScript.src = '/script/Graphoffline.Emscripten.js?v=1'; - document.body.appendChild(jsScript); - jsScript.addEventListener('load', () => { + let fullPathToGraphffoline = "features/graphoffline/Graphoffline.Emscripten.js"; + doIncludeAsync ([ + include (fullPathToGraphffoline), + ], () => { Module['onRuntimeInitialized'] = onRuntimeInitialized; var process = Module.cwrap('ProcessAlgorithm', 'string', ['string']); function onRuntimeInitialized() { application.setEmscripten(process); } - }); + }) } /* $(document).ready(function(){ diff --git a/script/canvas2svg.js b/script/shared/canvas2svg.js similarity index 100% rename from script/canvas2svg.js rename to script/shared/canvas2svg.js diff --git a/script/shared/config.js b/script/shared/config.js new file mode 100644 index 0000000..69e377a --- /dev/null +++ b/script/shared/config.js @@ -0,0 +1,2 @@ +let SiteDir = ""; // Used for load from sub directory +let UseCache = true; \ No newline at end of file diff --git a/script/shared/loader.js b/script/shared/loader.js new file mode 100644 index 0000000..7671a38 --- /dev/null +++ b/script/shared/loader.js @@ -0,0 +1,199 @@ +var include = function(filename, localDir) { + return {filename: filename, localDir: localDir}; +}; + +class ModuleLoader { + constructor(name) { + this.loadingStack = []; + this.startedLoading = new Set(); + this.loaded = new Set(); + this.isRunningSync = false; + this.syncLoaded = []; + this.cacheLoading = false; + this.callsAfterCacheResolve = []; + } + + getFullname = function (filename, localDir) + { + let versionParam = ""; + if (typeof globalVersion !== 'undefined') { + versionParam = "?v=" + globalVersion; + } + let localDirParam = ""; + if (typeof localDir !== 'undefined') { + localDirParam = localDir; + } + return "/" + SiteDir + "script/" + localDirParam + filename + "?v=" + globalVersion; + } + + isAllLoaded = function (includes) + { + self = this; + return includes.every((inc) => { + return self.loaded.has(inc); + }); + } + + load = function (fullFilename, checkQueue, sync) { + let self = this; + + let loadError = function() + { + console.error("Cannot load " + fullFilename); + checkQueue(); + } + let loadSuccess = function() + { + self.loaded.add(fullFilename); + console.log(self.loaded.size + ". " + fullFilename); + checkQueue(); + } + + if (this.loaded.has(fullFilename)) { + this.isRunning = true; + checkQueue(); + return; + } + + var script = document.createElement('script'); + script.src = fullFilename; + script.onload = loadSuccess; + script.onerror = loadError; + document.head.appendChild(script); + this.isRunning = true; + if (sync) { + this.syncLoaded.push(fullFilename); + } + } + + loadFromQueue = function (checkQueue) { + if (this.loadingStack.length == 0) { + return; + } + + let fullFilename = this.loadingStack.pop(); + this.load(fullFilename, checkQueue, true); + this.isRunning = true; + } + + // Load modules one by one in sync mode. + // Call fullLoadedCallback when all modules loaded. + doInclude = function (includes, fullLoadedCallback) { + let self = this; + + if (this.cacheLoading) { + this.callsAfterCacheResolve.push( + function() { + self.doInclude(includes, fullLoadedCallback); + } + ); + return; + } + + let checkQueue = function () { + if (self.loadingStack.length != 0) { + self.loadFromQueue(checkQueue); + return; + } + + self.isRunning = false; + if (typeof fullLoadedCallback === 'undefined' || fullLoadedCallback === null) { + return; + } + + fullLoadedCallback(); + } + + let pushToQueue = function (fullFilename) { + self.loadingStack.push(fullFilename) + self.startedLoading.add(fullFilename); + } + + let reversedIncludes = includes.reverse(); + + reversedIncludes.forEach((inc) => { + let fullFilename = self.getFullname(inc.filename, inc.localDir); + if (self.startedLoading.has(fullFilename)) { + return; + } + pushToQueue(fullFilename) + }); + + if (!self.isRunning) { + checkQueue(); + } + } + + // Load modules async start load all modules. + // Call fullLoadedCallback when all includes loaded. + doIncludeAsync = function (includes, fullLoadedCallback) { + let self = this; + if (this.cacheLoading) { + this.callsAfterCacheResolve.push( + function() { + self.doIncludeAsync(includes, fullLoadedCallback); + } + ); + return; + } + + let includesFull = []; + + let checkLoading = function () { + self.isRunning = false; + if (typeof fullLoadedCallback === 'undefined' || fullLoadedCallback === null) { + return; + } + + if (!self.isAllLoaded(includesFull)) { + return; + } + + fullLoadedCallback(); + } + + let pushToQueue = function (fullFilename) { + self.load(fullFilename, checkLoading, false); + self.startedLoading.add(fullFilename); + } + + let reversedIncludes = includes.reverse(); + + reversedIncludes.forEach((inc) => { + let fullFilename = self.getFullname(inc.filename, inc.localDir); + includesFull.push(fullFilename); + if (self.startedLoading.has(fullFilename)) { + return; + } + pushToQueue(fullFilename) + }); + + checkLoading(); + } + + beginCacheLoading = function (cachedFiles) { + let self = this; + cachedFiles.forEach((file) => { + self.startedLoading.add(file); + self.loaded.add(file); + }); + this.cacheLoading = true; + } + + endCacheLoading = function () { + this.cacheLoading = false; + this.callsAfterCacheResolve.forEach((func) => { + func(); + }); + } +} + +let moduleLoader = new ModuleLoader(); + +function doInclude(includes, callback) { + moduleLoader.doInclude(includes, callback); +} + +function doIncludeAsync(includes, callback) { + moduleLoader.doIncludeAsync(includes, callback); +} diff --git a/script/point.js b/script/shared/point.js old mode 100755 new mode 100644 similarity index 100% rename from script/point.js rename to script/shared/point.js diff --git a/script/utils.js b/script/shared/utils.js similarity index 82% rename from script/utils.js rename to script/shared/utils.js index 903a74b..a91b040 100644 --- a/script/utils.js +++ b/script/shared/utils.js @@ -41,4 +41,10 @@ function FullArrayCopy(arr) }); return res; -} \ No newline at end of file +} + +function formatString(string, params) { + return string.replace(/{(\d+)}/g, (match, index) => { + return typeof params[index] !== 'undefined' ? params[index] : match; + }); + } \ No newline at end of file diff --git a/tpl/create_graph_by_edge_list.php b/tpl/create_graph_by_edge_list.php index 483e3a5..5f93aba 100644 --- a/tpl/create_graph_by_edge_list.php +++ b/tpl/create_graph_by_edge_list.php @@ -1,11 +1,12 @@ - + + + + + + - + + + - - -

    @@ -302,11 +25,11 @@ window.onload = function ()
    +
    -
    diff --git a/tpl/graphs_examples.php b/tpl/graphs_examples.php index 49d2fc1..13419a8 100755 --- a/tpl/graphs_examples.php +++ b/tpl/graphs_examples.php @@ -14,7 +14,7 @@
    + +