source: Dev/branches/rest-dojo-ui/client/dojox/drawing/manager/Mouse.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

  • Property svn:executable set to *
File size: 13.2 KB
Line 
1dojo.provide("dojox.drawing.manager.Mouse");
2
3dojox.drawing.manager.Mouse = dojox.drawing.util.oo.declare(
4        // summary:
5        //              Master object (instance) that tracks mouse
6        //              events. A new instance is created for each
7        //              Drawing object.
8        // description:
9        //              You could connect to any method or event in this
10        //              class, but it is designed to have the object
11        //              'registered'. All objects with the current event
12        //              will be called directly.
13        //
14        //              Custom events are used often. In addition to
15        //              standard events onDown, onUp, onDrag, etc, if
16        //              a certain object is clicked upon (or dragged, etc),
17        //              that object's drawingType will create the custom event,
18        //              such as onAnchorDown, or onStencilDown.
19        //
20        function(/* Object */options){
21                this.util = options.util;
22                this.keys = options.keys;
23                this.id = options.id || this.util.uid("mouse");
24                this.currentNodeId = "";
25                this.registered = {};
26        },
27       
28        {
29                // doublClickSpeed: Number
30                //              Milliseconds between clicks to
31                //              register as for onDoubleClick
32                doublClickSpeed:400,
33               
34                // private properties
35               
36                _lastx:0,
37                _lasty:0,
38                __reg:0,
39                _downOnCanvas:false,
40               
41/*=====
42CustomEventMethod: function(){
43        // summary:
44        //              The custom event method that an Object that has
45        //              registered with manager.Mouse can receive.
46        //              Can contain any or all of the following methods
47        //              and they will be called as mouse events. All events
48        //              will be sent a EventObject event object.
49        //      NOTE:
50        //              Events happen anywhere in the document unless
51        //              otherwise noted.
52        //
53        //      onMove
54        //              Fires on mousemove when mouse is up
55        //      onDown
56        //              Fires on mousedown *on the canvas*
57        //      onDrag
58        //              Fires on mousemove when mouse is down
59        //      onUp
60        //              Fires on mouseup, anywhere in the document
61        //      onStencilDown
62        //              Fired on mousedown on a Stencil
63        //      onStencilDrag
64        //              Fired when mouse moves and mose is down on a Stencil
65        //      onStencilUp
66        //              Fired on mouseup off of a Stencil
67        //      on[Custom]Up|Down|Move
68        //              Custom events can bet set and fired by setting a
69        //              different drawingType on a Stencil, or by calling
70        //              setEventMode(customEventName)
71},
72EventObject: function(){
73        // summary:
74        //              The custom event object that is sent to registered objects
75        //              and their respective methods.
76        //      NOTE: Most event objects are the same with the exception
77        //              of the onDown events, which have fewer.
78        //
79        // All event properties included onDown:
80        //
81        //      id: String
82        //              Id of the focused object
83        //      pageX: Number
84        //              The X coordinate of the mouse from the left side of
85        //              the document.
86        //      pageY: Number
87        //              The Y coordinate of the mouse from the top of
88        //              the document.
89        //      x:      Number
90        //              The X coordinate of the mouse from the left side
91        //              of the canvas
92        //      y:      Number
93        //              The Y coordinate of the mouse from the top
94        //              of the canvas
95        //
96        // These event properties are *not* in onDown:
97        //
98        //      last:   Object
99        //              The x and y coordinates of the last mousemove
100        //              relative to the canvas
101        //      move: Object
102        //              The x and y amounts the mouse moved since the last event
103        //      orgX:   Number
104        //              The left side of the canvas from the side of the document
105        //      orgY:   Number
106        //              The top of the canvas from the top of the document
107        //      scroll: Object
108        //              The 'top' and 'left' scroll amounts of the canvas.
109        //      start:  Object
110        //              The x and y coordinates of the mousedown event
111        //      withinCanvas: Boolean
112        //              Whether the event happened within the Canvas or not
113       
114},
115=====*/
116                       
117                init: function(/* HTMLNode*/node){
118                        //      summary:
119                        //              Internal. Initializes mouse.
120                        //
121                        this.container = node;
122                        this.setCanvas();
123                        var c;
124                        var _isDown = false;
125                        dojo.connect(this.container, "rightclick", this, function(evt){
126                                console.warn("RIGHTCLICK")
127                        });
128                       
129                        dojo.connect(document.body, "mousedown", this, function(evt){
130                                //evt.preventDefault();
131                                //dojo.stopEvent(evt);
132                        });
133                       
134                        dojo.connect(this.container, "mousedown", this, function(evt){
135                                this.down(evt);
136                                // Right click shouldn't trigger drag
137                                if(evt.button != dojo.mouseButtons.RIGHT){
138                                        _isDown = true;
139                                        c = dojo.connect(document, "mousemove", this, "drag");
140                                }
141                        });
142                        dojo.connect(document, "mouseup", this, function(evt){
143                                dojo.disconnect(c);
144                                _isDown = false;
145                                this.up(evt);
146                        });
147                        dojo.connect(document, "mousemove", this, function(evt){
148                                if(!_isDown){
149                                        this.move(evt);
150                                }
151                        });
152                        dojo.connect(this.keys, "onEsc", this, function(evt){
153                                this._dragged = false;
154                        });
155                },
156               
157                setCanvas: function(){
158                        // summary:
159                        //              Internal. Sets canvas position
160                        var pos = dojo.coords(this.container.parentNode);
161                        this.origin = dojo.clone(pos);
162                },
163               
164                scrollOffset: function(){
165                        // summary:
166                        //      Gets scroll offset of canvas
167                        return {
168                                top:this.container.parentNode.scrollTop,
169                                left:this.container.parentNode.scrollLeft
170                        }; // Object
171                },
172
173                resize: function(width,height){
174                        if(this.origin){
175                                this.origin.w=width;
176                                this.origin.h=height;
177                        }
178                },
179
180                register: function(/* Object*/scope){
181                        // summary:
182                        //              All objects (Stencils) should register here if they
183                        //              use mouse events. When registering, the object will
184                        //              be called if it has that method.
185                        //      argument:
186                        //              The object to be called
187                        //      Returns: handle
188                        //              Keep the handle to be used for disconnection.
189                        // See: CustomEventMethod and EventObject
190                        //
191                        var handle = scope.id || "reg_"+(this.__reg++);
192                        if(!this.registered[handle]){ this.registered[handle] = scope; }
193                        return handle; // String
194                },
195                unregister: function(handle){
196                        // summary:
197                        //              Disconnects object. Mouse events are no longer
198                        //              called for it.
199                        if(!this.registered[handle]){ return; }
200                        delete this.registered[handle];
201                },
202               
203                _broadcastEvent:function(strEvt, obj){
204                        // summary:
205                        //              Fire events to all registered objects.
206                        //
207                        //console.log("mouse.broadcast:", strEvt, obj)
208                        for(var nm in this.registered){
209                                if(this.registered[nm][strEvt]) this.registered[nm][strEvt](obj);
210                        }
211                },
212               
213                onDown: function(obj){
214                        // summary:
215                        //              Create on[xx]Down event and send to broadcaster.
216                        //              Could be connected to.
217                        //console.info("onDown:", this.eventName("down"))
218                        this._broadcastEvent(this.eventName("down"), obj);
219                },
220               
221                onDrag: function(obj){
222                        // summary:
223                        //              Create on[xx]Drag event and send to broadcaster.
224                        //              Could be connected to.
225                        //
226                        var nm = this.eventName("drag");
227                        if(this._selected && nm == "onDrag"){
228                                nm = "onStencilDrag"
229                        }
230                        this._broadcastEvent(nm, obj);
231                },
232               
233                onMove: function(obj){
234                        // summary:
235                        //              Create onMove event and send to broadcaster.
236                        //              Could be connected to.
237                        //              Note: onMove never uses a custom event
238                        //              Note: onMove is currently not enabled in the app.
239                        //
240                        this._broadcastEvent("onMove", obj);
241                },
242               
243                overName: function(obj,evt){
244                        var nm = obj.id.split(".");
245                        evt = evt.charAt(0).toUpperCase() + evt.substring(1);
246                        if(nm[0] == "dojox" && (dojox.drawing.defaults.clickable || !dojox.drawing.defaults.clickMode)){
247                                return "onStencil"+evt;
248                        }else{
249                                return "on"+evt;
250                        }
251                       
252                },
253               
254                onOver: function(obj){
255                        // summary:
256                        //
257                        this._broadcastEvent(this.overName(obj,"over"), obj);
258                },
259               
260                onOut: function(obj){
261                        // summary:
262                        //
263                        this._broadcastEvent(this.overName(obj,"out"), obj);
264                },
265               
266                onUp: function(obj){
267                        // summary:
268                        //              Create on[xx]Up event and send to broadcaster.
269                        //              Could be connected to.
270                        //
271                        //      blocking first click-off (deselect), largely for TextBlock
272                        //      TODO: should have param to make this optional?
273                        var nm = this.eventName("up");
274                       
275                        if(nm == "onStencilUp"){
276                                this._selected  = true;
277                        }else if(this._selected && nm == "onUp"){ //////////////////////////////////////////
278                                nm = "onStencilUp";
279                                this._selected = false;
280                        }
281                       
282                        console.info("Up Event:", this.id, nm, "id:", obj.id);
283                        this._broadcastEvent(nm, obj);
284                       
285                        // Silverlight double-click handled in Silverlight class
286                        if(dojox.gfx.renderer == "silverlight"){ return; }
287                       
288                        // Check Double Click
289                        // If a double click is detected, the onDoubleClick event fires,
290                        // but does not replace the normal event. They both fire.
291                        this._clickTime = new Date().getTime();
292                        if(this._lastClickTime){
293                                if(this._clickTime-this._lastClickTime<this.doublClickSpeed){
294                                        var dnm = this.eventName("doubleClick");
295                                        console.warn("DOUBLE CLICK", dnm, obj);
296                                        this._broadcastEvent(dnm, obj);
297                                }else{
298                                        //console.log("    slow:", this._clickTime-this._lastClickTime)
299                                }
300                        }
301                        this._lastClickTime = this._clickTime;
302                       
303                },
304               
305                zoom: 1,
306                setZoom: function(zoom){
307                        // summary:
308                        //              Internal. Sets the mouse zoom percentage to
309                        //              that of the canvas
310                        this.zoom = 1/zoom;
311                },
312               
313                setEventMode: function(mode){
314                        // summary:
315                        //              Sets the mouse mode s that custom events can be called.
316                        //              Also can 'disable' events by using a bogus mode:
317                        //              |       mouse.setEventMode("DISABLED")
318                        //              (unless any object subscribes to this event,
319                        //              it is effectively disabled)
320                        //
321                        this.mode = mode ? "on" + mode.charAt(0).toUpperCase() + mode.substring(1) :  "";
322                },
323               
324                eventName: function(name){
325                        // summary:
326                        //              Internal. Determine the event name
327                        //
328                        name = name.charAt(0).toUpperCase() + name.substring(1);
329                        if(this.mode){
330                                if(this.mode == "onPathEdit"){
331                                        return "on"+name;
332                                }
333                                if(this.mode == "onUI"){
334                                        //return "on"+name;
335                                }
336                                return this.mode + name;
337                        }else{
338                                //Allow a mode where stencils aren't clickable
339                                if(!dojox.drawing.defaults.clickable && dojox.drawing.defaults.clickMode){return "on"+name;}
340                                var dt = !this.drawingType || this.drawingType=="surface" || this.drawingType=="canvas" ? "" : this.drawingType;
341                                var t = !dt ? "" : dt.charAt(0).toUpperCase() + dt.substring(1);
342                                return "on"+t+name;
343                        }
344                },
345               
346                up: function(evt){
347                        // summary:
348                        //              Internal. Create onUp event
349                        //
350                        this.onUp(this.create(evt));
351                },
352               
353                down: function(evt){
354                        // summary:
355                        //              Internal. Create onDown event
356                        //
357                        this._downOnCanvas = true;
358                        var sc = this.scrollOffset();
359                        var dim = this._getXY(evt);
360                        this._lastpagex = dim.x;
361                        this._lastpagey = dim.y;
362                        var o = this.origin;
363                        var x = dim.x - o.x + sc.left;
364                        var y = dim.y - o.y + sc.top;
365                       
366                        var withinCanvas = x>=0 && y>=0 && x<=o.w && y<=o.h;
367                        x*= this.zoom;
368                        y*= this.zoom;
369                       
370                        o.startx = x;
371                        o.starty = y;
372                        this._lastx = x;
373                        this._lasty = y;
374                       
375                        this.drawingType = this.util.attr(evt, "drawingType") || "";
376                        var id = this._getId(evt);
377                        //console.log("DOWN:", this.id, id, withinCanvas);
378                        //console.log("this.drawingType:", this.drawingType);
379                       
380                        if(evt.button == dojo.mouseButtons.RIGHT && this.id == "mse"){
381                                //Allow right click events to bubble for context menus
382                        }else{
383                                evt.preventDefault();
384                                dojo.stopEvent(evt);
385                        }
386                        this.onDown({
387                                mid:this.id,
388                                x:x,
389                                y:y,
390                                pageX:dim.x,
391                                pageY:dim.y,
392                                withinCanvas:withinCanvas,
393                                id:id
394                        });
395                       
396                },
397                over: function(obj){
398                        // summary:
399                        //              Internal.
400                        //
401                        this.onOver(obj);
402                },
403                out: function(obj){
404                        // summary:
405                        //              Internal.
406                        //
407                        this.onOut(obj);
408                },
409                move: function(evt){
410                        // summary:
411                        //              Internal.
412                        //
413                        var obj = this.create(evt);
414                        if(this.id=="MUI"){
415                                //console.log("obj.id:", obj.id, "was:", this.currentNodeId)
416                        }
417                        if(obj.id != this.currentNodeId){
418                                // TODO: I wonder if an ID is good enough
419                                //      that would avoid the mixin
420                                var outObj = {};
421                                for(var nm in obj){
422                                        outObj[nm] = obj[nm];
423                                }
424                                outObj.id = this.currentNodeId;
425                                this.currentNodeId && this.out(outObj);
426                                obj.id && this.over(obj);
427                                this.currentNodeId = obj.id;
428                        }
429                        this.onMove(obj);
430                },
431                drag: function(evt){
432                        // summary:
433                        //              Internal. Create onDrag event
434                        this.onDrag(this.create(evt, true));
435                },
436                create: function(evt, squelchErrors){
437                        // summary:
438                        //              Internal. Create EventObject
439                        //
440                        var sc = this.scrollOffset();
441                        var dim = this._getXY(evt);
442                       
443                        var pagex = dim.x;
444                        var pagey = dim.y;
445                       
446                        var o = this.origin;
447                        var x = dim.x - o.x + sc.left;
448                        var y = dim.y - o.y + sc.top;
449
450                        var withinCanvas = x>=0 && y>=0 && x<=o.w && y<=o.h;
451                        x*= this.zoom;
452                        y*= this.zoom;
453                       
454                        var id = withinCanvas ? this._getId(evt, squelchErrors) : "";
455                        var ret = {
456                                mid:this.id,
457                                x:x,
458                                y:y,
459                                pageX:dim.x,
460                                pageY:dim.y,
461                                page:{
462                                        x:dim.x,
463                                        y:dim.y
464                                },
465                                orgX:o.x,
466                                orgY:o.y,
467                                last:{
468                                        x: this._lastx,
469                                        y: this._lasty
470                                },
471                                start:{
472                                        x: this.origin.startx, //+ sc.left,
473                                        y: this.origin.starty //+ sc.top
474                                },
475                                move:{
476                                        x:pagex - this._lastpagex,
477                                        y:pagey - this._lastpagey
478                                },
479                                scroll:sc,
480                                id:id,
481                                withinCanvas:withinCanvas
482                        };
483                       
484                        //console.warn("MSE LAST:", x-this._lastx, y-this._lasty)
485                        this._lastx = x;
486                        this._lasty = y;
487                        this._lastpagex = pagex;
488                        this._lastpagey = pagey;
489                        dojo.stopEvent(evt);
490                        return ret; //Object
491                },
492                _getId: function(evt, squelchErrors){
493                        // summary:
494                        //              Internal. Gets ID of focused node.
495                        return this.util.attr(evt, "id", null, squelchErrors); // String
496                },
497                _getXY: function(evt){
498                        // summary:
499                        //              Internal. Gets mouse coords to page.
500                        return {x:evt.pageX, y:evt.pageY}; // Object
501                },
502               
503                setCursor: function(cursor,/* HTMLNode*/node){
504                        // summary:
505                        //              Sets the cursor for  a given node.  If no
506                        //              node is specified the containing node is used.
507                        if(!node){
508                                dojo.style(this.container, "cursor", cursor);
509                        }else{
510                                dojo.style(node, "cursor", cursor);
511                        }
512                }
513        }
514);
Note: See TracBrowser for help on using the repository browser.