001/* ---------------------------------------------------------------------------- 002 The Kiwi Toolkit - A Java Class Library 003 Copyright (C) 1998-2004 Mark A. Lindner 004 005 This library is free software; you can redistribute it and/or 006 modify it under the terms of the GNU General Public License as 007 published by the Free Software Foundation; either version 2 of the 008 License, or (at your option) any later version. 009 010 This library is distributed in the hope that it will be useful, 011 but WITHOUT ANY WARRANTY; without even the implied warranty of 012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 General Public License for more details. 014 015 You should have received a copy of the GNU General Public License 016 along with this library; if not, write to the Free Software 017 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 018 02111-1307, USA. 019 020 The author may be contacted at: mark_a_lindner@yahoo.com 021 ---------------------------------------------------------------------------- 022 $Log: WizardPanelSequence.java,v $ 023 Revision 1.9 2004/05/12 19:16:54 markl 024 comment block updates 025 026 Revision 1.8 2003/01/19 09:50:54 markl 027 Javadoc & comment header updates. 028 029 Revision 1.7 2001/03/12 09:28:02 markl 030 Source code and Javadoc cleanup. 031 032 Revision 1.6 2000/08/26 09:04:41 markl 033 Changed Wizard*.java APIs to facilitate easier control over forward/ 034 backward navigation. 035 036 Revision 1.5 1999/08/24 08:30:44 markl 037 Fixed some javadoc comments. 038 039 Revision 1.4 1999/03/11 03:59:01 markl 040 Minor layout fix. 041 042 Revision 1.3 1999/02/28 11:44:08 markl 043 Minor fixes. 044 045 Revision 1.2 1999/01/10 03:05:32 markl 046 added GPL header & RCS tag 047 ---------------------------------------------------------------------------- 048*/ 049 050package kiwi.ui; 051 052import java.util.*; 053import javax.swing.event.*; 054 055import kiwi.event.*; 056import kiwi.util.*; 057 058/** This class serves as a factory of <code>WizardPanel</code>s for a 059 * <code>WizardView</code>. A <code>WizardPanelSequence</code> maintains a set 060 * of <code>WizardPanel</code>s and a <code>Config</code> object. When a 061 * <code>WizardPanel</code> is added to the sequence, a reference to the 062 * <code>Config</code> object is passed to the panel. The panel may use this 063 * <code>Config</code> object to store results from user input or to look up 064 * the current or default values for its input fields. 065 * <p> 066 * Whenever the value of a property is changed or a property is added to or 067 * removed from the <code>Config</code> object, the <code>Config</code> 068 * object notifies the <code>WizardPanelSequence</code> via a 069 * <code>ChangeEvent</code>. Subclassers may override the 070 * <code>stateChanged()</code> method to handle these events. 071 * 072 * @see kiwi.ui.WizardView 073 * @see kiwi.ui.WizardPanel 074 * @see kiwi.util.Config 075 * @see javax.swing.event.ChangeEvent 076 * 077 * @author Mark Lindner 078 */ 079 080public class WizardPanelSequence implements ChangeListener 081 { 082 /** The list of <code>WizardPanel</code>s. */ 083 protected Vector panels; 084 /** The index of the currently-selected <code>WizardPanel</code>. */ 085 protected int currentIndex = -1; 086 private ChangeSupport support; 087 /** The configuration object for this sequence. */ 088 protected Config config; 089 090 /** Construct a new <code>WizardPanelSequence</code>. 091 */ 092 093 public WizardPanelSequence() 094 { 095 this(new Config()); 096 } 097 098 /** Construct a new <code>WizardPanelSequence</code> with the given 099 * configuration object. 100 * 101 * @param config The configuration object to use as a datasource. 102 */ 103 104 public WizardPanelSequence(Config config) 105 { 106 panels = new Vector(); 107 support = new ChangeSupport(this); 108 this.config = config; 109 config.addChangeListener(this); 110 } 111 112 /** Add a <code>WizardPanel</code> to this sequence. All panels should be 113 * added before the sequence is used to construct a <code>WizardView</code>. 114 * 115 * @param panel The panel to add. 116 * @see #addPanels 117 */ 118 119 public final void addPanel(WizardPanel panel) 120 { 121 panels.addElement(panel); 122 panel.addChangeListener(this); 123 panel.setConfig(config); 124 } 125 126 /** Add an array of <code>WizardPanel</code>s to this sequence. All panels 127 * should be added before the sequence is used to construct a 128 * <code>WizardView</code>. 129 * 130 * @param panels The panels to add. 131 * @see #addPanel 132 */ 133 134 public final void addPanels(WizardPanel panels[]) 135 { 136 for(int i = 0; i < panels.length; i++) 137 addPanel(panels[i]); 138 } 139 140 /** Reset the sequence. Resets the sequence so that the first panel in the 141 * sequence becomes the current panel; thus the next call to 142 * <code>getNextPanel()</code> will return the first panel in the sequence. 143 * 144 * @see #getNextPanel 145 */ 146 147 public void reset() 148 { 149 currentIndex = -1; 150 } 151 152 /** Get a reference to this <code>WizardPanelSequence</code>'s 153 * <code>Config</code> object. 154 * 155 * @return The <code>Config</code> object. 156 */ 157 158 public final Config getConfig() 159 { 160 return(config); 161 } 162 163 /** Get the currently displayed panel from this sequence. 164 * 165 * @return The current panel. 166 */ 167 168 public WizardPanel getCurrentPanel() 169 { 170 return((currentIndex < 0) ? null 171 : (WizardPanel)panels.elementAt(currentIndex)); 172 } 173 174 /** Get the next panel from this sequence. The default implementation 175 * returns the next panel from the <code>panels</code> vector and 176 * increments the <code>currentIndex</code> variable only if the end of 177 * the sequence has not been reached <i>and</i> the next panel is 178 * reachable (e.g., if <code>canMoveForward()</code> returns 179 * <cod>true</code>). 180 * 181 * @return The next panel to be displayed in the <code>WizardView</code>. 182 */ 183 184 public WizardPanel getNextPanel() 185 { 186 if(isLastPanel()) 187 return(null); 188 189// if(!canMoveForward()) return(null); 190 191 return((WizardPanel)panels.elementAt(++currentIndex)); 192 } 193 194 /** Get the previous panel from this sequence. The default implementation 195 * returns the previous panel from the <code>panels</code> vector and 196 * decrements the <code>currentIndex</code> variable only if the beginning 197 * of the sequence has not been reached <i>and</i> the previous panel is 198 * reachable (e.g., if <code>canMoveBackward()</code> returns 199 * <code>true</code>). 200 * 201 * @return The previous panel to be displayed in the 202 * <code>WizardView</code>. 203 */ 204 205 public WizardPanel getPreviousPanel() 206 { 207 if(currentIndex == 0) 208 return(null); 209 210// if(!canMoveBackward()) return(null); 211 212 return((WizardPanel)panels.elementAt(--currentIndex)); 213 } 214 215 /** Determine if the current panel is the last panel in the sequence. Once 216 * the last panel in a sequence has been reached, th 217 * <code>WizardView</code> changes its <i>Next</i> button to a 218 * <i>Finish</i> button. 219 * 220 * @return <code>true</code> if the current panel is the last panel, and 221 * <code>false</code> otherwise. 222 */ 223 224 public boolean isLastPanel() 225 { 226 return(currentIndex == (panels.size() - 1)); 227 } 228 229 /** Determine if the user is allowed to move to the next panel. The 230 * default implementation returns <code>true</code> if the current panel 231 * is not the last panel in the sequence <i>and</i> the 232 * <code>canMoveForward()</code> method of the current panel 233 * returns <code>true</code>. Subclassers may wish to override this 234 * method to allow movement forward only if certain conditions are 235 * met. 236 * 237 * @return <code>true</code> if the previous panel is reachable, and 238 * <code>false</code> otherwise. 239 */ 240 241 public boolean canMoveForward() 242 { 243 if(currentIndex > panels.size() - 1) 244 return(false); 245 246 WizardPanel p = getCurrentPanel(); 247 return((p == null) ? false : p.canMoveForward()); 248 } 249 250 /** Determine if the user is allowed to move to the previous 251 * panel. The default implementation returns <code>true</code> if the 252 * current panel is not the first panel in the sequence <i>and</i> 253 * the <code>canMoveBackward()</code> method of the current panel 254 * returns <code>true</code>. Subclassers may wish to override this 255 * method to allow movement backward only if certain conditions are 256 * met. 257 */ 258 259 public boolean canMoveBackward() 260 { 261 if(currentIndex <= 0) 262 return(false); 263 264 WizardPanel p = getCurrentPanel(); 265 return((p == null) ? false : p.canMoveBackward()); 266 } 267 268 /** Handle <code>ChangeEvent</code>s fired by the <code>WizardPanel</code>s 269 * that belong to this sequence. The default implementation does nothing; 270 * subclassers may wish to add logic to determine (based on the current 271 * values of properties in the <code>Config</code> object) whether movement 272 * to the next or previous panel is allowed, or to determine which panel 273 * will be displayed next, for example. 274 * 275 * @param evt The event. The source of the event is the 276 * <code>WizardPanel</code> that fired it. 277 * @see java.util.EventObject#getSource 278 */ 279 280 public void stateChanged(ChangeEvent evt) 281 { 282 // handle change events here 283 284 fireChangeEvent(); 285 } 286 287 /** Add a <code>ChangeListener</code> to this object's list of listeners. 288 * 289 * @param listener The listener to add. 290 */ 291 292 public void addChangeListener(ChangeListener listener) 293 { 294 support.addChangeListener(listener); 295 } 296 297 /** Remove a <code>ChangeListener</code> from this object's list of 298 * listeners. 299 * 300 * @param listener The listener to remove. 301 */ 302 303 public void removeChangeListener(ChangeListener listener) 304 { 305 support.removeChangeListener(listener); 306 } 307 308 /** Fire a change event. Notify listeners (typically only the 309 * <code>WizardView</code> that owns this sequence) that the state of this 310 * <code>WizardPanelSequence</code> has changed. Subclassers may wish to 311 * call this method from the body of the <code>stateChanged()</code> 312 * method if a change in the <code>Config</code> object has changed the 313 * state of this <code>WizardPanelSequence</code> in a way that will 314 * affect the appearance of the <code>WizardView</code>. 315 */ 316 317 protected void fireChangeEvent() 318 { 319 support.fireChangeEvent(); 320 } 321 322 /** Dispose of this object. */ 323 324 public void dispose() 325 { 326 config.removeChangeListener(this); 327 config = null; 328 } 329 330 } 331 332/* end of source file */