package glass.eclipse.theme;
import java.awt.*;
import java.awt.geom.*;
import javax.swing.border.*;
import bibliothek.extension.gui.dock.theme.eclipse.rex.*;
import bibliothek.extension.gui.dock.theme.eclipse.stack.tab.*;
import bibliothek.gui.*;
import bibliothek.gui.dock.station.stack.tab.layouting.*;
import bibliothek.gui.dock.util.color.*;
/**
* A border that has round edges.
* @author Thomas Hilbert
*/
@ColorCodes("stack.border.glass")
public class CEclipseBorder implements Border {
/** constant indicating the top left edge has to be painted round */
public static final int TOP_LEFT = 1;
/** constant indicating the top right edge has to be painted round */
public static final int TOP_RIGHT = 2;
/** constant indicating the bottom left edge has to be painted round */
public static final int BOTTOM_LEFT = 4;
/** constant indicating the bottom right edge has to be painted round */
public static final int BOTTOM_RIGHT = 8;
/** which edges to paint round */
private int roundEdges;
private DockController controller;
protected BorderedComponent owner;
protected int iCornerRadius = 5;
/**
* Creates a new border
* @param controller the owner of this border
* @param cornerRadius The radius of the round edges.
* @param owner The owner component.
* @param roundEdges Edge mask.
*/
public CEclipseBorder (DockController controller, int cornerRadius, BorderedComponent owner, int roundEdges) {
this(controller, cornerRadius, roundEdges);
if (owner == null) {
throw new IllegalArgumentException("owner must not be null");
}
this.owner = owner;
}
/**
* Creates a new border
* @param controller the owner of this border
* @param fillEdges whether to paint over the edges
* @param edges the edges that are painted round, or-ed from {@link #TOP_LEFT},
* {@link #TOP_RIGHT}, {@link #BOTTOM_LEFT} and {@link #BOTTOM_RIGHT}
*/
public CEclipseBorder (DockController controller, int cornerRadius, int edges) {
this.controller = controller;
roundEdges = edges;
iCornerRadius = cornerRadius;
}
/**
* Updates the edge mask for the specified placement.
* @param tabPlacement
*/
public void update4Placement (TabPlacement tabPlacement) {
switch (tabPlacement) {
case TOP_OF_DOCKABLE:
roundEdges = (CEclipseBorder.TOP_LEFT | CEclipseBorder.TOP_RIGHT);
break;
case BOTTOM_OF_DOCKABLE:
roundEdges = (CEclipseBorder.BOTTOM_LEFT | CEclipseBorder.BOTTOM_RIGHT);
break;
case LEFT_OF_DOCKABLE:
roundEdges = (CEclipseBorder.BOTTOM_LEFT | CEclipseBorder.TOP_LEFT);
break;
case RIGHT_OF_DOCKABLE:
roundEdges = (CEclipseBorder.BOTTOM_RIGHT | CEclipseBorder.TOP_RIGHT);
break;
}
}
/**
* Sets which edges are painted round.
* @param roundEdges the edges to paint round
*/
public void setRoundEdges (int roundEdges) {
this.roundEdges = roundEdges;
}
/**
* Tells which edges are painted round.
* @return the round edges
*/
public int getRoundEdges () {
return roundEdges;
}
public void setCornerRadius (int radius) {
iCornerRadius = radius;
}
public int getCornerRadius () {
return (iCornerRadius);
}
public static Path2D CreateBorderShape (int x, int y, int w, int h, int roundEdges, int cornerRadius) {
Path2D p = new Path2D.Float();
if ((roundEdges & TOP_LEFT) != 0) {
p.moveTo(x, y + cornerRadius);
p.quadTo(x, y, x + cornerRadius, y);
}
else {
p.moveTo(x, y);
}
if ((roundEdges & TOP_RIGHT) != 0) {
p.lineTo(x + w - 1 - cornerRadius, y);
p.quadTo(x + w - 1, y, x + w - 1, y + cornerRadius);
}
else {
p.lineTo(x + w - 1, y);
}
if ((roundEdges & BOTTOM_RIGHT) != 0) {
p.lineTo(x + w - 1, y + h - 1 - cornerRadius);
p.quadTo(x + w - 1, y + h - 1, x + w - 1 - cornerRadius, y + h - 1);
}
else {
p.lineTo(x + w - 1, y + h - 1);
}
if ((roundEdges & BOTTOM_LEFT) != 0) {
p.lineTo(x + cornerRadius, y + h - 1);
p.quadTo(x, y + h - 1, x, y + h - 1 - cornerRadius);
}
else {
p.lineTo(x, y + h - 1);
}
p.closePath();
return (p);
}
protected static boolean isSet (int mask, int bit) {
return ((mask & bit) == bit);
}
public static int ShiftEdgeMask (int srcMask, boolean CCW) {
int iMask = 0;
if (CCW) {
iMask |= isSet(srcMask, TOP_RIGHT) ? TOP_LEFT : 0;
iMask |= isSet(srcMask, TOP_LEFT) ? BOTTOM_LEFT : 0;
iMask |= isSet(srcMask, BOTTOM_LEFT) ? BOTTOM_RIGHT : 0;
iMask |= isSet(srcMask, BOTTOM_RIGHT) ? TOP_RIGHT : 0;
}
else {
iMask |= isSet(srcMask, TOP_RIGHT) ? BOTTOM_RIGHT : 0;
iMask |= isSet(srcMask, BOTTOM_RIGHT) ? BOTTOM_LEFT : 0;
iMask |= isSet(srcMask, BOTTOM_LEFT) ? TOP_LEFT : 0;
iMask |= isSet(srcMask, TOP_LEFT) ? TOP_RIGHT : 0;
}
return (iMask);
}
protected Path2D createShape (int x, int y, int w, int h, int cornerRadius) {
return (CreateBorderShape(x, y, w, h, roundEdges, cornerRadius));
}
public void paintBorder (Component c, Graphics g, int x, int y, int width, int height) {
Color color = controller.getColors().get("stack.border.glass");
if (color == null) {
color = RexSystemColor.getBorderColor();
}
Graphics2D g2d = (Graphics2D)g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(color);
Shape s = createShape(x, y, width, height, getCornerRadius());
g2d.draw(s);
g2d.dispose();
}
public Insets getBorderInsets (Component c) {
return new Insets(1, 1, 1, 1);
}
public boolean isBorderOpaque () {
return false;
}
}