blob: 96d646517d46c500d00c5c907d536b1d1f17f55f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006 Sybase, Inc. and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Sybase, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.pagedesigner.css2.border;
import java.util.Arrays;
import org.eclipse.draw2d.AbstractBorder;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.jst.pagedesigner.css2.ICSSStyle;
import org.eclipse.jst.pagedesigner.css2.property.ICSSPropertyID;
import org.eclipse.jst.pagedesigner.editors.pagedesigner.MessageFormater;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Display;
/**
* @author mengbo
*/
public class CSSBorder extends AbstractBorder {
private static final String BODER_QUERY_TEMPLETE = "border-{0}-style"; //$NON-NLS-1$
private static final String COLOR_QUERY_TEMPLETE = "border-{0}-color"; //$NON-NLS-1$
private final ICSSStyle _style;
private final Rectangle _innerRect = new Rectangle();
/**
* @param style
*/
public CSSBorder(ICSSStyle style) {
this._style = style;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.draw2d.Border#getInsets(org.eclipse.draw2d.IFigure)
*/
public Insets getInsets(IFigure figure) {
return _style.getBorderInsets();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.draw2d.Border#paint(org.eclipse.draw2d.IFigure,
* org.eclipse.draw2d.Graphics, org.eclipse.draw2d.geometry.Insets)
*/
public void paint(IFigure figure, Graphics graphics, Insets insets) {
tempRect.setBounds(getPaintRectangle(figure, insets));
_innerRect.setBounds(tempRect);
_innerRect.crop(_style.getBorderInsets());
paintEdge(graphics, tempRect, _innerRect, ICSSStyle.LEFT);
paintEdge(graphics, tempRect, _innerRect, ICSSStyle.RIGHT);
paintEdge(graphics, tempRect, _innerRect, ICSSStyle.TOP);
paintEdge(graphics, tempRect, _innerRect, ICSSStyle.BOTTOM);
}
/**
* @param style
* @return
*/
private boolean shouldDraw(String style) {
return style != null && !ICSSPropertyID.VAL_NONE.equals(style)
&& !ICSSPropertyID.VAL_HIDDEN.equals(style);
}
/**
* Fetchs the color array used to draw the given edge under the given style
*
* @param graphics
* @param style
* @param edge
* @return
*/
private RGB[] getEdgeColors(Graphics graphics, String style, String edge) {
String property = MessageFormater.format(COLOR_QUERY_TEMPLETE, edge);
Object obj = _style.getStyleProperty(property);
if (obj instanceof RGB) {
return getCustomColors(graphics, style, edge, (RGB) obj);
} else if (obj instanceof Color) {
return getCustomColors(graphics, style, edge, ((Color) obj)
.getRGB());
} else {
return getDefaultColors(graphics, style, edge);
}
}
// TODO: needs refactoring
private RGB[] getDefaultColors(Graphics graphics, String style, String edge) {
if (ICSSPropertyID.VAL_OUTSET.equals(style)) {
if (ICSSStyle.TOP.equals(edge) || ICSSStyle.LEFT.equals(edge)) {
return new RGB[] { ColorConstants.button.getRGB(),
ColorConstants.buttonLightest.getRGB() };
}
return new RGB[] { ColorConstants.buttonDarkest.getRGB(),
ColorConstants.buttonDarker.getRGB() };
} else if (ICSSPropertyID.VAL_INSET.equals(style)) {
if (ICSSStyle.TOP.equals(edge) || ICSSStyle.LEFT.equals(edge)) {
return new RGB[] { ColorConstants.buttonDarker.getRGB(),
ColorConstants.buttonDarkest.getRGB() };
}
return new RGB[] { ColorConstants.buttonLightest.getRGB(),
ColorConstants.button.getRGB() };
} else if (ICSSPropertyID.VAL_TDBORDERSTYLE.equals(style)) {
if (ICSSStyle.TOP.equals(edge) || ICSSStyle.LEFT.equals(edge)) {
return new RGB[] { ColorConstants.buttonDarker.getRGB() };
}
return new RGB[] { ColorConstants.button.getRGB() };
} else if (ICSSPropertyID.VAL_RIDGE.equals(style)) {
if (ICSSStyle.TOP.equals(edge) || ICSSStyle.LEFT.equals(edge)) {
return new RGB[] { ColorConstants.button.getRGB(),
ColorConstants.buttonDarkest.getRGB() };
}
return new RGB[] { ColorConstants.buttonDarkest.getRGB(),
ColorConstants.button.getRGB() };
} else if (ICSSPropertyID.VAL_GROOVE.equals(style)) {
if (ICSSStyle.TOP.equals(edge) || ICSSStyle.LEFT.equals(edge)) {
return new RGB[] { ColorConstants.buttonDarker.getRGB(),
ColorConstants.buttonLightest.getRGB() };
}
return new RGB[] { ColorConstants.buttonLightest.getRGB(),
ColorConstants.buttonDarker.getRGB(), };
} else if (ICSSPropertyID.VAL_DOUBLE.equals(style)) {
return new RGB[] { ColorConstants.buttonDarkest.getRGB(),
graphics.getBackgroundColor().getRGB(),
ColorConstants.buttonDarkest.getRGB() };
} else if (ICSSPropertyID.VAL_SOLID.equals(style)) {
return new RGB[] { ColorConstants.black.getRGB() };
}
return new RGB[] { ColorConstants.black.getRGB() };
}
// TODO: needs refactoring
private RGB[] getCustomColors(Graphics graphics, String style, String edge,
RGB baseColor) {
if (ICSSPropertyID.VAL_OUTSET.equals(style)) {
if (ICSSStyle.TOP.equals(edge) || ICSSStyle.LEFT.equals(edge)) {
return new RGB[] {
new RGB(baseColor.red * 3 / 4,
baseColor.green * 3 / 4,
baseColor.blue * 3 / 4),
new RGB(baseColor.red, baseColor.green, baseColor.blue) };
}
return new RGB[] {
new RGB(baseColor.red / 2,
baseColor.green / 2,
baseColor.blue / 2),
new RGB(baseColor.red / 4,
baseColor.green / 4,
baseColor.blue / 4) };
} else if (ICSSPropertyID.VAL_INSET.equals(style)) {
if (ICSSStyle.TOP.equals(edge) || ICSSStyle.LEFT.equals(edge)) {
return new RGB[] {
new RGB(baseColor.red / 4,
baseColor.green / 4,
baseColor.blue / 4),
new RGB(baseColor.red / 2,
baseColor.green / 2,
baseColor.blue / 2) };
}
return new RGB[] {
new RGB(baseColor.red, baseColor.green, baseColor.blue),
new RGB(baseColor.red * 3 / 4,
baseColor.green * 3 / 4,
baseColor.blue * 3 / 4), };
} else if (ICSSPropertyID.VAL_TDBORDERSTYLE.equals(style)) {
if (ICSSStyle.TOP.equals(edge) || ICSSStyle.LEFT.equals(edge)) {
return new RGB[] { new RGB(baseColor.red / 4,
baseColor.green / 4, baseColor.blue / 4) };
}
return new RGB[] { new RGB(baseColor.red, baseColor.green,
baseColor.blue) };
} else if (ICSSPropertyID.VAL_RIDGE.equals(style)) {
if (ICSSStyle.TOP.equals(edge) || ICSSStyle.LEFT.equals(edge)) {
return new RGB[] {
new RGB(baseColor.red * 3 / 4,
baseColor.green * 3 / 4,
baseColor.blue * 3 / 4),
new RGB(baseColor.red / 2,
baseColor.green / 2,
baseColor.blue / 2) };
}
return new RGB[] {
new RGB(baseColor.red / 2,
baseColor.green / 2,
baseColor.blue / 2),
new RGB(baseColor.red * 3 / 4,
baseColor.green * 3 / 4,
baseColor.blue * 3 / 4) };
} else if (ICSSPropertyID.VAL_GROOVE.equals(style)) {
if (ICSSStyle.TOP.equals(edge) || ICSSStyle.LEFT.equals(edge)) {
return new RGB[] {
new RGB(baseColor.red / 4,
baseColor.green / 4,
baseColor.blue / 4),
new RGB(baseColor.red, baseColor.green, baseColor.blue) };
}
return new RGB[] {
new RGB(baseColor.red, baseColor.green, baseColor.blue),
new RGB(baseColor.red / 4,
baseColor.green / 4,
baseColor.blue / 4) };
} else if (ICSSPropertyID.VAL_DOUBLE.equals(style)) {
return new RGB[] {
new RGB(baseColor.red, baseColor.green, baseColor.blue),
graphics.getBackgroundColor().getRGB(),
new RGB(baseColor.red, baseColor.green, baseColor.blue) };
} else if (ICSSPropertyID.VAL_SOLID.equals(style)) {
return new RGB[] { new RGB(baseColor.red, baseColor.green,
baseColor.blue) };
}
return new RGB[] { new RGB(baseColor.red, baseColor.green,
baseColor.blue) };
}
/**
* @param graphics
* @param rect
* @param innerRect
* @param edge
* @param style
*/
public void paintEdge(Graphics graphics, Rectangle rect,
Rectangle innerRect, String edge, String style) {
if (!shouldDraw(style)) {
return;
}
RGB[] rgbs = getEdgeColors(graphics, style, edge);
if (ICSSStyle.TOP.equals(edge)) {
paintTopEdge(graphics, rgbs, style, rect, innerRect);
} else if (ICSSStyle.BOTTOM.equals(edge)) {
paintBottomEdge(graphics, rgbs, style, rect, innerRect);
} else if (ICSSStyle.LEFT.equals(edge)) {
paintLeftEdge(graphics, rgbs, style, rect, innerRect);
} else if (ICSSStyle.RIGHT.equals(edge)) {
paintRightEdge(graphics, rgbs, style, rect, innerRect);
}
}
/**
* @param graphics
* @param rect
* @param innerRect
* @param edge
*/
protected void paintEdge(Graphics graphics, Rectangle rect,
Rectangle innerRect, String edge) {
String property = MessageFormater.format(BODER_QUERY_TEMPLETE, edge);
Object obj = _style.getStyleProperty(property);
String style = obj.toString();
paintEdge(graphics, rect, innerRect, edge, style);
}
private void paintTopEdge(Graphics graphics, RGB[] rgbs, String style,
Rectangle rect, Rectangle innerRect) {
int leftX = rect.x;
int rightX = rect.right() - 1;
int y = rect.y;
int width = innerRect.y - rect.y;
if (ICSSPropertyID.VAL_DOTTED.equals(style)) {
drawDottedBorder(graphics, rgbs, ICSSStyle.TOP, rect, width);
} else if (ICSSPropertyID.VAL_DASHED.equals(style)) {
drawDashedBorder(graphics, rgbs, ICSSStyle.TOP, rect, width);
} else {
double xLeftRate = ((double) (innerRect.x - rect.x)) / width;
double xRightRate = ((double) (rect.right() - innerRect.right()))
/ width;
graphics.pushState();
for (int i = 0; i < width; i++) {
Color color = new Color(Display.getCurrent(), rgbs[rgbs.length
* i / width]);
graphics.setForegroundColor(color);
graphics.drawLine((int) (leftX + i * xLeftRate), y + i,
(int) (rightX - i * xRightRate), y + i);
color.dispose();
}
graphics.popState();
}
}
private void paintBottomEdge(Graphics graphics, RGB[] rgbs, String style,
Rectangle rect, Rectangle innerRect) {
int leftX = rect.x;
int rightX = rect.right() - 1;
int y = rect.bottom() - 1;
int width = rect.bottom() - innerRect.bottom();
if (ICSSPropertyID.VAL_DOTTED.equals(style)) {
drawDottedBorder(graphics, rgbs, ICSSStyle.BOTTOM, rect, width);
} else if (ICSSPropertyID.VAL_DASHED.equals(style)) {
drawDashedBorder(graphics, rgbs, ICSSStyle.BOTTOM, rect, width);
} else {
double xLeftRate = ((double) (innerRect.x - rect.x)) / width;
double xRightRate = ((double) (rect.right() - innerRect.right()))
/ width;
graphics.pushState();
for (int i = 0; i < width; i++) {
Color color = new Color(Display.getCurrent(), rgbs[rgbs.length
* i / width]);
graphics.setForegroundColor(color);
graphics.drawLine(leftX + (int) (i * xLeftRate), y - i, rightX
- (int) (i * xRightRate), y - i);
color.dispose();
}
graphics.popState();
}
}
private void paintLeftEdge(Graphics graphics, RGB[] rgbs, String style,
Rectangle rect, Rectangle innerRect) {
int x = rect.x;
int topY = rect.y;
int bottomY = rect.bottom() - 1;
int width = innerRect.x - rect.x;
if (ICSSPropertyID.VAL_DOTTED.equals(style)) {
drawDottedBorder(graphics, rgbs, ICSSStyle.LEFT, rect, width);
} else if (ICSSPropertyID.VAL_DASHED.equals(style)) {
drawDashedBorder(graphics, rgbs, ICSSStyle.LEFT, rect, width);
} else {
double yTopRate = ((double) (innerRect.y - rect.y)) / width;
double yBottomRate = ((double) (rect.bottom() - innerRect.bottom()))
/ width;
graphics.pushState();
for (int i = 0; i < width; i++) {
Color color = new Color(Display.getCurrent(), rgbs[rgbs.length
* i / width]);
graphics.setForegroundColor(color);
graphics.drawLine(x + i, topY + (int) (i * yTopRate), x + i,
bottomY - (int) (i * yBottomRate));
color.dispose();
}
graphics.popState();
}
}
private void paintRightEdge(Graphics graphics, RGB[] rgbs, String style,
Rectangle rect, Rectangle innerRect) {
int x = rect.right() - 1;
int topY = rect.y;
int bottomY = rect.bottom() - 1;
int width = rect.right() - innerRect.right();
if (ICSSPropertyID.VAL_DOTTED.equals(style)) {
drawDottedBorder(graphics, rgbs, ICSSStyle.RIGHT, rect, width);
} else if (ICSSPropertyID.VAL_DASHED.equals(style)) {
drawDashedBorder(graphics, rgbs, ICSSStyle.RIGHT, rect, width);
} else {
graphics.pushState();
for (int i = 0; i < width; i++) {
double yTopRate = ((double) (innerRect.y - rect.y)) / width;
double yBottomRate = ((double) (rect.bottom() - innerRect
.bottom()))
/ width;
Color color = new Color(Display.getCurrent(), rgbs[rgbs.length
* i / width]);
graphics.setForegroundColor(color);
graphics.drawLine(x - i, topY + (int) (i * yTopRate), x - i,
bottomY - (int) (i * yBottomRate));
color.dispose();
}
graphics.popState();
}
}
private void drawDottedBorder(Graphics graphics, RGB[] rgbs, String style,
Rectangle rect, int width) {
if (width == 0 || 3 * width > rect.width) {
return;
}
int beginX = 0;
int beginY = 0;
int xRate = 0;
int yRate = 0;
int span = 0;
if (ICSSStyle.TOP.equals(style)) {
beginX = rect.x;
beginY = rect.y;
xRate = 1;
yRate = 0;
span = rect.width;
} else if (ICSSStyle.LEFT.equals(style)) {
beginX = rect.x;
beginY = rect.y;
xRate = 0;
yRate = 1;
span = rect.height;
} else if (ICSSStyle.BOTTOM.equals(style)) {
beginX = rect.x;
beginY = rect.y + rect.height - width;
xRate = 1;
yRate = 0;
span = rect.width;
} else if (ICSSStyle.RIGHT.equals(style)) {
beginX = rect.x + rect.width - width;
beginY = rect.y;
xRate = 0;
yRate = 1;
span = rect.height;
}
int dottedCount = (span + width) / (2 * width);
if (dottedCount < 2) {
dottedCount = 2;
}
int averagePad = (span - dottedCount * width) / (dottedCount - 1);
int leftPad = (span - dottedCount * width) % (dottedCount - 1);
int[] paddings = new int[dottedCount - 1];
Arrays.fill(paddings, averagePad);
for (int i = 0; i < leftPad; i++) {
paddings[i] = paddings[i] + 1;
}
int pad = 0;
Color color = new Color(Display.getCurrent(), rgbs[0]);
graphics.pushState();
graphics.setBackgroundColor(color);
for (int i = 0; i < dottedCount; i++) {
graphics.fillOval(beginX + (pad + width * i) * xRate, beginY
+ (pad + width * i) * yRate, width, width);
if (i != dottedCount - 1) {
pad += paddings[i];
}
}
graphics.popState();
color.dispose();
}
private void drawDashedBorder(Graphics graphics, RGB[] rgbs, String style,
Rectangle rect, int borderThick) {
if (borderThick == 0 || 5 * borderThick > rect.width) {
return;
}
if ((5 * borderThick > rect.height)
&& (ICSSStyle.LEFT.equals(style) || ICSSStyle.RIGHT
.equals(style))) {
return;
}
int width = 0;
int height = 0;
int edgeLength = 0;
int beginX = 0;
int beginY = 0;
int xRate = 0;
int yRate = 0;
int span = 0;
if (ICSSStyle.TOP.equals(style)) {
width = borderThick * 2;
height = borderThick;
beginX = rect.x;
beginY = rect.y;
xRate = 1;
yRate = 0;
span = rect.width;
edgeLength = width;
} else if (ICSSStyle.LEFT.equals(style)) {
width = borderThick;
height = borderThick * 2;
beginX = rect.x;
beginY = rect.y;
xRate = 0;
yRate = 1;
span = rect.height;
edgeLength = height;
} else if (ICSSStyle.BOTTOM.equals(style)) {
width = borderThick * 2;
height = borderThick;
beginX = rect.x;
beginY = rect.y + rect.height - height;
xRate = 1;
yRate = 0;
span = rect.width;
edgeLength = width;
} else if (ICSSStyle.RIGHT.equals(style)) {
width = borderThick;
height = borderThick * 2;
beginX = rect.x + rect.width - width;
beginY = rect.y;
xRate = 0;
yRate = 1;
span = rect.height;
edgeLength = height;
}
int dottedCount = (span + borderThick) / (edgeLength + borderThick);
if (dottedCount < 2) {
dottedCount = 2;
}
int averagePad = (span - dottedCount * edgeLength) / (dottedCount - 1);
int leftPad = (span - dottedCount * edgeLength) % (dottedCount - 1);
int[] paddings = new int[dottedCount - 1];
Arrays.fill(paddings, averagePad);
for (int i = 0; i < leftPad; i++) {
paddings[i] = paddings[i] + 1;
}
int pad = 0;
graphics.pushState();
Color color = new Color(Display.getCurrent(), rgbs[0]);
graphics.setBackgroundColor(color);
for (int i = 0; i < dottedCount; i++) {
graphics.fillRectangle(beginX + (pad + width * i) * xRate, beginY
+ (pad + height * i) * yRate, width, height);
if (i != dottedCount - 1) {
pad += paddings[i];
}
}
graphics.popState();
color.dispose();
}
}