[Schmitzm-commits] r1759 - in trunk/schmitzm-core/src/main/java/de/schmitzm: lang swing

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Wed Oct 19 15:32:57 CEST 2011


Author: mojays
Date: 2011-10-19 15:32:56 +0200 (Wed, 19 Oct 2011)
New Revision: 1759

Added:
   trunk/schmitzm-core/src/main/java/de/schmitzm/lang/ApplicationProps.java
   trunk/schmitzm-core/src/main/java/de/schmitzm/swing/ApplicationFrame.java
Modified:
   trunk/schmitzm-core/src/main/java/de/schmitzm/swing/SwingUtil.java
Log:
Some new utility methods moved from WIME to SwingUtil.
New frame super class ApplicationFrame.
New super class ApplicationProps.

Added: trunk/schmitzm-core/src/main/java/de/schmitzm/lang/ApplicationProps.java
===================================================================
--- trunk/schmitzm-core/src/main/java/de/schmitzm/lang/ApplicationProps.java	2011-10-15 18:13:01 UTC (rev 1758)
+++ trunk/schmitzm-core/src/main/java/de/schmitzm/lang/ApplicationProps.java	2011-10-19 13:32:56 UTC (rev 1759)
@@ -0,0 +1,349 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Martin O. J. Schmitz.
+ * 
+ * This file is part of the SCHMITZM library - a collection of utility 
+ * classes based on Java 1.6, focusing (not only) on Java Swing 
+ * and the Geotools library.
+ * 
+ * The SCHMITZM project is hosted at:
+ * http://wald.intevation.org/projects/schmitzm/
+ * 
+ * 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 Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License (license.txt)
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ * or try this link: http://www.gnu.org/licenses/lgpl.html
+ * 
+ * Contributors:
+ *     Martin O. J. Schmitz - initial API and implementation
+ *     Stefan A. Tzeggai - additional utility classes
+ ******************************************************************************/
+
+package de.schmitzm.lang;
+
+import java.awt.Component;
+import java.awt.Window;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Properties;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.log4j.Logger;
+
+import de.schmitzm.swing.ExceptionDialog;
+import de.schmitzm.temp.BaseTypeUtil;
+
+/**
+ * General implementation for application properties.
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+ */
+public abstract class ApplicationProps<KEYS> {
+  private static final String INTERNER_FEHLER_DIE_INTERNE_EINSTELLUNGSDATEI_KONNTE_NICHT_GEFUNDEN_WERDEN = "Interner Fehler: Die interne Einstellungsdatei konnte nicht gefunden werden.";
+  private static final Logger LOGGER = Logger.getLogger(ApplicationProps.class);
+
+  /** TODO: Rethink where this "default" shall be used. */
+  public static final String DEFAULT_CHARSET_NAME = "UTF-8";
+
+  /**
+   * This stores the properties
+   */
+  private final Properties properties = new Properties();
+
+  private boolean autoSave;
+  private FileOutputStream FOS = null;
+  private boolean haveToCloseFOS = false;
+  private File propertiesFile = null;
+  private Component owner;
+  
+  /**
+   * Creates a new application properties instance.
+   * @param load if <code>true</code> {@link #load()} is
+   *             immediately called
+   */
+  public ApplicationProps(boolean load, boolean autoSave) {
+    setAutoSave(autoSave);
+    if ( load )
+      load();
+  }
+  
+  @Override
+  protected void finalize() throws Throwable {
+      synchronized (FOS) {
+          if (haveToCloseFOS) {
+              FOS.close();
+              haveToCloseFOS = false;
+          }
+      }
+  }
+
+  /**
+   * Returns a GUI-owner for error messages. 
+   */
+  public Component getOwner() {
+    return owner;
+  }
+  
+  /**
+   * Sets a GUI-owner for error messages. 
+   */
+  public void setOwner(Window owner) {
+    this.owner = owner;
+  }
+  
+  /**
+   * Returns whether the parameter file is automatically saved
+   * after each set-call.
+   */
+  public boolean getAutoSave() {
+    return autoSave;
+  }
+
+  /**
+   * Sets whether the parameter file is automatically saved
+   * after each set-call.
+   */
+  public void setAutoSave(boolean autoSave) {
+    this.autoSave = autoSave;
+  }
+
+  //***************************************************
+  //************* GETTER ******************************
+  //***************************************************
+
+  public <T> T get(KEYS key, Class<T> destType) {
+    Object value = properties.get(key.toString());
+    if ( value == null )
+      return null;
+    if ( destType != null && destType.isInstance(value) )
+      return (T)value;
+    try {
+      return BaseTypeUtil.convertFromString(value.toString(), destType);
+    } catch( Exception err ) {
+      LOGGER.warn(
+          "The property value saved for " + key
+                  + " can't be converted to " + LangUtil.getSimpleClassName(destType)
+                  + " Returning default value.");
+      return null;
+    }
+  }
+  
+  public <T> T get(KEYS key, Class<T> destType, T defaultValue) {
+    if ( destType == null && defaultValue != null)
+      destType = (Class<T>)defaultValue.getClass();
+    T value = get(key,destType);
+    if ( value == null )
+      return defaultValue;
+    return value;
+  }
+
+  public <T> T get(KEYS key, T defaultValue) {
+    return get(key,null,defaultValue);
+  }
+
+  public Boolean getBool(KEYS key, Boolean... defaultValue) {
+    if ( defaultValue.length == 0 )
+      return get(key,Boolean.class);
+    return get(key,Boolean.class,defaultValue[0]);
+  }
+
+  public Integer getInt(KEYS key, Integer... defaultValue) {
+    if ( defaultValue.length == 0 )
+      return get(key,Integer.class);
+    return get(key,Integer.class,defaultValue[0]);
+  }
+
+  public Double getDouble(KEYS key, Double... defaultValue) {
+    if ( defaultValue.length == 0 )
+      return get(key,Double.class);
+    return get(key,Double.class,defaultValue[0]);
+  }
+
+  public String getString(KEYS key, String... defaultValue) {
+    if ( defaultValue.length == 0 )
+      return get(key,String.class);
+    return get(key,String.class,defaultValue[0]);
+  }
+  
+  //***************************************************
+  //************* SETTER ******************************
+  //***************************************************
+  /**
+   * Set the value in the underlying {@link Properties}
+   * and store it.
+   */
+  public void set(KEYS key, Object value) {
+    properties.setProperty(key.toString(), value.toString());
+    if ( getAutoSave() )
+      store();
+  }
+
+  /////////////////////////////////////////////////////
+  ///////////////  Property storage  //////////////////
+  /////////////////////////////////////////////////////
+  /**
+   * Returns a default properties file copied to
+   * user home if no such file already exists.
+   */
+  public abstract URL getDefaultPropertiesFile();
+
+  /**
+   * Returns the name of the folder in the user home,
+   * where the properties file is stored.
+   */
+  public abstract String getPropertiesFolderName();
+
+  /**
+   * Returns the name of the file in the user home,
+   * where the properties are stored in.
+   */
+  public abstract String getPropertiesFilename();
+
+  /**
+   * Returns a description which is added to the top of
+   * the properties file.
+   */
+  public abstract String getPropertiesFileDescription();
+
+  /**
+   * Returns the directory the user properties file is
+   * stored in. 
+   */
+  public File getApplicationPropertiesDir() {
+    File applicationPropertiesDirectory = new File(new File(
+        System.getProperty("user.home")), getPropertiesFolderName());
+    if (!applicationPropertiesDirectory.exists())
+      applicationPropertiesDirectory.mkdirs();
+    return applicationPropertiesDirectory;
+  }
+
+  /**
+   * Returns the user properties file. 
+   */
+  protected File getPropertiesFile() {
+    if (propertiesFile == null) {
+      File applicationPropertiesDirectory = getApplicationPropertiesDir();
+      propertiesFile = new File(applicationPropertiesDirectory,
+          getPropertiesFilename());
+      
+      if (!propertiesFile.exists()) {
+        resetProperties();
+      } else {
+        FileInputStream inStream = null;
+        try {
+          inStream = new FileInputStream(getPropertiesFile());
+          properties.load(inStream);
+        } catch (Exception e) {
+          ExceptionDialog.show(null, e);
+        } finally {
+          if (inStream != null)
+            try {
+              inStream.close();
+            } catch (IOException ioe) {
+              LOGGER.error("Unable to close FileInputStream of "
+                  + getPropertiesFile(), ioe);
+            }
+        }
+      }
+    }
+    return propertiesFile;
+  }
+  
+  /**
+   * Loads the properties from the file.
+   * @see #getPropertiesFile()
+   */
+  public void load() {
+    /**
+     * It is not a problem if the propertiesFile for the can't
+     * be loaded
+     */
+    try {
+        properties.load(new FileInputStream(getPropertiesFile()));
+    } catch (FileNotFoundException e) {
+    } catch (IOException e) {
+        LOGGER.error(e);
+    }
+  }
+
+  /**
+   * Deletes the .properties in the ApplicationPreferences directory and
+   * creates a default .properties file
+   * 
+   * @param guiOwner
+   *            If not <code>null</code> a JDialog message will inform the
+   *            user.
+   * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Tzeggai</a>
+   */
+  public void resetProperties() {
+      // Create the new one
+      // e.printStackTrace();
+      LOGGER.info("Resetting " + getPropertiesFile().getAbsolutePath());
+      // If we don't have a .properties file, we copy the one from the jar
+      URL inJar = null;
+      try {
+          inJar = getDefaultPropertiesFile();
+          // LOGGER.debug("inJar = " + inJar);
+          if (inJar == null)
+              throw new RuntimeException(
+                      INTERNER_FEHLER_DIE_INTERNE_EINSTELLUNGSDATEI_KONNTE_NICHT_GEFUNDEN_WERDEN);
+          FileUtils.copyURLToFile(inJar, getPropertiesFile());
+          /**
+           * After creating the new default file, we may not forget to read it
+           * ;-)
+           */
+          properties.load(new FileInputStream(getPropertiesFile()));
+      } catch (final IOException e1) {
+          if (getOwner() != null) {
+              ExceptionDialog.show(getOwner(), e1);
+          } else {
+              LOGGER.error(
+                      INTERNER_FEHLER_DIE_INTERNE_EINSTELLUNGSDATEI_KONNTE_NICHT_GEFUNDEN_WERDEN,
+                      e1);
+          }
+      }
+      // Create the new one
+      // LOGGER.error(e);
+      LOGGER.info("Resetting " + getPropertiesFile().getAbsolutePath());
+      // Delete the old one
+      getPropertiesFile().delete();
+      store();
+  }
+
+
+  /**
+   * Save the changes to the .properties file
+   */
+  public void store() {
+      // LOGGER.debug("STORE AS PROPS");
+      try {
+          FOS = new FileOutputStream(getPropertiesFile());
+          haveToCloseFOS = true;
+
+          properties.store(FOS,getPropertiesFileDescription());
+      } catch (IOException e) {
+          LOGGER.error("Can't write to " + getPropertiesFile().toString(), e);
+      } finally {
+          if (haveToCloseFOS)
+              try {
+                  FOS.close();
+                  haveToCloseFOS = false;
+              } catch (IOException e) {
+                  LOGGER.error("Can't close FOS!", e);
+                  ExceptionDialog.show(getOwner(), e);
+              }
+      }
+  }
+}

Added: trunk/schmitzm-core/src/main/java/de/schmitzm/swing/ApplicationFrame.java
===================================================================
--- trunk/schmitzm-core/src/main/java/de/schmitzm/swing/ApplicationFrame.java	2011-10-15 18:13:01 UTC (rev 1758)
+++ trunk/schmitzm-core/src/main/java/de/schmitzm/swing/ApplicationFrame.java	2011-10-19 13:32:56 UTC (rev 1759)
@@ -0,0 +1,135 @@
+package de.schmitzm.swing;
+
+import java.awt.AWTEvent;
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.Action;
+import javax.swing.BorderFactory;
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JMenuBar;
+
+import de.schmitzm.swing.menu.ToolBarsPanel;
+
+/**
+ * Super class for a main application frame with {@link BorderLayout},
+ * which contains
+ * <ul>
+ *   <li>an (empty) {@link JMenuBar}</li>
+ *   <li>an (empty) {@link #toolBarsPanel} at {@link BorderLayout#NORTH}</li>
+ *   <li>a status label at {@link BorderLayout#SOUTH}</li>
+ * </ul> 
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+ *
+ */
+public abstract class ApplicationFrame extends JFrame {
+  /** Holds the main content pane. */
+  protected Container contentPane = null;
+  /** Holds a panel, which can contain several tool bars.
+   *  @see BorderLayout#NORTH */
+  protected ToolBarsPanel toolBarsPanel = null;
+  /** Global action listener, calling {@link #performAction(ActionEvent)}
+   *  which can be used for the frame actions. */
+  protected ActionListener menuActionListener;
+  /** Holds the status bar on the bottom of the frame.
+   *  @see BorderLayout#SOUTH */
+  protected JLabel statusBar = null;
+
+  /**
+   * Creates a new frame.
+   */
+  public ApplicationFrame() {
+    this(null);
+  }
+
+  /**
+   * Creates a new frame.
+   * @param title frame title
+   */
+  public ApplicationFrame(String title) {
+    this(title,true);
+  }
+  
+  /**
+   * Creates a new frame.
+   * @param title frame title
+   * @param pack indicates whether {@link #pack()} is called
+   */
+  protected ApplicationFrame(String title, boolean pack) {
+    super(title);
+    contentPane = getContentPane();
+    contentPane.setLayout(new BorderLayout());
+
+    setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
+    enableEvents(AWTEvent.WINDOW_EVENT_MASK);
+
+    JPanel statusContainer = new JPanel(new BorderLayout());
+    statusContainer.setBorder(BorderFactory.createLoweredBevelBorder());
+    this.statusBar = new JLabel(" ");
+    this.statusBar.setBorder(BorderFactory.createEmptyBorder(2, 5, 2, 5));
+    statusContainer.add(statusBar, BorderLayout.CENTER);
+    contentPane.add(statusContainer, BorderLayout.SOUTH);
+    
+    this.toolBarsPanel = new ToolBarsPanel();
+    contentPane.add(toolBarsPanel, BorderLayout.NORTH);
+
+    this.setJMenuBar( new JMenuBar() );
+    this.menuActionListener = new ActionListener() {
+        public void actionPerformed(ActionEvent e) {
+            performAction(e);
+        }
+    };
+
+    initActions();
+    updateActions();
+    
+    if( pack )
+      pack();
+  }
+  
+  /**
+   * Creates an {@link Action} which uses the global {@link #menuActionListener}.
+   * @param title action title
+   * @param commandID command id
+   * @param desc action description for tooltip
+   * @param icon icon for buttons or menues
+   */
+  protected Action createAction(String title, String commandID, String desc, Icon icon) {
+    return SwingUtil.createAction(title, this.menuActionListener, commandID, desc, icon);
+  }
+
+  /**
+   * Creates an {@link Action} which uses the global {@link #menuActionListener}.
+   * @param title action title
+   * @param commandID command id
+   * @param desc action description for tooltip
+   * @param iconName name of icon file for buttons or menues (icon must be located
+   *        under {@code 'resource/icons/small/..'} in {@link SwingUtil} resource path) 
+   */
+  protected Action createAction(String title, String commandID, String desc, String iconName) {
+    String iconPath = "resource/icons/small/"+iconName;
+    ImageIcon icon = SwingUtil.createImageIconFromResourcePath(iconPath, null);
+    return SwingUtil.createAction(title, this.menuActionListener, commandID, desc, icon);
+  }
+
+  /**
+   * Initializes the actions, menu entries and tool bars.
+   */
+  protected abstract void initActions();
+  
+  /**
+   * Can be called to update the enable state of the
+   * actions.
+   */
+  public abstract void updateActions();
+  
+  /**
+   * Called by the {@link #menuActionListener}.
+   */
+  protected abstract void performAction(ActionEvent e);
+}

Modified: trunk/schmitzm-core/src/main/java/de/schmitzm/swing/SwingUtil.java
===================================================================
--- trunk/schmitzm-core/src/main/java/de/schmitzm/swing/SwingUtil.java	2011-10-15 18:13:01 UTC (rev 1758)
+++ trunk/schmitzm-core/src/main/java/de/schmitzm/swing/SwingUtil.java	2011-10-19 13:32:56 UTC (rev 1759)
@@ -47,6 +47,7 @@
 import java.awt.Toolkit;
 import java.awt.Window;
 import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
 import java.awt.event.MouseWheelListener;
 import java.awt.image.BufferedImage;
 import java.io.File;
@@ -68,10 +69,13 @@
 import javax.imageio.ImageIO;
 import javax.swing.AbstractAction;
 import javax.swing.AbstractButton;
+import javax.swing.Action;
 import javax.swing.CellEditor;
 import javax.swing.DefaultCellEditor;
+import javax.swing.Icon;
 import javax.swing.ImageIcon;
 import javax.swing.JCheckBox;
+import javax.swing.JCheckBoxMenuItem;
 import javax.swing.JComboBox;
 import javax.swing.JDialog;
 import javax.swing.JFormattedTextField;
@@ -86,6 +90,8 @@
 import javax.swing.JScrollPane;
 import javax.swing.JTable;
 import javax.swing.JTextField;
+import javax.swing.JToggleButton;
+import javax.swing.JToolBar;
 import javax.swing.JTree;
 import javax.swing.JViewport;
 import javax.swing.SwingUtilities;
@@ -1625,7 +1631,72 @@
 		return DUMMY_LABEL.getBackground();
 	}
 
-	/**
+    /**
+     * Creates a menu item.
+     * 
+     * @param title
+     *            title for the menu item
+     * @param actionListener
+     *            listener to perform the action
+     * @param commandID
+     *            identifies the action in the action listener (if the listener
+     *            is used for multiple actions)
+     * @param desc
+     *            optional (tooltip) description
+     * @param icon
+     *            optional icon
+     */
+    public static Action createAction(String title,
+            final ActionListener actionListener, String commandID, String desc,
+            Icon icon) {
+        AbstractAction action = new AbstractAction(title) {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                actionListener.actionPerformed(e);
+            }
+        };
+        action.putValue(Action.ACTION_COMMAND_KEY, commandID);
+        if (desc != null) {
+            action.putValue(Action.LONG_DESCRIPTION, desc);
+            action.putValue(Action.SHORT_DESCRIPTION, desc);
+        }
+        if (icon != null)
+            action.putValue(Action.SMALL_ICON, icon);
+        return action;
+    }
+
+    /**
+     * Creates a checkbox menu item for an action.
+     */
+    public static JCheckBoxMenuItem createCheckboxMenuItem(Action action, boolean selected) {
+      action.putValue(AbstractAction.SELECTED_KEY, selected);
+      JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem(action);
+      return menuItem;
+    }
+
+    /**
+     * Creates a {@link JToggleButton} for the use in a {@link JToolBar}.
+     * Regardless of the {@linkplain AbstractAction#NAME action name},
+     * the button will only show the icon.
+     */
+    public static JToggleButton createToggleToolbarButton(Action action, boolean selected) {
+      action.putValue(AbstractAction.SELECTED_KEY, selected);
+      return createToggleToolbarButton(action);
+    }
+
+    /**
+     * Creates a {@link JToggleButton} for the use in a {@link JToolBar}.
+     * Regardless of the {@linkplain AbstractAction#NAME action name},
+     * the button will only show the icon.
+     */
+    public static JToggleButton createToggleToolbarButton(Action action) {
+      JToggleButton button = new JToggleButton(action);
+      if ( button.getIcon() != null )
+        button.setText(null);
+      return button;
+    }
+
+    /**
 	 * Create a {@link JMenu} that allows to switch the Log-Level of the root
 	 * logger.
 	 */



More information about the Schmitzm-commits mailing list