| /******************************************************************************* |
| * 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"; |
| |
| private static final String COLOR_QUERY_TEMPLETE = "border-{0}-color"; |
| |
| private ICSSStyle _style; |
| |
| protected Rectangle _innerRect = new Rectangle(); |
| |
| 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) }; |
| } |
| |
| 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); |
| } |
| } |
| |
| 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(); |
| } |
| |
| } |