This bug occurs with nested Panels, in which the outer Panel has
non-zero insets, and the inner panel has zero-insets.
In this situation, items placed at x=0 or y=0 in the inner container
get placed at the corresponing x=0 or y=0 on the outer container.
I know, it's confusing ... I have a test applet to demo it very graphically.
The applet uses a very simple subtype of Panel that allows the insets
to be specified. It also tries to draw boxes to indicate its bounding box
and its insets. These boxes are in a specified color.
It also defines and uses a very simple canvas that draws its bounding
box and diagonals in a specified color.
At the top level of the applet, a Panel is created called "pair".
It has an inset of 20,20,20,20 and uses a GridLayout to lay out
2 children, one above the other. The bounding box and insets
are drawn in magenta.
The lower child of "pair" is a simple DemoCanvas, drawn in white.
The upper child of "pair" is a nested Panel with an inset of 0,0,0,0
and a nominated color of orange, although with a zero inset, you
shouldn't be able to see any highlighting!
The nested panel has a 2x2 grid of canvases, in red, green, yellow
and blue.
Now for the fun stuff. Run the demo. the red, green and blue
boxes are not correctly nested. They overflow out of the container
they're supposed to be in. The yellow canvas is placed correctly.
Now try editing the test program and setting the inset argument
to test panel to 1or any other number, in the first line of Main.init.
Panel quad = new TestPanel(0, Color.orange);
***
Run the test program again, and the red, green, and blue boxes have
jumped by much more than one pixel ... they're now correctly nested
in their container.
Even more dramatic ... set that argument to the TestPanel constructor
to a negative number. It works, and the boxes become bigger the way
you'd expect but clipped to the container also like you'd expect.
In short, the only problem value is zero, which is a real bummer, because
that is the default value of a normal Panel's inset.
Go figure!
It has taken a while to narrow the bug down this far. Experiment shows that
it is not GridLayout that is at fault .... I have seen the same problem with
other LayoutManagers ... I first found this effect in a custom layout manager
of mine, and it took a while to convince myself it was not that at fault.
I have also tried chasing paint and reshape calls all the way down to Motif
to no avail; I do not see anything blatantly wrong.
-----applet---------------------------------------------
import java.applet.Applet;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Panel;
public class Main extends Applet
{
//----- Applet methods
public void init() {
Panel quad = new TestPanel(0, Color.orange);
quad.setLayout(new GridLayout(2, 2));
quad.add(new DemoCanvas(10, 30, Color.red));
quad.add(new DemoCanvas(30, 20, Color.green));
quad.add(new DemoCanvas(10, 30, Color.blue));
quad.add(new DemoCanvas(30, 20, Color.yellow));
Panel pair = new TestPanel(20, Color.magenta);
pair.setLayout(new GridLayout(2, 1));
pair.add(quad);
pair.add(new DemoCanvas(100, 100, Color.white));
add(pair);
validate();
}
}
class TestPanel extends Panel
{
TestPanel(int border, Color c) {
this.border = border;
this.color = c;
}
public Insets insets() {
return new Insets(border, border, border, border);
}
public void paint(Graphics g) {
Dimension s = size();
Insets i = insets();
g.setColor(color);
g.drawRect(0, 0, s.width - 1, s.height - 1);
g.setColor(color.darker());
g.drawRect(i.left - 1, i.top - 1,
s.width - i.left - i.right + 2, s.height - i.top - i.bottom + 2);
}
Color color;
int border;
}
class DemoCanvas extends Canvas
{
DemoCanvas(int w, int h, Color c) {
this.c = c;
d = new Dimension(w, h);
}
public void paint(Graphics g) {
Dimension s = size();
g.setColor(c);
g.drawLine(0, 0, s.width, s.height);
g.drawLine(s.width, 0, 0, s.height);
g.drawRect(0, 0, s.width-1, s.height-1);
}
public Dimension minimumSize() { return d; }
public Dimension preferredSize() { return d; }
Color c;
Dimension d;
}
----- test doc --------------------------------------------------
<html>
<head>
<TITLE>Compiler test demo</TITLE>
</head>
<body>
<applet
codebase=/home/jjg/javatest/src/javatest/crawler
code="Main.class"
width=500
height=600
>
<param name=testsuite value=/home/jjg/javatest/tests/testsuite.html>
COMPILER TEST SUITE
</applet>
</body>
</html>
non-zero insets, and the inner panel has zero-insets.
In this situation, items placed at x=0 or y=0 in the inner container
get placed at the corresponing x=0 or y=0 on the outer container.
I know, it's confusing ... I have a test applet to demo it very graphically.
The applet uses a very simple subtype of Panel that allows the insets
to be specified. It also tries to draw boxes to indicate its bounding box
and its insets. These boxes are in a specified color.
It also defines and uses a very simple canvas that draws its bounding
box and diagonals in a specified color.
At the top level of the applet, a Panel is created called "pair".
It has an inset of 20,20,20,20 and uses a GridLayout to lay out
2 children, one above the other. The bounding box and insets
are drawn in magenta.
The lower child of "pair" is a simple DemoCanvas, drawn in white.
The upper child of "pair" is a nested Panel with an inset of 0,0,0,0
and a nominated color of orange, although with a zero inset, you
shouldn't be able to see any highlighting!
The nested panel has a 2x2 grid of canvases, in red, green, yellow
and blue.
Now for the fun stuff. Run the demo. the red, green and blue
boxes are not correctly nested. They overflow out of the container
they're supposed to be in. The yellow canvas is placed correctly.
Now try editing the test program and setting the inset argument
to test panel to 1or any other number, in the first line of Main.init.
Panel quad = new TestPanel(0, Color.orange);
***
Run the test program again, and the red, green, and blue boxes have
jumped by much more than one pixel ... they're now correctly nested
in their container.
Even more dramatic ... set that argument to the TestPanel constructor
to a negative number. It works, and the boxes become bigger the way
you'd expect but clipped to the container also like you'd expect.
In short, the only problem value is zero, which is a real bummer, because
that is the default value of a normal Panel's inset.
Go figure!
It has taken a while to narrow the bug down this far. Experiment shows that
it is not GridLayout that is at fault .... I have seen the same problem with
other LayoutManagers ... I first found this effect in a custom layout manager
of mine, and it took a while to convince myself it was not that at fault.
I have also tried chasing paint and reshape calls all the way down to Motif
to no avail; I do not see anything blatantly wrong.
-----applet---------------------------------------------
import java.applet.Applet;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Panel;
public class Main extends Applet
{
//----- Applet methods
public void init() {
Panel quad = new TestPanel(0, Color.orange);
quad.setLayout(new GridLayout(2, 2));
quad.add(new DemoCanvas(10, 30, Color.red));
quad.add(new DemoCanvas(30, 20, Color.green));
quad.add(new DemoCanvas(10, 30, Color.blue));
quad.add(new DemoCanvas(30, 20, Color.yellow));
Panel pair = new TestPanel(20, Color.magenta);
pair.setLayout(new GridLayout(2, 1));
pair.add(quad);
pair.add(new DemoCanvas(100, 100, Color.white));
add(pair);
validate();
}
}
class TestPanel extends Panel
{
TestPanel(int border, Color c) {
this.border = border;
this.color = c;
}
public Insets insets() {
return new Insets(border, border, border, border);
}
public void paint(Graphics g) {
Dimension s = size();
Insets i = insets();
g.setColor(color);
g.drawRect(0, 0, s.width - 1, s.height - 1);
g.setColor(color.darker());
g.drawRect(i.left - 1, i.top - 1,
s.width - i.left - i.right + 2, s.height - i.top - i.bottom + 2);
}
Color color;
int border;
}
class DemoCanvas extends Canvas
{
DemoCanvas(int w, int h, Color c) {
this.c = c;
d = new Dimension(w, h);
}
public void paint(Graphics g) {
Dimension s = size();
g.setColor(c);
g.drawLine(0, 0, s.width, s.height);
g.drawLine(s.width, 0, 0, s.height);
g.drawRect(0, 0, s.width-1, s.height-1);
}
public Dimension minimumSize() { return d; }
public Dimension preferredSize() { return d; }
Color c;
Dimension d;
}
----- test doc --------------------------------------------------
<html>
<head>
<TITLE>Compiler test demo</TITLE>
</head>
<body>
<applet
codebase=/home/jjg/javatest/src/javatest/crawler
code="Main.class"
width=500
height=600
>
<param name=testsuite value=/home/jjg/javatest/tests/testsuite.html>
COMPILER TEST SUITE
</applet>
</body>
</html>