Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4853056

REGRESSION: SpringLayout bug appears in 1.4.1_02

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Not an Issue
    • Icon: P3 P3
    • None
    • 1.4.1, 1.4.1_02, 1.4.2
    • client-libs
    • x86
    • windows_2000, windows_xp



      Name: jk109818 Date: 04/23/2003


      FULL PRODUCT VERSION :
      1.4.1_02-b06

      FULL OS VERSION :
      Windows XP Home 2002

      A DESCRIPTION OF THE PROBLEM :
      A dialog that uses SpringLayout works fine in jre 140_01 but does not work in jre 141_02. It includes a table and textarea that do not display at all, even when the dialog is resized. I have included the source code below.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      source is attached below, includes main() to open dialog

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      dialog should work as it does in 140_01
      dialog no longer works

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.awt.BorderLayout;
      import java.awt.Component;
      import java.awt.FlowLayout;
      import java.awt.HeadlessException;
      import java.awt.event.ActionEvent;
      import java.awt.event.ActionListener;

      import javax.swing.BorderFactory;
      import javax.swing.JButton;
      import javax.swing.JDialog;
      import javax.swing.JFrame;
      import javax.swing.JLabel;
      import javax.swing.JPanel;
      import javax.swing.JScrollPane;
      import javax.swing.JTable;
      import javax.swing.JTextArea;
      import javax.swing.Spring;
      import javax.swing.SpringLayout;
      import javax.swing.table.AbstractTableModel;

      /**
       * This class demonstrates a bug in SpringLayout.
       * This dialog works ok with jre 140_01 but not
       * jre 141_02.
       */
      public class SpringDialog extends JDialog implements ActionListener {

      class ParamTableModel extends AbstractTableModel {

      //the opening table has 6 rows which allows
      //table space to be allocated to fit that many
      String[][] data = { { "", "" }, {
      "", "" }, {
      "", "" }, {
      "", "" }, {
      "", "" }, {
      "", "" }
      };

      public int getColumnCount() {
      return 2;
      }

      public int getRowCount() {
      return data.length;
      }

      public String getColumnName(int col) {
      if (col == 0)
      return "Name";
      return "Value";
      }

      public Object getValueAt(int row, int col) {
      return data[row][col];
      }

      public boolean isCellEditable(int row, int col) {
      return col == 1;
      }

      public void updateParameterData() {

      /*Vector list = model.parameterList();
      String[][] newData = new String[list.size()][2];
      String[] listParam;
      String[] modelParam;
      for (int i = 0; i < list.size(); i++) {
      listParam = (String[]) list.elementAt(i);
      modelParam = new String[2];
      modelParam[0] = listParam[0];
      modelParam[1] = listParam[1];
      newData[i] = modelParam;
      }
      data = newData;
      fireTableDataChanged();*/
      }

      public void setValueAt(Object value, int row, int col) {

      /*String name = (String) getValueAt(row, 0);
      String confirmedValue =
      model.confirmParamValue(name, (String) value);
      if (confirmedValue == null)
      return;
      data[row][col] = confirmedValue;
      fireTableCellUpdated(row, col);*/
      }
      }

      /**
      * Create and open a new dialog.
      */
      public static void main(String[] args) {

      SpringDialog dialog = new SpringDialog(new JFrame());
      dialog.show();
      }

      private ParamTableModel dataModel;
      private JTable table;

      /**
      * Create a modal dialog for component.
      */
      public SpringDialog(JFrame frame) throws HeadlessException {

      super(frame, "Spring Test Dialog", true);
      layoutDialog();
      }

      public void actionPerformed(ActionEvent e) {

      if ("exit".equals(e.getActionCommand())) {
      System.exit(0);
      return;
      }
      }

      /**
      * Layout the dialog controls.
      */
      protected void layoutDialog() {

      getContentPane().setLayout(new BorderLayout());

      int numPairs = 3;
      Component[] leftComp = new Component[numPairs];
      Component[] rightComp = new Component[numPairs];

      JButton button1 = new JButton("Button1");
      button1.setActionCommand("button1");
      JButton button2 = new JButton("Button2");
      button2.setActionCommand("button2");

      leftComp[0] = button1;
      leftComp[1] = button2;
      leftComp[2] = new JLabel("Table:");

      JLabel stylesheetLabel = new JLabel("label1");
      rightComp[0] = stylesheetLabel;
      JLabel resultLabel = new JLabel("label2");
      rightComp[1] = resultLabel;
      rightComp[2] = new JLabel("");

      JPanel labelPanel = createLabelPanel(leftComp, rightComp, 5, 5, 5, 5);
      getContentPane().add(labelPanel, BorderLayout.NORTH);

      dataModel = new ParamTableModel();
      table = new JTable(dataModel);
      table.getTableHeader().setReorderingAllowed(false);
      JScrollPane scrollpane = new JScrollPane(table);
      scrollpane.setBorder(BorderFactory.createEtchedBorder());
      //set pref. size so that centerPanel will allocate
      //correct size to the log panel
      table.setPreferredScrollableViewportSize(table.getPreferredSize());
      table.setColumnSelectionAllowed(false);
      table.setRowSelectionAllowed(false);

      JTextArea textArea = new JTextArea();
      textArea.setBorder(BorderFactory.createEtchedBorder());
      JPanel centerPanel = createCenterPanel(scrollpane, textArea, 5, 5);
      getContentPane().add(centerPanel, BorderLayout.CENTER);

      JPanel buttonPanel = new JPanel();
      buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
      JButton closeButton = new JButton("Exit");
      closeButton.setActionCommand("exit");
      closeButton.addActionListener(this);
      buttonPanel.add(closeButton);
      getContentPane().add(buttonPanel, BorderLayout.SOUTH);

      pack();
      setSize(500, 400);
      setLocationRelativeTo(this.getOwner());

      //send this now to clear (or show) parameters
      //after table sizing and layout
      dataModel.updateParameterData();
      }

      private JPanel createCenterPanel(
      Component top,
      Component bottom,
      int xPad,
      int yPad) {

      SpringLayout layout = new SpringLayout();
      JPanel parent = new JPanel(layout);
      parent.add(top);
      parent.add(bottom);

      Spring xPadSpring = Spring.constant(xPad);
      Spring yPadSpring = Spring.constant(yPad);
      Spring xPadSpring2 = Spring.sum(xPadSpring, xPadSpring);
      Spring yPadSpring2 = Spring.sum(yPadSpring, yPadSpring);
      SpringLayout.Constraints consTop = layout.getConstraints(top);
      SpringLayout.Constraints consBottom = layout.getConstraints(bottom);
      SpringLayout.Constraints consParent = layout.getConstraints(parent);

      consTop.setX(xPadSpring);
      consTop.setWidth(
      Spring.sum(consParent.getWidth(), Spring.minus(xPadSpring2)));
      consTop.setY(yPadSpring);
      consTop.setHeight(Spring.constant(top.getPreferredSize().height));

      consBottom.setX(xPadSpring);
      consBottom.setWidth(consTop.getWidth());
      consBottom.setY(Spring.sum(consTop.getY(), consTop.getHeight()));
      consBottom.setHeight(
      Spring.sum(
      consParent.getHeight(),
      Spring.minus(consBottom.getY())));

      return parent;
      }

      /**
      * Creates a panel that uses a SpringLayout to present
      * pairs of components. For example:
      * <pre>
      * LLLL RRR
      * LL RRR
      * L RRR
      * LLLLL RRR
      * </pre>
      * where the max of the widths of the L (left) components
      * dictates the x location of the R (right) components.
      * The width of the Rs is locked to that of the container
      * so that all extra space is given to them.
      *
      * Copied from SpringLayout demo in the java 1.4 tutorial.
      * Some minor changes were made and are noted below.
      */
      private JPanel createLabelPanel(
      Component[] leftComponents,
      Component[] rightComponents,
      int initialX,
      int initialY,
      int xPad,
      int yPad) {

      SpringLayout layout = new SpringLayout();
      int numRows = Math.max(leftComponents.length, rightComponents.length);

      // The constant springs we'll use to enforce spacing.
      Spring xSpring = Spring.constant(initialX);
      Spring ySpring = Spring.constant(initialY);
      Spring xPadSpring = Spring.constant(xPad);
      Spring yPadSpring = Spring.constant(yPad);
      Spring negXPadSpring = Spring.constant(-xPad);

      // Create the container and add the components to it.
      JPanel parent = new JPanel(layout);
      for (int i = 0; i < numRows; i++) {
      parent.add(leftComponents[i]);
      parent.add(rightComponents[i]);
      }

      // maxEastSpring will contain the highest min/pref/max values
      // for the right edges of the components in the first column
      // (i.e. the largest X coordinate in a first-column component).
      // We use layout.getConstraint instead of layout.getConstraints
      // (layout.getConstraints(comp).getConstraint("East"))
      // because we need a proxy -- not the current Spring.
      // Otherwise, it won't take the revised X position into account
      // for the initial layout.
      Spring maxEastSpringLeft =
      layout.getConstraint("East", leftComponents[0]);
      for (int row = 1; row < numRows; row++) {
      maxEastSpringLeft =
      Spring.max(
      maxEastSpringLeft,
      layout.getConstraint("East", leftComponents[row]));
      }

      // Lay out each pair. The left column's x is constrained based on
      // the passed x location. The y for each component in the left column
      // is the max of the previous pair's height. In the right column, x is
      // constrained by the max width of the left column (maxEastSpringLeft),
      // y is constrained as in the left column, and the width is
      // constrained to be the x location minus the width of the
      // parent container. This last constraint makes the right column fill
      // all extra horizontal space.
      SpringLayout.Constraints lastConsL = null;
      SpringLayout.Constraints lastConsR = null;
      Spring parentWidth = layout.getConstraint("East", parent);
      Spring rWidth = null;
      Spring maxHeightSpring = null;
      Spring rX = Spring.sum(maxEastSpringLeft, xPadSpring);
      //right col location
      Spring negRX = Spring.minus(rX); //negative of rX

      for (int row = 0; row < numRows; row++) {
      SpringLayout.Constraints consL =
      layout.getConstraints(leftComponents[row]);
      SpringLayout.Constraints consR =
      layout.getConstraints(rightComponents[row]);

      consL.setX(xSpring);
      consR.setX(rX);

      //modified to equalize height so labels will
      //center vertically next to buttons
      consR.setHeight(consL.getHeight());

      rWidth = consR.getWidth();
      //get the spring that tracks this
      //component's min/pref/max width after
      //setting the X spring but before
      //setting the width spring (to avoid
      //a circularity); we really only
      //need to do this once for the
      //textfield case, since they have the
      //same size info
      //XXX To account for other cases,
      //XXX we should probably take the max
      //XXX of the widths.
      //This is used to set the container's
      //width after this loop.
      consR.setWidth(
      Spring.sum(Spring.sum(parentWidth, negRX), negXPadSpring));
      if (row == 0) {
      consL.setY(ySpring);
      consR.setY(ySpring);
      maxHeightSpring =
      Spring.sum(
      ySpring,
      Spring.max(consL.getHeight(), consR.getHeight()));
      } else { // row > 0
      Spring y =
      Spring.sum(
      Spring.max(
      lastConsL.getConstraint("South"),
      lastConsR.getConstraint("South")),
      yPadSpring);

      consL.setY(y);
      consR.setY(y);
      maxHeightSpring =
      Spring.sum(
      yPadSpring,
      Spring.sum(
      maxHeightSpring,
      Spring.max(consL.getHeight(), consR.getHeight())));
      }
      lastConsL = consL;
      lastConsR = consR;
      } // end of for loop

      // Wire up the east/south of the container so that the its preferred
      // size is valid. The east spring is the distance to the right
      // column (rX) + the right component's width (rWidth) + the final
      // padding (xPadSpring).
      // The south side is maxHeightSpring + the final padding (yPadSpring).
      SpringLayout.Constraints consParent = layout.getConstraints(parent);

      //modified to not use rWidth - let parent fill space
      //consParent.setConstraint(
      // "East",
      // Spring.sum(rX, Spring.sum(rWidth, xPadSpring)));

      //modified to not use yPadSpring at bottom
      //consParent.setConstraint(
      // "South",
      // Spring.sum(maxHeightSpring, yPadSpring));
      consParent.setConstraint("South", maxHeightSpring);

      return parent;
      }
      }

      ---------- END SOURCE ----------

      Release Regression From : 1.4.0_01
      The above release value was the last known release where this
      bug was known to work. Since then there has been a regression.

      (Review ID: 183178)
      ======================================================================

            svioletsunw Scott Violet (Inactive)
            jkimsunw Jeffrey Kim (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: