Source code: echopoint/DialogPanel.java
1 package echopoint;
2
3 /*
4 * This file is part of the Echo Point Project. This project is a collection
5 * of Components that have extended the Echo Web Application Framework.
6 *
7 * EchoPoint is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * EchoPoint is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with Echo Point; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 import java.io.Serializable;
23 import java.util.EventListener;
24
25 import echopoint.event.DialogEvent;
26 import echopoint.event.DialogListener;
27 import echopoint.layout.LayoutManager;
28
29 import nextapp.echo.Color;
30 import nextapp.echo.Component;
31 import nextapp.echo.Font;
32 import nextapp.echo.event.HierarchyEvent;
33 import nextapp.echo.event.HierarchyListener;
34 import nextapp.echo.event.ActionListener;
35 import nextapp.echo.event.ActionEvent;
36
37 /**
38 * <code>DialogPanel</code>, which extends <code>ScrollablePanel</code> is
39 * a generic container that implements <code>Scrollable</code>,
40 * <code>Positionable</code> and <code>Clippable</code>.
41 * <p>
42 * When a DialogPanel is placed into the Component heirarchy, it places itself over all
43 * other components and only allows the user to interact with the components within
44 * it. It is thus said to be "modal".
45 * <p>
46 * Typically you would use the <code>DialogPanel</code> to obtain information from the user while
47 * not allowing them to interact further with the application Window until they provide
48 * that information.
49 * <p>
50 * DialogPanels stack onto top of other DialogPanels. You can add child DialogPanels to
51 * parent DialogPanels and the child ones will be "modal" with respect to the parent ones. Hence you
52 * can have a DialogPanel invoke another and have it "stack" on top of the original.
53 * <p>
54 * DialogPanels use a special zIndex range to "stack" themselves over other content. There are always
55 * placed starting at <code>DialogPanel.ZINDEX_RANGE</code>. Therefore any content you want to be "under" the
56 * DialogPanel must have a zIndex less that this. In general most components will work
57 * however this is something you will want to be aware of. If you choose to set
58 * the zIndex parameter yourself, then you will need to manage z-Index values inside
59 * your program.
60 * <p>
61 * The <code>DialogPanel</code> will center itself vertically and horizontally
62 * on the screen, unless its <code>Positionable</code> parameters are set, in which case
63 * these will values apply.
64 * <p>
65 * <code>DialogPanel</code> uses the <code>DialogListener</code> interface to raise
66 * <code>DialogEvent</code>'s when it is opened, about to be closed and closed.
67 * You can receive this events by implementing <code>DialogListener</code> and adding
68 * it to the <code>DialogPanel</code>.
69 * <p>
70 * The default <code>TitleBar</code> provide with <code>DialogPanel</code> has a close icon on it.
71 * <code>DialogPanel</code> is wired to listen to this TitleBar and will close itself when the
72 * close button is pressed. If you replace the default TitleBar, you must rewire the
73 * ActionListener interface yourself.
74 * <p>
75 * @see echopoint.positionable.Positionable
76 * @see echopoint.positionable.Scrollable
77 * @see echopoint.positionable.Clippable
78 * @see echopoint.positionable.AbstractScrollableComponent
79 * <p>
80 * @author Brad Baker
81 */
82 public class DialogPanel extends ScrollablePanel implements ActionListener{
83
84
85 /* we listen to ourselves for new parents and the close action*/
86 private class OurDialogListener implements HierarchyListener, ActionListener, Serializable {
87
88 private OurDialogListener() {
89 DialogPanel.this.addHierarchyListener(this);
90 }
91
92 public void actionPerformed(ActionEvent e) {
93 if (e.getSource() == DialogPanel.this.getTitleBar()) {
94 if (TitleBar.ACTION_CLOSE.equals(e.getActionCommand())) {
95 DialogPanel.this.close();
96 }
97 }
98
99 }
100
101 public void hierarchyChanged(HierarchyEvent e) {
102 if (e.getChanged() == DialogPanel.this) {
103 if ((e.getChangeFlags()& HierarchyEvent.PARENT_CHANGED) == HierarchyEvent.PARENT_CHANGED) {
104 if (e.getChanged().getParent() == null)
105 fireDialogClosed();
106 else
107 fireDialogOpened();
108
109 }
110 }
111 }
112 }
113
114 /** default background color is greyish */
115 public static Color defaultBackground = new Color(0xc0, 0xc0, 0xc0);
116
117 /** default titlebar background color is blueish */
118 public static Color defaultTitleBarBackground = new Color(0x33, 0x33, 0x99);
119
120 /** default titlebar font is sans serif 10*/
121 public static Font defaultTitleBarFont = new Font(Font.SANS_SERIF, Font.BOLD, 10);
122
123 /**
124 * DialogPanels always start out with this ZINDEX value
125 */
126 public static int ZINDEX_RANGE = 5000;
127
128 /**
129 * This close action command with close the DialogPanel
130 */
131 public static String ACTION_CLOSE = "close";
132
133 /** default titlebar foreground color is white */
134 public static Color defaultTitleBarForeground = Color.WHITE;
135 public static String DITHERING_CHANGED_PROPERTY = "dithering";
136 public static String DRAG_WINDOW_USED_CHANGED_PROPERTY = "dragWindowUsed";
137 public static String TITLEBAR_CHANGED_PROPERTY = "titleBar";
138 private boolean backgroundDithered = true;
139 private boolean dragWindowUsed = true;
140 private OurDialogListener ourDialogListener = null;
141
142 /** the internal titlebar reference */
143 private TitleBar titleBar;
144
145 /**
146 * DialogPanel constructor.
147 */
148 public DialogPanel() {
149 super();
150 _construct();
151 }
152
153 /**
154 * Constructs a <code>DialogPanel</code> with a LayoutManager
155 */
156 public DialogPanel(LayoutManager layoutManager) {
157 super(layoutManager);
158 setzIndex(ZINDEX_RANGE);
159 _construct();
160 }
161
162 /**
163 * DialogPanel constructor.
164 * @param left int
165 * @param top int
166 */
167 public DialogPanel(int left, int top) {
168 super(left, top);
169 setzIndex(ZINDEX_RANGE);
170 _construct();
171 }
172 /**
173 * DialogPanel constructor.
174 * @param left int
175 * @param top int
176 * @param right int
177 * @param bottom int
178 */
179 public DialogPanel(int left, int top, int right, int bottom) {
180 super(left, top, right, bottom);
181 setzIndex(ZINDEX_RANGE);
182 _construct();
183 }
184 /**
185 * DialogPanel constructor.
186 * @param left int
187 * @param top int
188 * @param right int
189 * @param bottom int
190 * @param zIndex int
191 */
192 public DialogPanel(int left, int top, int right, int bottom, int zIndex) {
193 super(left, top, right, bottom, zIndex);
194 _construct();
195 }
196 /**
197 * DialogPanel constructor.
198 * @param left int
199 * @param top int
200 * @param right int
201 * @param bottom int
202 * @param zIndex int
203 * @param positioning int
204 */
205 public DialogPanel(int left, int top, int right, int bottom, int zIndex, int positioning) {
206 super(left, top, right, bottom, zIndex, positioning);
207 _construct();
208 }
209 /**
210 * DialogPanel constructor.
211 * @param left int
212 * @param top int
213 * @param right int
214 * @param bottom int
215 * @param zIndex int
216 * @param positioning int
217 * @param scrollBarPolicy int
218 */
219 public DialogPanel(int left, int top, int right, int bottom, int zIndex, int positioning, int scrollBarPolicy) {
220 super(left, top, right, bottom, zIndex, positioning, scrollBarPolicy);
221 _construct();
222 }
223 /**
224 * DialogPanel constructor.
225 * @param left int
226 * @param top int
227 * @param right int
228 * @param bottom int
229 * @param zIndex int
230 * @param positioning int
231 * @param scrollBarPolicy int
232 * @param clipRect int[]
233 */
234 public DialogPanel(int left, int top, int right, int bottom, int zIndex, int positioning, int scrollBarPolicy, int[] clipRect) {
235 super(left, top, right, bottom, zIndex, positioning, scrollBarPolicy, clipRect);
236 _construct();
237 }
238 /**
239 * DialogPanel constructor.
240 */
241 public DialogPanel(String dialogTitle) {
242 super();
243 setzIndex(ZINDEX_RANGE);
244 _construct();
245 titleBar.setText(dialogTitle);
246 }
247 /**
248 * A private common constructor method
249 */
250 private void _construct() {
251 ourDialogListener = new OurDialogListener();
252
253 setBackground(defaultBackground);
254 setScrollBarPolicy(DialogPanel.SCROLLBARS_AUTO);
255
256 titleBar = new TitleBar("Dialog", TitleBar.TB_CLOSE);
257
258 titleBar.setBackground(defaultTitleBarBackground);
259 titleBar.setFont(defaultTitleBarFont);
260 titleBar.setForeground(defaultTitleBarForeground);
261 titleBar.setHorizontalAlignment(nextapp.echo.EchoConstants.LEFT);
262 add(titleBar);
263 titleBar.addActionListener(ourDialogListener);
264 }
265 /**
266 * adds and removes an Component from the current hierarchy tree
267 */
268 private void _reRegisterComponents(Component oldValue, Component newValue) {
269 if (oldValue != null && this.isAncestorOf(oldValue)) {
270 super.remove(oldValue);
271 }
272 if (newValue != null && !this.isAncestorOf(newValue)) {
273 super.add(newValue, -1);
274 }
275 }
276 /**
277 * Adds a <code>DialogListener</code> to the dialog
278 *
279 * @param l The <code>DialogListener</code> to be added.
280 */
281 public void addDialogListener(DialogListener l) {
282 listenerList.addListener(DialogListener.class, l);
283 }
284 /**
285 * Closes the dialog.
286 * <p>
287 * This helper method removes the dialog from its parent, if it has one, and hence
288 * the dialog will not longer appear.
289 */
290 public void close() {
291 if (getParent() != null) {
292 fireDialogClosing();
293 getParent().remove(this);
294 }
295 }
296
297 /**
298 * Notifies <code>DialogListener</code>s that the dialog has been closed.
299 */
300 private void fireDialogClosed() {
301 DialogEvent e = new DialogEvent(this);
302 EventListener[] listeners = listenerList.getListeners(DialogListener.class);
303 for (int index = 0; index < listeners.length; ++index) {
304 ((DialogListener) listeners[index]).dialogClosed(e);
305 }
306 }
307
308 /**
309 * Notifies <code>DialogListener</code>s that dialog is closing.
310 */
311 private void fireDialogClosing() {
312 DialogEvent e = new DialogEvent(this);
313 EventListener[] listeners = listenerList.getListeners(DialogListener.class);
314 for (int index = 0; index < listeners.length; ++index) {
315 ((DialogListener) listeners[index]).dialogClosing(e);
316 }
317 }
318
319 /**
320 * Notifies <code>DialogListener</code>s that the dialog has been opened.
321 */
322 private void fireDialogOpened() {
323 DialogEvent e = new DialogEvent(this);
324 EventListener[] listeners = listenerList.getListeners(DialogListener.class);
325 for (int index = 0; index < listeners.length; ++index) {
326 ((DialogListener) listeners[index]).dialogOpened(e);
327 }
328 }
329 /**
330 * Gets the titlebar used by the DialogPanel
331 *
332 * @return echopoint.TitleBar
333 */
334 public TitleBar getTitleBar() {
335 return titleBar;
336 }
337 /**
338 * Retursn true if the background, under the DialogPanel, is to be dithered.
339 *
340 * @return boolean
341 */
342 public boolean isBackgroundDithered() {
343 return backgroundDithered;
344 }
345
346 /**
347 * Removes a <code>DialogListener</code> from the dialog
348 *
349 * @param l The <code>DialogListener</code> to be removed.
350 */
351 public void removeDialogListener(DialogListener l) {
352 listenerList.removeListener(DialogListener.class, l);
353 }
354 /**
355 Sets whether the background, under the DialogPanel, is to be dithered.
356 *
357 * @param newBackgroundDithered boolean
358 */
359 public void setBackgroundDithered(boolean newBackgroundDithered) {
360 boolean oldValue = backgroundDithered;
361 backgroundDithered = newBackgroundDithered;
362 firePropertyChange(DITHERING_CHANGED_PROPERTY, oldValue, newBackgroundDithered);
363 }
364 /**
365 * Sets the titlebar used by the DialogPanel
366 *
367 * @param newTitleBar echopoint.TitleBar
368 */
369 public void setTitleBar(TitleBar newTitleBar) {
370 TitleBar oldValue = titleBar;
371 titleBar = newTitleBar;
372 _reRegisterComponents(oldValue, newTitleBar);
373 firePropertyChange(TITLEBAR_CHANGED_PROPERTY, oldValue, newTitleBar);
374 }
375 /**
376 * Returns whether a drag window is used when dragging.
377 *
378 * @return - boolean
379 */
380 public boolean isDragWindowUsed() {
381 return dragWindowUsed;
382 }
383
384 /**
385 * Sets whether a drag window is used when dragging. This is a
386 * semi-transparent visual artifact that indicates where DialogPanel
387 * can be dragged.
388 *
389 * @param newValue - whether a drag window is used while dragging.
390 */
391 public void setDragWindowUsed(boolean newValue) {
392 boolean oldValue = dragWindowUsed;
393 dragWindowUsed = newValue;
394 firePropertyChange(DRAG_WINDOW_USED_CHANGED_PROPERTY,oldValue,newValue);
395 }
396
397 /**
398 * @see echopoint.positionable.Positionable#getzIndex()
399 */
400 public int getzIndex() {
401 return super.getzIndex();
402 }
403
404
405 /**
406 * @see echopoint.ScrollablePanel#setzIndex(int)
407 */
408 public void setzIndex(int newValue) {
409 super.setzIndex(newValue);
410 }
411
412 /**
413 * The <code>DialogPanel</code> is an <code>ActionListener</code> and
414 * it listens for an <code>ActionEvent</code> with a command
415 * of <code>DialogPanel.ACTION_CLOSE</code>. If it receives
416 * such an event then it will close itself.
417 *
418 * @see nextapp.echo.event.ActionListener#actionPerformed(nextapp.echo.event.ActionEvent)
419 */
420 public void actionPerformed(ActionEvent e) {
421 if (e != null && ACTION_CLOSE.equals(e.getActionCommand())) {
422 this.close();
423 }
424 }
425
426 /** @see echopoint.util.ReflectionSetter#set(Field, Object) */
427 public Object set(java.lang.reflect.Field field, Object newValue) throws Exception {
428 Object oldValue = field.get(this); field.set(this,newValue); return oldValue;
429 }
430
431 }