1/*
2 * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25package sun.awt.X11;
26
27import java.awt.*;
28import java.awt.peer.*;
29import java.awt.event.MouseEvent;
30import java.awt.event.FocusEvent;
31import java.awt.event.KeyEvent;
32import java.awt.event.ActionEvent;
33import javax.swing.plaf.basic.*;
34import javax.swing.SwingUtilities;
35import javax.swing.SwingConstants;
36public class XButtonPeer extends XComponentPeer implements ButtonPeer {
37    private boolean pressed;
38    private boolean armed;
39    private Insets focusInsets;
40    private Insets borderInsets;
41    private Insets contentAreaInsets;
42
43    private static final String propertyPrefix = "Button" + ".";
44    protected Color focusColor =  SystemColor.windowText;
45
46    private boolean disposed = false;
47
48    String label;
49
50    protected String getPropertyPrefix() {
51        return propertyPrefix;
52    }
53
54    void preInit(XCreateWindowParams params) {
55        super.preInit(params);
56        borderInsets = new Insets(2,2,2,2);
57        focusInsets = new Insets(0,0,0,0);
58        contentAreaInsets = new Insets(3,3,3,3);
59    }
60
61
62    public  XButtonPeer(Button target) {
63        super(target);
64        pressed = false;
65        armed = false;
66        label = target.getLabel();
67        updateMotifColors(getPeerBackground());
68    }
69
70    public  void dispose() {
71        synchronized (target)
72        {
73            disposed = true;
74        }
75        super.dispose();
76    }
77
78    public boolean isFocusable() {
79        return true;
80    }
81
82    @Override
83    public void setLabel(String label) {
84        if (label == null) {
85            label = "";
86        }
87        if (!label.equals(this.label)) {
88            this.label = label;
89            repaint();
90        }
91    }
92
93    public void setBackground(Color c) {
94        updateMotifColors(c);
95        super.setBackground(c);
96    }
97
98    void handleJavaMouseEvent(MouseEvent e) {
99        super.handleJavaMouseEvent(e);
100        int id = e.getID();
101        switch (id) {
102          case MouseEvent.MOUSE_PRESSED:
103              if (XToolkit.isLeftMouseButton(e) ) {
104                  Button b = (Button) e.getSource();
105
106                  if(b.contains(e.getX(), e.getY())) {
107                      if (!isEnabled()) {
108                          // Disabled buttons ignore all input...
109                          return;
110                      }
111                      pressed = true;
112                      armed = true;
113                      repaint();
114                  }
115              }
116
117              break;
118
119          case MouseEvent.MOUSE_RELEASED:
120              if (XToolkit.isLeftMouseButton(e)) {
121                  if (armed)
122                  {
123                      @SuppressWarnings("deprecation")
124                      final int modifiers = e.getModifiers();
125                      action(e.getWhen(), modifiers);
126                  }
127                  pressed = false;
128                  armed = false;
129                  repaint();
130              }
131
132              break;
133
134          case  MouseEvent.MOUSE_ENTERED:
135              if (pressed)
136                  armed = true;
137              break;
138          case MouseEvent.MOUSE_EXITED:
139              armed = false;
140              break;
141        }
142    }
143
144
145    // NOTE: This method is called by privileged threads.
146    //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
147    public void action(final long when, final int modifiers) {
148        postEvent(new ActionEvent(target, ActionEvent.ACTION_PERFORMED,
149                                  ((Button)target).getActionCommand(),
150                                  when, modifiers));
151    }
152
153
154    public void focusGained(FocusEvent e) {
155        super.focusGained(e);
156        repaint();
157    }
158
159    public void focusLost(FocusEvent e) {
160        super.focusLost(e);
161        repaint();
162    }
163
164    void handleJavaKeyEvent(KeyEvent e) {
165        int id = e.getID();
166        switch (id) {
167          case KeyEvent.KEY_PRESSED:
168              if (e.getKeyCode() == KeyEvent.VK_SPACE)
169              {
170                  pressed=true;
171                  armed=true;
172                  repaint();
173                  @SuppressWarnings("deprecation")
174                  final int modifiers = e.getModifiers();
175                  action(e.getWhen(), modifiers);
176              }
177
178              break;
179
180          case KeyEvent.KEY_RELEASED:
181              if (e.getKeyCode() == KeyEvent.VK_SPACE)
182              {
183                  pressed = false;
184                  armed = false;
185                  repaint();
186              }
187
188              break;
189
190
191        }
192    }
193
194    public Dimension getMinimumSize() {
195        FontMetrics fm = getFontMetrics(getPeerFont());
196        if ( label == null ) {
197            label = "";
198        }
199        return new Dimension(fm.stringWidth(label) + 14,
200                             fm.getHeight() + 8);
201    }
202
203    /**
204     * DEPRECATED
205     */
206    public Dimension minimumSize() {
207        return getMinimumSize();
208    }
209    /**
210     * This method is called from Toolkit Thread and so it should not call any
211     * client code.
212     */
213    @Override
214    void paintPeer(final Graphics g) {
215        if (!disposed) {
216            Dimension size = getPeerSize();
217            g.setColor( getPeerBackground() );   /* erase the existing button remains */
218            g.fillRect(0,0, size.width , size.height);
219            paintBorder(g,borderInsets.left,
220                        borderInsets.top,
221                        size.width-(borderInsets.left+borderInsets.right),
222                        size.height-(borderInsets.top+borderInsets.bottom));
223
224            FontMetrics fm = g.getFontMetrics();
225
226            Rectangle textRect,iconRect,viewRect;
227
228            textRect = new Rectangle();
229            viewRect = new Rectangle();
230            iconRect = new Rectangle();
231
232
233            viewRect.width = size.width - (contentAreaInsets.left+contentAreaInsets.right);
234            viewRect.height = size.height - (contentAreaInsets.top+contentAreaInsets.bottom);
235            viewRect.x = contentAreaInsets.left;
236            viewRect.y = contentAreaInsets.top;
237            String llabel = (label != null) ? label : "";
238            // layout the text and icon
239            String text = SwingUtilities.layoutCompoundLabel(
240                                                             fm, llabel, null,
241                                                             SwingConstants.CENTER, SwingConstants.CENTER,
242                                                             SwingConstants.CENTER, SwingConstants.CENTER,
243                                                             viewRect, iconRect, textRect, 0);
244
245            Font f = getPeerFont();
246
247            g.setFont(f);
248
249            // perform UI specific press action, e.g. Windows L&F shifts text
250            if (pressed && armed) {
251                paintButtonPressed(g,target);
252            }
253
254            paintText(g, target, textRect, text);
255
256            if (hasFocus()) {
257                // paint UI specific focus
258                paintFocus(g,focusInsets.left,
259                           focusInsets.top,
260                           size.width-(focusInsets.left+focusInsets.right)-1,
261                           size.height-(focusInsets.top+focusInsets.bottom)-1);
262            }
263        }
264        flush();
265    }
266
267    public void paintBorder(Graphics g, int x, int y, int w, int h) {
268        drawMotif3DRect(g, x, y, w-1, h-1, pressed);
269    }
270
271    protected void paintFocus(Graphics g, int x, int y, int w, int h){
272        g.setColor(focusColor);
273        g.drawRect(x,y,w,h);
274    }
275
276    protected void paintButtonPressed(Graphics g, Component b) {
277        Dimension size = getPeerSize();
278        g.setColor(selectColor);
279        g.fillRect(contentAreaInsets.left,
280                   contentAreaInsets.top,
281                   size.width-(contentAreaInsets.left+contentAreaInsets.right),
282                   size.height-(contentAreaInsets.top+contentAreaInsets.bottom));
283
284    }
285    protected void paintText(Graphics g, Component c, Rectangle textRect, String text) {
286        FontMetrics fm = g.getFontMetrics();
287
288        int mnemonicIndex = -1;
289
290        /* Draw the Text */
291        if(isEnabled()) {
292            /*** paint the text normally */
293            g.setColor(getPeerForeground());
294            BasicGraphicsUtils.drawStringUnderlineCharAt(g,text,mnemonicIndex , textRect.x , textRect.y + fm.getAscent() );
295        }
296        else {
297            /*** paint the text disabled ***/
298            g.setColor(getPeerBackground().brighter());
299            BasicGraphicsUtils.drawStringUnderlineCharAt(g,text, mnemonicIndex,
300                                                         textRect.x, textRect.y + fm.getAscent());
301            g.setColor(getPeerBackground().darker());
302            BasicGraphicsUtils.drawStringUnderlineCharAt(g,text, mnemonicIndex,
303                                                         textRect.x - 1, textRect.y + fm.getAscent() - 1);
304        }
305    }
306}
307