
com.globalmentor.swing.AbstractConfiguredFramedSwingApplication Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of globalmentor-swing Show documentation
Show all versions of globalmentor-swing Show documentation
GlobalMentor Java Swing library.
The newest version!
/*
* Copyright © 1996-2009 GlobalMentor, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.globalmentor.swing;
import java.io.*;
import java.net.URI;
import static com.globalmentor.java.OperatingSystem.*;
import com.globalmentor.io.*;
import com.globalmentor.java.*;
import com.globalmentor.log.Log;
import com.globalmentor.model.Modifiable;
/**
* A framed Swing application that maintains configuration information.
*
* If a configuration is provided via setConfiguration()
, that configuration is automatically loaded and saved.
*
* @param The type of configuration object.
* @author Garret Wilson
*/
public abstract class AbstractConfiguredFramedSwingApplication extends AbstractFramedSwingApplication implements Modifiable {
/** The filename of the configuration file. */
public static final String CONFIGURATION_FILENAME = "configuration.rdf";
/** Whether the object has been modified; the default is not modified. */
private boolean modified = false;
/** The name of the configuration directory, or null
if the default should be used. */
private String configurationDirectoryName = null;
/**
* @return The name of the configuration directory. If no configuration directory has been assigned, a default is returned constructed from the local name of
* the application class in lowercase, preceded by a full stop character ('.').
*/
protected String getConfigurationDirectoryName() {
return configurationDirectoryName != null //if a configuration directory name has been assigned
? configurationDirectoryName //return the configuration directory name
: String.valueOf(Files.FILENAME_EXTENSION_SEPARATOR) + Classes.getLocalName(getClass()).toLowerCase(); //otherwise, return ".applicationname"
}
/**
* Sets the name of the configuration directory.
* @param configurationDirectoryName The name of the configuration directory, or null
if the default should be used.
*/
protected void setConfigurationDirectoryName(final String configurationDirectoryName) {
this.configurationDirectoryName = configurationDirectoryName;
}
/**
* @return The configuration directory for the application.
* @throws SecurityException if a security manager exists and its checkPropertyAccess
method doesn't allow access to the user home system
* property.
* @see OperatingSystem#getUserHomeDirectory()
* @see #getConfigurationDirectoryName()
*/
public File getConfigurationDirectory() throws SecurityException {
return new File(getUserHomeDirectory(), getConfigurationDirectoryName()); //return the configuration directory inside the user home directory
}
/**
* @return An object representing the file containing the configuration information.
* @throws SecurityException if a security manager exists and its checkPropertyAccess
method doesn't allow access to the user home system
* property.
* @see #getConfigurationDirectory()
*/
public File getConfigurationFile() throws SecurityException {
return new File(getConfigurationDirectory(), CONFIGURATION_FILENAME); //return the configuration file inside the configuration directory
}
/** The application configuration, or null
if there is no configuration. */
private C configuration = null;
/** @return The application configuration, or null
if there is no configuration. */
public C getConfiguration() {
return configuration;
}
/**
* Sets the application configuration.
* @param config The application configuration, or null
if there should be no configuration.
*/
private void setConfiguration(final C config) {
configuration = config;
}
/** The configuration storage I/O kit, or null
if there is no configuration storage. */
private IOKit configurationIOKit = null;
/** @return The configuration storage I/O kit, or null
if there is no configuration storage. */
public IOKit getConfigurationIOKit() {
return configurationIOKit;
}
/**
* Sets the configuration storage I/O kit.
* @param ioKit The configuration storage I/O kit, or null
if there should be no configuration.
*/
protected void setConfigurationIOKit(final IOKit ioKit) {
configurationIOKit = ioKit;
}
/**
* Reference URI constructor.
* @param uri The URI identifying the application.
* @param name The name of the application.
*/
public AbstractConfiguredFramedSwingApplication(final URI uri, final String name) {
this(uri, name, NO_ARGUMENTS); //construct the class with no arguments
}
/**
* Reference URI and arguments constructor.
* @param uri The URI identifying the application.
* @param name The name of the application.
* @param args The command line arguments.
*/
public AbstractConfiguredFramedSwingApplication(final URI uri, final String name, final String[] args) {
super(uri, name, args); //construct the parent class
}
/**
* Initializes the application. This method is called after construction but before application execution. This version loads the configuration information,
* if it exists.
* @throws Exception Thrown if anything goes wrong.
*/
public void initialize() throws Exception { //TODO create a flag that only allows initialization once
super.initialize(); //do the default initialization
loadConfiguration(); //load the configuration
if(getConfiguration() == null) { //if we were unable to load the configuration
final C configuration = createDefaultConfiguration(); //create a default configuration
if(configuration != null) { //if we created a default configuration
setConfiguration(configuration); //set the configuration
}
}
}
/**
* Creates a default configuration if one cannot be loaded. This version returns null
.
* @return A default configuration, or null
if the application does not need a configuration.
*/
protected C createDefaultConfiguration() {
return null; //this version doesn't create a configuration
}
/**
* Loads configuration information.
* @throws IOException if there is an error loading the configuration information.
*/
protected void loadConfiguration() throws IOException {
final IOKit configurationIOKit = getConfigurationIOKit(); //see if we can access the configuration
if(configurationIOKit != null) { //if we can load application configuration information
C configuration = null; //we'll try to get the configuration from somewhere
try {
final File configurationFile = getConfigurationFile(); //get the configuration file
if(Files.ensureExistsFromBackup(configurationFile)) { //if there is a configuration file (or a backup configuration file)
configuration = configurationIOKit.load(Files.toURI(configurationFile)); //ask the I/O kit to load the configuration file
}
} catch(SecurityException securityException) { //if we can't access the configuration file
Log.warn(securityException); //warn of the security problem
}
setConfiguration(configuration); //set the configuration to whatever we found
setModified(false); //the application has not been modified, as its configuration has just been loaded
}
}
/**
* Saves the configuration.
* @throws IOException if there is an error saving the configuration information.
*/
public void saveConfiguration() throws IOException {
final IOKit configurationIOKit = getConfigurationIOKit(); //see if we can access the configuration
final C configuration = getConfiguration(); //get the configuration
if(configurationIOKit != null && configuration != null) { //if we can save application configuration information, and there is configuration information to save
try {
final File configurationFile = getConfigurationFile(); //get the configuration file
final File configurationDirectory = configurationFile.getParentFile(); //get the directory of the file
if(!configurationDirectory.exists() || !configurationDirectory.isDirectory()) { //if the directory doesn't exist as a directory
Files.mkdirs(configurationDirectory); //create the directory
}
final File tempFile = Files.getTempFile(configurationFile); //get a temporary file to write to
final File backupFile = Files.getBackupFile(configurationFile); //get a backup file
configurationIOKit.save(configuration, Files.toURI(tempFile)); //ask the I/O kit to save the configuration to the temporary file
Files.move(tempFile, configurationFile, backupFile); //move the temp file to the normal file, creating a backup if necessary
setModified(false); //the application has not been modified, as its configuration has just been saved
} catch(SecurityException securityException) { //if we can't access the configuration file
Log.warn(securityException); //warn of the security problem
}
}
}
/**
* Determines whether the application can exit. This method may query the user. If the application has been modified, the configuration is saved if possible.
* If there is no configuration I/O kit, no action is taken. If an error occurs, the user is notified.
* @return true
if the application can exit, else false
.
*/
protected boolean canExit() {
if(!super.canExit()) { //do the default checks
return false;
}
//if there is configuration information and it has been modified
if(isModified()) { //if the application has been modified
try {
saveConfiguration(); //save the configuration
} catch(IOException ioException) { //if there is an error saving the configuration
displayError(ioException); //alert the user of the error
/*TODO fix for Swing
//ask if we can close even though we can't save the configuration information
canClose=JOptionPane.showConfirmDialog(this,
"Unable to save configuration information; are you sure you want to close?",
"Unable to save configuration", JOptionPane.YES_NO_OPTION)==JOptionPane.YES_OPTION; //TODO i18n
*/
}
}
return true; //show that we can exit
}
/** @return Whether the object been modified. */
public boolean isModified() {
return modified;
}
/**
* Sets whether the object has been modified. This is a bound property.
* @param newModified The new modification status.
*/
public void setModified(final boolean newModified) {
final boolean oldModified = modified; //get the old modified value
if(oldModified != newModified) { //if the value is really changing
modified = newModified; //update the value
//show that the modified property has changed
//TODO fix firePropertyChange(MODIFIED_PROPERTY, Boolean.valueOf(oldModified), Boolean.valueOf(newModified));
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy