Add global undo for graph

This commit is contained in:
Oleg Sh 2021-07-17 21:53:21 +02:00
parent 50f1d0b936
commit 112e2b37ae
6 changed files with 97 additions and 40 deletions

View File

@ -734,6 +734,11 @@ Application.prototype.SetHandlerMode = function(mode)
var setupBackgroundStyle = new SetupBackgroundStyle(this); var setupBackgroundStyle = new SetupBackgroundStyle(this);
setupBackgroundStyle.show(); setupBackgroundStyle.show();
} }
else if (mode == "graphUndo")
{
if (!this.IsUndoStackEmpty())
this.Undo();
}
else if (g_AlgorithmIds.indexOf(mode) >= 0) else if (g_AlgorithmIds.indexOf(mode) >= 0)
{ {
this.handler = new AlgorithmGraphHandler(this, g_Algorithms[g_AlgorithmIds.indexOf(mode)](this.graph, this)); this.handler = new AlgorithmGraphHandler(this, g_Algorithms[g_AlgorithmIds.indexOf(mode)](this.graph, this));
@ -819,6 +824,9 @@ Application.prototype.onPostLoadEvent = function()
} }
} }
if (this.IsUndoStackEmpty())
document.getElementById('GraphUndo').style.display = 'none';
this.updateMessage(); this.updateMessage();
this.redrawGraph(); this.redrawGraph();
} }
@ -1341,14 +1349,18 @@ Application.prototype.PushToStack = function(actionName)
{ {
var object = {}; var object = {};
object.actionName = actionName; object.actionName = actionName;
object.graphSave = this.graph.SaveToXML(""); object.graphSave = this.graph.SaveToXML(this.SaveUserSettings());
this.undoStack.push(object); this.undoStack.push(object);
while (this.undoStack.length > this.maxUndoStackSize) while (this.undoStack.length > this.maxUndoStackSize)
{ {
this.undoStack.shift(); this.undoStack.shift();
} }
//console.log("push undo:" + object.actionName + " size =" + this.undoStack.length);
document.getElementById('GraphUndo').style.display = 'inline-block';
} }
Application.prototype.Undo = function() Application.prototype.Undo = function()
@ -1358,9 +1370,18 @@ Application.prototype.Undo = function()
var state = this.undoStack.pop(); var state = this.undoStack.pop();
this.graph = new Graph(); this.graph = new Graph();
var empty;
this.graph.LoadFromXML(state.graphSave, empty); var userSettings = {};
this.graph.LoadFromXML(state.graphSave, userSettings);
if (userSettings.hasOwnProperty("data") && userSettings["data"].length > 0)
this.LoadUserSettings(userSettings["data"]);
this.redrawGraph(); this.redrawGraph();
//console.log("undo:" + state.actionName + " size =" + this.undoStack.length);
if (this.IsUndoStackEmpty())
document.getElementById('GraphUndo').style.display = 'none';
} }
Application.prototype.ClearUndoStack = function() Application.prototype.ClearUndoStack = function()

View File

@ -50,4 +50,4 @@ BaseBackgroundDrawer.prototype.Draw = function(style, width, height, position, s
context.fillRect(-rect.minPoint.x, -rect.minPoint.y, rect.size().x + 1, rect.size().y + 1); context.fillRect(-rect.minPoint.x, -rect.minPoint.y, rect.size().x + 1, rect.size().y + 1);
context.globalAlpha = 1.0; context.globalAlpha = 1.0;
} }
} }

View File

@ -175,6 +175,8 @@ TextEnumVertexsCustom.prototype.ShowDialog = function(callback, buttonText, titl
var dialogButtons = {}; var dialogButtons = {};
app = this.app; app = this.app;
dialogButtons[buttonText] = function() { dialogButtons[buttonText] = function() {
app.PushToStack("RenameVertex");
callback(new TextEnumTitle(app, $("#VertexTitle").val())); callback(new TextEnumTitle(app, $("#VertexTitle").val()));
$( this ).dialog( "close" ); $( this ).dialog( "close" );
}; };

View File

@ -15,7 +15,7 @@ function BaseHandler(app)
this.app = app; this.app = app;
this.app.setRenderPath([]); this.app.setRenderPath([]);
this.app.ClearUndoStack(); //this.app.ClearUndoStack();
} }
// Need redraw or nor. // Need redraw or nor.
@ -212,6 +212,7 @@ function DefaultHandler(app)
this.groupingSelect = false; this.groupingSelect = false;
this.selectedLogRect = false; this.selectedLogRect = false;
this.selectedLogCtrl = false; this.selectedLogCtrl = false;
this.saveUndo = false;
} }
// inheritance. // inheritance.
@ -225,12 +226,24 @@ DefaultHandler.prototype.MouseMove = function(pos)
{ {
if (this.dragObject) if (this.dragObject)
{ {
if (!this.saveUndo)
{
this.app.PushToStack("Move");
this.saveUndo = true;
}
this.dragObject.position.x = pos.x; this.dragObject.position.x = pos.x;
this.dragObject.position.y = pos.y; this.dragObject.position.y = pos.y;
this.needRedraw = true; this.needRedraw = true;
} }
else if (this.selectedObjects.length > 0 && this.pressed && !this.groupingSelect) 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); var offset = (new Point(pos.x, pos.y)).subtract(this.prevPosition);
for (var i = 0; i < this.selectedObjects.length; i ++) for (var i = 0; i < this.selectedObjects.length; i ++)
{ {
@ -241,7 +254,7 @@ DefaultHandler.prototype.MouseMove = function(pos)
} }
} }
this.prevPosition = pos; this.prevPosition = pos;
this.needRedraw = true; this.needRedraw = true;
} }
else if (this.pressed) else if (this.pressed)
{ {
@ -332,6 +345,7 @@ DefaultHandler.prototype.RenameVertex = function(text)
DefaultHandler.prototype.MouseUp = function(pos) DefaultHandler.prototype.MouseUp = function(pos)
{ {
this.saveUndo = false;
this.message = g_textsSelectAndMove + " <span class=\"hidden-phone\">" + g_selectGroupText + "</span>"; this.message = g_textsSelectAndMove + " <span class=\"hidden-phone\">" + g_selectGroupText + "</span>";
this.dragObject = null; this.dragObject = null;
this.pressed = false; this.pressed = false;
@ -361,7 +375,7 @@ DefaultHandler.prototype.MouseUp = function(pos)
}; };
$('#message').unbind(); $('#message').unbind();
$('#message').on('click', '#renameButton', function(){ $('#message').on('click', '#renameButton', function(){
var customEnum = new TextEnumVertexsCustom(); var customEnum = new TextEnumVertexsCustom(handler.app);
customEnum.ShowDialog(callback, g_rename, g_renameVertex, handler.selectedObject.mainText); customEnum.ShowDialog(callback, g_rename, g_renameVertex, handler.selectedObject.mainText);
}); });
$('#message').on('click', '#changeCommonStyle', function(){ $('#message').on('click', '#changeCommonStyle', function(){
@ -399,6 +413,8 @@ DefaultHandler.prototype.MouseUp = function(pos)
var dialogButtons = {}; var dialogButtons = {};
dialogButtons[g_save] = function() { dialogButtons[g_save] = function() {
handler.app.PushToStack("ChangeCurvelEdge");
handler.selectedObject.SetWeight(document.getElementById('EdgeWeight').value); handler.selectedObject.SetWeight(document.getElementById('EdgeWeight').value);
handler.selectedObject.SetUpText(document.getElementById('EdgeLable').value); handler.selectedObject.SetUpText(document.getElementById('EdgeLable').value);
@ -441,12 +457,16 @@ DefaultHandler.prototype.MouseUp = function(pos)
}); });
$('#message').on('click', '#incCurvel', function(){ $('#message').on('click', '#incCurvel', function(){
handler.app.PushToStack("ChangeCurvelEdge");
handler.selectedObject.model.ChangeCurvedValue(DefaultHandler.prototype.curvedValue); handler.selectedObject.model.ChangeCurvedValue(DefaultHandler.prototype.curvedValue);
handler.needRedraw = true; handler.needRedraw = true;
handler.app.redrawGraph(); handler.app.redrawGraph();
userAction("Edge.Bend"); userAction("Edge.Bend");
}); });
$('#message').on('click', '#decCurvel', function(){ $('#message').on('click', '#decCurvel', function(){
handler.app.PushToStack("ChangeCurvelEdge");
handler.selectedObject.model.ChangeCurvedValue(-DefaultHandler.prototype.curvedValue); handler.selectedObject.model.ChangeCurvedValue(-DefaultHandler.prototype.curvedValue);
handler.needRedraw = true; handler.needRedraw = true;
handler.app.redrawGraph(); handler.app.redrawGraph();
@ -514,6 +534,8 @@ DefaultHandler.prototype.MouseUp = function(pos)
$('#message').unbind(); $('#message').unbind();
$('#message').on('click', '#DublicateSelected', function(){ $('#message').on('click', '#DublicateSelected', function(){
handler.app.PushToStack("DublicateSelection");
userAction("GroupSelected.Dublicate"); userAction("GroupSelected.Dublicate");
var newSelected = []; var newSelected = [];
@ -578,6 +600,8 @@ DefaultHandler.prototype.MouseUp = function(pos)
}); });
$('#message').on('click', '#RemoveSelected', function(){ $('#message').on('click', '#RemoveSelected', function(){
handler.app.PushToStack("RemoveSelection");
userAction("GroupSelected.Remove"); userAction("GroupSelected.Remove");
for(var i = 0; i < handler.selectedObjects.length; i ++) for(var i = 0; i < handler.selectedObjects.length; i ++)
@ -660,6 +684,8 @@ AddGraphHandler.prototype = Object.create(BaseHandler.prototype);
AddGraphHandler.prototype.MouseDown = function(pos) AddGraphHandler.prototype.MouseDown = function(pos)
{ {
this.app.PushToStack("Add");
this.app.CreateNewGraph(pos.x, pos.y); this.app.CreateNewGraph(pos.x, pos.y);
this.needRedraw = true; this.needRedraw = true;
this.inited = false; this.inited = false;
@ -750,11 +776,13 @@ ConnectionGraphHandler.prototype.SelectVertex = function(selectedObject)
} }
dialogButtons[g_orintEdge] = function() { dialogButtons[g_orintEdge] = function() {
handler.AddNewEdge(selectedObject, true); handler.app.PushToStack("Connect");
handler.AddNewEdge(selectedObject, true);
$( this ).dialog( "close" ); $( this ).dialog( "close" );
}; };
dialogButtons[g_notOrintEdge] = function() { dialogButtons[g_notOrintEdge] = function() {
handler.AddNewEdge(selectedObject, false); handler.app.PushToStack("Connect");
handler.AddNewEdge(selectedObject, false);
$( this ).dialog( "close" ); $( this ).dialog( "close" );
}; };
@ -882,31 +910,6 @@ DeleteGraphHandler.prototype.MouseDown = function(pos)
this.app.PushToStack("Delete"); this.app.PushToStack("Delete");
this.app.DeleteObject(selectedObject); this.app.DeleteObject(selectedObject);
this.needRedraw = true; this.needRedraw = true;
this.UpdateUndoButton();
}
DeleteGraphHandler.prototype.UpdateUndoButton = function()
{
if (!this.app.IsUndoStackEmpty())
{
this.message = g_selectObjectToDelete + "<span style=\"float:right;\"><button type=\"button\" id=\"undoDelete\" class=\"btn btn-default btn-xs\"> " + g_Undo + " </button>";
var handler = this;
$('#message').unbind();
$('#message').on('click', '#undoDelete', function(){
handler.app.Undo();
userAction("Undo.Delete");
handler.UpdateUndoButton();
});
}
else
{
this.message = g_selectObjectToDelete;
}
this.app.updateMessage();
} }
/** /**
@ -923,6 +926,8 @@ DeleteAllHandler.prototype = Object.create(BaseHandler.prototype);
DeleteAllHandler.prototype.clear = function() DeleteAllHandler.prototype.clear = function()
{ {
this.app.PushToStack("DeleteAll");
// Selected Graph. // Selected Graph.
this.app.graph = new Graph(); this.app.graph = new Graph();
this.app.savedGraphName = ""; this.app.savedGraphName = "";
@ -966,6 +971,7 @@ ShowAdjacencyMatrix.prototype.show = function()
}); });
dialogButtons[g_save] = function() { dialogButtons[g_save] = function() {
handler.app.PushToStack("ChangeAdjacencyMatrix");
handler.app.SetAdjacencyMatrixSmart($( "#AdjacencyMatrixField" ).val()); handler.app.SetAdjacencyMatrixSmart($( "#AdjacencyMatrixField" ).val());
$( this ).dialog( "close" ); $( this ).dialog( "close" );
}; };
@ -1029,7 +1035,8 @@ ShowIncidenceMatrix.prototype.show = function()
}); });
dialogButtons[g_save] = function() { dialogButtons[g_save] = function() {
handler.app.SetIncidenceMatrixSmart($( "#IncidenceMatrixField" ).val()); handler.app.PushToStack("IncidenceMatrixChanged");
handler.app.SetIncidenceMatrixSmart($( "#IncidenceMatrixField" ).val());
$( this ).dialog( "close" ); $( this ).dialog( "close" );
}; };
dialogButtons[g_cancel] = function() { dialogButtons[g_cancel] = function() {
@ -1409,6 +1416,8 @@ GroupRenameVertices.prototype.show = function()
var app = this.app; var app = this.app;
dialogButtons[g_save] = function() { dialogButtons[g_save] = function() {
app.PushToStack("Rename");
var titlesList = $( "#VertextTitleList" ).val().split('\n'); var titlesList = $( "#VertextTitleList" ).val().split('\n');
for (i = 0; i < Math.min(graph.vertices.length, titlesList.length); i ++) for (i = 0; i < Math.min(graph.vertices.length, titlesList.length); i ++)
{ {
@ -1622,6 +1631,8 @@ SetupVertexStyle.prototype.show = function(index, selectedVertexes)
class : "MarginLeft", class : "MarginLeft",
click : function() { click : function() {
app.PushToStack("ChangeStyle");
applyDiameter(forAll ? (new VertexModel()).diameter : app.GetDefaultVertexSize()); applyDiameter(forAll ? (new VertexModel()).diameter : app.GetDefaultVertexSize());
var indexes = []; var indexes = [];
@ -1655,6 +1666,8 @@ SetupVertexStyle.prototype.show = function(index, selectedVertexes)
dialogButtons[g_save] = function() { dialogButtons[g_save] = function() {
app.PushToStack("ChangeStyle");
applyDiameter(parseInt($( "#vertexSize" ).val())); applyDiameter(parseInt($( "#vertexSize" ).val()));
var indexes = []; var indexes = [];
@ -1915,6 +1928,8 @@ SetupEdgeStyle.prototype.show = function(index, selectedEdges)
text : g_default, text : g_default,
class : "MarginLeft", class : "MarginLeft",
click : function() { click : function() {
app.PushToStack("ChangeStyle");
applyWidth(forAll ? (new EdgeModel()).width : app.GetDefaultEdgeWidth()); applyWidth(forAll ? (new EdgeModel()).width : app.GetDefaultEdgeWidth());
var indexes = []; var indexes = [];
if (self.index == "all") if (self.index == "all")
@ -1947,6 +1962,8 @@ SetupEdgeStyle.prototype.show = function(index, selectedEdges)
dialogButtons[g_save] = function() { dialogButtons[g_save] = function() {
app.PushToStack("ChangeStyle");
applyWidth(parseInt($( "#edgeWidth" ).val())); applyWidth(parseInt($( "#edgeWidth" ).val()));
var indexes = []; var indexes = [];
@ -2040,7 +2057,7 @@ SetupBackgroundStyle.prototype.show = function()
var dialogButtons = {}; var dialogButtons = {};
var graph = this.app.graph; var graph = this.app.graph;
var app = this.app; var app = this.app;
var style = Object.assign({}, app.backgroundCommonStyle); var style = FullObjectCopy(app.backgroundCommonStyle);
var fillFields = function() var fillFields = function()
{ {
@ -2069,6 +2086,9 @@ SetupBackgroundStyle.prototype.show = function()
text : g_default, text : g_default,
class : "MarginLeft", class : "MarginLeft",
click : function() { click : function() {
app.PushToStack("ChangeBackground");
app.ResetBackgroundStyle(); app.ResetBackgroundStyle();
app.redrawGraph(); app.redrawGraph();
$( this ).dialog( "close" ); $( this ).dialog( "close" );
@ -2076,6 +2096,7 @@ SetupBackgroundStyle.prototype.show = function()
}; };
dialogButtons[g_save] = function() { dialogButtons[g_save] = function() {
app.PushToStack("ChangeBackground");
app.SetBackgroundStyle(style); app.SetBackgroundStyle(style);
app.redrawGraph(); app.redrawGraph();
$( this ).dialog( "close" ); $( this ).dialog( "close" );

View File

@ -240,6 +240,8 @@ function postLoadPage()
var key = getChar(event); var key = getChar(event);
var code = getCharCode(event); var code = getCharCode(event);
console.log(key + " code=" + code); console.log(key + " code=" + code);
var evtobj = window.event ? event : e;
var isCtrl = evtobj ? evtobj.ctrlKey : false;
var moveValue = 10; var moveValue = 10;
if (code == 61 || code == 43) // + if (code == 61 || code == 43) // +
@ -289,6 +291,11 @@ function postLoadPage()
{ {
selectHandler('Default', 'default'); selectHandler('Default', 'default');
} }
else if (code == 26 && isCtrl)
{
userAction("Key_GraphUndo");
application.SetHandlerMode("graphUndo");
}
} }
$(document).keydown(function(event) { $(document).keydown(function(event) {
@ -463,6 +470,12 @@ function postLoadPage()
userAction(this.id); userAction(this.id);
application.SetHandlerMode("setupBackgroundStyle"); application.SetHandlerMode("setupBackgroundStyle");
} }
document.getElementById('GraphUndo').onclick = function ()
{
userAction(this.id);
application.SetHandlerMode("graphUndo");
}
document.getElementById('runUserScript').onclick = function () document.getElementById('runUserScript').onclick = function ()
{ {
@ -652,8 +665,6 @@ function postLoadPage()
}); });
var devTools = document.getElementById('developerTools'); var devTools = document.getElementById('developerTools');
devTools.style.left = 0; devTools.style.left = 0;
resizeCanvas(); resizeCanvas();

View File

@ -10,7 +10,7 @@
<script src="<?= Root('i/js/dev/jquery-ui.js')?>"></script> <script src="<?= Root('i/js/dev/jquery-ui.js')?>"></script>
<script src="<?= Root('i/js/dev/jquery.feedback_me.js')?>"></script> <script src="<?= Root('i/js/dev/jquery.feedback_me.js')?>"></script>
<script src="<?= Root("script/example.js?v=46")?>" ></script> <script src="<?= Root("script/example.js?v=47")?>" ></script>
</head> </head>
<!-- <!--
<div class="pull-right"> <div class="pull-right">
@ -134,6 +134,8 @@
</ul> </ul>
</div> </div>
<button type="button" class="btn btn-default btn-sm" id="GraphUndo"><span class="glyphicon glyphicon-arrow-left fa-fw"></span><span class="hidden-phone"> <?= L('undo')?> <sub style="color:#AAAAAA">crtl+z</sub></span></button>
<!-- <!--
<? if (!$wasVote && count($voteTopics) > 0): ?> <? if (!$wasVote && count($voteTopics) > 0): ?>
<button type="button" class="btn btn-success" id="VoteButton"><span class="glyphicon glyphicon-thumbs-up"></span> <?= L('vote') ?></button> <button type="button" class="btn btn-success" id="VoteButton"><span class="glyphicon glyphicon-thumbs-up"></span> <?= L('vote') ?></button>