jaxx.runtime.swing.config.model.ConfigUIModel Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jaxx-config Show documentation
Show all versions of jaxx-config Show documentation
Config UI based on org.nuiton.config.ApplicationConfig
package jaxx.runtime.swing.config.model;
/*
* #%L
* JAXX :: Config
* %%
* Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit
* %%
* 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%
*/
import com.google.common.base.Joiner;
import com.google.common.base.Supplier;
import com.google.common.collect.Lists;
import jaxx.runtime.JAXXUtil;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuiton.config.ApplicationConfig;
import javax.swing.Icon;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static org.nuiton.i18n.I18n.t;
/**
* Le modele de l'ui des preferences.
*
* Ce modele contient les catégories des options.
*
* @author Tony Chemit - [email protected]
* @since 2.5.11
*/
public class ConfigUIModel implements Iterable {
/** Logger. */
private static final Log log = LogFactory.getLog(ConfigUIModel.class);
public static final String CATEGORY_MODEL_PROPERTY_NAME = "categoryModel";
/** le dictionnaire des options disponibles par categorie */
protected final Map categories;
/**
* Le fichier où sauvegarder la configuration.
* @since 2.5.21
*/
protected final File configFile;
/** La configuration de l'application */
protected final Object configBean;
/** La configuration de l'application */
protected final ApplicationConfig applicationConfig;
/** la cateogrie en cours d'utilisation */
protected CategoryModel categoryModel;
/**
* un drapeau pour savoir si la configuration a été modifiée au moins une
* fois.
*
* On utilise ce drapeau lors de la sortie pour verifier s'il faut ou non
* redemarer l'application (si non en mode standalone)
*/
protected boolean saved;
/**
* un drapeau pour savoir si l'ui de configuration a été lancée en mode
* standalone ou pas.
*
* Si pas lancée en mode standalone, et si la confi a été sauvé on vérifie
* s'il ne faut pas relancer l'application.
*/
protected boolean standalone;
/** Callbacks manager */
protected CallBacksManager callBacksManager;
/**
* optional action to execute (if not null) if no call backs fits.
*
* @since 1.4.2
*/
protected Runnable closeAction;
/** support of modification notifications */
protected final PropertyChangeSupport pcs;
public ConfigUIModel(Supplier config) {
this(config, config.get());
}
public ConfigUIModel(Supplier config, File configFile) {
this(config, config.get(), configFile);
}
public ConfigUIModel(ApplicationConfig applicationConfig) {
this(applicationConfig, applicationConfig);
}
public ConfigUIModel(ApplicationConfig applicationConfig, File configFile) {
this(applicationConfig, applicationConfig, configFile);
}
public ConfigUIModel(Object configBean, ApplicationConfig applicationConfig) {
this(configBean, applicationConfig, applicationConfig.getUserConfigFile());
}
public ConfigUIModel(Object configBean, ApplicationConfig applicationConfig, File configFile) {
this.configBean = configBean;
this.applicationConfig = applicationConfig;
this.configFile = configFile;
categories = new LinkedHashMap();
callBacksManager = new CallBacksManager();
pcs = new PropertyChangeSupport(this);
}
/**
* Ajoute une categorie dans le modele.
*
* @param category la categorie a ajouter au modèle.
*/
public void addCategory(CategoryModel category) {
if (categories.containsKey(category.getCategory())) {
throw new IllegalArgumentException(
t("config.error.category.already.exists",
category.getCategory()));
}
categories.put(category.getCategory(), category);
}
/**
* Change la categorie en cours d'édition.
*
* @param category l'id de la categorie courante
*/
public void setCategory(String category) {
if (!categories.containsKey(category)) {
throw new IllegalArgumentException(
t("config.error.category.not.found", category));
}
CategoryModel newCategoryModel = categories.get(category);
setCategoryModel(newCategoryModel);
newCategoryModel.firePropertyChange(
CategoryModel.MODIFIED_PROPERTY_NAME, false,
getCategoryModel().isModified());
newCategoryModel.firePropertyChange(
CategoryModel.VALID_PROPERTY_NAME, false,
getCategoryModel().isValid());
}
/**
* Registers a new callback.
*
* Note: the order of registred callback is used to determine
* the higher priority of callback to launch if required.
*
* @param name the unique name of a callback
* @param description the i18n key to describe the action
* @param icon the icon of the callBack (used in ui)
* @param action the action of the callback
*/
public void registerCallBack(String name,
String description,
Icon icon,
Runnable action) {
callBacksManager.registerCallBack(name, description, icon, action);
}
/**
* Registers a option into a known callback.
*
* @param name the name of the callback
* @param option the option to register for the given callback
*/
public void registerOptionCallBack(String name, OptionModel option) {
callBacksManager.registerOption(name, option);
}
public void setFinalizer(CallBackFinalizer finalizer) {
callBacksManager.setFinalizer(finalizer);
}
public Runnable getCloseAction() {
return closeAction;
}
public void setCloseAction(Runnable closeAction) {
this.closeAction = closeAction;
}
/**
* Obtain the dictionnary of callback for all to saved modified options.
*
* @return the dictonnary
*/
public CallBackMap getCallBacksForSaved() {
return callBacksManager.getCallBacksForSaved(this);
}
@Override
public Iterator iterator() {
return categories.values().iterator();
}
public CategoryModel getCategoryModel() {
return categoryModel;
}
public void setCategoryModel(CategoryModel categoryModel) {
CategoryModel old = this.categoryModel;
this.categoryModel = categoryModel;
firePropertyChange(CATEGORY_MODEL_PROPERTY_NAME, old, categoryModel);
}
public boolean isSaved() {
return saved;
}
public void setSaved(boolean saved) {
this.saved = saved;
}
public boolean isStandalone() {
return standalone;
}
public void setStandalone(boolean standalone) {
this.standalone = standalone;
}
public void saveModified() {
// compute transients keys (to never be saved)
List transients = new ArrayList();
applicationConfig.setAdjusting(true);
try {
for (OptionModel option : categoryModel) {
if (option.isModified()) {
Object value = option.getValue();
if (option.getPropertyName() != null) {
// this is a javaBean option, push value via mutator
try {
PropertyUtils.setProperty(configBean,
option.getPropertyName(), value);
} catch (Exception e) {
throw new RuntimeException(
"could not set property [" +
option.getPropertyName() +
"] with value = " + value, e);
}
} else {
// simple option with no javabeans, just push the option
// value
String toSave;
if (value == null) {
toSave = null;
} else {
if (option.isArrayType()) {
int length = Array.getLength(value);
List