United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: 4726194 SpringLayout doesn't always resolve constraints correctly
4726194 : SpringLayout doesn't always resolve constraints correctly

Details
Type:
Enhancement
Submit Date:
2002-08-05
Status:
Resolved
Updated Date:
2005-09-20
Project Name:
JDK
Resolved Date:
2005-09-20
Component:
client-libs
OS:
windows_xp
Sub-Component:
javax.swing
CPU:
x86
Priority:
P3
Resolution:
Fixed
Affected Versions:
1.4.0
Fixed Versions:
6

Related Reports

Sub Tasks

Description
Name: pa48320			Date: 08/05/2002


FULL PRODUCT VERSION :
java version "1.4.0_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0_01-b03)
Java HotSpot(TM) Client VM (build 1.4.0_01-b03, mixed mode)

and

java version "1.4.1-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-beta-b14)
Java HotSpot(TM) Client VM (build 1.4.1-beta-b14, mixed mode)

FULL OPERATING SYSTEM VERSION :
Microsoft Windows XP [Version 5.1.2600]

ADDITIONAL OPERATING SYSTEMS :
Red Hat Linux release 7.3 (Valhalla)
#1 SMP Thu Apr 18 07:17:10 EDT 2002
2.4.18-3bigmem



A DESCRIPTION OF THE PROBLEM :
SpringLayout fails to properly evaluate constraints under
many conditions, one of them being that the order in which
constraints are attached is significant. The attached
reproduction is a trivial example with a known workaround.
However, for many of the non-trivial layouts we have tried
to use in a production system there are no known
workarounds.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Run this attached source code.
2. Swap constraints A and B and run it again.
3. Note the different behavior.

EXPECTED VERSUS ACTUAL BEHAVIOR :
In step 1, the text field collapses to width 0 and tracks
the East edge of the parent. It should conform to both
constraints and resize appropriately, as it does in step
3. In the general case, any legal set of constraints
should be obeyed, but they are not.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
package test;

import javax.swing.*;

public class TestSpring extends JPanel {

  public TestSpring() {
        SpringLayout m_layout = new SpringLayout();
        setLayout(m_layout);
        Spring margin = Spring.constant(5);

        JLabel m_lName = new JLabel("Label");
        add(m_lName);
        SpringLayout.Constraints cons = m_layout.getConstraints(m_lName);
        cons.setX(margin);
        cons.setY(margin);
        cons.setWidth(Spring.constant(60));

        JTextField m_tName = new JTextField();
        add(m_tName);
        cons = m_layout.getConstraints(m_tName);
        cons.setY(margin);
        // Constraint A
        m_layout.putConstraint(SpringLayout.WEST, m_tName, 5,
                               SpringLayout.EAST, m_lName);
        // Constraint B
        m_layout.putConstraint(SpringLayout.EAST, m_tName, -5,
                               SpringLayout.EAST, this);

        m_layout.layoutContainer(this);
  }

   public static void main(String[] args) {
     JFrame jf = new JFrame("Test SpringLayout");
     jf.setDefaultCloseOperation(jf.EXIT_ON_CLOSE);
     jf.getContentPane().add(new TestSpring());
     jf.setLocation(100,100);
     jf.setSize(400,280);
     jf.doLayout(); // Just for good measure...1
     jf.setVisible(true);
   }
}


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

CUSTOMER WORKAROUND :
In the general case, none. For the specific case in the
source code, swap constraints A and B.
(Review ID: 160271) 
======================================================================

                                    

Comments
EVALUATION

Unfortunately the setting of constraints is order dependant.
The constraints object is used to determine two values along a given
axis (left and right edge or top and bottom edge) but allows you to
specify three Springs (west, width and east or north, height and south).
If you have specified two of the springs along a give axis the other
spring can be calculated. For example, if you specify the
west and width spring, the east spring can be calculated as 
west + width.
But what happens if both the west and width spring are specified (as is
the default) and you specify an east spring? At this point the Constraints object
is considered over constrained along a given axis and one of the edges
must be reset. Why you ask? The values from the springs may not match,
that is the value from the east spring may not match that of the west
spring - width spring. The javadoc for Constraints indicates
what happens when an axis is over constrained:

Value Being Set(method used)  -               Result When Over-Constrained Horizontally (x, width, and the east edge are all non-null)
------------------------------------------    ------------------------------------------------------------------------------
x or the west edge (setX or setConstraint)    width value is automatically set to east - x.
width(setWidth)                               east edge's value is automatically set to x + width.
east edge(setConstraint)                      x value is automatically set to east - width.

The constraints object is first created such that the x edge has
a spring bound to 0, and the width spring matches
the prefered width. The example than sets the west edge.
Everything is ok, as the horizontal axis is not over
constrained.
The example then sets the east constraint which results
in the horizontal axis becoming over constrained and
an edge must be reset. Looking at the above table
shows the x edge will be reset to the east - width.
Because the preferred width of an empty text field is almost 0,
this results in a really small text field.

The second test case is to reverse the order the edges
are set in. If the east edge is set first the x edge
will be reset, but the x edge will be again programmatically
set to what is desired and everything works ok.

###@###.### 2002-08-05

I'm reopening this and moving it to RFE.
Ideally setting the constraints would NOT be order dependent.
###@###.### 2005-2-11 00:57:51 GMT

Phil has proposed a way to resolve this.  The algorithm used to calculate springs will be based on the last two springs (along each axis) that have been specified.  This fixs the problem in that SpringLayout will in effect know the last two springs that have been specified so that it doesn't have to guess at what you wanted and addresses the order previous order dependancy.

For example, this bug was adding a component, specifying the west edge, then the east edge this resulted in the west edge getting reset to east - width.  With the new code SpringLayout will remember the last two settings, in this case it will remember the developer specified the west edge, then east, resulting in deriving the width and all will work.

The down side of this is that it has the potential for incompatability, in that if a developer was relying on the above algorithm, they would have problems.
###@###.### 2005-07-19 22:18:25 GMT
                                     
2005-07-19



Hardware and Software, Engineered to Work Together