OSDN Git Service

cdd5433ff2718dce73595d400e1a339a4de53279
[pettanr/clientJs.git] / 0.6.x / js / ui / 08_Box.js
1 \r
2 X.UI.Layout.Canvas = X.UI.Layout.create( {\r
3         name : 'CanvasLayout',\r
4         \r
5         overrideAttrsForSelf : {\r
6                 selectable  : false,\r
7                 role        : [ 0, X.UI.Dirty.CLEAN, X.UI.Attr.USER.UINODE, X.UI.Attr.Type.INIT_ONLY | X.UI.Attr.Type.LIST, 'none,chrome,container' ],\r
8                 \r
9                 width       : [ '100%',         X.UI.Dirty.LAYOUT, X.UI.Attr.USER.LAYOUT, X.UI.Attr.Type.LENGTH | X.UI.Attr.Type.PERCENT ],\r
10                 maxWidth    : [ X.UI.Attr.AUTO, X.UI.Dirty.LAYOUT, X.UI.Attr.USER.LAYOUT, X.UI.Attr.Type.LENGTH | X.UI.Attr.Type.PERCENT ],\r
11                 height      : [ 0,              X.UI.Dirty.LAYOUT, X.UI.Attr.USER.LAYOUT, X.UI.Attr.Type.LENGTH | X.UI.Attr.Type.PERCENT ],\r
12                 maxHeight   : [ X.UI.Attr.AUTO, X.UI.Dirty.LAYOUT, X.UI.Attr.USER.LAYOUT, X.UI.Attr.Type.LENGTH | X.UI.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                 if( isNeedsDetection && ( data.boxWidth === X.UI.Attr.AUTO || data.boxHeight === X.UI.Attr.AUTO ) ) return;\r
28                 \r
29                 _x = data.contentL;\r
30                 _y = data.contentT;\r
31                 _w = data.contentWidth;\r
32                 _h = data.contentHeight;\r
33 \r
34                 if( ( uinodes = data.uinodes ) && ( l = uinodes.length ) ){\r
35                         for( i = 0; i < l; ++i ){\r
36                                 node = uinodes[ i ];\r
37                                 node.calculate( false, _x, _y, _w, _h );        \r
38                         };\r
39                 } else\r
40                 if( data.contentHeight === X.UI.Attr.AUTO ){\r
41                         data.contentHeight = data.minContentHeight !== X.UI.Attr.AUTO ? data.minContentHeight : 0;\r
42                 };\r
43                 \r
44                 data.postMesure();\r
45                 data.updateLayout( x + data.boxX, y + data.boxY );\r
46         }\r
47 });\r
48 \r
49 \r
50 var _Box = _AbstractUINode.inherits(\r
51         '_Box',\r
52         X.Class.PRIVATE_DATA | X.Class.SUPER_ACCESS, // 現状 super 指定がないとconstructor未定擬時に親のconstructor が使われない\r
53         {\r
54                 layout          : null,\r
55                 uinodes         : null,\r
56                 xnodes          : null,\r
57                 \r
58                 hitChildData    : null,\r
59                 pointerChildren : true,\r
60                 through         : false,\r
61 \r
62                 scrollingX      : 0,\r
63                 scrollingY      : 0,\r
64 \r
65                 Constructor : function( layout, args ){\r
66                         var i = 0,\r
67                                 l = args.length,\r
68                                 j = -1,\r
69                                 uinodes, arg, _data, attrs, support;\r
70                         \r
71                         if( !this.User.instanceOf( Box ) ){\r
72                                 //throw new Error( 'Box を継承したインスタンスだけが _Box のオーナーになれます' );\r
73                         };                      \r
74                         \r
75                         this.xnode  = X.Dom.Node.create( 'div' );\r
76                         \r
77                         // すでに定義されていればそちらを採用\r
78                         // supportAttrs や attrClass が、layout を元に上書きされているため\r
79                         this.layout = this.layout || layout;\r
80                         \r
81                         for( ; i < l; ++i ){\r
82                                 arg = args[ i ];\r
83                                 if( arg.instanceOf && arg.instanceOf( AbstractUINode ) ){\r
84                                         _data = X.Class._getPrivate( arg );\r
85                                         if( !uinodes ) this.uinodes = uinodes = [];\r
86                                         uinodes[ ++j ] = _data;\r
87                                         if( _data.parent ){\r
88                                                 //throw new Error( 'インスタンスはすでに親に追加されています ' + arg );\r
89                                         };\r
90                                 } else\r
91                                 if( arg.instanceOf && arg.instanceOf( X.UI.Layout.Base ) ){\r
92                                         //this.layout = arg;\r
93                                 } else\r
94                                 if( X.Type.isObject( arg ) ){\r
95                                         if( attrs ){\r
96                                                 attrs = X.Class._override( attrs, arg );\r
97                                         } else {\r
98                                                 attrs = arg;\r
99                                         };\r
100                                 } else {\r
101                                         //throw new Error( 'AbstractUINode を継承したインスタンスを渡してください ' + arg );\r
102                                 };\r
103                         };\r
104                         \r
105                         for( p in attrs ){\r
106                                 ( support = this.supportAttrs[ p ] ) && this.setAttr( p, support, attrs[ p ] );\r
107                         };\r
108                 },\r
109         /* Rellay */\r
110                 initialize : function( root, rootData, parent, parentData ){\r
111                         var uinodes = this.uinodes,\r
112                                 i       = uinodes && uinodes.length;\r
113                         this.root       = root;\r
114                         this.rootData   = rootData;\r
115                         this.parent     = parent;\r
116                         this.parentData = parentData;\r
117                         //this.xnode      = X.Dom.Node.create( 'div' );\r
118                         \r
119                         if( i ){\r
120                                 for( ; i; ){\r
121                                         uinodes[ --i ].initialize( root, rootData, this.User, this );\r
122                                 };                              \r
123                         };\r
124                         \r
125                         this.phase = 1;\r
126                         this.User.dispatch( { type : X.UI.Event.INIT } );\r
127                 },\r
128                 \r
129                 addToParent : function( parentXNode ){\r
130                         var uinodes = this.uinodes,\r
131                                 l       = uinodes && uinodes.length,\r
132                                 i;\r
133 \r
134                         parentXNode && parentXNode.append( this.xnode );\r
135                         \r
136                         if( l ){\r
137                                 for( i = 0; i < l; ++i ){\r
138                                         uinodes[ i ].addToParent( this.xnode );\r
139                                 };\r
140                         };\r
141                         \r
142                         this.phase = 2;\r
143                         this.User.dispatch( { type : X.UI.Event.ADDED } );\r
144                 },\r
145                 \r
146         /* Rellay */\r
147                 creationComplete : function(){\r
148                         var uinodes = this.uinodes,\r
149                                 i       = uinodes && uinodes.length;\r
150                         if( i ){\r
151                                 for( ; i; ){\r
152                                         uinodes[ --i ].creationComplete();\r
153                                 };                              \r
154                         };\r
155                         \r
156                         _AbstractUINode.prototype.creationComplete.apply( this, arguments );\r
157                 },\r
158                 \r
159                 calculate : function( isNeedsDetection, x, y, w, h ){\r
160                         this.layout.calculate( this, isNeedsDetection, x, y, w, h );                    \r
161                         this.phase = 4;\r
162                 },\r
163                 \r
164                 capcher : function( x, y ){\r
165                         var uinodes, child, _x, _y, hit, i;\r
166                         if( this.pointerDisabled ) return false;\r
167                         delete this.hitChildData;\r
168                         x -= this.boxX;\r
169                         y -= this.boxY;\r
170                         if( this.pointerChildren && ( uinodes = this.uinodes ) && ( i = uinodes.length ) ){\r
171                                 _x = x - this.scrollingX;\r
172                                 _y = y - this.scrollingY;\r
173                                 for( ; i; ){\r
174                                         child = uinodes[ --i ];\r
175                                         if( !child.pointerDisabled && child.boxX <= _x && _x < child.boxX + child.boxWidth && child.boxY <= _y && _y < child.boxY + child.boxHeight && child.capcher( _x, _y ) ){\r
176                                                 //console.log( 'hit child ' + _x + ' ' + _y + ' boxX:' + child.boxX + ' boxY:' + child.boxY );\r
177                                                 this.hitChildData = child;\r
178                                                 break;\r
179                                         };\r
180                                 };\r
181                         };\r
182                         if( this.through ){\r
183                                 this.hitChildData && !this.hovering && ( this.rootData.hoverList[ this.rootData.hoverList.length ] = this );\r
184                                 return !!this.hitChildData;\r
185                         };\r
186                         hit = 0 <= x && x < this.boxWidth && 0 <= y && y < this.boxHeight;\r
187                         ( this.hitChildData || hit ) && !this.hovering && ( this.rootData.hoverList[ this.rootData.hoverList.length ] = this );\r
188                         if( hit && this.hitChildData === null ) this.rootData.targetNodeData = this;\r
189                         return hit || !!this.hitChildData;\r
190                 },\r
191                 \r
192                 addAt : function( index, _uinodes ){\r
193                         //console.log( '# AddAt ' + this.phase )\r
194                         var uinodes = this.uinodes,\r
195                                 num     = uinodes.length,\r
196                                 p1      = 1 <= this.phase,\r
197                                 p2      = 2 <= this.phase,\r
198                                 p3      = 3 <= this.phase,\r
199                                 i       = 0,\r
200                                 _p1, _p2,\r
201                                 l, data;\r
202 \r
203                         //console.log( '### AddAt ' + this.phase )\r
204                         for( l = _uinodes.length; i < l; ++i ){\r
205                                 data = X.Class._getPrivate( _uinodes[ i ] );\r
206                                 _p1  = p1 && data.phase < 1;\r
207                                 _p2  = p2 && data.phase < 2;\r
208                                 _p1 && data.initialize( this.root, this.rootData, this.User, this );\r
209                                 if( index <= num ){\r
210                                         // _p2 && this.xnode.insertBefore( data.xnode, uinodes[ index + i ].xnode );\r
211                                         _p2 && uinodes[ index + i ].xnode.before( data.xnode );\r
212                                         _p2 && data.addToParent( this.xnode );\r
213                                         uinodes.splice( index + i, 0, data );\r
214                                 } else {\r
215                                         _p2 && data.addToParent( this.xnode );\r
216                                         uinodes[ uinodes.length ] = data;       \r
217                                 };\r
218                                 p3 && data.phase < 3 && data.creationComplete();\r
219                         };\r
220                         4 <= this.phase && this.rootData.reserveCalc();\r
221                 },\r
222                 \r
223                 remove : function( _uinodes ){\r
224                         //console.log( '# AddAt ' + this.phase )\r
225                         var uinodes = this.uinodes,\r
226                                 i       = _uinodes.length,\r
227                                 n, data;\r
228 \r
229                         //console.log( '### AddAt ' + this.phase )\r
230                         for( ; i; ){\r
231                                 data = X.Class._getPrivate( _uinodes[ --i ] );\r
232                                 if( ( n = uinodes.indexOf( data ) ) !== -1 ){\r
233                                         uinodes.splice( n, 1 );\r
234                                         data._remove();\r
235                                 };\r
236                         };\r
237                         4 <= this.phase && this.rootData.reserveCalc();\r
238                 },\r
239                 \r
240                 removeAt : function( from, length ){\r
241                         var uinodes = this.uinodes,\r
242                                 i       = uinodes.length,\r
243                                 to      = from + ( X.Type.isNumber( length ) && 1 <= length ? length : 1 ),\r
244                                 node;\r
245                         for( ; i; ){\r
246                                 node = uinodes[ --i ];\r
247                                 if( from <= i && i < to ){\r
248                                         uinodes.splice( i, 1 );\r
249                                         node._remove();\r
250                                 };\r
251                         };\r
252                         4 <= this.phase && this.rootData.reserveCalc();\r
253                 },\r
254                 \r
255                 _remove : function(){\r
256                         var uinodes = this.uinodes,\r
257                                 i       = uinodes.length;\r
258                         for( ; i; ){ uinodes[ --i ]._remove(); };\r
259                                         \r
260                         switch( this.phase ){\r
261                                 case 4:\r
262                                 case 3:\r
263                                 case 2:\r
264                                         this.xnode.remove();\r
265                                 case 1:\r
266                                         delete this.root;\r
267                                         delete this.rootData;\r
268                                         delete this.parent;\r
269                                         delete this.parentData;\r
270                                         delete this.xnode;\r
271                         };\r
272                         delete this.phase;\r
273                 }\r
274         }\r
275 );\r
276 \r
277 var Box = AbstractUINode.inherits(\r
278         'Box',\r
279         X.Class.SUPER_ACCESS,\r
280         _Box,\r
281         {\r
282                 Constructor : function(){\r
283                         X.Class._newPrivate( this, X.UI.Layout.Canvas, arguments );\r
284                 },\r
285                 \r
286                 add : function( node /* , node, node ... */ ){\r
287                         X.Class._getPrivate( this ).addAt( this.numNodes() + 1, Array.prototype.slice.call( arguments ) );\r
288                         return this;\r
289                 },\r
290                 addAt : function( index, node /* , node, node ... */ ){\r
291                         if( index < 0 ) index = 0;\r
292                         X.Class._getPrivate( this ).addAt( arguments[ 0 ], Array.prototype.slice.call( arguments, 1 ) );\r
293                         return this;\r
294                 },\r
295                 remove : function( node /* , node, node ... */ ){\r
296                         X.Class._getPrivate( this ).remove( Array.prototype.slice.call( arguments ) );\r
297                         return this;\r
298                 },\r
299                 removeAt : function( from, length ){\r
300                         X.Class._getPrivate( this ).removeAt( from, length );\r
301                         return this;\r
302                 },\r
303                 getNodesByClass : function( klass ){\r
304                         var ret     = [],\r
305                                 uinodes = X.Class._getPrivate( this ).uinodes,\r
306                                 i, l, node;\r
307                         if( !uinodes || uinodes.length === 0 ) return ret;\r
308                         for( i = 0, l = uinodes.length; i < l; ++i ){\r
309                                 node = uinodes[ i ].User;\r
310                                 if( node.instanceOf( klass ) ) ret[ ret.length ] = node;\r
311                         };\r
312                         return ret;\r
313                 },\r
314                 getFirstChild : function(){\r
315                         return this.getNodeAt( 0 );\r
316                 },\r
317                 getLastChild : function(){\r
318                         var uinodes = X.Class._getPrivate( this ).uinodes;\r
319                         return uinodes && uinodes.length && uinodes[ uinodes.length - 1 ].User || null;\r
320                 },\r
321                 getNodeAt : function( index ){\r
322                         if( index < 0 ) return null;\r
323                         var uinodes = X.Class._getPrivate( this ).uinodes;\r
324                         return uinodes && uinodes[ index ].User || null;\r
325                 },\r
326                 numNodes : function(){\r
327                         var uinodes = X.Class._getPrivate( this ).uinodes;\r
328                         return uinodes && uinodes.length || 0;\r
329                 }\r
330         }\r
331 );\r
332 \r
333 /*\r
334  * layout が設定されている Box のサブクラスに対して、layout を指定できない.\r
335  * \r
336  */\r
337 Box.presets = function(){\r
338         var args   = arguments,\r
339                 i      = 0,\r
340                 l      = args.length,   \r
341                 shadow = X.Class._getClassDef( this ).privateClass,\r
342                 layout = shadow.prototype.layout,\r
343                 arg, attrs, supports, klass, klassDef, privateKlass, boxName;\r
344                         \r
345         for( ; i < l; ++i ){\r
346                 arg = args[ i ];\r
347                 if( !arg ) continue;\r
348                 // レイアウトの preset ができるのは layout が未定義な Box だけ\r
349                 if( !shadow.prototype.layout && arg.instanceOf && arg.instanceOf( X.UI.Layout.Base ) ){\r
350                         layout = arg;\r
351                 } else\r
352                 if( ( klassDef = X.Class._getClassDef( arg ) ) && klassDef.isPrivate ){\r
353                         privateKlass = arg;\r
354                         layout = privateKlass.prototype.layout;\r
355                 } else\r
356                 if( X.Type.isObject( arg ) ){\r
357                         if( attrs ){\r
358                                 X.Class._override( attrs, arg, true );\r
359                         } else {\r
360                                 attrs = arg;\r
361                         };\r
362                 } else\r
363                 if( X.Type.isString( arg ) ){\r
364                         boxName = arg;\r
365                 };\r
366         };\r
367         \r
368         if( privateKlass ){\r
369                 supports = X.UI.Attr.createAttrDef( privateKlass.prototype.supportAttrs, layout.overrideAttrsForSelf );\r
370                 \r
371                 klass = this.inherits( privateKlass );\r
372                 privateKlass.prototype.supportAttrs = supports,\r
373                 privateKlass.prototype.attrClass    = privateKlass.prototype.attrClass( supports, attrs );\r
374         } else {\r
375                 supports = X.UI.Attr.createAttrDef( shadow.prototype.supportAttrs, layout.overrideAttrsForSelf );\r
376                 \r
377                 klass = this.inherits(\r
378                         boxName,\r
379                         shadow.inherits(\r
380                                 {\r
381                                         layout       : layout,\r
382                                         supportAttrs : supports,\r
383                                         attrClass    : shadow.prototype.attrClass( supports, attrs )\r
384                                 }\r
385                         )\r
386                 );              \r
387         };\r
388 \r
389         klass.presets = this.presets || Box.presets;\r
390         \r
391         return klass;\r
392 };\r