123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338 |
- /* This file is part of AToMPM - A Tool for Multi-Paradigm Modelling
- * Copyright 2011 by the AToMPM team and licensed under the LGPL
- * See COPYING.lesser and README.md in the root of this project for full details
- */
- var __selectionOverlay;
- var __highlighted = [];
- var __selection;
- function __isSelected(it)
- {
- return __selection != undefined && utils.contains(__selection['items'],it);
- }
- /* draw a selection overlay rectangle around the specified (via uri) icons
- 1. clear any past __selection
- 2. return undefined on undefined argument
- 2. extract uri from non-array argument (when select called with event.target)
- ... event.target may be:
- a) normal icon: selection becomes that icon's uri
- b) center-piece: selection becomes center-piece and all of its connected
- edges
- c) edge: selection becomes connected center-piece and all of its
- connected edges
- 2. remove selected items <edgeTo,centerPiece,edgeFrom> if any of the 3 are
- missing (e.g., when the canvas selection overlay contains only edgeTo or
- centerPiece)
- 3. foreach icon in the updated selection, add its contents if any/applicable
- except when the 'ignoreContents' is set to true
- 4. return undefined on empty updated selection
- 5. compute a bbox that contains all specified icons/edges
- 6. draw a selection overlay rectangle matching computed bbox and style it
- appropriately
- 7. remember the drawn rectangle, the computed bbox and the selection in
- __selection
- 8. give rectangle listener to report __EVENT_LEFT_PRESS_SELECTION
- 9. return true (to indicate successfully selecting something) */
- function __select(selection,ignoreContents)
- {
- if( __selection != undefined )
- {
- __selection['rect'].remove();
- __selection = undefined;
- GeometryUtils.hideGeometryControlsOverlay();
- GeometryUtils.hideTransformationPreviewOverlay();
- }
- if( selection == undefined )
- return;
- else if( ! utils.isArray(selection) )
- /* selection is event.target */
- {
- if( (uri = __vobj2uri(selection)) )
- selection = [uri].concat(
- (__isConnectionType(uri) ? __getConnectedEdges(uri) : []));
- else
- selection = __getConnectionParticipants( __edge2edgeId(selection) );
- }
- else
- /* filter canvas selection for incomplete connection tuples */
- {
- var missingFromSelection =
- function(required)
- {
- return required.some(
- function(edgeId)
- {return ! utils.contains(selection,edgeId);});
- };
- while(
- selection.length > 0 &&
- selection.some(
- function(it)
- {
- if( it in __edges )
- var items = __getConnectionParticipants(it);
- else if( __isConnectionType(it) )
- var items = [it].concat(__getConnectedEdges(it));
- if( items != undefined && missingFromSelection(items) )
- {
- utils.filter(selection,items);
- return true;
- }
- }) ) ;
- }
- /* add icon contents */
- if( !ignoreContents )
- {
- var containedIcons = [];
- selection.forEach(
- function(it)
- {
- if( it in __icons )
- containedIcons =
- containedIcons.concat( __getIconsInContainer(it) );
- });
- selection = selection.concat(
- containedIcons.filter(
- function(ci)
- {
- return ! utils.contains(selection,ci);
- }));
- }
-
- /* compute selection bbox */
- if( selection.length == 0 )
- return;
- else if( selection.length == 1 )
- var bbox = __icons[selection[0]]['icon'].getBBox();
- else
- var bbox = __getGlobalBBox(selection);
- __selection =
- {'items':selection,
- 'bbox':bbox,
- 'rect':__bbox2rect(bbox,'canvas_selection')};
- __selection['rect'].node.onmousedown =
- function(event)
- {
- if( event.button == 0 )
- BehaviorManager.handleUserEvent(__EVENT_LEFT_PRESS_SELECTION,event);
- };
- __selection['rect'].node.onmouseup =
- function(event)
- {
- if( event.button == 0 )
- BehaviorManager.handleUserEvent(__EVENT_LEFT_RELEASE_SELECTION,event);
- };
- return true;
- }
- /* returns true if __selection contains an 'instance' of the given type */
- function __selectionContainsType(type)
- {
- if( __selection == undefined )
- return false;
-
- return __selection['items'].some(
- function(it)
- {
- return (type == __EDGETYPE && it in __edges) ||
- (type == __NODETYPE && it in __icons);
- });
- }
- /* temporarily highlight specified icon (e.g., to draw attention on it) without
- disrupting other highlighted elements */
- function __flash(uri,color,timeout)
- {
- __icons[uri]['icon'].highlight({'color':color || 'MediumVioletRed','fill':true});
- function turnOff()
- {
- try {__icons[uri]['icon'].unhighlight();}
- catch(err) {
- console.log(err);
- }
- }
- window.setTimeout(turnOff,timeout || 500);
- }
- /* if 'uri' isn't already highlighted, unhighlights whatever is (if applicable)
- and highlights 'uri'... highlighting implies setting
-
- 1. highlighting 'uri'
- 2. possibly highlighting 'uri''s cross-formalism neighbors
- 3. possibly setting a timeout to remove the highlight
- 4. setting up the __highlighted object like so
- 'uri' :: 'uri'
- 'turnOff' :: a function that unhighlights 'uri' and nodes from step 2. if
- any... the try/catch blocks ensure safety against deletion of
- highlighted icons */
- function __highlight(uri,followCrossFormalismLinks,timeout,color)
- {
- if( ! isHighlighted(uri) )
- {
- __unhighlight(uri);
- __icons[uri]['icon'].highlight({'color':color || 'DarkTurquoise','fill':true});
- if( followCrossFormalismLinks != undefined )
- {
- var neighbors =
- __getCrossFormalismNeighbors(uri,followCrossFormalismLinks);
- neighbors.nodes.forEach(
- function(n)
- {
- if( n != uri )
- __icons[n]['icon'].highlight({'color':'Gold','fill':true});
- });
- }
- if( timeout != undefined )
- var tid = window.setTimeout(__unhighlight,timeout);
- __highlighted.push(
- {'uri':uri,
- 'turnOff':
- function()
- {
- try {__icons[uri]['icon'].unhighlight();}
- catch(err) {
- console.log(err);
- }
- if( followCrossFormalismLinks != undefined )
- neighbors.nodes.forEach(
- function(n) {
- try {__icons[n]['icon'].unhighlight();}
- catch(err) {
- console.log(err);
- }
- } );
- if( timeout != undefined )
- window.clearTimeout(tid);
- }});
- }
- }
- function isHighlighted(uri)
- {
- return __highlighted.length > 0 && __highlighted.filter(function(hl) {return uri == hl['uri'];}).length == 1;
- }
- function __unhighlight(uri)
- {
- if( __highlighted.length > 0 )
- {
- __highlighted.filter(function(hl) {return !uri || uri == hl['uri'];}).forEach(function(hl) {hl.turnOff();});
- if (!uri) {
- __highlighted = [];
- } else {
- __highlighted = __highlighted.filter(function(hl) {return uri != hl['uri'];});
- }
-
- }
- }
- /* return the contents of the selection orverlay rectangle... the max parameter
- is used to stop searching after the specified number of contained icons/edges
- are found */
- function __getCanvasSelectionOverlayContents(max)
- {
- if( __selectionOverlay == undefined )
- return [];
- var sobbox = {'x' : __selectionOverlay.attr('x'),
- 'y' : __selectionOverlay.attr('y'),
- 'width' : __selectionOverlay.attr('width'),
- 'height': __selectionOverlay.attr('height')};
- contents = [];
- [__icons,__edges].some(
- function(A)
- {
- for( var a in A )
- {
- if( A[a]['icon'].isVisible() &&
- __isBBoxInside(A[a]['icon'].getBBox(),sobbox) )
- {
- contents.push(a);
- if( contents.length == max )
- return true;
- }
- }
- });
- return contents;
- }
- /* initialize a Raphael.rect originating at (x,y), appropriately styled, and
- that reports events (specifically, mouseup) as if it were the canvas
- NOTE:: _x0 and _y0 are use to remember the point from where the selection
- began */
- function __initCanvasSelectionOverlay(x,y)
- {
- if( __selectionOverlay != undefined )
- return;
- __selectionOverlay = __canvas.rect(x,y,0,0);
- __selectionOverlay.node.setAttribute('class','canvas_selection_overlay');
- __selectionOverlay.node.setAttribute('_x0',x);
- __selectionOverlay.node.setAttribute('_y0',y);
- __selectionOverlay.node.onmouseup =
- function(event)
- {
- if( event.button == 0 )
- BehaviorManager.handleUserEvent(__EVENT_LEFT_RELEASE_CANVAS,event);
- };
- }
- /* returns true if there is at least one icon fully encompassed within the
- selection overlay rectangle */
- function __isCanvasSelectionOverlayEmpty()
- {
- return __getCanvasSelectionOverlayContents(1).length == 0;
- }
- /* selects contents of and hides canvas selection overlay */
- function __selectSelection()
- {
- var selectedSomething = __select( __getCanvasSelectionOverlayContents() );
- __selectionOverlay.remove();
- __selectionOverlay = undefined;
- return selectedSomething;
- }
- /* resizes the selection overlay rectangle following a mouse motion... resizing
- may involve changing x and y attributes because widths and heights can not be
- negative */
- function __updateCanvasSelectionOverlay(x,y)
- {
- var w = x - parseInt(__selectionOverlay.node.getAttribute('_x0')),
- h = y - parseInt(__selectionOverlay.node.getAttribute('_y0'));
- if( w < 0 )
- {
- __selectionOverlay.attr('x', x);
- __selectionOverlay.attr('width', -w);
- }
- else
- __selectionOverlay.attr('width', w);
- if( h < 0 )
- {
- __selectionOverlay.attr('y', y);
- __selectionOverlay.attr('height', -h);
- }
- else
- __selectionOverlay.attr('height', h);
- }
|