source: Dev/branches/rest-dojo-ui/client/dojox/gfx/shape.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).

File size: 27.2 KB
Line 
1define(["./_base", "dojo/_base/lang", "dojo/_base/declare", "dojo/_base/window", "dojo/_base/sniff",
2        "dojo/_base/connect", "dojo/_base/array", "dojo/dom-construct", "dojo/_base/Color", "./matrix"],
3  function(g, lang, declare, win, has, events, arr, domConstruct, Color, matrixLib){
4
5/*=====
6        dojox.gfx.shape = {
7                // summary:
8                //              This module contains the core graphics Shape API.
9                //              Different graphics renderer implementation modules (svg, canvas, vml, silverlight, etc.) extend this
10                //              basic api to provide renderer-specific implementations for each shape.
11        };
12  =====*/
13
14        var shape = g.shape = {};
15        // a set of ids (keys=type)
16        var _ids = {};
17        // a simple set impl to map shape<->id
18        var registry = {};
19       
20        shape.register = function(/*dojox.gfx.shape.Shape*/shape){
21                // summary:
22                //              Register the specified shape into the graphics registry.
23                // shape: dojox.gfx.shape.Shape
24                //              The shape to register.
25                // returns:
26                //              The unique id associated with this shape.
27                // the id pattern : type+number (ex: Rect0,Rect1,etc)
28                var t = shape.declaredClass.split('.').pop();
29                var i = t in _ids ? ++_ids[t] : ((_ids[t] = 0));
30                var uid = t+i;
31                registry[uid] = shape;
32                return uid;
33        };
34       
35        shape.byId = function(/*String*/id){
36                // summary:
37                //              Returns the shape that matches the specified id.
38                // id: String
39                //              The unique identifier for this Shape.
40                return registry[id]; //dojox.gfx.shape.Shape
41        };
42       
43        shape.dispose = function(/*dojox.gfx.shape.Shape*/shape){
44                // summary:
45                //              Removes the specified shape from the registry.
46                // shape: dojox.gfx.shape.Shape
47                //              The shape to unregister.
48                delete registry[shape.getUID()];
49        };
50       
51        declare("dojox.gfx.shape.Shape", null, {
52                // summary: a Shape object, which knows how to apply
53                // graphical attributes and transformations
54       
55                constructor: function(){
56                        //      rawNode: Node
57                        //              underlying graphics-renderer-specific implementation object (if applicable)
58                        this.rawNode = null;
59                        //      shape: Object: an abstract shape object
60                        //      (see dojox.gfx.defaultPath,
61                        //      dojox.gfx.defaultPolyline,
62                        //      dojox.gfx.defaultRect,
63                        //      dojox.gfx.defaultEllipse,
64                        //      dojox.gfx.defaultCircle,
65                        //      dojox.gfx.defaultLine,
66                        //      or dojox.gfx.defaultImage)
67                        this.shape = null;
68       
69                        //      matrix: dojox.gfx.Matrix2D
70                        //              a transformation matrix
71                        this.matrix = null;
72       
73                        //      fillStyle: Object
74                        //              a fill object
75                        //              (see dojox.gfx.defaultLinearGradient,
76                        //              dojox.gfx.defaultRadialGradient,
77                        //              dojox.gfx.defaultPattern,
78                        //              or dojo.Color)
79                        this.fillStyle = null;
80       
81                        //      strokeStyle: Object
82                        //              a stroke object
83                        //              (see dojox.gfx.defaultStroke)
84                        this.strokeStyle = null;
85       
86                        // bbox: dojox.gfx.Rectangle
87                        //              a bounding box of this shape
88                        //              (see dojox.gfx.defaultRect)
89                        this.bbox = null;
90       
91                        // virtual group structure
92       
93                        // parent: Object
94                        //              a parent or null
95                        //              (see dojox.gfx.Surface,
96                        //              dojox.gfx.shape.VirtualGroup,
97                        //              or dojox.gfx.Group)
98                        this.parent = null;
99       
100                        // parentMatrix: dojox.gfx.Matrix2D
101                        //      a transformation matrix inherited from the parent
102                        this.parentMatrix = null;
103                       
104                        var uid = shape.register(this);
105                        this.getUID = function(){
106                                return uid;
107                        }
108                },     
109       
110                // trivial getters
111       
112                getNode: function(){
113                        // summary: Different graphics rendering subsystems implement shapes in different ways.  This
114                        //      method provides access to the underlying graphics subsystem object.  Clients calling this
115                        //      method and using the return value must be careful not to try sharing or using the underlying node
116                        //      in a general way across renderer implementation.
117                        //      Returns the underlying graphics Node, or null if no underlying graphics node is used by this shape.
118                        return this.rawNode; // Node
119                },
120                getShape: function(){
121                        // summary: returns the current Shape object or null
122                        //      (see dojox.gfx.defaultPath,
123                        //      dojox.gfx.defaultPolyline,
124                        //      dojox.gfx.defaultRect,
125                        //      dojox.gfx.defaultEllipse,
126                        //      dojox.gfx.defaultCircle,
127                        //      dojox.gfx.defaultLine,
128                        //      or dojox.gfx.defaultImage)
129                        return this.shape; // Object
130                },
131                getTransform: function(){
132                        // summary: Returns the current transformation matrix applied to this Shape or null
133                        return this.matrix;     // dojox.gfx.Matrix2D
134                },
135                getFill: function(){
136                        // summary: Returns the current fill object or null
137                        //      (see dojox.gfx.defaultLinearGradient,
138                        //      dojox.gfx.defaultRadialGradient,
139                        //      dojox.gfx.defaultPattern,
140                        //      or dojo.Color)
141                        return this.fillStyle;  // Object
142                },
143                getStroke: function(){
144                        // summary: Returns the current stroke object or null
145                        //      (see dojox.gfx.defaultStroke)
146                        return this.strokeStyle;        // Object
147                },
148                getParent: function(){
149                        // summary: Returns the parent Shape, Group or VirtualGroup or null if this Shape is unparented.
150                        //      (see dojox.gfx.Surface,
151                        //      dojox.gfx.shape.VirtualGroup,
152                        //      or dojox.gfx.Group)
153                        return this.parent;     // Object
154                },
155                getBoundingBox: function(){
156                        // summary: Returns the bounding box Rectanagle for this shape or null if a BoundingBox cannot be
157                        //      calculated for the shape on the current renderer or for shapes with no geometric area (points).
158                        //      A bounding box is a rectangular geometric region
159                        //      defining the X and Y extent of the shape.
160                        //      (see dojox.gfx.defaultRect)
161                        return this.bbox;       // dojox.gfx.Rectangle
162                },
163                getTransformedBoundingBox: function(){
164                        // summary: returns an array of four points or null
165                        //      four points represent four corners of the untransformed bounding box
166                        var b = this.getBoundingBox();
167                        if(!b){
168                                return null;    // null
169                        }
170                        var m = this._getRealMatrix(),
171                                gm = matrixLib;
172                        return [        // Array
173                                        gm.multiplyPoint(m, b.x, b.y),
174                                        gm.multiplyPoint(m, b.x + b.width, b.y),
175                                        gm.multiplyPoint(m, b.x + b.width, b.y + b.height),
176                                        gm.multiplyPoint(m, b.x, b.y + b.height)
177                                ];
178                },
179                getEventSource: function(){
180                        // summary: returns a Node, which is used as
181                        //      a source of events for this shape
182                        // COULD BE RE-IMPLEMENTED BY THE RENDERER!
183                        return this.rawNode;    // Node
184                },
185       
186                // empty settings
187       
188                setShape: function(shape){
189                        // summary: sets a shape object
190                        //      (the default implementation simply ignores it)
191                        // shape: Object
192                        //      a shape object
193                        //      (see dojox.gfx.defaultPath,
194                        //      dojox.gfx.defaultPolyline,
195                        //      dojox.gfx.defaultRect,
196                        //      dojox.gfx.defaultEllipse,
197                        //      dojox.gfx.defaultCircle,
198                        //      dojox.gfx.defaultLine,
199                        //      or dojox.gfx.defaultImage)
200                        // COULD BE RE-IMPLEMENTED BY THE RENDERER!
201                        this.shape = g.makeParameters(this.shape, shape);
202                        this.bbox = null;
203                        return this;    // self
204                },
205                setFill: function(fill){
206                        // summary: sets a fill object
207                        //      (the default implementation simply ignores it)
208                        // fill: Object
209                        //      a fill object
210                        //      (see dojox.gfx.defaultLinearGradient,
211                        //      dojox.gfx.defaultRadialGradient,
212                        //      dojox.gfx.defaultPattern,
213                        //      or dojo.Color)
214                        // COULD BE RE-IMPLEMENTED BY THE RENDERER!
215                        if(!fill){
216                                // don't fill
217                                this.fillStyle = null;
218                                return this;    // self
219                        }
220                        var f = null;
221                        if(typeof(fill) == "object" && "type" in fill){
222                                // gradient or pattern
223                                switch(fill.type){
224                                        case "linear":
225                                                f = g.makeParameters(g.defaultLinearGradient, fill);
226                                                break;
227                                        case "radial":
228                                                f = g.makeParameters(g.defaultRadialGradient, fill);
229                                                break;
230                                        case "pattern":
231                                                f = g.makeParameters(g.defaultPattern, fill);
232                                                break;
233                                }
234                        }else{
235                                // color object
236                                f = g.normalizeColor(fill);
237                        }
238                        this.fillStyle = f;
239                        return this;    // self
240                },
241                setStroke: function(stroke){
242                        // summary: sets a stroke object
243                        //      (the default implementation simply ignores it)
244                        // stroke: Object
245                        //      a stroke object
246                        //      (see dojox.gfx.defaultStroke)
247                        // COULD BE RE-IMPLEMENTED BY THE RENDERER!
248                        if(!stroke){
249                                // don't stroke
250                                this.strokeStyle = null;
251                                return this;    // self
252                        }
253                        // normalize the stroke
254                        if(typeof stroke == "string" || lang.isArray(stroke) || stroke instanceof Color){
255                                stroke = {color: stroke};
256                        }
257                        var s = this.strokeStyle = g.makeParameters(g.defaultStroke, stroke);
258                        s.color = g.normalizeColor(s.color);
259                        return this;    // self
260                },
261                setTransform: function(matrix){
262                        // summary: sets a transformation matrix
263                        // matrix: dojox.gfx.Matrix2D
264                        //      a matrix or a matrix-like object
265                        //      (see an argument of dojox.gfx.Matrix2D
266                        //      constructor for a list of acceptable arguments)
267                        // COULD BE RE-IMPLEMENTED BY THE RENDERER!
268                        this.matrix = matrixLib.clone(matrix ? matrixLib.normalize(matrix) : matrixLib.identity);
269                        return this._applyTransform();  // self
270                },
271       
272                _applyTransform: function(){
273                        // summary: physically sets a matrix
274                        // COULD BE RE-IMPLEMENTED BY THE RENDERER!
275                        return this;    // self
276                },
277       
278                // z-index
279       
280                moveToFront: function(){
281                        // summary: moves a shape to front of its parent's list of shapes
282                        var p = this.getParent();
283                        if(p){
284                                p._moveChildToFront(this);
285                                this._moveToFront();    // execute renderer-specific action
286                        }
287                        return this;    // self
288                },
289                moveToBack: function(){
290                        // summary: moves a shape to back of its parent's list of shapes
291                        var p = this.getParent();
292                        if(p){
293                                p._moveChildToBack(this);
294                                this._moveToBack();     // execute renderer-specific action
295                        }
296                        return this;
297                },
298                _moveToFront: function(){
299                        // summary: renderer-specific hook, see dojox.gfx.shape.Shape.moveToFront()
300                        // COULD BE RE-IMPLEMENTED BY THE RENDERER!
301                },
302                _moveToBack: function(){
303                        // summary: renderer-specific hook, see dojox.gfx.shape.Shape.moveToFront()
304                        // COULD BE RE-IMPLEMENTED BY THE RENDERER!
305                },
306       
307                // apply left & right transformation
308       
309                applyRightTransform: function(matrix){
310                        // summary: multiplies the existing matrix with an argument on right side
311                        //      (this.matrix * matrix)
312                        // matrix: dojox.gfx.Matrix2D
313                        //      a matrix or a matrix-like object
314                        //      (see an argument of dojox.gfx.Matrix2D
315                        //      constructor for a list of acceptable arguments)
316                        return matrix ? this.setTransform([this.matrix, matrix]) : this;        // self
317                },
318                applyLeftTransform: function(matrix){
319                        // summary: multiplies the existing matrix with an argument on left side
320                        //      (matrix * this.matrix)
321                        // matrix: dojox.gfx.Matrix2D
322                        //      a matrix or a matrix-like object
323                        //      (see an argument of dojox.gfx.Matrix2D
324                        //      constructor for a list of acceptable arguments)
325                        return matrix ? this.setTransform([matrix, this.matrix]) : this;        // self
326                },
327                applyTransform: function(matrix){
328                        // summary: a shortcut for dojox.gfx.Shape.applyRightTransform
329                        // matrix: dojox.gfx.Matrix2D
330                        //      a matrix or a matrix-like object
331                        //      (see an argument of dojox.gfx.Matrix2D
332                        //      constructor for a list of acceptable arguments)
333                        return matrix ? this.setTransform([this.matrix, matrix]) : this;        // self
334                },
335       
336                // virtual group methods
337       
338                removeShape: function(silently){
339                        // summary: removes the shape from its parent's list of shapes
340                        // silently: Boolean
341                        //              if true, do not redraw a picture yet
342                        if(this.parent){
343                                this.parent.remove(this, silently);
344                        }
345                        return this;    // self
346                },
347                _setParent: function(parent, matrix){
348                        // summary: sets a parent
349                        // parent: Object
350                        //      a parent or null
351                        //      (see dojox.gfx.Surface,
352                        //      dojox.gfx.shape.VirtualGroup,
353                        //      or dojox.gfx.Group)
354                        // matrix: dojox.gfx.Matrix2D
355                        //      a 2D matrix or a matrix-like object
356                        this.parent = parent;
357                        return this._updateParentMatrix(matrix);        // self
358                },
359                _updateParentMatrix: function(matrix){
360                        // summary: updates the parent matrix with new matrix
361                        // matrix: dojox.gfx.Matrix2D
362                        //      a 2D matrix or a matrix-like object
363                        this.parentMatrix = matrix ? matrixLib.clone(matrix) : null;
364                        return this._applyTransform();  // self
365                },
366                _getRealMatrix: function(){
367                        // summary: returns the cumulative ('real') transformation matrix
368                        //      by combining the shape's matrix with its parent's matrix
369                        var m = this.matrix;
370                        var p = this.parent;
371                        while(p){
372                                if(p.matrix){
373                                        m = matrixLib.multiply(p.matrix, m);
374                                }
375                                p = p.parent;
376                        }
377                        return m;       // dojox.gfx.Matrix2D
378                }
379        });
380       
381        shape._eventsProcessing = {
382                connect: function(name, object, method){
383                        // summary: connects a handler to an event on this shape
384                        // COULD BE RE-IMPLEMENTED BY THE RENDERER!
385                        // redirect to fixCallback to normalize events and add the gfxTarget to the event. The latter
386                        // is done by dojox.gfx.fixTarget which is defined by each renderer
387                        return events.connect(this.getEventSource(), name, shape.fixCallback(this, g.fixTarget, object, method));
388                       
389                },
390                disconnect: function(token){
391                        // summary: connects a handler by token from an event on this shape
392                        // COULD BE RE-IMPLEMENTED BY THE RENDERER!
393       
394                        events.disconnect(token);
395                }
396        };
397       
398        shape.fixCallback = function(gfxElement, fixFunction, scope, method){
399                //  summary:
400                //      Wraps the callback to allow for tests and event normalization
401                //      before it gets invoked. This is where 'fixTarget' is invoked.
402                //  gfxElement: Object
403                //      The GFX object that triggers the action (ex.:
404                //      dojox.gfx.Surface and dojox.gfx.Shape). A new event property
405                //      'gfxTarget' is added to the event to reference this object.
406                //      for easy manipulation of GFX objects by the event handlers.
407                //  fixFunction: Function
408                //      The function that implements the logic to set the 'gfxTarget'
409                //      property to the event. It should be 'dojox.gfx.fixTarget' for
410                //      most of the cases
411                //  scope: Object
412                //      Optional. The scope to be used when invoking 'method'. If
413                //      omitted, a global scope is used.
414                //  method: Function|String
415                //      The original callback to be invoked.
416                if(!method){
417                        method = scope;
418                        scope = null;
419                }
420                if(lang.isString(method)){
421                        scope = scope || win.global;
422                        if(!scope[method]){ throw(['dojox.gfx.shape.fixCallback: scope["', method, '"] is null (scope="', scope, '")'].join('')); }
423                        return function(e){ 
424                                return fixFunction(e,gfxElement) ? scope[method].apply(scope, arguments || []) : undefined; }; // Function
425                }
426                return !scope
427                        ? function(e){
428                                return fixFunction(e,gfxElement) ? method.apply(scope, arguments) : undefined; }
429                        : function(e){
430                                return fixFunction(e,gfxElement) ? method.apply(scope, arguments || []) : undefined; }; // Function
431        };
432        lang.extend(shape.Shape, shape._eventsProcessing);
433       
434        shape.Container = {
435                // summary: a container of shapes, which can be used
436                //      as a foundation for renderer-specific groups, or as a way
437                //      to logically group shapes (e.g, to propagate matricies)
438       
439                _init: function() {
440                        // children: Array: a list of children
441                        this.children = [];
442                },
443       
444                // group management
445       
446                openBatch: function() {
447                        // summary: starts a new batch, subsequent new child shapes will be held in
448                        //      the batch instead of appending to the container directly
449                },
450                closeBatch: function() {
451                        // summary: submits the current batch, append all pending child shapes to DOM
452                },
453                add: function(shape){
454                        // summary: adds a shape to the list
455                        // shape: dojox.gfx.Shape
456                        //              the shape to add to the list
457                        var oldParent = shape.getParent();
458                        if(oldParent){
459                                oldParent.remove(shape, true);
460                        }
461                        this.children.push(shape);
462                        return shape._setParent(this, this._getRealMatrix());   // self
463                },
464                remove: function(shape, silently){
465                        // summary: removes a shape from the list
466                        //      shape: dojox.gfx.shape.Shape
467                        //              the shape to remove
468                        // silently: Boolean
469                        //              if true, do not redraw a picture yet
470                        for(var i = 0; i < this.children.length; ++i){
471                                if(this.children[i] == shape){
472                                        if(silently){
473                                                // skip for now
474                                        }else{
475                                                shape.parent = null;
476                                                shape.parentMatrix = null;
477                                        }
478                                        this.children.splice(i, 1);
479                                        break;
480                                }
481                        }
482                        return this;    // self
483                },
484                clear: function(){
485                        // summary: removes all shapes from a group/surface
486                        var shape;
487                        for(var i = 0; i < this.children.length;++i){
488                                shape = this.children[i];
489                                shape.parent = null;
490                                shape.parentMatrix = null;
491                        }
492                        this.children = [];
493                        return this;    // self
494                },
495       
496                // moving child nodes
497       
498                _moveChildToFront: function(shape){
499                        // summary: moves a shape to front of the list of shapes
500                        //      shape: dojox.gfx.shape.Shape
501                        //              one of the child shapes to move to the front
502                        for(var i = 0; i < this.children.length; ++i){
503                                if(this.children[i] == shape){
504                                        this.children.splice(i, 1);
505                                        this.children.push(shape);
506                                        break;
507                                }
508                        }
509                        return this;    // self
510                },
511                _moveChildToBack: function(shape){
512                        // summary: moves a shape to back of the list of shapes
513                        //      shape: dojox.gfx.shape.Shape
514                        //              one of the child shapes to move to the front
515                        for(var i = 0; i < this.children.length; ++i){
516                                if(this.children[i] == shape){
517                                        this.children.splice(i, 1);
518                                        this.children.unshift(shape);
519                                        break;
520                                }
521                        }
522                        return this;    // self
523                }
524        };
525       
526        declare("dojox.gfx.shape.Surface", null, {
527                // summary: a surface object to be used for drawings
528                constructor: function(){
529                        // underlying node
530                        this.rawNode = null;
531                        // the parent node
532                        this._parent = null;
533                        // the list of DOM nodes to be deleted in the case of destruction
534                        this._nodes = [];
535                        // the list of events to be detached in the case of destruction
536                        this._events = [];
537                },
538                destroy: function(){
539                        // summary: destroy all relevant external resources and release all
540                        //      external references to make this object garbage-collectible
541                        arr.forEach(this._nodes, domConstruct.destroy);
542                        this._nodes = [];
543                        arr.forEach(this._events, events.disconnect);
544                        this._events = [];
545                        this.rawNode = null;    // recycle it in _nodes, if it needs to be recycled
546                        if(has("ie")){
547                                while(this._parent.lastChild){
548                                        domConstruct.destroy(this._parent.lastChild);
549                                }
550                        }else{
551                                this._parent.innerHTML = "";
552                        }
553                        this._parent = null;
554                },
555                getEventSource: function(){
556                        // summary: returns a node, which can be used to attach event listeners
557                        return this.rawNode; // Node
558                },
559                _getRealMatrix: function(){
560                        // summary: always returns the identity matrix
561                        return null;    // dojox.gfx.Matrix2D
562                },
563                isLoaded: true,
564                onLoad: function(/*dojox.gfx.Surface*/ surface){
565                        // summary: local event, fired once when the surface is created
566                        // asynchronously, used only when isLoaded is false, required
567                        // only for Silverlight.
568                },
569                whenLoaded: function(/*Object|Null*/ context, /*Function|String*/ method){
570                        var f = lang.hitch(context, method);
571                        if(this.isLoaded){
572                                f(this);
573                        }else{
574                                var h = events.connect(this, "onLoad", function(surface){
575                                        events.disconnect(h);
576                                        f(surface);
577                                });
578                        }
579                }
580        });
581       
582        lang.extend(shape.Surface, shape._eventsProcessing);
583       
584        declare("dojox.gfx.Point", null, {
585                // summary: a hypothetical 2D point to be used for drawings - {x, y}
586                // description: This object is defined for documentation purposes.
587                //      You should use the naked object instead: {x: 1, y: 2}.
588        });
589       
590        declare("dojox.gfx.Rectangle", null, {
591                // summary: a hypothetical rectangle - {x, y, width, height}
592                // description: This object is defined for documentation purposes.
593                //      You should use the naked object instead: {x: 1, y: 2, width: 100, height: 200}.
594        });
595       
596        declare("dojox.gfx.shape.Rect", shape.Shape, {
597                // summary: a generic rectangle
598                constructor: function(rawNode){
599                        // rawNode: Node
600                        //              The underlying graphics system object (typically a DOM Node)
601                        this.shape = g.getDefault("Rect");
602                        this.rawNode = rawNode;
603                },
604                getBoundingBox: function(){
605                        // summary: returns the bounding box (its shape in this case)
606                        return this.shape;      // dojox.gfx.Rectangle
607                }
608        });
609       
610        declare("dojox.gfx.shape.Ellipse", shape.Shape, {
611                // summary: a generic ellipse
612                constructor: function(rawNode){
613                        // rawNode: Node
614                        //              a DOM Node
615                        this.shape = g.getDefault("Ellipse");
616                        this.rawNode = rawNode;
617                },
618                getBoundingBox: function(){
619                        // summary: returns the bounding box
620                        if(!this.bbox){
621                                var shape = this.shape;
622                                this.bbox = {x: shape.cx - shape.rx, y: shape.cy - shape.ry,
623                                        width: 2 * shape.rx, height: 2 * shape.ry};
624                        }
625                        return this.bbox;       // dojox.gfx.Rectangle
626                }
627        });
628       
629        declare("dojox.gfx.shape.Circle", shape.Shape, {
630                // summary: a generic circle
631                //      (this is a helper object, which is defined for convenience)
632                constructor: function(rawNode){
633                        // rawNode: Node
634                        //              a DOM Node
635                        this.shape = g.getDefault("Circle");
636                        this.rawNode = rawNode;
637                },
638                getBoundingBox: function(){
639                        // summary: returns the bounding box
640                        if(!this.bbox){
641                                var shape = this.shape;
642                                this.bbox = {x: shape.cx - shape.r, y: shape.cy - shape.r,
643                                        width: 2 * shape.r, height: 2 * shape.r};
644                        }
645                        return this.bbox;       // dojox.gfx.Rectangle
646                }
647        });
648       
649        declare("dojox.gfx.shape.Line", shape.Shape, {
650                // summary: a generic line
651                //      (this is a helper object, which is defined for convenience)
652                constructor: function(rawNode){
653                        // rawNode: Node
654                        //              a DOM Node
655                        this.shape = g.getDefault("Line");
656                        this.rawNode = rawNode;
657                },
658                getBoundingBox: function(){
659                        // summary: returns the bounding box
660                        if(!this.bbox){
661                                var shape = this.shape;
662                                this.bbox = {
663                                        x:              Math.min(shape.x1, shape.x2),
664                                        y:              Math.min(shape.y1, shape.y2),
665                                        width:  Math.abs(shape.x2 - shape.x1),
666                                        height: Math.abs(shape.y2 - shape.y1)
667                                };
668                        }
669                        return this.bbox;       // dojox.gfx.Rectangle
670                }
671        });
672       
673        declare("dojox.gfx.shape.Polyline", shape.Shape, {
674                // summary: a generic polyline/polygon
675                //      (this is a helper object, which is defined for convenience)
676                constructor: function(rawNode){
677                        // rawNode: Node
678                        //              a DOM Node
679                        this.shape = g.getDefault("Polyline");
680                        this.rawNode = rawNode;
681                },
682                setShape: function(points, closed){
683                        // summary: sets a polyline/polygon shape object
684                        // points: Object
685                        //              a polyline/polygon shape object
686                        // closed: Boolean
687                        //              close the polyline to make a polygon
688                        if(points && points instanceof Array){
689                                // points: Array: an array of points
690                                this.inherited(arguments, [{points: points}]);
691                                if(closed && this.shape.points.length){
692                                        this.shape.points.push(this.shape.points[0]);
693                                }
694                        }else{
695                                this.inherited(arguments, [points]);
696                        }
697                        return this;    // self
698                },
699                _normalizePoints: function(){
700                        // summary: normalize points to array of {x:number, y:number}
701                        var p = this.shape.points, l = p && p.length;
702                        if(l && typeof p[0] == "number"){
703                                var points = [];
704                                for(var i = 0; i < l; i += 2){
705                                        points.push({x: p[i], y: p[i + 1]});
706                                }
707                                this.shape.points = points;
708                        }
709                },
710                getBoundingBox: function(){
711                        // summary: returns the bounding box
712                        if(!this.bbox && this.shape.points.length){
713                                var p = this.shape.points;
714                                var l = p.length;
715                                var t = p[0];
716                                var bbox = {l: t.x, t: t.y, r: t.x, b: t.y};
717                                for(var i = 1; i < l; ++i){
718                                        t = p[i];
719                                        if(bbox.l > t.x) bbox.l = t.x;
720                                        if(bbox.r < t.x) bbox.r = t.x;
721                                        if(bbox.t > t.y) bbox.t = t.y;
722                                        if(bbox.b < t.y) bbox.b = t.y;
723                                }
724                                this.bbox = {
725                                        x:              bbox.l,
726                                        y:              bbox.t,
727                                        width:  bbox.r - bbox.l,
728                                        height: bbox.b - bbox.t
729                                };
730                        }
731                        return this.bbox;       // dojox.gfx.Rectangle
732                }
733        });
734       
735        declare("dojox.gfx.shape.Image", shape.Shape, {
736                // summary: a generic image
737                //      (this is a helper object, which is defined for convenience)
738                constructor: function(rawNode){
739                        // rawNode: Node
740                        //              a DOM Node
741                        this.shape = g.getDefault("Image");
742                        this.rawNode = rawNode;
743                },
744                getBoundingBox: function(){
745                        // summary: returns the bounding box (its shape in this case)
746                        return this.shape;      // dojox.gfx.Rectangle
747                },
748                setStroke: function(){
749                        // summary: ignore setting a stroke style
750                        return this;    // self
751                },
752                setFill: function(){
753                        // summary: ignore setting a fill style
754                        return this;    // self
755                }
756        });
757       
758        declare("dojox.gfx.shape.Text", shape.Shape, {
759                // summary: a generic text
760                constructor: function(rawNode){
761                        // rawNode: Node
762                        //              a DOM Node
763                        this.fontStyle = null;
764                        this.shape = g.getDefault("Text");
765                        this.rawNode = rawNode;
766                },
767                getFont: function(){
768                        // summary: returns the current font object or null
769                        return this.fontStyle;  // Object
770                },
771                setFont: function(newFont){
772                        // summary: sets a font for text
773                        // newFont: Object
774                        //              a font object (see dojox.gfx.defaultFont) or a font string
775                        this.fontStyle = typeof newFont == "string" ? g.splitFontString(newFont) :
776                                g.makeParameters(g.defaultFont, newFont);
777                        this._setFont();
778                        return this;    // self
779                }
780        });
781       
782        shape.Creator = {
783                // summary: shape creators
784                createShape: function(shape){
785                        // summary: creates a shape object based on its type; it is meant to be used
786                        //      by group-like objects
787                        // shape: Object
788                        //              a shape descriptor object
789                        switch(shape.type){
790                                case g.defaultPath.type:                return this.createPath(shape);
791                                case g.defaultRect.type:                return this.createRect(shape);
792                                case g.defaultCircle.type:      return this.createCircle(shape);
793                                case g.defaultEllipse.type:     return this.createEllipse(shape);
794                                case g.defaultLine.type:                return this.createLine(shape);
795                                case g.defaultPolyline.type:    return this.createPolyline(shape);
796                                case g.defaultImage.type:               return this.createImage(shape);
797                                case g.defaultText.type:                return this.createText(shape);
798                                case g.defaultTextPath.type:    return this.createTextPath(shape);
799                        }
800                        return null;
801                },
802                createGroup: function(){
803                        // summary: creates a group shape
804                        return this.createObject(g.Group);      // dojox.gfx.Group
805                },
806                createRect: function(rect){
807                        // summary: creates a rectangle shape
808                        // rect: Object
809                        //              a path object (see dojox.gfx.defaultRect)
810                        return this.createObject(g.Rect, rect); // dojox.gfx.Rect
811                },
812                createEllipse: function(ellipse){
813                        // summary: creates an ellipse shape
814                        // ellipse: Object
815                        //              an ellipse object (see dojox.gfx.defaultEllipse)
816                        return this.createObject(g.Ellipse, ellipse);   // dojox.gfx.Ellipse
817                },
818                createCircle: function(circle){
819                        // summary: creates a circle shape
820                        // circle: Object
821                        //              a circle object (see dojox.gfx.defaultCircle)
822                        return this.createObject(g.Circle, circle);     // dojox.gfx.Circle
823                },
824                createLine: function(line){
825                        // summary: creates a line shape
826                        // line: Object
827                        //              a line object (see dojox.gfx.defaultLine)
828                        return this.createObject(g.Line, line); // dojox.gfx.Line
829                },
830                createPolyline: function(points){
831                        // summary: creates a polyline/polygon shape
832                        // points: Object
833                        //              a points object (see dojox.gfx.defaultPolyline)
834                        //              or an Array of points
835                        return this.createObject(g.Polyline, points);   // dojox.gfx.Polyline
836                },
837                createImage: function(image){
838                        // summary: creates a image shape
839                        // image: Object
840                        //              an image object (see dojox.gfx.defaultImage)
841                        return this.createObject(g.Image, image);       // dojox.gfx.Image
842                },
843                createText: function(text){
844                        // summary: creates a text shape
845                        // text: Object
846                        //              a text object (see dojox.gfx.defaultText)
847                        return this.createObject(g.Text, text); // dojox.gfx.Text
848                },
849                createPath: function(path){
850                        // summary: creates a path shape
851                        // path: Object
852                        //              a path object (see dojox.gfx.defaultPath)
853                        return this.createObject(g.Path, path); // dojox.gfx.Path
854                },
855                createTextPath: function(text){
856                        // summary: creates a text shape
857                        // text: Object
858                        //              a textpath object (see dojox.gfx.defaultTextPath)
859                        return this.createObject(g.TextPath, {}).setText(text); // dojox.gfx.TextPath
860                },
861                createObject: function(shapeType, rawShape){
862                        // summary: creates an instance of the passed shapeType class
863                        // SHOULD BE RE-IMPLEMENTED BY THE RENDERER!
864                        // shapeType: Function
865                        //              a class constructor to create an instance of
866                        // rawShape: Object
867                        //              properties to be passed in to the classes 'setShape' method
868       
869                        return null;    // dojox.gfx.Shape
870                }
871        };
872       
873        return shape;
874});
875
Note: See TracBrowser for help on using the repository browser.