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

jaxx.runtime.swing.config.model.ConfigUIModel Maven / Gradle / Ivy

There is a newer version: 3.0-alpha-1
Show newest version
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 values = Lists.newArrayListWithCapacity(length); for (int i = 0; i < length; i++) { values.add(Array.get(value, i)); } toSave = Joiner.on(",").join(values); } else { toSave = value.toString(); } } applicationConfig.setOption(option.getKey(), toSave); } // l'option a été sauvegardée, on la marque option.setSaved(true); // this is the new original value option.initValue(value); } if (option.isTransient()) { transients.add(option.getKey()); } } } finally { applicationConfig.setAdjusting(false); } setSaved(true); // save config // Ano // applicationConfig.saveForUser(transients.toArray(new String[transients.size()])); try { applicationConfig.save(configFile, false, transients.toArray(new String[transients.size()])); } catch (IOException eee) { if (log.isWarnEnabled()) { log.warn(t("config.error.applicationconfig.save", configFile), eee); } } // notify data has changed categoryModel.firePropertyChange( CategoryModel.MODIFIED_PROPERTY_NAME, categoryModel.isModified(), true); categoryModel.firePropertyChange( CategoryModel.VALID_PROPERTY_NAME, false, categoryModel.isValid()); categoryModel.firePropertyChange( CategoryModel.RELOAD_PROPERTY_NAME, false, true); } public void reset() { // reset all modified options of the current category for (OptionModel key : categoryModel) { if (key.isModified()) { key.initValue(key.getOriginalValue()); } } // notify data has changed categoryModel.firePropertyChange( CategoryModel.MODIFIED_PROPERTY_NAME, categoryModel.isModified(), true); categoryModel.firePropertyChange( CategoryModel.VALID_PROPERTY_NAME, false, categoryModel.isValid()); categoryModel.firePropertyChange( CategoryModel.RELOAD_PROPERTY_NAME, false, true); } public int getCategoryIndex(String category) { int i = 0; for (CategoryModel m : this) { if (category.equals(m.getCategory())) { return i; } i++; } // not found return -1; } public void firePropertyChange(String propertyName, Object oldValue, Object newValue) { pcs.firePropertyChange(propertyName, oldValue, newValue); } 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 boolean hasListeners(String propertyName) { return pcs.hasListeners(propertyName); } public PropertyChangeListener[] getPropertyChangeListeners( String propertyName) { return pcs.getPropertyChangeListeners(propertyName); } public PropertyChangeListener[] getPropertyChangeListeners() { return pcs.getPropertyChangeListeners(); } public void destroy() { JAXXUtil.destroy(pcs); } @Override protected void finalize() throws Throwable { super.finalize(); destroy(); } /** * @return the underlined application config * @deprecated since 2.5.4 use now {@link #getApplicationConfig()}. */ protected ApplicationConfig getConfig() { return applicationConfig; } /** * @return the underlined application config * @since 2.5.4 */ protected ApplicationConfig getApplicationConfig() { return applicationConfig; } protected CallBacksManager getCallBacksManager() { return callBacksManager; } public String getCategoryName(int index) { return Lists.newArrayList(categories.keySet()).get(index); } }