From: <ste...@us...> - 2010-07-17 20:27:29
|
Revision: 1344 http://rails.svn.sourceforge.net/rails/?rev=1344&view=rev Author: stefanfrey Date: 2010-07-17 20:27:23 +0000 (Sat, 17 Jul 2010) Log Message: ----------- Update configuration management Modified Paths: -------------- trunk/18xx/LocalisedText.properties trunk/18xx/data/Properties.xml trunk/18xx/rails/ui/swing/ConfigWindow.java trunk/18xx/rails/util/Config.java trunk/18xx/rails/util/ConfigItem.java Modified: trunk/18xx/LocalisedText.properties =================================================================== --- trunk/18xx/LocalisedText.properties 2010-07-17 15:06:13 UTC (rev 1343) +++ trunk/18xx/LocalisedText.properties 2010-07-17 20:27:23 UTC (rev 1344) @@ -64,6 +64,7 @@ CLOSE_WINDOW=Do you really want to exit the game? COMPANY=Company COMPANY_DETAILS=Company details +CONFIG_CURRENT_PROFILE=Active profile = {0} (based on = {1}) CORRECT_CASH=Cash Correction CORRECT_MAP=Map Correction CURRENT=Current Modified: trunk/18xx/data/Properties.xml =================================================================== --- trunk/18xx/data/Properties.xml 2010-07-17 15:06:13 UTC (rev 1343) +++ trunk/18xx/data/Properties.xml 2010-07-17 20:27:23 UTC (rev 1344) @@ -4,7 +4,7 @@ --> <Properties> <Panel name="General"> - <Property name="locale" type="STRING"/> + <Property name="locale" type="LIST" values="en_US,de" /> </Panel> <Panel name="Colors"> <Property name="route.colour.1" type="COLOR"/> Modified: trunk/18xx/rails/ui/swing/ConfigWindow.java =================================================================== --- trunk/18xx/rails/ui/swing/ConfigWindow.java 2010-07-17 15:06:13 UTC (rev 1343) +++ trunk/18xx/rails/ui/swing/ConfigWindow.java 2010-07-17 20:27:23 UTC (rev 1344) @@ -2,29 +2,49 @@ import java.awt.Color; import java.awt.Component; +import java.awt.EventQueue; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.io.File; import java.util.Map; import java.util.List; +import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JColorChooser; +import javax.swing.JComboBox; import javax.swing.JComponent; +import javax.swing.JFileChooser; +import javax.swing.filechooser.FileFilter; import javax.swing.JFormattedTextField; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; +import javax.swing.JSpinner; import javax.swing.JTabbedPane; +import javax.swing.SpinnerListModel; +import javax.swing.SwingConstants; +import javax.swing.border.Border; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import rails.game.ConfigurationException; import rails.util.Config; import rails.util.ConfigItem; import rails.util.LocalText; +import rails.util.Util; class ConfigWindow extends JFrame { private static final long serialVersionUID = 1L; - private JTabbedPane pane; + private JPanel profilePanel; + private JTabbedPane configPane; + private JPanel buttonPanel; ConfigWindow() { // JFrame properties @@ -32,55 +52,66 @@ // setSize(400,300); // add profile panel - add(setupProfilePanel(), "North"); + profilePanel = new JPanel(); + add(profilePanel, "North"); // configSetup pane - setupConfigPane(); - add(pane, "Center"); + configPane = new JTabbedPane(); + add(configPane, "Center"); // buttons - JPanel buttonPanel = new JPanel(); - - JButton saveButton = new JButton(LocalText.getText("Save")); - saveButton.addActionListener( - new ActionListener() { - public void actionPerformed(ActionEvent arg0) { - ConfigWindow.this.saveConfig(); - } - } - ); - buttonPanel.add(saveButton); + buttonPanel = new JPanel(); + add(buttonPanel, "South"); - JButton cancelButton = new JButton(LocalText.getText("Cancel")); - cancelButton.addActionListener( - new ActionListener() { - public void actionPerformed(ActionEvent arg0) { - ConfigWindow.this.cancelConfig(); - } - } - ); - buttonPanel.add(cancelButton); - - add(buttonPanel, "South"); - + init(); + } + + private void init() { + setupProfilePanel(); + setupConfigPane(); + setupButtonPanel(); this.pack(); } - - private JComponent setupProfilePanel() { - JComponent panel = new JPanel(); - panel.setLayout(new GridLayout(0,4)); + private void setupProfilePanel() { + profilePanel.removeAll(); - // default profile + profilePanel.setLayout(new GridLayout(0,4)); + String activeProfile = Config.getActiveProfileName(); + String defaultProfile = Config.getDefaultProfileName(); + Border etched = BorderFactory.createEtchedBorder(); + Border titled = BorderFactory.createTitledBorder(etched, LocalText.getText("CONFIG_CURRENT_PROFILE", activeProfile, defaultProfile)); + profilePanel.setBorder(titled); - return panel; + JLabel userLabel = new JLabel(LocalText.getText("CONFIG_SELECT_USER")); + profilePanel.add(userLabel); + final JComboBox comboBoxUser = new JComboBox(Config.getUserProfiles().toArray()); + comboBoxUser.setSelectedItem(Config.getActiveProfileName()); + comboBoxUser.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent arg0) { + Config.changeActiveProfile((String)comboBoxUser.getSelectedItem()); + EventQueue.invokeLater(new Runnable() { + public void run() { + init(); + ConfigWindow.this.repaint(); + } + } + ); + } + } + ); + profilePanel.add(comboBoxUser); + } private void setupConfigPane() { - // create pane - pane = new JTabbedPane(); + configPane.removeAll(); + Border etched = BorderFactory.createEtchedBorder(); + Border titled = BorderFactory.createTitledBorder(etched, LocalText.getText("CONFIG_SETTINGS")); + configPane.setBorder(titled); + Map<String, List<ConfigItem>> configPanels = Config.getConfigPanels(); for (String panelName:configPanels.keySet()) { @@ -89,54 +120,153 @@ for (ConfigItem item:configPanels.get(panelName)) { defineElement(newPanel, item); } - pane.addTab(panelName, newPanel); + configPane.addTab(panelName, newPanel); } } - private void defineElement(JPanel panel, ConfigItem item) { - + private void defineElement(JPanel panel, final ConfigItem item) { + // item label panel.add(new JLabel(LocalText.getText("Config." + item.name))); - final String configValue = Config.get(item.name); + // standard components + final String configValue = item.getCurrentValue(); + + switch (item.type) { - case COLOR: { + case COLOR: final JLabel label = new JLabel(configValue); Color selectedColor; try { - selectedColor = Color.decode(configValue); - } catch (NumberFormatException e) { + selectedColor = Util.parseColour(configValue); + } catch (ConfigurationException e) { selectedColor = Color.WHITE; } label.setOpaque(true); + label.setHorizontalAlignment(SwingConstants.CENTER); label.setBackground(selectedColor); + if (Util.isDark(selectedColor)) { + label.setForeground(Color.WHITE); + } else { + label.setForeground(Color.BLACK); + } panel.add(label); - JButton button = new JButton("Color"); + JButton button = new JButton("Choose..."); final Color oldColor = selectedColor; button.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { Color selectedColor=JColorChooser.showDialog(ConfigWindow.this, "", oldColor); - label.setText(Integer.toHexString(selectedColor.getRGB()).substring(2)); + if (selectedColor == null) return; + String newValue = Integer.toHexString(selectedColor.getRGB()).substring(3); + label.setText(newValue); + item.setNewValue(newValue); label.setBackground(selectedColor); + if (Util.isDark(selectedColor)) { + label.setForeground(Color.WHITE); + } else { + label.setForeground(Color.BLACK); + } } } ); panel.add(button); break; - } + case LIST: + final JComboBox comboBox = new JComboBox(item.allowedValues.toArray()); + comboBox.setSelectedItem(configValue); + comboBox.addFocusListener(new FocusListener() { + public void focusGained(FocusEvent arg0) { + // do nothing + } + public void focusLost(FocusEvent arg0) { + item.setNewValue((String)comboBox.getSelectedItem()); + } + } + ); + panel.add(comboBox); + break; case STRING: - default: { - JFormattedTextField textField = new JFormattedTextField(); + default: // default like String + final JFormattedTextField textField = new JFormattedTextField(); textField.setValue(configValue); + textField.addFocusListener(new FocusListener() { + public void focusGained(FocusEvent arg0) { + // do nothing + } + public void focusLost(FocusEvent arg0) { + item.setNewValue(textField.getText()); + } + } + ); panel.add(textField); + break; } + } + + private void setupButtonPanel() { + buttonPanel.removeAll(); + + // save button + if (Config.isFilePathDefined()) { + JButton saveButton = new JButton(LocalText.getText("SAVE")); + saveButton.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent arg0) { + ConfigWindow.this.saveConfig(); + } + } + ); + buttonPanel.add(saveButton); } + + JButton saveAsButton = new JButton(LocalText.getText("SAVEAS")); + saveAsButton.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent arg0) { + ConfigWindow.this.saveAsConfig(); + } + } + ); + buttonPanel.add(saveAsButton); + + JButton cancelButton = new JButton(LocalText.getText("CANCEL")); + cancelButton.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent arg0) { + ConfigWindow.this.cancelConfig(); + } + } + ); + buttonPanel.add(cancelButton); + } private void saveConfig() { this.dispose(); } + private void saveAsConfig() { + JFileChooser fc = new JFileChooser(); + fc.setFileFilter( + new FileFilter() { + public boolean accept( File f ){ + return f.isDirectory() || + f.getName().toLowerCase().endsWith( ".rails_config" ); + } + public String getDescription() { + return "Rails Config"; + } + } + ); + + int state = fc.showOpenDialog( null ); + if ( state == JFileChooser.APPROVE_OPTION ) + { + File file = fc.getSelectedFile(); + Config.setActiveFilepath(file.getPath()); + } + } + private void cancelConfig() { this.dispose(); } Modified: trunk/18xx/rails/util/Config.java =================================================================== --- trunk/18xx/rails/util/Config.java 2010-07-17 15:06:13 UTC (rev 1343) +++ trunk/18xx/rails/util/Config.java 2010-07-17 20:27:23 UTC (rev 1344) @@ -8,10 +8,13 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.Set; import org.apache.log4j.Logger; @@ -31,13 +34,6 @@ protected static Logger log = Logger.getLogger(Config.class.getPackage().getName()); - - /** - * Defines possible types (Java classes used as types in ConfigItem below - */ - public static enum ConfigType { - INTEGER, FLOAT, STRING, BOOLEAN, DIRECTORY, COLOR; - } /** XML setup */ private static final String CONFIG_XML_DIR = "data"; @@ -59,12 +55,11 @@ private static final String TEST_PROFILE_SELECTION = "test"; private static final String DEFAULT_PROFILE_SELECTION = "default"; private static final String DEFAULT_PROFILE_PROPERTY = "default.profile"; - private static final String STANDARD_PROFILE_PROPERTY = "standard.profile"; + private static final String STANDARD_PROFILE_SELECTION = "user"; /** selected profile */ private static String selectedProfile; private static boolean legacyConfigFile; - private static boolean standardProfile; /** properties storage. */ private static Properties defaultProperties = new Properties(); @@ -157,20 +152,13 @@ } -// /** -// * store user config file -// */ -// public static boolean saveUserConfig() { -// } -// -// /** -// * @return if user location is defined -// */ -// public static boolean hasUserLocation() { -// return userConfigFile != null; -// } + /** + * @return if user location is defined + */ + public static boolean isFilePathDefined() { + return Util.hasValue(userProfiles.getProperty(selectedProfile)); + } - private static boolean storePropertyFile(Properties properties, String filepath) { File outFile = new File(filepath); boolean result = true; @@ -192,24 +180,46 @@ /** * change active Profile */ - public static boolean setActiveProfile(String profileName) { - boolean result = loadPropertyProfile(profileName); - if (result) selectedProfile = profileName; - return result; + public static boolean changeActiveProfile(String profileName) { + readConfigSetupXML(); + loadPropertyProfile(profileName); + selectedProfile = profileName; + return true; } + private static Map<String, String> convertProperties(Properties properties) { + Map<String, String> converted = new HashMap<String, String>(); + for (Object key:properties.keySet()) { + converted.put((String) key, (String) properties.get(key)); + } + return converted; + } + + + /** + * get all default profiles + */ + public static List<String> getDefaultProfiles() { + List<String> profiles = new ArrayList<String>(convertProperties(defaultProfiles).keySet()); + profiles.remove(DEFAULT_PROFILE_PROPERTY); + Collections.sort(profiles); + return profiles; + } + + /** + * get all user profiles + */ + public static List<String> getUserProfiles() { + List<String> profiles = new ArrayList<String>(convertProperties(userProfiles).keySet()); + Collections.sort(profiles); + return profiles; + } + /** * returns name of (active) default profile */ public static String getDefaultProfileName() { - String defaultProfileName = null; - if (isUserProfileActive()) { - defaultProfileName = userProfiles.getProperty(DEFAULT_PROFILE_PROPERTY); - if (defaultProfileName == null) { -// return - } - } - return defaultProfileName; + return userProperties.getProperty(DEFAULT_PROFILE_PROPERTY); } /** @@ -235,13 +245,6 @@ } /** - * returns true if active profile is a user profile - */ - public static boolean isUserProfileActive() { - return userProfiles.getProperty(selectedProfile) != null; - } - - /** * activates settings used for testing */ public static void setConfigTest() { @@ -290,9 +293,8 @@ } /* if nothing has selected so far, choose standardProfile */ - standardProfile = false; if (!Util.hasValue(configSelection)) { - standardProfile = true; + configSelection = STANDARD_PROFILE_SELECTION; } selectedProfile = configSelection; @@ -303,7 +305,7 @@ private static void initialLoad() { if (legacyConfigFile) { if (!propertiesLoaded) { - loadPropertyFile(defaultProperties, selectedProfile, true, false); + loadPropertyFile(defaultProperties, selectedProfile, false); propertiesLoaded = true; setSaveDirDefaults(); } @@ -311,45 +313,47 @@ } if (!profilesLoaded) { - loadPropertyFile(defaultProfiles, defaultProfilesFile, true, false); - loadPropertyFile(userProfiles, userProfilesFile, false, false); + loadPropertyFile(defaultProfiles, defaultProfilesFile, true); + loadPropertyFile(userProfiles, userProfilesFile, false); profilesLoaded = true; } - if (standardProfile) { - selectedProfile = userProfiles.getProperty(STANDARD_PROFILE_PROPERTY); - if (selectedProfile == null) { - selectedProfile = defaultProfiles.getProperty(STANDARD_PROFILE_PROPERTY); - } - if (selectedProfile == null) { - selectedProfile = DEFAULT_PROFILE_SELECTION; - } - } - /* Tell the properties loader to read this file. */ log.info("Selected profile = " + selectedProfile); if (!propertiesLoaded) { - propertiesLoaded = loadPropertyProfile(selectedProfile); + loadPropertyProfile(selectedProfile); + propertiesLoaded = true; } } - private static boolean loadPropertyProfile(String profileName) { + /** + * loads a user profile and the according default profile + * if not defined or loadable, creates a default user profile + */ + private static void loadPropertyProfile(String userProfile) { + // reset properties + userProperties = new Properties(); + defaultProperties = new Properties(); - /* first check if it is a default profile */ - String defaultConfigFile = defaultProfiles.getProperty(profileName); + // check if the profile is already defined under userProfiles + String userConfigFile = userProfiles.getProperty(userProfile); + String defaultConfigFile = null; + if (Util.hasValue(userConfigFile) && // load user profile + loadPropertyFile(userProperties, userConfigFile, false)) { + String defaultConfig = userProperties.getProperty(DEFAULT_PROFILE_PROPERTY); + if (defaultConfig != null) { + defaultConfigFile = defaultProfiles.getProperty(defaultConfig); + } + } else { + userProfiles.setProperty(userProfile, ""); + } if (defaultConfigFile == null) { - String userConfigFile = userProfiles.getProperty(profileName); - if (userConfigFile == null) return false; - loadPropertyFile(userProperties, userConfigFile, false, false); - defaultConfigFile = userProperties.getProperty(DEFAULT_PROFILE_PROPERTY); - if (defaultConfigFile == null) { - defaultConfigFile = defaultProfiles.getProperty(DEFAULT_PROFILE_SELECTION); - } + defaultConfigFile = defaultProfiles.getProperty(DEFAULT_PROFILE_SELECTION); + userProperties.setProperty(DEFAULT_PROFILE_PROPERTY, DEFAULT_PROFILE_SELECTION); } - loadPropertyFile(defaultProperties, defaultConfigFile, true, false); + loadPropertyFile(defaultProperties, defaultConfigFile, true); setSaveDirDefaults(); - return true; } /** @@ -357,11 +361,11 @@ * * @param filename - file key name as a String. * @param resource - if TRUE, loaded from jar (via classloader), otherwise from filesystem - * @param required - if TRUE, an exception will be logged if the file does - * not exist. + * @return TRUE if load was successful */ - private static void loadPropertyFile(Properties properties, String filename, boolean resource, boolean required) { + private static boolean loadPropertyFile(Properties properties, String filename, boolean resource) { + boolean result = true; try { log.info("Loading properties from file " + filename); InputStream inFile; @@ -371,15 +375,13 @@ inFile = new FileInputStream(filename); } properties.load(inFile); - } catch (FileNotFoundException FNFE) { - if (required) { - System.err.println("File not found: " + filename); - } } catch (Exception e) { System.err.println(e + " whilst loading properties file " + filename); e.printStackTrace(System.err); + result = false; } + return result; } private static void setSaveDirDefaults() { Modified: trunk/18xx/rails/util/ConfigItem.java =================================================================== --- trunk/18xx/rails/util/ConfigItem.java 2010-07-17 15:06:13 UTC (rev 1343) +++ trunk/18xx/rails/util/ConfigItem.java 2010-07-17 20:27:23 UTC (rev 1344) @@ -2,21 +2,38 @@ import java.util.Arrays; import java.util.List; + +import org.apache.log4j.Logger; + import rails.game.ConfigurationException; -import rails.util.Config.ConfigType; /** * Defines an item used for the configuration of rails * T represents the value type */ -public class ConfigItem { +public final class ConfigItem { + + protected static Logger log = + Logger.getLogger(ConfigItem.class.getPackage().getName()); + + /** + * Defines possible types (Java classes used as types in ConfigItem below + */ + public static enum ConfigType { + INTEGER, FLOAT, STRING, BOOLEAN, LIST, DIRECTORY, COLOR; + } + + // static attributes public final String name; public final ConfigType type; public final List<String> allowedValues; public final String formatMask; public final String helpText; + // dynamic attributes + private String newValue; + ConfigItem(Tag tag) throws ConfigurationException { // check name and type (required) String name = tag.getAttributeAsString("name"); @@ -25,29 +42,68 @@ } else { throw new ConfigurationException("Missing name for configuration item"); } - String type = tag.getAttributeAsString("type"); - if (Util.hasValue(type)) { - this.type = ConfigType.valueOf(type); - } else { - throw new ConfigurationException("Missing or invalid type for configuration item"); - } // optional: list of allowed values String valueString = tag.getAttributeAsString("values"); if (Util.hasValue(valueString)) { allowedValues = Arrays.asList(valueString.split(",")); + this.type = ConfigType.LIST; } else { allowedValues = null; + String type = tag.getAttributeAsString("type"); + if (Util.hasValue(type)) { + try { + this.type = ConfigType.valueOf(type.toUpperCase()); + } catch (Exception e) { + throw new ConfigurationException("Missing or invalid type for configuration item"); + } + } else { + throw new ConfigurationException("Missing or invalid type for configuration item"); + } + if (this.type == ConfigType.LIST) { + throw new ConfigurationException("No values defined for LIST config item"); + } } + // optional: formatMask formatMask = tag.getAttributeAsString("formatMask"); // optional: helpText helpText = tag.getAttributeAsString("formatMask"); + + newValue = null; } + public boolean hasNewValue() { + return (newValue != null); + } + + public String getNewValue() { + return newValue; + } + + public void setNewValue(String newValue) { + if (newValue.equals(getConfigValue())) { + this.newValue = null; + } else { + this.newValue = newValue; + } + log.debug("ConfigItem " + name + " set to new value " + this.newValue); + } + + public String getCurrentValue() { + if (newValue != null) return newValue; + return getConfigValue(); + } + + public String getConfigValue() { + return Config.get(this.name); + } + public String toString() { StringBuffer s = new StringBuffer(); s.append("Configuration Item: name = " + name + ", type = " + type); + s.append(", config value = " + getConfigValue()); + s.append(", current value = " + getCurrentValue()); if (allowedValues != null) { s.append(", allowedValues = " + allowedValues); } @@ -57,6 +113,7 @@ if (helpText != null) { s.append(", helpText = " + helpText); } + return s.toString(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |