~eda-qa/dhlib/main

« back to all changes in this revision

Viewing changes to lib/ui/FreeLayout.mhx

  • Committer: edA-qa mort-ora-y
  • Date: 2010-02-16 05:36:32 UTC
  • Revision ID: eda-qa@disemia.com-20100216053632-60lt7fndfi3fgblw
first

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* <license>
 
2
 * This file is part of the dis-Emi-A HaXe Library. Copyright (c) edA-qa mort-ora-y
 
3
 * For full copyright and license information please refer to doc/license.txt.
 
4
 * </license> 
 
5
 */
 
6
package ui;
 
7
 
 
8
import flash.display.DisplayObject;
 
9
import mathx.Point2;
 
10
 
 
11
private class FreeItemHolder implements Sizeable, implements BaseItemHolder
 
12
{
 
13
        public var item : Widget;
 
14
        public var sizeTypes : Array<SizeType>; //left,top,width,height
 
15
        public var sizes : Array<Float>;
 
16
        public var visible : Bool;
 
17
        public var zIndex : Int;
 
18
        public var addOrder : Int;      //used to track original insertion order for zOrder calculations
 
19
        
 
20
        public var layout : FreeLayout;
 
21
        
 
22
        public function getWidget() : Widget { return item; }
 
23
        public function setVisible( vis : Bool ) : Void { visible = vis; }
 
24
        
 
25
        public function new() 
 
26
        {
 
27
                sizeTypes = new Array<SizeType>();
 
28
                sizes = new Array<Float>();
 
29
                visible = true;
 
30
                zIndex = 0;
 
31
                addOrder = 0;   //though default should not be used
 
32
        }
 
33
        
 
34
        public function getSizeType() : SizeType 
 
35
        {
 
36
                return sizeTypes[layout.itemIndex];
 
37
        }
 
38
        
 
39
        public function setPlacement( offset : Float, size : Float ) : Void
 
40
        {
 
41
                //ignore offset
 
42
                sizes[layout.itemIndex] = size;
 
43
        }
 
44
}
 
45
 
 
46
/**
 
47
 * Creates a layout for arbitrary placement.
 
48
 *
 
49
 * For relative sizing behaves as a vertical layout for primary/secondary sizing, though
 
50
 * beware the Fill sizes do *NOT* work!
 
51
 *
 
52
 * NOTE:
 
53
 *              spacing - this is applied only around outside edges and does not impact individual items
 
54
 *              collapseMargin - if true, equivalent to 0 spacing
 
55
 *
 
56
 * Requires manual update after modifications
 
57
 */
 
58
class FreeLayout extends Layout<FreeItemHolder>
 
59
{
 
60
        //for FreeItemHolder
 
61
        public var itemIndex : Int;
 
62
 
 
63
        var addOrder : Int;
 
64
        var dirtyZ : Bool;
 
65
        
 
66
        public var offset : mathx.Point2; //how much to offset each item
 
67
        
 
68
        private function new()
 
69
        {
 
70
                super();
 
71
                dirtyZ = false;
 
72
                addOrder = 0;
 
73
                spacing = padding = 0; //better defaults for free layout
 
74
                offset = Point2.at( 0, 0 );
 
75
        }
 
76
        
 
77
        /**
 
78
         * Creates a simple FreeLayout where all the items are placed
 
79
         * individually and behave normally.
 
80
         */
 
81
        static public function simple() : FreeLayout
 
82
        {
 
83
                return new FreeLayout();
 
84
        }
 
85
        
 
86
        override public function _resize( w : Float, h : Float ) 
 
87
        {
 
88
                super._resize(w,h );
 
89
                                
 
90
                var horzSizer = new Sizer( 0, true, false );
 
91
                var vertSizer = new Sizer( 0, true, true );
 
92
                
 
93
                if( !collapseMargin )
 
94
                {
 
95
                        w -= spacing * 2;
 
96
                        h -= spacing * 2;
 
97
                }
 
98
                
 
99
                //left
 
100
                itemIndex = 0;
 
101
                horzSizer.size( w, h, items );
 
102
                //top
 
103
                itemIndex = 1;
 
104
                vertSizer.size( h, w, items );
 
105
                //width
 
106
                itemIndex = 2;
 
107
                horzSizer.size( w, h, items );
 
108
                //height
 
109
                itemIndex = 3;
 
110
                vertSizer.size( h, w, items );
 
111
                
 
112
                for( i in items )
 
113
                {
 
114
                        var left = i.sizes[0] + padding + spacing + offset.x;
 
115
                        var top = i.sizes[1] + padding + spacing + offset.y;
 
116
                        var width =  i.sizes[2] - 2 * padding;
 
117
                        var height = i.sizes[3] - 2 * padding;
 
118
                        
 
119
                        //hide items not partially shown
 
120
                        if( !alwaysShow )
 
121
                        {
 
122
                                if( (showPartial && (left >= w || top >= h || (left+width) <= 0 || (top+height) <= 0))
 
123
                                        || (!showPartial && (left < 0 || top < 0 || (left+width) > w || (top+height) > h) ) )
 
124
                                {
 
125
                                        i.item.setVisible( false );
 
126
                                        continue;
 
127
                                }
 
128
                        }
 
129
                        
 
130
                        i.item.move( left, top );
 
131
                        i.item.resize( width, height );
 
132
                        i.item.setVisible( i.visible );
 
133
                }
 
134
                
 
135
                if( dirtyZ )
 
136
                        resetZOrder();
 
137
        }
 
138
        
 
139
        //FEATURE: zOrder could be moved to Layout base (though only makes sense for overlapping items)
 
140
        function resetZOrder()
 
141
        {
 
142
                var sorted = items.copy();      //shallow copy
 
143
                sorted.sort( function( a, b ) { 
 
144
                        var ret = a.zIndex - b.zIndex; 
 
145
                        if( ret != 0 )
 
146
                                return ret;
 
147
                        //when z is equal, resort to original add order
 
148
                        return a.addOrder - b.addOrder;
 
149
                        } );
 
150
                
 
151
                //FLASH: This can produce error 2006: The Supplied index is out of bounds
 
152
                //This happens if the same widget has been added twice -- removed won't see this since
 
153
                //flash won't consider the child removed. (TODO: fix/prevent this)
 
154
                for( i in 0...sorted.length )
 
155
                        setChildIndex( sorted[i].item.getNative(), i );
 
156
                        
 
157
                //finally restore background position
 
158
                if( background != null )
 
159
                        setChildIndex( background.getNative(), 0 );
 
160
        }
 
161
        
 
162
        /**
 
163
         * Adds an item to the layout.
 
164
         *
 
165
         * @param item [in,keep] which item to add
 
166
         * @param zIndex [in] in which layer to add it (default 0). The layers will decide
 
167
         *              the order in which these are placed in the FreeLayout -- lower numbers
 
168
         *              are the lower layers.
 
169
         *              To remain simple, and retain natural flash use, the order in which items are
 
170
         *              added will be tracked.  If the zOrder of two items are the same, the one which
 
171
         *              was added first will be lower in the final zOrder.
 
172
         */
 
173
        public function add( item : Widget, 
 
174
                left : SizeType, top : SizeType,                
 
175
                width : SizeType, height : SizeType,
 
176
                zIndex : Int = 0 )
 
177
        {
 
178
                Assert.notNull( item );
 
179
                
 
180
                var fih = new FreeItemHolder();
 
181
                fih.item = item;
 
182
                fih.sizeTypes[0] = left;
 
183
                fih.sizeTypes[1] = top;
 
184
                fih.sizeTypes[2] = width;
 
185
                fih.sizeTypes[3] = height;
 
186
                
 
187
                fih.layout = this;
 
188
                fih.zIndex = zIndex;
 
189
                fih.addOrder = addOrder++;
 
190
                dirtyZ = true;
 
191
                
 
192
                item.setVisible( false );
 
193
                insertToItems( fih );
 
194
        }
 
195
        
 
196
        /**
 
197
         * This is a specialized form where all sizes are SizeType.Primary and is used quite
 
198
         * often for FreeLayout's more often than other sizing types in our current uses
 
199
         */
 
200
        public function addPS( item : Widget, left : Float, top : Float, width : Float, height : Float, zIndex : Int = 0 )
 
201
        {
 
202
                add( item, SizeType.Primary( left ), SizeType.Primary( top ), SizeType.Primary( width ), SizeType.Primary( height ), zIndex );
 
203
        }
 
204
        
 
205
        public function addPSCtr( item : Widget, x : Float, y : Float, width : Float, height : Float, zIndex : Int = 0 )
 
206
        {
 
207
                var ctr = item.getCenter();
 
208
                add( item, SizeType.Primary( x-width*ctr.x ), SizeType.Primary( y-height*ctr.y ), SizeType.Primary( width ), SizeType.Primary( height ), zIndex );
 
209
        }
 
210
        
 
211
        public function addPSRect( item : Widget, rect : mathx.Rect2, zIndex : Int = 0 )
 
212
        {
 
213
                add( item, SizeType.Primary( rect.left ), SizeType.Primary( rect.top ), SizeType.Primary( rect.width ), SizeType.Primary( rect.height ), zIndex );
 
214
        }
 
215
        
 
216
        override public function getPrefWidth() : ui.SizeType
 
217
        {
 
218
                return SizeType.Fill( 1 );
 
219
        }
 
220
        
 
221
        override public function getPrefHeight() : ui.SizeType
 
222
        {
 
223
                return SizeType.Fill( 1 );
 
224
        }
 
225
}