//>>built // wrapped by build app define("dojox/drawing/manager/Mouse", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){ dojo.provide("dojox.drawing.manager.Mouse"); dojox.drawing.manager.Mouse = dojox.drawing.util.oo.declare( // summary: // Master object (instance) that tracks mouse // events. A new instance is created for each // Drawing object. // description: // You could connect to any method or event in this // class, but it is designed to have the object // 'registered'. All objects with the current event // will be called directly. // // Custom events are used often. In addition to // standard events onDown, onUp, onDrag, etc, if // a certain object is clicked upon (or dragged, etc), // that object's drawingType will create the custom event, // such as onAnchorDown, or onStencilDown. // function(/* Object */options){ this.util = options.util; this.keys = options.keys; this.id = options.id || this.util.uid("mouse"); this.currentNodeId = ""; this.registered = {}; }, { // doublClickSpeed: Number // Milliseconds between clicks to // register as for onDoubleClick doublClickSpeed:400, // private properties _lastx:0, _lasty:0, __reg:0, _downOnCanvas:false, /*===== CustomEventMethod: function(){ // summary: // The custom event method that an Object that has // registered with manager.Mouse can receive. // Can contain any or all of the following methods // and they will be called as mouse events. All events // will be sent a EventObject event object. // NOTE: // Events happen anywhere in the document unless // otherwise noted. // // onMove // Fires on mousemove when mouse is up // onDown // Fires on mousedown *on the canvas* // onDrag // Fires on mousemove when mouse is down // onUp // Fires on mouseup, anywhere in the document // onStencilDown // Fired on mousedown on a Stencil // onStencilDrag // Fired when mouse moves and mose is down on a Stencil // onStencilUp // Fired on mouseup off of a Stencil // on[Custom]Up|Down|Move // Custom events can bet set and fired by setting a // different drawingType on a Stencil, or by calling // setEventMode(customEventName) }, EventObject: function(){ // summary: // The custom event object that is sent to registered objects // and their respective methods. // NOTE: Most event objects are the same with the exception // of the onDown events, which have fewer. // // All event properties included onDown: // // id: String // Id of the focused object // pageX: Number // The X coordinate of the mouse from the left side of // the document. // pageY: Number // The Y coordinate of the mouse from the top of // the document. // x: Number // The X coordinate of the mouse from the left side // of the canvas // y: Number // The Y coordinate of the mouse from the top // of the canvas // // These event properties are *not* in onDown: // // last: Object // The x and y coordinates of the last mousemove // relative to the canvas // move: Object // The x and y amounts the mouse moved since the last event // orgX: Number // The left side of the canvas from the side of the document // orgY: Number // The top of the canvas from the top of the document // scroll: Object // The 'top' and 'left' scroll amounts of the canvas. // start: Object // The x and y coordinates of the mousedown event // withinCanvas: Boolean // Whether the event happened within the Canvas or not }, =====*/ init: function(/* HTMLNode*/node){ // summary: // Internal. Initializes mouse. // this.container = node; this.setCanvas(); var c; var _isDown = false; dojo.connect(this.container, "rightclick", this, function(evt){ console.warn("RIGHTCLICK") }); dojo.connect(document.body, "mousedown", this, function(evt){ //evt.preventDefault(); //dojo.stopEvent(evt); }); dojo.connect(this.container, "mousedown", this, function(evt){ this.down(evt); // Right click shouldn't trigger drag if(evt.button != dojo.mouseButtons.RIGHT){ _isDown = true; c = dojo.connect(document, "mousemove", this, "drag"); } }); dojo.connect(document, "mouseup", this, function(evt){ dojo.disconnect(c); _isDown = false; this.up(evt); }); dojo.connect(document, "mousemove", this, function(evt){ if(!_isDown){ this.move(evt); } }); dojo.connect(this.keys, "onEsc", this, function(evt){ this._dragged = false; }); }, setCanvas: function(){ // summary: // Internal. Sets canvas position var pos = dojo.coords(this.container.parentNode); this.origin = dojo.clone(pos); }, scrollOffset: function(){ // summary: // Gets scroll offset of canvas return { top:this.container.parentNode.scrollTop, left:this.container.parentNode.scrollLeft }; // Object }, resize: function(width,height){ if(this.origin){ this.origin.w=width; this.origin.h=height; } }, register: function(/* Object*/scope){ // summary: // All objects (Stencils) should register here if they // use mouse events. When registering, the object will // be called if it has that method. // argument: // The object to be called // Returns: handle // Keep the handle to be used for disconnection. // See: CustomEventMethod and EventObject // var handle = scope.id || "reg_"+(this.__reg++); if(!this.registered[handle]){ this.registered[handle] = scope; } return handle; // String }, unregister: function(handle){ // summary: // Disconnects object. Mouse events are no longer // called for it. if(!this.registered[handle]){ return; } delete this.registered[handle]; }, _broadcastEvent:function(strEvt, obj){ // summary: // Fire events to all registered objects. // //console.log("mouse.broadcast:", strEvt, obj) for(var nm in this.registered){ if(this.registered[nm][strEvt]) this.registered[nm][strEvt](obj); } }, onDown: function(obj){ // summary: // Create on[xx]Down event and send to broadcaster. // Could be connected to. //console.info("onDown:", this.eventName("down")) this._broadcastEvent(this.eventName("down"), obj); }, onDrag: function(obj){ // summary: // Create on[xx]Drag event and send to broadcaster. // Could be connected to. // var nm = this.eventName("drag"); if(this._selected && nm == "onDrag"){ nm = "onStencilDrag" } this._broadcastEvent(nm, obj); }, onMove: function(obj){ // summary: // Create onMove event and send to broadcaster. // Could be connected to. // Note: onMove never uses a custom event // Note: onMove is currently not enabled in the app. // this._broadcastEvent("onMove", obj); }, overName: function(obj,evt){ var nm = obj.id.split("."); evt = evt.charAt(0).toUpperCase() + evt.substring(1); if(nm[0] == "dojox" && (dojox.drawing.defaults.clickable || !dojox.drawing.defaults.clickMode)){ return "onStencil"+evt; }else{ return "on"+evt; } }, onOver: function(obj){ // summary: // this._broadcastEvent(this.overName(obj,"over"), obj); }, onOut: function(obj){ // summary: // this._broadcastEvent(this.overName(obj,"out"), obj); }, onUp: function(obj){ // summary: // Create on[xx]Up event and send to broadcaster. // Could be connected to. // // blocking first click-off (deselect), largely for TextBlock // TODO: should have param to make this optional? var nm = this.eventName("up"); if(nm == "onStencilUp"){ this._selected = true; }else if(this._selected && nm == "onUp"){ ////////////////////////////////////////// nm = "onStencilUp"; this._selected = false; } console.info("Up Event:", this.id, nm, "id:", obj.id); this._broadcastEvent(nm, obj); // Silverlight double-click handled in Silverlight class if(dojox.gfx.renderer == "silverlight"){ return; } // Check Double Click // If a double click is detected, the onDoubleClick event fires, // but does not replace the normal event. They both fire. this._clickTime = new Date().getTime(); if(this._lastClickTime){ if(this._clickTime-this._lastClickTime=0 && y>=0 && x<=o.w && y<=o.h; x*= this.zoom; y*= this.zoom; o.startx = x; o.starty = y; this._lastx = x; this._lasty = y; this.drawingType = this.util.attr(evt, "drawingType") || ""; var id = this._getId(evt); //console.log("DOWN:", this.id, id, withinCanvas); //console.log("this.drawingType:", this.drawingType); if(evt.button == dojo.mouseButtons.RIGHT && this.id == "mse"){ //Allow right click events to bubble for context menus }else{ evt.preventDefault(); dojo.stopEvent(evt); } this.onDown({ mid:this.id, x:x, y:y, pageX:dim.x, pageY:dim.y, withinCanvas:withinCanvas, id:id }); }, over: function(obj){ // summary: // Internal. // this.onOver(obj); }, out: function(obj){ // summary: // Internal. // this.onOut(obj); }, move: function(evt){ // summary: // Internal. // var obj = this.create(evt); if(this.id=="MUI"){ //console.log("obj.id:", obj.id, "was:", this.currentNodeId) } if(obj.id != this.currentNodeId){ // TODO: I wonder if an ID is good enough // that would avoid the mixin var outObj = {}; for(var nm in obj){ outObj[nm] = obj[nm]; } outObj.id = this.currentNodeId; this.currentNodeId && this.out(outObj); obj.id && this.over(obj); this.currentNodeId = obj.id; } this.onMove(obj); }, drag: function(evt){ // summary: // Internal. Create onDrag event this.onDrag(this.create(evt, true)); }, create: function(evt, squelchErrors){ // summary: // Internal. Create EventObject // var sc = this.scrollOffset(); var dim = this._getXY(evt); var pagex = dim.x; var pagey = dim.y; var o = this.origin; var x = dim.x - o.x + sc.left; var y = dim.y - o.y + sc.top; var withinCanvas = x>=0 && y>=0 && x<=o.w && y<=o.h; x*= this.zoom; y*= this.zoom; var id = withinCanvas ? this._getId(evt, squelchErrors) : ""; var ret = { mid:this.id, x:x, y:y, pageX:dim.x, pageY:dim.y, page:{ x:dim.x, y:dim.y }, orgX:o.x, orgY:o.y, last:{ x: this._lastx, y: this._lasty }, start:{ x: this.origin.startx, //+ sc.left, y: this.origin.starty //+ sc.top }, move:{ x:pagex - this._lastpagex, y:pagey - this._lastpagey }, scroll:sc, id:id, withinCanvas:withinCanvas }; //console.warn("MSE LAST:", x-this._lastx, y-this._lasty) this._lastx = x; this._lasty = y; this._lastpagex = pagex; this._lastpagey = pagey; dojo.stopEvent(evt); return ret; //Object }, _getId: function(evt, squelchErrors){ // summary: // Internal. Gets ID of focused node. return this.util.attr(evt, "id", null, squelchErrors); // String }, _getXY: function(evt){ // summary: // Internal. Gets mouse coords to page. return {x:evt.pageX, y:evt.pageY}; // Object }, setCursor: function(cursor,/* HTMLNode*/node){ // summary: // Sets the cursor for a given node. If no // node is specified the containing node is used. if(!node){ dojo.style(this.container, "cursor", cursor); }else{ dojo.style(node, "cursor", cursor); } } } ); });