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