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 package javax.swing.plaf.synth; 26 27 import sun.awt.AppContext; 28 29 import java.util.HashMap; 30 import java.util.Locale; 31 import java.util.Map; 32 import javax.swing.JComponent; 33 import javax.swing.UIDefaults; 34 35 /** 36 * A distinct rendering area of a Swing component. A component may 37 * support one or more regions. Specific component regions are defined 38 * by the typesafe enumeration in this class. 39 * <p> 40 * Regions are typically used as a way to identify the <code>Component</code>s 41 * and areas a particular style is to apply to. Synth's file format allows you 42 * to bind styles based on the name of a <code>Region</code>. 43 * The name is derived from the field name of the constant: 44 * <ol> 45 * <li>Map all characters to lowercase. 46 * <li>Map the first character to uppercase. 47 * <li>Map the first character after underscores to uppercase. 48 * <li>Remove all underscores. 49 * </ol> 50 * For example, to identify the <code>SPLIT_PANE</code> 51 * <code>Region</code> you would use <code>SplitPane</code>. 52 * The following shows a custom <code>SynthStyleFactory</code> 53 * that returns a specific style for split panes: 54 * <pre> 55 * public SynthStyle getStyle(JComponent c, Region id) { 56 * if (id == Region.SPLIT_PANE) { 57 * return splitPaneStyle; 58 * } 59 * ... 60 * } 61 * </pre> 62 * The following <a href="doc-files/synthFileFormat.html">xml</a> 63 * accomplishes the same thing: 64 * <pre> 65 * <style id="splitPaneStyle"> 66 * ... 67 * </style> 68 * <bind style="splitPaneStyle" type="region" key="SplitPane"/> 69 * </pre> 70 * 71 * @since 1.5 72 * @author Scott Violet 73 */ 74 public class Region { 75 private static final Object UI_TO_REGION_MAP_KEY = new Object(); 76 private static final Object LOWER_CASE_NAME_MAP_KEY = new Object(); 77 78 /** 79 * ArrowButton's are special types of buttons that also render a 80 * directional indicator, typically an arrow. ArrowButtons are used by 81 * composite components, for example ScrollBar's contain ArrowButtons. 82 * To bind a style to this <code>Region</code> use the name 83 * <code>ArrowButton</code>. 84 */ 85 public static final Region ARROW_BUTTON = new Region("ArrowButton", false); 86 87 /** 88 * Button region. To bind a style to this <code>Region</code> use the name 89 * <code>Button</code>. 90 */ 91 public static final Region BUTTON = new Region("Button", false); 92 93 /** 94 * CheckBox region. To bind a style to this <code>Region</code> use the name 95 * <code>CheckBox</code>. 96 */ 97 public static final Region CHECK_BOX = new Region("CheckBox", false); 98 99 /** 100 * CheckBoxMenuItem region. To bind a style to this <code>Region</code> use 101 * the name <code>CheckBoxMenuItem</code>. 102 */ 103 public static final Region CHECK_BOX_MENU_ITEM = new Region("CheckBoxMenuItem", false); 104 105 /** 106 * ColorChooser region. To bind a style to this <code>Region</code> use 107 * the name <code>ColorChooser</code>. 108 */ 109 public static final Region COLOR_CHOOSER = new Region("ColorChooser", false); 110 111 /** 112 * ComboBox region. To bind a style to this <code>Region</code> use 113 * the name <code>ComboBox</code>. 114 */ 115 public static final Region COMBO_BOX = new Region("ComboBox", false); 116 117 /** 118 * DesktopPane region. To bind a style to this <code>Region</code> use 119 * the name <code>DesktopPane</code>. 120 */ 121 public static final Region DESKTOP_PANE = new Region("DesktopPane", false); 122 123 /** 124 * DesktopIcon region. To bind a style to this <code>Region</code> use 125 * the name <code>DesktopIcon</code>. 126 */ 127 public static final Region DESKTOP_ICON = new Region("DesktopIcon", false); 128 129 /** 130 * EditorPane region. To bind a style to this <code>Region</code> use 131 * the name <code>EditorPane</code>. 132 */ 133 public static final Region EDITOR_PANE = new Region("EditorPane", false); 134 135 /** 136 * FileChooser region. To bind a style to this <code>Region</code> use 137 * the name <code>FileChooser</code>. 138 */ 139 public static final Region FILE_CHOOSER = new Region("FileChooser", false); 140 141 /** 142 * FormattedTextField region. To bind a style to this <code>Region</code> use 143 * the name <code>FormattedTextField</code>. 144 */ 145 public static final Region FORMATTED_TEXT_FIELD = new Region("FormattedTextField", false); 146 147 /** 148 * InternalFrame region. To bind a style to this <code>Region</code> use 149 * the name <code>InternalFrame</code>. 150 */ 151 public static final Region INTERNAL_FRAME = new Region("InternalFrame", false); 152 153 /** 154 * TitlePane of an InternalFrame. The TitlePane typically 155 * shows a menu, title, widgets to manipulate the internal frame. 156 * To bind a style to this <code>Region</code> use the name 157 * <code>InternalFrameTitlePane</code>. 158 */ 159 public static final Region INTERNAL_FRAME_TITLE_PANE = new Region("InternalFrameTitlePane", false); 160 161 /** 162 * Label region. To bind a style to this <code>Region</code> use the name 163 * <code>Label</code>. 164 */ 165 public static final Region LABEL = new Region("Label", false); 166 167 /** 168 * List region. To bind a style to this <code>Region</code> use the name 169 * <code>List</code>. 170 */ 171 public static final Region LIST = new Region("List", false); 172 173 /** 174 * Menu region. To bind a style to this <code>Region</code> use the name 175 * <code>Menu</code>. 176 */ 177 public static final Region MENU = new Region("Menu", false); 178 179 /** 180 * MenuBar region. To bind a style to this <code>Region</code> use the name 181 * <code>MenuBar</code>. 182 */ 183 public static final Region MENU_BAR = new Region("MenuBar", false); 184 185 /** 186 * MenuItem region. To bind a style to this <code>Region</code> use the name 187 * <code>MenuItem</code>. 188 */ 189 public static final Region MENU_ITEM = new Region("MenuItem", false); 190 191 /** 192 * Accelerator region of a MenuItem. To bind a style to this 193 * <code>Region</code> use the name <code>MenuItemAccelerator</code>. 194 */ 195 public static final Region MENU_ITEM_ACCELERATOR = new Region("MenuItemAccelerator", true); 196 197 /** 198 * OptionPane region. To bind a style to this <code>Region</code> use 199 * the name <code>OptionPane</code>. 200 */ 201 public static final Region OPTION_PANE = new Region("OptionPane", false); 202 203 /** 204 * Panel region. To bind a style to this <code>Region</code> use the name 205 * <code>Panel</code>. 206 */ 207 public static final Region PANEL = new Region("Panel", false); 208 209 /** 210 * PasswordField region. To bind a style to this <code>Region</code> use 211 * the name <code>PasswordField</code>. 212 */ 213 public static final Region PASSWORD_FIELD = new Region("PasswordField", false); 214 215 /** 216 * PopupMenu region. To bind a style to this <code>Region</code> use 217 * the name <code>PopupMenu</code>. 218 */ 219 public static final Region POPUP_MENU = new Region("PopupMenu", false); 220 221 /** 222 * PopupMenuSeparator region. To bind a style to this <code>Region</code> 223 * use the name <code>PopupMenuSeparator</code>. 224 */ 225 public static final Region POPUP_MENU_SEPARATOR = new Region("PopupMenuSeparator", false); 226 227 /** 228 * ProgressBar region. To bind a style to this <code>Region</code> 229 * use the name <code>ProgressBar</code>. 230 */ 231 public static final Region PROGRESS_BAR = new Region("ProgressBar", false); 232 233 /** 234 * RadioButton region. To bind a style to this <code>Region</code> 235 * use the name <code>RadioButton</code>. 236 */ 237 public static final Region RADIO_BUTTON = new Region("RadioButton", false); 238 239 /** 240 * RegionButtonMenuItem region. To bind a style to this <code>Region</code> 241 * use the name <code>RadioButtonMenuItem</code>. 242 */ 243 public static final Region RADIO_BUTTON_MENU_ITEM = new Region("RadioButtonMenuItem", false); 244 245 /** 246 * RootPane region. To bind a style to this <code>Region</code> use 247 * the name <code>RootPane</code>. 248 */ 249 public static final Region ROOT_PANE = new Region("RootPane", false); 250 251 /** 252 * ScrollBar region. To bind a style to this <code>Region</code> use 253 * the name <code>ScrollBar</code>. 254 */ 255 public static final Region SCROLL_BAR = new Region("ScrollBar", false); 256 257 /** 258 * Track of the ScrollBar. To bind a style to this <code>Region</code> use 259 * the name <code>ScrollBarTrack</code>. 260 */ 261 public static final Region SCROLL_BAR_TRACK = new Region("ScrollBarTrack", true); 262 263 /** 264 * Thumb of the ScrollBar. The thumb is the region of the ScrollBar 265 * that gives a graphical depiction of what percentage of the View is 266 * currently visible. To bind a style to this <code>Region</code> use 267 * the name <code>ScrollBarThumb</code>. 268 */ 269 public static final Region SCROLL_BAR_THUMB = new Region("ScrollBarThumb", true); 270 271 /** 272 * ScrollPane region. To bind a style to this <code>Region</code> use 273 * the name <code>ScrollPane</code>. 274 */ 275 public static final Region SCROLL_PANE = new Region("ScrollPane", false); 276 277 /** 278 * Separator region. To bind a style to this <code>Region</code> use 279 * the name <code>Separator</code>. 280 */ 281 public static final Region SEPARATOR = new Region("Separator", false); 282 283 /** 284 * Slider region. To bind a style to this <code>Region</code> use 285 * the name <code>Slider</code>. 286 */ 287 public static final Region SLIDER = new Region("Slider", false); 288 289 /** 290 * Track of the Slider. To bind a style to this <code>Region</code> use 291 * the name <code>SliderTrack</code>. 292 */ 293 public static final Region SLIDER_TRACK = new Region("SliderTrack", true); 294 295 /** 296 * Thumb of the Slider. The thumb of the Slider identifies the current 297 * value. To bind a style to this <code>Region</code> use the name 298 * <code>SliderThumb</code>. 299 */ 300 public static final Region SLIDER_THUMB = new Region("SliderThumb", true); 301 302 /** 303 * Spinner region. To bind a style to this <code>Region</code> use the name 304 * <code>Spinner</code>. 305 */ 306 public static final Region SPINNER = new Region("Spinner", false); 307 308 /** 309 * SplitPane region. To bind a style to this <code>Region</code> use the name 310 * <code>SplitPane</code>. 311 */ 312 public static final Region SPLIT_PANE = new Region("SplitPane", false); 313 314 /** 315 * Divider of the SplitPane. To bind a style to this <code>Region</code> 316 * use the name <code>SplitPaneDivider</code>. 317 */ 318 public static final Region SPLIT_PANE_DIVIDER = new Region("SplitPaneDivider", true); 319 320 /** 321 * TabbedPane region. To bind a style to this <code>Region</code> use 322 * the name <code>TabbedPane</code>. 323 */ 324 public static final Region TABBED_PANE = new Region("TabbedPane", false); 325 326 /** 327 * Region of a TabbedPane for one tab. To bind a style to this 328 * <code>Region</code> use the name <code>TabbedPaneTab</code>. 329 */ 330 public static final Region TABBED_PANE_TAB = new Region("TabbedPaneTab", true); 331 332 /** 333 * Region of a TabbedPane containing the tabs. To bind a style to this 334 * <code>Region</code> use the name <code>TabbedPaneTabArea</code>. 335 */ 336 public static final Region TABBED_PANE_TAB_AREA = new Region("TabbedPaneTabArea", true); 337 338 /** 339 * Region of a TabbedPane containing the content. To bind a style to this 340 * <code>Region</code> use the name <code>TabbedPaneContent</code>. 341 */ 342 public static final Region TABBED_PANE_CONTENT = new Region("TabbedPaneContent", true); 343 344 /** 345 * Table region. To bind a style to this <code>Region</code> use 346 * the name <code>Table</code>. 347 */ 348 public static final Region TABLE = new Region("Table", false); 349 350 /** 351 * TableHeader region. To bind a style to this <code>Region</code> use 352 * the name <code>TableHeader</code>. 353 */ 354 public static final Region TABLE_HEADER = new Region("TableHeader", false); 355 356 /** 357 * TextArea region. To bind a style to this <code>Region</code> use 358 * the name <code>TextArea</code>. 359 */ 360 public static final Region TEXT_AREA = new Region("TextArea", false); 361 362 /** 363 * TextField region. To bind a style to this <code>Region</code> use 364 * the name <code>TextField</code>. 365 */ 366 public static final Region TEXT_FIELD = new Region("TextField", false); 367 368 /** 369 * TextPane region. To bind a style to this <code>Region</code> use 370 * the name <code>TextPane</code>. 371 */ 372 public static final Region TEXT_PANE = new Region("TextPane", false); 373 374 /** 375 * ToggleButton region. To bind a style to this <code>Region</code> use 376 * the name <code>ToggleButton</code>. 377 */ 378 public static final Region TOGGLE_BUTTON = new Region("ToggleButton", false); 379 380 /** 381 * ToolBar region. To bind a style to this <code>Region</code> use 382 * the name <code>ToolBar</code>. 383 */ 384 public static final Region TOOL_BAR = new Region("ToolBar", false); 385 386 /** 387 * Region of the ToolBar containing the content. To bind a style to this 388 * <code>Region</code> use the name <code>ToolBarContent</code>. 389 */ 390 public static final Region TOOL_BAR_CONTENT = new Region("ToolBarContent", true); 391 392 /** 393 * Region for the Window containing the ToolBar. To bind a style to this 394 * <code>Region</code> use the name <code>ToolBarDragWindow</code>. 395 */ 396 public static final Region TOOL_BAR_DRAG_WINDOW = new Region("ToolBarDragWindow", false); 397 398 /** 399 * ToolTip region. To bind a style to this <code>Region</code> use 400 * the name <code>ToolTip</code>. 401 */ 402 public static final Region TOOL_TIP = new Region("ToolTip", false); 403 404 /** 405 * ToolBar separator region. To bind a style to this <code>Region</code> use 406 * the name <code>ToolBarSeparator</code>. 407 */ 408 public static final Region TOOL_BAR_SEPARATOR = new Region("ToolBarSeparator", false); 409 410 /** 411 * Tree region. To bind a style to this <code>Region</code> use the name 412 * <code>Tree</code>. 413 */ 414 public static final Region TREE = new Region("Tree", false); 415 416 /** 417 * Region of the Tree for one cell. To bind a style to this 418 * <code>Region</code> use the name <code>TreeCell</code>. 419 */ 420 public static final Region TREE_CELL = new Region("TreeCell", true); 421 422 /** 423 * Viewport region. To bind a style to this <code>Region</code> use 424 * the name <code>Viewport</code>. 425 */ 426 public static final Region VIEWPORT = new Region("Viewport", false); 427 428 private static Map<String, Region> getUItoRegionMap() { 429 AppContext context = AppContext.getAppContext(); 430 @SuppressWarnings("unchecked") 431 Map<String, Region> map = (Map<String, Region>) context.get(UI_TO_REGION_MAP_KEY); 432 if (map == null) { 433 map = new HashMap<String, Region>(); 434 map.put("ArrowButtonUI", ARROW_BUTTON); 435 map.put("ButtonUI", BUTTON); 436 map.put("CheckBoxUI", CHECK_BOX); 437 map.put("CheckBoxMenuItemUI", CHECK_BOX_MENU_ITEM); 438 map.put("ColorChooserUI", COLOR_CHOOSER); 439 map.put("ComboBoxUI", COMBO_BOX); 440 map.put("DesktopPaneUI", DESKTOP_PANE); 441 map.put("DesktopIconUI", DESKTOP_ICON); 442 map.put("EditorPaneUI", EDITOR_PANE); 443 map.put("FileChooserUI", FILE_CHOOSER); 444 map.put("FormattedTextFieldUI", FORMATTED_TEXT_FIELD); 445 map.put("InternalFrameUI", INTERNAL_FRAME); 446 map.put("InternalFrameTitlePaneUI", INTERNAL_FRAME_TITLE_PANE); 447 map.put("LabelUI", LABEL); 448 map.put("ListUI", LIST); 449 map.put("MenuUI", MENU); 450 map.put("MenuBarUI", MENU_BAR); 451 map.put("MenuItemUI", MENU_ITEM); 452 map.put("OptionPaneUI", OPTION_PANE); 453 map.put("PanelUI", PANEL); 454 map.put("PasswordFieldUI", PASSWORD_FIELD); 455 map.put("PopupMenuUI", POPUP_MENU); 456 map.put("PopupMenuSeparatorUI", POPUP_MENU_SEPARATOR); 457 map.put("ProgressBarUI", PROGRESS_BAR); 458 map.put("RadioButtonUI", RADIO_BUTTON); 459 map.put("RadioButtonMenuItemUI", RADIO_BUTTON_MENU_ITEM); 460 map.put("RootPaneUI", ROOT_PANE); 461 map.put("ScrollBarUI", SCROLL_BAR); 462 map.put("ScrollPaneUI", SCROLL_PANE); 463 map.put("SeparatorUI", SEPARATOR); 464 map.put("SliderUI", SLIDER); 465 map.put("SpinnerUI", SPINNER); 466 map.put("SplitPaneUI", SPLIT_PANE); 467 map.put("TabbedPaneUI", TABBED_PANE); 468 map.put("TableUI", TABLE); 469 map.put("TableHeaderUI", TABLE_HEADER); 470 map.put("TextAreaUI", TEXT_AREA); 471 map.put("TextFieldUI", TEXT_FIELD); 472 map.put("TextPaneUI", TEXT_PANE); 473 map.put("ToggleButtonUI", TOGGLE_BUTTON); 474 map.put("ToolBarUI", TOOL_BAR); 475 map.put("ToolTipUI", TOOL_TIP); 476 map.put("ToolBarSeparatorUI", TOOL_BAR_SEPARATOR); 477 map.put("TreeUI", TREE); 478 map.put("ViewportUI", VIEWPORT); 479 context.put(UI_TO_REGION_MAP_KEY, map); 480 } 481 return map; 482 } 483 484 private static Map<Region, String> getLowerCaseNameMap() { 485 AppContext context = AppContext.getAppContext(); 486 @SuppressWarnings("unchecked") 487 Map<Region, String> map = (Map<Region, String>) context.get(LOWER_CASE_NAME_MAP_KEY); 488 if (map == null) { 489 map = new HashMap<Region, String>(); 490 context.put(LOWER_CASE_NAME_MAP_KEY, map); 491 } 492 return map; 493 } 494 495 static Region getRegion(JComponent c) { 496 return getUItoRegionMap().get(c.getUIClassID()); 497 } 498 499 static void registerUIs(UIDefaults table) { 500 for (Object key : getUItoRegionMap().keySet()) { 501 table.put(key, "javax.swing.plaf.synth.SynthLookAndFeel"); 502 } 503 } 504 505 private final String name; 506 private final boolean subregion; 507 508 private Region(String name, boolean subregion) { 509 if (name == null) { 510 throw new NullPointerException("You must specify a non-null name"); 511 } 512 this.name = name; 513 this.subregion = subregion; 514 } 515 516 /** 517 * Creates a Region with the specified name. This should only be 518 * used if you are creating your own <code>JComponent</code> subclass 519 * with a custom <code>ComponentUI</code> class. 520 * 521 * @param name Name of the region 522 * @param ui String that will be returned from 523 * <code>component.getUIClassID</code>. This will be null 524 * if this is a subregion. 525 * @param subregion Whether or not this is a subregion. 526 */ 527 protected Region(String name, String ui, boolean subregion) { 528 this(name, subregion); 529 if (ui != null) { 530 getUItoRegionMap().put(ui, this); 531 } 532 } 533 534 /** 535 * Returns true if the Region is a subregion of a Component, otherwise 536 * false. For example, <code>Region.BUTTON</code> corresponds do a 537 * <code>Component</code> so that <code>Region.BUTTON.isSubregion()</code> 538 * returns false. 539 * 540 * @return true if the Region is a subregion of a Component. 541 */ 542 public boolean isSubregion() { 543 return subregion; 544 } 545 546 /** 547 * Returns the name of the region. 548 * 549 * @return name of the Region. 550 */ 551 public String getName() { 552 return name; 553 } 554 555 /** 556 * Returns the name, in lowercase. 557 * 558 * @return lower case representation of the name of the Region 559 */ 560 String getLowerCaseName() { 561 Map<Region, String> lowerCaseNameMap = getLowerCaseNameMap(); 562 String lowerCaseName = lowerCaseNameMap.get(this); 563 if (lowerCaseName == null) { 564 lowerCaseName = name.toLowerCase(Locale.ENGLISH); 565 lowerCaseNameMap.put(this, lowerCaseName); 566 } 567 return lowerCaseName; 568 } 569 570 /** 571 * Returns the name of the Region. 572 * 573 * @return name of the Region. 574 */ 575 @Override 576 public String toString() { 577 return name; 578 } 579 }