[Schmitzm-commits] r2381 - in trunk: schmitzm-core/src/main/java/de/schmitzm/lang schmitzm-core/src/main/java/de/schmitzm/swing schmitzm-core/src/main/java/de/schmitzm/swing/input schmitzm-gt/src/main/java/de/schmitzm/geotools/gui

scm-commit at wald.intevation.org scm-commit at wald.intevation.org
Sat Aug 3 14:13:20 CEST 2013


Author: mojays
Date: 2013-08-03 14:13:20 +0200 (Sat, 03 Aug 2013)
New Revision: 2381

Modified:
   trunk/schmitzm-core/src/main/java/de/schmitzm/lang/LangUtil.java
   trunk/schmitzm-core/src/main/java/de/schmitzm/swing/ToolTipComboBoxRenderer.java
   trunk/schmitzm-core/src/main/java/de/schmitzm/swing/input/SelectionInputOption.java
   trunk/schmitzm-gt/src/main/java/de/schmitzm/geotools/gui/CRSSelectionDialog.java
Log:
LangUtil.createGenericsArray(.): workaround method to create generics array without explicit cast
SelectionInputOption: parameterized with generics type <E>
ToolTipComboBoxRenderer: pipe an existing renderer


Modified: trunk/schmitzm-core/src/main/java/de/schmitzm/lang/LangUtil.java
===================================================================
--- trunk/schmitzm-core/src/main/java/de/schmitzm/lang/LangUtil.java	2013-08-01 17:49:36 UTC (rev 2380)
+++ trunk/schmitzm-core/src/main/java/de/schmitzm/lang/LangUtil.java	2013-08-03 12:13:20 UTC (rev 2381)
@@ -77,6 +77,7 @@
 import org.apache.log4j.PatternLayout;
 
 import de.schmitzm.io.IOUtil;
+import de.schmitzm.swing.input.SelectionInputOption;
 import de.schmitzm.temp.BaseTypeUtil;
 
 /**
@@ -1529,6 +1530,50 @@
 			newArray[source.length + i] = newElem[i];
 		return newArray;
 	}
+	
+	/**
+	 * This is a workaround method, because it is NOT possible in Java to
+	 * instantiate a generics array (like {@code E[] array = new E[10]}).
+	 * Sometimes it works to simply cast a new {@link Object Object[]} array (like
+	 * {@code E[] array = (E[])new Object[10]}). But this only works inside
+	 * the class where {@code E} is clearly bounded. When assigning
+	 * {@code array = (E[])new Object[10]} to an array field (of type {@code E[]})
+	 * which is decared in super class, an {@link ClassCastException} occurs.<br>
+	 * Example in SCHMITZM-HIBERNATE:<br>
+	 * Method {@code performSelectionUpdate()} in {@code SelectionInputOption.Combo<E>}:<br>
+	 * <code>
+	 *   E[] newSelObj = (E[])new Object[this.selectionObject.length+1];<br>
+	 *   ...<br>
+	 *   this.selectionObject = newSelObj;<br>
+	 * </code>
+	 * works without Exception, while the overriden methdod in
+	 * {@code BasicTypeInputOption.Combo<E> extends SelectionInputOption.Combo<E>} results
+	 * in Exception:<br>
+	 * <code>
+	 *   selectionObject = (E[])new Object[basicTypeComboBox.getItemCount()];<br>
+	 * </code>
+	 * <br>
+	 * <br>
+	 * Do not ask why, but using this small method, avoids the problem:<br>
+     * <code>
+     *   selectionObject = LangUtil.createGenericsArray(basicTypeComboBox.getItemCount());<br>
+     * </code>
+	 * No compiler message (only warning), no runtime {@link ClassCastException}.<br>
+	 * Note:<br>
+     * <code>
+     *   selectionObject = (E[])LangUtil.createGenericsArray(basicTypeComboBox.getItemCount());<br>
+     * </code>
+     * will still result in exception!!
+	 * 
+	 * @param length length of array
+	 * @param array only a dummy! not allowed to be specified!
+	 */
+    public static <E> E[] createGenericsArray(int length, E... array) {
+        if ( array.length > 0 )
+          throw new IllegalArgumentException("Array parameter is not allowed to specified!");
+        return Arrays.copyOf(array, length);
+    }
+  
 
 	/**
 	 * Liefert die Klassen-Namen zu einem Array von Klassen.

Modified: trunk/schmitzm-core/src/main/java/de/schmitzm/swing/ToolTipComboBoxRenderer.java
===================================================================
--- trunk/schmitzm-core/src/main/java/de/schmitzm/swing/ToolTipComboBoxRenderer.java	2013-08-01 17:49:36 UTC (rev 2380)
+++ trunk/schmitzm-core/src/main/java/de/schmitzm/swing/ToolTipComboBoxRenderer.java	2013-08-03 12:13:20 UTC (rev 2381)
@@ -32,33 +32,68 @@
 import java.awt.Component;
 import java.util.Map;
 
+import javax.swing.DefaultListCellRenderer;
 import javax.swing.JList;
+import javax.swing.ListCellRenderer;
 import javax.swing.plaf.basic.BasicComboBoxRenderer;
 
 /**
  * Extends the {@link BasicComboBoxRenderer} with tooltip functionality.
  * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
  */
-public class ToolTipComboBoxRenderer extends BasicComboBoxRenderer {
+public class ToolTipComboBoxRenderer implements ListCellRenderer<Object> {
+  /** Holds the renderer which is extended by tooltip functionality */
+  protected ListCellRenderer pipedRenderer = null;
   /** Holds the tooltips for each list value */
   protected Map<Object,String> tooltips = null;
   
   /**
    * Creates a new renderer.
    * @param tooltips map with tooltip for each list value (can be {@code null})
+   * @param pipedRenderer used to render the items; created component is extended by tooltip
+   *                      functionality (if {@code null}, {@link DefaultListCellRenderer} is used) 
    */
-  public ToolTipComboBoxRenderer(Map<Object,String> tooltips) {
+  public ToolTipComboBoxRenderer(ListCellRenderer pipedRenderer, Map<Object,String> tooltips) {
     super();
     this.tooltips = tooltips;
+    setPipedRenderer(pipedRenderer);
   }
+
+  /**
+   * Creates a new renderer. Def
+   * @param tooltips map with tooltip for each list value (can be {@code null})
+   */
+  public ToolTipComboBoxRenderer(Map<Object,String> tooltips) {
+    this(null,tooltips);
+  }
   
   /**
+   * Sets the renderer to render the list item. The rendering components are extended with
+   * tooltip functionality.
+   * @param pipedRenderer renderer for the list items (if {@code null}, {@link DefaultListCellRenderer}
+   *                      is used)
+   */
+  public void setPipedRenderer(ListCellRenderer pipedRenderer) {
+    if ( pipedRenderer == null )
+      pipedRenderer = new DefaultListCellRenderer();
+    this.pipedRenderer = pipedRenderer;
+  }
+  
+  /**
+   * Returns the renderer to render the list item. The rendering components are extended with
+   * tooltip functionality.
+   */
+  public ListCellRenderer getPipedRenderer() {
+    return this.pipedRenderer;
+  }
+
+  /**
    * After calling the super method, the tooltip is set (if value is selected).
    */
   public Component getListCellRendererComponent(JList list, Object value,
       int index, boolean isSelected, boolean cellHasFocus) {
     // Create component
-    Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
+    Component c = pipedRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
     // set tooltip, if item is selected
     if ( tooltips != null && isSelected && index >= 0 ) {
       String tooltip = tooltips.get(value);

Modified: trunk/schmitzm-core/src/main/java/de/schmitzm/swing/input/SelectionInputOption.java
===================================================================
--- trunk/schmitzm-core/src/main/java/de/schmitzm/swing/input/SelectionInputOption.java	2013-08-01 17:49:36 UTC (rev 2380)
+++ trunk/schmitzm-core/src/main/java/de/schmitzm/swing/input/SelectionInputOption.java	2013-08-03 12:13:20 UTC (rev 2381)
@@ -148,7 +148,7 @@
    *            <code>value</code> und <code>display</code> unterscheiden
    */
   protected SelectionInputOption(String label, boolean inputNeeded, E[] value, Object[] display) {
-    this(label,inputNeeded,value,value.length > 0 ? 0 : -1, display);
+    this(label,inputNeeded,value,value != null && value.length > 0 ? 0 : -1, display);
   }
 
   /**
@@ -323,7 +323,7 @@
    * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
    * @version 1.0
    */
-  public static class Combo<E> extends SelectionInputOption {
+  public static class Combo<E> extends SelectionInputOption<E> {
     /**
      * Erzeugt eine neue Eingabe-Option. {@link #init(String, boolean, boolean)}
      * muss nachtraeglich aufgerufen werden!
@@ -401,7 +401,7 @@
      * @param inputNeeded gibt an, ob eine Eingabe erforderlich ist
      */
     public Combo(String label, boolean inputNeeded) {
-      super(label,inputNeeded,new Object[0],new Object[0]);
+      super(label,inputNeeded,null,null);
     }
 
     /**
@@ -411,10 +411,10 @@
       JComboBox comboBox = new JComboBox();
       // Change Listener
       comboBox.addItemListener( new ItemListener() {
-        Object oldValue = null;
+        E oldValue = null;
         public void itemStateChanged(ItemEvent e) {
           if ( e.getStateChange() == ItemEvent.SELECTED ) {
-            Object newValue = getValue();
+            E newValue = getValue();
             if ( oldValue != newValue )
               fireOptionChanged(oldValue,newValue);
             oldValue = newValue;
@@ -431,7 +431,7 @@
       // wenn eine Leereingabe erlaubt ist, wird am Anfang ein
       // null-Eintrag eingefuegt
       if ( !inputNeeded() ) {
-        Object[] newSelObj = new Object[this.selectionObject.length+1];
+        E[]      newSelObj = (E[])new Object[this.selectionObject.length+1];
         Object[] newDisObj = new Object[this.displayObject.length+1];
 
         newSelObj[0] = null;
@@ -464,9 +464,9 @@
      * @param idx Listen-Index (-1 um eine Leer-Auswahl zu erzeugen)
      */
     public void setSelectedIndex(int idx) {
-      Object oldValue = getValue();
+      E oldValue = getValue();
       ((JComboBox)inpComp).setSelectedIndex(idx);
-      Object newValue = getValue();
+      E newValue = getValue();
       if ( oldValue != newValue || oldValue!=null && !oldValue.equals( getValue() ) )
         fireOptionChanged(oldValue,newValue);
     }
@@ -478,11 +478,11 @@
    * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
    * @version 1.0
    */
-  public static class Radio<E> extends SelectionInputOption {
+  public static class Radio<E> extends SelectionInputOption<E> {
     /** Gruppe, in der die RadioButton agieren. */
     protected ButtonGroup buttonGroup;
     /** Speichert die letzte Auswahl. */
-    protected Object lastSelection = null;
+    protected E lastSelection = null;
     /** Liste der Buttons. */
     protected Vector<JRadioButton> buttonList;
 
@@ -577,7 +577,7 @@
      * @param inputNeeded gibt an, ob eine Eingabe erforderlich ist
      */
     public Radio(String label, boolean inputNeeded) {
-      super(label,inputNeeded,new Object[0],new Object[0]);
+      super(label,inputNeeded,null,null);
     }
 
     /**
@@ -588,7 +588,7 @@
     protected JPanel createInputComponent() {
       actionListener = new ActionListener() {
         public void actionPerformed(ActionEvent e) {
-          Object newValue = getValue();
+          E newValue = getValue();
           if ( lastSelection != newValue )
             fireOptionChanged(lastSelection,newValue);
           lastSelection = newValue;
@@ -645,12 +645,12 @@
     public void setSelectedIndex(int idx) {
 // Event wird - glaube ich - bereits durch den ActionListener
 // des RadioButtons realisiert! >> DEM IST NICHT SO!
-      Object oldValue = getValue();
+      E oldValue = getValue();
       if ( idx == -1 || idx >= buttonList.size() )
         buttonGroup.setUnselected();
       else
         buttonList.elementAt(idx).setSelected(true);
-      Object newValue = getValue();
+      E newValue = getValue();
       if ( oldValue != newValue || oldValue!=null && !oldValue.equals( getValue() ) )
         fireOptionChanged(oldValue,newValue);
       lastSelection = newValue;
@@ -663,7 +663,7 @@
    * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
    * @version 1.0
    */
-  public static class List<E> extends SelectionInputOption {
+  public static class List<E> extends SelectionInputOption<E> {
     /**
      * Erzeugt eine neue Eingabe-Option. {@link #init(String, boolean, boolean)}
      * muss nachtraeglich aufgerufen werden!
@@ -759,7 +759,7 @@
      * @param inputNeeded gibt an, ob eine Eingabe erforderlich ist
      */
     public List(String label, boolean inputNeeded) {
-      this(label,inputNeeded,(E[])new Object[0],new Object[0]);
+      this(label,inputNeeded,null,null);
     }
 
     /**
@@ -792,13 +792,13 @@
       list.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
       // Change Listener
       list.getSelectionModel().addListSelectionListener( new ListSelectionListener() {
-        Object oldValue = null;
+        E oldValue = null;
         
         @Override
         public void valueChanged(ListSelectionEvent e) {
           if ( e.getValueIsAdjusting() )
             return;
-          Object newValue = getValue();
+          E newValue = getValue();
           if ( oldValue != newValue )
             fireOptionChanged(oldValue,newValue);
           oldValue = newValue;
@@ -823,7 +823,7 @@
       // wenn eine Leereingabe erlaubt ist, wird am Anfang ein
       // null-Eintrag eingefuegt
       if ( !inputNeeded() ) {
-        Object[] newSelObj = new Object[this.selectionObject.length+1];
+        E[]      newSelObj = (E[])new Object[this.selectionObject.length+1];
         Object[] newDisObj = new Object[this.displayObject.length+1];
 
         newSelObj[0] = null;
@@ -850,9 +850,9 @@
      * @param idx Listen-Index (-1 um eine Leer-Auswahl zu erzeugen)
      */
     public void setSelectedIndex(int idx) {
-      Object oldValue = getValue();
+      E oldValue = getValue();
       ((JList)inpComp).setSelectedIndex(idx);
-      Object newValue = getValue();
+      E newValue = getValue();
       if ( oldValue != newValue || oldValue!=null && !oldValue.equals( getValue() ) )
         fireOptionChanged(oldValue,newValue);
     }

Modified: trunk/schmitzm-gt/src/main/java/de/schmitzm/geotools/gui/CRSSelectionDialog.java
===================================================================
--- trunk/schmitzm-gt/src/main/java/de/schmitzm/geotools/gui/CRSSelectionDialog.java	2013-08-01 17:49:36 UTC (rev 2380)
+++ trunk/schmitzm-gt/src/main/java/de/schmitzm/geotools/gui/CRSSelectionDialog.java	2013-08-03 12:13:20 UTC (rev 2381)
@@ -183,7 +183,7 @@
 		this.authoritySelect = new SelectionInputOption.Combo<String>(null,
 				true);
 		this.authoritySelect.setSelectionObjects(predefinedCRS.keySet()
-				.toArray(), null);
+				.toArray(new String[0]), null);
 		this.authoritySelect.setSelectedItem(0);
 		SwingUtil.setPreferredWidth(this.authoritySelect, 100);
 		SwingUtil.setMinimumWidth(this.authoritySelect, 100);



More information about the Schmitzm-commits mailing list