1//////////////////////////////////////////////////////////////////////////////// 2// 3// ADOBE SYSTEMS INCORPORATED 4// Copyright 2003-2007 Adobe Systems Incorporated 5// All Rights Reserved. 6// 7// NOTICE: Adobe permits you to use, modify, and distribute this file 8// in accordance with the terms of the license agreement accompanying it. 9// 10//////////////////////////////////////////////////////////////////////////////// 11 12package mx.containers 13{ 14 15import flash.events.Event; 16import mx.containers.utilityClasses.BoxLayout; 17import mx.core.Container; 18import mx.core.IUIComponent; 19import mx.core.mx_internal; 20 21use namespace mx_internal; 22 23//-------------------------------------- 24// Styles 25//-------------------------------------- 26 27include "../styles/metadata/AlignStyles.as"; 28include "../styles/metadata/GapStyles.as"; 29 30/** 31 * Number of pixels between the container's bottom border 32 * and the bottom of its content area. 33 * The default value is 0. 34 * 35 * @langversion 3.0 36 * @playerversion Flash 9 37 * @playerversion AIR 1.1 38 * @productversion Flex 3 39 */ 40[Style(name="paddingBottom", type="Number", format="Length", inherit="no")] 41 42/** 43 * Number of pixels between the container's top border 44 * and the top of its content area. 45 * The default value is 0. 46 * 47 * @langversion 3.0 48 * @playerversion Flash 9 49 * @playerversion AIR 1.1 50 * @productversion Flex 3 51 */ 52[Style(name="paddingTop", type="Number", format="Length", inherit="no")] 53 54//-------------------------------------- 55// Excluded APIs 56//-------------------------------------- 57 58[Exclude(name="focusIn", kind="event")] 59[Exclude(name="focusOut", kind="event")] 60 61[Exclude(name="focusBlendMode", kind="style")] 62[Exclude(name="focusSkin", kind="style")] 63[Exclude(name="focusThickness", kind="style")] 64 65[Exclude(name="focusInEffect", kind="effect")] 66[Exclude(name="focusOutEffect", kind="effect")] 67 68//-------------------------------------- 69// Other metadata 70//-------------------------------------- 71 72[IconFile("Box.png")] 73 74[Alternative(replacement="spark.components.HGroup", since="4.0")] 75[Alternative(replacement="spark.components.VGroup", since="4.0")] 76[Alternative(replacement="spark.components.BorderContainer", since="4.0")] 77 78/** 79 * A Halo Box container lays out its children in a single vertical column 80 * or a single horizontal row. 81 * The <code>direction</code> property determines whether to use 82 * vertical (default) or horizontal layout. 83 * 84 * <p><b>Note:</b> Adobe recommends that, when possible, you use the Spark containers 85 * with HorizontalLayout or VerticalLayout instead of the Halo Box container.</p> 86 * 87 * <p>The Box class is the base class for the VBox and HBox classes. 88 * You use the <code><mx:Box></code>, <code><mx:VBox></code>, 89 * and <code><mx:HBox></code> tags to define Box containers.</p> 90 * 91 * <p>A Box container has the following default sizing characteristics:</p> 92 * <table class="innertable"> 93 * <tr> 94 * <th>Characteristic</th> 95 * <th>Description</th> 96 * </tr> 97 * <tr> 98 * <td>Default size</td> 99 * <td><strong>Vertical Box</strong> The height is large enough to hold all its children at the default 100 * or explicit height of the children, plus any vertical gap between the children, plus the top and 101 * bottom padding of the container. The width is the default or explicit width of the widest child, 102 * plus the left and right padding of the container. 103 * <br><strong>Horizontal Box</strong> The width is large enough to hold all of its children at the 104 * default width of the children, plus any horizontal gap between the children, plus the left and 105 * right padding of the container. The height is the default or explicit height of the tallest child, 106 * plus the top and bottom padding for the container.</br> 107 * </td> 108 * </tr> 109 * <tr> 110 * <td>Default padding</td> 111 * <td>0 pixels for the top, bottom, left, and right values.</td> 112 * </tr> 113 * </table> 114 * 115 * @mxml 116 * 117 * <p>The <code><mx:Box></code> tag inherits all of the tag 118 * attributes of its superclass, and adds the following tag attributes:</p> 119 * 120 * <p> 121 * <pre> 122 * <mx:Box 123 * <strong>Properties</strong> 124 * direction="vertical|horizontal" 125 * <strong>Styles</strong> 126 * horizontalAlign="left|center|right" 127 * horizontalGap="8" 128 * paddingBottom="0" 129 * paddingTop="0" 130 * verticalAlign="top|middle|bottom" 131 * verticalGap="6" 132 * > 133 * ... 134 * <i>child tags</i> 135 * ... 136 * </mx:Box> 137 * </pre> 138 * </p> 139 * 140 * @includeExample examples/SimpleBoxExample.mxml 141 * 142 * @see mx.core.Container 143 * @see mx.containers.HBox 144 * @see mx.containers.VBox 145 * 146 * @langversion 3.0 147 * @playerversion Flash 9 148 * @playerversion AIR 1.1 149 * @productversion Flex 3 150 */ 151public class Box extends Container 152{ 153 include "../core/Version.as" 154 155 //-------------------------------------------------------------------------- 156 // 157 // Constructor 158 // 159 //-------------------------------------------------------------------------- 160 161 /** 162 * Constructor. 163 * 164 * @langversion 3.0 165 * @playerversion Flash 9 166 * @playerversion AIR 1.1 167 * @productversion Flex 3 168 */ 169 public function Box() 170 { 171 super(); 172 173 layoutObject.target = this; 174 } 175 176 //-------------------------------------------------------------------------- 177 // 178 // Variables 179 // 180 //-------------------------------------------------------------------------- 181 182 /** 183 * @private 184 */ 185 mx_internal var layoutObject:BoxLayout = new BoxLayout(); 186 187 //-------------------------------------------------------------------------- 188 // 189 // Public properties 190 // 191 //-------------------------------------------------------------------------- 192 193 //---------------------------------- 194 // direction 195 //---------------------------------- 196 197 [Bindable("directionChanged")] 198 [Inspectable(category="General", enumeration="vertical,horizontal", defaultValue="vertical")] 199 200 /** 201 * The direction in which this Box container lays out its children. 202 * Possible MXML values are 203 * <code>"horizontal"</code> and <code>"vertical"</code>. 204 * Possible values in ActionScript are <code>BoxDirection.HORIZONTAL</code> 205 * and <code>BoxDirection.VERTICAL</code>. 206 * 207 * @default BoxDirection.VERTICAL 208 * 209 * @langversion 3.0 210 * @playerversion Flash 9 211 * @playerversion AIR 1.1 212 * @productversion Flex 3 213 */ 214 public function get direction():String 215 { 216 return layoutObject.direction; 217 } 218 219 /** 220 * @private 221 */ 222 public function set direction(value:String):void 223 { 224 layoutObject.direction = value; 225 226 invalidateSize(); 227 invalidateDisplayList(); 228 229 dispatchEvent(new Event("directionChanged")); 230 } 231 232 //-------------------------------------------------------------------------- 233 // 234 // Overridden methods 235 // 236 //-------------------------------------------------------------------------- 237 238 /** 239 * Calculates the default sizes and minimum and maximum values of the Box 240 * container. 241 * 242 * <p>If the Box container's <code>direction</code> property is set to 243 * <code>BoxDirection.HORIZONTAL</code>, its <code>measuredWidth</code> 244 * property is equal to the sum of default widths of all of its children, 245 * plus the thickness of the borders, plus the left and right padding, 246 * plus the horizontal gap between each child. 247 * The value of the <code>measuredHeight</code> property is the maximum of 248 * all the children's default heights, plus room for the borders and 249 * padding. 250 * If the Box container's <code>direction</code> property is set to 251 * <code>BoxDirection.VERTICAL</code>, these two values are reversed.</p> 252 * 253 * <p>The Box container's <code>minWidth</code> and <code>minHeight</code> 254 * properties are calculated similarly, by combining the minimum widths 255 * and minimum heights of the children. 256 * If the child's <code>width</code> property is a percentage value, the 257 * Box container's minimum width is equal to the value of the child's 258 * <code>minWidth</code> property. 259 * If the child's <code>width</code> is unset or set to a fixed value, 260 * the child refuses to grow or shrink, so the Box container's minimum 261 * width is equal to the value of the child's <code>explicitWidth</code> 262 * property. 263 * The child's minimum height is calculated similarly.</p> 264 * 265 * <p>The Box container's <code>maxWidth</code> and 266 * <code>maxHeight</code> properties are not calculated. 267 * The Box container is assumed to have an infinite maximum width and 268 * height.</p> 269 * 270 * <p>All of the values described previously are the <i>measured</i> 271 * widths and heights of the Box container. 272 * The user can override the measured values by explicitly supplying 273 * a value for the following properties:</p> 274 * 275 * <ul> 276 * <li><code>width</code></li> 277 * <li><code>height</code></li> 278 * <li><code>minWidth</code></li> 279 * <li><code>minHeight</code></li> 280 * <li><code>maxWidth</code></li> 281 * <li><code>maxHeight</code></li> 282 * </ul> 283 * 284 * <p>You should not call the <code>measure()</code> method directly. 285 * The Flex LayoutManager calls it at the appropriate time. 286 * At application startup, the Flex LayoutManager attempts to measure 287 * all components from the children to the parents before setting them 288 * to their final sizes.</p> 289 * 290 * <p>This is an advanced method for use in subclassing. 291 * If you override this method, your implementation must call 292 * the <code>super.measure()</code> method, or set the 293 * <code>measuredHeight</code> and 294 * <code>measuredWidth</code> properties. 295 * You may also optionally set the following properties:</p> 296 * 297 * <ul> 298 * <li><code>measuredMinWidth</code></li> 299 * <li><code>measuredMinHeight</code></li> 300 * </ul> 301 * 302 * <p>These properties correspond to the layout properties listed 303 * previously and, therefore, are not separately documented.</p> 304 * 305 * @langversion 3.0 306 * @playerversion Flash 9 307 * @playerversion AIR 1.1 308 * @productversion Flex 3 309 */ 310 override protected function measure():void 311 { 312 super.measure(); 313 314 layoutObject.measure(); 315 } 316 317 /** 318 * Sets the size and position of each child of the Box container. 319 * 320 * <p>To understand the layout algorithm for the Box container, assume 321 * that the Box container's direction is horizontal.</p> 322 * 323 * <p>All of the Box container's children are positioned side-by-side in a 324 * single horizontal row, with <code>horizontalGap</code> pixels between 325 * each pair of adjacent children. 326 * Initially, the widths of children without an explicit 327 * width value are set equal to the values of their 328 * <code>measuredWidth</code> properties.</p> 329 * 330 * <p>If the sum of the values of the <code>measuredWidth</code> 331 * properties of the children is greater than or less than the width of 332 * the Box container, and if some of the children have a percentage value 333 * for the <code>width</code> property, the sizes of those children are 334 * grown or shrunk until all children exactly fit in the Box. 335 * However, no child is shrunk to less than the value of its 336 * <code>minWidth</code> property or increased greater than the value of 337 * its <code>maxWidth</code> property. 338 * Among the growing (or shrinking) children, extra space is added 339 * (or removed) in proportion to the child's <code>percentWidth</code>. 340 * For example, a child with a <code>percentWidth</code> of 40 percent 341 * will grow twice as much as a child with a <code>percentWidth</code> of 342 * 20 percent until all of the available space is filled or the prescribed 343 * sizes are reached.</p> 344 * 345 * <p>After all flexible children have grown or shrunk, Flex checks to see 346 * if the sum of the children's widths match the width of the Box 347 * container. 348 * If not, the group of children are all shifted according to the value 349 * of the Box container's <code>horizontalAlign</code> property, so the 350 * children are aligned with the left edge of the Box, aligned with the 351 * right edge of the Box, or centered in the middle of the Box.</p> 352 * 353 * <p>To determine the height of each child, Flex examines the value 354 * of the child's <code>height</code> property. 355 * If the <code>height</code> is unset, the child's height 356 * is set to its <code>measuredHeight</code>. 357 * If the <code>height</code> is set to a pixel value, that value is used. 358 * If the <code>height</code> is set to a percentage value, 359 * the child's height is grown or shrunk to match the specified 360 * percentage of the height of the Box, as long as the child's height 361 * is not shrunk to less than the value of its <code>minHeight</code> 362 * property or grown to be larger than the value of its 363 * <code>maxHeight</code> property.</p> 364 * 365 * <p>The vertical position of each child is determined by 366 * the Box container's <code>verticalAlign</code> property. 367 * Each child is shifted so that it is aligned with the top edge 368 * of the box, aligned with the bottom edge of the box, 369 * or centered in the Box.</p> 370 * 371 * <p>If the Box container's <code>direction</code> is 372 * <code>vertical</code>, the same rules apply, except that the widths and 373 * heights are swapped. 374 * The children are arranged in a single vertical column.</p> 375 * 376 * <p>You should not call this method directly. 377 * The Flex LayoutManager calls it at the appropriate time. 378 * At application startup, the Flex LayoutManager calls the 379 * <code>updateDisplayList()</code> method on every component, 380 * starting with the Application object and working downward.</p> 381 * 382 * <p>This is an advanced method for use in subclassing. 383 * If you override this method, your implementation should call the 384 * <code>super.updateDisplayList()</code> method and call the 385 * <code>move()</code> and <code>setActualSize()</code> methods 386 * on each of the children. 387 * For the purposes of performing layout, you should get the size 388 * of this container from the <code>unscaledWidth</code> and 389 * <code>unscaledHeight</code> properties, not the <code>width</code> 390 * and <code>height</code> properties. 391 * The <code>width</code> and <code>height</code> properties 392 * do not take into account the values of the <code>scaleX</code> 393 * and <code>scaleY</code> properties for this container.</p> 394 * 395 * @param unscaledWidth Specifies the width of the component, in pixels, 396 * in the component's coordinates, regardless of the value of the 397 * <code>scaleX</code> property of the component. 398 * 399 * @param unscaledHeight Specifies the height of the component, in pixels, 400 * in the component's coordinates, regardless of the value of the 401 * <code>scaleY</code> property of the component. 402 * 403 * @langversion 3.0 404 * @playerversion Flash 9 405 * @playerversion AIR 1.1 406 * @productversion Flex 3 407 */ 408 override protected function updateDisplayList(unscaledWidth:Number, 409 unscaledHeight:Number):void 410 { 411 super.updateDisplayList(unscaledWidth, unscaledHeight); 412 413 layoutObject.updateDisplayList(unscaledWidth, unscaledHeight); 414 } 415 416 //-------------------------------------------------------------------------- 417 // 418 // Methods 419 // 420 //-------------------------------------------------------------------------- 421 422 /** 423 * Method used to convert number of pixels to a 424 * percentage relative to the contents of this container. 425 * 426 * <p>The percentage value is relevant only while the 427 * container does not change size or layout. 428 * After a resize and/or new layout has occurred, 429 * the value returned from this method may be stale.</p> 430 * 431 * <p>An example of how this method could be used would 432 * be to restore a component's size to a specific number 433 * of pixels after hiding it.</p> 434 * 435 * @param pxl The number of pixels for which a percentage 436 * value is desired. 437 * 438 * @return The percentage value that would be equivalent 439 * to <code>pxl</code> under the current layout conditions 440 * of this container. 441 * A negative value indicates that the container must grow 442 * in order to accommodate the requested size. 443 * 444 * @langversion 3.0 445 * @playerversion Flash 9 446 * @playerversion AIR 1.1 447 * @productversion Flex 3 448 */ 449 public function pixelsToPercent(pxl:Number):Number 450 { 451 var vertical:Boolean = isVertical(); 452 453 // Compute our total percent and total # pixels for that percent. 454 var totalPerc:Number = 0; 455 var totalSize:Number = 0; 456 457 var n:int = numChildren; 458 for (var i:int = 0; i < n; i++) 459 { 460 var child:IUIComponent = getLayoutChildAt(i); 461 462 var size:Number = vertical ? child.height : child.width; 463 var perc:Number = vertical ? child.percentHeight : child.percentWidth; 464 465 if (!isNaN(perc)) 466 { 467 totalPerc += perc; 468 totalSize += size; 469 } 470 } 471 472 // Now if we found one let's compute the percent amount 473 // that we'd require for a given number of pixels. 474 var p:Number = 100; 475 if (totalSize != pxl) 476 { 477 // Now we want the ratio of pixels per percent to 478 // remain constant as we assume the a component 479 // will consume them. So, 480 // 481 // (totalSize - pxl) / totalPerc = totalSize / (totalPerc + p) 482 // 483 // where we solve for p. 484 485 p = ((totalSize * totalPerc) / (totalSize - pxl)) - totalPerc; 486 } 487 488 return p; 489 } 490 491 /** 492 * @private 493 */ 494 mx_internal function isVertical():Boolean 495 { 496 return direction != BoxDirection.HORIZONTAL; 497 } 498} 499 500} 501