123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431 |
- /**
- * Copyright (c) 2006-2016, JGraph Ltd
- * Copyright (c) 2006-2016, Gaudenz Alder
- */
- /**
- * Class: mxRubberband
- *
- * Event handler that selects rectangular regions. This is not built-into
- * <mxGraph>. To enable rubberband selection in a graph, use the following code.
- *
- * Example:
- *
- * (code)
- * var rubberband = new mxRubberband(graph);
- * (end)
- *
- * Constructor: mxRubberband
- *
- * Constructs an event handler that selects rectangular regions in the graph
- * using rubberband selection.
- */
- function mxRubberband(graph)
- {
- if (graph != null)
- {
- this.graph = graph;
- this.graph.addMouseListener(this);
- // Handles force rubberband event
- this.forceRubberbandHandler = mxUtils.bind(this, function(sender, evt)
- {
- var evtName = evt.getProperty('eventName');
- var me = evt.getProperty('event');
-
- if (evtName == mxEvent.MOUSE_DOWN && this.isForceRubberbandEvent(me))
- {
- var offset = mxUtils.getOffset(this.graph.container);
- var origin = mxUtils.getScrollOrigin(this.graph.container);
- origin.x -= offset.x;
- origin.y -= offset.y;
- this.start(me.getX() + origin.x, me.getY() + origin.y);
- me.consume(false);
- }
- });
-
- this.graph.addListener(mxEvent.FIRE_MOUSE_EVENT, this.forceRubberbandHandler);
-
- // Repaints the marquee after autoscroll
- this.panHandler = mxUtils.bind(this, function()
- {
- this.repaint();
- });
-
- this.graph.addListener(mxEvent.PAN, this.panHandler);
-
- // Does not show menu if any touch gestures take place after the trigger
- this.gestureHandler = mxUtils.bind(this, function(sender, eo)
- {
- if (this.first != null)
- {
- this.reset();
- }
- });
-
- this.graph.addListener(mxEvent.GESTURE, this.gestureHandler);
-
- // Automatic deallocation of memory
- if (mxClient.IS_IE)
- {
- mxEvent.addListener(window, 'unload',
- mxUtils.bind(this, function()
- {
- this.destroy();
- })
- );
- }
- }
- };
- /**
- * Variable: defaultOpacity
- *
- * Specifies the default opacity to be used for the rubberband div. Default
- * is 20.
- */
- mxRubberband.prototype.defaultOpacity = 20;
- /**
- * Variable: enabled
- *
- * Specifies if events are handled. Default is true.
- */
- mxRubberband.prototype.enabled = true;
- /**
- * Variable: div
- *
- * Holds the DIV element which is currently visible.
- */
- mxRubberband.prototype.div = null;
- /**
- * Variable: sharedDiv
- *
- * Holds the DIV element which is used to display the rubberband.
- */
- mxRubberband.prototype.sharedDiv = null;
- /**
- * Variable: currentX
- *
- * Holds the value of the x argument in the last call to <update>.
- */
- mxRubberband.prototype.currentX = 0;
- /**
- * Variable: currentY
- *
- * Holds the value of the y argument in the last call to <update>.
- */
- mxRubberband.prototype.currentY = 0;
- /**
- * Variable: fadeOut
- *
- * Optional fade out effect. Default is false.
- */
- mxRubberband.prototype.fadeOut = false;
- /**
- * Function: isEnabled
- *
- * Returns true if events are handled. This implementation returns
- * <enabled>.
- */
- mxRubberband.prototype.isEnabled = function()
- {
- return this.enabled;
- };
-
- /**
- * Function: setEnabled
- *
- * Enables or disables event handling. This implementation updates
- * <enabled>.
- */
- mxRubberband.prototype.setEnabled = function(enabled)
- {
- this.enabled = enabled;
- };
- /**
- * Function: isForceRubberbandEvent
- *
- * Returns true if the given <mxMouseEvent> should start rubberband selection.
- * This implementation returns true if the alt key is pressed.
- */
- mxRubberband.prototype.isForceRubberbandEvent = function(me)
- {
- return mxEvent.isAltDown(me.getEvent());
- };
- /**
- * Function: mouseDown
- *
- * Handles the event by initiating a rubberband selection. By consuming the
- * event all subsequent events of the gesture are redirected to this
- * handler.
- */
- mxRubberband.prototype.mouseDown = function(sender, me)
- {
- if (!me.isConsumed() && this.isEnabled() && this.graph.isEnabled() &&
- me.getState() == null && !mxEvent.isMultiTouchEvent(me.getEvent()))
- {
- var offset = mxUtils.getOffset(this.graph.container);
- var origin = mxUtils.getScrollOrigin(this.graph.container);
- origin.x -= offset.x;
- origin.y -= offset.y;
- this.start(me.getX() + origin.x, me.getY() + origin.y);
- // Does not prevent the default for this event so that the
- // event processing chain is still executed even if we start
- // rubberbanding. This is required eg. in ExtJs to hide the
- // current context menu. In mouseMove we'll make sure we're
- // not selecting anything while we're rubberbanding.
- me.consume(false);
- }
- };
- /**
- * Function: start
- *
- * Sets the start point for the rubberband selection.
- */
- mxRubberband.prototype.start = function(x, y)
- {
- this.first = new mxPoint(x, y);
- var container = this.graph.container;
-
- function createMouseEvent(evt)
- {
- var me = new mxMouseEvent(evt);
- var pt = mxUtils.convertPoint(container, me.getX(), me.getY());
-
- me.graphX = pt.x;
- me.graphY = pt.y;
-
- return me;
- };
- this.dragHandler = mxUtils.bind(this, function(evt)
- {
- this.mouseMove(this.graph, createMouseEvent(evt));
- });
- this.dropHandler = mxUtils.bind(this, function(evt)
- {
- this.mouseUp(this.graph, createMouseEvent(evt));
- });
- // Workaround for rubberband stopping if the mouse leaves the container in Firefox
- if (mxClient.IS_FF)
- {
- mxEvent.addGestureListeners(document, null, this.dragHandler, this.dropHandler);
- }
- };
- /**
- * Function: mouseMove
- *
- * Handles the event by updating therubberband selection.
- */
- mxRubberband.prototype.mouseMove = function(sender, me)
- {
- if (!me.isConsumed() && this.first != null)
- {
- var origin = mxUtils.getScrollOrigin(this.graph.container);
- var offset = mxUtils.getOffset(this.graph.container);
- origin.x -= offset.x;
- origin.y -= offset.y;
- var x = me.getX() + origin.x;
- var y = me.getY() + origin.y;
- var dx = this.first.x - x;
- var dy = this.first.y - y;
- var tol = this.graph.tolerance;
-
- if (this.div != null || Math.abs(dx) > tol || Math.abs(dy) > tol)
- {
- if (this.div == null)
- {
- this.div = this.createShape();
- }
-
- // Clears selection while rubberbanding. This is required because
- // the event is not consumed in mouseDown.
- mxUtils.clearSelection();
-
- this.update(x, y);
- me.consume();
- }
- }
- };
- /**
- * Function: createShape
- *
- * Creates the rubberband selection shape.
- */
- mxRubberband.prototype.createShape = function()
- {
- if (this.sharedDiv == null)
- {
- this.sharedDiv = document.createElement('div');
- this.sharedDiv.className = 'mxRubberband';
- mxUtils.setOpacity(this.sharedDiv, this.defaultOpacity);
- }
- this.graph.container.appendChild(this.sharedDiv);
- var result = this.sharedDiv;
-
- if (mxClient.IS_SVG && (!mxClient.IS_IE || document.documentMode >= 10) && this.fadeOut)
- {
- this.sharedDiv = null;
- }
-
- return result;
- };
- /**
- * Function: isActive
- *
- * Returns true if this handler is active.
- */
- mxRubberband.prototype.isActive = function(sender, me)
- {
- return this.div != null && this.div.style.display != 'none';
- };
- /**
- * Function: mouseUp
- *
- * Handles the event by selecting the region of the rubberband using
- * <mxGraph.selectRegion>.
- */
- mxRubberband.prototype.mouseUp = function(sender, me)
- {
- var active = this.isActive();
- this.reset();
-
- if (active)
- {
- this.execute(me.getEvent());
- me.consume();
- }
- };
- /**
- * Function: execute
- *
- * Resets the state of this handler and selects the current region
- * for the given event.
- */
- mxRubberband.prototype.execute = function(evt)
- {
- var rect = new mxRectangle(this.x, this.y, this.width, this.height);
- this.graph.selectRegion(rect, evt);
- };
- /**
- * Function: reset
- *
- * Resets the state of the rubberband selection.
- */
- mxRubberband.prototype.reset = function()
- {
- if (this.div != null)
- {
- if (mxClient.IS_SVG && (!mxClient.IS_IE || document.documentMode >= 10) && this.fadeOut)
- {
- var temp = this.div;
- mxUtils.setPrefixedStyle(temp.style, 'transition', 'all 0.2s linear');
- temp.style.pointerEvents = 'none';
- temp.style.opacity = 0;
-
- window.setTimeout(function()
- {
- temp.parentNode.removeChild(temp);
- }, 200);
- }
- else
- {
- this.div.parentNode.removeChild(this.div);
- }
- }
- mxEvent.removeGestureListeners(document, null, this.dragHandler, this.dropHandler);
- this.dragHandler = null;
- this.dropHandler = null;
-
- this.currentX = 0;
- this.currentY = 0;
- this.first = null;
- this.div = null;
- };
- /**
- * Function: update
- *
- * Sets <currentX> and <currentY> and calls <repaint>.
- */
- mxRubberband.prototype.update = function(x, y)
- {
- this.currentX = x;
- this.currentY = y;
-
- this.repaint();
- };
- /**
- * Function: repaint
- *
- * Computes the bounding box and updates the style of the <div>.
- */
- mxRubberband.prototype.repaint = function()
- {
- if (this.div != null)
- {
- var x = this.currentX - this.graph.panDx;
- var y = this.currentY - this.graph.panDy;
-
- this.x = Math.min(this.first.x, x);
- this.y = Math.min(this.first.y, y);
- this.width = Math.max(this.first.x, x) - this.x;
- this.height = Math.max(this.first.y, y) - this.y;
- var dx = (mxClient.IS_VML) ? this.graph.panDx : 0;
- var dy = (mxClient.IS_VML) ? this.graph.panDy : 0;
-
- this.div.style.left = (this.x + dx) + 'px';
- this.div.style.top = (this.y + dy) + 'px';
- this.div.style.width = Math.max(1, this.width) + 'px';
- this.div.style.height = Math.max(1, this.height) + 'px';
- }
- };
- /**
- * Function: destroy
- *
- * Destroys the handler and all its resources and DOM nodes. This does
- * normally not need to be called, it is called automatically when the
- * window unloads.
- */
- mxRubberband.prototype.destroy = function()
- {
- if (!this.destroyed)
- {
- this.destroyed = true;
- this.graph.removeMouseListener(this);
- this.graph.removeListener(this.forceRubberbandHandler);
- this.graph.removeListener(this.panHandler);
- this.reset();
-
- if (this.sharedDiv != null)
- {
- this.sharedDiv = null;
- }
- }
- };
- __mxOutput.mxRubberband = typeof mxRubberband !== 'undefined' ? mxRubberband : undefined;
|