/* * global vars and configuration * */ var DE_paper, // objects DE_shapes_by_id = {}, DE_shapes = [], DE_target_shapes = [], DE_texts = [], DE_connections = {}, DE_id = 0, DE_next_grid = 0, // ui DE_ui_margin = 64, DE_ui_padding = DE_ui_margin/3, DE_ui_xbegin = 10, DE_ui_ybegin = 5, DE_ui_box_height = 32, DE_ui_line_margin = 70, DE_ui_ysource = DE_ui_ybegin, DE_ui_ytarget = DE_ui_ysource+DE_ui_line_margin; DE_ui_font_size = 14, DE_ui_font_width = -1, /////////////////////////////////////////////////////////////////////////////// DE_ui_stroke_width = 1, DE_ui_stroke_width_hi = 3, DE_ui_align_stroke = "#eee", DE_ui_align_stroke_hi = "#000", DE_ui_text_att = { "text-anchor": "start", "font-size": DE_ui_font_size, "font-family": "Times New Roman" }, /////////////////////////////////////////////////////////////////////////////// // dragging DE_cur_drag = null, DE_dragging = false, DE_new_pos = -1, DE_old_pos = -1; // connecting DE_connect_mode = false, DE_connect_mode_shape = null, DE_new_conns = [], // editing DE_cur_ed = null, DE_cur_ed_shape = null, DE_edit_mode = false, // removing DE_rm_mult = [], DE_undo_stack = [], // keyboard interface DE_kbd_focused_phrase = null, DE_kbd_move_mode = false, DE_kbd_select_mode = false, // done DE_target_done = [], // data DE_data_source = null, DE_data_target = null, DE_data_align = null, // lock DE_locked = false; /****************************************************************************** * * style * */ var ch_style = function (item, shape_att, text_att, anim=false, anim_dur=50) { if (!anim) { item.attr(shape_att); if (item.pair) item.pair.attr(text_att); } else { item.animate(shape_att, anim_dur); item.pair.animate(text_att, anim_dur); } } var DE_ui_style_normal = function (item, type=null) { if (!item) return; if (!type) type = item["type_"]; var to_delete = false; var color = "#fff"; var stroke_color = "#eee"; var text_color = "#eee"; if (DE_rm_mult.indexOf(item)>-1) color = stroke_color = "#f00"; if (DE_target_done.indexOf(item)>-1) { color = "#fff"; text_color = stroke_color= "#000"; } var shape_att; var text_att; if (type == "source") { shape_att = { "fill": "#fff", "fill-opacity": 1.0, "stroke": "#000", "stroke-width": 1 }; text_att = { "fill": "#000", "fill-opacity": 1.0, "stroke": "none", "stroke-width": 0 }; } else { // type == "target" shape_att = { "fill": color, "fill-opacity": 1.0, "stroke": stroke_color, "stroke-width": 1 }; text_att = { "fill": text_color, "fill-opacity": 1.0, "stroke": text_color, "stroke-width": 0 }; } ch_style(item, shape_att, text_att); } var DE_ui_style_highlight = function (item, type=null) { if (!type) type = item["type_"]; var to_delete = false; var color = "#fff"; var stroke_color = "#000"; var stroke_width = 3; var text_color = "#000"; if (DE_rm_mult.indexOf(item)>-1) color = stroke_color = "#f00"; if (DE_target_done.indexOf(item)>-1) { color = "#fff"; text_color = stroke_color = "#000"; stroke_width = 5; } var shape_att; var text_att; if (type == "source") { shape_att = { "fill": "#fff", "fill-opacity": 1.0, "stroke": "#000", "stroke-width": 3 }; text_att = { "fill": "#000", "fill-opacity": 1.0, "stroke": "none", "stroke-width": 0 }; } else { // type == "target" shape_att = { "fill": color, "fill-opacity": 1.0, "stroke": stroke_color, "stroke-width": stroke_width }; text_att = { "fill": text_color, "fill-opacity": 1.0, "stroke": text_color, "stroke-width": 0 }; } ch_style(item, shape_att, text_att); } var DE_ui_style_mark = function (item, type=null) { if (!type) type = item["type_"]; var shape_att; var text_att; if (type == "source") { shape_att = { "fill": "#ff0000", "fill-opacity": 0.25, "stroke": "#000", "stroke-width": 3 }; text_att = { "fill": "#000", "fill-opacity": 1.0, "stroke": "none", "stroke-width": 0 }; } else { // type == "target" shape_att = { "fill": "#000", "fill-opacity": 1.0, "stroke": "#000000", "stroke-width": 9 }; text_att = { "fill": "#fff", "fill-opacity": 1.0, "stroke": "#fff", "stroke-width": 0 }; } ch_style(item, shape_att, text_att); } /****************************************************************************** * * connections/links * */ Raphael.fn.connection = function (obj1, obj2, line, bg) { if (obj1.line && obj1.from && obj1.to) { line = obj1; obj1 = line.from; obj2 = line.to; } if (!obj1.getBBox() || !obj2.getBBox()) return; var bb1 = obj1.getBBox(), bb2 = obj2.getBBox(), x1 = bb1.x+bb1.width/2, y1 = bb1.y+bb1.height, x2 = bb2.x+bb2.width/2, y2 = bb2.y, path = ["M", x1, y1, "L", x2, y2]; if (line && line.line) { line.bg && line.bg.attr({path: path}); line.line.attr({path: path}); } else { return { bg: bg && bg.split && this.path(path).attr({ "stroke": bg.split("|")[0], "fill": "none", "stroke-width": bg.split("|")[1] || 3 }), line: this.path(path).attr({ "stroke": DE_ui_align_stroke, "fill": "none" }), from: obj1, to: obj2 }; } } var DE_conn_str = function (obj1, obj2) { return obj1["id_"]+"-"+obj2["id_"]; } var DE_make_conn = function(obj1, obj2) { DE_connections[DE_conn_str(obj1,obj2)] = DE_paper.connection(obj1, obj2); if (DE_connect_mode) { DE_new_conns.push(DE_connections[DE_conn_str(obj1,obj2)]); DE_connections[DE_conn_str(obj1,obj2)].line.attr({ "stroke":DE_ui_align_stroke_hi, "stroke-width":DE_ui_stroke_width_hi }); } } var DE_rm_conn = function (id1, id2) { var b = false; for (var i=0; i= b_right || a_right <= b_left)) { // collision! if (a["grid_"] > b["grid_"]) { // a should be right of b a.attr({"x": a.attr("x")+(a_right-b_left)}); a.pair.attr({"x": a.pair.attr("x")+(a_right-b_left)}); } else { // a should be left of b b.attr({"x": a.attr("x")+(a_right-b_left)}); b.pair.attr({"x": a.pair.attr("x")+(a_right-b_left)}); } } } } } var DE_collide = function (obj) { if (DE_edit_mode) return; if (obj["type_"]=="source") return; // not a shape if (!obj["id_"] || obj.type!="rect") return; if (DE_cur_drag["grid_tmp_"] > obj["grid_tmp_"]) { // right -> left /*if (DE_cur_drag.getBBox().width < obj.getBBox().width && DE_cur_drag.getBBox().x > (obj.getBBox().x+obj.getBBox().width/1000)) { // ignored tolerance, when return; // dragging onto shapes }*/ att = { x: obj.attr("x")+DE_cur_drag.getBBox().width+(DE_ui_margin-2*DE_ui_padding) }; obj.attr(att); att = { x: obj.pair.attr("x")+DE_cur_drag.getBBox().width+(DE_ui_margin-2*DE_ui_padding) }; obj.pair.attr(att); DE_colldetect("rl"); } else { // left -> right /*if (DE_cur_drag.getBBox().width < obj.getBBox().width && DE_cur_drag.getBBox().x < (obj.getBBox().x+obj.getBBox().width/1000)) { return; }*/ att = { x: obj.attr("x")-(DE_cur_drag.getBBox().width+(DE_ui_margin-2*DE_ui_padding)) }; obj.attr(att); att = { x: obj.pair.attr("x")-(DE_cur_drag.getBBox().width+(DE_ui_margin-2*DE_ui_padding)) }; obj.pair.attr(att); DE_colldetect("lr"); } // grid pos DE_new_pos = obj["grid_tmp_"]; var tmp_pos = DE_cur_drag["grid_tmp_"]; DE_cur_drag["grid_tmp_"] = obj["grid_tmp_"]; obj["grid_tmp_"] = tmp_pos; } var DE_snap_to_grid = function (anim=false, ignore_cur_drag=false) { // just x coord, y is fixed in drag var d = DE_ui_xbegin; // just target objs DE_target_shapes.sort(function(a, b) { return a["grid_"]-b["grid_"]; }); // switch if (DE_cur_drag) { // fix glitch when calling from DE_add_object() and up() DE_cur_drag["grid_"] = DE_new_pos; cur_id = DE_cur_drag["id_"]; if (DE_new_pos > DE_old_pos) { // left -> right for (var i=0; i < DE_target_shapes.length; i++) { pos = DE_target_shapes[i]["grid_"]; id_ = DE_target_shapes[i]["id_"]; if (id_ == cur_id) continue; if (pos >= DE_old_pos && pos <= DE_new_pos) { DE_target_shapes[i]["grid_"] -= 1; } else { continue; } } } else if (DE_new_pos < DE_old_pos) { // right -> left for (var i=0; i < DE_target_shapes.length; i++) { pos = DE_target_shapes[i]["grid_"]; id_ = DE_target_shapes[i]["id_"]; if (id_ == cur_id) continue; if (pos >= DE_new_pos && pos <= DE_old_pos) { DE_target_shapes[i]["grid_"] += 1; } else { continue; } } } } // ^ fix glitch // sort by grid pos DE_target_shapes.sort(function(a, b) { return a["grid_"]-b["grid_"]; }); // fix box layout for (var i = 0; i < DE_target_shapes.length; i++) { var obj = DE_target_shapes[i]; if (DE_cur_drag && ignore_cur_drag && obj["id_"]==DE_cur_drag["id_"]) continue; if (!obj || !obj.attrs) { // removed return; } att = { x:d }; if (anim) { obj.attr(att); } else { obj.attr(att); } att = { x: obj.getBBox().x+DE_ui_padding }; if (anim) { //obj.pair.animate(att,50); obj.pair.attr(att); } else { obj.pair.attr(att); } d += obj.getBBox().width+(DE_ui_margin-2*DE_ui_padding); // fix tmp grid obj["grid_tmp_"] = obj["grid_"]; } for (key in DE_connections) { DE_paper.connection(DE_connections[key]); } // now mouseout() can remove highligting if (!ignore_cur_drag) DE_cur_drag = null; } var DE_debug_DE_snap_to_grid = function () { var s = ""; for (var i=0; i-1) align_done = true; if (parseInt(c.split("-")[idx]) == item["id_"]) { var obj = DE_shapes_by_id[parseInt(c.split("-")[other_idx])]; if (parseInt(c.split("-")[1]) != DE_kbd_focused_phrase["id_"]) { var x = false; for (d in DE_connections) { if (d == c.split("-")[0]+'-'+DE_kbd_focused_phrase["id_"]) { x = true; break; } } if (!x) { if (!(DE_connect_mode_shape && obj["id_"]==DE_connect_mode_shape["id_"])) DE_ui_style_normal(obj); } if (align_done) { DE_connections[c].line.attr({"stroke-width":DE_ui_stroke_width, "stroke":DE_ui_align_stroke_hi}); } else { DE_connections[c].line.attr({"stroke-width":DE_ui_stroke_width, "stroke":DE_ui_align_stroke}); } } else { aligned_with_focused = true; } } } if (!aligned_with_focused) DE_ui_style_normal(item); for (var i=0; i-1) return; var index = DE_rm_mult.indexOf(item); if (index != -1) { DE_rm_mult.splice(index, 1); for (c in DE_connections) { var i = parseInt(c.split("-")[1]); if (i == item["id_"]) DE_connections[c].line.attr({"stroke":"#000"}); } DE_ui_style_highlight(item); } else { item.attr({"stroke":"red", "fill":"red"}); for (c in DE_connections) { var i = parseInt(c.split("-")[1]); if (i == item["id_"]) DE_connections[c].line.attr({"stroke":"#f00"}); } DE_rm_mult.push(item); } } else if(e.shiftKey && false) { // add var x = DE_shapes_by_id[item["id_"]].attr("x")+DE_shapes_by_id[item["id_"]].attr("width") +2*DE_ui_padding; var new_obj = DE_make_obj(x, "", "target"); var new_grid = item["grid_"]+1; new_obj["grid_"] = new_grid; new_obj.pair["grid_"] = new_grid; for (var i=0; i=new_grid) { sh["grid_"] += 1; sh.pair["grid_"] += 1; } } DE_snap_to_grid(true); } } } var DE_item_click_source = function (e, item) { if (DE_locked) return; if (DE_connect_mode) { if (item != DE_connect_mode_shape) return; if (item != DE_kbd_focused_phrase) DE_ui_style_highlight(item); DE_connect_mode = false; DE_connect_mode_shape = null; } else { DE_ui_style_mark(item); DE_connect_mode = true; DE_connect_mode_shape = item; } } /****************************************************************************** * * add/remove objects * */ var DE_make_obj = function (x, text, type, grid_pos=null, id=null) { var y; if (type == "source") { y = DE_ui_ysource; } else if (type == "target") { y = DE_ui_ytarget; } // make text obj DE_texts.push(DE_paper.text(x, y+(DE_ui_box_height/2), text).attr(DE_ui_text_att)); // make shape obj var x_shape = DE_texts[DE_texts.length-1].getBBox().x-DE_ui_padding, x_width = DE_texts[DE_texts.length-1].getBBox().width+(2*DE_ui_padding); DE_shapes.push(DE_paper.rect(x_shape, y, x_width, DE_ui_box_height, 5)); tx = DE_texts[DE_texts.length-1]; sh = DE_shapes[DE_shapes.length-1]; // fix z-index tx.toFront(); sh.toBack(); // pair text/shape tx.pair = DE_shapes[DE_shapes.length-1]; sh.pair = DE_texts[DE_texts.length-1]; // style DE_ui_style_normal(DE_shapes[DE_shapes.length-1]); // meta sh["type_"] = type; sh["id_"] = id; if (!id) sh["id_"] = DE_id; DE_shapes_by_id[sh["id_"]] = sh; if (type == "target") { // :'( //sh.drag(DE_move, DE_dragger, DE_up).onDragOver(function(obj) { DE_collide(obj); }) //sh.attr({ cursor: "move" }); //tx.drag(DE_move, DE_dragger, DE_up); sh["grid_"] = grid_pos; sh["grid_tmp_"] = grid_pos; if (!sh["grid_"]) { sh["grid_"] = DE_next_grid; sh["grid_tmp_"] = DE_next_grid; } sh.click(function(e) { DE_item_click_target(e, this); }); tx.click(function(e) { DE_item_click_target(e, this.pair); }); DE_target_shapes.push(sh); // inline text editing DE_paper.inlineTextEditing(tx); sh.dblclick(function(){ DE_enter_edit_mode(this); }); tx.dblclick(function(){ DE_enter_edit_mode(this.pair); }) } else if (type == "source") { sh.click(function(e) { DE_item_click_source(e, this); }); tx.click(function(e) { DE_item_click_source(e, this.pair); }); } // mouseover -out sh.mouseover(function() { DE_item_mouseover(this); }); sh.mouseout(function() { DE_item_mouseout(this); }); tx.mouseover(function() { DE_item_mouseover(this.pair); }); tx.mouseout(function() { //DE_item_mouseout(this.pair); }); DE_id++; if (type == "target") DE_next_grid++; return sh; } var DE_add_object = function() { if (!data) return; var max=0, max_idx=-1; for (var i=0; i < DE_shapes.length; i++) { if (DE_shapes[i]["grid_"] > max) { max_idx = i; max = DE_shapes[i]["grid_"]; } } if (!DE_shapes[max_idx]) { DE_make_obj(DE_ui_xbegin+DE_ui_padding, "", "target"); } else { DE_make_obj(DE_shapes[max_idx].getBBox().x2+(DE_ui_margin-DE_ui_padding), "", "target"); } DE_paper.setSize( DE_paper.width +DE_target_shapes[DE_target_shapes.length-1].getBBox().width +DE_ui_margin, DE_paper.height); DE_cur_drag = null; if (DE_target_shapes.length==1) DE_kbd_focus_shape(DE_target_shapes[0]); DE_snap_to_grid(true); } var DE_make_objs = function (a, type) { for (var i=0; i < a.length; i++) { var x = 0; if (i == 0) { x = DE_ui_xbegin+DE_ui_padding; } else { x = DE_ui_margin+DE_texts[DE_texts.length-1].getBBox().x2; } DE_make_obj(x, a[i], type); } }; var rm_obj = function(obj) { if (!obj) return; var del = DE_shapes_by_id[obj["id_"]]; if (!del) return; var del_grid = del["grid_"] for (key in DE_connections) { if (key.split("-")[1] == obj["id_"]) { DE_rm_conn(key.split("-")[0], key.split("-")[1]); } } var i=DE_data_source.length; for (; i del_grid) { DE_target_shapes[i]["grid_"] -= 1; } if (g > max) max = g; } DE_next_grid = g; if (!DE_next_grid) // empty DE_next_grid = 0; DE_cur_drag = null; DE_snap_to_grid(true); return; } var DE_enter_edit_mode = function (sh, kbd=false) { if (DE_locked) return; if (DE_edit_mode) return; if (kbd && !DE_kbd_focused_phrase) return; if (DE_target_done.indexOf(sh)>-1) return; if (DE_rm_mult.indexOf(sh)>-1) return; DE_edit_mode = true; //sh.pair.toFront(); //sh.toBack(); DE_cur_ed = sh.pair; DE_cur_ed_shape = sh; var input = DE_cur_ed.inlineTextEditing.startEditing(); var text_before = trim($(DE_cur_ed.node.innerHTML).text()) var id = sh["id_"]; input.addEventListener("keypress", function(e) { if (e.keyCode==27 || e.keyCode==37 || e.keyCode==38 || e.keyCode==39 || e.keyCode==40) { // esc, arrows, backspace return; } else if (e.keyCode == 8) { // backspace DE_cur_ed_shape.animate({width:DE_cur_ed_shape.getBBox().width-DE_ui_font_width},50); setTimeout(function(){DE_snap_to_grid(true);},125); } else if (e.keyCode == 13) { // return e.preventDefault(); DE_cur_ed.inlineTextEditing.stopEditing(); //DE_cur_ed_shape.toFront(); //DE_cur_ed.toBack(); DE_cur_ed_shape.animate({width:DE_cur_ed.getBBox().width+(DE_ui_margin-DE_ui_padding)},50); setTimeout(function(){DE_snap_to_grid(true);},50); DE_edit_mode = false; var text_now = trim($(DE_cur_ed.node.innerHTML).text()) if (text_before != text_now) { DE_undo_stack.push(["edit", id, text_before]); } } else { // input DE_cur_ed_shape.animate({width:(this.value.length*DE_ui_font_width)+2*DE_ui_font_width+2*DE_ui_padding},25); setTimeout(function(){ DE_snap_to_grid(true); DE_paper.setSize(DE_paper.width+DE_ui_font_width, DE_paper.height); },25); } }); /*input.addEventListener("blur", function(e) { DE_cur_ed.inlineTextEditing.stopEditing(); //DE_cur_ed_shape.toFront(); //DE_cur_ed.toBack(); DE_cur_ed_shape.animate({width:DE_cur_ed.getBBox().width+(DE_ui_margin-DE_ui_padding)},125); //setTimeout(function(){DE_snap_to_grid(true);},125); DE_edit_mode = false; var text_now = trim($(DE_cur_ed.node.innerHTML).text()) if (text_before != text_now) { DE_undo_stack.push(["edit", id, text_before]); } }, true);*/ } /****************************************************************************** * * extract data from ui * */ var DE_extract_data = function () { el = document.getElementById("data"); d = {}; d["source"] = []; d["target"] = []; d["align"] = []; // target var ids = []; DE_target_shapes.sort(function(a, b) { return a["grid_"]-b["grid_"]; }); for (var i=0; i-1) { DE_target_done.splice(DE_target_done.indexOf(DE_kbd_focused_phrase),1); } else { DE_target_done.push(DE_kbd_focused_phrase); DE_kbd_move_mode = false; DE_kbd_select_mode = true; } DE_ui_style_highlight(DE_kbd_focused_phrase); } if (e.keyCode==13 && DE_kbd_move_mode) { e.preventDefault(); DE_kbd_move_mode = false; DE_kbd_select_mode = true; DE_snap_to_grid(); } if (char_str == "A") { // add if (DE_target_shapes.length > 0) { var x = DE_kbd_focused_phrase.attr("x")+DE_kbd_focused_phrase.attr("width") +2*DE_ui_padding; var new_obj = DE_make_obj(x, "", "target"); var new_grid = DE_kbd_focused_phrase["grid_"]+1; new_obj["grid_"] = new_grid; new_obj.pair["grid_"] = new_grid; for (var i=0; i=new_grid) { sh["grid_"] += 1; sh.pair["grid_"] += 1; } } } else { var new_obj = DE_make_obj(0, "", "target"); DE_kbd_focus_shape(new_obj); } DE_snap_to_grid(true); } else if (char_str == "U") { DE_undo(); } else if (char_str == "M") { // move mode if (DE_kbd_move_mode) { DE_kbd_move_mode = false; DE_kbd_select_mode = true; DE_snap_to_grid(); } else { if (DE_target_done.indexOf(DE_kbd_focused_phrase)>-1) return; DE_kbd_move_mode = true; DE_kbd_select_mode = false; } } else if (char_str == "E") { // edit mode DE_enter_edit_mode(DE_kbd_focused_phrase, true); } else if (char_str=="S") { // select mode if (DE_kbd_select_mode) { DE_kbd_move_mode = false; } else { DE_kbd_select_mode = true; DE_kbd_move_mode = false; } } else if (char_str == "D") { // remove var x = false; if (DE_rm_mult.indexOf(DE_kbd_focused_phrase) > -1) x = true; if (DE_rm_mult.length>0) { for (var i=0; i 0) DE_kbd_focus_shape(DE_target_shapes[0]); } } else { var d = DE_kbd_focused_phrase; if (DE_target_done.indexOf(d) > -1) return; DE_kbd_focused_phrase = DE_kbd_get_next_to("right", DE_kbd_focused_phrase); if (!DE_kbd_focused_phrase) { DE_kbd_focused_phrase = DE_kbd_get_next_to("left", d); } DE_kbd_focus_shape(DE_kbd_focused_phrase); var connected_source_phrases = []; for (c in DE_connections) { var i = parseInt(c.split('-')[1]); if (i == d["id_"]) connected_source_phrases.push(DE_connections[c].from); } if (d) { DE_undo_stack.push(["rm", d["grid_"], d["id_"], $(d.pair.node.innerHTML).text(), connected_source_phrases]); rm_obj(d); } } } if (DE_kbd_select_mode && DE_kbd_focused_phrase) { // select <- -> if (e.keyCode == 39) { // right e.preventDefault(); DE_kbd_select_phrase("right", DE_kbd_focused_phrase); } else if (e.keyCode == 37) { // left e.preventDefault(); DE_kbd_select_phrase("left", DE_kbd_focused_phrase); } } if (DE_kbd_move_mode && DE_kbd_focused_phrase) { // move <- -> if (e.keyCode == 39) { // right e.preventDefault(); DE_kbd_swap("right", DE_kbd_focused_phrase); } else if (e.keyCode == 37) { // left e.preventDefault(); DE_kbd_swap("left", DE_kbd_focused_phrase); } } }; var DE_kbd_get_next_to = function(dir, shape) { if (!shape) return null; DE_target_shapes.sort(function(a, b) { return a["grid_"]-b["grid_"]; }); for (var i=0; i-1) align_done = true; if (align_done) { DE_connections[c].line.attr({"stroke-width":DE_ui_stroke_width, "stroke":DE_ui_align_stroke_hi}); } else { DE_connections[c].line.attr({"stroke-width":DE_ui_stroke_width, "stroke":DE_ui_align_stroke}); } } for (sh in DE_shapes_by_id) DE_ui_style_normal(DE_shapes_by_id[sh]); DE_kbd_focused_phrase = obj; // style DE_ui_style_highlight(obj); for (c in DE_connections) { if (parseInt(c.split("-")[1]) == DE_kbd_focused_phrase["id_"]) { DE_connections[c].line.attr({"stroke-width":DE_ui_stroke_width_hi,"stroke":DE_ui_align_stroke_hi}); DE_ui_style_highlight(DE_shapes_by_id[parseInt(c.split("-")[0])], "source"); } } if (obj2) DE_ui_style_normal(obj2); } var DE_kbd_swap = function(dir="right", shape) { if (DE_edit_mode) return; if (!shape) return; if (DE_target_done.indexOf(shape)>-1) return; DE_target_shapes.sort(function(a, b) { return a["grid_"]-b["grid_"]; }); var grid_pos = []; for (var i=0; i left if (dir == "left") { att = { x: obj.attr("x")+shape.getBBox().width+(DE_ui_margin-2*DE_ui_padding) }; obj.attr(att); att = { x: obj.pair.attr("x")+shape.getBBox().width+(DE_ui_margin-2*DE_ui_padding) }; obj.pair.attr(att); att = { x: shape.attr("x")-(obj.getBBox().width+(DE_ui_margin-2*DE_ui_padding)) }; shape.attr(att); att = { x: shape.pair.attr("x")-(obj.getBBox().width+(DE_ui_margin-2*DE_ui_padding)) }; shape.pair.attr(att); } else { // right att = { x: obj.attr("x")-(shape.getBBox().width+(DE_ui_margin-2*DE_ui_padding)) }; obj.attr(att); att = { x: obj.pair.attr("x")-(shape.getBBox().width+(DE_ui_margin-2*DE_ui_padding)) }; obj.pair.attr(att); att = { x: shape.attr("x")+(obj.getBBox().width+(DE_ui_margin-2*DE_ui_padding)) }; shape.attr(att); att = { x: shape.pair.attr("x")+(obj.getBBox().width+(DE_ui_margin-2*DE_ui_padding)) }; shape.pair.attr(att); } // grid pos var tmp_pos = shape["grid_"]; shape["grid_"] = obj["grid_"]; obj["grid_"] = tmp_pos; for (key in DE_connections) { DE_paper.connection(DE_connections[key]); } } var DE_kbd_start_interface = function () { DE_kbd_focus_shape(DE_target_shapes[0]); DE_kbd_select_mode = true; } /****************************************************************************** * * undo/redo * */ var DE_undo = function () { var x = DE_undo_stack.pop(); if (!x) return; if (x[0] == "rm") { DE_undo_rm(x[1], x[2], x[3], x[4]); } else if (x[0] == "edit") { DE_undo_edit(x[1], x[2]); } else if (x[0] == "rm_conn") { DE_make_conn(DE_shapes_by_id[x[1]], DE_shapes_by_id[x[2]]); if (DE_shapes_by_id[x[2]] == DE_kbd_focused_phrase) { DE_connections[x[1]+"-"+x[2]].line.attr({"stroke":"#000","stroke-width":DE_ui_stroke_width_hi}); DE_ui_style_highlight(DE_shapes_by_id[x[1]]); } } else if (x[0] == "add_conn") { DE_rm_conn(x[1], x[2]); } else { return; } } var DE_undo_edit = function (id, text) { var obj = DE_shapes_by_id[id]; obj.pair.attr("text", text); obj.attr({"width": obj.pair.getBBox().width+(DE_ui_margin-DE_ui_padding)}); DE_snap_to_grid(); } var DE_undo_rm = function (grid_pos, id, text, source_phrases) { DE_target_shapes.sort(function(a, b) { return a["grid_"]-b["grid_"]; }); var j; var rightmost=0; var found = false; for (var i = 0; i=grid_pos) { if (!found) { j = i; found = true; } DE_target_shapes[i]["grid_"] += 1; } rightmost++; } if (!j) { j = rightmost; } var x = DE_ui_xbegin; if (DE_target_shapes[j]) { x = DE_target_shapes[j].attr("x")+DE_target_shapes[j].attr("width") +2*DE_ui_padding; } var obj = DE_make_obj(x, text, "target", grid_pos, id); obj["grid_"] = grid_pos; DE_snap_to_grid(); for (var i=0; i