~eda-qa/dhlib/main

« back to all changes in this revision

Viewing changes to lib/ui/DragMaster.mhx

  • Committer: edA-qa mort-ora-y
  • Date: 2010-02-16 05:36:32 UTC
  • Revision ID: eda-qa@disemia.com-20100216053632-60lt7fndfi3fgblw
first

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package ui;
 
2
 
 
3
import flash.events.MouseEvent;
 
4
import mathx.Point2;
 
5
 
 
6
/**
 
7
 * Simplifies creation of drag-and-drop operations by handling the common functionality.
 
8
 */
 
9
class DragMaster extends AnimatedWidget
 
10
{
 
11
        static var singleton : DragMaster;
 
12
        
 
13
        public var filtersBad : Array<flashx.filter.Filter>;
 
14
        public var filtersGood : Array<flashx.filter.Filter>;
 
15
        public var dragStart : Int; //how much the mouse must move before the drag actually starts
 
16
        
 
17
        /**
 
18
         * Starts dragging a particular object. This object will be added to the stage at the current
 
19
         * mouse location with the offset applied. It is assumed to have the correct size. It will
 
20
         * be allowed to be dragged around the stage and dropped on a target which can
 
21
         * accept it.
 
22
         *
 
23
         * @param object [in,keep] the object to drag around
 
24
         * @param offset [in] how far the top-left/origin of the object should be positioned relative to the mouse
 
25
         * @param controller [in] the interface used to decide how to handle the dragging
 
26
         * @param data [in,keep] custom data passed back to the controller
 
27
         */
 
28
        static public function startDrag( controller : DragController, data : Dynamic )
 
29
        {
 
30
                ASSERT_NULL( singleton );
 
31
                
 
32
                singleton = new DragMaster( controller, data );
 
33
                flash.Lib.current.stage.addChild( singleton );
 
34
                singleton.origPos = Point2.at( singleton.stage.mouseX, singleton.stage.mouseY );
 
35
                ui.Events.captureMouse( singleton );
 
36
                
 
37
                return singleton; //allows setting options
 
38
        }
 
39
        
 
40
        /**
 
41
         * Cancels any drag operation currently in progress.
 
42
         */
 
43
        static public function cancelDrag()
 
44
        {
 
45
                if( singleton == null )
 
46
                        return;
 
47
                        
 
48
                singleton.cancel();
 
49
        }
 
50
        
 
51
        function abort()
 
52
        {
 
53
                ctl.dragAbort( data );
 
54
                cleanup();
 
55
        }
 
56
        
 
57
        function cancel()
 
58
        {
 
59
                ctl.dragCancel( data );
 
60
                cleanup();
 
61
        }
 
62
        
 
63
        function cleanup()
 
64
        {
 
65
                ui.Events.endCapture( this );
 
66
                flash.Lib.current.stage.removeChild( singleton );
 
67
                singleton = null;
 
68
                if( object != null )
 
69
                        object.getNative().filters = origFilters;
 
70
        }
 
71
        
 
72
        var object : Widget;
 
73
        var offset : Point2;
 
74
        var data : Dynamic;
 
75
        var ctl : DragController;
 
76
        var cancelIn : Null<Float>;
 
77
        var origFilters : Array<Dynamic>;
 
78
        var origPos : Point2;
 
79
        var started : Bool;
 
80
        var fullStage : Bool;
 
81
                
 
82
        function new( ctl, data )
 
83
        {
 
84
                super();
 
85
                
 
86
                this.data = data;
 
87
                this.ctl = ctl;
 
88
                
 
89
                dragStart = 0; //start on any move by default
 
90
                started = false;
 
91
                fullStage = false;
 
92
                
 
93
                addEventListener( MouseEvent.MOUSE_UP, onMouseUp );
 
94
                addEventListener( MouseEvent.MOUSE_MOVE, onMouseMove );
 
95
                addEventListener( MouseEvent.MOUSE_OVER, onMouseOver );
 
96
                addEventListener( MouseEvent.MOUSE_OUT, onMouseOut );
 
97
        }
 
98
        
 
99
        /**
 
100
         * Actually starts the dragging operation. Up until this point it was rather
 
101
         * tentative with minimal work done in case dragging is not actually to be performed.
 
102
         */
 
103
        function startDragNow( sp : Point2 )
 
104
        {
 
105
                started = true;
 
106
                var d = ctl.dragStart( data, sp );
 
107
                object = d.item;
 
108
                offset = d.offset;
 
109
                origFilters = object.getNative().filters;
 
110
                
 
111
                singleton.addChild( object.getNative() );
 
112
                singleton.positionObject();
 
113
        }
 
114
        
 
115
        function onMouseMove( ev : MouseEvent )
 
116
        {
 
117
                if( !started )
 
118
                {
 
119
                        //check if we've moved far enough to start
 
120
                        var sp = Point2.at( stage.mouseX, stage.mouseY );
 
121
                        if( sp.distanceTo( origPos ) < dragStart )
 
122
                                return;
 
123
                        startDragNow( sp );
 
124
                }
 
125
                positionObject();
 
126
        }
 
127
        
 
128
        function onMouseUp( ev : MouseEvent )
 
129
        {
 
130
                //if we haven't started allow the event to propogate normally and we simply abord the drag
 
131
                if( !started )
 
132
                {
 
133
                        Events.captureContProp = true;
 
134
                        abort();
 
135
                        return;
 
136
                }
 
137
                
 
138
                //check if we can accept here and then accept or cancel
 
139
                var sp = Point2.at( stage.mouseX, stage.mouseY );
 
140
                var loc = sp.add( offset );
 
141
                
 
142
                if( !ctl.dragCanAccept( data, sp, loc ) )
 
143
                        cancel();
 
144
                else
 
145
                {
 
146
                        //it could still be rejected now
 
147
                        if( !ctl.dragAccept( data, sp, loc ) )
 
148
                                cancel();
 
149
                        else
 
150
                                cleanup();
 
151
                }
 
152
        }
 
153
        
 
154
        function onMouseOver( ev : MouseEvent )
 
155
        {
 
156
                //if we come back to our window and the mouse isn't down, cancel the drag
 
157
                if( !ev.buttonDown )
 
158
                        cancel();
 
159
        }
 
160
        
 
161
        function onMouseOut( ev : MouseEvent )
 
162
        {
 
163
                //if we are out of bounds too long then we simply cancel the drag
 
164
                cancelIn = 10;
 
165
        }
 
166
        
 
167
        function positionObject()
 
168
        {
 
169
                var sp = Point2.at( stage.mouseX, stage.mouseY );
 
170
                var loc = sp.add( offset );
 
171
                object.move( loc.x, loc.y );
 
172
                
 
173
                //apply filters based on accept at this point
 
174
                if( ctl.dragCanAccept( data, sp, loc ) )
 
175
                        object.getNative().filters = filtersGood;
 
176
                else
 
177
                        object.getNative().filters = filtersBad;
 
178
        }
 
179
        
 
180
        override function _animate( elapsed : Float )
 
181
        {
 
182
                //run the cancellation timeout
 
183
                if( cancelIn != null )
 
184
                {
 
185
                        cancelIn -= elapsed;
 
186
                        if( cancelIn < 0 )
 
187
                        {
 
188
                                cancelIn = null;
 
189
                                cancel();
 
190
                        }
 
191
                }
 
192
        }
 
193
        
 
194
        public function enableFullStage()
 
195
        {
 
196
                fullStage = true;
 
197
                update();
 
198
        }
 
199
        
 
200
        override function _resize( w : Float, h : Float )
 
201
        {
 
202
                //not awlays needed, so only do if requested (efficiency)
 
203
                if( fullStage )
 
204
                {
 
205
                        //full area to ensure mouse events capture
 
206
                        gfx.use( draw.Brush.clear() );
 
207
                        gfx.drawRect( 0, 0, w, h );
 
208
                }
 
209
        }
 
210
}