1 /***
2 * Redistribution and use in source and binary forms, with or without
3 * modification, are permitted provided that the following conditions are
4 * met :
5 *
6 * . Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 *
9 * . Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * . The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 *
28 * $Id$
29 */
30
31 package palmed.ui;
32
33 import java.util.Enumeration;
34 import java.util.Vector;
35 import javax.microedition.lcdui.Canvas;
36 import javax.microedition.lcdui.Graphics;
37 import javax.microedition.lcdui.Image;
38 import javax.microedition.lcdui.Item;
39
40 /***
41 * This class implements a graphical container of components.
42 *
43 * @author Mathieu Champlon
44 * @version $Revision$ $Date$
45 */
46 public class Container extends Canvas implements ILayoutManager
47 {
48 /***
49 * The components.
50 */
51 private final Vector components_;
52 /***
53 * The component holding focus.
54 */
55 private Component focus_;
56 /***
57 * The offscreen buffer to handle double buffering manually if needed.
58 */
59 private Image offscreen_;
60 /***
61 * Whether a refresh must be performed or not.
62 */
63 private boolean mustRefresh_;
64
65 /***
66 * Create a container.
67 */
68 public Container()
69 {
70 setFullScreenMode( true );
71 components_ = new Vector();
72 mustRefresh_ = false;
73 }
74
75 /***
76 * Add a component in the container.
77 *
78 * @param component the component
79 */
80 public final void add( final IComponent component )
81 {
82 components_.insertElementAt( new Component( component ), 0 );
83 mustRefresh_ = true;
84 }
85
86 /***
87 * {@inheritDoc}
88 */
89 protected final void paint( final Graphics g )
90 {
91 while( mustRefresh_ )
92 layoutComponents( getWidth(), getHeight() );
93 if( offscreen_ == null )
94 paintComponents( g );
95 else
96 {
97 paintComponents( offscreen_.getGraphics() );
98 g.drawImage( offscreen_, 0, 0, Graphics.LEFT | Graphics.TOP );
99 }
100 }
101
102 private void paintComponents( final Graphics g )
103 {
104 final Enumeration components = components_.elements();
105 while( components.hasMoreElements() )
106 ((Component)components.nextElement()).paint( g );
107 }
108
109 /***
110 * {@inheritDoc}
111 */
112 protected final void sizeChanged( final int width, final int height )
113 {
114 if( !isDoubleBuffered() )
115 offscreen_ = Image.createImage( width, height );
116 mustRefresh_ = true;
117 }
118
119 /***
120 * {@inheritDoc}
121 */
122 public final void refresh()
123 {
124 mustRefresh_ = true;
125 repaint();
126 }
127
128 private void layoutComponents( final int width, final int height )
129 {
130 mustRefresh_ = false;
131 int w = width;
132 int h = height;
133 final Enumeration components = components_.elements();
134 while( components.hasMoreElements() )
135 {
136 int componentX = 0;
137 int componentY = 0;
138 int componentWidth, componentHeight;
139 final Component component = (Component)components.nextElement();
140 if( expandsHorizontally( component ) )
141 {
142 componentWidth = w;
143 w = width;
144 }
145 else
146 {
147 componentWidth = component.getWidth();
148 componentX = w - componentWidth;
149 w -= componentWidth;
150 }
151 if( expandsVertically( component ) )
152 componentHeight = h;
153 else
154 {
155 componentHeight = component.getHeight();
156 componentY = h - componentHeight;
157 if( expandsHorizontally( component ) )
158 h -= componentHeight;
159 }
160 component.move( componentX, componentY );
161 component.resize( componentWidth, componentHeight );
162 }
163 }
164
165 private boolean expandsVertically( final IComponent component )
166 {
167 return (component.getLayout() & Item.LAYOUT_VEXPAND) != 0;
168 }
169
170 private boolean expandsHorizontally( final IComponent component )
171 {
172 return (component.getLayout() & Item.LAYOUT_EXPAND) != 0;
173 }
174
175 /***
176 * {@inheritDoc}
177 */
178 protected final void pointerPressed( final int x, final int y )
179 {
180 final Enumeration components = components_.elements();
181 while( components.hasMoreElements() )
182 {
183 final Component component = (Component)components.nextElement();
184 if( component.click( x, y ) )
185 {
186 focus_ = component;
187 repaint();
188 }
189 }
190 }
191
192 /***
193 * {@inheritDoc}
194 */
195 protected final void pointerReleased( final int x, final int y )
196 {
197 if( focus_ != null )
198 {
199 focus_.unclick( x, y );
200 focus_ = null;
201 repaint();
202 }
203 }
204
205 /***
206 * {@inheritDoc}
207 */
208 protected final void pointerDragged( final int x, final int y )
209 {
210 if( focus_ != null )
211 {
212 focus_.drag( x, y );
213 repaint();
214 }
215 }
216 }