Subversion Repositories Applications.papyrus

Rev

Blame | Last modification | View Log | RSS feed

if(!dojo._hasResource["dojox.layout.ResizeHandle"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.layout.ResizeHandle"] = true;
dojo.provide("dojox.layout.ResizeHandle");
dojo.experimental("dojox.layout.ResizeHandle"); 

dojo.require("dijit._Widget");
dojo.require("dijit._Templated"); 
dojo.require("dojo.fx"); 

dojo.declare("dojox.layout.ResizeHandle", [dijit._Widget, dijit._Templated], {
        // summary
        //      The handle on the bottom-right corner of FloatingPane or other widgets that allows
        //      the widget to be resized.
        //      Typically not used directly.

        // targetId: String
        //      id of the Widget OR DomNode that I will size
        targetId: '',

        // targetContainer: DomNode
        //      over-ride targetId and attch this handle directly to a reference of a DomNode
        targetContainer: null, 

        // resizeAxis: String
        //      one of: x|y|xy limit resizing to a single axis, default to xy ... 
        resizeAxis: "xy",

        // activeResize: Boolean
        //      if true, node will size realtime with mouse movement, 
        //      if false, node will create virtual node, and only resize target on mouseUp
        activeResize: false,
        
        // activeResizeClass: String
        //      css class applied to virtual resize node. 
        activeResizeClass: 'dojoxResizeHandleClone',

        // animateSizing: Boolean
        //      only applicable if activeResize = false. onMouseup, animate the node to the
        //      new size
        animateSizing: true,
        
        // animateMethod: String
        //      one of "chain" or "combine" ... visual effect only. combine will "scale" 
        //      node to size, "chain" will alter width, then height
        animateMethod: 'chain',

        // animateDuration: Integer
        //      time in MS to run sizing animation. if animateMethod="chain", total animation 
        //      playtime is 2*animateDuration
        animateDuration: 225,

        // minHeight: Integer
        //      smallest height in px resized node can be
        minHeight: 100,

        // minWidth: Integer
        //      smallest width in px resize node can be
        minWidth: 100,

        // resize handle template, fairly easy to override: 
        templateString: '<div dojoAttachPoint="resizeHandle" class="dojoxResizeHandle"><div></div></div>',

        // private propteries and holders
        _isSizing: false,
        _connects: [],
        _activeResizeNode: null,        
        _activeResizeLastEvent: null,
        // defaults to match default resizeAxis. set resizeAxis variable to modify. 
        _resizeX: true,
        _resizeY: true,


        postCreate: function(){
                // summary: setup our one major listener upon creation
                dojo.connect(this.resizeHandle, "onmousedown", this, "_beginSizing");
                if(!this.activeResize){ 
                        this._activeResizeNode = document.createElement('div');
                        dojo.addClass(this._activeResizeNode,this.activeResizeClass); 
                }else{ this.animateSizing = false; }    

                if (!this.minSize) { 
                        this.minSize = { w: this.minWidth, h: this.minHeight };
                }
                // should we modify the css for the cursor hover to n-resize nw-resize and w-resize?
                this._resizeX = this._resizeY = false; 
                switch (this.resizeAxis.toLowerCase()) {
                case "xy" : 
                        this._resizeX = this._resizeY = true; 
                        // FIXME: need logic to determine NW or NE class to see
                        // based on which [todo] corner is clicked
                        dojo.addClass(this.resizeHandle,"dojoxResizeNW"); 
                        break; 
                case "x" : 
                        this._resizeX = true; 
                        dojo.addClass(this.resizeHandle,"dojoxResizeW");
                        break;
                case "y" : 
                        this._resizeY = true; 
                        dojo.addClass(this.resizeHandle,"dojoxResizeN");
                        break;
                }
        },

        _beginSizing: function(/*Event*/ e){
                // summary: setup movement listeners and calculate initial size
                
                if (this._isSizing){ return false; }

                this.targetWidget = dijit.byId(this.targetId);

                // FIXME: resizing widgets does weird things, disable virtual resizing for now:
                if (this.targetWidget) { this.activeResize = true; } 

                this.targetDomNode = this.targetWidget ? this.targetWidget.domNode : dojo.byId(this.targetId);
                if (this.targetContainer) { this.targetDomNode = this.targetContainer; } 
                if (!this.targetDomNode){ return; }

                if (!this.activeResize) {
                        this.targetDomNode.appendChild(this._activeResizeNode); 
                        dojo.fadeIn({ node: this._activeResizeNode, duration:120, 
                                beforeBegin: dojo.hitch(this,function(){
                                        this._activeResizeNode.style.display=''; 
                                })
                        }).play(); 
                }

                this._isSizing = true;
                this.startPoint  = {'x':e.clientX, 'y':e.clientY};

                // FIXME: this is funky: marginBox adds height, contentBox ignores padding (expected, but foo!)
                var mb = (this.targetWidget) ? dojo.marginBox(this.targetDomNode) : dojo.contentBox(this.targetDomNode);  
                this.startSize  = { 'w':mb.w, 'h':mb.h };

                this._connects = []; 
                this._connects.push(dojo.connect(document,"onmousemove",this,"_updateSizing")); 
                this._connects.push(dojo.connect(document,"onmouseup", this, "_endSizing"));

                e.preventDefault();
        },

        _updateSizing: function(/*Event*/ e){
                // summary: called when moving the ResizeHandle ... determines 
                //      new size based on settings/position and sets styles.

                if(this.activeResize){
                        this._changeSizing(e);
                }else{
                        var tmp = this._getNewCoords(e);        
                        if(tmp === false){ return; }
                        dojo.style(this._activeResizeNode,"width",tmp.width+"px");
                        dojo.style(this._activeResizeNode,"height",tmp.height+"px"); 
                        this._activeResizeNode.style.display=''; 
                }
        },

        _getNewCoords: function(/* Event */ e){
                
                // On IE, if you move the mouse above/to the left of the object being resized,
                // sometimes clientX/Y aren't set, apparently.  Just ignore the event.
                try{
                        if(!e.clientX  || !e.clientY){ return false; }
                }catch(e){
                        // sometimes you get an exception accessing above fields...
                        return false;
                }
                this._activeResizeLastEvent = e; 

                var dx = this.startPoint.x - e.clientX;
                var dy = this.startPoint.y - e.clientY;
                
                var newW = (this._resizeX) ? this.startSize.w - dx : this.startSize.w;
                var newH = (this._resizeY) ? this.startSize.h - dy : this.startSize.h;

                // minimum size check
                if(this.minSize){
                        //var mb = dojo.marginBox(this.targetDomNode);
                        if(newW < this.minSize.w){
                                newW = this.minSize.w;
                        }
                        if(newH < this.minSize.h){
                                newH = this.minSize.h;
                        }
                }
                return {width:newW, height:newH};  // Object
        },
        
        _changeSizing: function(/*Event*/ e){
                // summary: apply sizing information based on information in (e) to attached node
                var tmp = this._getNewCoords(e);
                if(tmp===false){ return; }

                if(this.targetWidget && typeof this.targetWidget.resize == "function"){ 
                        this.targetWidget.resize({ w: tmp.width, h: tmp.height });
                }else{
                        if(this.animateSizing){
                                var anim = dojo.fx[this.animateMethod]([
                                        dojo.animateProperty({
                                                node: this.targetDomNode,
                                                properties: { 
                                                        width: { start: this.startSize.w, end: tmp.width, unit:'px' } 
                                                },      
                                                duration: this.animateDuration
                                        }),
                                        dojo.animateProperty({
                                                node: this.targetDomNode,
                                                properties: { 
                                                        height: { start: this.startSize.h, end: tmp.height, unit:'px' }
                                                },
                                                duration: this.animateDuration
                                        })
                                ]);
                                anim.play();
                        }else{
                                dojo.style(this.targetDomNode,"width",tmp.width+"px"); 
                                dojo.style(this.targetDomNode,"height",tmp.height+"px");
                        }
                }       
                e.preventDefault();
        },

        _endSizing: function(/*Event*/ e){
                // summary: disconnect listenrs and cleanup sizing
                dojo.forEach(this._connects,function(c){
                        dojo.disconnect(c); 
                });
                if(!this.activeResize){
                        dojo.fadeOut({ node:this._activeResizeNode, duration:250,
                                onEnd: dojo.hitch(this,function(){
                                        this._activeResizeNode.style.display="none";
                                })
                        }).play();
                        this._changeSizing(e);
                }
                this._isSizing = false;
        }

});

}