Skip to content

Commit

Permalink
Merge pull request #131 from DCMLab/redo
Browse files Browse the repository at this point in the history
The redo stack, segmenting it into its own file together with undo .
  • Loading branch information
pettter authored Aug 4, 2021
2 parents 694560c + 0587adc commit e6248f8
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 98 deletions.
2 changes: 2 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
<script src="js/draw.js" type="text/javascript"></script>
<script src="js/graph.js" type="text/javascript"></script>
<script src="js/delete.js" type="text/javascript"></script>
<script src="js/undo_redo.js" type="text/javascript"></script>
<script src="js/reductions.js" type="text/javascript"></script>
<script src="js/layers.js" type="text/javascript"></script>
<script src="js/accidentals.js" type="text/javascript"></script>
Expand Down Expand Up @@ -123,6 +124,7 @@
</div>
<div id="basic_buttons">
<input type="button" id="undobutton" value="Undo" onclick="do_undo()">
<input type="button" id="redobutton" value="Redo" onclick="do_redo()">
<input type="button" id="selectvisiblesaltbutton" value="Select visible relations" onclick="select_visibles(current_draw_context)">
<input type="button" id="deselectbutton" value="Deselect all" onclick="do_deselect()">
<input type="button" id="deletebutton" value="Delete meta-relations" onclick="delete_relations()" >
Expand Down
1 change: 1 addition & 0 deletions js/conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ try {
// General action shortcuts.
var action_conf = {
"undo": "U",
"redo": "I",
"deselect_all": "d",
"delete_all": "D",
"add_bookmark": "^",
Expand Down
27 changes: 18 additions & 9 deletions js/coordinates.js
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,6 @@ function add_note(layer_context, pname, oct, note, sim=true, id="") {
c = l.closest("chord");
else{
c = note_to_chord(mei,l);
console.log(c);
l.parentElement.insertBefore(c,l);
l.parentElement.removeChild(l);
c.appendChild(l);
Expand All @@ -283,20 +282,30 @@ function add_note(layer_context, pname, oct, note, sim=true, id="") {
return added.reverse();
}

function do_note(pname, oct, note, offset, id, redoing=false) {
var new_element_id = "new-"+random_id();
let n = note;
if(typeof(id) != "undefined")
new_element_id = id;
var added = [];
// Draw it temporarily
console.log(note);
added.push(draw_note(pname, oct, note, offset, new_element_id));
// Add it to the current layer
added.push(add_note(current_draw_context.layer, pname, oct, note, offset, new_element_id));
toggle_placing_note();
if(!redoing)
flush_redo();
undo_actions.push(["add note",added.reverse(),[n],[]]);
}


function place_note() {
if(placing_note!="" && !current_draw_context.layer.original_score){
let [pname, oct, note] = note_params();
if(!pname)
return;
var new_element_id = "new-"+random_id();
var added = [];
// Draw it temporarily
added.push(draw_note(pname, oct, note, true, new_element_id));
// Add it to the current layer
added.push(add_note(current_draw_context.layer, pname, oct, note, true, new_element_id));
toggle_placing_note();
undo_actions.push(["add note",added.reverse(),[],[]]);
do_note(pname, oct, note, true);
}
}

Expand Down
6 changes: 4 additions & 2 deletions js/delete.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ function delete_relation(elem) {
var mei_id = get_id(elem);
var mei_he = get_by_id(mei,mei_id);
var svg_hes = [];
var metarel = get_class_from_classlist(elem);
var metarel = get_class_from_classlist(elem) == "metarelation";
for(draw_context of draw_contexts){
let svg_he = get_by_id(document,draw_context.id_prefix + mei_id);
if(svg_he){
Expand Down Expand Up @@ -41,7 +41,7 @@ function delete_relation(elem) {
return action_removed;
}

function delete_relations() {
function delete_relations(redoing=false) {
console.debug("Using globals: selected for element selection, undo_actions for storing the action");
//Assume no meta-edges for now, meaning we only have to
var sel = selected.concat(extraselected);
Expand All @@ -53,6 +53,8 @@ function delete_relations() {
var removed = sel.flatMap(delete_relation);
undo_actions.push(["delete relation",removed.reverse(),selected,extraselected]);
sel.forEach(toggle_selected);
if(!redoing)
flush_redo();
}


23 changes: 23 additions & 0 deletions js/draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,29 @@ function draw_relation(draw_context, mei_graph, g_elem) {

}

function undraw_meta_or_relation(draw_context, g_elem) {
let mei_id = get_id(g_elem);
let svg_id = draw_context.id_prefix + mei_id;
let svg_he = get_by_id(document,svg_id);
if(!svg_he){
console.debug("Could not undraw relation in draw context",g_elem, draw_context);
return false;
}
if(g_elem.getAttribute("type") == "relation")
unmark_secondaries(draw_context, mei_graph, mei_he);
var primaries = relation_primaries(mei_graph,g_elem).map(
(e) => document.getElementById(id_in_svg(draw_context,node_to_note_id(e)))
);
var secondaries = relation_secondaries(mei_graph,g_elem).map(
(e) => document.getElementById(id_in_svg(draw_context,node_to_note_id(e)))
);
primaries.forEach( (item) => { item.classList.remove("extrahover"); });
secondaries.forEach((item) => { item.classList.remove("selecthover"); });
svg_he.parentNode.removeChild(svg_he);
return true;
}


function redraw_relation(draw_context,g_elem) {
var svg_g_elem = get_by_id(document, id_in_svg(draw_context, get_id(g_elem)));
if(!svg_g_elem){
Expand Down
95 changes: 8 additions & 87 deletions js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ window.onerror = function errorHandler(errorMsg, url, lineNumber) {

// OK we've selected stuff, let's make the selection into a
// "relation".
function do_relation(type) {
function do_relation(type, id, redoing=false) {
console.debug("Using globals: selected, extraselected, mei, undo_actions");
if (selected.length == 0 && extraselected == 0) {
return;}
Expand Down Expand Up @@ -115,7 +115,7 @@ function do_relation(type) {
var primaries = extraselected.map((e) => add_mei_node_for(mei_graph,e));
var secondaries = selected.map((e) => add_mei_node_for(mei_graph,e));
added.push(primaries.concat(secondaries));
[he_id,mei_elems] = add_relation(mei_graph,primaries, secondaries, type);
[he_id,mei_elems] = add_relation(mei_graph,primaries, secondaries, type, id);
added.push(mei_elems);
for(var i = 0; i < draw_contexts.length; i++) {
let g_elem =draw_relation(draw_contexts[i],mei_graph,get_by_id(mei_graph.getRootNode(), he_id));
Expand All @@ -127,6 +127,8 @@ function do_relation(type) {
undo_actions.push(["relation",added.reverse(),selected,extraselected]);
selected.concat(extraselected).forEach(toggle_selected); // De-select
}
if(!redoing)
flush_redo();
tooltip_update();
}

Expand All @@ -150,7 +152,7 @@ function do_comborelation(type) {
}


function do_metarelation(type) {
function do_metarelation(type, id, redoing=false) {
console.debug("Using globals: mei_graph, selected, extraselected");
if (selected.length == 0 && extraselected == 0) {
return;}
Expand All @@ -165,100 +167,19 @@ function do_metarelation(type) {
get_by_id(mei_graph.getRootNode(), id_or_oldid(e)));
var secondaries = selected.map((e) =>
get_by_id(mei_graph.getRootNode(), id_or_oldid(e)));
var [he_id,mei_elems] = add_metarelation(mei_graph, primaries, secondaries, type);
var [he_id,mei_elems] = add_metarelation(mei_graph, primaries, secondaries, type, id);
added.push(mei_elems);
for(var i = 0; i< draw_contexts.length; i++)
added.push(draw_metarelation(draw_contexts[i], mei_graph, get_by_id(mei_graph.getRootNode(),he_id))); // Draw the edge

undo_actions.push(["metarelation",added,selected,extraselected]);
selected.concat(extraselected).forEach(toggle_selected); // De-select
tooltip_update();
if(!redoing)
flush_redo();
}


// Oops, undo whatever we did last.
function do_undo() {
console.debug("Using globals: undo_actions, selected, extraselected, mei, rerendered_after_action");
// Get latest undo_actions
if(undo_actions.length == 0) {
console.log("Nothing to undo");
return;
}
if(undo_actions.length == rerendered_after_action){
console.log("Cannot undo past a rerender");
alert("Cannot undo past a rerender.");
return;
}
// Deselect the current selection, if any
selected.forEach(toggle_selected);
extraselected.forEach((x) => {toggle_selected(x,true);});

[what,elems,sel,extra] = undo_actions.pop();
if(what == "edges" || what == "relation" || what == "metarelation") {
var added = elems;
if(what == "relation")
added.flat().forEach((x) => {
if(mei_graph.contains(x) && x.getAttribute("type") == "relation")
for(var i = 0; i < draw_contexts.length; i++)
unmark_secondaries(draw_contexts[i],mei_graph,x)
});
// Remove added elements
added.flat().forEach((x) => {
if(!node_referred_to(x.getAttribute("xml:id")))
x.parentNode.removeChild(x);
});
// Select last selection
sel.forEach((x) => {toggle_selected(x);});
extra.forEach((x) => {toggle_selected(x,true);});
}else if( what == "delete relation" ) {
var removed = elems;
removed.forEach((x) => {
x[1].insertBefore(x[0],x[2])
let dc = draw_contexts.find((d) => d.svg_elem.contains(x[0]));
let rel = get_class_from_classlist(x[0]) == "relation";
if(dc && rel){
let mei_id = get_id(x[0]);
let mei_he = get_by_id(mei,mei_id);
mark_secondaries(dc, mei_graph, mei_he)
}
});
// Select last selection
sel.forEach((x) => {toggle_selected(x);});
extra.forEach((x) => {toggle_selected(x,true);});

}else if (what == "change relation type") {
var types = elems;
sel.concat(extra).forEach((he) => {
//TODO: move type_synonym application so that this
//is the right type == the one from the MEI
var [from,to] = types.pop();
var id = id_or_oldid(he);
var hes = [get_by_id(document,id)].concat(get_by_oldid(document,id));
hes.forEach((he) => he.setAttribute("type",from));
var mei_he = get_by_id(mei,id);
mei_he.getElementsByTagName("label")[0].setAttribute("type",from);
hes.forEach(toggle_shade);
});
sel.forEach((x) => {toggle_selected(x);});
extra.forEach((x) => {toggle_selected(x,true);});
}else if (what == "reduce") {
var [relations,notes,graphicals] = elems;
graphicals.flat().forEach((x) => { if(x) x.classList.remove("hidden");});
sel.forEach((x) => {toggle_selected(x);});
extra.forEach((x) => {toggle_selected(x,true);});
}else if (what == "add note") {
var [mei_elems,graphicals] = elems;
graphicals.forEach((x) => x.parentNode.removeChild(x));
mei_elems[0].parentNode.removeChild(mei_elems[0]);
if(mei_elems.length > 1){
var c = mei_elems[1];
c.parentNode.insertBefore(c.children[0],c);
c.parentNode.removeChild(c);
}
}
tooltip_update();
}

// Function to download data to a file
// Taken from StackOverflow answer by Kanchu at
// https://stackoverflow.com/questions/13405129/javascript-create-and-save-file
Expand Down
2 changes: 2 additions & 0 deletions js/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,8 @@ function handle_keypress(ev) {
if (elem.onmouseout) elem.onmouseout();
} else if (ev.key == action_conf.undo) { // UNDO
do_undo();
} else if (ev.key == action_conf.redo) { // UNDO
do_redo();
} else if (ev.key == action_conf.reduce_relations) { // Reduce relations
do_reduce_pre(current_draw_context);
} else if (ev.key == action_conf.show_hide_notation) { // Show/hide ties etc.
Expand Down
Loading

0 comments on commit e6248f8

Please sign in to comment.