Hello,

I'm cross-posting this to Mac and Java groups because I suspect it
could be a Mac related problem.

I have a java application that does a distributed drawing board with
Li & Hudak "IVY" distributed model, but the problem here lies in the GUI.


PROBLEM :

Prior to Java 1.4.1 *update 1* on MacOS X.2.6, interactive drawing by
xoring the old line was OK.

Since this update, it seems the XOR drawing mode has changed but I
cannot find in what way exactly.
The xor color seems to interact in a new way and, according to the
color, I now get an xoring enclosing rectangle instead of the line itself.
Moreover, instead of xoring the coordinates of the last mouse position
to draw the new ones, the lines don't appear at all during the mouse drag.

I tried some variations of the code (below) with no success.

I tried returning to Java 1.4.1 original by setting the symlinks as in
sudo ln -s /System/Library/Frameworks/JavaVM.framework/Versions/1.4.1
/System/Library/Frameworks/JavaVM.framework/Versions/Current
but, surprise, it didn't return to normal.

I had to return to 1.3.1 the same way with
sudo ln -s /System/Library/Frameworks/JavaVM.framework/Versions/1.3.1
/System/Library/Frameworks/JavaVM.framework/Versions/Current
to get the old, normal behaviour.

But I'd definitely prefer to be correct on the last Java version.

I /CANNOT/ consider doing a whole refresh, even double buffered,
during the drag, instead of xoring because that would interfere with
the guts of the IVY algorithm and call for deadlocks and new problems.


QUESTIONS :

- has anybody some info about the changes to xoring and drawing on
Mac latest Java ?

- has anyone experienced the same problem with xoring in Java
1.4.1-1 on Mac OS X ?

- is there a known way to cope with this ?

- attached is the (still long, sorry) relevant code. it should
compile and run as is, if someone wants to. Info on how it works on
another platform would be greatly appreciated, as I have no PC.
the relevant section is between // Drawing and // End Drawing.
it is (i think) a normal xor drawing section.
if anyone has spirits to put an eye on this code and ideas to
amend it, thanks *A LOT*.

- if someone has a running example, I'll gratefuly try it but the
examples I already found here and there behave the same way.

- anything else ?

BTW, to test for inclusion of a point in a line I didn't find anything
better than coding Bresenham.
Isn't there a cleaner Java method to test this ?
I couldn't find it in theDoc.

Sorry for this long message and requests.
Thanks for any help.

[followup to comp.lang.java.gui]

--
Olivier
To reach me remove theShield.



// javac Board.java && java Board && rm *.class

// clic and drag to create and then modify lines

// works on Mac OS X.2.6 with java 1.3.1 but not 1.4.1-1

import java.awt.*;
import java.awt.event.*;

public class Board extends Frame {

public static void main(String argv[]) {
final Board applic = new Board();
applic.pack();
applic.setSize(400, 300);
applic.setLocation(32, 32);
applic.setVisible(true);
}

private Array array = null;

public Board() {
super("Board");
setBackground(Color.decode("0xFFFFFF"));
setFont(new Font("sansserif", Font.PLAIN, 14));
setLayout(new BorderLayout());

array = new Array(5, this); // small set for the example

Panel p = new Panel();

this.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
Board.this.mousePressed(e);
}

public void mouseReleased(MouseEvent e) {
Board.this.mouseReleased(e);
}
});

this.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
Board.this.mouseDragged(e);
}
});
}

public void paint(Graphics g) {
g.setColor(getBackground());
g.fillRect(0, 0, getSize().width, getSize().height);
for (int i=1 ; i<=array.size() ; i++) {
g.setColor(Color.blue);
array.get(i).draw(g);
}
}

//################################################## ########################
// Drawing
//################################################## ########################

// action modes
private static final int NEW = 1; // make new line
private static final int MV1 = 2; // move origin
private static final int MV2 = 3; // move endpoint
private static final int MOV = 4; // move the line

private Color xorCol = Color.yellow; // blue's complement

private int origx, origy; // start click position
private int lastx, lasty; // current mouse position
private Line modline = null;
private int mode = 0;
private int dx, dy; // offset between click and origin
private int lx, ly; // x and y sizes of the line

private void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
if ((modline = array.findOrig(x,y)) != null) {
mode = MV1;
origx = modline.x2;
origy = modline.y2;
lastx = x;
lasty = y;
Graphics g = getGraphics();
g.setColor(getBackground());
modline.draw(g);
modline.set(modline.x2, modline.y2, modline.x1, modline.y1);
}
else if ((modline = array.findExtr(x,y)) != null) {
mode = MV2;
origx = modline.x1;
origy = modline.y1;
lastx = x;
lasty = y;
Graphics g = getGraphics();
g.setColor(getBackground());
modline.draw(g);
}
else if ((modline = array.findLine(x,y)) != null) {
mode = MOV;
origx = x;
origy = y;
lastx = x;
lasty = y;
dx = x-modline.x1();
dy = y-modline.y1();
lx = modline.x2() - modline.x1();
ly = modline.y2() - modline.y1();
Graphics g = getGraphics();
g.setColor(getBackground());
modline.draw(g);
}
else {
mode = NEW;
origx = x;
origy = y;
lastx = origx;
lasty = origy;
}
}

private void mouseDragged(MouseEvent e) {
if (mode==MV1 || mode==MV2) {
Graphics g = getGraphics();
g.setXORMode(xorCol);
int x = e.getX(), y = e.getY();
//if (x!=lastx || y!=lasty) {
g.drawLine(origx, origy, lastx, lasty);
lastx = x; lasty = y;
g.drawLine(origx, origy, lastx, lasty);
//}
}
if (mode==MOV) {
Graphics g = getGraphics();
g.setXORMode(xorCol);
setForeground(Color.black);
int x = e.getX(), y = e.getY();
//if (x!=lastx || y!=lasty) {
g.drawLine(lastx-dx, lasty-dy, lastx-dx+lx, lasty-dy+ly);
lastx = x; lasty = y;
g.drawLine(lastx-dx, lasty-dy, lastx-dx+lx, lasty-dy+ly);
//}
}
if (mode==NEW) {
Graphics g = getGraphics();
g.setXORMode(xorCol);
int x = e.getX(), y = e.getY();
//if (x!=lastx || y!=lasty) {
g.drawLine(origx, origy, lastx, lasty);
lastx = x; lasty = y;
g.drawLine(origx, origy, lastx, lasty);
//}
}
}

private void mouseReleased(MouseEvent e) {
lastx = e.getX();
lasty = e.getY();
if (mode==MV1 || mode==MV2) {
Graphics g = getGraphics();
g.setXORMode(xorCol);
g.drawLine(modline.x1, modline.y1, modline.x2, modline.y2);
g.drawLine(origx, origy, lastx, lasty);
g.setPaintMode();
g.setColor(Color.blue);
Line.draw(g,origx, origy, lastx, lasty);
modline.set(origx,origy, lastx, lasty);
modline.draw(g);
}
if (mode==MOV) {
Graphics g = getGraphics();
g.setXORMode(xorCol);
g.drawLine(modline.x1, modline.y1, modline.x2, modline.y2);
g.drawLine(lastx-dx, lasty-dy, lastx-dx+lx, lasty-dy+ly);
g.setPaintMode();
g.setColor(Color.blue);
Line.draw(g,lastx-dx, lasty-dy, lastx-dx+lx, lasty-dy+ly);
modline.set(lastx-dx, lasty-dy, lastx-dx+lx, lasty-dy+ly);
modline.draw(g);
}
if (mode==NEW) {
if (lastx != origx && lasty != origy) {
Graphics g = getGraphics();
g.setXORMode(xorCol);
g.drawLine(origx, origy, lastx, lasty);
g.setPaintMode();
g.setColor(Color.blue);
Line.draw(g,origx, origy, lastx, lasty);
try {
array.add(new Line(origx,origy, lastx, lasty));
}
catch (Exception ex) {}

}
}
repaint();
}

//################################################## ########################
// End Drawing
//################################################## ########################

}

//################################################## ########################

class Array extends Object {
Board board = null;

private Object objets[] = null;

public Array(int maxElems, Board ctrl) {
board = ctrl;
objets = new Object[maxElems];
objets[0] = new Int(0);
for (int i=1 ; i<maxElems ; i++)
objets[i] = null;
}

public int size() { return ((Int)objets[0]).get();}

public Line get(int i) { return ((Line)objets[i]);}

public void set(int i, Line l) { objets[i] = new Line(l);}

public void add(Line l) {
int i = size()+1;
objets[i] = new Line(l);
objets[0] = new Int(i);
}

public Line findOrig(int x, int y) {
for (int i=size() ; i>0 ; i--) {
if (get(i).hasOrig(x,y))
return get(i);
}
return null;
}

public Line findExtr(int x, int y) {
for (int i=size() ; i>0 ; i--) {
if (get(i).hatr(x,y))
return get(i);
}
return null;
}

public Line findLine(int x, int y) {
for (int i=size() ; i>0 ; i--) {
if (get(i).contains(x,y))
return get(i);
}
return null;
}
}

//################################################## ########################

class Int extends Object {
private int value;

public Int(int val) { super(); set(val);}

public int get() { return value;}
public void set(int val) { value = val;}

public String toString() {
return "{" + "Int = " + value + ", " + super.toString() + " }";
}
}

//################################################## ########################

class Line extends Object {

int x1, y1, x2, y2;

public Line() { super();}

public Line(int x1, int y1, int x2, int y2) {
super();
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}

public Line(Line l) {
this.x1 = l.x1;
this.y1 = l.y1;
this.x2 = l.x2;
this.y2 = l.y2;
}

public static void draw(Graphics g, int x1, int y1, int x2, int y2) {
g.drawLine(x1, y1, x2, y2);
}


public int x1() { return x1;}
public int y1() { return y1;}
public int x2() { return x2;}
public int y2() { return y2;}

public void set(int x1, int y1, int x2, int y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}

public void draw0(Graphics g) {
g.drawLine(x1, y1, x2, y2);
}

void draw(Graphics g) {
draw(g, x1, y1, x2, y2);
}

public boolean contains0(int x0, int y0) {
int xmin = Math.min(x1,x2);
int xmax = Math.max(x1,x2);
int ymin = Math.min(y1,y2);
int ymax = Math.max(y1,y2);

if (x0>=xmin && y0>=ymin && x0<=xmax && y0<=ymax)
return true;
else
return false;
}

public boolean hasOrig(int x0, int y0) {
return (Math.abs(x0-x1)+Math.abs(y0-y1)<4);
}

public boolean hatr(int x0, int y0) {
return (Math.abs(x0-x2)+Math.abs(y0-y2)<4);
}

public boolean contains(int x0, int y0) {
int d, inc1, inc2, xend, yend;
int x, y, dx, dy;

dx = Math.abs(x2 - x1);
dy = Math.abs(y2 - y1);
if (dx>dy) {
d = (dy<<1) - dx;
inc1 = dy<<1;
inc2 = 2 * (dy - dx);
if (x1>x2) {
x = x2;
y = y2;
xend = x1;
}
else {
x = x1;
y = y1;
xend = x2;
}
if (Math.abs(x0-x)+Math.abs(y0-y)<4) return true;

if ( (y1<y2 && xend == x2) || (y1>y2 && xend == x1))
while (x++<xend) {
if (d<0) d += inc1;
else {
y++;
d += inc2;
}
if (Math.abs(x0-x)+Math.abs(y0-y)<4) return true;
}

else while (x++<xend) {
if (d<0) d += inc1;
else {
y--;
d += inc2;
}
if (Math.abs(x0-x)+Math.abs(y0-y)<4) return true;
}
}

else {
d = (dx <<1) - dy;
inc1 = dx <<1;
inc2 = 2 * (dx - dy);
if (y1 > y2) {
y = y2;
x = x2;
yend = y1;
}
else {
y = y1;
x = x1;
yend = y2;
}
if (Math.abs(x0-x)+Math.abs(y0-y)<4) return true;

if( (x1 < x2 && yend == y2) || (x1 > x2 && yend == y1) )
while(y++ < yend){
if( d<0) d += inc1;
else {
x++;
d += inc2;
}
if (Math.abs(x0-x)+Math.abs(y0-y)<4) return true;
}

else while (y++<yend) {
if (d<0) d += inc1;
else {
x--;
d += inc2;
}
if (Math.abs(x0-x)+Math.abs(y0-y)<4) return true;
}
}
return false;
}

public String toString() {
return "{" + "Line =" + 0 + ", " + super.toString() + " }";
}
}