<Swing Dev> Two Gtk-LNF bugs+fixes

Clemens Eisserer linuxhippy at gmail.com
Wed Jan 2 12:08:06 UTC 2008


Hello,

On my laptop running Fedora7, GTKLookAndFeel showed some artifacts on
JInternalFrames, as can be seen here:
http://picasaweb.google.at/linuxhippy/GtkLnf

There are two problems + sugested fixes:
1.)
Description:  The titlebar of JInternalFrames showed lines, grey when
selected and transparent when in backgrounf.

Cause: The ClearLooks-Theme used by default uses a lot of
gradient-stops, and because the drawGradient()-Method in
com.sun.java.swing.plaf.gtk.Metacity uses integer arithmetic there
were rouding errors - which caused some areas not to be painted at all
(which left the gray/transparent lines in the title bar).

Suggested fix:
My suggestion would be to use float and the new Java2D fill() method
instead of fillRect which only accepts integer coordinates, the Java2d
should care which pixels should be painted and which not.
However I am a bit in doubt because I read that the new Java2d methods
work with "72dpi user-space coordinates" whereas Graphics-1 methods
use the device coordinate system - so I hope it does not break
anything. At least on my display it worked fine ;)

Code:
  protected void drawGradient(Node node, Graphics g) {
	NamedNodeMap attrs = node.getAttributes();
	String type = getStringAttr(attrs, "type");
	float alpha = getFloatAttr(node, "alpha", -1F);
	float x = aee.evaluate(getStringAttr(attrs, "x")); //Fix
	float y = aee.evaluate(getStringAttr(attrs, "y"));
	float w = aee.evaluate(getStringAttr(attrs, "width"));
	float h = aee.evaluate(getStringAttr(attrs, "height"));
	if (getInt("width") == -1) {
	    x -= w;
	}
	if (getInt("height") == -1) {
	    y -= h;
	}

	// Get colors from child nodes
	Node[] colorNodes = getNodesByName(node, "color");
	Color[] colors = new Color[colorNodes.length];
	for (int i = 0; i < colorNodes.length; i++) {
	    colors[i] = parseColor(getStringAttr(colorNodes[i], "value"));
	}

	boolean horizontal = ("diagonal".equals(type) || "horizontal".equals(type));
	boolean vertical   = ("diagonal".equals(type) || "vertical".equals(type));

	if (g instanceof Graphics2D) {
	    Graphics2D g2 = (Graphics2D)g;
	    Composite oldComp = g2.getComposite();
	    if (alpha >= 0F) {
		g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
	    }
	    int n = colors.length - 1;
	    for (int i = 0; i < n; i++) {
	    	
		g2.setPaint(new GradientPaint(x + (horizontal ? (i*w/n) : 0),
					      y + (vertical   ? (i*h/n) : 0),
					      colors[i],
					      x + (horizontal ? ((i+1)*w/n) : 0),
					      y + (vertical   ? ((i+1)*h/n) : 0),
					      colors[i+1]));
	
		g2.fill(new Rectangle2D.Float(x + (horizontal ? (i*w/n)  : 0),
			    y + (vertical   ? (i*h/n) : 0),
			    (horizontal ? (w/n) : w),
			    (vertical   ? (h/n) : h)));
		
	    }
	    g2.setComposite(oldComp);
	}
    }


2.) Description: The area between the JInternal-Frame-Border and the
ContentPane was not filled, so JInternalFrames were partly
transparent.

Cause: JInternalFrames with round corners are not opaque, but
metacity-windows are by default. Areas which are not specified to be
painted by the MetacityTheme will leave "holes" in the window where
the background shines through.

Suggested fix: Fill the area of the JInternalFrame with the
JInternalFrame's backround color, this simulates the non-opaque
behaviour of metacity.
However this would maybe break themes with pictures as background of
panels, windows etc. - I am not sure about this. Most likely themes
with picture-backgournd will specify the whole area to be painted a
the background-picture.

Code:
com.sun.java.swing.plaf.gtk.Metacity.paintFrameBorder:

		    if (roundTopLeft || roundTopRight || roundBottomLeft || roundBottomRight)
		    { 	
                            ..............................................
		    }
                    Rectangle clipBound		    	jif.setOpaque(false);

	(roundBottomRight ? RoundRectClipShape.BOTTOM_RIGHT : 0)));s =
oldClip.getBounds();
                    g.clipRect(clipBounds.x, clipBounds.y,
                               clipBounds.width, clipBounds.height);

                    //Fix
                    g.setColor(jif.getBackground());
                    g.fillRect(0, 0, jif.getWidth(), jif.getHeight());

..............................................


I would be happy about feedback.

lg Clemens

PS: Thanks for open.sourcing Java :)



More information about the swing-dev mailing list