home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 July / Chip_1998-07_cd.bin / zkuste / JBuilder / BDK / Win / bdk_sep97.exe / _SETUP.1 / PropertySheet.java < prev    next >
Encoding:
Java Source  |  1997-09-10  |  11.1 KB  |  444 lines

  1.  
  2. package sun.beanbox;
  3.  
  4. import java.beans.*;
  5. import java.lang.reflect.*;
  6. import java.awt.*;
  7. import java.util.Hashtable;
  8. import java.util.Vector;
  9.  
  10. public class PropertySheet extends Frame {
  11.     private PropertySheetPanel panel;
  12.     private boolean started;
  13.  
  14.     PropertySheet(Wrapper target, int x, int y) {
  15.     super("Properties - <initializing...>");
  16.     setLayout(null);
  17.     setBackground(Color.lightGray);    
  18.     setBounds(x,y, 100, 100);
  19.  
  20.     panel = new PropertySheetPanel(this);
  21.  
  22.     show();
  23.     panel.setTarget(target.getBean());
  24.     setTitle("Properties - " + target.getBeanLabel());
  25.  
  26.     started = true;
  27.     }
  28.  
  29.     void setTarget(Wrapper targ) {
  30.     Object bean = targ.getBean();
  31.     BeanInfo bi = null;
  32.     try {
  33.         bi = Introspector.getBeanInfo(bean.getClass());
  34.     } catch (Exception ex) {};
  35.     String displayName = targ.getBeanLabel();
  36.     panel.setTarget(targ.getBean());
  37.     setTitle("Properties - " + displayName);
  38.     }
  39.  
  40.     public void doLayout() {
  41.     // Normally we get called when propertySheetPanel.setTarget
  42.     // has changed the size of the ScrollPane and of us.
  43.     if (!started) {
  44.         return;
  45.     }
  46.     panel.stretch();
  47.     }
  48.  
  49.     void setCustomizer(Customizer c) {
  50.     panel.setCustomizer(c);
  51.     }
  52.  
  53.     void wasModified(PropertyChangeEvent evt) {
  54.     panel.wasModified(evt);
  55.     }
  56. }
  57.  
  58. class PropertySheetPanel extends Panel {
  59.  
  60.     PropertySheetPanel(PropertySheet frame) {
  61.     this.frame = frame;
  62.     setLayout(null);
  63.     }
  64.  
  65.     synchronized void setTarget(Object targ) {
  66.     
  67.     frame.removeAll();    
  68.  
  69.     removeAll();
  70.  
  71.     // We make the panel invisivle during the reconfiguration
  72.     // to try to reduce screen flicker.
  73.  
  74.     // As a workaround for #4056424, we avoid maling the panel
  75.     // invisible first time though, during startup.
  76.     if (target != null) {
  77.         setVisible(false);
  78.     }
  79.  
  80.     target = targ; 
  81.  
  82.         try {
  83.         BeanInfo bi = Introspector.getBeanInfo(target.getClass());
  84.         properties = bi.getPropertyDescriptors();
  85.     } catch (IntrospectionException ex) {
  86.         error("PropertySheet: Couldn't introspect", ex);
  87.         return;
  88.     }
  89.  
  90.     editors = new PropertyEditor[properties.length];
  91.     values = new Object[properties.length];
  92.     views = new Component[properties.length];
  93.     labels = new Label[properties.length];
  94.  
  95.     // Create an event adaptor.
  96.     EditedAdaptor adaptor = new EditedAdaptor(frame);
  97.  
  98.     for (int i = 0; i < properties.length; i++) {
  99.  
  100.         // Don't display hidden or expert properties.
  101.         if (properties[i].isHidden() || properties[i].isExpert()) {
  102.         continue;
  103.         }
  104.  
  105.         String name = properties[i].getDisplayName();
  106.         Class type = properties[i].getPropertyType();
  107.         Method getter = properties[i].getReadMethod();
  108.         Method setter = properties[i].getWriteMethod();
  109.  
  110.         // Only display read/write properties.
  111.         if (getter == null || setter == null) {
  112.         continue;
  113.         }
  114.     
  115.         Component view = null;
  116.  
  117.         try {
  118.         Object args[] = { };
  119.         Object value = getter.invoke(target, args);
  120.             values[i] = value;
  121.  
  122.             PropertyEditor editor = null;
  123.             Class pec = properties[i].getPropertyEditorClass();
  124.         if (pec != null) {
  125.             try {
  126.             editor = (PropertyEditor)pec.newInstance();
  127.             } catch (Exception ex) {
  128.             // Drop through.
  129.             }
  130.         }
  131.         if (editor == null) {
  132.             editor = PropertyEditorManager.findEditor(type);
  133.         }
  134.             editors[i] = editor;
  135.  
  136.             // If we can't edit this component, skip it.
  137.             if (editor == null) {
  138.             continue;
  139.             }
  140.  
  141.         // Don't try to set null values:
  142.         if (value == null) {
  143.             continue;
  144.         }
  145.  
  146.             editor.setValue(value);
  147.             editor.addPropertyChangeListener(adaptor);
  148.  
  149.         // Now figure out how to display it...
  150.         if (editor.isPaintable() && editor.supportsCustomEditor()) {
  151.             view = new PropertyCanvas(frame, editor);
  152.         } else if (editor.getTags() != null) {
  153.             view = new PropertySelector(editor);
  154.         } else if (editor.getAsText() != null) {
  155.             String init = editor.getAsText();
  156.             view = new PropertyText(editor);
  157.         } else {
  158.             System.err.println("Skipping non-displayable property " + name);
  159.             continue;
  160.         }
  161.  
  162.         } catch (InvocationTargetException ex) {
  163.         System.err.println("Skipping property " + name + " ; exception on target: " + ex.getTargetException());
  164.         ex.getTargetException().printStackTrace();
  165.         continue;
  166.         } catch (Exception ex) {
  167.         System.err.println("Skipping property " + name + " ; exception: " + ex);
  168.         ex.printStackTrace();
  169.         continue;
  170.         }
  171.  
  172.         labels[i] = new Label(name, Label.RIGHT);
  173.         add(labels[i]);
  174.  
  175.         views[i] = view;
  176.         add(views[i]);
  177.     }
  178.  
  179.     frame.add(this);
  180.     doLayout(true);
  181.  
  182.     processEvents = true;
  183.  
  184.     Insets ins = frame.getInsets();
  185.     
  186.     int frameWidth = getSize().width + ins.left + ins.right;
  187.     int frameHeight = getSize().height + ins.top + ins.bottom;
  188.  
  189.     // Do we need to add a scrollpane ?
  190.     boolean needPane = false;
  191.     if (frameWidth > maxWidth) {
  192.         needPane = true;
  193.         frameWidth = maxWidth;
  194.     }
  195.     if (frameHeight > maxHeight) {
  196.         needPane = true;
  197.         frameHeight = maxHeight;
  198.     }
  199.  
  200.     if (needPane) {
  201.         // Put us in a ScrollPane.
  202.  
  203.         // Note that the exact ordering of this code is
  204.         // very important in order to get correct behaviour
  205.         // on win32.  Don't modify unless you have a lot of
  206.         // spare time to test/debug it.
  207.  
  208.         frame.remove(this);
  209.  
  210.         frameWidth = frameWidth + 30;
  211.         if (frameWidth > maxWidth) {
  212.         frameWidth = maxWidth;
  213.         }
  214.         frameHeight = frameHeight + 30;
  215.         if (frameHeight > maxHeight) {
  216.         frameHeight = maxHeight;
  217.         }
  218.  
  219.         ScrollPane pane = new ScrollPane(ScrollPane.SCROLLBARS_ALWAYS);
  220.         pane.setBounds(ins.left, ins.top,
  221.                 frameWidth - (ins.left + ins.right),
  222.                 frameHeight - (ins.top + ins.bottom));
  223.  
  224.         frame.setSize(frameWidth,frameHeight);    
  225.         pane.add(this);
  226.         frame.add(pane);
  227.  
  228.         pane.doLayout();
  229.  
  230.     } else {
  231.         frame.setSize(frameWidth,frameHeight);    
  232.         //We don't need a ScrollPane.
  233.         setLocation(ins.left, ins.top);
  234.         frame.add(this);
  235.     }
  236.  
  237.     setVisible(true);
  238.     
  239.     }
  240.  
  241.     void stretch() {
  242.     // This gets called when a user explicitly resizes the frame.
  243.  
  244.     Component child = null;
  245.     try {
  246.         child = frame.getComponent(0);
  247.     } catch (Exception ex) {
  248.         // frame has no active children;
  249.         return;
  250.     }
  251.     Dimension childSize = child.getSize();
  252.     Dimension frameSize = frame.getSize();
  253.     Insets ins = frame.getInsets();
  254.     int vpad = ins.top + ins.bottom;
  255.     int hpad = ins.left + ins.right;
  256.  
  257.     // If the frame size hasn't changed, do nothing.
  258.     if (frameSize.width == (childSize.width + hpad) &&
  259.         frameSize.height == (childSize.height + vpad)) {
  260.         return;
  261.     }
  262.  
  263.     // We treat the new frame sizes as a future maximum for our own
  264.     // voluntary size changes.
  265.     maxHeight = frameSize.height;
  266.     maxWidth = frameSize.width;
  267.  
  268.     // If we've gotten smaller, force new layout.
  269.     if (frameSize.width < (childSize.width + hpad) ||
  270.             frameSize.height < (childSize.height + vpad)) {
  271.         // frame has shrunk in at least one dimension.
  272.         setTarget(target);
  273.     } else {
  274.        // Simply resize the contents.  Note that this won't make
  275.        // any ScrollPane go away, that will happen on the next
  276.        // focus change.
  277.         child.setSize(frameSize.width - hpad, frameSize.height - vpad);
  278.         
  279.     }
  280.     }
  281.  
  282.     private void doLayout(boolean doSetSize) {
  283.     if (views == null || labels == null) {
  284.         return;
  285.     }
  286.  
  287.     // First figure out the size of the columns.
  288.     int labelWidth = 92;
  289.     int viewWidth = 120;
  290.  
  291.     for (int i = 0; i < properties.length; i++) {
  292.         if (labels[i] == null || views[i] == null) {
  293.         continue;
  294.         }
  295.         int w = labels[i].getPreferredSize().width;
  296.         if (w > labelWidth) {
  297.         labelWidth = w;
  298.         }
  299.         w = views[i].getPreferredSize().width;
  300.         if (w > viewWidth) {
  301.         viewWidth = w;
  302.         }
  303.     }
  304.     int width = 3*hPad + labelWidth + viewWidth;
  305.  
  306.     // Now position all the components.
  307.     int y = 10;
  308.     for (int i = 0; i < properties.length; i++) {
  309.         if (labels[i] == null || views[i] == null) {
  310.         continue;
  311.         }
  312.         labels[i].setBounds(hPad, y+5, labelWidth, 25);
  313.  
  314.         Dimension viewSize = views[i].getPreferredSize();
  315.         int h = viewSize.height;
  316.         if (h < 30) {
  317.         h = 30;
  318.         }
  319.         views[i].setBounds(labelWidth + 2*hPad, y, viewWidth, h);
  320.         y += (h + vPad);
  321.     }
  322.  
  323.     y += vPad;
  324.  
  325.     if (doSetSize) {
  326.         setSize(width, y);
  327.     }
  328.     }
  329.  
  330.  
  331.     public void doLayout() {
  332.     doLayout(false);
  333.     }
  334.  
  335.  
  336.     synchronized void setCustomizer(Customizer c) {
  337.     if (c != null) {
  338.         c.addPropertyChangeListener(new EditedAdaptor(frame));
  339.     }
  340.     }
  341.  
  342.     synchronized void wasModified(PropertyChangeEvent evt) {
  343.  
  344.     if (!processEvents) {
  345.         return;
  346.     }
  347.  
  348.     if (evt.getSource() instanceof PropertyEditor) {
  349.         PropertyEditor editor = (PropertyEditor) evt.getSource();
  350.         for (int i = 0 ; i < editors.length; i++) {
  351.             if (editors[i] == editor) {
  352.             PropertyDescriptor property = properties[i];
  353.                 Object value = editor.getValue();
  354.                 values[i] = value;
  355.             Method setter = property.getWriteMethod();
  356.             try {
  357.                 Object args[] = { value };
  358.                 args[0] = value;
  359.                 setter.invoke(target, args);
  360.             } catch (InvocationTargetException ex) {
  361.               if (ex.getTargetException() instanceof PropertyVetoException) {
  362.             warning("Vetoed; reason is: " + ex.getTargetException().getMessage());
  363.               }
  364.               else
  365.                 error("InvocationTargetException while updating " + 
  366.                     property.getName(), ex.getTargetException());
  367.             } catch (Exception ex) {
  368.                 error("Unexpected exception while updating " + 
  369.                     property.getName(), ex);
  370.                 }
  371.                 if (views[i] != null && views[i] instanceof PropertyCanvas) {
  372.                 views[i].repaint();
  373.                 }
  374.             break;
  375.         }
  376.         }
  377.     }
  378.  
  379.     // Now re-read all the properties and update the editors
  380.     // for any other properties that have changed.
  381.     for (int i = 0; i < properties.length; i++) {
  382.         Object o;
  383.         try {
  384.             Method getter = properties[i].getReadMethod();
  385.             Object args[] = { };
  386.             o = getter.invoke(target, args);
  387.         } catch (Exception ex) {
  388.         o = null;
  389.         }
  390.         if (o == values[i] || (o != null && o.equals(values[i]))) {
  391.             // The property is equal to its old value.
  392.         continue;
  393.         }
  394.         values[i] = o;
  395.         // Make sure we have an editor for this property...
  396.         if (editors[i] == null) {
  397.         continue;
  398.         }
  399.         // The property has changed!  Update the editor.
  400.         editors[i].setValue(o);
  401.         if (views[i] != null) {
  402.         views[i].repaint();
  403.         }
  404.     }
  405.  
  406.     // Make sure the target bean gets repainted.
  407.     if (Beans.isInstanceOf(target, Component.class)) {
  408.         ((Component)(Beans.getInstanceOf(target, Component.class))).repaint();
  409.     }
  410.     }
  411.  
  412.     private void warning(String s) {
  413.     new ErrorDialog(frame, "Warning: " + s);
  414.     }
  415.  
  416.     //----------------------------------------------------------------------
  417.     // Log an error.
  418.  
  419.     private void error(String message, Throwable th) {
  420.     String mess = message + ":\n" + th;
  421.     System.err.println(message);
  422.     th.printStackTrace();
  423.     // Popup an ErrorDialog with the given error message.
  424.     new ErrorDialog(frame, mess);
  425.  
  426.     }
  427.  
  428.     //----------------------------------------------------------------------
  429.     private PropertySheet frame;
  430.  
  431.     private Object target;
  432.     private PropertyDescriptor properties[];
  433.     private PropertyEditor editors[];
  434.     private Object values[];
  435.     private Component views[];
  436.     private Label labels[];
  437.  
  438.     private boolean processEvents;
  439.     private static int hPad = 4;
  440.     private static int vPad = 4;
  441.     private int maxHeight = 500;
  442.     private int maxWidth = 300;
  443. }
  444.