1 /*
2  * Copyright (c) 1997, 2010, 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  */
25 
26 package com.sun.java.swing.plaf.motif;
27 
28 import sun.swing.SwingUtilities2;
29 import javax.swing.*;
30 import javax.swing.border.*;
31 import javax.swing.plaf.*;
32 
33 import java.awt.Color;
34 import java.awt.Component;
35 import java.awt.Dimension;
36 import java.awt.Font;
37 import java.awt.FontMetrics;
38 import java.awt.Graphics;
39 import java.awt.Insets;
40 import java.awt.Point;
41 import java.awt.Rectangle;
42 
43 /**
44  * Factory object that can vend Icons appropriate for the basic L & F.
45  * <p>
46  * <strong>Warning:</strong>
47  * Serialized objects of this class will not be compatible with
48  * future Swing releases.  The current serialization support is appropriate
49  * for short term storage or RMI between applications running the same
50  * version of Swing.  A future release of Swing will provide support for
51  * long term persistence.
52  *
53  * @author Amy Fowler
54  */
55 public class MotifBorders {
56 
57     public static class BevelBorder extends AbstractBorder implements UIResource {
58         private Color darkShadow = UIManager.getColor("controlShadow");
59         private Color lightShadow = UIManager.getColor("controlLtHighlight");
60         private boolean isRaised;
61 
BevelBorder(boolean isRaised, Color darkShadow, Color lightShadow)62         public BevelBorder(boolean isRaised, Color darkShadow, Color lightShadow) {
63             this.isRaised = isRaised;
64             this.darkShadow = darkShadow;
65             this.lightShadow = lightShadow;
66         }
67 
paintBorder(Component c, Graphics g, int x, int y, int w, int h)68         public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) {
69             g.setColor((isRaised) ? lightShadow : darkShadow);
70             g.drawLine(x, y, x+w-1, y);           // top
71             g.drawLine(x, y+h-1, x, y+1);         // left
72 
73             g.setColor((isRaised) ? darkShadow : lightShadow);
74             g.drawLine(x+1, y+h-1, x+w-1, y+h-1); // bottom
75             g.drawLine(x+w-1, y+h-1, x+w-1, y+1); // right
76         }
77 
getBorderInsets(Component c, Insets insets)78         public Insets getBorderInsets(Component c, Insets insets) {
79             insets.set(1, 1, 1, 1);
80             return insets;
81         }
82 
isOpaque(Component c)83         public boolean isOpaque(Component c) {
84             return true;
85         }
86 
87     }
88 
89 
90     public static class FocusBorder extends AbstractBorder implements UIResource {
91         private Color focus;
92         private Color control;
93 
FocusBorder(Color control, Color focus)94         public FocusBorder(Color control, Color focus) {
95             this.control = control;
96             this.focus = focus;
97         }
98 
paintBorder(Component c, Graphics g, int x, int y, int w, int h)99         public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) {
100             if (c.hasFocus()) {
101                 g.setColor(focus);
102                 g.drawRect(x, y, w-1, h-1);
103             } else {
104                 g.setColor(control);
105                 g.drawRect(x, y, w-1, h-1);
106             }
107         }
108 
getBorderInsets(Component c, Insets insets)109         public Insets getBorderInsets(Component c, Insets insets) {
110             insets.set(1, 1, 1, 1);
111             return insets;
112         }
113     }
114 
115 
116     public static class ButtonBorder extends AbstractBorder implements UIResource {
117         protected Color focus = UIManager.getColor("activeCaptionBorder");
118         protected Color shadow = UIManager.getColor("Button.shadow");
119         protected Color highlight = UIManager.getColor("Button.light");
120         protected Color darkShadow;
121 
ButtonBorder(Color shadow, Color highlight, Color darkShadow, Color focus)122         public ButtonBorder(Color shadow, Color highlight, Color darkShadow, Color focus) {
123             this.shadow = shadow;
124             this.highlight = highlight;
125             this.darkShadow = darkShadow;
126             this.focus = focus;
127         }
128 
paintBorder(Component c, Graphics g, int x, int y, int w, int h)129         public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) {
130             boolean isPressed = false;
131             boolean hasFocus = false;
132             boolean canBeDefault = false;
133             boolean isDefault = false;
134 
135             if (c instanceof AbstractButton) {
136                 AbstractButton b = (AbstractButton)c;
137                 ButtonModel model = b.getModel();
138 
139                 isPressed = (model.isArmed() && model.isPressed());
140                 hasFocus = (model.isArmed() && isPressed) ||
141                            (b.isFocusPainted() && b.hasFocus());
142                 if (b instanceof JButton) {
143                     canBeDefault = ((JButton)b).isDefaultCapable();
144                     isDefault = ((JButton)b).isDefaultButton();
145                 }
146             }
147             int bx1 = x+1;
148             int by1 = y+1;
149             int bx2 = x+w-2;
150             int by2 = y+h-2;
151 
152             if (canBeDefault) {
153                 if (isDefault) {
154                     g.setColor(shadow);
155                     g.drawLine(x+3, y+3, x+3, y+h-4);
156                     g.drawLine(x+3, y+3, x+w-4, y+3);
157 
158                     g.setColor(highlight);
159                     g.drawLine(x+4, y+h-4, x+w-4, y+h-4);
160                     g.drawLine(x+w-4, y+3, x+w-4, y+h-4);
161                 }
162                 bx1 +=6;
163                 by1 += 6;
164                 bx2 -= 6;
165                 by2 -= 6;
166             }
167 
168             if (hasFocus) {
169                 g.setColor(focus);
170                 if (isDefault) {
171                     g.drawRect(x, y, w-1, h-1);
172                 } else {
173                     g.drawRect(bx1-1, by1-1, bx2-bx1+2, by2-by1+2);
174                 }
175             }
176 
177             g.setColor(isPressed? shadow : highlight);
178             g.drawLine(bx1, by1, bx2, by1);
179             g.drawLine(bx1, by1, bx1, by2);
180 
181             g.setColor(isPressed? highlight : shadow);
182             g.drawLine(bx2, by1+1, bx2, by2);
183             g.drawLine(bx1+1, by2, bx2, by2);
184         }
185 
getBorderInsets(Component c, Insets insets)186         public Insets getBorderInsets(Component c, Insets insets) {
187             int thickness = (c instanceof JButton && ((JButton)c).isDefaultCapable())? 8 : 2;
188             insets.set(thickness, thickness, thickness, thickness);
189             return insets;
190         }
191 
192     }
193 
194     public static class ToggleButtonBorder extends ButtonBorder {
195 
ToggleButtonBorder(Color shadow, Color highlight, Color darkShadow, Color focus)196         public ToggleButtonBorder(Color shadow, Color highlight, Color darkShadow, Color focus) {
197              super(shadow, highlight, darkShadow, focus);
198         }
199 
paintBorder(Component c, Graphics g, int x, int y, int width, int height)200         public void paintBorder(Component c, Graphics g, int x, int y,
201                             int width, int height) {
202             if (c instanceof AbstractButton) {
203                 AbstractButton b = (AbstractButton)c;
204                 ButtonModel model = b.getModel();
205 
206                 if (model.isArmed() && model.isPressed() || model.isSelected()) {
207                     drawBezel(g, x, y, width, height,
208                               (model.isPressed() || model.isSelected()),
209                               b.isFocusPainted() && b.hasFocus(), shadow, highlight, darkShadow, focus);
210                 } else {
211                     drawBezel(g, x, y, width, height,
212                               false, b.isFocusPainted() && b.hasFocus(),
213                               shadow, highlight, darkShadow, focus);
214                 }
215             } else {
216                 drawBezel(g, x, y, width, height, false, false,
217                           shadow, highlight, darkShadow, focus);
218             }
219         }
220 
getBorderInsets(Component c, Insets insets)221         public Insets getBorderInsets(Component c, Insets insets) {
222             insets.set(2, 2, 3, 3);
223             return insets;
224         }
225     }
226 
227     public static class MenuBarBorder extends ButtonBorder {
228 
MenuBarBorder(Color shadow, Color highlight, Color darkShadow, Color focus)229         public MenuBarBorder(Color shadow, Color highlight, Color darkShadow, Color focus) {
230             super(shadow, highlight, darkShadow, focus);
231         }
232 
paintBorder(Component c, Graphics g, int x, int y, int width, int height)233         public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
234             if (!(c instanceof JMenuBar)) {
235                 return;
236             }
237             JMenuBar menuBar = (JMenuBar)c;
238             if (menuBar.isBorderPainted() == true) {
239                 // this draws the MenuBar border
240                 Dimension size = menuBar.getSize();
241                 drawBezel(g,x,y,size.width,size.height,false,false,
242                           shadow, highlight, darkShadow, focus);
243             }
244         }
245 
getBorderInsets(Component c, Insets insets)246         public Insets getBorderInsets(Component c, Insets insets) {
247             insets.set(6, 6, 6, 6);
248             return insets;
249         }
250     }
251 
252     public static class FrameBorder extends AbstractBorder implements UIResource {
253 
254         JComponent jcomp;
255         Color frameHighlight;
256         Color frameColor;
257         Color frameShadow;
258 
259         // The width of the border
260         public final static int BORDER_SIZE = 5;
261 
262         /** Constructs an FrameBorder for the JComponent <b>comp</b>.
263         */
FrameBorder(JComponent comp)264         public FrameBorder(JComponent comp) {
265             jcomp = comp;
266         }
267 
268         /** Sets the FrameBorder's JComponent.
269       */
setComponent(JComponent comp)270         public void setComponent(JComponent comp) {
271             jcomp = comp;
272         }
273 
274         /** Returns the FrameBorder's JComponent.
275           * @see #setComponent
276           */
component()277         public JComponent component() {
278             return jcomp;
279         }
280 
getFrameHighlight()281         protected Color getFrameHighlight() {
282             return frameHighlight;
283         }
284 
getFrameColor()285         protected Color getFrameColor() {
286             return frameColor;
287         }
288 
getFrameShadow()289         protected Color getFrameShadow() {
290             return frameShadow;
291         }
292 
getBorderInsets(Component c, Insets newInsets)293         public Insets getBorderInsets(Component c, Insets newInsets) {
294             newInsets.set(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE);
295             return newInsets;
296         }
297 
298        /** Draws the FrameBorder's top border.
299          */
drawTopBorder(Component c, Graphics g, int x, int y, int width, int height)300         protected boolean drawTopBorder(Component c, Graphics g,
301                                     int x, int y, int width, int height) {
302             Rectangle titleBarRect = new Rectangle(x, y, width, BORDER_SIZE);
303             if (!g.getClipBounds().intersects(titleBarRect)) {
304                 return false;
305             }
306 
307             int maxX = width - 1;
308             int maxY = BORDER_SIZE - 1;
309 
310             // Draw frame
311             g.setColor(frameColor);
312             g.drawLine(x, y + 2, maxX - 2, y + 2);
313             g.drawLine(x, y + 3, maxX - 2, y + 3);
314             g.drawLine(x, y + 4, maxX - 2, y + 4);
315 
316             // Draw highlights
317             g.setColor(frameHighlight);
318             g.drawLine(x, y, maxX, y);
319             g.drawLine(x, y + 1, maxX, y + 1);
320             g.drawLine(x, y + 2, x, y + 4);
321             g.drawLine(x + 1, y + 2, x + 1, y + 4);
322 
323             // Draw shadows
324             g.setColor(frameShadow);
325             g.drawLine(x + 4, y + 4, maxX - 4, y + 4);
326             g.drawLine(maxX, y + 1, maxX, maxY);
327             g.drawLine(maxX - 1, y + 2, maxX - 1, maxY);
328 
329             return true;
330         }
331 
332         /** Draws the FrameBorder's left border.
333           */
drawLeftBorder(Component c, Graphics g, int x, int y, int width, int height)334         protected boolean drawLeftBorder(Component c, Graphics g, int x, int y,
335                                int width, int height) {
336             Rectangle borderRect =
337                 new Rectangle(0, 0, getBorderInsets(c).left, height);
338             if (!g.getClipBounds().intersects(borderRect)) {
339                 return false;
340             }
341 
342             int startY = BORDER_SIZE;
343 
344             g.setColor(frameHighlight);
345             g.drawLine(x, startY, x, height - 1);
346             g.drawLine(x + 1, startY, x + 1, height - 2);
347 
348             g.setColor(frameColor);
349             g.fillRect(x + 2, startY, x + 2, height - 3);
350 
351             g.setColor(frameShadow);
352             g.drawLine(x + 4, startY, x + 4, height - 5);
353 
354             return true;
355         }
356 
357         /** Draws the FrameBorder's right border.
358           */
drawRightBorder(Component c, Graphics g, int x, int y, int width, int height)359         protected boolean drawRightBorder(Component c, Graphics g, int x, int y,
360                                 int width, int height) {
361             Rectangle borderRect = new Rectangle(
362                 width - getBorderInsets(c).right, 0,
363                 getBorderInsets(c).right, height);
364             if (!g.getClipBounds().intersects(borderRect)) {
365                 return false;
366             }
367 
368             int startX = width - getBorderInsets(c).right;
369             int startY = BORDER_SIZE;
370 
371             g.setColor(frameColor);
372             g.fillRect(startX + 1, startY, 2, height - 1);
373 
374             g.setColor(frameShadow);
375             g.fillRect(startX + 3, startY, 2, height - 1);
376 
377             g.setColor(frameHighlight);
378             g.drawLine(startX, startY, startX, height - 1);
379 
380             return true;
381         }
382 
383         /** Draws the FrameBorder's bottom border.
384           */
drawBottomBorder(Component c, Graphics g, int x, int y, int width, int height)385         protected boolean drawBottomBorder(Component c, Graphics g, int x, int y,
386                                  int width, int height) {
387             Rectangle    borderRect;
388             int     marginHeight, startY;
389 
390             borderRect = new Rectangle(0, height - getBorderInsets(c).bottom,
391                                   width, getBorderInsets(c).bottom);
392             if (!g.getClipBounds().intersects(borderRect)) {
393                 return false;
394             }
395 
396             startY = height - getBorderInsets(c).bottom;
397 
398             g.setColor(frameShadow);
399             g.drawLine(x + 1, height - 1, width - 1, height - 1);
400             g.drawLine(x + 2, height - 2, width - 2, height - 2);
401 
402             g.setColor(frameColor);
403             g.fillRect(x + 2, startY + 1, width - 4, 2);
404 
405             g.setColor(frameHighlight);
406             g.drawLine(x + 5, startY, width - 5, startY);
407 
408             return true;
409         }
410 
411         // Returns true if the associated component has focus.
isActiveFrame()412         protected boolean isActiveFrame() {
413             return jcomp.hasFocus();
414         }
415 
416         /** Draws the FrameBorder in the given Rect.  Calls
417           * <b>drawTitleBar</b>, <b>drawLeftBorder</b>, <b>drawRightBorder</b> and
418           * <b>drawBottomBorder</b>.
419           */
paintBorder(Component c, Graphics g, int x, int y, int width, int height)420         public void paintBorder(Component c, Graphics g,
421                             int x, int y, int width, int height) {
422             if (isActiveFrame()) {
423                 frameColor = UIManager.getColor("activeCaptionBorder");
424             } else {
425                 frameColor = UIManager.getColor("inactiveCaptionBorder");
426             }
427             frameHighlight = frameColor.brighter();
428             frameShadow = frameColor.darker().darker();
429 
430             drawTopBorder(c, g, x, y, width, height);
431             drawLeftBorder(c, g, x, y, width, height);
432             drawRightBorder(c, g, x, y, width, height);
433             drawBottomBorder(c, g, x, y, width, height);
434         }
435     }
436 
437     public static class InternalFrameBorder extends FrameBorder {
438 
439         JInternalFrame frame;
440 
441         // The size of the bounding box for Motif frame corners.
442         public final static int CORNER_SIZE = 24;
443 
444         /** Constructs an InternalFrameBorder for the InternalFrame
445           * <b>aFrame</b>.
446           */
InternalFrameBorder(JInternalFrame aFrame)447         public InternalFrameBorder(JInternalFrame aFrame) {
448             super(aFrame);
449             frame = aFrame;
450         }
451 
452         /** Sets the InternalFrameBorder's InternalFrame.
453           */
setFrame(JInternalFrame aFrame)454         public void setFrame(JInternalFrame aFrame) {
455             frame = aFrame;
456         }
457 
458         /** Returns the InternalFrameBorder's InternalFrame.
459           * @see #setFrame
460           */
frame()461         public JInternalFrame frame() {
462             return frame;
463         }
464 
465         /** Returns the width of the InternalFrameBorder's resize controls,
466           * appearing along the InternalFrameBorder's bottom border.  Clicking
467           * and dragging within these controls lets the user change both the
468           * InternalFrame's width and height, while dragging between the controls
469           * constrains resizing to just the vertical dimension.  Override this
470           * method if you implement your own bottom border painting and use a
471           * resize control with a different size.
472           */
resizePartWidth()473         public int resizePartWidth() {
474             if (!frame.isResizable()) {
475                 return 0;
476             }
477             return FrameBorder.BORDER_SIZE;
478         }
479 
480         /** Draws the InternalFrameBorder's top border.
481          */
drawTopBorder(Component c, Graphics g, int x, int y, int width, int height)482         protected boolean drawTopBorder(Component c, Graphics g,
483                                     int x, int y, int width, int height) {
484             if (super.drawTopBorder(c, g, x, y, width, height) &&
485                 frame.isResizable()) {
486                 g.setColor(getFrameShadow());
487                 g.drawLine(CORNER_SIZE - 1, y + 1, CORNER_SIZE - 1, y + 4);
488                 g.drawLine(width - CORNER_SIZE - 1, y + 1,
489                        width - CORNER_SIZE - 1, y + 4);
490 
491                 g.setColor(getFrameHighlight());
492                 g.drawLine(CORNER_SIZE, y, CORNER_SIZE, y + 4);
493                 g.drawLine(width - CORNER_SIZE, y, width - CORNER_SIZE, y + 4);
494                 return true;
495             }
496             return false;
497         }
498 
499         /** Draws the InternalFrameBorder's left border.
500           */
drawLeftBorder(Component c, Graphics g, int x, int y, int width, int height)501         protected boolean drawLeftBorder(Component c, Graphics g, int x, int y,
502                                      int width, int height) {
503             if (super.drawLeftBorder(c, g, x, y, width, height) &&
504                 frame.isResizable()) {
505                 g.setColor(getFrameHighlight());
506                 int topY = y + CORNER_SIZE;
507                 g.drawLine(x, topY, x + 4, topY);
508                 int bottomY = height - CORNER_SIZE;
509                 g.drawLine(x + 1, bottomY, x + 5, bottomY);
510                 g.setColor(getFrameShadow());
511                 g.drawLine(x + 1, topY - 1, x + 5, topY - 1);
512                 g.drawLine(x + 1, bottomY - 1, x + 5, bottomY - 1);
513                 return true;
514             }
515             return false;
516         }
517 
518         /** Draws the InternalFrameBorder's right border.
519           */
drawRightBorder(Component c, Graphics g, int x, int y, int width, int height)520         protected boolean drawRightBorder(Component c, Graphics g, int x, int y,
521                                       int width, int height) {
522             if (super.drawRightBorder(c, g, x, y, width, height) &&
523                 frame.isResizable()) {
524                 int startX = width - getBorderInsets(c).right;
525                 g.setColor(getFrameHighlight());
526                 int topY = y + CORNER_SIZE;
527                 g.drawLine(startX, topY, width - 2, topY);
528                 int bottomY = height - CORNER_SIZE;
529                 g.drawLine(startX + 1, bottomY, startX + 3, bottomY);
530                 g.setColor(getFrameShadow());
531                 g.drawLine(startX + 1, topY - 1, width - 2, topY - 1);
532                 g.drawLine(startX + 1, bottomY - 1, startX + 3, bottomY - 1);
533                 return true;
534             }
535             return false;
536         }
537 
538         /** Draws the InternalFrameBorder's bottom border.
539           */
drawBottomBorder(Component c, Graphics g, int x, int y, int width, int height)540         protected boolean drawBottomBorder(Component c, Graphics g, int x, int y,
541                                        int width, int height) {
542             if (super.drawBottomBorder(c, g, x, y, width, height) &&
543                 frame.isResizable()) {
544                 int startY = height - getBorderInsets(c).bottom;
545 
546                 g.setColor(getFrameShadow());
547                 g.drawLine(CORNER_SIZE - 1, startY + 1,
548                        CORNER_SIZE - 1, height - 1);
549                 g.drawLine(width - CORNER_SIZE, startY + 1,
550                        width - CORNER_SIZE, height - 1);
551 
552                 g.setColor(getFrameHighlight());
553                 g.drawLine(CORNER_SIZE, startY, CORNER_SIZE, height - 2);
554                 g.drawLine(width - CORNER_SIZE + 1, startY,
555                        width - CORNER_SIZE + 1, height - 2);
556                 return true;
557             }
558             return false;
559         }
560 
561         // Returns true if the associated internal frame has focus.
isActiveFrame()562         protected boolean isActiveFrame() {
563             return frame.isSelected();
564         }
565     }
566 
drawBezel(Graphics g, int x, int y, int w, int h, boolean isPressed, boolean hasFocus, Color shadow, Color highlight, Color darkShadow, Color focus)567     public static void drawBezel(Graphics g, int x, int y, int w, int h,
568                                boolean isPressed, boolean hasFocus,
569                                Color shadow, Color highlight,
570                                Color darkShadow, Color focus)  {
571 
572         Color oldColor = g.getColor();
573         g.translate(x, y);
574 
575         if (isPressed) {
576             if (hasFocus){
577                 g.setColor(focus);
578                 g.drawRect(0, 0, w-1, h-1);
579             }
580             g.setColor(shadow);         // inner border
581             g.drawRect(1, 1, w-3, h-3);
582 
583             g.setColor(highlight);    // inner 3D border
584             g.drawLine(2, h-3, w-3, h-3);
585             g.drawLine(w-3, 2, w-3, h-4);
586 
587         } else {
588             if (hasFocus) {
589                 g.setColor(focus);
590                 g.drawRect(0, 0, w-1, h-1);
591 
592                 g.setColor(highlight);   // inner 3D border
593                 g.drawLine(1, 1, 1, h-3);
594                 g.drawLine(2, 1, w-4, 1);
595 
596                 g.setColor(shadow);
597                 g.drawLine(2, h-3, w-3, h-3);
598                 g.drawLine(w-3, 1, w-3, h-4);
599 
600                 g.setColor(darkShadow);        // black drop shadow  __|
601                 g.drawLine(1, h-2, w-2, h-2);
602                 g.drawLine(w-2, h-2, w-2, 1);
603             } else {
604                 g.setColor(highlight);    // inner 3D border
605                 g.drawLine(1,1,1,h-3);
606                 g.drawLine(2,1,w-4,1);
607                 g.setColor(shadow);
608                 g.drawLine(2,h-3,w-3,h-3);
609                 g.drawLine(w-3,1,w-3,h-4);
610 
611                 g.setColor(darkShadow);         // black drop shadow  __|
612                 g.drawLine(1,h-2,w-2,h-2);
613                 g.drawLine(w-2,h-2,w-2,0);
614 
615             }
616             g.translate(-x, -y);
617         }
618         g.setColor(oldColor);
619     }
620 
621     public static class MotifPopupMenuBorder extends AbstractBorder implements UIResource {
622         protected Font   font;
623         protected Color  background;
624         protected Color  foreground;
625         protected Color  shadowColor;
626         protected Color  highlightColor;
627 
628         // Space between the border and text
629         static protected final int TEXT_SPACING = 2;
630 
631         // Space for the separator under the title
632         static protected final int GROOVE_HEIGHT = 2;
633 
634         /**
635          * Creates a MotifPopupMenuBorder instance
636          *
637          */
MotifPopupMenuBorder( Font titleFont, Color bgColor, Color fgColor, Color shadow, Color highlight)638         public MotifPopupMenuBorder(
639                                     Font titleFont,
640                                     Color bgColor,
641                                     Color fgColor,
642                                     Color shadow,
643                                     Color highlight)       {
644             this.font = titleFont;
645             this.background = bgColor;
646             this.foreground = fgColor;
647             this.shadowColor = shadow;
648             this.highlightColor = highlight;
649         }
650 
651         /**
652          * Paints the border for the specified component with the
653          * specified position and size.
654          * @param c the component for which this border is being painted
655          * @param g the paint graphics
656          * @param x the x position of the painted border
657          * @param y the y position of the painted border
658          * @param width the width of the painted border
659          * @param height the height of the painted border
660          */
paintBorder(Component c, Graphics g, int x, int y, int width, int height)661         public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
662             if (!(c instanceof JPopupMenu)) {
663                 return;
664             }
665 
666             Font origFont = g.getFont();
667             Color origColor = g.getColor();
668             JPopupMenu popup = (JPopupMenu)c;
669 
670             String title = popup.getLabel();
671             if (title == null) {
672                 return;
673             }
674 
675             g.setFont(font);
676 
677             FontMetrics fm = SwingUtilities2.getFontMetrics(popup, g, font);
678             int         fontHeight = fm.getHeight();
679             int         descent = fm.getDescent();
680             int         ascent = fm.getAscent();
681             Point       textLoc = new Point();
682             int         stringWidth = SwingUtilities2.stringWidth(popup, fm,
683                                                                   title);
684 
685             textLoc.y = y + ascent + TEXT_SPACING;
686             textLoc.x = x + ((width - stringWidth) / 2);
687 
688             g.setColor(background);
689             g.fillRect(textLoc.x - TEXT_SPACING, textLoc.y - (fontHeight-descent),
690                        stringWidth + (2 * TEXT_SPACING), fontHeight - descent);
691             g.setColor(foreground);
692             SwingUtilities2.drawString(popup, g, title, textLoc.x, textLoc.y);
693 
694             MotifGraphicsUtils.drawGroove(g, x, textLoc.y + TEXT_SPACING,
695                                           width, GROOVE_HEIGHT,
696                                           shadowColor, highlightColor);
697 
698             g.setFont(origFont);
699             g.setColor(origColor);
700         }
701 
702         /**
703          * Reinitialize the insets parameter with this Border's current Insets.
704          * @param c the component for which this border insets value applies
705          * @param insets the object to be reinitialized
706          */
getBorderInsets(Component c, Insets insets)707         public Insets getBorderInsets(Component c, Insets insets) {
708             if (!(c instanceof JPopupMenu)) {
709                 return insets;
710             }
711             FontMetrics fm;
712             int         descent = 0;
713             int         ascent = 16;
714 
715             String title = ((JPopupMenu)c).getLabel();
716             if (title == null) {
717                 insets.left = insets.top = insets.right = insets.bottom = 0;
718                 return insets;
719             }
720 
721             fm = c.getFontMetrics(font);
722 
723             if(fm != null) {
724                 descent = fm.getDescent();
725                 ascent = fm.getAscent();
726             }
727 
728             insets.top += ascent + descent + TEXT_SPACING + GROOVE_HEIGHT;
729             return insets;
730         }
731 
732     }
733 
734 }
735