|
1 /* |
|
2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. |
|
3 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. |
|
4 */ |
|
5 |
|
6 package javax.swing.plaf; |
|
7 |
|
8 import javax.accessibility.Accessible; |
|
9 import javax.swing.*; |
|
10 import javax.swing.plaf.ComponentUI; |
|
11 import java.awt.*; |
|
12 import java.awt.event.*; |
|
13 import java.beans.PropertyChangeEvent; |
|
14 import java.beans.PropertyChangeSupport; |
|
15 import java.beans.PropertyChangeListener; |
|
16 import java.io.Serializable; |
|
17 |
|
18 /** |
|
19 * The base class for all {@link javax.swing.JLayer}'s UI delegates. |
|
20 * <p/> |
|
21 * {@link #paint(java.awt.Graphics, javax.swing.JComponent)} method performes the |
|
22 * painting of the {@code JLayer} |
|
23 * and {@link #eventDispatched(AWTEvent, JLayer)} method is notified |
|
24 * about any {@code AWTEvent}s which have been generated by a {@code JLayer} |
|
25 * or any of its subcomponents. |
|
26 * <p/> |
|
27 * The {@code LayerUI} differs from the UI delegates of the other components, |
|
28 * because it is LookAndFeel independent and is not updated by default when |
|
29 * the system LookAndFeel is changed. |
|
30 * <p/> |
|
31 * The subclasses of {@code LayerUI} can either be stateless and shareable |
|
32 * by multiple {@code JLayer}s or not shareable. |
|
33 * |
|
34 * @param <V> one of the super types of {@code JLayer}'s view component |
|
35 * |
|
36 * @see JLayer#setUI(LayerUI) |
|
37 * @see JLayer#setView(Component) |
|
38 * @see JLayer#getView() |
|
39 * @since 1.7 |
|
40 * |
|
41 * @author Alexander Potochkin |
|
42 */ |
|
43 public class LayerUI<V extends Component> |
|
44 extends ComponentUI implements Serializable { |
|
45 |
|
46 private final PropertyChangeSupport propertyChangeSupport = |
|
47 new PropertyChangeSupport(this); |
|
48 |
|
49 /** |
|
50 * Paints the specified component. |
|
51 * Subclasses should override this method and use |
|
52 * the specified {@code Graphics} object to |
|
53 * render the content of the component. |
|
54 * |
|
55 * @param g the {@code Graphics} context in which to paint; |
|
56 * @param c the component being painted; |
|
57 * it can be safely cast to the {@code JLayer<V>} |
|
58 */ |
|
59 @Override |
|
60 public void paint(Graphics g, JComponent c) { |
|
61 c.paint(g); |
|
62 } |
|
63 |
|
64 /** |
|
65 * Dispatches {@code AWTEvent}s for {@code JLayer} |
|
66 * and <b>all it subcomponents</b> to this {@code LayerUI} instance. |
|
67 * <p> |
|
68 * To enable the {@code AWTEvent} of the particular type, |
|
69 * you call {@link javax.swing.JLayer#setLayerEventMask} |
|
70 * in {@link #installUI(javax.swing.JComponent)} |
|
71 * and set the layer event mask to {@code 0} |
|
72 * in {@link #uninstallUI(javax.swing.JComponent)} after that |
|
73 * |
|
74 * @param e the event to be dispatched |
|
75 * @param l the layer this LayerUI is set to |
|
76 * |
|
77 * @see JLayer#setLayerEventMask(long) |
|
78 * @see javax.swing.JLayer#getLayerEventMask() |
|
79 */ |
|
80 public void eventDispatched(AWTEvent e, JLayer<? extends V> l){ |
|
81 } |
|
82 |
|
83 /** |
|
84 * Invoked when {@link javax.swing.JLayer#updateUI()} is called |
|
85 * by the {@code JLayer} this {@code LayerUI} is set to. |
|
86 * |
|
87 * @param l the {@code JLayer} which UI is updated |
|
88 */ |
|
89 public void updateUI(JLayer<? extends V> l){ |
|
90 } |
|
91 |
|
92 /** |
|
93 * Configures the {@code JLayer} this {@code LayerUI} is set to. |
|
94 * The default implementation registers the {@code LayerUI} |
|
95 * as a property change listener for the passed {@code JLayer} component. |
|
96 * |
|
97 * @param c the {@code JLayer} component where this UI delegate is being installed |
|
98 */ |
|
99 public void installUI(JComponent c) { |
|
100 addPropertyChangeListener((JLayer) c); |
|
101 } |
|
102 |
|
103 /** |
|
104 * Reverses the configuration which was previously set |
|
105 * in the {@link #installUI(JComponent)} method. |
|
106 * The default implementation unregisters the property change listener |
|
107 * for the passed JLayer component. |
|
108 * |
|
109 * @param c the component from which this UI delegate is being removed. |
|
110 */ |
|
111 public void uninstallUI(JComponent c) { |
|
112 removePropertyChangeListener((JLayer) c); |
|
113 } |
|
114 |
|
115 /** |
|
116 * Adds a PropertyChangeListener to the listener list. The listener is |
|
117 * registered for all bound properties of this class. |
|
118 * <p/> |
|
119 * If {@code listener} is {@code null}, |
|
120 * no exception is thrown and no action is performed. |
|
121 * |
|
122 * @param listener the property change listener to be added |
|
123 * @see #removePropertyChangeListener |
|
124 * @see #getPropertyChangeListeners |
|
125 * @see #addPropertyChangeListener(String, java.beans.PropertyChangeListener) |
|
126 */ |
|
127 public void addPropertyChangeListener(PropertyChangeListener listener) { |
|
128 propertyChangeSupport.addPropertyChangeListener(listener); |
|
129 } |
|
130 |
|
131 /** |
|
132 * Removes a PropertyChangeListener from the listener list. This method |
|
133 * should be used to remove PropertyChangeListeners that were registered |
|
134 * for all bound properties of this class. |
|
135 * <p/> |
|
136 * If {@code listener} is {@code null}, |
|
137 * no exception is thrown and no action is performed. |
|
138 * |
|
139 * @param listener the PropertyChangeListener to be removed |
|
140 * @see #addPropertyChangeListener |
|
141 * @see #getPropertyChangeListeners |
|
142 * @see #removePropertyChangeListener(String, PropertyChangeListener) |
|
143 */ |
|
144 public void removePropertyChangeListener(PropertyChangeListener listener) { |
|
145 propertyChangeSupport.removePropertyChangeListener(listener); |
|
146 } |
|
147 |
|
148 /** |
|
149 * Returns an array of all the property change listeners |
|
150 * registered on this component. |
|
151 * |
|
152 * @return all of this ui's {@code PropertyChangeListener}s |
|
153 * or an empty array if no property change |
|
154 * listeners are currently registered |
|
155 * @see #addPropertyChangeListener |
|
156 * @see #removePropertyChangeListener |
|
157 * @see #getPropertyChangeListeners(String) |
|
158 */ |
|
159 public PropertyChangeListener[] getPropertyChangeListeners() { |
|
160 return propertyChangeSupport.getPropertyChangeListeners(); |
|
161 } |
|
162 |
|
163 /** |
|
164 * Adds a PropertyChangeListener to the listener list for a specific |
|
165 * property. |
|
166 * <p/> |
|
167 * If {@code propertyName} or {@code listener} is {@code null}, |
|
168 * no exception is thrown and no action is taken. |
|
169 * |
|
170 * @param propertyName one of the property names listed above |
|
171 * @param listener the property change listener to be added |
|
172 * @see #removePropertyChangeListener(String, PropertyChangeListener) |
|
173 * @see #getPropertyChangeListeners(String) |
|
174 * @see #addPropertyChangeListener(String, PropertyChangeListener) |
|
175 */ |
|
176 public void addPropertyChangeListener(String propertyName, |
|
177 PropertyChangeListener listener) { |
|
178 propertyChangeSupport.addPropertyChangeListener(propertyName, listener); |
|
179 } |
|
180 |
|
181 /** |
|
182 * Removes a {@code PropertyChangeListener} from the listener |
|
183 * list for a specific property. This method should be used to remove |
|
184 * {@code PropertyChangeListener}s |
|
185 * that were registered for a specific bound property. |
|
186 * <p/> |
|
187 * If {@code propertyName} or {@code listener} is {@code null}, |
|
188 * no exception is thrown and no action is taken. |
|
189 * |
|
190 * @param propertyName a valid property name |
|
191 * @param listener the PropertyChangeListener to be removed |
|
192 * @see #addPropertyChangeListener(String, PropertyChangeListener) |
|
193 * @see #getPropertyChangeListeners(String) |
|
194 * @see #removePropertyChangeListener(PropertyChangeListener) |
|
195 */ |
|
196 public void removePropertyChangeListener(String propertyName, |
|
197 PropertyChangeListener listener) { |
|
198 propertyChangeSupport.removePropertyChangeListener(propertyName, listener); |
|
199 } |
|
200 |
|
201 /** |
|
202 * Returns an array of all the listeners which have been associated |
|
203 * with the named property. |
|
204 * |
|
205 * @return all of the {@code PropertyChangeListener}s associated with |
|
206 * the named property; if no such listeners have been added or |
|
207 * if {@code propertyName} is {@code null}, an empty |
|
208 * array is returned |
|
209 * @see #addPropertyChangeListener(String, PropertyChangeListener) |
|
210 * @see #removePropertyChangeListener(String, PropertyChangeListener) |
|
211 * @see #getPropertyChangeListeners |
|
212 */ |
|
213 public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) { |
|
214 return propertyChangeSupport.getPropertyChangeListeners(propertyName); |
|
215 } |
|
216 |
|
217 /** |
|
218 * Support for reporting bound property changes for Object properties. |
|
219 * This method can be called when a bound property has changed and it will |
|
220 * send the appropriate PropertyChangeEvent to any registered |
|
221 * PropertyChangeListeners. |
|
222 * |
|
223 * @param propertyName the property whose value has changed |
|
224 * @param oldValue the property's previous value |
|
225 * @param newValue the property's new value |
|
226 */ |
|
227 protected void firePropertyChange(String propertyName, |
|
228 Object oldValue, Object newValue) { |
|
229 propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue); |
|
230 } |
|
231 |
|
232 /** |
|
233 * Notifies the {@code LayerUI} when any of its property are changed |
|
234 * and enables updating every {@code JLayer} this {@code LayerUI} instance is set to. |
|
235 * |
|
236 * @param evt the PropertyChangeEvent generated by this {@code LayerUI} |
|
237 * @param l the {@code JLayer} this LayerUI is set to |
|
238 */ |
|
239 public void applyPropertyChange(PropertyChangeEvent evt, JLayer<? extends V> l) { |
|
240 } |
|
241 |
|
242 /** |
|
243 * Returns the preferred size of the viewport for a view component. |
|
244 * |
|
245 * @return the preferred size of the viewport for a view component |
|
246 * @see Scrollable#getPreferredScrollableViewportSize() |
|
247 */ |
|
248 public Dimension getPreferredScrollableViewportSize(JLayer<? extends V> l) { |
|
249 if (l.getView() instanceof Scrollable) { |
|
250 return ((Scrollable)l.getView()).getPreferredScrollableViewportSize(); |
|
251 } |
|
252 return l.getPreferredSize(); |
|
253 } |
|
254 |
|
255 /** |
|
256 * Returns a scroll increment, which is required for components |
|
257 * that display logical rows or columns in order to completely expose |
|
258 * one block of rows or columns, depending on the value of orientation. |
|
259 * |
|
260 * @return the "block" increment for scrolling in the specified direction |
|
261 * @see Scrollable#getScrollableBlockIncrement(Rectangle, int, int) |
|
262 */ |
|
263 public int getScrollableBlockIncrement(JLayer<? extends V> l, |
|
264 Rectangle visibleRect, |
|
265 int orientation, int direction) { |
|
266 if (l.getView() instanceof Scrollable) { |
|
267 return ((Scrollable)l.getView()).getScrollableBlockIncrement( |
|
268 visibleRect,orientation, direction); |
|
269 } |
|
270 return (orientation == SwingConstants.VERTICAL) ? visibleRect.height : |
|
271 visibleRect.width; |
|
272 } |
|
273 |
|
274 /** |
|
275 * Returns {@code false} to indicate that the height of the viewport does not |
|
276 * determine the height of the layer, unless the preferred height |
|
277 * of the layer is smaller than the height of the viewport. |
|
278 * |
|
279 * @return whether the layer should track the height of the viewport |
|
280 * @see Scrollable#getScrollableTracksViewportHeight() |
|
281 */ |
|
282 public boolean getScrollableTracksViewportHeight(JLayer<? extends V> l) { |
|
283 if (l.getView() instanceof Scrollable) { |
|
284 return ((Scrollable)l.getView()).getScrollableTracksViewportHeight(); |
|
285 } |
|
286 if (l.getParent() instanceof JViewport) { |
|
287 return (((JViewport)l.getParent()).getHeight() > l.getPreferredSize().height); |
|
288 } |
|
289 return false; |
|
290 } |
|
291 |
|
292 /** |
|
293 * Returns {@code false} to indicate that the width of the viewport does not |
|
294 * determine the width of the layer, unless the preferred width |
|
295 * of the layer is smaller than the width of the viewport. |
|
296 * |
|
297 * @return whether the layer should track the width of the viewport |
|
298 * @see Scrollable |
|
299 * @see LayerUI#getScrollableTracksViewportWidth(JLayer) |
|
300 */ |
|
301 public boolean getScrollableTracksViewportWidth(JLayer<? extends V> l) { |
|
302 if (l.getView() instanceof Scrollable) { |
|
303 return ((Scrollable)l.getView()).getScrollableTracksViewportWidth(); |
|
304 } |
|
305 if (l.getParent() instanceof JViewport) { |
|
306 return (((JViewport)l.getParent()).getWidth() > l.getPreferredSize().width); |
|
307 } |
|
308 return false; |
|
309 } |
|
310 |
|
311 /** |
|
312 * Returns a scroll increment, which is required for components |
|
313 * that display logical rows or columns in order to completely expose |
|
314 * one new row or column, depending on the value of orientation. |
|
315 * Ideally, components should handle a partially exposed row or column |
|
316 * by returning the distance required to completely expose the item. |
|
317 * <p> |
|
318 * Scrolling containers, like JScrollPane, will use this method |
|
319 * each time the user requests a unit scroll. |
|
320 * |
|
321 * @return The "unit" increment for scrolling in the specified direction. |
|
322 * This value should always be positive. |
|
323 * @see Scrollable#getScrollableUnitIncrement(Rectangle, int, int) |
|
324 */ |
|
325 public int getScrollableUnitIncrement(JLayer<? extends V> l, |
|
326 Rectangle visibleRect, |
|
327 int orientation, int direction) { |
|
328 if (l.getView() instanceof Scrollable) { |
|
329 return ((Scrollable)l.getView()).getScrollableUnitIncrement( |
|
330 visibleRect, orientation, direction); |
|
331 } |
|
332 return 1; |
|
333 } |
|
334 |
|
335 /** |
|
336 * If the {@code JLayer}'s view component is not {@code null}, |
|
337 * this calls the view's {@code getBaseline()} method. |
|
338 * Otherwise, the default implementation is called. |
|
339 * |
|
340 * @param c {@code JLayer} to return baseline resize behavior for |
|
341 * @param width the width to get the baseline for |
|
342 * @param height the height to get the baseline for |
|
343 * @return baseline or a value < 0 indicating there is no reasonable |
|
344 * baseline |
|
345 */ |
|
346 public int getBaseline(JComponent c, int width, int height) { |
|
347 JLayer l = (JLayer) c; |
|
348 if (l.getView() != null) { |
|
349 return l.getView().getBaseline(width, height); |
|
350 } |
|
351 return super.getBaseline(c, width, height); |
|
352 } |
|
353 |
|
354 /** |
|
355 * If the {@code JLayer}'s view component is not {@code null}, |
|
356 * this calls the view's {@code getBaselineResizeBehavior()} method. |
|
357 * Otherwise, the default implementation is called. |
|
358 * |
|
359 * @param c {@code JLayer} to return baseline resize behavior for |
|
360 * @return an enum indicating how the baseline changes as the component |
|
361 * size changes |
|
362 */ |
|
363 public Component.BaselineResizeBehavior getBaselineResizeBehavior(JComponent c) { |
|
364 JLayer l = (JLayer) c; |
|
365 if (l.getView() != null) { |
|
366 return l.getView().getBaselineResizeBehavior(); |
|
367 } |
|
368 return super.getBaselineResizeBehavior(c); |
|
369 } |
|
370 } |