|  |  | 
 |  |  |  * | 
 |  |  |  * Licensed under the Apache License, Version 2 | 
 |  |  |  * | 
 |  |  |  * Copyright(c) 2010 Will Schleter  | 
 |  |  |  * Copyright(c) 2010 Will Schleter | 
 |  |  |  *   based on ext-arrows.js by Copyright(c) 2010 Alexis Deveria | 
 |  |  |  * | 
 |  |  |  * This extension provides for the addition of markers to the either end | 
 |  |  |  * or the middle of a line, polyline, path, polygon.  | 
 |  |  |  *  | 
 |  |  |  * or the middle of a line, polyline, path, polygon. | 
 |  |  |  * | 
 |  |  |  * Markers may be either a graphic or arbitary text | 
 |  |  |  *  | 
 |  |  |  * | 
 |  |  |  * to simplify the coding and make the implementation as robust as possible, | 
 |  |  |  * markers are not shared - every object has its own set of markers. | 
 |  |  |  * this relationship is maintained by a naming convention between the | 
 |  |  |  * ids of the markers and the ids of the object | 
 |  |  |  *  | 
 |  |  |  * | 
 |  |  |  * The following restrictions exist for simplicty of use and programming | 
 |  |  |  *    objects and their markers to have the same color | 
 |  |  |  *    marker size is fixed | 
 |  |  |  *    text marker font, size, and attributes are fixed | 
 |  |  |  *    an application specific attribute - se_type - is added to each marker element | 
 |  |  |  *        to store the type of marker | 
 |  |  |  *         | 
 |  |  |  * | 
 |  |  |  * TODO: | 
 |  |  |  *    remove some of the restrictions above | 
 |  |  |  *    add option for keeping text aligned to horizontal | 
 |  |  | 
 |  |  |  | 
 |  |  |   var marker_prefix = 'se_marker_'; | 
 |  |  |   var id_prefix = 'mkr_'; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |   // note - to add additional marker types add them below with a unique id | 
 |  |  |   // and add the associated icon(s) to marker-icons.svg | 
 |  |  |   // the geometry is normallized to a 100x100 box with the origin at lower left | 
 |  |  |   // Safari did not like negative values for low left of viewBox | 
 |  |  |   // remember that the coordinate system has +y downward | 
 |  |  |   var marker_types = { | 
 |  |  |     nomarker: {},   | 
 |  |  |     leftarrow:   | 
 |  |  |     nomarker: {}, | 
 |  |  |     leftarrow: | 
 |  |  |       {element:'path', attr:{d:'M0,50 L100,90 L70,50 L100,10 Z'}}, | 
 |  |  |     rightarrow: | 
 |  |  |       {element:'path', attr:{d:'M100,50 L0,90 L30,50 L0,10 Z'}}, | 
 |  |  | 
 |  |  |     mcircle: | 
 |  |  |       {element:'circle', attr:{r:30, cx:50, cy:50}} | 
 |  |  |   } | 
 |  |  |    | 
 |  |  |    | 
 |  |  |  | 
 |  |  |  | 
 |  |  |   var lang_list = { | 
 |  |  |     "en":[ | 
 |  |  |       {id: "start_marker_list", title: "Select start marker type" }, | 
 |  |  | 
 |  |  |   $.each(['leftarrow','rightarrow','box','star','mcircle','triangle'],function(i,v) { | 
 |  |  |     marker_types[v+'_o'] = marker_types[v]; | 
 |  |  |   }); | 
 |  |  |    | 
 |  |  |  | 
 |  |  |   // elem = a graphic element will have an attribute like marker-start | 
 |  |  |   // attr - marker-start, marker-mid, or marker-end | 
 |  |  |   // returns the marker element that is linked to the graphic element | 
 |  |  | 
 |  |  |             txtbox.hide() // hide text box | 
 |  |  |           } | 
 |  |  |         } | 
 |  |  |         txtbox.val(val);         | 
 |  |  |         txtbox.val(val); | 
 |  |  |         setIcon(pos,ci); | 
 |  |  |       }) | 
 |  |  |     } | 
 |  |  |   }  | 
 |  |  |   } | 
 |  |  |  | 
 |  |  |   function addMarker(id, val) { | 
 |  |  |     var txt_box_bg = '#ffffff'; | 
 |  |  |     var txt_box_border = 'none'; | 
 |  |  |     var txt_box_stroke_width = 0; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |     var marker = S.getElem(id); | 
 |  |  |  | 
 |  |  |     if (marker) return; | 
 |  |  |  | 
 |  |  |     if (val=='' || val=='\\nomarker') return; | 
 |  |  |  | 
 |  |  |     var el = selElems[0];     | 
 |  |  |     var el = selElems[0]; | 
 |  |  |     var color = el.getAttribute('stroke'); | 
 |  |  |     //NOTE: Safari didn't like a negative value in viewBox | 
 |  |  |     //so we use a standardized 0 0 100 100 | 
 |  |  | 
 |  |  |     else se_type='textmarker'; | 
 |  |  |  | 
 |  |  |     if (!marker_types[se_type]) return; // an unknown type! | 
 |  |  |      | 
 |  |  |  | 
 |  |  |     // create a generic marker | 
 |  |  |     marker = addElem({ | 
 |  |  |       "element": "marker", | 
 |  |  | 
 |  |  |       marker.setAttribute("orient",0); | 
 |  |  |       marker.appendChild(box); | 
 |  |  |       marker.appendChild(text); | 
 |  |  |     }  | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     marker.setAttribute("viewBox",viewBox); | 
 |  |  |     marker.setAttribute("markerWidth", markerWidth); | 
 |  |  | 
 |  |  |       var m = elem.getAttribute(nam); | 
 |  |  |       if (m) pline.setAttribute(nam,elem.getAttribute(nam)); | 
 |  |  |     }); | 
 |  |  |      | 
 |  |  |  | 
 |  |  |     var batchCmd = new S.BatchCommand(); | 
 |  |  |     batchCmd.addSubCommand(new S.RemoveElementCommand(elem, elem.parentNode)); | 
 |  |  |     batchCmd.addSubCommand(new S.InsertElementCommand(pline)); | 
 |  |  |      | 
 |  |  |  | 
 |  |  |     $(elem).after(pline).remove(); | 
 |  |  |     svgCanvas.clearSelection(); | 
 |  |  |     pline.id = id; | 
 |  |  | 
 |  |  |     //if (val.substr(0,1)=='\\') txtbox.hide(); | 
 |  |  |     //else txtbox.show(); | 
 |  |  |   } | 
 |  |  |    | 
 |  |  |  | 
 |  |  |   function setIcon(pos,id) { | 
 |  |  |     if (id.substr(0,1)!='\\') id='\\textmarker' | 
 |  |  |     var ci = '#'+id_prefix+pos+'_'+id.substr(1); | 
 |  |  |     methodDraw.setIcon('#cur_' + pos +'_marker_list', $(ci).children()); | 
 |  |  |     $(ci).addClass('current').siblings().removeClass('current'); | 
 |  |  |   } | 
 |  |  |      | 
 |  |  |  | 
 |  |  |   function setMarkerSet(obj) { | 
 |  |  |     var parts = this.id.split('_'); | 
 |  |  |     var set = parts[2]; | 
 |  |  | 
 |  |  |       break; | 
 |  |  |     } | 
 |  |  |   } | 
 |  |  |      | 
 |  |  |  | 
 |  |  |   function showTextPrompt(pos) { | 
 |  |  |     var def = $('#'+pos+'_marker').val(); | 
 |  |  |     if (def.substr(0,1)=='\\') def=''; | 
 |  |  |     $.prompt('Enter text for ' + pos + ' marker', def , function(txt) { if (txt) triggerTextEntry(pos,txt); }); | 
 |  |  |   } | 
 |  |  |    | 
 |  |  |  | 
 |  |  |   // callback function for a toolbar button click | 
 |  |  |   function setArrowFromButton(obj) { | 
 |  |  |      | 
 |  |  |  | 
 |  |  |     var parts = this.id.split('_'); | 
 |  |  |     var pos = parts[1]; | 
 |  |  |     var val = parts[2]; | 
 |  |  |     if (parts[3]) val+='_'+parts[3]; | 
 |  |  |      | 
 |  |  |  | 
 |  |  |     if (val!='textmarker') { | 
 |  |  |       triggerTextEntry(pos,'\\'+val); | 
 |  |  |     } else { | 
 |  |  |       showTextPrompt(pos); | 
 |  |  |     } | 
 |  |  |   } | 
 |  |  |    | 
 |  |  |  | 
 |  |  |   function getTitle(lang,id) { | 
 |  |  |     var list = lang_list[lang]; | 
 |  |  |     for (var i in list) { | 
 |  |  | 
 |  |  |     } | 
 |  |  |     return id; | 
 |  |  |   } | 
 |  |  |    | 
 |  |  |    | 
 |  |  |  | 
 |  |  |  | 
 |  |  |   // build the toolbar button array from the marker definitions | 
 |  |  |   // TODO: need to incorporate language specific titles | 
 |  |  |   function buildButtonList() { | 
 |  |  | 
 |  |  |     } ], | 
 |  |  |     callback: function() { | 
 |  |  |       $('#marker_panel').addClass('toolset').hide(); | 
 |  |  |        | 
 |  |  |  | 
 |  |  |     }, | 
 |  |  |     addLangData: function(lang) { | 
 |  |  |       return { data: lang_list[lang] }; | 
 |  |  | 
 |  |  |     } | 
 |  |  |   }, | 
 |  |  |  | 
 |  |  |   elementChanged: function(opts) {     | 
 |  |  |   elementChanged: function(opts) { | 
 |  |  |     //console.log('elementChanged',opts); | 
 |  |  |     var elem = opts.elems[0]; | 
 |  |  |     if(elem && ( |