/* 
 | 
 * ext-arrows.js 
 | 
 * 
 | 
 * Licensed under the Apache License, Version 2 
 | 
 * 
 | 
 * Copyright(c) 2010 Alexis Deveria 
 | 
 * 
 | 
 */ 
 | 
  
 | 
  
 | 
methodDraw.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); 
 | 
        } 
 | 
         
 | 
      } 
 | 
    }; 
 | 
}); 
 |