/***************************************************************************
* Copyright 2001-2009 The VietSpider All rights reserved. *
**************************************************************************/
package org.sf.feeling.swt.win32.extension.widgets;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Pattern;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.vietspider.generic.ColorCache;
/**
* Author : Nhu Dinh Thuan
* nhudinhthuan@yahoo.com
* Jul 6, 2009
*/
public class CCheckBox extends CAbstractButton {
private static final int SUBMENUWIDTH = 11;
private static final int HORIZON_MARGIN = 5, VERTICAL_MARGIN = 2;
private static final int DRAW_FLAGS = SWT.DRAW_TAB | SWT.DRAW_TRANSPARENT | SWT.DRAW_DELIMITER;
public static final int STATE_NONE = 0;
public static final int STATE_HOVER = 1;
public static final int STATE_SELECTED = 2;
public static final int STATE_HOVER_AND_SELECTED = 3;
//TEXT
protected Color mTextColor = ColorCache.getInstance().getColor(0, 50, 100);
//ColorCache.getInstance().getColor(21, 66, 139);
// disabled text
protected Color mTextColor_Disabled = ColorCache.getInstance().getColor(165, 141, 159);
//disabled
private Color mCheckBoxBorderOuterSquareTopLeft_Disabled = ColorCache.getInstance().getColor(224, 226, 229);
private Color mCheckBoxBorderOuterSquareBottomRight_Disabled = ColorCache.getInstance().getColor(242, 243, 243);
private Color mCheckBoxBorderInnerSquareTopLeft_Disabled = ColorCache.getInstance().getColor(238, 240, 242);
private Color mCheckBoxBorderInnerSquareBottomRight_Disabled = ColorCache.getInstance().getColor(251, 251, 251);
// normal
private Color mCheckBoxBorderOuterSquareTopLeft_Normal = ColorCache.getInstance().getColor(162, 172, 185);
private Color mCheckBoxBorderOuterSquareBottomRight_Normal = ColorCache.getInstance().getColor(228, 230, 234);
private Color mCheckBoxBorderInnerSquareTopLeft_Normal = ColorCache.getInstance().getColor(202, 207, 213);
private Color mCheckBoxBorderInnerSquareBottomRight_Normal = ColorCache.getInstance().getColor(246, 246, 246);
//hover
private Color mCheckBoxBorderOuterSquareTopLeft_Hover = ColorCache.getInstance().getColor(250, 213, 122);
private Color mCheckBoxBorderOuterSquareBottomRight_Hover = ColorCache.getInstance().getColor(253, 241, 207);
private Color mCheckBoxBorderInnerSquareTopLeft_Hover = ColorCache.getInstance().getColor(252, 231, 175);
private Color mCheckBoxBorderInnerSquareBottomRight_Hover = ColorCache.getInstance().getColor(254, 248, 231);
private Color mCheckBoxBorderOuter_Normal = ColorCache.getInstance().getColor(171, 193, 222);
private Color mCheckBoxBorderInner_Normal = ColorCache.getInstance().getColor(244, 244, 244);
private Color mCheckBoxBorderOuter_Hover= ColorCache.getInstance().getColor(85, 119, 163);
private Color mCheckBoxBorderInner_Hover = ColorCache.getInstance().getColor(222, 234, 250);
private Color mCheckBoxBorderOuter_Disabled = ColorCache.getInstance().getColor(174, 177, 181);
private Color mCheckBoxBorderInner_Disabled = ColorCache.getInstance().getColor(255, 255, 255);
// actual check mark
private Color mCheckBoxCheckmarkDark = ColorCache.getInstance().getColor(78, 108, 141);
private Color mCheckBoxCheckmarkDark2 = ColorCache.getInstance().getColor(102, 126, 149);
private Color mCheckBoxCheckmarkDark3 = ColorCache.getInstance().getColor(142, 163, 189);
private Color mCheckBoxCheckmarkDark4 = ColorCache.getInstance().getColor(178, 190, 204);
private Color mCheckBoxCheckmarkLight = ColorCache.getInstance().getColor(230, 229, 222);
private Color mCheckBoxCheckmarkLight2 = ColorCache.getInstance().getColor(213, 215, 209);
private Color mCheckBoxCheckmarkLight3 = ColorCache.getInstance().getColor(253, 249, 245);
public CCheckBox(Composite parent) {
super(parent, SWT.NONE);
// button = new Canvas(parent, SWT.NONE) {
// @SuppressWarnings("unused")
// public Point computeSize(int wHint, int hHint, boolean changed) {
// checkWidget();
// Point size = recalculate();
// int width = size.x;
// int height = size.y;
// if (wHint != SWT.DEFAULT) width = wHint;
// if (hHint != SWT.DEFAULT) height = hHint;
// int border = getBorderWidth();
// width += border * 2;
// height += border * 2;
// return new Point(width, height);
// }
// };
addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {
onPaint(e);
}
});
addMouseListener(new MouseAdapter() {
@SuppressWarnings("unused")
public void mouseUp(MouseEvent e) {
if (isEnabled()) {
Event event = new Event();
event.widget = CCheckBox.this;
event.data = this;
event.type = SWT.SELECTED;
fireSelectionEvent(event);
Display.getDefault().asyncExec(new Runnable() {
public void run() {
redraw();
}
});
selection = !selection;
redraw();
}
}
});
}
private Point recalculate() {
GC gc = new GC(this);
int BREADTH_GAP = (gc.getFontMetrics().getHeight() / 3) + 1;
int rowHeight = gc.getFontMetrics().getHeight() + BREADTH_GAP * 2 + BREADTH_GAP/2;
if ((style & SWT.TOP) != 0 || (style & SWT.BOTTOM) != 0) {
if (image != null) rowHeight += image.getImageData().height;
rowHeight += 2 * VERTICAL_MARGIN;
} else {
if (image != null) rowHeight =
(image.getImageData().height > rowHeight ? image.getImageData().height : rowHeight);
}
int cellLength = 0;
int cellMinLength = HORIZON_MARGIN * 3;// + HORIZON_MARGIN/2;
if (getText() == null) {
cellLength = cellMinLength;
if (image != null) cellLength += image.getImageData().width;
} else if (image == null) {
cellLength = cellMinLength + gc.textExtent(getText(), DRAW_FLAGS).x*2;
} else {
if ((style & SWT.TOP) == 0 && (style & SWT.BOTTOM) == 0) {
cellLength = cellMinLength + gc.textExtent(getText(), DRAW_FLAGS).x* 2 + HORIZON_MARGIN;
if (image != null) cellLength += image.getImageData().width;
} else {
cellLength = gc.textExtent(getText(), DRAW_FLAGS).x * 2;
if (image != null) {
cellLength = cellLength < image.getImageData().width ? image.getImageData().width : cellLength;
} else {
cellLength = cellLength < image.getImageData().width ? image.getImageData().width : cellLength;
}
cellLength += (cellMinLength);
}
}
if (getMenu() != null) cellLength += SUBMENUWIDTH;
gc.dispose();
return new Point(cellLength, rowHeight);
}
private void onPaint(PaintEvent e) {
GC gc = e.gc;
if(font != null) gc.setFont(font);
Rectangle bounds = getBounds();
System.out.println(bounds.y + " / "+ bounds.height);
// bounds.x = 0;
int x = bounds.x;
int y = bounds.y;
int cbWidth = 12;
int cbHeight = 12;
if (getSelection()) {
gc.setForeground(mCheckBoxBorderOuter_Normal);
} else {
gc.setForeground(mCheckBoxBorderOuter_Hover);
}
if (!isEnabled()) gc.setForeground(mCheckBoxBorderOuter_Disabled);
gc.drawRectangle(x, y, cbWidth, cbHeight);
if (getSelection()) {
gc.setForeground(mCheckBoxBorderInner_Normal);
} else {
gc.setForeground(mCheckBoxBorderInner_Hover);
}
if (!isEnabled()) gc.setForeground(mCheckBoxBorderInner_Disabled);
gc.drawRectangle(x+1, y+1, cbWidth-2, cbHeight-2);
Color outerTopLeft = null;
Color outerBottomRight = null;
Color innerTopLeft = null;
Color innerBottomRight = null;
if(getSelection()) {
outerTopLeft = mCheckBoxBorderOuterSquareTopLeft_Normal;
outerBottomRight = mCheckBoxBorderOuterSquareBottomRight_Normal;
innerTopLeft = mCheckBoxBorderInnerSquareTopLeft_Normal;
innerBottomRight = mCheckBoxBorderInnerSquareBottomRight_Normal;
} else {
outerTopLeft = mCheckBoxBorderOuterSquareTopLeft_Hover;
outerBottomRight = mCheckBoxBorderOuterSquareBottomRight_Hover;
innerTopLeft = mCheckBoxBorderInnerSquareTopLeft_Hover;
innerBottomRight = mCheckBoxBorderInnerSquareBottomRight_Hover;
}
if (!isEnabled()) {
outerTopLeft = mCheckBoxBorderOuterSquareTopLeft_Disabled;
outerBottomRight = mCheckBoxBorderOuterSquareBottomRight_Disabled;
innerTopLeft = mCheckBoxBorderInnerSquareTopLeft_Disabled;
innerBottomRight = mCheckBoxBorderInnerSquareBottomRight_Disabled;
}
Pattern p = new Pattern(gc.getDevice(), bounds.x+2, bounds.y+2, bounds.x+2+9, bounds.y+2+9, outerTopLeft, outerBottomRight);
gc.setForegroundPattern(p);
gc.setBackgroundPattern(p);
gc.fillRectangle(new Rectangle(bounds.x+2, bounds.y+2, 9, 9));
Pattern p2 = new Pattern(gc.getDevice(), bounds.x+3, bounds.y+3, bounds.x+3+7, bounds.y+3+7, innerTopLeft, innerBottomRight);
gc.setForegroundPattern(p2);
gc.setBackgroundPattern(p2);
gc.fillRectangle(new Rectangle(bounds.x+3, bounds.y+3, 7, 7));
gc.setForeground(mTextColor);
if (!isEnabled()) {
gc.setForeground(mTextColor_Disabled);
}
if (getText() != null) {
gc.drawString(getText(), x+13+6, y-1, true);
}
p.dispose();
p2.dispose();
gc.setForegroundPattern(null);
gc.setBackgroundPattern(null);
// force GC back to normal! 1x1 px drawing does not work otherwise (see bug #199658 I filed against this problem)
gc.setAdvanced(false);
// draw check mark
if (!getSelection()) return;
// center bottom 4px square
gc.setForeground(mCheckBoxCheckmarkDark);
gc.setBackground(mCheckBoxCheckmarkDark);
gc.fillRectangle(x+5, y+8, 2, 2);
// dark color on left of square, 2 pixels up
gc.drawLine(x+4, y+7, x+4, y+7+1);
// other side, similar but not-connected to square, corner to corner only
gc.drawLine(x+7, y+6, x+7, y+6+1);
// same deal again, top right of the above
gc.drawLine(x+8, y+4, x+8, y+4+1);
// and again, just 1px
gc.drawLine(x+9, y+3, x+9, y+3);
// bottom uses slightly lighter colors
gc.setForeground(mCheckBoxCheckmarkDark3);
// very bottom left
gc.drawLine(x+4, y+9, x+4, y+9);
// bottom bottom, 2px wide
gc.drawLine(x+5, y+10, x+6, y+10);
// top
gc.drawLine(x+4, y+6, x+4, y+6);
// next darkness level, slightly lighter
gc.setForeground(mCheckBoxCheckmarkDark2);
gc.drawLine(x+9, y+2, x+9, y+2);
// lets start from the top and go down
// left of the last 1px pixel
gc.drawLine(x+8, y+3, x+8, y+3);
// and below that same px
gc.drawLine(x+9, y+4, x+9, y+4);
// similar pattern a bit down
gc.drawLine(x+7, y+5, x+7, y+5);
gc.drawLine(x+8, y+6, x+8, y+6);
// and again
gc.drawLine(x+6, y+7, x+6, y+7);
gc.drawLine(x+7, y+8, x+7, y+8);
// and one on the left side
gc.drawLine(x+3, y+7, x+3, y+7);
// and lighter still
gc.setForeground(mCheckBoxCheckmarkDark4);
// start at top again
// top right
gc.drawLine(x+10, y+3, x+10, y+3);
// left and down 1
gc.drawLine(x+7, y+4, x+7, y+4);
// right and down 1
gc.drawLine(x+9, y+5, x+9, y+5);
// left and down 1
gc.drawLine(x+6, y+6, x+6, y+6);
// right and down 1
gc.drawLine(x+8, y+7, x+8, y+7);
// and farthest down
gc.drawLine(x+7, y+9, x+7, y+9);
// lighter colors
gc.setForeground(mCheckBoxCheckmarkLight);
// left side
gc.drawLine(x+3, y+8, x+3, y+8);
// bit further right
gc.drawLine(x+5, y+7, x+5, y+7);
// lighter yet, outer corner of the v-part
gc.setForeground(mCheckBoxCheckmarkLight2);
gc.drawLine(x+3, y+6, x+3, y+6);
// TODO: fill in more colors? it's hardly visible to the eye the difference at this point
// white colors, make it stand out
gc.setForeground(mCheckBoxCheckmarkLight3);
gc.drawLine(x+8, y+8, x+8, y+8);
}
@SuppressWarnings("unused")
public Point computeSize(int wHint, int hHint, boolean changed) {
return computeSize(wHint, hHint);
}
public Point computeSize(int wHint, int hHint) {
checkWidget();
Point size = recalculate();
int width = size.x;
int height = size.y;
if (wHint != SWT.DEFAULT) width = wHint;
if (hHint != SWT.DEFAULT) height = hHint;
int border = getBorderWidth();
width += border * 2;
height += border * 2;
return new Point(width, height);
}
}