OSDN Git Service

7bebfa4e1f3621e2c72eca1c9c589c09f578455b
[pettanr/clientJs.git] / 0.6.x / js / ui / 06_AbstractUINode.js
1 var _AbstractUINode = X.EventDispatcher.inherits(\r
2         '_AbstractUINode',\r
3         X.Class.ABSTRACT | X.Class.PRIVATE_DATA,\r
4         {\r
5                 phase         : 0,\r
6                 root          : null,\r
7                 rootData      : null,\r
8                 parent        : null,\r
9                 parentData    : null,\r
10                 rawElement    : null,\r
11                 rawStyle      : null,\r
12                 \r
13                 //events        : null, // X.EventDispatcher で設定される\r
14                 reserveEvents : null,\r
15                 gesture       : null,\r
16                 //elmScroll     : null,\r
17                 //elmScroller   : null,\r
18                 //elmScrollbar  : null,\r
19                                 \r
20                 style         : null,\r
21                 styleData     : null,\r
22                 forChrome     : false, // メッキ\r
23 \r
24                 x              : 0,\r
25                 y              : 0,\r
26                 w              : 0,\r
27                 h              : 0,\r
28                 t              : 0, // top\r
29                 l              : 0, // left\r
30                 b              : 0, // bottom\r
31                 r              : 0, // right\r
32                 absoluteX      : 0,\r
33                 absoluteY      : 0,\r
34                 //_scrollX       : 0,\r
35                 //_scrollY       : 0,\r
36                 scrollingX     : 0,\r
37                 scrollingY     : 0,\r
38                 _cursor        : '',\r
39                 hitChildData   : null,\r
40                 hitSelf        : false,\r
41                 _disabled      : false,\r
42                 _childDisabled : false,\r
43                 through        : false,\r
44                 clip           : false,\r
45                 hover          : false,\r
46                 hoverStyleName : null,\r
47                 isHover        : false,\r
48                 scroll         : false,\r
49                 dragdrop       : false,\r
50                 tooltip        : null,\r
51                 \r
52                 _content          : null,\r
53                 updateContent     : false,\r
54                 \r
55                 boxWidth          : 0,\r
56                 boxHeight         : 0,\r
57                 contentL          : 0,\r
58                 contentT          : 0,\r
59                 contentR          : 0,\r
60                 contentB          : 0,\r
61                 boxSizingOffsetLR : 0,\r
62                 boxSizingOffsetTB : 0,          \r
63                 contentWidth      : 0,\r
64                 minContentWidth   : 0,\r
65                 maxContentWidth   : AUTO,\r
66                 lastContentWidth  : -1,\r
67                 contentHeight     : 0,\r
68                 minContentHeight  : 0,\r
69                 maxContentHeight  : AUTO,\r
70                 \r
71                 // :hover, :focus, :disabled\r
72                 \r
73                 initialize : function( root, rootData, parent, parentData ){\r
74                         this.root       = root;\r
75                         this.rootData   = rootData;\r
76                         this.parent     = parent;\r
77                         this.parentData = parentData;\r
78                         this.rawElement = X.Dom.Node.create( 'div' );\r
79                         \r
80                         this.styleData.initialize();\r
81                         \r
82                         this.phase = 1;\r
83                         this.dispatch( { type : X.UI.Event.INIT } );\r
84                 },\r
85                 \r
86                 addToParent : function( parentElement ){\r
87                         //parentElement && parentElement.appendChild( this.rawElement );\r
88                         parentElement && parentElement.append( this.rawElement );\r
89                         \r
90                         this.phase = 2;\r
91                         this.dispatch( { type : X.UI.Event.ADDED } );\r
92                 },\r
93 \r
94         /* Rellay\r
95                 afterAddition : function(){\r
96                         this.styleData.afterAddition();\r
97                         \r
98                         this.phase = 3;\r
99                         this.dispatch( { type : X.UI.Event.CREATION_COMPLETE } );\r
100                 }, */\r
101                 \r
102                 creationComplete : function(){\r
103                         if( this.phase < 3 ) return;\r
104                         \r
105                         var nodes  = this.nodes,\r
106                                 events = this.reserveEvents,\r
107                                 l, i;\r
108                         if( nodes ){\r
109                                 for( i = 0, l = nodes.length; i < l; ++i ){\r
110                                         nodes[ i ].creationComplete();\r
111                                 };\r
112                         };\r
113                         this.mesure();\r
114                         \r
115                         // this.scroll === true && ScrollBarManager.register( this );\r
116                         \r
117                         // html 要素が親に追加されるまで控えていたイベントの登録\r
118                         if( events && ( l = events.length ) ){\r
119                                 for( i = 0; i < l; ++i ){\r
120                                         this.listen.apply( this, events[ i ] );\r
121                                 };\r
122                                 events.length = 0;\r
123                                 delete this.reserveEvents;\r
124                         };\r
125                 },\r
126                 \r
127                 mesure : function(){\r
128                         var elm = this.rawElement,\r
129                                 x, y, w, h, parent;\r
130                         if( elm ){\r
131                                 w = elm.width();//w = elm.offsetWidth;\r
132                                 h = elm.height();//h = elm.offsetHeight;\r
133                                 x = elm.x();//x = elm.offsetLeft;\r
134                                 y = elm.y();//y = elm.offsetTop;                                \r
135                                 if( this.x !== x || this.y !== y || this.w !== w || this.h !== h ){\r
136                                         this.x = x;\r
137                                         this.y = y;\r
138                                         this.w = w;\r
139                                         this.h = h;\r
140                                         ( parent = this.parentData ) && this.updateAbsoluteXY( parent.absoluteX, parent.absoluteY );\r
141                                 };                      \r
142                         };\r
143                         this.updateRectangle();\r
144                 },\r
145                 \r
146                 updateAbsoluteXY : function( x, y /* , scrollX, scrollY */ ){\r
147                         var nodes = this.nodes, i;\r
148                         this.absoluteX = x = this.x + x;\r
149                         this.absoluteY = y = this.y + y;\r
150                         if( !nodes ) return;\r
151                         for( i = nodes.length; i; ){\r
152                                 nodes[ --i ].updateAbsoluteXY( x, y );\r
153                         };\r
154                 },\r
155                 \r
156                 updateRectangle : function(){\r
157                         var w = this.w, h = this.h, x = this.x, y = this.y,\r
158                                 l = x, t = y, r = x + w, b = y + h,\r
159                                 nodes = this.nodes, i, node;\r
160                                 \r
161                         if( nodes && this.clip === false ){\r
162                                 for( i = nodes.length; i; ){\r
163                                         node = nodes[ --i ];\r
164                                         if( node.l + x < l ) l = x + node.l;\r
165                                         if( node.t + y < t ) t = y + node.t;\r
166                                         if( r < node.r + x ) r = x + node.r;\r
167                                         if( b < node.b + y ) b = y + node.b;\r
168                                 };\r
169                         };\r
170                         // update\r
171                         if( b !== this.b || r !== this.r || t !== this.t || l !== this.l ){\r
172                                 this.l = l;\r
173                                 this.t = t;\r
174                                 this.r = r;\r
175                                 this.b = b;\r
176                                 this.parentData && this.parentData.clip === false && this.parentData.updateRectangle();\r
177                         };\r
178                 },\r
179                 \r
180                 capcher : function( x, y ){\r
181                         var nodes, child, _x, _y, hit, i;\r
182                         if( this._disabled === true ) return false;\r
183                         delete this.hitChildData;\r
184                         x -= this.x;\r
185                         y -= this.y;\r
186                         // この部分 Box に移動\r
187                         if( nodes = this.nodes ){\r
188                                 _x = x - this.scrollingX;\r
189                                 _y = y - this.scrollingY;\r
190                                 for( i = nodes.length; i; ){\r
191                                         child = nodes[ --i ];\r
192                                         if( child._disabled === false && child.l <= _x && _x < child.r && child.t <= _y && _y < child.b && child.capcher( _x, _y ) === true ){\r
193                                                 this.hitChildData = child;\r
194                                                 break;\r
195                                         };\r
196                                 };\r
197                         };\r
198                         if( this.through === true ){\r
199                                 this.hitChildData && this.hitSelf === false && this.rootData.hoverList.push( this );\r
200                                 return !!this.hitChildData;\r
201                         };\r
202                         hit = 0 <= x && x < this.w && 0 <= y && y < this.h;\r
203                         ( this.hitChildData || hit ) && this.hitSelf === false && this.rootData.hoverList.push( this );\r
204                         if( hit === true && this.hitChildData === null ) this.rootData.targetNodeData = this;\r
205                         return hit || !!this.hitChildData;\r
206                 },\r
207                 \r
208                 _remove : function(){\r
209                         switch( this.phase ){\r
210                                 case 4:\r
211                                 case 3:\r
212                                         //this.styleData.afterAddition();\r
213                                 case 2:\r
214                                         //this.rawElement.parentNode.removeChild( this.rawElement );\r
215                                         this.rawElement.remove();\r
216                                 case 1:\r
217                                         //this.styleData.initialize();\r
218                                         delete this.root;\r
219                                         delete this.rootData;\r
220                                         delete this.parent;\r
221                                         delete this.parentData;\r
222                                         delete this.rawElement;\r
223                         };\r
224                         delete this.phase;\r
225                 },\r
226                 //killed\r
227                 \r
228                 \r
229                 content : function( v ){\r
230                         if( Type.isString( v ) === true ){\r
231                                 if( !this.rawText || this.rawText.data !== v ){\r
232                                         this._content = v;\r
233                                         this.updateContent = true;\r
234                                 };\r
235                                 return this.User;\r
236                         } else\r
237                         if( v === null ){\r
238                                 if( this._content !== v && this.rawText ){\r
239                                         this.updateContent = true;\r
240                                 };\r
241                                 delete this._content;\r
242                                 return this.User;\r
243                         };\r
244                         if( this._content || this._content === null ) return this._content;\r
245                         if( this.rawText ) return this.rawText.data;\r
246                         return null;\r
247                 },\r
248 \r
249 \r
250 \r
251                 /*\r
252                  * 親の サイズを元に自身のサイズを計算していく\r
253                  */\r
254                 preMesure : function( allowW, allowH ){\r
255                         var style    = this.styleData,\r
256                                 styles, calc, box, min, max,\r
257                                 contentW, contentH, boxMinus,\r
258                                 paddingT, paddingR, paddingB, paddingL,\r
259                                 borderT, borderR, borderB, borderL;\r
260 \r
261                         if( style ){\r
262                                 styles   = style.data;\r
263                                 calc     = _AbstractUINode.calcValue;\r
264                                 box      = styles[ X.Css.AttrNo.sizing ];\r
265                                 \r
266                                 // Width が確定するパターン\r
267                                 // 自身が constraintW の場合 親が AUTO ではない\r
268                                 // 自身が constraintW でない場合自身が  AUTO はなくかつ親 が AUTO の場合 or 自身は % でない\r
269                                 if( style.constraintW ? allowW !== AUTO : !style.autoWidth && ( allowW !== AUTO || !style.percentWidth ) ){\r
270                                         if( style.constraintW ){ // 制約レイアウト\r
271                                                 contentW = allowW - calc( styles[ X.Css.AttrNo.left ], allowW ) - calc( styles[ X.Css.AttrNo.right ], allowW );\r
272                                         } else {\r
273                                                 contentW = _AbstractUINode.finalValue( styles[ X.Css.AttrNo.width ], styles[ X.Css.AttrNo.minWidth ], styles[ X.Css.AttrNo.maxWidth ], allowW );                                        \r
274                                         };\r
275                                         paddingR = calc( styles[ X.Css.AttrNo.padding + 1 ], allowW );\r
276                                         paddingL = calc( styles[ X.Css.AttrNo.padding + 3 ], allowW );\r
277                                         borderR  = styles[ X.Css.AttrNo.border + 1 ];\r
278                                         borderL  = styles[ X.Css.AttrNo.border + 3 ];\r
279                                         boxMinus = 0;\r
280                                         switch( box ){\r
281                                                 case 2 : // border-box\r
282                                                          boxMinus -= borderR + borderL;\r
283                                                 case 1 : // padding-box\r
284                                                          boxMinus -= paddingR + paddingL;\r
285                                                 // case 0 : // content-box\r
286                                         };\r
287                                         this.contentL     = borderL + paddingL;\r
288                                         this.contentR     = borderR + paddingR;         \r
289                                         this.contentWidth = contentW + boxMinus;\r
290                                         this.boxWidth     = contentW - boxMinus + this.contentL + this.contentR;\r
291                                         this.boxSizingOffsetLR = boxMinus;\r
292                                 } else {\r
293                                         this.boxWidth = this.contentWidth = AUTO;\r
294                                         min = styles[ X.Css.AttrNo.minWidth ];\r
295                                         max = styles[ X.Css.AttrNo.maxWidth ];\r
296                                         this.minContentWidth = 1 <= min ? min : 0;\r
297                                         this.maxContentWidth = 1 <= max ? max : AUTO;\r
298                                         delete this.boxSizingOffsetLR;\r
299                                 };\r
300                                 \r
301                                 // Height\r
302                                 if( style.constraintH ? allowH !== AUTO : !style.autoHeight && ( allowH !== AUTO || !style.percentHeight ) ){\r
303                                         if( style.constraintH ){ // 制約レイアウト\r
304                                                 contentH = allowH - calc( styles[ X.Css.AttrNo.top ], allowH ) - calc( styles[ X.Css.AttrNo.bottom ], allowH );\r
305                                         } else {\r
306                                                 contentH = _AbstractUINode.finalValue( styles[ X.Css.AttrNo.height ], styles[ X.Css.AttrNo.minHeight ], styles[ X.Css.AttrNo.maxHeight ], allowH );\r
307                                         };\r
308                                         paddingT  = calc( styles[ X.Css.AttrNo.padding + 0 ], allowH );// paddingTRBL の % 指定は 最大幅に対して TB でも幅に対して\r
309                                         paddingB  = calc( styles[ X.Css.AttrNo.padding + 2 ], allowH );\r
310                                         borderT   = styles[ X.Css.AttrNo.border + 0 ];\r
311                                         borderB   = styles[ X.Css.AttrNo.border + 2 ];\r
312                                         this.boxHeight = contentH;\r
313                                         boxMinus = 0;\r
314                                         switch( box ){\r
315                                                 case 2 : // border-box\r
316                                                          boxMinus -= borderT + borderB;\r
317                                                 case 1 : // padding-box\r
318                                                          boxMinus -= paddingT + paddingB;\r
319                                                 // case 0 : // content-box\r
320                                         };                      \r
321                                         this.contentT      = borderT + paddingT;\r
322                                         this.conetntB      = borderB + paddingB;                        \r
323                                         this.contentHeight = contentH + boxMinus;\r
324                                         this.boxHeight     = contentH - boxMinus + this.contentT + this.conetntB; // padding-box の場合 border だけ足される\r
325                                         this.boxSizingOffsetTB = boxMinus;\r
326                                 } else {\r
327                                         this.boxHeight = this.contentHeight = AUTO;\r
328                                         min = styles[ X.Css.AttrNo.minHeight ];\r
329                                         max = styles[ X.Css.AttrNo.maxHeight ];\r
330                                         this.minContentHeight = 1 <= min ? min : 0;\r
331                                         this.maxContentHeight = 1 <= max ? max : AUTO;\r
332                                         delete this.boxSizingOffsetTB;\r
333                                 };\r
334                         } else {\r
335                                 this.boxWidth  = this.contentWidth  = allowW;\r
336                                 this.boxHeight = this.contentHeight = allowH;\r
337                                 delete this.minContentWidth;\r
338                                 delete this.maxContentWidth;\r
339                                 delete this.minContentHeight;\r
340                                 delete this.maxContentHeight;\r
341                                 delete this.contentL;\r
342                                 delete this.contentT;\r
343                                 delete this.contentR;\r
344                                 delete this.contentB;\r
345                         };\r
346                 },\r
347                 \r
348                 /**\r
349                  * 要素の追加・削除\r
350                  * 1. ペイントがある // 予約のみ\r
351                  * 2. コンテンツがある // 予約のみ *\r
352                  * 3. コンテンツを削除 // 予約のみ\r
353                  * 4. 要素を削除 // 予約のみ\r
354                  * \r
355                  * コンテンツの再計算\r
356                  * 0. 要素追加して css セット\r
357                  * 1. コンテンツの変更\r
358                  * 2. font 指定の変更\r
359                  * 3. contentWidth の変更 (コンテンツの高さの再計算) 前回の contentWidth の保持\r
360                  * \r
361                  * contentSize, scrollSize の決定\r
362                  */\r
363                 _mesure : function( dirty ){\r
364                         var content = this._content,\r
365                                 root    = this.rootData,\r
366                                 style   = this.styleData,\r
367                                 w       = this.contentWidth,\r
368                                 h       = this.contentHeight;\r
369                         switch( this.updateContent === true ? X.Css.Dirty.CONTENT : dirty ){\r
370                                 \r
371                                 case X.Css.Dirty.CONTENT : // コンテンツが変更された\r
372                                 case X.Css.Dirty.FONT   : // フォントサイズが変更された\r
373                                         this.hasTextNode && Node.root._startUpdate();\r
374                                         this.lastContentWidth = -1;\r
375                                 case X.Css.Dirty.REFLOW : // レイアウトの再計算が必要\r
376                                         /* http://web-designs.seesaa.net/article/188400668.html\r
377                                          * min-width の値が max-width の値より大きい場合は、max-width の値は min-width の値に設定される。\r
378                                          * \r
379                                          * テキストノードがあり\r
380                                          * 1. contentWidth === AUTO\r
381                                          *     style を更新して contentWidth の決定\r
382                                          *     min or max に引っかかったら style 更新\r
383                                          *     contentHeight === AUTO の場合\r
384                                          *     textHeight の決定\r
385                                          *     contentHeight !== AUTO の場合 scrollHeight のみ更新\r
386                                          * 2. contentHeight === AUTO かつ \r
387                                          *     コンテンツの高さの再取得が必要( contentWidth が最終計測時の contentWidth と一致 かつ フォント・コンテンツに変更無し の場合再取得不要)\r
388                                          *      style を更新して contentHeight の決定\r
389                                          *     必要でない\r
390                                          * 3. content のサイズがすでに決定している\r
391                                          *     コンテンツの高さの再取得が必要\r
392                                          *     必要でない\r
393                                          */   \r
394                                         if( this.hasTextNode ){\r
395                                                 elm = this.rawElement;\r
396                                                 if( w === AUTO ){\r
397                                                         w = this.contentWidth = elm.width();\r
398                                                         this.scrollWidth = w + this.contentL + this.contentR;\r
399                                                         if( this.maxContentWidth < w - this.boxSizingOffsetLR ) this.contentWidth = this.maxContentWidth + this.boxSizingOffsetLR;\r
400                                                         if( w - this.boxSizingOffsetLR < this.minContentWidth ) this.contentWidth = this.minContentWidth + this.boxSizingOffsetLR;\r
401                                                         this.lastContentWidth = this.contentWidth;\r
402                                                         \r
403                                                         w !== this.contentWidth && elm.css( 'width', this.contentWidth + 'px' );\r
404                                                         \r
405                                                         if( h === AUTO ){\r
406                                                                 this.conetntHeight = h = elm.height();\r
407                                                                 this.scrollHeight  = h + this.contentT + this.contentB;\r
408                                                                 if( this.maxContentHeight < h - this.boxSizingOffsetTB ) this.contentHeight = this.maxContentHeight + this.boxSizingOffsetTB;\r
409                                                                 if( h - this.boxSizingOffsetTB < this.minContentHeight ) this.contentHeight = this.minContentHeight + this.boxSizingOffsetTB;\r
410                                                         } else {\r
411                                                                 this.scrollHeight = elm.height() + this.contentT + this.contentB;\r
412                                                         };\r
413                                                 } else\r
414                                                 if( h === AUTO ){\r
415                                                         if( w !== this.lastContentWidth ){\r
416                                                                 elm.css( 'width', w + 'px' );\r
417                                                                 this.lastContentWidth  = w;\r
418                                                                 this.conetntHeight = h = elm.height();\r
419                                                                 this.scrollWidth       = w + this.contentL + this.contentR;\r
420                                                                 this.scrollHeight      = h + this.contentT + this.contentB;\r
421                                                                 if( this.maxContentHeight < h - this.boxSizingOffsetTB ) this.contentHeight = this.maxContentHeight + this.boxSizingOffsetTB;\r
422                                                                 if( h - this.boxSizingOffsetTB < this.minContentHeight ) this.contentHeight = this.minContentHeight + this.boxSizingOffsetTB;                                                           \r
423                                                         } else {\r
424                                                                 this.scrollWidth  = w + this.contentL + this.contentR;\r
425                                                                 this.scrollHeight = h + this.contentT + this.contentB;\r
426                                                                 //root.paintReserve( this );\r
427                                                         };\r
428                                                 } else\r
429                                                 if( dirty !== X.Css.Dirty.REFLOW ){\r
430                                                         this.contentWidth  = elm.width();\r
431                                                         this.contentHeight = elm.height();\r
432                                                         this.scrollWidth   = this.contentWidth  + this.contentL + this.contentR;\r
433                                                         this.scrollHeight  = this.contentHeight + this.contentT + this.contentB;\r
434                                                 } else {\r
435                                                         //root.paintReserve( this );\r
436                                                         this.scrollWidth  = w + this.contentL + this.contentR;\r
437                                                         this.scrollHeight = h + this.contentT + this.contentB;\r
438                                                 };              \r
439                                         } else {\r
440                                                 // コンテンツを持たないため基本のサイズは0\r
441                                                 if( w === AUTO ) this.contentWidth  = w = 0 < this.minContentWidth  ? this.minContentWidth  : 0;\r
442                                                 if( h === AUTO ) this.contentHeight = h = 0 < this.minContentHeight ? this.minContentHeight : 0;\r
443                                                 this.scrollWidth  = w + this.contentL + this.contentR;\r
444                                                 this.scrollHeight = h + this.contentT + this.contentB;\r
445                                                 //root.paintReserve( this );\r
446                                         };\r
447                                         break;                  \r
448                                 case X.Css.Dirty.PAINT : // 再描画のみ必要\r
449                                         root.paintReserve( this );\r
450                                         break;                                          \r
451                         };\r
452                 },\r
453                 /**\r
454                  * 自身のコンテンツサイズを元に AUTO な width, height を確定していく\r
455                  */\r
456                 postMesure : function(){\r
457                         var style = this.styleData,\r
458                                 styles, calc, box,\r
459                                 contentW, contentH,\r
460                                 contentPlus,\r
461                                 paddingT, paddingR, paddingB, paddingL,\r
462                                 borderT, borderR, borderB, borderL,\r
463                                 min, max;\r
464                         if( style ){\r
465                                 styles   = style.data;\r
466                                 calc     = _AbstractUINode.advancedCalcValue;\r
467                                 contentW = this.contentWidth;\r
468                                 box      = styles[ X.Css.AttrNo.sizing ];\r
469                                 \r
470                                 // Width\r
471                                 if( this.boxWidth === AUTO ){\r
472                                         paddingR = calc( styles[ X.Css.AttrNo.padding + 1 ], contentW );                                        \r
473                                         paddingL = calc( styles[ X.Css.AttrNo.padding + 3 ], contentW );                                        \r
474                                         borderR  = styles[ X.Css.AttrNo.border + 1 ];                                   \r
475                                         borderL  = styles[ X.Css.AttrNo.border + 3 ];\r
476                                         contentPlus = 0;\r
477                                         switch( box ){\r
478                                                 case 2 : // border-box\r
479                                                          contentPlus  = borderR + borderL;\r
480                                                 case 1 : // padding-box\r
481                                                          contentPlus += paddingR + paddingL;\r
482                                                 // case 0 : // content-box\r
483                                         };\r
484                                         \r
485                                         if( !style.constraintW ){\r
486                                                 contentW += contentPlus;\r
487                                                 min = styles[ X.Css.AttrNo.minWidth ];\r
488                                                 max = styles[ X.Css.AttrNo.maxWidth ];\r
489                                                 if( contentW < min && contentPlus < min ){\r
490                                                         this.contentWidth = min - contentPlus;\r
491                                                 } else\r
492                                                 if( max < contentW && contentPlus < max ){\r
493                                                         this.contentWidth = max - contentPlus;\r
494                                                 };\r
495                                         };\r
496                                         this.contentL = borderL + paddingL;\r
497                                         this.contentR = borderR + paddingR;\r
498                                         this.boxWidth = this.contentWidth + this.contentL + this.contentR;\r
499                                 };\r
500                                 // Height\r
501                                 if( this.boxHeight === AUTO ){\r
502                                         contentH    = this.contentHeight;\r
503                                         paddingT    = calc( styles[ X.Css.AttrNo.padding + 0 ], contentH );// paddingTRBL の % 指定は 最大幅に対して TB でも幅に対して\r
504                                         paddingB    = calc( styles[ X.Css.AttrNo.padding + 2 ], contentH );\r
505                                         borderT     = styles[ X.Css.AttrNo.border + 0 ];\r
506                                         borderB     = styles[ X.Css.AttrNo.border + 2 ];\r
507                                         contentPlus = 0;\r
508                                         switch( box ){\r
509                                                 case 2 : // border-box\r
510                                                          contentPlus  = borderT + borderB;\r
511                                                 case 1 : // padding-box\r
512                                                          contentPlus += paddingT + paddingB;\r
513                                                 // case 0 : // content-box\r
514                                         };\r
515                                         if( !style.constraintH ){\r
516                                                 contentH += contentPlus;\r
517                                                 min = styles[ X.Css.AttrNo.minHeight ];\r
518                                                 max = styles[ X.Css.AttrNo.maxHeight ];\r
519                                                 if( contentH < min && contentPlus < min ){\r
520                                                         this.contentHeight = min - contentPlus;\r
521                                                 } else\r
522                                                 if( max < contentH && contentPlus < max ){\r
523                                                         this.contentHeight = max - contentPlus;\r
524                                                 };\r
525                                         };\r
526                                         this.contentT  = borderT + paddingT;\r
527                                         this.contentB  = borderB + paddingB;\r
528                                         this.boxHeight = this.contentHeight + this.contentT + this.contentB;\r
529                                 };                              \r
530                         } else {\r
531                                 this.boxWidth  = this.contentWidth;\r
532                                 this.boxHeight = this.contentHeight;\r
533                                 delete this.minContentWidth;\r
534                                 delete this.maxContentWidth;\r
535                                 delete this.minContentHeight;\r
536                                 delete this.maxContentHeight;\r
537                                 delete this.contentL;\r
538                                 delete this.contentT;\r
539                                 delete this.contentR;\r
540                                 delete this.contentB;\r
541                         };\r
542                 },\r
543                 \r
544                 listen : function( type, arg1, arg2, arg3 ){\r
545                         var root, events, counter;\r
546                         if( X.UI.Event._START_POINTER <= type && type <= X.UI.Event._END_POINTER ){\r
547                                 if( this.phase < 3 ){\r
548                                         if( !( events = this.reserveEvents ) ) this.reserveEvents = events = [];\r
549                                         events[ events.length ] = [ type, arg1, arg2, arg3 ];\r
550                                         return this;\r
551                                 };\r
552                                 if( X.UI.Event._START_XUI_EVENT < type && type < X.UI.Event._END_XUI_EVENT ){\r
553                                         if( !this.gesture ){\r
554                                                 this.gesture = new X.UI.Gesture( this.root, this, type );\r
555                                         } else {\r
556                                                 this.gesture.listen( type );\r
557                                         };\r
558                                 } else {\r
559                                         root    = this.rootData;\r
560                                         counter = root.eventCounter;\r
561                                         if( counter[ type ] ){\r
562                                                 ++counter[ type ];\r
563                                         } else {\r
564                                                 counter[ type ] = 1;                            \r
565                                                 root.elmMouseCatch.listen( X.UI.Event.IdToName[ type ], eventRellay );\r
566                                         };\r
567                                 };\r
568                         };\r
569                         if( typeof arg1 === 'function' ){\r
570                                 return X.EventDispatcher.prototype.listen.apply( this, [ type, this.User, arg1, arg2 ] );\r
571                         };\r
572                         return X.EventDispatcher.prototype.listen.apply( this, [ type, arg1 || this.User, arg2 || arg1, arg3 || arg2 ] );\r
573                 },\r
574                 unlisten : function( type, arg1, arg2, arg3 ){\r
575                         var root, events, i, ev, counter;\r
576                         if( X.UI.Event._START_POINTER <= type && type <= X.UI.Event._END_POINTER ){\r
577                                 if( this.phase < 3 ){\r
578                                         if( !( events = this.reserveEvents ) ) return this;\r
579                                         for( i = events.length; i; ){\r
580                                                 ev = events[ --i ];\r
581                                                 if( ev[ 0 ] === type && ev[ 1 ] === arg1 && ev[ 2 ] === arg2 ){\r
582                                                         events.split( i, 1 );\r
583                                                         return this;\r
584                                                 };\r
585                                         }; \r
586                                         return this;\r
587                                 };\r
588 \r
589                                 if( X.UI.Event._START_XUI_EVENT < type && type < X.UI.Event._END_XUI_EVENT ){\r
590                                         this.gesture && this.gesture.unlisten( type );\r
591                                 } else {\r
592                                         root    = this.rootData;\r
593                                         counter = root.eventCounter;\r
594                                         if( !counter[ type ] ) return this;\r
595                                         --counter[ type ];\r
596                                         if( counter[ type ] === 0 ){\r
597                                                 X.Dom.Event.remove( root.elmMouseCatch, X.UI.Event.IdToName[ type ], eventRellay );\r
598                                                 delete counter[ type ];\r
599                                         };\r
600                                 };\r
601                         };\r
602                         if( typeof arg1 === 'function' ){\r
603                                 return X.EventDispatcher.prototype.unlisten.apply( this, [ type, this.User, arg1, arg2 ] );\r
604                         };\r
605                         return X.EventDispatcher.prototype.unlisten.apply( this, [ type, arg1 || this.User, arg2 || arg1, arg3 || arg2 ] );\r
606                 },\r
607                 \r
608                 dispatch : function( e ){\r
609                         var xve  = X.UI.Event,\r
610                                 ret  = X.EventDispatcher.prototype.dispatch.call( this, e ),\r
611                                 type = e.type;\r
612                         if( ret & X.Callback.MONOPOLY && !this.hitChildData && ( xve._POINTER_MOVE === type || xve._MOUSE_MOVE === type || xve.FILE_DRAG === type ) ){\r
613                                 this.rootData.monopolyNodeData = this;\r
614                                 return ret;\r
615                         };\r
616                         this.rootData.monopolyNodeData = null;\r
617                         if( xve._START_BUBLEUP < type && this.parentData && ret & X.Callback.STOP_PROPAGATION === 0 && ret & X.Callback.STOP_NOW === 0 ) return this.parentData.dispatch( e );\r
618                         return ret;\r
619                 }\r
620                 \r
621         }\r
622 );\r
623 \r
624 _AbstractUINode.finalValue = function( styleValue, styleMin, styleMax, srcValue ){\r
625         var calc = _AbstractUINode.calcValue,\r
626                 v    = calc( styleValue, srcValue ),\r
627                 min  = calc( styleMin,   srcValue ),\r
628                 max  = calc( styleMax,   srcValue );\r
629         if( v < min ) return min;\r
630         if( max < v ) return max;\r
631         return v;\r
632 };\r
633 _AbstractUINode.calcValue = function( styleValue, srcValue ){\r
634         switch( styleValue ){\r
635                 case 0 :\r
636                         return 0;\r
637                 case AUTO :\r
638                         return AUTO;\r
639                 case FULL :\r
640                         return srcValue; // 100%\r
641         };\r
642         if( 1 <= styleValue ) return styleValue; // legth\r
643         if( -1 < styleValue ) return FLOOR( srcValue * styleValue ); // %       \r
644         return styleValue; // - length\r
645 };\r
646 _AbstractUINode.advancedCalcValue = function( styleValue, srcValue ){\r
647         switch( styleValue ){\r
648                 case 0 :\r
649                         return 0;\r
650                 case AUTO :\r
651                         return srcValue;\r
652                 case FULL :\r
653                         //throw new Error( 'advancedCalcValue FULL' ); \r
654                         // return ; // 100%\r
655         };\r
656         if( 1 <= styleValue ) return styleValue; \r
657         if( -1 < styleValue ) return FLOOR( ( srcValue / ( 1 - styleValue ) ) * styleValue ); // %      \r
658         return styleValue; // - length\r
659 };\r
660 \r
661 \r
662 var AbstractUINode = X.Class.create(\r
663         'AbstractUINode',\r
664         X.Class.ABSTRACT | X.Class.SUPER_ACCESS,\r
665         {\r
666                 style : null,\r
667                 parent : function(){\r
668                         return X.Class._getPrivate( this ).parent;\r
669                 },\r
670                 root : function(){\r
671                         return X.Class._getPrivate( this ).root;\r
672                 },\r
673                 listen : function( type, arg1, arg2, arg3 ){\r
674                         X.Class._getPrivate( this ).listen( type, arg1, arg2, arg3 );\r
675                         return this;\r
676                 },\r
677                 listenOnce : function( type, arg1, arg2, arg3 ){\r
678                         X.Class._getPrivate( this ).listenOnce( type, arg1, arg2, arg3 );\r
679                         return this;\r
680                 },\r
681                 unlisten : function( type, arg1, arg2, arg3 ){\r
682                         X.Class._getPrivate( this ).unlisten( type, arg1, arg2, arg3 );\r
683                         return this;\r
684                 },\r
685                 getNextNode : function(){\r
686                         \r
687                 },\r
688                 getPrevNode : function(){\r
689                         \r
690                 },\r
691                 dispatch : function( e ){\r
692                         return X.Class._getPrivate( this ).dispatch( e );\r
693                 },\r
694                 nodeIndex : function( v ){\r
695                         var data = X.Class._getPrivate( this );\r
696                         if( typeof v === 'number' ){\r
697                                 // data.nodeIndex( v );\r
698                                 return this;\r
699                         };\r
700                         return data.parentData ? data.parentData.nodes.indexOf( data ) : 0;\r
701                 },\r
702                 displayIndex : function(){\r
703                         \r
704                 },\r
705                 // ちゃんとやれば不要!\r
706                 mesure : function(){\r
707                         var data = X.Class._getPrivate( this );\r
708                         data.mesure();\r
709                         4 <= data.phase && data.rootData.reserveCalc();\r
710                         return this;\r
711                 },\r
712                 getX : function(){\r
713                         // dirty の場合、rootData.calculate\r
714                         return X.Class._getPrivate( this ).x;\r
715                 },\r
716                 getY : function(){\r
717                         // dirty の場合、rootData.calculate\r
718                         return X.Class._getPrivate( this ).y;\r
719                 },\r
720                 getAbsoluteX : function(){\r
721                         // dirty の場合、rootData.calculate\r
722                         return X.Class._getPrivate( this ).absoluteX;\r
723                 },\r
724                 getAbsoluteY: function(){\r
725                         // dirty の場合、rootData.calculate\r
726                         return X.Class._getPrivate( this ).absoluteY;\r
727                 },\r
728                 getWidth : function(){\r
729                         // dirty の場合、rootData.calculate\r
730                         return X.Class._getPrivate( this ).w;\r
731                 },\r
732                 getHeight : function(){\r
733                         // dirty の場合、rootData.calculate\r
734                         return X.Class._getPrivate( this ).h;\r
735                 },\r
736                 scrollTo : function( x, y ){\r
737                         X.Class._getPrivate( this ).scrollTo( x, y );\r
738                 },\r
739                 getScrollX : function( v ){\r
740                         // dirty の場合、rootData.calculate\r
741                         return X.Class._getPrivate( this ).scrollX( v );\r
742                 },\r
743                 getScrollY : function( v ){\r
744                         // dirty の場合、rootData.calculate\r
745                         return X.Class._getPrivate( this ).scrollY( v );\r
746                 },\r
747                 disabled : function( v ){\r
748                         return X.Class._getPrivate( this ).disabled( v );\r
749                 },\r
750                 cursor : function( v ){\r
751                         return X.Class._getPrivate( this ).cursor( v );\r
752                 }\r
753         }\r
754 );