All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy