ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From meta...@apache.org
Subject cvs commit: jakarta-ant/src/antidote/org/apache/tools/ant/gui/customizer ObjectPropertyEditor.java DynamicCustomizer.java
Date Tue, 16 Jan 2001 21:45:12 GMT
metasim     01/01/16 13:45:12

  Modified:    src/antidote/org/apache/tools/ant/gui/customizer
                        DynamicCustomizer.java
  Added:       src/antidote/org/apache/tools/ant/gui/customizer
                        ObjectPropertyEditor.java
  Log:
  Added property editor for generic Object with no special property editor.
  
  Revision  Changes    Path
  1.9       +177 -27   jakarta-ant/src/antidote/org/apache/tools/ant/gui/customizer/DynamicCustomizer.java
  
  Index: DynamicCustomizer.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/src/antidote/org/apache/tools/ant/gui/customizer/DynamicCustomizer.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- DynamicCustomizer.java	2001/01/16 19:21:20	1.8
  +++ DynamicCustomizer.java	2001/01/16 21:45:11	1.9
  @@ -59,18 +59,16 @@
   import javax.swing.*;
   import java.util.*;
   import java.io.File;
  -import java.awt.GridBagLayout;
  -import java.awt.GridBagConstraints;
  -import java.awt.Component;
  +import java.awt.*;
   
   /**
    * Widget for dynamically constructing a property editor based on the 
    * an Object's BeanInfo. Essentially a property sheet.
    * 
  - * @version $Revision: 1.8 $ 
  + * @version $Revision: 1.9 $ 
    * @author Simeon Fitch 
    */
  -public class DynamicCustomizer extends JPanel implements Customizer {
  +public class DynamicCustomizer extends JPanel implements Customizer, Scrollable {
   	static {
   		PropertyEditorManager.registerEditor(
   			String.class, StringPropertyEditor.class);
  @@ -88,6 +86,8 @@
   			Properties.class, PropertiesPropertyEditor.class);
   		PropertyEditorManager.registerEditor(
   			File.class, FilePropertyEditor.class);
  +		PropertyEditorManager.registerEditor(
  +			Object.class, ObjectPropertyEditor.class);
   	}
   
       /** Property name that PropertyDescriptors can save in their property
  @@ -109,7 +109,7 @@
       private boolean _readOnly = false;
       /** List of property change listeners interested when the bean
        *  being edited has been changed. */
  -    private List _changeListeners = new LinkedList();
  +    private java.util.List _changeListeners = new LinkedList();
       /** Flag to trun off event propogation. */
       private boolean _squelchChangeEvents = false;
   
  @@ -152,7 +152,7 @@
                   
                   // Lookup the editor.
                   PropertyEditor editor = getEditorForProperty(props[i]);
  -                if(editor == null) continue;
  +
                   // Add a listener to the editor so we know when to update
                   // the bean's fields.
                   editor.addPropertyChangeListener(_eListener);
  @@ -161,7 +161,8 @@
                   // that makes use of the "paintable" capability of the editor.
                   Component comp = editor.getCustomEditor();
                   if(comp == null) {
  -                    comp = new JLabel("<<null editor>>");
  +                    comp = new JLabel("<No editor available.>");
  +                    ((JLabel)comp).setBorder(BorderFactory.createEtchedBorder());
                   }
                   
                   // See if it is a read-only property. If so, then just
  @@ -183,7 +184,6 @@
                       }
                   }
   
  -
                   // Add the label and fields.
                   add(label, gbc.forLabel());
                   add(comp, gbc.forField());
  @@ -272,6 +272,11 @@
               }
           }
   
  +        // In the worse case we resort to the generic editor for Object types.
  +        if(retval == null) {
  +            retval = PropertyEditorManager.findEditor(Object.class);
  +        }
  +
           return retval;
       }
   
  @@ -316,6 +321,111 @@
           }
       }
   
  +    /**
  +     * Returns the preferred size of the viewport for a view component.
  +     * For example the preferredSize of a JList component is the size
  +     * required to acommodate all of the cells in its list however the
  +     * value of preferredScrollableViewportSize is the size required for
  +     * JList.getVisibleRowCount() rows.   A component without any properties
  +     * that would effect the viewport size should just return 
  +     * getPreferredSize() here.
  +     * 
  +     * @return The preferredSize of a JViewport whose view is this Scrollable.
  +     * @see JViewport#getPreferredSize
  +     */
  +    public Dimension getPreferredScrollableViewportSize() {
  +        Dimension size = getPreferredSize();
  +        Dimension retval = new Dimension();
  +        retval.width = size.width > 600 ? 600 : size.width;
  +        retval.height = size.height > 400 ? 400 : size.height;
  +        return retval;
  +    }
  +
  +
  +    /**
  +     * Components that display logical rows or columns should compute
  +     * the scroll increment that will completely expose one new row
  +     * or column, depending on the value of orientation.  Ideally, 
  +     * components should handle a partially exposed row or column by 
  +     * returning the distance required to completely expose the item.
  +     * <p>
  +     * Scrolling containers, like JScrollPane, will use this method
  +     * each time the user requests a unit scroll.
  +     * 
  +     * @param visibleRect The view area visible within the viewport
  +     * @param orientation Either SwingConstants.VERTICAL or 
  +     *                    SwingConstants.HORIZONTAL.
  +     * @param direction Less than zero to scroll up/left, 
  +     *                  greater than zero for down/right.
  +     * @return The "unit" increment for scrolling in the specified direction
  +     * @see JScrollBar#setUnitIncrement
  +     */
  +    public int getScrollableUnitIncrement(Rectangle visibleRect, 
  +                                          int orientation, int direction) {
  +        return 1;
  +    }
  +
  +
  +    /**
  +     * Components that display logical rows or columns should compute
  +     * the scroll increment that will completely expose one block
  +     * of rows or columns, depending on the value of orientation. 
  +     * <p>
  +     * Scrolling containers, like JScrollPane, will use this method
  +     * each time the user requests a block scroll.
  +     * 
  +     * @param visibleRect The view area visible within the viewport
  +     * @param orientation Either SwingConstants.VERTICAL or 
  +     *                    SwingConstants.HORIZONTAL.
  +     * @param direction Less than zero to scroll up/left, 
  +     *                  greater than zero for down/right.
  +     * @return The "block" increment for scrolling in the specified direction.
  +     * @see JScrollBar#setBlockIncrement
  +     */
  +    public int getScrollableBlockIncrement(Rectangle visibleRect, 
  +                                           int orientation, int direction) {
  +        return orientation == SwingConstants.VERTICAL ? 
  +            visibleRect.height / 2 : visibleRect.width / 2;
  +    }
  +    
  +
  +    /**
  +     * Return true if a viewport should always force the width of this 
  +     * Scrollable to match the width of the viewport.  For example a noraml 
  +     * text view that supported line wrapping would return true here, since it
  +     * would be undesirable for wrapped lines to disappear beyond the right
  +     * edge of the viewport.  Note that returning true for a Scrollable
  +     * whose ancestor is a JScrollPane effectively disables horizontal
  +     * scrolling.
  +     * <p>
  +     * Scrolling containers, like JViewport, will use this method each 
  +     * time they are validated.  
  +     * 
  +     * @return True if a viewport should force the Scrollables 
  +     *         width to match its own.
  +     */
  +    public boolean getScrollableTracksViewportWidth() {
  +        return true;
  +    }
  +
  +    /**
  +     * Return true if a viewport should always force the height of this 
  +     * Scrollable to match the height of the viewport.  For example a 
  +     * columnar text view that flowed text in left to right columns 
  +     * could effectively disable vertical scrolling by returning
  +     * true here.
  +     * <p>
  +     * Scrolling containers, like JViewport, will use this method each 
  +     * time they are validated.  
  +     * 
  +     * @return True if a viewport should force the Scrollables 
  +     *         height to match its own.
  +     */
  +    public boolean getScrollableTracksViewportHeight() {
  +        return false;
  +    }
  +
  +
       /** Class for receiving change events from the PropertyEditor objects. */
       private class EditorChangeListener implements PropertyChangeListener {
           public void propertyChange(PropertyChangeEvent e) {
  @@ -354,7 +464,7 @@
               Integer i2 = (Integer) p2.getValue(SORT_ORDER);
               
               if(i1 == null && i2 == null) {
  -                return 0;
  +                return p1.getName().compareTo(p2.getName());
               }
               else if(i1 != null) {
                   return i1.compareTo(i2);
  @@ -365,21 +475,26 @@
           }
       }
   
  +
  +    /*----------------------------------------------------------------------*/
  +
       /** Class for testing this. */
  -    private static class TestClass {
  -        private String _String = null;
  -        private String[] _StringArray = null;
  -        private int _int = 0;
  -        private Integer _Integer = null;
  -        private double _double = 0;
  -        private Double _Double = null;
  -        private Properties _Properties = null;
  -        private File _File = null;
  +    private static class TestClass implements Cloneable {
  +        private String _String = "This string is my name.";
  +        private String[] _StringArray = { "one", "two", "three" };
  +        private int _int = Integer.MIN_VALUE;
  +        private Integer _Integer = new Integer(Integer.MAX_VALUE);
  +        private double _double = Double.MIN_VALUE;
  +        private Double _Double = new Double(Double.MAX_VALUE);
  +        private Properties _Properties = System.getProperties();
  +        private File _File = new File("/");
  +        private Object _Object = new Font("Monospaced", Font.PLAIN, 12);
  +        private JButton _button = new JButton("I'm a button!");
   
  -        public void setString(String string) {
  +        public void setName(String string) {
               _String = string;
           }
  -        public String getString() {
  +        public String getName() {
               return _String;
           }
   
  @@ -431,6 +546,31 @@
           public File getFile() {
               return _File;
           }
  +        
  +        public void setButton(JButton button) {
  +            _button = button;
  +        }
  +
  +        public JButton getButton() {
  +            return _button;
  +        }
  +
  +        public void setObject(Object o) {
  +            _Object = o;
  +        }
  +
  +        public Object getObject() {
  +            return _Object;
  +        }
  +
  +        public Object clone() {
  +            try {
  +                return super.clone();
  +            }
  +            catch(CloneNotSupportedException ex) {
  +                return null;
  +            }
  +        }
       }
   
   
  @@ -442,12 +582,22 @@
       public static void main(String[] args) {
   
           try {
  -            Class c = args.length > 0 ? Class.forName(args[0]) : TestClass.class;
  -            JFrame f = new JFrame(c.getName());
  -            DynamicCustomizer custom = 
  -                new DynamicCustomizer(c);
  -            custom.setObject(c.newInstance());
  -            f.getContentPane().add(custom);
  +            Class type = null;
  +            Object instance = null;
  +            if(args.length > 0) {
  +                type = Class.forName(args[0]);
  +                instance = type.newInstance();
  +            }
  +            else {
  +                type = TestClass.class;
  +                instance = new TestClass();
  +                ((TestClass)instance).setObject(new TestClass());
  +            }
  +
  +            JFrame f = new JFrame(type.getName());
  +            DynamicCustomizer custom = new DynamicCustomizer(type);
  +            custom.setObject(instance);
  +            f.getContentPane().add(new JScrollPane(custom));
               f.pack();
               f.setVisible(true);
           }
  
  
  
  1.1                  jakarta-ant/src/antidote/org/apache/tools/ant/gui/customizer/ObjectPropertyEditor.java
  
  Index: ObjectPropertyEditor.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Ant", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.tools.ant.gui.customizer;
  
  import javax.swing.*;
  import java.awt.*;
  import java.awt.event.ActionListener;
  import java.awt.event.ActionEvent;
  import java.lang.reflect.Method;
  import javax.swing.border.BevelBorder;
  
  /**
   * Custom property editor for generic Object types. Useful for 
   * complex objects where using the DynamicCustomizer may be useful.
   * 
   * @version $Revision: 1.1 $ 
   * @author Simeon Fitch 
   */
  public class ObjectPropertyEditor extends AbstractPropertyEditor {
      /** Area for typing in the file name. */
      private JTextField _widget = null;
      /** Container for the editor. */
      private JPanel _container = null;
      /** The current object value. */
      private Object _value = null;
      /** The editing button. */
      private JButton _button = null;
      /** Flag to indicate that cancellation of editing is supported. */
      private boolean _supportCancel = true;
      /** Original value. Only used if _supportCancel is true. */
      private Object _original = null;
  
      /** 
       * Default ctor.
       * 
       */
      public ObjectPropertyEditor() {
          _container = new JPanel(new BorderLayout());
          
          _widget = new JTextField(25);
          _widget.setEditable(false);
          _widget.addFocusListener(new FocusHandler(this));
          _widget.setBorder(
              BorderFactory.createBevelBorder(BevelBorder.LOWERED));
  
          _container.add(_widget, BorderLayout.CENTER);
  
          _button = new JButton("Edit...");
          _button.addActionListener(new ActionHandler());
          _container.add(_button, BorderLayout.EAST);
      }
  
      /** 
       * Get the child editing component. Uses JComponent so we can have tool
       * tips, etc.
       * 
       * @return Child editing component.
       */
      protected Component getChild() {
          return _container;
      }
  
  
      /**
       * This method is intended for use when generating Java code to set
       * the value of the property.  It should return a fragment of Java code
       * that can be used to initialize a variable with the current property
       * value.
       * <p>
       * Example results are "2", "new Color(127,127,34)", "Color.orange", etc.
       *
       * @return A fragment of Java code representing an initializer for the
       *      current value.
       */
      public String getJavaInitializationString() {
          return null;
      }
  
      /**
       * Set (or change) the object that is to be edited.  Builtin types such
       * as "int" must be wrapped as the corresponding object type such as
       * "java.lang.Integer".
       *
       * @param value The new target object to be edited.  Note that this
       *     object should not be modified by the PropertyEditor, rather 
       *     the PropertyEditor should create a new object to hold any
       *     modified value.
       * @exception IllegalArgumentException thrown if value can't be cloned.
       */
      public void setValue(Object value) {
  
          if(_supportCancel && value != _value) {
              try {
                  _value = makeClone(value);
              }
              catch(CloneNotSupportedException ex){
                  // If cloning doesn't work then we can't support a "cancel"
                  // option on the editing dialog.
                  _supportCancel = false;
              }
              _original = value;
          }
          
          _value = value;
  
          _button.setEnabled(_value != null);
  
          _widget.setText(getAsString(_value));
      }
  
      /** 
       * Convert the given value into some appropriate string. NB: This method
       * can be continually improved to be made more and more smart over time.
       * 
       * @param value Value to convert.
       * @return String value to display.
       */
      private String getAsString(Object value) {
          String retval = null;
          if(value == null) {
              retval = "<null>";
          }
  
          // We try to be smart by querying for various, logical string 
          // representation of the value.
          if(retval == null) {
              try {
                  Method m = value.getClass().getMethod("getName", null);
                  retval = (String) m.invoke(value, null);
              }
              catch(Exception ex) {
              }
          }
          if(retval == null) {
              try {
                  Method m = value.getClass().getMethod("getLabel", null);
                  retval = (String) m.invoke(value, null);
              }
              catch(Exception ex) {
              }
              
          }
          if(retval == null) {
              try {
                  Method m = value.getClass().getMethod("getText", null);
                  retval = (String) m.invoke(value, null);
              }
              catch(Exception ex) {
              }
          }
  
          if(retval == null) {
              retval = value.toString();
          }
  
          if(retval.length() > 256) {
              retval = retval.substring(0, 253) + "...";
          }
  
          return retval;
      }
  
      /** 
       * Attampt to make a clone of the given value.
       * 
       * @param value Value to clone.
       * @return Cloned value, or null if value given was null.
       * @exception IllegalArgumentException thrown if value can't be cloned.
       */
      private Object makeClone(Object value) throws CloneNotSupportedException {
          Object retval = null;
          if(value != null) {
              try {
                  Method m = value.getClass().getMethod("clone", null);
                  retval = m.invoke(value, null);
              }
              catch(Throwable ex) {
                  throw new CloneNotSupportedException(
                      "This editor only supports types that have publically " +
                      "accessible clone() methods.\n" + 
                      value.getClass().getName() + 
                      " does not have such a method.");
              }
          }
          return retval;
      }
  
      /**
       * @return The value of the property.  Builtin types
       * such as "int" will be wrapped as the corresponding
       * object type such as "java.lang.Integer".  */
      public Object getValue() {
          return _value;
      }
  
      /**
       * Set the property value by parsing a given String.  May raise
       * java.lang.IllegalArgumentException if either the String is
       * badly formatted or if this kind of property can't be expressed
       * as text.
       * @param text  The string to be parsed.
       */
      public void setAsText(String text) throws IllegalArgumentException {
          throw new IllegalArgumentException("String conversion not supported.");
      }
  
      /**
       * @return The property value as a human editable string.
       * <p>   Returns null if the value can't be expressed 
       *       as an editable string.
       * <p>   If a non-null value is returned, then the PropertyEditor should
       *       be prepared to parse that string back in setAsText().
       */
      public String getAsText() {
          return null;
      } 
  
      /** Handler for presses of the edit button. */
      private class ActionHandler implements ActionListener {
          public void actionPerformed(ActionEvent e) {
              if(_value == null) return;
              Class type = _value.getClass();
              DynamicCustomizer c = new DynamicCustomizer(type);
              c.setObject(_value);
  
              int returnVal = JOptionPane.OK_OPTION;
              if(_supportCancel) {
                  returnVal = JOptionPane.showConfirmDialog(
                      getChild(), new JScrollPane(c), "Editing...", 
                      JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
              }
              else {
                  JOptionPane.showMessageDialog(
                      getChild(), new JScrollPane(c), "Editing...",
                      JOptionPane.PLAIN_MESSAGE);
                  returnVal = JOptionPane.OK_OPTION;
              }
  
              if(returnVal == JOptionPane.OK_OPTION) {
                  Object oldValue = _original;
                  Object newValue = _value;
  
                  setValue(newValue);
                  firePropertyChange(oldValue, newValue);
              } 
              else {
                  try {
                      _value = makeClone(_original);
                  }
                  catch(CloneNotSupportedException ex) {
                      // XXX log me. Shouldn't have gotten here as
                      // the test for cloneability should have already been done.
                      ex.printStackTrace();
                      _supportCancel = false;
                  }
              }
          }
      }
  
  }
  
  
  
  
  

Mime
View raw message