OSDN Git Service

Version 0.6.159, fix X.Class & X.XHR.Gadget.
[pettanr/clientJs.git] / 0.6.x / js / 20_ui / 08_Box.js
1 \r
2 var XUI_Layout_Canvas = X[ 'UI' ][ 'Layout' ][ 'Canvas' ] = XUI_createLayout( {\r
3         name : 'CanvasLayout',\r
4         \r
5         overrideAttrsForSelf : {\r
6                 selectable  : false,\r
7                 role        : [ 0, XUI_Dirty.CLEAN, XUI_Attr_USER.UINODE, XUI_Attr_Type.INIT_ONLY | XUI_Attr_Type.LIST, 'none,chrome,container' ],\r
8                 \r
9                 width       : [ '100%',         XUI_Dirty.LAYOUT, XUI_Attr_USER.LAYOUT, XUI_Attr_Type.LENGTH | XUI_Attr_Type.PERCENT ],\r
10                 maxWidth    : [ XUI_Attr_AUTO, XUI_Dirty.LAYOUT, XUI_Attr_USER.LAYOUT, XUI_Attr_Type.LENGTH | XUI_Attr_Type.PERCENT ],\r
11                 height      : [ 0,              XUI_Dirty.LAYOUT, XUI_Attr_USER.LAYOUT, XUI_Attr_Type.LENGTH | XUI_Attr_Type.PERCENT ],\r
12                 maxHeight   : [ XUI_Attr_AUTO, XUI_Dirty.LAYOUT, XUI_Attr_USER.LAYOUT, XUI_Attr_Type.LENGTH | XUI_Attr_Type.PERCENT ]\r
13         },\r
14         \r
15         overrideAttrsForChild : {\r
16                 left   : true,\r
17                 top    : true,\r
18                 bottom : true,\r
19                 right  : true\r
20         },\r
21         \r
22         calculate : function( data, isNeedsDetection, x, y, w, h ){\r
23                 var uinodes, l, i, _x, _y, _w, _h, node;\r
24 \r
25                 data.preMesure( w, h );\r
26                 \r
27                 console.log( w + ' > ' + data.boxWidth );\r
28                 \r
29                 //  data.boxWidth と data.boxHeight のどちらかでも Infinity\r
30                 if( isNeedsDetection && data.boxWidth + data.boxHeight === XUI_Attr_AUTO ) return false;\r
31                 \r
32                 _x = data.contentL;\r
33                 _y = data.contentT;\r
34                 _w = data.contentWidth;\r
35                 _h = data.contentHeight;\r
36 \r
37                 if( ( uinodes = data.uinodes ) && ( l = uinodes.length ) ){\r
38                         console.log( _w + ' x ' + _h + ' l:' + l );\r
39                         for( i = 0; i < l; ++i ){\r
40                                 node = uinodes[ i ];\r
41                                 node.calculate( false, _x, _y, _w, _h );\r
42                         };\r
43                 } else\r
44                 if( data.contentHeight === XUI_Attr_AUTO ){\r
45                         data.contentHeight = data.contentHeightMin !== XUI_Attr_AUTO ? data.contentHeightMin : 0;\r
46                 };\r
47                 \r
48                 data.postMesure();\r
49 \r
50                 if( !isNeedsDetection ){\r
51                         data.boxX += x;\r
52                         data.boxY += y;\r
53                 };\r
54                 return true;\r
55         }\r
56 });\r
57 \r
58 \r
59 var XUI_Box = XUI_AbstractUINode.inherits(\r
60         'X.UI._Box',\r
61         X_Class.NONE,\r
62         {\r
63                 usableAttrs     : XUI_Attr_createAttrDef( XUI_AbstractUINode.prototype.usableAttrs, XUI_Layout_Canvas.overrideAttrsForSelf ),\r
64                 \r
65                 layout          : null,\r
66                 uinodes         : null,\r
67                 xnodes          : null,\r
68                 \r
69                 hitChildData    : null,\r
70                 pointerChildren : true,\r
71                 through         : false,\r
72 \r
73                 scrollingX      : 0, // TODO 現在のスクロール位置\r
74                 scrollingY      : 0, // TODO \r
75 \r
76                 Constructor : function( user, layout, args ){\r
77                         var i = 0,\r
78                                 l = args && args.length,\r
79                                 j = -1,\r
80                                 uinodes, arg, _data, attrs, attrDef, p;\r
81                         \r
82                         //if( !args.length ) args = [ args ];\r
83                         \r
84                         if( !user[ 'instanceOf' ]( X.UI.Box ) ){\r
85                                 //throw new Error( 'Box を継承したインスタンスだけが _Box のオーナーになれます' );\r
86                         };\r
87                         \r
88                         this.User   = user;\r
89                         \r
90                         // TODO デフォルトの attr 指定の中から XNODE に指定するものを集めて適用。\r
91                         this.xnode  = X_Doc_create( 'div' );\r
92                         \r
93                         // すでに定義されていればそちらを採用\r
94                         // usableAttrs や attrClass が、layout を元に上書きされているため\r
95                         this.layout = this.layout || layout;\r
96                         \r
97                         for( ; i < l; ++i ){\r
98                                 arg = args[ i ];\r
99                                 if( arg[ 'instanceOf' ] && arg[ 'instanceOf' ]( X.UI.AbstractUINode ) ){\r
100                                         _data = X_Pair_get( arg );\r
101                                         if( !uinodes ) this.uinodes = uinodes = [];\r
102                                         uinodes[ ++j ] = _data;\r
103                                         if( _data.parent ){\r
104                                                 //throw new Error( 'インスタンスはすでに親に追加されています ' + arg );\r
105                                         };\r
106                                 } else\r
107                                 if( X_Type_isObject( arg ) ){\r
108                                         if( attrs ){\r
109                                                 attrs = X_Class_override( attrs, arg );\r
110                                         } else {\r
111                                                 attrs = arg;\r
112                                         };\r
113                                 } else {\r
114                                         //throw new Error( 'AbstractUINode を継承したインスタンスを渡してください ' + arg );\r
115                                 };\r
116                         };\r
117                         \r
118                         for( p in attrs ){\r
119                                 if( X_EMPTY_OBJECT[ p ] ) continue;\r
120                                 ( attrDef = this.usableAttrs[ p ] ) && this.setAttr( p, attrDef, attrs[ p ] );\r
121                         };\r
122                 },\r
123         /* Rellay */\r
124                 initialize : function( root, rootData, parent, parentData ){\r
125                         var uinodes = this.uinodes,\r
126                                 i       = uinodes && uinodes.length;\r
127                         \r
128                         if( i ){\r
129                                 for( ; i; ){\r
130                                         uinodes[ --i ].initialize( root, rootData, this.User, this );\r
131                                 };                              \r
132                         };\r
133                         \r
134                         XUI_AbstractUINode.prototype.initialize.apply( this, arguments );\r
135                 },\r
136                 \r
137                 addToParent : function( parentXNode ){\r
138                         var uinodes = this.uinodes,\r
139                                 l       = uinodes && uinodes.length,\r
140                                 i;\r
141 \r
142                         if( l ){\r
143                                 for( i = 0; i < l; ++i ){\r
144                                         uinodes[ i ].addToParent( this.xnode );\r
145                                 };\r
146                         };\r
147                         \r
148                         XUI_AbstractUINode.prototype.addToParent.apply( this, arguments );\r
149                 },\r
150                 \r
151         /* Rellay */\r
152                 creationComplete : function(){\r
153                         var uinodes = this.uinodes,\r
154                                 i       = uinodes && uinodes.length;\r
155                         if( i ){\r
156                                 for( ; i; ){\r
157                                         uinodes[ --i ].creationComplete();\r
158                                 };                              \r
159                         };\r
160                         \r
161                         XUI_AbstractUINode.prototype.creationComplete.apply( this, arguments );\r
162                 },\r
163                 \r
164                 calculate : function( isNeedsDetection, x, y, w, h ){\r
165                         var ret = this.layout.calculate( this, isNeedsDetection, x, y, w, h );                  \r
166                         this.phase = 4;\r
167                         return ret;\r
168                 },\r
169         \r
170                 updateLayout : function(){\r
171                         var uinodes = this.uinodes, i, l;\r
172 \r
173                         if( uinodes && ( l = uinodes.length ) ){\r
174                                 for( i = 0; i < l; ++i ){\r
175                                         uinodes[ i ].updateLayout();\r
176                                 };      \r
177                         };\r
178                         XUI_AbstractUINode.prototype.updateLayout.call( this );\r
179                 },\r
180                 \r
181                 capcher : function( x, y ){\r
182                         var uinodes, child, _x, _y, hit, i;\r
183                         if( this.pointerDisabled ) return false;\r
184                         delete this.hitChildData;\r
185                         x -= this.boxX;\r
186                         y -= this.boxY;\r
187                         if( this.pointerChildren && ( uinodes = this.uinodes ) && ( i = uinodes.length ) ){\r
188                                 _x = x - this.scrollingX;\r
189                                 _y = y - this.scrollingY;\r
190                                 for( ; i; ){\r
191                                         child = uinodes[ --i ];\r
192                                         if( !child.pointerDisabled && child.boxX <= _x && _x < child.boxX + child.boxWidth && child.boxY <= _y && _y < child.boxY + child.boxHeight && child.capcher( _x, _y ) ){\r
193                                                 //console.log( 'hit child ' + _x + ' ' + _y + ' boxX:' + child.boxX + ' boxY:' + child.boxY );\r
194                                                 this.hitChildData = child;\r
195                                                 break;\r
196                                         };\r
197                                 };\r
198                         };\r
199                         if( this.through ){\r
200                                 this.hitChildData && !this.hovering && ( this.rootData.hoverList[ this.rootData.hoverList.length ] = this );\r
201                                 return !!this.hitChildData;\r
202                         };\r
203                         hit = 0 <= x && x < this.boxWidth && 0 <= y && y < this.boxHeight;\r
204                         ( this.hitChildData || hit ) && !this.hovering && ( this.rootData.hoverList[ this.rootData.hoverList.length ] = this );\r
205                         if( hit && this.hitChildData === null ) this.rootData.targetNodeData = this;\r
206                         return hit || !!this.hitChildData;\r
207                 },\r
208                 \r
209                 addAt : function( index, _uinodes ){\r
210                         //console.log( '# AddAt ' + this.phase )\r
211                         var uinodes = this.uinodes || ( this.uinodes = [] ),\r
212                                 num     = uinodes.length,\r
213                                 p1      = 1 <= this.phase,\r
214                                 p2      = 2 <= this.phase,\r
215                                 p3      = 3 <= this.phase,\r
216                                 i       = 0,\r
217                                 _p1, _p2,\r
218                                 l, data;\r
219 \r
220                         //console.log( '### AddAt ' + this.phase )\r
221                         for( l = _uinodes.length; i < l; ++i ){\r
222                                 data = X_Pair_get( _uinodes[ i ] );\r
223                                 _p1  = p1 && data.phase < 1;\r
224                                 _p2  = p2 && data.phase < 2;\r
225                                 _p1 && data.initialize( this.root, this.rootData, this.User, this );\r
226                                 if( index < num ){\r
227                                         _p2 && uinodes[ index + i ].xnode[ 'prev' ]( data.xnode );\r
228                                         _p2 && data.addToParent( this.xnode );\r
229                                         uinodes.splice( index + i, 0, data );\r
230                                 } else {\r
231                                         _p2 && data.addToParent( this.xnode );\r
232                                         uinodes[ uinodes.length ] = data;\r
233                                 };\r
234                                 p3 && data.phase < 3 && data.creationComplete();\r
235                         };\r
236                         4 <= this.phase && this.rootData.reserveCalc();\r
237                 },\r
238                 \r
239                 remove : function( _uinodes ){\r
240                         //console.log( '# AddAt ' + this.phase )\r
241                         var uinodes = this.uinodes,\r
242                                 i       = _uinodes.length,\r
243                                 n, data;\r
244 \r
245                         //console.log( '### AddAt ' + this.phase )\r
246                         for( ; i; ){\r
247                                 data = X_Pair_get( _uinodes[ --i ] );\r
248                                 if( ( n = uinodes.indexOf( data ) ) !== -1 ){\r
249                                         uinodes.splice( n, 1 );\r
250                                         data._remove();\r
251                                 };\r
252                         };\r
253                         4 <= this.phase && this.rootData.reserveCalc();\r
254                 },\r
255                 \r
256                 removeAt : function( from, length ){\r
257                         var uinodes = this.uinodes,\r
258                                 i       = uinodes.length,\r
259                                 to      = from + ( X_Type_isNumber( length ) && 1 <= length ? length : 1 ),\r
260                                 node;\r
261                         for( ; i; ){\r
262                                 node = uinodes[ --i ];\r
263                                 if( from <= i && i < to ){\r
264                                         uinodes.splice( i, 1 );\r
265                                         node._remove();\r
266                                 };\r
267                         };\r
268                         4 <= this.phase && this.rootData.reserveCalc();\r
269                 },\r
270                 \r
271                 _remove : function(){\r
272                         var uinodes = this.uinodes,\r
273                                 i       = uinodes.length;\r
274                         for( ; i; ){ uinodes[ --i ]._remove(); };\r
275                                         \r
276                         switch( this.phase ){\r
277                                 case 4:\r
278                                 case 3:\r
279                                 case 2:\r
280                                         this.xnode[ 'remove' ]();\r
281                                 case 1:\r
282                                         delete this.root;\r
283                                         delete this.rootData;\r
284                                         delete this.parent;\r
285                                         delete this.parentData;\r
286                                         delete this.xnode;\r
287                         };\r
288                         delete this.phase;\r
289                 }\r
290         }\r
291 );\r
292 \r
293 X.UI.Box = X.UI.AbstractUINode.inherits(\r
294         'Box',\r
295         X_Class.NONE,\r
296         {\r
297                 Constructor : function(){\r
298                         X_Pair_create( this, XUI_Box( this, XUI_Layout_Canvas, arguments ) );\r
299                 },\r
300                 \r
301                 add : function( /* node, node, node ... */ ){\r
302                         X_Pair_get( this ).addAt( this.numNodes() + 1, X_Object_cloneArray( arguments ) );\r
303                         return this;\r
304                 },\r
305                 addAt : function( index /* , node , node, node ... */ ){\r
306                         var nodes;\r
307                         if( index < 0 ) index = 0;\r
308                         nodes = X_Object_cloneArray( arguments );\r
309                         X_Pair_get( this ).addAt( nodes.shift(), nodes );\r
310                         return this;\r
311                 },\r
312                 remove : function( /* node, node, node ... */ ){\r
313                         X_Pair_get( this )[ 'remove' ]( X_Object_cloneArray( arguments ) );\r
314                         return this;\r
315                 },\r
316                 removeAt : function( from, length ){\r
317                         X_Pair_get( this ).removeAt( from, length );\r
318                         return this;\r
319                 },\r
320                 getNodesByClass : function( klass ){\r
321                         var ret     = [],\r
322                                 uinodes = X_Pair_get( this ).uinodes,\r
323                                 i, l, node;\r
324                         if( !uinodes || uinodes.length === 0 ) return ret;\r
325                         for( i = 0, l = uinodes.length; i < l; ++i ){\r
326                                 node = uinodes[ i ].User;\r
327                                 if( node[ 'instanceOf' ]( klass ) ) ret[ ret.length ] = node;\r
328                         };\r
329                         return ret;\r
330                 },\r
331                 getFirstChild : function(){\r
332                         return this.getNodeAt( 0 );\r
333                 },\r
334                 getLastChild : function(){\r
335                         var uinodes = X_Pair_get( this ).uinodes;\r
336                         return uinodes && uinodes.length && uinodes[ uinodes.length - 1 ].User || null;\r
337                 },\r
338                 getNodeAt : function( index ){\r
339                         if( index < 0 ) return null;\r
340                         var uinodes = X_Pair_get( this ).uinodes;\r
341                         return uinodes && uinodes[ index ].User || null;\r
342                 },\r
343                 numNodes : function(){\r
344                         var uinodes = X_Pair_get( this ).uinodes;\r
345                         return uinodes && uinodes.length || 0;\r
346                 },\r
347                 \r
348                 clone : function( opt_cloneListener ){\r
349                         var clone   = XUI_AbstractUINode.prototype.clone.call( this,  opt_cloneListener ),\r
350                                 uinodes = X_Pair_get( this ).uinodes,\r
351                                 i       = 0,\r
352                                 l       = uinodes && uinodes.length,\r
353                                 copies  = [];\r
354                         \r
355                         for( ; i < l; ++i ){\r
356                                 copies[ i ] = uinodes[ i ].clone( opt_cloneListener );\r
357                         };\r
358 \r
359                         return l ? clone.add.apply( clone, copies ) : clone;\r
360                 }\r
361         }\r
362 );\r
363 \r
364 /*\r
365  * layout が設定されている Box のサブクラスに対して、layout を指定できない.\r
366  * \r
367  */\r
368 X.UI.Box.presets = function(){\r
369         var args   = arguments,\r
370                 i      = 0,\r
371                 l      = args.length,   \r
372                 shadow = X_Class_getClassDef( this ).privateClass,\r
373                 layout = shadow.prototype.layout,\r
374                 arg, attrs, supports, klass, klassDef, privateKlass, boxName;\r
375                         \r
376         for( ; i < l; ++i ){\r
377                 arg = args[ i ];\r
378                 if( !arg ) continue;\r
379                 // レイアウトの preset ができるのは layout が未定義な Box だけ\r
380                 if( !shadow.prototype.layout && arg[ 'instanceOf' ] && arg[ 'instanceOf' ]( XUI_LayoutBase ) ){\r
381                         layout = arg;\r
382                 } else\r
383                 if( ( klassDef = X_Class_getClassDef( arg ) ) && klassDef.isPrivate ){\r
384                         privateKlass = arg;\r
385                         layout = privateKlass.prototype.layout;\r
386                 } else\r
387                 if( X_Type_isObject( arg ) ){\r
388                         if( attrs ){\r
389                                 X_Class_override( attrs, arg, true );\r
390                         } else {\r
391                                 attrs = arg;\r
392                         };\r
393                 } else\r
394                 if( X_Type_isString( arg ) ){\r
395                         boxName = arg;\r
396                 };\r
397         };\r
398         \r
399         if( privateKlass ){\r
400                 /*\r
401                  * スーパークラスの属性定義リストをレイアウトの持つ属性定義で上書きした新しい属性定義リストを作る。\r
402                  */\r
403                 supports = XUI_Attr_createAttrDef( privateKlass.prototype.usableAttrs, layout.overrideAttrsForSelf );\r
404                 \r
405                 klass = this.inherits( privateKlass );\r
406                 privateKlass.prototype.usableAttrs = supports;\r
407                 privateKlass.prototype.attrClass    = XUI_Attr_preset( privateKlass.prototype.attrClass, supports, attrs );\r
408         } else {\r
409                 supports = XUI_Attr_createAttrDef( shadow.prototype.usableAttrs, layout.overrideAttrsForSelf );\r
410                 \r
411                 klass = this.inherits(\r
412                         boxName,\r
413                         shadow.inherits(\r
414                                 {\r
415                                         layout       : layout,\r
416                                         usableAttrs : supports,\r
417                                         attrClass    : XUI_Attr_preset( shadow.prototype.attrClass, supports, attrs )\r
418                                 }\r
419                         )\r
420                 );              \r
421         };\r
422 \r
423         klass.presets = this.presets || X.UI.Box.presets;\r
424         \r
425         return klass;\r
426 };\r