123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865 |
- /*******************************************************************************
- AToMPM - A Tool for Multi-Paradigm Modelling
- Copyright (c) 2011 Raphael Mannadiar (raphael.mannadiar@mail.mcgill.ca)
- Modified by Conner Hansen (chansen@crimson.ua.edu)
- This file is part of AToMPM.
- AToMPM is free software: you can redistribute it and/or modify it under the
- terms of the GNU Lesser General Public License as published by the Free Software
- Foundation, either version 3 of the License, or (at your option) any later
- version.
- AToMPM is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public License along
- with AToMPM. If not, see <http://www.gnu.org/licenses/>.
- *******************************************************************************/
- /*TODO: look into reworking naming convention to be more intuitive
- *ie:
- * button: btn_someFunc
- * window: wnd_someFunc
- * private: _someFunc
- * etc
- */
- /* NOTES:
- NAMING CONVENTION... functions and variables starting with '_' are meant to
- be used from within Button code (most of them are directly associated to a
- native back-end operation)... functions starting with '__' are meant to be
- private and should only be used from within application code
- WINDOW TITLE... window titles are set to pretty-print '__saveas'... if any
- changelogs have been received since we loaded/saved the model, the title is
- changed to explicit this
- the BACKDOOR API section contains methods that are accessible from the
- backend (or from anyone who has access to the backend, e.g., a synthesized
- application)... they are all void (i.e., they don't return anything or any
- feedback to the 'caller') and should only be accessed remotely, via
- 'PUT /GET/console {CLIENT_BDAPI:...}' to the backend
-
- TBI:: add caching mechanism to avoid recompiling the same icon models into
- the same SVG over and over
- TBI:: add helper functions for parsing and manipulating path strings (see
- Raphael.parsePathString()... not only would this elevate abstraction,
- but a lot of our connection-related operations could be optimized
- (including less string matching and splitting) if segments were arrays
- of points rather than strings
- TBI:: when SVG 1.2 gets Chrome support, the __SVG_TEXT_EDITOR dialog could be
- removed in favor of native SVG text editing facilities */
- /******************************** GLOBAL VARS *********************************/
- var __user = undefined,
- __wid,
- __aswid,
- __prefs,
- __typeToCreate,
- __loadedToolbars = {},
- __icons = {},
- __edges = {},
- __canvas,
- __saveas;
- /******************************** GLOBAL VARS *********************************/
- AtomPMClient = function(){
-
- /**
- * Log deprecated function calls
- */
- this.alertDeprecatedFunctionCall = function( funcName ){
- console.warn("Deprecated function call: " + funcName);
- };
-
- return this;
- }();
- /**
- * Automatically saves the current model.
- *
- * If mode == backup, save the current model into a backup file
- * If mode == overwrite, overwrite the current file model
- */
- function __autosave(mode)
- {
- if( mode == 'backup' )
- {
- if( __saveas )
- {
- var matches = __saveas.match(/(.*\/)(.*)/);
- _saveModel(matches[1]+'.autosave.'+matches[2],true,true);
- }
- else
- _saveModel(undefined,true,true);
- }
- else if( mode == 'overwrite' )
- _saveModel(undefined,false,true);
- }
- /**
- * Launches the autosave daemon, which automatically tries to
- * save the model based on the interval stored in the preferences
- * array
- */
- function __launchAutosave()
- {
- if( __prefs['autosave-delay']['value'] > 0 )
- window.setInterval(
- __autosave,
- __prefs['autosave-delay']['value'] * 1000,
- __prefs['autosave-mode']['value']);
- }
- /********************************* 'USER' API *********************************/
- /**
- * Creates an SVG blob out of the current SVG elements on the canvas
- *
- * Note 1: an alternative to the current implementation (though less
- * efficient) would be to POST the data to the server and then have
- * the returned file be downloadable
- *
- * Note 2: a click is simulated instead of using
- * window.location.assign() so that the target filename can be
- * chosen
- *
- * Note 3: the output width of the image is altered in order to fit
- * the content. This would be fixed if we utilized a dynamically
- * expanding canvas
- *
- * Note 4: the 'href' tags are changed to 'xlink:href' tags in the
- * generated SVG file. All images are embedded as data uris in the
- * output in order to increase robustness.
- */
- function _exportSVG(fname)
- {
- var BlobBuilder = window.WebKitBlobBuilder || window.MozBlobBuilder,
- URL = window.URL || window.webkitURL,
- a = $('<a>'),
- bb = undefined,
- iconsbbox = __getGlobalBBox(
- utils.keys(__icons).concat(utils.keys(__edges)) ),
- svg = $('#div_canvas').html().
- replace(/^(<svg.*? width=")(.*?)(".*?>)/,
- '$1'+(2*iconsbbox.x+iconsbbox.width)+'$3').
- replace(/^(<svg.*? height=")(.*?)(".*?>)/,
- '$1'+(2*iconsbbox.y+iconsbbox.height)+'$3'),
- exportSVG =
- function()
- {
- bb = new Blob([svg], {"type": "text\/xml"});
- a.attr("href", URL.createObjectURL(bb));
- a.attr("download", fname || "model.svg");
- a.get(0).click();
- URL.revokeObjectURL(a.href);
- };
- if( (images = svg.match(/<image.*? href=".*?".*?>/g)) )
- {
- var datauris = [];
- images.forEach(
- function(image,i)
- {
- HttpUtils.imageToDataURI(
- image.match(/^<image.*? href="(.*?)".*?>$/)[1],
- function(datauri)
- {
- datauris[i] = datauri;
- if( datauris.length == images.length &&
- ! utils.contains(datauris,undefined) )
- {
- svg = svg.replace(
- /(<image.*? )href=".*?"(.*?>)/g,
- function(p0,p1,p2)
- {
- return p1+' xlink:href="'+datauris.shift()+'"'+p2;
- });
- exportSVG();
- }
- });
- });
- }
- else
- exportSVG();
- }
- /**
- * Retrieves the value that matches the subset, and then passes
- * it back into the callback function
- *
- * @param callback the function that the value is passed to
- * @param subset the matching preference entry
- */
- function _getUserPreferences(callback,subset)
- {
- console.debug("Get User Preferences");
- console.debug(subset);
- HttpUtils.httpReq(
- 'GET',
- HttpUtils.url('/prefs',__NO_WID),
- (subset == undefined ?
- undefined :
- '?subset='+encodeURIComponent(utils.jsons(subset))),
- function(statusCode,resp)
- {
- console.debug("Callback Get User Preferences");
- console.debug(statusCode);
- console.debug(resp);
- if( ! utils.isHttpSuccessCode(statusCode) )
- UserManagement.logout();
- else
- callback(utils.jsonp(resp));
- });
- }
- /**
- * Generates an HTTP request
- *
- * @param method GET/DELETE/POST/PUT
- * @param url the URL to hit
- * @param params the parameters to pass in
- * @param onresponse the callback function to perform on response
- * @param sync whether or not this request is synchronous
- */
- function _httpReq(method,url,params,onresponse,sync)
- {
- if( method != 'GET' )
- BehaviorManager.handleUserEvent(__EVENT_CODED_CANVAS_EDIT);
- HttpUtils.httpReq(method,url,params,onresponse,sync);
- }
- /**
- * Inserts another model into the current canvas
- */
- function _insertModel(fname)
- {
- if( ! __isModel(fname) )
- WindowManagement.openDialog(
- _ERROR,
- 'invalid extension... loadable models are "*.model" files');
- else
- DataUtils.loadm(fname,true);
- }
- /**
- * Loads a model from the selected file name. This automatically
- * strips out the .autosave portion of the filename, if it is
- * present
- *
- * @param fname the name of the file to load
- */
- function _loadModel(fname)
- {
- if( ! __isModel(fname) )
- WindowManagement.openDialog(
- _ERROR,
- 'invalid extension... loadable models are "*.model" files');
- else
- {
- if( (matches = fname.match(/(.*)\.autosave\.(.+\.model)/)) )
- __saveas = matches[1]+matches[2];
- else
- __saveas = fname;
- DataUtils.loadm(fname);
- }
- }
- /**
- * Loads a new toolbar onto the current canvas
- * @param fname the name of the file to load
- */
- function _loadToolbar(fname)
- {
- if( __isButtonModel(fname) )
- DataUtils.loadbm(fname);
- else if( __isIconMetamodel(fname) )
- DataUtils.loadmm(fname);
- }
- /* save model
- 1. if no filename is specified,
- a) if autosave is specified,
- - if __saveas is specified, use it
- - otherwise, use __DEFAULT_SAVEAS
- b) else, ask the user to choose a file to save to (first time user saves a model)
- 2. otherwise, if an incorrect filename is specified, show error and return
- 3. save model
- 4. if this isn't an automated backup (i.e., the backup flag is unset),
- remember filename in __saveas and adjust window title to reflect fact that
- all changes are saved */
- function _saveModel(fname,backup,autosave)
- {
- if( fname == undefined ) {
- if (!autosave && (__saveas == undefined || __saveas == null)) {
- var options = {'extensions':['\\.model'],
- 'multipleChoice':false,
- 'manualInput':true,
- 'title':'specify target model',
- 'startDir':'model'},
- callback =
- function(fnames)
- {
- _saveModel(fnames[0]);
- };
- WindowManagement.openDialog(_FILE_BROWSER,options,callback);
- return;
- } else {
- fname = (__saveas || __DEFAULT_SAVEAS);
- }
- } else if( ! __isModel(fname) ) {
- WindowManagement.openDialog(
- _ERROR,
- 'invalid extension... models must be saved as "*.model" files');
- return;
- }
- DataUtils.savem(fname);
- if( ! backup )
- {
- __saveas = fname;
- WindowManagement.setWindowTitle();
- }
- }
- /* TBI::
- . unselect invisible items
- . remember visibility settings s.t. newly created items (e.g., by
- collaborator) inherit them */
- function _setInvisibleMetamodels(mms)
- {
- mms = mms.map( function(mm) {return mm.match(/(.*)\.metamodel/)[1]} );
- function hideOrShow(uri,icon)
- {
- if( ! mms.some(
- function(mm)
- {
- if( uri.match(mm+'/') )
- {
- icon.hide();
- return true;
- }
- }) )
- icon.show();
- }
- for( var uri in __icons )
- hideOrShow(uri,__icons[uri]['icon']);
- for( var uri in __edges )
- hideOrShow(uri,__edges[uri]['icon']);
- }
- /**
- * Updates the current user preferences and then
- * executes the passed in callback function
- *
- * @param prefs the new user preferences
- * @param callback the function to be executed
- */
- function _setUserPreferences(prefs,callback)
- {
- HttpUtils.httpReq(
- 'PUT',
- HttpUtils.url('/prefs',__NO_WID),
- prefs,
- function(statusCode,resp)
- {
- if( ! utils.isHttpSuccessCode(statusCode) )
- WindowManagement.openDialog(_ERROR, 'failed to update user preferences :: '+resp);
- else if( callback )
- callback();
- });
- }
- /**
- * Creates a new formalism under /Formalisms/ with the specified name.
- *
- * @param formalism_name the name of the new formalism
- */
- function _newFormalism(formalism_name) {
- HttpUtils.httpReq(
- 'POST',
- window.localStorage.getItem('user') + "/" + formalism_name + '.formalism',
- undefined,
- function(statusCode,resp)
- {
- if( ! utils.isHttpSuccessCode(statusCode) ) {
- WindowManagement.openDialog(_ERROR, 'failed to create new formalism :: '+resp);
- } else {
- WindowManagement.spawnClient("/Formalisms/" + formalism_name + "/" + formalism_name + ".model")
- WindowManagement.spawnClient("/Formalisms/" + formalism_name + "/" + formalism_name + ".defaultIcons.model")
- }
- });
- }
- /**
- * Creates a new transformation on the specified location.
- *
- * @param transformation_loc the location of the new transformation
- */
- function _newTransformation(transformation_loc) {
- if (transformation_loc.match(/.*\/T_.*\.model$/)) {
- HttpUtils.httpReq(
- 'POST',
- window.localStorage.getItem('user') + transformation_loc + '.transformation',
- undefined,
- function(statusCode,resp)
- {
- if( ! utils.isHttpSuccessCode(statusCode) ) {
- WindowManagement.openDialog(_ERROR, 'failed to create new transformation :: '+resp);
- } else {
- WindowManagement.spawnClient(transformation_loc)
- }
- });
- } else {
- WindowManagement.openDialog(_ERROR, 'failed to create new transformation :: '+transformation_loc+" is not a valid transformation name");
- }
- }
- /**
- * Creates a new rule on the specified location.
- *
- * @param rule_loc the location of the new rule
- */
- function _newRule(rule_loc) {
- if (rule_loc.match(/.*\/R_.*\.model$/)) {
- HttpUtils.httpReq(
- 'POST',
- window.localStorage.getItem('user') + rule_loc + '.rule',
- undefined,
- function(statusCode,resp)
- {
- if( ! utils.isHttpSuccessCode(statusCode) ) {
- WindowManagement.openDialog(_ERROR, 'failed to create new rule :: '+resp);
- } else {
- WindowManagement.spawnClient(rule_loc)
- }
- });
- } else {
- WindowManagement.openDialog(_ERROR, 'failed to create new rule :: '+rule_loc+" is not a valid rule name");
- }
- }
- /**
- * Sets the current type of entity to be created
- * @param fulltype the type to be created
- */
- function _setTypeToCreate(fulltype)
- {
- __typeToCreate = fulltype;
- }
- /**
- * Unloads the selected toolbar from the current canvas
- * @param tb the toolbar to be unloaded
- */
- function _unloadToolbar(tb)
- {
- if( __isButtonModel(tb) )
- DataUtils.unloadbm(tb);
- else if( __isIconMetamodel(tb) )
- DataUtils.unloadmm(tb);
- }
- /**
- * Validates the current model
- */
- function _validate()
- {
- HttpUtils.httpReq(
- 'GET',
- HttpUtils.url('/validatem',__NO_USERNAME));
- }
- /******************************* 'BACKDOOR' API *******************************/
- /* highlight the specified node or unhighlight any highlighted nodes... the
- 'followCrossFormalismLinks' parameter indicates whether or not (and which)
- neighbors along cross-formalism links should also be highlighted... the
- 'timeout' parameter, if specified, indicates the duration of the highlight */
- function _highlight(args/*asid[,followCrossFormalismLinks,timeout]*/)
- {
- if( args == undefined )
- __unhighlight();
- else
- {
- var uri = __asid2csuri(args['asid']),
- fcfl = args['followCrossFormalismLinks'],
- timeout = args['timeout'];
- __highlight(uri,fcfl,timeout);
- }
- }
- function _highlightState(args/*asid[,followCrossFormalismLinks,timeout]*/)
- {
- var uri = __asid2csuri(args['asid']),
- fcfl = args['followCrossFormalismLinks'],
- timeout = args['timeout'];
- __highlight(uri,fcfl,timeout);
- }
- /* unhighlight any highlighted nodes - sadaf */
- function _unhighlight()
- {
- __unhighlight();
- }
- /* unhighlight any highlighted nodes - sadaf */
- function _unhighlightState(args/*asid*/)
- {
- //var uri = __asid2csuri(args['asid']);
- //__icons[uri]['icon'].unhighlight();
- __unhighlight(__asid2csuri(args['asid']));
- }
- /* interface to WindowManagement.spawnClient() 'USER' API function */
- function _loadModelInNewWindow(args/*fname[,callback-url]*/)
- {
- WindowManagement.spawnClient(args['fname'],args['callback-url']);
- }
- /* tag the specified node with some text, possibly appending it to an existing
- tag... the 'timeout' parameter, if specified, indicates how long the tag
- should be displayed */
- function _tag(args/*asid,text[,style,append,timeout]*/)
- {
- var uri = __asid2csuri(args['asid']),
- text = args['text'],
- style = utils.mergeDicts(
- [{'font-size':'16px', 'font-style':'italic', 'fill':'#ffffff'},
- args['style']]),
- append = args['append'],
- timeout = args['timeout'];
- __tag(uri,text,style,append,timeout);
- }
- /* update an attribute of the specified node, possibly highlighting the node to
- indicate the change (note that this doesn't unhighlight any currently
- highlighted nodes) */
- function _updateAttr(args/*asid,attr,val[,highlight]*/)
- {
- var uri = __asid2csuri(args['asid']),
- changes = {};
- changes[args['attr']] = args['val'];
- DataUtils.update(uri,changes);
- if( args['highlight'] )
- __flash(uri);
- }
- /******************************** CRUD QUERIES ********************************/
- /*************************** HANDLE QUERY RESPONSE ****************************/
- /***************************** EDIT CONFLICTS... ******************************/
- var __watchList = {};
- function __changed(uri,set)
- {
- if( set )
- __watchList[uri] = __EDIT_CONFLICT;
- else
- return __watchList[uri] == __EDIT_CONFLICT;
- }
- //TBC place calls to this appropriately (with CS/AS uris...)
- function __unwatch(uri)
- {
- delete __watchList[uri];
- }
- //TBC place calls to this appropriately (with CS/AS uris...)
- function __watch(uri)
- {
- __watchList[uri] = __NO_CONFLICT;
- }
- function __watching(uri)
- {
- return uri in __watchList;
- }
- /***************************** MMM-RELATED LOGIC ******************************/
- /**************************** CANVAS BEHAVIOUR... *****************************/
- /*------------------------ BEHAVIOUR-RELATED UTILITIES -----------------------*/
- /*------------------------- SELECTING ICONS/EDGES... -------------------------*/
- /*--------------------------- DRAWING CONNECTIONS ----------------------------*/
- /*------------------------------ HIGHLIGHTING --------------------------------*/
- /*--------------------------------- TAGGING ----------------------------------*/
- /* tag the specified node and setup delayed tag removal, when applicable */
- function __tag(uri,text,style,append,timeout)
- {
- __icons[uri]['icon'].tag(text,style,append);
- if( timeout != undefined )
- window.setTimeout(__icons[uri]['icon'].tag,timeout,'');
- }
- /*------------------------------- LAYERING... --------------------------------*/
- function __iconToBack(tgt)
- {
- __icons[__vobj2uri(tgt)]['icon'].toBack();
- }
- function __iconToFront(tgt)
- {
- __icons[__vobj2uri(tgt)]['icon'].toFront();
- }
- /*---------------------------- SELECTION OVERLAY -----------------------------*/
- /*---------------- GEOMETRY CONTROLS AND TRANSFORMATIONS... ------------------*/
- /*-------------------------- CONNECTION EDITING... ---------------------------*/
- /************************* GRAPH TRAVERSAL UTILITIES **************************/
- /* return the ids of edges connected to the specified node */
- function __getConnectedEdges(uri)
- {
- var edgeIds = [];
- for( var edgeId in __edges )
- if( __edges[edgeId]['start'] == uri ||
- __edges[edgeId]['end'] == uri )
- edgeIds.push(edgeId);
- return edgeIds;
- }
- /* given an edge, returns an array containing that edge's start and/or end
- linktype(s), and its(their) connected edges (which include the given edge) */
- function __getConnectionParticipants(edgeId)
- {
- var start = __edges[edgeId]['start'],
- end = __edges[edgeId]['end'],
- cm = [];
- if( __isConnectionType(start) )
- cm = cm.concat(start, __getConnectedEdges(start));
- if( __isConnectionType(end) )
- cm = cm.concat(end, __getConnectedEdges(end));
- return cm;
- }
- /* return all of the edges and nodes directly or indirectly connected to 'uri'
- via cross-formalism links in direction 'dir'... the meaning of 'dir' follows
- from the convention that cross-formalism link go from higher-level constructs
- to lower-level ones
-
- 1. filter __edges keeping only cross-formalism ones
- 2. if dir is '*' or 'DOWN', recursively navigate the edges from step 1.
- out of 'uri' marking appropriate nodes and edges
- 3. if dir is '*' or 'UP', recursively navigate the edges from step 1.
- into 'uri' marking appropriate nodes and edges */
- function __getCrossFormalismNeighbors(uri,dir)
- {
- var crossFormalismEdges = [];
- for( var edgeId in __edges )
- if( __getMetamodel(__edges[edgeId]['start']) !=
- __getMetamodel(__edges[edgeId]['end']) )
- crossFormalismEdges.push(edgeId);
- function _(neighbors,lookfor,append)
- {
- var tovisit = [uri];
- while( tovisit.length > 0 )
- {
- var curr = tovisit.shift();
-
- neighbors.nodes.push(curr);
- crossFormalismEdges.forEach(
- function(edgeId)
- {
- if( __edges[edgeId][lookfor] == curr )
- {
- var ext = __edges[edgeId][append];
- if( ! utils.contains(neighbors.nodes,ext) )
- tovisit.push(ext);
- if( ! utils.contains(neighbors.edges,edgeId) )
- neighbors.edges.push(edgeId);
- }
- });
- }
- return neighbors;
- }
- var dn = {'nodes':[],'edges':[]}, un = {'nodes':[],'edges':[]};
- if( dir == '*' || dir == 'DOWN' )
- _(dn,'start','end');
- if( dir == '*' || dir == 'UP' )
- _(un,'end','start');
- return {'nodes':utils.toSet(dn.nodes.concat(un.nodes)),
- 'edges':utils.toSet(dn.nodes.concat(un.nodes))};
- }
- /***************************** HTML-GUI UTILITIES *****************************/
- /****************************** SVG... UTILITIES ******************************/
- /******************************* MISC UTILITIES *******************************/
- /* returns the csuri associated to the given asid */
- function __asid2csuri(asid)
- {
- for( var uri in __icons )
- if( __icons[uri]['icon'].getAttr('__asuri').
- match(/.*\/(.*)\.instance/)[1] == asid )
- return uri;
- }
- /* returns the edgeId associated to the given edge DOM element */
- function __edge2edgeId(edge)
- {
- return edge.parentNode.getAttribute('__edgeId');
- }
- /* returns both ends contained in the given edgeId */
- function __edgeId2ends(edgeId)
- {
- if( edgeId in __edges )
- return [__edges[edgeId]['start'],__edges[edgeId]['end']];
- else
- return edgeId.match(/^(.*\.instance)--(.*\.instance)$/).slice(1);
- }
- /* returns the linkuri associated to the given edgeId */
- function __edgeId2linkuri(edgeId)
- {
- return __edges[edgeId]['icon'].getAttr('__linkuri');
- }
- /* filter a list of filenames given the specified extensions */
- function __filterFilenamesByExtension(fnames,extensions)
- {
- var ffnames = fnames.filter(
- function(fname)
- {
- return extensions.some(
- function(ext)
- {
- return fname.match(ext+'$');
- });
- });
- return ffnames;
- }
- /* return the icon associated to the given csuri or edgeid */
- function __getIcon(_)
- {
- return (_ in __icons ?
- __icons[_]['icon'] :
- (_ in __edges ?
- __edges[_]['icon'] :
- undefined));
- }
- /* return true if the current model contains no unsaved changes */
- function __isSaved()
- {
- return ! document.title.match(__TITLE+' - \\+');
- }
- /* return true if the given element is a toolbar or inside a toolbar */
- function __isAToolbar(el)
- {
- return Boolean(
- (el.id && el.id.match(/^div_toolbar_/)) ||
- (el.parentNode && __isAToolbar(el.parentNode)) );
- }
- /* return true if the given element is the canvas or something drawn on it */
- function __isCanvasElement(el)
- {
- return el.attr("id") == 'div_canvas' ||
- ( (el.parent().length > 0) && __isCanvasElement(el.parent()));
- }
- /* returns the $segments hash associated to the given edgeId */
- function __linkuri2segments(linkuri)
- {
- return utils.jsonp(__icons[linkuri]['icon'].getAttr('__segments'));
- }
- /* truncate './users/<username>' from a list of filenames */
- function __localizeFilenames(fnames)
- {
- return fnames.map(
- function(n)
- {
- return n.match(/^\.\/users\/.*?(\/.*)/)[1];
- });
- }
- /* modify a URL as needed to ensure GETting it will produce desired result:
- . prepend username to user files
- . do nothing for WWW files */
- function __relativizeURL(url)
- {
- if( url.charAt(0) == '.' || url.charAt(0) == '/' )
- return HttpUtils.url(url,__NO_WID);
- return url;
- }
- /* returns the csuri of the icon that contains the specified VisualObject */
- function __vobj2uri(vobj)
- {
- if( vobj != document.body )
- return vobj.parentNode.getAttribute('__csuri') ||
- __vobj2uri(vobj.parentNode);
- }
- function __getRecentDir(name) {
- return utils.readCookie('recentDir'+name);
- }
- function __setRecentDir(name,value) {
- utils.createCookie('recentDir'+name,value);
- }
|