org.nuiton.jaxx.runtime.swing.wizard.WizardModel Maven / Gradle / Ivy
The newest version!
/*
* #%L
* JAXX :: Runtime
* %%
* Copyright (C) 2008 - 2024 Code Lutin, Ultreia.io
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
package org.nuiton.jaxx.runtime.swing.wizard;
import org.nuiton.jaxx.runtime.JAXXUtil;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Un modèle de wizard.
*
*
* Note: le type des étapes doit être uné énumération qui implante {@link
* WizardStep}.
*
* @param le type des étapes.
* @author Tony Chemit - [email protected]
* @see WizardStep
* @since 1.3
*/
public abstract class WizardModel {
public static final String STEPS_PROPERTY_NAME = "steps";
public static final String STEP_PROPERTY_NAME = "step";
public static final String PREVIOUS_STEP_PROPERTY_NAME = "previousStep";
public static final String NEXT_STEP_PROPERTY_NAME = "nextStep";
public static final String VALID_STEP_PROPERTY_NAME = "validStep";
public static final String BUSY_PROPERTY_NAME = "busy";
/** le type d'une etape du model (doit etre une enumeration) */
protected final Class stepClass;
/** Toutes les étapes à passer */
protected List steps;
/** les etapes a exclure */
protected List excludeSteps;
/** L'étape courante */
protected E step;
/** drapeau pour valider l'état de l'étape courante */
protected boolean validStep;
/** un drapeau pour savoir si le modèle est occupé. */
private boolean busy;
/**
* drapeau lorsque le modele effectue des operations de transformation de
* modele mais que les écouteurs ne devraient pas tenir compte des
* modifications
*/
protected boolean valueAdjusting;
/** pour propager les changements dans le modèle vers l'ui */
protected PropertyChangeSupport pcs;
public WizardModel(Class stepClass, E... steps) {
if (!Enum.class.isAssignableFrom(stepClass)) {
throw new IllegalArgumentException("stepClass must be an" +
" Enumeration but was " + stepClass.getName());
}
this.stepClass = stepClass;
pcs = new PropertyChangeSupport(this);
this.steps = new ArrayList<>();
if (steps.length > 0) {
setSteps(steps);
}
}
public void start() {
if (steps.isEmpty()) {
throw new IllegalStateException("can not start, no step found");
}
step = null;
E startStep = steps.get(0);
setStep(startStep);
}
public void destroy() {
// suppression de tous les listeners
JAXXUtil.destroy(pcs);
}
public void gotoNextStep() {
E nextStep = getNextStep();
if (nextStep == null) {
throw new IllegalStateException("no next step to go");
}
setStep(nextStep);
}
public void gotoPreviousStep() {
E previousStep = getPreviousStep();
if (previousStep == null) {
throw new IllegalStateException("no previous step to go");
}
setStep(previousStep);
}
public void gotoStep(E e) {
if (e == null) {
throw new NullPointerException("step can not be null");
}
if (!steps.contains(e)) {
throw new IllegalStateException("step " + e.toString() +
" is not in universe of steps (" + steps + ')');
}
setBusy(true);
try {
setStep(e);
} finally {
setBusy(false);
}
}
public E getStep() {
return step;
}
public int getStepIndex(E s) {
return steps.indexOf(s);
}
public boolean isValidStep() {
return validStep;
}
public E getPreviousStep() {
return getPreviousStep(step);
}
public E getPreviousStep(E step) {
int index = getStepIndex(step);
if (index < 1) {
// si pas de step ou sur premier step
return null;
}
return steps.get(index - 1);
}
public E getNextStep(E step) {
int index = getStepIndex(step);
if (index < 1) {
// si pas de step ou sur premier step
return null;
}
return steps.get(index - 1);
}
public E getNextStep() {
int index = getStepIndex(step);
if (index == -1 || index == steps.size() - 1) {
// si pas de step positionne ou dernier etape
return null;
}
return steps.get(index + 1);
}
public List getSteps() {
return steps;
}
public boolean containsStep(E step) {
return getSteps().contains(step);
}
public boolean isValueAdjusting() {
return valueAdjusting;
}
public boolean isBusy() {
return busy;
}
public void setBusy(boolean busy) {
boolean oldValue = this.busy;
this.busy = busy;
firePropertyChange(BUSY_PROPERTY_NAME, oldValue, busy);
}
/**
* Change l'univers des etapes.
*
* Note: on presume ici que l'étape courante est toujours la meme.
*
* @param steps le nouvel univers des etapes
*/
public void setSteps(E... steps) {
List oldValue = this.steps;
this.steps = Collections.unmodifiableList(Arrays.asList(steps));
firePropertyChange(STEPS_PROPERTY_NAME, oldValue, this.steps);
// la propriete nextStep peut avoir changee
firePropertyChange(NEXT_STEP_PROPERTY_NAME, null, getNextStep());
}
public void setValueAdjusting(boolean valueAdjusting) {
this.valueAdjusting = valueAdjusting;
}
public void setExcludeSteps(List excludeSteps) {
this.excludeSteps = excludeSteps;
}
public boolean validate(E s) {
return step != null;
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcs.addPropertyChangeListener(listener);
}
public void addPropertyChangeListener(String propertyName,
PropertyChangeListener listener) {
pcs.addPropertyChangeListener(propertyName, listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
pcs.removePropertyChangeListener(listener);
}
public void removePropertyChangeListener(String propertyName,
PropertyChangeListener listener) {
pcs.removePropertyChangeListener(propertyName, listener);
}
public void removePropertyChangeListeners() {
JAXXUtil.destroy(pcs);
}
@Override
protected void finalize() throws Throwable {
super.finalize();
destroy();
}
public void validate() {
if (step == null) {
// pas de validation quand aucune etape n'est sélectionnée
return;
}
validStep = validate(step);
// toujours forcer la propagation
firePropertyChange(VALID_STEP_PROPERTY_NAME, null, validStep);
}
public abstract void updateUniverse();
public Class getStepClass() {
return stepClass;
}
protected void setStep(E step) {
E oldValue = this.step;
this.step = step;
firePropertyChange(STEP_PROPERTY_NAME, oldValue, step);
// la propriete nextStep peut avoir changee
firePropertyChange(NEXT_STEP_PROPERTY_NAME, null, getNextStep());
// la propriete previousStep peut avoir changee
firePropertyChange(PREVIOUS_STEP_PROPERTY_NAME, null, getPreviousStep());
validate();
}
protected void firePropertyChange(String propertyName, Object oldValue,
Object newValue) {
pcs.firePropertyChange(propertyName, oldValue, newValue);
}
protected void firePropertyChange(String propertyName, Object newValue) {
pcs.firePropertyChange(propertyName, null, newValue);
}
protected void fireIndexedPropertyChange(String propertyName, int index,
Object oldValue, Object newValue) {
pcs.fireIndexedPropertyChange(propertyName, index, oldValue, newValue);
}
}