1 /* 2 * Copyright (c) 1997, 2016, 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; 27 28 import javax.swing.JComponent; 29 import javax.swing.SwingUtilities; 30 import javax.accessibility.Accessible; 31 32 import java.awt.Component; 33 import java.awt.Dimension; 34 import java.awt.Graphics; 35 import javax.swing.UIManager; 36 import sun.swing.SwingUtilities2; 37 38 39 /** 40 * The base class for all UI delegate objects in the Swing pluggable 41 * look and feel architecture. The UI delegate object for a Swing 42 * component is responsible for implementing the aspects of the 43 * component that depend on the look and feel. 44 * The <code>JComponent</code> class 45 * invokes methods from this class in order to delegate operations 46 * (painting, layout calculations, etc.) that may vary depending on the 47 * look and feel installed. <b>Client programs should not invoke methods 48 * on this class directly.</b> 49 * 50 * @see javax.swing.JComponent 51 * @see javax.swing.UIManager 52 * 53 */ 54 public abstract class ComponentUI { 55 56 private TextUIDrawing textUIDrawing; 57 58 /** 59 * Sole constructor. (For invocation by subclass constructors, 60 * typically implicit.) 61 */ 62 public ComponentUI() { 63 } 64 65 /** 66 * Configures the specified component appropriately for the look and feel. 67 * This method is invoked when the <code>ComponentUI</code> instance is being installed 68 * as the UI delegate on the specified component. This method should 69 * completely configure the component for the look and feel, 70 * including the following: 71 * <ol> 72 * <li>Install default property values for color, fonts, borders, 73 * icons, opacity, etc. on the component. Whenever possible, 74 * property values initialized by the client program should <i>not</i> 75 * be overridden. 76 * <li>Install a <code>LayoutManager</code> on the component if necessary. 77 * <li>Create/add any required sub-components to the component. 78 * <li>Create/install event listeners on the component. 79 * <li>Create/install a <code>PropertyChangeListener</code> on the component in order 80 * to detect and respond to component property changes appropriately. 81 * <li>Install keyboard UI (mnemonics, traversal, etc.) on the component. 82 * <li>Initialize any appropriate instance data. 83 * </ol> 84 * @param c the component where this UI delegate is being installed 85 * 86 * @see #uninstallUI 87 * @see javax.swing.JComponent#setUI 88 * @see javax.swing.JComponent#updateUI 89 */ 90 public void installUI(JComponent c) { 91 92 if (textUIDrawing == null || textUIDrawing instanceof UIResource) { 93 textUIDrawing = (TextUIDrawing) UIManager.get("uiDrawing.text"); 94 } 95 96 if (textUIDrawing == null) { 97 textUIDrawing = SwingUtilities2.DEFAULT_UI_TEXT_DRAWING; 98 } 99 } 100 101 /** 102 * Reverses configuration which was done on the specified component during 103 * <code>installUI</code>. This method is invoked when this 104 * <code>UIComponent</code> instance is being removed as the UI delegate 105 * for the specified component. This method should undo the 106 * configuration performed in <code>installUI</code>, being careful to 107 * leave the <code>JComponent</code> instance in a clean state (no 108 * extraneous listeners, look-and-feel-specific property objects, etc.). 109 * This should include the following: 110 * <ol> 111 * <li>Remove any UI-set borders from the component. 112 * <li>Remove any UI-set layout managers on the component. 113 * <li>Remove any UI-added sub-components from the component. 114 * <li>Remove any UI-added event/property listeners from the component. 115 * <li>Remove any UI-installed keyboard UI from the component. 116 * <li>Nullify any allocated instance data objects to allow for GC. 117 * </ol> 118 * @param c the component from which this UI delegate is being removed; 119 * this argument is often ignored, 120 * but might be used if the UI object is stateless 121 * and shared by multiple components 122 * 123 * @see #installUI 124 * @see javax.swing.JComponent#updateUI 125 */ 126 public void uninstallUI(JComponent c) { 127 if (textUIDrawing instanceof UIResource) { 128 textUIDrawing = null; 129 } 130 } 131 132 /** 133 * Paints the specified component appropriately for the look and feel. 134 * This method is invoked from the <code>ComponentUI.update</code> method when 135 * the specified component is being painted. Subclasses should override 136 * this method and use the specified <code>Graphics</code> object to 137 * render the content of the component. 138 * 139 * @param g the <code>Graphics</code> context in which to paint 140 * @param c the component being painted; 141 * this argument is often ignored, 142 * but might be used if the UI object is stateless 143 * and shared by multiple components 144 * 145 * @see #update 146 */ 147 public void paint(Graphics g, JComponent c) { 148 } 149 150 /** 151 * Notifies this UI delegate that it is time to paint the specified 152 * component. This method is invoked by <code>JComponent</code> 153 * when the specified component is being painted. 154 * 155 * <p>By default this method fills the specified component with 156 * its background color if its {@code opaque} property is {@code true}, 157 * and then immediately calls {@code paint}. In general this method need 158 * not be overridden by subclasses; all look-and-feel rendering code should 159 * reside in the {@code paint} method. 160 * 161 * @param g the <code>Graphics</code> context in which to paint 162 * @param c the component being painted; 163 * this argument is often ignored, 164 * but might be used if the UI object is stateless 165 * and shared by multiple components 166 * 167 * @see #paint 168 * @see javax.swing.JComponent#paintComponent 169 */ 170 public void update(Graphics g, JComponent c) { 171 if (c.isOpaque()) { 172 g.setColor(c.getBackground()); 173 g.fillRect(0, 0, c.getWidth(),c.getHeight()); 174 } 175 paint(g, c); 176 } 177 178 /** 179 * Returns the specified component's preferred size appropriate for 180 * the look and feel. If <code>null</code> is returned, the preferred 181 * size will be calculated by the component's layout manager instead 182 * (this is the preferred approach for any component with a specific 183 * layout manager installed). The default implementation of this 184 * method returns <code>null</code>. 185 * 186 * @param c the component whose preferred size is being queried; 187 * this argument is often ignored, 188 * but might be used if the UI object is stateless 189 * and shared by multiple components 190 * @return a {@code Dimension} object containing given component's preferred 191 * size appropriate for the look and feel 192 * @see javax.swing.JComponent#getPreferredSize 193 * @see java.awt.LayoutManager#preferredLayoutSize 194 */ 195 public Dimension getPreferredSize(JComponent c) { 196 return null; 197 } 198 199 /** 200 * Returns the specified component's minimum size appropriate for 201 * the look and feel. If <code>null</code> is returned, the minimum 202 * size will be calculated by the component's layout manager instead 203 * (this is the preferred approach for any component with a specific 204 * layout manager installed). The default implementation of this 205 * method invokes <code>getPreferredSize</code> and returns that value. 206 * 207 * @param c the component whose minimum size is being queried; 208 * this argument is often ignored, 209 * but might be used if the UI object is stateless 210 * and shared by multiple components 211 * 212 * @return a <code>Dimension</code> object or <code>null</code> 213 * 214 * @see javax.swing.JComponent#getMinimumSize 215 * @see java.awt.LayoutManager#minimumLayoutSize 216 * @see #getPreferredSize 217 */ 218 public Dimension getMinimumSize(JComponent c) { 219 return getPreferredSize(c); 220 } 221 222 /** 223 * Returns the specified component's maximum size appropriate for 224 * the look and feel. If <code>null</code> is returned, the maximum 225 * size will be calculated by the component's layout manager instead 226 * (this is the preferred approach for any component with a specific 227 * layout manager installed). The default implementation of this 228 * method invokes <code>getPreferredSize</code> and returns that value. 229 * 230 * @param c the component whose maximum size is being queried; 231 * this argument is often ignored, 232 * but might be used if the UI object is stateless 233 * and shared by multiple components 234 * @return a <code>Dimension</code> object or <code>null</code> 235 * 236 * @see javax.swing.JComponent#getMaximumSize 237 * @see java.awt.LayoutManager2#maximumLayoutSize 238 */ 239 public Dimension getMaximumSize(JComponent c) { 240 return getPreferredSize(c); 241 } 242 243 /** 244 * Returns <code>true</code> if the specified <i>x,y</i> location is 245 * contained within the look and feel's defined shape of the specified 246 * component. <code>x</code> and <code>y</code> are defined to be relative 247 * to the coordinate system of the specified component. Although 248 * a component's <code>bounds</code> is constrained to a rectangle, 249 * this method provides the means for defining a non-rectangular 250 * shape within those bounds for the purpose of hit detection. 251 * 252 * @param c the component where the <i>x,y</i> location is being queried; 253 * this argument is often ignored, 254 * but might be used if the UI object is stateless 255 * and shared by multiple components 256 * @param x the <i>x</i> coordinate of the point 257 * @param y the <i>y</i> coordinate of the point 258 * @return {@code true} if the specified {@code x,y} location is contained 259 * within the look and feel's defined shape for the given component 260 * @see javax.swing.JComponent#contains 261 * @see java.awt.Component#contains 262 */ 263 @SuppressWarnings("deprecation") 264 public boolean contains(JComponent c, int x, int y) { 265 return c.inside(x, y); 266 } 267 268 /** 269 * Returns an instance of the UI delegate for the specified component. 270 * Each subclass must provide its own static <code>createUI</code> 271 * method that returns an instance of that UI delegate subclass. 272 * If the UI delegate subclass is stateless, it may return an instance 273 * that is shared by multiple components. If the UI delegate is 274 * stateful, then it should return a new instance per component. 275 * The default implementation of this method throws an error, as it 276 * should never be invoked. 277 * 278 * @param c a {@code JComponent} for which to create a UI delegate 279 * @return a {@code ComponentUI} object for {@code c} 280 */ 281 public static ComponentUI createUI(JComponent c) { 282 throw new Error("ComponentUI.createUI not implemented."); 283 } 284 285 /** 286 * Returns the baseline. The baseline is measured from the top of 287 * the component. This method is primarily meant for 288 * <code>LayoutManager</code>s to align components along their 289 * baseline. A return value less than 0 indicates this component 290 * does not have a reasonable baseline and that 291 * <code>LayoutManager</code>s should not align this component on 292 * its baseline. 293 * <p> 294 * This method returns -1. Subclasses that have a meaningful baseline 295 * should override appropriately. 296 * 297 * @param c <code>JComponent</code> baseline is being requested for 298 * @param width the width to get the baseline for 299 * @param height the height to get the baseline for 300 * @throws NullPointerException if <code>c</code> is <code>null</code> 301 * @throws IllegalArgumentException if width or height is < 0 302 * @return baseline or a value < 0 indicating there is no reasonable 303 * baseline 304 * @see javax.swing.JComponent#getBaseline(int,int) 305 * @since 1.6 306 */ 307 public int getBaseline(JComponent c, int width, int height) { 308 if (c == null) { 309 throw new NullPointerException("Component must be non-null"); 310 } 311 if (width < 0 || height < 0) { 312 throw new IllegalArgumentException( 313 "Width and height must be >= 0"); 314 } 315 return -1; 316 } 317 318 /** 319 * Returns an enum indicating how the baseline of the component 320 * changes as the size changes. This method is primarily meant for 321 * layout managers and GUI builders. 322 * <p> 323 * This method returns <code>BaselineResizeBehavior.OTHER</code>. 324 * Subclasses that support a baseline should override appropriately. 325 * 326 * @param c <code>JComponent</code> to return baseline resize behavior for 327 * @return an enum indicating how the baseline changes as the component 328 * size changes 329 * @throws NullPointerException if <code>c</code> is <code>null</code> 330 * @see javax.swing.JComponent#getBaseline(int, int) 331 * @since 1.6 332 */ 333 public Component.BaselineResizeBehavior getBaselineResizeBehavior( 334 JComponent c) { 335 if (c == null) { 336 throw new NullPointerException("Component must be non-null"); 337 } 338 return Component.BaselineResizeBehavior.OTHER; 339 } 340 341 /** 342 * Returns the number of accessible children in the object. If all 343 * of the children of this object implement <code>Accessible</code>, 344 * this 345 * method should return the number of children of this object. 346 * UIs might wish to override this if they present areas on the 347 * screen that can be viewed as components, but actual components 348 * are not used for presenting those areas. 349 * 350 * Note: As of v1.3, it is recommended that developers call 351 * <code>Component.AccessibleAWTComponent.getAccessibleChildrenCount()</code> instead 352 * of this method. 353 * 354 * @param c {@code JComponent} for which to get count of accessible children 355 * @return the number of accessible children in the object 356 * @see #getAccessibleChild 357 */ 358 public int getAccessibleChildrenCount(JComponent c) { 359 return SwingUtilities.getAccessibleChildrenCount(c); 360 } 361 362 /** 363 * Returns the <code>i</code>th <code>Accessible</code> child of the object. 364 * UIs might need to override this if they present areas on the 365 * screen that can be viewed as components, but actual components 366 * are not used for presenting those areas. 367 * 368 * <p> 369 * 370 * Note: As of v1.3, it is recommended that developers call 371 * <code>Component.AccessibleAWTComponent.getAccessibleChild()</code> instead of 372 * this method. 373 * 374 * @param c a {@code JComponent} for which to get a child object 375 * @param i zero-based index of child 376 * @return the <code>i</code>th <code>Accessible</code> child of the object 377 * @see #getAccessibleChildrenCount 378 */ 379 public Accessible getAccessibleChild(JComponent c, int i) { 380 return SwingUtilities.getAccessibleChild(c, i); 381 } 382 383 /** 384 * Returns the {@code TextUIDrawing} instance responsible for text drawing 385 * and measuring. 386 * 387 * @return {@code TextUIDrawing} instance 388 * 389 * @since 9 390 */ 391 public TextUIDrawing getTextUIDrawing() { 392 return textUIDrawing; 393 } 394 }