1/*******************************************************************************
2 * Copyright (c) 2011 Google, Inc.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 *    Google, Inc. - initial API and implementation
10 *******************************************************************************/
11package org.eclipse.wb.core.controls;
12
13import org.eclipse.wb.draw2d.IColorConstants;
14import org.eclipse.wb.internal.core.utils.ui.DrawUtils;
15
16import org.eclipse.swt.SWT;
17import org.eclipse.swt.events.PaintEvent;
18import org.eclipse.swt.events.PaintListener;
19import org.eclipse.swt.graphics.Color;
20import org.eclipse.swt.graphics.GC;
21import org.eclipse.swt.graphics.Image;
22import org.eclipse.swt.graphics.Rectangle;
23import org.eclipse.swt.widgets.Canvas;
24import org.eclipse.swt.widgets.Composite;
25import org.eclipse.swt.widgets.Event;
26import org.eclipse.swt.widgets.Listener;
27
28/**
29 * Class representing flat push button as it looks in Mac OSX.
30 *
31 * It doesn't draw text, not need for now. ;-)
32 *
33 * @author mitin_aa
34 */
35public final class CFlatButton extends Canvas {
36  // colors
37  private static final Color COLOR_FACE = DrawUtils.getShiftedColor(IColorConstants.button, 12);
38  private static final Color COLOR_FACE_SELECTED = IColorConstants.buttonDarker;
39  private static final Color COLOR_BORDER_GRADIENT1 = DrawUtils.getShiftedColor(
40      IColorConstants.button,
41      -12);
42  private static final Color COLOR_BORDER_GRADIENT1_SELECTED = DrawUtils.getShiftedColor(
43      IColorConstants.buttonDarker,
44      64);
45  private static final Color COLOR_BORDER_GRADIENT2 = DrawUtils.getShiftedColor(COLOR_FACE, -8);
46  private static final Color COLOR_BORDER_GRADIENT2_SELECTED = DrawUtils.getShiftedColor(
47      COLOR_FACE_SELECTED,
48      -8);
49  // fields
50  private Image m_image;
51  private boolean m_down;
52  private boolean m_selected;
53
54  ////////////////////////////////////////////////////////////////////////////
55  //
56  // Constructor
57  //
58  ////////////////////////////////////////////////////////////////////////////
59  public CFlatButton(Composite parent, int style) {
60    super(parent, style);
61    addPaintListener(new PaintListener() {
62      public void paintControl(PaintEvent e) {
63        boolean isSelected = m_down | m_selected;
64        Color faceColor = isSelected ? COLOR_FACE_SELECTED : COLOR_FACE;
65        Color borderGradientColor1 =
66            isSelected ? COLOR_BORDER_GRADIENT1_SELECTED : COLOR_BORDER_GRADIENT1;
67        Color borderGradientColor2 =
68            isSelected ? COLOR_BORDER_GRADIENT2_SELECTED : COLOR_BORDER_GRADIENT2;
69        GC gc = e.gc;
70        Rectangle ca = getClientArea();
71        // draw client area
72        // dark border
73        gc.setForeground(IColorConstants.buttonDarker);
74        gc.drawRectangle(ca.x, ca.y, ca.width - 1, ca.height - 1);
75        cropClientArea(ca);
76        // gradient border
77        gc.setForeground(borderGradientColor1);
78        gc.setBackground(borderGradientColor2);
79        gc.fillGradientRectangle(ca.x, ca.y, ca.width, ca.height, true);
80        cropClientArea(ca);
81        // fill background
82        gc.setBackground(faceColor);
83        gc.fillRectangle(ca);
84        // draw face upper-half gradient
85        Rectangle ca1 = getClientArea();
86        cropClientArea(ca1);
87        gc.setForeground(faceColor);
88        gc.setBackground(borderGradientColor1);
89        gc.fillGradientRectangle(ca1.x, ca1.y, ca1.width, ca1.height / 4, true);
90        // draw face down-half gradient
91        ca1.x += 1;
92        ca1.width -= 2;
93        gc.setForeground(borderGradientColor1);
94        gc.setBackground(faceColor);
95        gc.fillGradientRectangle(ca1.x, ca1.y + ca1.height / 4 - 1, ca1.width, ca1.height / 2, true);
96        // draw image
97        Image image = getImage();
98        if (image != null) {
99          Rectangle imageBounds = image.getBounds();
100          // center it in client area
101          int x = ca.x + (ca.width - imageBounds.width) / 2;
102          int y = ca.y + (ca.height - imageBounds.height) / 2;
103          gc.drawImage(image, x, y);
104        }
105      }
106    });
107    addListener(SWT.MouseDown, new Listener() {
108      public void handleEvent(Event e) {
109        m_down = true;
110        redraw();
111      }
112    });
113    addListener(SWT.MouseUp, new Listener() {
114      public void handleEvent(Event e) {
115        m_down = false;
116        redraw();
117        update();
118        if (getClientArea().contains(e.x, e.y)) {
119          fireSelectionEvent(e.time, e.stateMask);
120        }
121      }
122    });
123  }
124
125  ////////////////////////////////////////////////////////////////////////////
126  //
127  // Utils
128  //
129  ////////////////////////////////////////////////////////////////////////////
130  private void fireSelectionEvent(int time, int stateMask) {
131    Event event = new Event();
132    event.time = time;
133    event.stateMask = stateMask;
134    notifyListeners(SWT.Selection, event);
135  }
136
137  private void cropClientArea(Rectangle ca) {
138    ca.x += 1;
139    ca.y += 1;
140    ca.width -= 2;
141    ca.height -= 2;
142  }
143
144  ////////////////////////////////////////////////////////////////////////////
145  //
146  // Access
147  //
148  ////////////////////////////////////////////////////////////////////////////
149  public final Image getImage() {
150    return m_image;
151  }
152
153  public void setImage(Image image) {
154    m_image = image;
155  }
156
157  public void setSelected(boolean selected) {
158    m_selected = selected;
159  }
160}
161