Subversion Repositories Applications.papyrus

Rev

Blame | Last modification | View Log | RSS feed

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

dojo.require("dojo.dnd.common");
dojo.require("dojo.dnd.autoscroll");
dojo.require("dojo.dnd.Avatar");

dojo.dnd.Manager = function(){
        // summary: the manager of DnD operations (usually a singleton)
        this.avatar  = null;
        this.source = null;
        this.nodes = [];
        this.copy  = true;
        this.target = null;
        this.canDropFlag = false;
        this.events = [];
};

dojo.extend(dojo.dnd.Manager, {
        // avatar's offset from the mouse
        OFFSET_X: 16,
        OFFSET_Y: 16,
        // methods
        overSource: function(source){
                // summary: called when a source detected a mouse-over conditiion
                // source: Object: the reporter
                if(this.avatar){
                        this.target = (source && source.targetState != "Disabled") ? source : null;
                        this.avatar.update();
                }
                dojo.publish("/dnd/source/over", [source]);
        },
        outSource: function(source){
                // summary: called when a source detected a mouse-out conditiion
                // source: Object: the reporter
                if(this.avatar){
                        if(this.target == source){
                                this.target = null;
                                this.canDropFlag = false;
                                this.avatar.update();
                                dojo.publish("/dnd/source/over", [null]);
                        }
                }else{
                        dojo.publish("/dnd/source/over", [null]);
                }
        },
        startDrag: function(source, nodes, copy){
                // summary: called to initiate the DnD operation
                // source: Object: the source which provides items
                // nodes: Array: the list of transferred items
                // copy: Boolean: copy items, if true, move items otherwise
                this.source = source;
                this.nodes  = nodes;
                this.copy   = Boolean(copy); // normalizing to true boolean
                this.avatar = this.makeAvatar();
                dojo.body().appendChild(this.avatar.node);
                dojo.publish("/dnd/start", [source, nodes, this.copy]);
                this.events = [
                        dojo.connect(dojo.doc, "onmousemove", this, "onMouseMove"),
                        dojo.connect(dojo.doc, "onmouseup",   this, "onMouseUp"),
                        dojo.connect(dojo.doc, "onkeydown",   this, "onKeyDown"),
                        dojo.connect(dojo.doc, "onkeyup",     this, "onKeyUp")
                ];
                var c = "dojoDnd" + (copy ? "Copy" : "Move");
                dojo.addClass(dojo.body(), c); 
        },
        canDrop: function(flag){
                // summary: called to notify if the current target can accept items
                var canDropFlag = this.target && flag;
                if(this.canDropFlag != canDropFlag){
                        this.canDropFlag = canDropFlag;
                        this.avatar.update();
                }
        },
        stopDrag: function(){
                // summary: stop the DnD in progress
                dojo.removeClass(dojo.body(), "dojoDndCopy");
                dojo.removeClass(dojo.body(), "dojoDndMove");
                dojo.forEach(this.events, dojo.disconnect);
                this.events = [];
                this.avatar.destroy();
                this.avatar = null;
                this.source = null;
                this.nodes = [];
        },
        makeAvatar: function(){
                // summary: makes the avatar, it is separate to be overwritten dynamically, if needed
                return new dojo.dnd.Avatar(this);
        },
        updateAvatar: function(){
                // summary: updates the avatar, it is separate to be overwritten dynamically, if needed
                this.avatar.update();
        },
        // mouse event processors
        onMouseMove: function(e){
                // summary: event processor for onmousemove
                // e: Event: mouse event
                var a = this.avatar;
                if(a){
                        //dojo.dnd.autoScrollNodes(e);
                        dojo.dnd.autoScroll(e);
                        dojo.marginBox(a.node, {l: e.pageX + this.OFFSET_X, t: e.pageY + this.OFFSET_Y});
                        var copy = Boolean(this.source.copyState(dojo.dnd.getCopyKeyState(e)));
                        if(this.copy != copy){ 
                                this._setCopyStatus(copy);
                        }
                }
        },
        onMouseUp: function(e){
                // summary: event processor for onmouseup
                // e: Event: mouse event
                if(this.avatar && (!("mouseButton" in this.source) || this.source.mouseButton == e.button)){
                        if(this.target && this.canDropFlag){
                                var params = [this.source, this.nodes, Boolean(this.source.copyState(dojo.dnd.getCopyKeyState(e))), this.target];
                                dojo.publish("/dnd/drop/before", params);
                                dojo.publish("/dnd/drop", params);
                        }else{
                                dojo.publish("/dnd/cancel");
                        }
                        this.stopDrag();
                }
        },
        // keyboard event processors
        onKeyDown: function(e){
                // summary: event processor for onkeydown:
                //      watching for CTRL for copy/move status, watching for ESCAPE to cancel the drag
                // e: Event: keyboard event
                if(this.avatar){
                        switch(e.keyCode){
                                case dojo.keys.CTRL:
                                        var copy = Boolean(this.source.copyState(true));
                                        if(this.copy != copy){ 
                                                this._setCopyStatus(copy);
                                        }
                                        break;
                                case dojo.keys.ESCAPE:
                                        dojo.publish("/dnd/cancel");
                                        this.stopDrag();
                                        break;
                        }
                }
        },
        onKeyUp: function(e){
                // summary: event processor for onkeyup, watching for CTRL for copy/move status
                // e: Event: keyboard event
                if(this.avatar && e.keyCode == dojo.keys.CTRL){
                        var copy = Boolean(this.source.copyState(false));
                        if(this.copy != copy){ 
                                this._setCopyStatus(copy);
                        }
                }
        },
        // utilities
        _setCopyStatus: function(copy){
                // summary: changes the copy status
                // copy: Boolean: the copy status
                this.copy = copy;
                this.source._markDndStatus(this.copy);
                this.updateAvatar();
                dojo.removeClass(dojo.body(), "dojoDnd" + (this.copy ? "Move" : "Copy"));
                dojo.addClass(dojo.body(), "dojoDnd" + (this.copy ? "Copy" : "Move"));
        }
});

// summary: the manager singleton variable, can be overwritten, if needed
dojo.dnd._manager = null;

dojo.dnd.manager = function(){
        // summary: returns the current DnD manager, creates one if it is not created yet
        if(!dojo.dnd._manager){
                dojo.dnd._manager = new dojo.dnd.Manager();
        }
        return dojo.dnd._manager;       // Object
};

}