123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 |
- /*
- * ext-arrows.js
- *
- * Licensed under the Apache License, Version 2
- *
- * Copyright(c) 2010 Alexis Deveria
- *
- */
-
- svgEditor.addExtension("Arrows", function(S) {
- var svgcontent = S.svgcontent,
- addElem = S.addSvgElementFromJson,
- nonce = S.nonce,
- randomize_ids = S.randomize_ids,
- selElems;
- svgCanvas.bind('setnonce', setArrowNonce);
- svgCanvas.bind('unsetnonce', unsetArrowNonce);
-
- var lang_list = {
- "en":[
- {"id": "arrow_none", "textContent": "No arrow" }
- ],
- "fr":[
- {"id": "arrow_none", "textContent": "Sans flèche" }
- ]
- };
-
- var prefix = 'se_arrow_';
- if (randomize_ids) {
- var arrowprefix = prefix + nonce + '_';
- } else {
- var arrowprefix = prefix;
- }
- var pathdata = {
- fw: {d:"m0,0l10,5l-10,5l5,-5l-5,-5z", refx:8, id: arrowprefix + 'fw'},
- bk: {d:"m10,0l-10,5l10,5l-5,-5l5,-5z", refx:2, id: arrowprefix + 'bk'}
- }
-
- function setArrowNonce(window, n) {
- randomize_ids = true;
- arrowprefix = prefix + n + '_';
- pathdata.fw.id = arrowprefix + 'fw';
- pathdata.bk.id = arrowprefix + 'bk';
- }
- function unsetArrowNonce(window) {
- randomize_ids = false;
- arrowprefix = prefix;
- pathdata.fw.id = arrowprefix + 'fw';
- pathdata.bk.id = arrowprefix + 'bk';
- }
- function getLinked(elem, attr) {
- var str = elem.getAttribute(attr);
- if(!str) return null;
- var m = str.match(/\(\#(.*)\)/);
- if(!m || m.length !== 2) {
- return null;
- }
- return S.getElem(m[1]);
- }
-
- function showPanel(on) {
- $('#arrow_panel').toggle(on);
-
- if(on) {
- var el = selElems[0];
- var end = el.getAttribute("marker-end");
- var start = el.getAttribute("marker-start");
- var mid = el.getAttribute("marker-mid");
- var val;
-
- if(end && start) {
- val = "both";
- } else if(end) {
- val = "end";
- } else if(start) {
- val = "start";
- } else if(mid) {
- val = "mid";
- if(mid.indexOf("bk") != -1) {
- val = "mid_bk";
- }
- }
-
- if(!start && !mid && !end) {
- val = "none";
- }
-
- $("#arrow_list").val(val);
- }
- }
-
- function resetMarker() {
- var el = selElems[0];
- el.removeAttribute("marker-start");
- el.removeAttribute("marker-mid");
- el.removeAttribute("marker-end");
- }
-
- function addMarker(dir, type, id) {
- // TODO: Make marker (or use?) per arrow type, since refX can be different
- id = id || arrowprefix + dir;
-
- var marker = S.getElem(id);
- var data = pathdata[dir];
-
- if(type == "mid") {
- data.refx = 5;
- }
- if(!marker) {
- marker = addElem({
- "element": "marker",
- "attr": {
- "viewBox": "0 0 10 10",
- "id": id,
- "refY": 5,
- "markerUnits": "strokeWidth",
- "markerWidth": 5,
- "markerHeight": 5,
- "orient": "auto",
- "style": "pointer-events:none" // Currently needed for Opera
- }
- });
- var arrow = addElem({
- "element": "path",
- "attr": {
- "d": data.d,
- "fill": "#000000"
- }
- });
- marker.appendChild(arrow);
- S.findDefs().appendChild(marker);
- }
-
- marker.setAttribute('refX', data.refx);
-
- return marker;
- }
-
- function setArrow() {
- var type = this.value;
- resetMarker();
-
- if(type == "none") {
- return;
- }
-
- // Set marker on element
- var dir = "fw";
- if(type == "mid_bk") {
- type = "mid";
- dir = "bk";
- } else if(type == "both") {
- addMarker("bk", type);
- svgCanvas.changeSelectedAttribute("marker-start", "url(#" + pathdata.bk.id + ")");
- type = "end";
- dir = "fw";
- } else if (type == "start") {
- dir = "bk";
- }
-
- addMarker(dir, type);
- svgCanvas.changeSelectedAttribute("marker-"+type, "url(#" + pathdata[dir].id + ")");
- S.call("changed", selElems);
- }
-
- function colorChanged(elem) {
- var color = elem.getAttribute('stroke');
-
- var mtypes = ['start','mid','end'];
- var defs = S.findDefs();
-
- $.each(mtypes, function(i, type) {
- var marker = getLinked(elem, 'marker-'+type);
- if(!marker) return;
-
- var cur_color = $(marker).children().attr('fill');
- var cur_d = $(marker).children().attr('d');
- var new_marker = null;
- if(cur_color === color) return;
-
- var all_markers = $(defs).find('marker');
- // Different color, check if already made
- all_markers.each(function() {
- var attrs = $(this).children().attr(['fill', 'd']);
- if(attrs.fill === color && attrs.d === cur_d) {
- // Found another marker with this color and this path
- new_marker = this;
- }
- });
-
- if(!new_marker) {
- // Create a new marker with this color
- var last_id = marker.id;
- var dir = last_id.indexOf('_fw') !== -1?'fw':'bk';
-
- new_marker = addMarker(dir, type, arrowprefix + dir + all_markers.length);
- $(new_marker).children().attr('fill', color);
- }
-
- $(elem).attr('marker-'+type, "url(#" + new_marker.id + ")");
-
- // Check if last marker can be removed
- var remove = true;
- $(S.svgcontent).find('line, polyline, path, polygon').each(function() {
- var elem = this;
- $.each(mtypes, function(j, mtype) {
- if($(elem).attr('marker-' + mtype) === "url(#" + marker.id + ")") {
- return remove = false;
- }
- });
- if(!remove) return false;
- });
-
- // Not found, so can safely remove
- if(remove) {
- $(marker).remove();
- }
- });
-
- }
-
- return {
- name: "Arrows",
- context_tools: [{
- type: "select",
- panel: "arrow_panel",
- title: "Select arrow type",
- id: "arrow_list",
- options: {
- none: "No arrow",
- end: "---->",
- start: "<----",
- both: "<--->",
- mid: "-->--",
- mid_bk: "--<--"
- },
- defval: "none",
- events: {
- change: setArrow
- }
- }],
- callback: function() {
- $('#arrow_panel').hide();
- // Set ID so it can be translated in locale file
- $('#arrow_list option')[0].id = 'connector_no_arrow';
- },
- addLangData: function(lang) {
- return {
- data: lang_list[lang]
- };
- },
- selectedChanged: function(opts) {
-
- // Use this to update the current selected elements
- selElems = opts.elems;
-
- var i = selElems.length;
- var marker_elems = ['line','path','polyline','polygon'];
-
- while(i--) {
- var elem = selElems[i];
- if(elem && $.inArray(elem.tagName, marker_elems) != -1) {
- if(opts.selectedElement && !opts.multiselected) {
- showPanel(true);
- } else {
- showPanel(false);
- }
- } else {
- showPanel(false);
- }
- }
- },
- elementChanged: function(opts) {
- var elem = opts.elems[0];
- if(elem && (
- elem.getAttribute("marker-start") ||
- elem.getAttribute("marker-mid") ||
- elem.getAttribute("marker-end")
- )) {
- // var start = elem.getAttribute("marker-start");
- // var mid = elem.getAttribute("marker-mid");
- // var end = elem.getAttribute("marker-end");
- // Has marker, so see if it should match color
- colorChanged(elem);
- }
-
- }
- };
- });
|