OSDN Git Service

Version 0.6.96. add lock function @X.EventDispatcher.
[pettanr/clientJs.git] / 0.6.x / js / 01_core / 10_XCallback.js
1 \r
2 // ------------------------------------------------------------------------- //\r
3 // ------------ local variables -------------------------------------------- //\r
4 // ------------------------------------------------------------------------- //\r
5 \r
6 var X_Callback_LIVE_LIST        = [],\r
7         X_Callback_POOL_LIST        = [],\r
8         X_Closure_COMMAND_BACK      = X_Callback_LIVE_LIST,\r
9         X_Closure_COMMAND_DROP      = X_Callback_POOL_LIST,\r
10         \r
11         X_Callback_THIS_FUNC        = 1,\r
12         X_Callback_HANDLEEVENT      = 2,\r
13         X_Callback_FUNC_ONLY        = 3,\r
14 \r
15         X_Callback_NONE             =  0,\r
16         X_Callback_UN_LISTEN        =  1,\r
17         X_Callback_STOP_PROPAGATION =  2,  // 上位階層への伝播のキャンセル\r
18         X_Callback_STOP_NOW         =  4 | 2,  // 同一階層のリスナーのキャンセル(上位へもキャンセル)\r
19         X_Callback_PREVENT_DEFAULT  =  8,  // 結果動作のキャンセル,\r
20         X_Callback_MONOPOLY         = 16,  // move event を独占する\r
21         X_Callback_SYS_CANCEL       = 32 | 4 | 2;\r
22 \r
23 /*\r
24  * handleEvent という関数のメンバーを持つオブジェクト\r
25  * @typedef {{ handleEvent : function }}\r
26  */\r
27 var listener;\r
28 \r
29 /*\r
30  * コールバックに thisObject や、追加の引数を設定するための情報を収めたハッシュ\r
31  * @typedef {{ k : number, f : (function|undefined), x : (listener|undefined), s : (Array|undefined) }}\r
32  */\r
33 var callbackHash;\r
34 \r
35 /*\r
36  * \r
37  * @typedef {(funciton|{ _ : function, same : function, kill : function, a : (Array|undefined) })}\r
38  */\r
39 var functionHash;\r
40 \r
41 X.Callback = {\r
42         NONE             : X_Callback_NONE,\r
43         UN_LISTEN        : X_Callback_UN_LISTEN,\r
44         STOP_PROPAGATION : X_Callback_STOP_PROPAGATION,\r
45         STOP_NOW         : X_Callback_STOP_NOW,\r
46         PREVENT_DEFAULT  : X_Callback_PREVENT_DEFAULT,\r
47         MONOPOLY         : X_Callback_MONOPOLY\r
48 };\r
49 \r
50 // ------------------------------------------------------------------------- //\r
51 // --- implements ---------------------------------------------------------- //\r
52 // ------------------------------------------------------------------------- //\r
53 \r
54 function X_Callback_create( thisObject, opt_callback, opt_args /* [ listener || ( context + function ) || function ][ args... ] */ ){\r
55         var obj = X_Callback_classifyCallbackArgs( thisObject, opt_callback, opt_args ),\r
56                 l, ret, _obj;\r
57         if( !obj.k ) return obj;\r
58         if( l = X_Callback_POOL_LIST.length ){\r
59                 ret    = X_Callback_POOL_LIST[ l - 1 ]; --X_Callback_POOL_LIST.length; // ret = X_Callback_POOL_LIST.pop();\r
60                 _obj   = ret( X_Closure_COMMAND_BACK );\r
61                 _obj.k = obj.k;\r
62                 _obj.f = obj.f;\r
63                 _obj.x = obj.x;\r
64                 _obj.s = obj.s;\r
65         } else {\r
66                 ret = X_Closure_actualClosure( obj );\r
67         };\r
68         X_Callback_LIVE_LIST[ X_Callback_LIVE_LIST.length ] = ret;\r
69         return ret;\r
70 };\r
71 \r
72 function X_Closure_actualClosure( obj ){\r
73         return function(){\r
74                 if( arguments[ 0 ] === X_Closure_COMMAND_BACK ) return obj;\r
75                 if( arguments[ 0 ] !== X_Closure_COMMAND_DROP ) return X_Callback_proxyCallback( obj, arguments );\r
76         };\r
77 };\r
78 \r
79 function X_Callback_classifyCallbackArgs( arg1, arg2, arg3, alt_context ){\r
80         var obj;\r
81         \r
82         if( arg1 && X.Type.isFunction( arg2 ) ){\r
83                 obj  = { x : arg1, f : arg2, k : X_Callback_THIS_FUNC };\r
84         } else\r
85         if( arg1 && X.Type.isFunction( arg1[ 'handleEvent' ] ) ){\r
86                 obj  = { x : arg1, k : X_Callback_HANDLEEVENT };\r
87                 arg3 = arg2;\r
88         } else\r
89         if( X.Type.isFunction( arg1 ) ){\r
90                 arg3 = arg2;\r
91                 if( alt_context ){\r
92                         obj  = { x : alt_context, f : arg1, k : X_Callback_THIS_FUNC };\r
93                 } else {\r
94                         obj  = { f : arg1, k : X_Callback_FUNC_ONLY };\r
95                 };\r
96         } else\r
97         if( X.Type.isFunction( arg2 ) ){\r
98                 //console.log( 'X_Callback_classifyCallbackArgs : arg1 が ' + arg1 + 'です' ); ie4 で error\r
99                 if( alt_context ){\r
100                         obj  = { x : alt_context, f : arg2, k : X_Callback_THIS_FUNC };\r
101                 } else {\r
102                         obj  = { f : arg2, k : X_Callback_FUNC_ONLY };\r
103                 };\r
104         } else\r
105         if( alt_context ){\r
106                 obj  = { x : alt_context, k : X_Callback_HANDLEEVENT };\r
107                 arg3 = arg1;\r
108         } else {\r
109                 console.log( '不正 ' + arg1 );\r
110                 console.dir( arg1 );\r
111                 return;\r
112         };\r
113         \r
114         if( X.Type.isArray( arg3 )){\r
115                 obj.s = arg3;\r
116         };\r
117         return ( obj.x || obj.s ) ? obj : arg1;\r
118 };\r
119 \r
120 function X_Callback_proxyCallback( xfunc, _args ){\r
121         var args    = _args || [],\r
122                 thisObj = xfunc.x,\r
123                 func    = xfunc.f,\r
124                 supp    = xfunc.s,\r
125                 temp, ret;      \r
126         \r
127         if( supp && supp.length ){\r
128                 temp = [];\r
129                 args.length &&\r
130                         (\r
131                                 args.length === 1 ?\r
132                                         ( temp[ 0 ] = args[ 0 ] ) :\r
133                                         temp.push.apply( temp, args )\r
134                         );\r
135                 supp.length === 1 ?\r
136                         ( temp[ temp.length ] = supp[ 0 ] ) :\r
137                         temp.push.apply( temp, supp );\r
138                 args = temp;\r
139         };\r
140         \r
141         switch( xfunc.k ){\r
142 \r
143                 case X_Callback_THIS_FUNC :\r
144                         return args.length === 0 ? func.call( thisObj ) : func.apply( thisObj, args );\r
145                         \r
146                 case X_Callback_HANDLEEVENT :\r
147                         temp = thisObj[ 'handleEvent' ];\r
148                         if( X.Type.isFunction( temp ) ){\r
149                                 return args.length === 0 ? thisObj[ 'handleEvent' ]() :\r
150                                            args.length === 1 ? thisObj[ 'handleEvent' ]( args[ 0 ] ) : temp.apply( thisObj, args );\r
151                         };\r
152                         break;\r
153                         /*\r
154                         if( temp !== func && X.Type.isFunction( temp ) ){\r
155                                 return args.length === 0 ? thisObj[ 'handleEvent' ]() : temp.apply( thisObj, args );\r
156                         } else\r
157                         if( X.Type.isFunction( thisObj ) ){\r
158                                 return args.length === 0 ? thisObj.call( thisObj ) : thisObj.apply( thisObj, args );\r
159                         };\r
160                         return args.length === 0 ? func.call( thisObj ) : func.apply( thisObj, args );*/\r
161                                                 \r
162                 case X_Callback_FUNC_ONLY :\r
163                         return args.length === 0 ?\r
164                                         func() :\r
165                                 args.length === 1 ?\r
166                                         func( args[ 0 ] ) :\r
167                                         func.apply( null, args );\r
168         };\r
169         return X_Callback_NONE;\r
170 };\r
171 \r
172 function X_Callback_correct( f ){\r
173         var i = X_Callback_LIVE_LIST.indexOf( f ),\r
174                 obj;\r
175         if( i !== -1 ){\r
176                 X_Callback_LIVE_LIST.splice( i, 1 );\r
177                 X_Callback_POOL_LIST[ X_Callback_POOL_LIST.length ] = f;\r
178                 obj = f( X_Closure_COMMAND_BACK );\r
179                 delete obj.k;\r
180                 if( obj.f ) delete obj.f;\r
181                 if( obj.x ) delete obj.x;\r
182                 if( obj.s ) delete obj.s;\r
183                 return true;\r
184         };\r
185         return false;\r
186 };\r
187 \r
188 \r
189 // sys\r
190 X_TEMP.X_Callback_onSystemReady = function( sys ){\r
191         delete X_TEMP.X_Callback_onSystemReady;\r
192         sys.monitor( X_Callback_monitor );\r
193         sys.gc( X_Callback_gc );\r
194 };\r
195 \r
196 function X_Callback_monitor(){\r
197         return {\r
198                 'Callback:Live' : X_Callback_LIVE_LIST.length,\r
199                 'Callback:Pool' : X_Callback_POOL_LIST.length\r
200         };\r
201 };\r
202 function X_Callback_gc(){\r
203         X_Callback_POOL_LIST.length = 0; // ?\r
204 };\r
205 \r
206 X_TEMP.onSystemReady.push( X_TEMP.X_Callback_onSystemReady );\r
207 \r
208 \r
209 console.log( 'X.Core.Callback' );\r
210 \r