001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU General
007: * Public License Version 2 only ("GPL") or the Common Development and Distribution
008: * License("CDDL") (collectively, the "License"). You may not use this file except in
009: * compliance with the License. You can obtain a copy of the License at
010: * http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP. See the
011: * License for the specific language governing permissions and limitations under the
012: * License. When distributing the software, include this License Header Notice in
013: * each file and include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Sun
014: * designates this particular file as subject to the "Classpath" exception as
015: * provided by Sun in the GPL Version 2 section of the License file that
016: * accompanied this code. If applicable, add the following below the License Header,
017: * with the fields enclosed by brackets [] replaced by your own identifying
018: * information: "Portions Copyrighted [year] [name of copyright owner]"
019: *
020: * Contributor(s):
021: *
022: * The Original Software is NetBeans. The Initial Developer of the Original Software
023: * is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All
024: * Rights Reserved.
025: *
026: * If you wish your version of this file to be governed by only the CDDL or only the
027: * GPL Version 2, indicate your decision by adding "[Contributor] elects to include
028: * this software in this distribution under the [CDDL or GPL Version 2] license." If
029: * you do not indicate a single choice of license, a recipient has the option to
030: * distribute your version of this file under either the CDDL, the GPL Version 2 or
031: * to extend the choice of license to its licensees as provided above. However, if
032: * you add GPL Version 2 code and therefore, elected the GPL Version 2 license, then
033: * the option applies only if the new code is made subject to such option by the
034: * copyright holder.
035: */
036:
037: package org.netbeans.installer.wizard.components;
038:
039: import org.netbeans.installer.wizard.Wizard;
040: import org.netbeans.installer.wizard.ui.WizardUi;
041:
042: /**
043: * This class is a specialization of the {@link WizardComponent} which defines
044: * behavior specific to sequences.
045: *
046: * <p>
047: * A sequence is merely a list of {@link WizardComponent}s which executes when the
048: * sequence itself is executed. This makes wizard sequences the instrument to add
049: * "depth" to the wizard, enable conditional execution of a set of components, etc.
050: * It is also the only "standard" component which actually makes use of its child
051: * components.
052: *
053: * <p>
054: * {@link WizardSequence} uses child {@link Wizard} instances to execute its
055: * child components. The {@link Wizard} instances are created via the
056: * {@link Wizard#createSubWizard(List,int)} method.
057: *
058: * <p>
059: * A wizard sequence does not have a UI of its own - it completely relies on the UI
060: * of its child components.
061: *
062: * @author Kirill Sorokin
063: * @since 1.0
064: */
065: public class WizardSequence extends WizardComponent {
066: /**
067: * Current child {@link WIzard} instance which is used to iterate of over the
068: * list of child {@link WizardComponent}s.
069: */
070: protected Wizard childWizard;
071:
072: /**
073: * Executes the sequence when it is reached via a call to {@link Wizard#next()}.
074: * This method simply creates a new child instance of {@link Wizard} over the
075: * list of child components, sets the index of the active component to the
076: * pre-first one and calls {@link Wizard#next()}.
077: *
078: * @see WizardComponent#executeForward()
079: */
080: public void executeForward() {
081: childWizard = getWizard().createSubWizard(getChildren(), -1);
082:
083: childWizard.next();
084: }
085:
086: /**
087: * Executes the sequence when it is reached via a call to
088: * {@link Wizard#previous()}. This method simply creates a new child instance
089: * of {@link Wizard} over the of child components, sets the index of the active
090: * component to the after-last one and calls {@link Wizard#previous()}.
091: *
092: * @see WizardComponent#executeBackward()
093: */
094: public void executeBackward() {
095: childWizard = getWizard().createSubWizard(getChildren(),
096: getChildren().size());
097:
098: childWizard.previous();
099: }
100:
101: /**
102: * The default implementation of this method for {@link WizardSequence} has an
103: * empty body. Concrete implementations are expected to override this method
104: * if they require any custom initialization.
105: *
106: * @see WizardComponent#initialize()
107: */
108: public void initialize() {
109: // does nothing
110: }
111:
112: /**
113: * Whether the sequence can be executed when reached via a call to
114: * {@link Wizard#next()}. Since the sequence does not contain any logic of its
115: * own, it searches through the list of child components checking whether there
116: * is one that can be executed. If such a component is found, the sequence
117: * considers itself to be able to execute.
118: *
119: * @return <code>true</code> is the sequence can be executed, <code>false</code>
120: * otherwise.
121: */
122: @Override
123: public boolean canExecuteForward() {
124: // whether a sequence can be executed completely depends on whether its
125: // children can be executed, thus we should run through them and check
126: for (int i = 0; i < getChildren().size(); i++) {
127: final WizardComponent component = getChildren().get(i);
128:
129: // if the component can be executed forward the whole sequence can be
130: // executed as well
131: if (component.canExecuteForward()) {
132: return true;
133: }
134: }
135:
136: // if none of the components can be executed, it does not make sense to
137: // execute the sequence as well
138: return false;
139: }
140:
141: /**
142: * Whether the sequence can be executed when reached via a call to
143: * {@link Wizard#previous()}. Since the sequence does not contain any logic of
144: * its own, it searches through the list of child components checking whether
145: * there is one that can be executed. If such a component is found, the sequence
146: * considers itself to be able to execute.
147: *
148: * @return <code>true</code> is the sequence can be executed, <code>false</code>
149: * otherwise.
150: */
151: @Override
152: public boolean canExecuteBackward() {
153: // whether a sequence can be executed completely depends on whether its
154: // children can be executed, thus we should run through them and check
155: for (int i = getChildren().size() - 1; i > -1; i--) {
156: final WizardComponent component = getChildren().get(i);
157:
158: // if the component can be executed backward the whole sequence can be
159: // executed as well
160: if (component.canExecuteBackward()) {
161: return true;
162: }
163:
164: // if the currently examined component is a point of no return and it
165: // cannot be executed (since we passed the previous statement) - we have
166: // no previous component
167: if (component.isPointOfNoReturn()) {
168: return false;
169: }
170: }
171:
172: // if none of the components can be executed it does not make sense to
173: // execute the sequence as well
174: return false;
175: }
176:
177: /**
178: * Whether the sequence is a point of no return. Since the sequence does not
179: * contain any logic of its own, it searches through the list of child
180: * components checking whether there is one that is a point of no return. If
181: * such a component is found and the index of the active component is greater
182: * than that of the found component, the sequence considers itself to be the
183: * point of no return.
184: *
185: * @return <code>true</code> is the sequence is the point of no return,
186: * <code>false</code> otherwise.
187: */
188: @Override
189: public boolean isPointOfNoReturn() {
190: // if there is a point-of-no-return child and it has already been passed,
191: // then the sequence of a point of no return, otherwise it's not
192: if (childWizard != null) {
193: for (int i = 0; i < getChildren().size(); i++) {
194: if (getChildren().get(i).isPointOfNoReturn()
195: && (i < childWizard.getIndex())) {
196: return true;
197: }
198: }
199: }
200:
201: // otherwise, it's not
202: return false;
203: }
204:
205: /**
206: * Returns the {@link WizardUi} object for this component. Since the sequence
207: * does not have an UI of its own, this method always returns <code>null</code>.
208: *
209: * @return <code>null</code>.
210: */
211: public WizardUi getWizardUi() {
212: // a sequence does not have a UI of its own, thus returning null
213: return null;
214: }
215: }
|