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  */
25 
26 package javax.swing.plaf.synth;
27 
28 import javax.swing.*;
29 import javax.swing.plaf.*;
30 import javax.swing.plaf.basic.*;
31 import java.awt.Graphics;
32 import java.beans.PropertyChangeListener;
33 import java.beans.PropertyChangeEvent;
34 
35 /**
36  * Provides the Synth L&F UI delegate for
37  * {@link javax.swing.JPopupMenu}.
38  *
39  * @author Georges Saab
40  * @author David Karlton
41  * @author Arnaud Weber
42  * @since 1.7
43  */
44 public class SynthPopupMenuUI extends BasicPopupMenuUI
45                               implements PropertyChangeListener, SynthUI {
46     private SynthStyle style;
47 
48     /**
49      * Creates a new UI object for the given component.
50      *
51      * @param x component to create UI object for
52      * @return the UI object
53      */
createUI(JComponent x)54     public static ComponentUI createUI(JComponent x) {
55         return new SynthPopupMenuUI();
56     }
57 
58     /**
59      * {@inheritDoc}
60      */
61     @Override
installDefaults()62     public void installDefaults() {
63         if (popupMenu.getLayout() == null ||
64             popupMenu.getLayout() instanceof UIResource) {
65             popupMenu.setLayout(new SynthMenuLayout(popupMenu, BoxLayout.Y_AXIS));
66         }
67         updateStyle(popupMenu);
68     }
69 
updateStyle(JComponent c)70     private void updateStyle(JComponent c) {
71         SynthContext context = getContext(c, ENABLED);
72         SynthStyle oldStyle = style;
73         style = SynthLookAndFeel.updateStyle(context, this);
74         if (style != oldStyle) {
75             if (oldStyle != null) {
76                 uninstallKeyboardActions();
77                 installKeyboardActions();
78             }
79         }
80     }
81 
82     /**
83      * {@inheritDoc}
84      */
85     @Override
installListeners()86     protected void installListeners() {
87         super.installListeners();
88         popupMenu.addPropertyChangeListener(this);
89     }
90 
91     /**
92      * {@inheritDoc}
93      */
94     @Override
uninstallDefaults()95     protected void uninstallDefaults() {
96         SynthContext context = getContext(popupMenu, ENABLED);
97 
98         style.uninstallDefaults(context);
99         style = null;
100 
101         if (popupMenu.getLayout() instanceof UIResource) {
102             popupMenu.setLayout(null);
103         }
104     }
105 
106     /**
107      * {@inheritDoc}
108      */
109     @Override
uninstallListeners()110     protected void uninstallListeners() {
111         super.uninstallListeners();
112         popupMenu.removePropertyChangeListener(this);
113     }
114 
115     /**
116      * {@inheritDoc}
117      */
118     @Override
getContext(JComponent c)119     public SynthContext getContext(JComponent c) {
120         return getContext(c, getComponentState(c));
121     }
122 
getContext(JComponent c, int state)123     private SynthContext getContext(JComponent c, int state) {
124         return SynthContext.getContext(c, style, state);
125     }
126 
getComponentState(JComponent c)127     private int getComponentState(JComponent c) {
128         return SynthLookAndFeel.getComponentState(c);
129     }
130 
131     /**
132      * Notifies this UI delegate to repaint the specified component.
133      * This method paints the component background, then calls
134      * the {@link #paint(SynthContext,Graphics)} method.
135      *
136      * <p>In general, this method does not need to be overridden by subclasses.
137      * All Look and Feel rendering code should reside in the {@code paint} method.
138      *
139      * @param g the {@code Graphics} object used for painting
140      * @param c the component being painted
141      * @see #paint(SynthContext,Graphics)
142      */
143     @Override
update(Graphics g, JComponent c)144     public void update(Graphics g, JComponent c) {
145         SynthContext context = getContext(c);
146 
147         SynthLookAndFeel.update(context, g);
148         context.getPainter().paintPopupMenuBackground(context,
149                           g, 0, 0, c.getWidth(), c.getHeight());
150         paint(context, g);
151     }
152 
153     /**
154      * Paints the specified component according to the Look and Feel.
155      * <p>This method is not used by Synth Look and Feel.
156      * Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
157      *
158      * @param g the {@code Graphics} object used for painting
159      * @param c the component being painted
160      * @see #paint(SynthContext,Graphics)
161      */
162     @Override
paint(Graphics g, JComponent c)163     public void paint(Graphics g, JComponent c) {
164         SynthContext context = getContext(c);
165 
166         paint(context, g);
167     }
168 
169     /**
170      * Paints the specified component. This implementation does nothing.
171      *
172      * @param context context for the component being painted
173      * @param g the {@code Graphics} object used for painting
174      * @see #update(Graphics,JComponent)
175      */
paint(SynthContext context, Graphics g)176     protected void paint(SynthContext context, Graphics g) {
177     }
178 
179     /**
180      * {@inheritDoc}
181      */
182     @Override
paintBorder(SynthContext context, Graphics g, int x, int y, int w, int h)183     public void paintBorder(SynthContext context, Graphics g, int x,
184                             int y, int w, int h) {
185         context.getPainter().paintPopupMenuBorder(context, g, x, y, w, h);
186     }
187 
188     /**
189      * {@inheritDoc}
190      */
191     @Override
propertyChange(PropertyChangeEvent e)192     public void propertyChange(PropertyChangeEvent e) {
193         if (SynthLookAndFeel.shouldUpdateStyle(e)) {
194             updateStyle(popupMenu);
195         }
196     }
197 }
198