001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2006-2010 Sun Microsystems, Inc. 025 * Portions Copyright 2013-2015 ForgeRock AS. 026 */ 027package org.opends.quicksetup.ui; 028 029import static org.opends.messages.QuickSetupMessages.*; 030 031import java.awt.Color; 032import java.awt.Component; 033import java.awt.Font; 034import java.awt.Image; 035import java.awt.Insets; 036import java.awt.Rectangle; 037import java.awt.Toolkit; 038import java.awt.event.FocusEvent; 039import java.awt.event.FocusListener; 040import java.util.HashMap; 041 042import javax.swing.BorderFactory; 043import javax.swing.ImageIcon; 044import javax.swing.JButton; 045import javax.swing.JCheckBox; 046import javax.swing.JComponent; 047import javax.swing.JEditorPane; 048import javax.swing.JFrame; 049import javax.swing.JLabel; 050import javax.swing.JList; 051import javax.swing.JPanel; 052import javax.swing.JPasswordField; 053import javax.swing.JRadioButton; 054import javax.swing.JScrollBar; 055import javax.swing.JScrollPane; 056import javax.swing.JTextField; 057import javax.swing.ListCellRenderer; 058import javax.swing.SwingUtilities; 059import javax.swing.UIManager; 060import javax.swing.border.Border; 061import javax.swing.border.EmptyBorder; 062import javax.swing.text.JTextComponent; 063import javax.swing.text.html.HTMLEditorKit; 064 065import org.forgerock.i18n.LocalizableMessage; 066import org.forgerock.i18n.slf4j.LocalizedLogger; 067 068/** 069 * This class provides constants an methods to create Swing objects and to 070 * generate UI elements with a common look and feel. 071 * <p> 072 * When we want to change a color, a background or a font this is the class 073 * that should be modified. 074 */ 075public class UIFactory 076{ 077 private static boolean initialized; 078 private static String parentPackagePath; 079 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 080 081 /** Specifies the horizontal insets between buttons. */ 082 public static final int HORIZONTAL_INSET_BETWEEN_BUTTONS = 5; 083 084 /** Specifies the top inset for the steps. */ 085 public static final int TOP_INSET_STEP = 15; 086 087 /** Specifies the left inset for the steps. */ 088 public static final int LEFT_INSET_STEP = 5; 089 090 /** Specifies the extra left inset for the sub-steps. */ 091 public static final int LEFT_INSET_SUBSTEP = 20; 092 /** Specifies the top inset for the instructions sub panel. */ 093 public static final int TOP_INSET_INSTRUCTIONS_SUBPANEL = 5; 094 095 /** Specifies the top inset for input subpanel. */ 096 public static final int TOP_INSET_INPUT_SUBPANEL = 10; 097 098 /** Specifies the top inset for a primary field. */ 099 public static final int TOP_INSET_PRIMARY_FIELD = 10; 100 101 /** Specifies the top inset for a secondary field. */ 102 public static final int TOP_INSET_SECONDARY_FIELD = 5; 103 104 /** Specifies the top inset for a radio button. */ 105 public static final int TOP_INSET_RADIOBUTTON = 0; 106 107 /** Specifies the top inset for a radio button subordinate panel. */ 108 public static final int TOP_INSET_RADIO_SUBORDINATE = 0; 109 110 /** Specifies the top inset for the progress bar. */ 111 public static final int TOP_INSET_PROGRESS_BAR = 5; 112 113 /** Specifies the top inset for the progress text area. */ 114 public static final int TOP_INSET_PROGRESS_TEXTAREA = 4; 115 116 /** Specifies the top inset for the background image. */ 117 public static final int TOP_INSET_BACKGROUND = 70; 118 119 /** Specifies the top inset for the error message. */ 120 public static final int TOP_INSET_ERROR_MESSAGE = 10; 121 122 /** Specifies the top inset for the browse button. */ 123 public static final int TOP_INSET_BROWSE = 5; 124 125 /** Specifies the right inset for background image. */ 126 public static final int RIGHT_INSET_BACKGROUND = 20; 127 128 /** Specifies the left inset for the primary field. */ 129 public static final int LEFT_INSET_PRIMARY_FIELD = 10; 130 131 /** Specifies the left inset for the browse button. */ 132 public static final int LEFT_INSET_BROWSE = 10; 133 134 /** Specifies the left inset for radio subordinate panel. */ 135 public static final int LEFT_INSET_RADIO_SUBORDINATE = 35; 136 137 /** Specifies the left inset for the secondary field. */ 138 public static final int LEFT_INSET_SECONDARY_FIELD = 5; 139 140 /** Specifies the left inset for the background image. */ 141 public static final int LEFT_INSET_BACKGROUND = 20; 142 143 /** Specifies the left inset for the copy url button. */ 144 public static final int LEFT_INSET_COPY_BUTTON = 10; 145 146 /** Specifies the left inset for a subordinate subpanel. */ 147 public static final int LEFT_INSET_SUBPANEL_SUBORDINATE = 30; 148 149 /** Specifies the left inset for the progress bar. */ 150 public static final int BOTTOM_INSET_PROGRESS_BAR = 10; 151 152 /** Specifies the bottom inset for the background image. */ 153 public static final int BOTTOM_INSET_BACKGROUND = 30; 154 155 /** Specifies the top inset for a secondary field. */ 156 public static final int BOTTOM_INSET_SECONDARY_FIELD = 5; 157 158 /** Specifies the number of columns of a text field for a path. */ 159 public static final int PATH_FIELD_SIZE = 20; 160 161 /** Specifies the number of columns of a text field for a relative path. */ 162 public static final int RELATIVE_PATH_FIELD_SIZE = 10; 163 164 /** Specifies the number of columns of a text field for a host name. */ 165 public static final int HOST_FIELD_SIZE = 20; 166 167 /** Specifies the number of columns of a text field for a UID. */ 168 public static final int UID_FIELD_SIZE = 15; 169 170 /** Specifies the number of columns of a text field for a port. */ 171 public static final int PORT_FIELD_SIZE = 5; 172 173 /** Specifies the number of columns of a text field for a dn. */ 174 public static final int DN_FIELD_SIZE = 20; 175 176 /** Specifies the number of columns of a text field for a password. */ 177 public static final int PASSWORD_FIELD_SIZE = 15; 178 179 /** 180 * Specifies the number of columns of a text field for the number of entries. 181 */ 182 public static final int NUMBER_ENTRIES_FIELD_SIZE = 7; 183 184 /** Specifies the number of points for the width of the progress bar. */ 185 public static final int PROGRESS_BAR_SIZE = 220; 186 187 /** 188 * Specifies the number of extra points that we add to the minimum size of the 189 * dialog. 190 */ 191 public static final int EXTRA_DIALOG_HEIGHT = 75; 192 193 private static final Insets BUTTONS_PANEL_INSETS = new Insets(5, 0, 5, 10); 194 195 private static final Insets STEPS_PANEL_INSETS = new Insets(15, 10, 5, 10); 196 197 private static final Insets CURRENT_STEP_PANEL_INSETS = new Insets(15, 15, 15, 15); 198 199 private static final Insets EMPTY_INSETS = new Insets(0, 0, 0, 0); 200 201 /** Specifies the default background color. */ 202 public static final Color DEFAULT_BACKGROUND = getColor(INFO_DEFAULT_BACKGROUND_COLOR.get()); 203 204 /** Specifies the current step background color. */ 205 public static final Color CURRENT_STEP_PANEL_BACKGROUND = getColor(INFO_CURRENT_STEP_PANEL_BACKGROUND_COLOR.get()); 206 207 /** Specifies the default label color. */ 208 public static final Color DEFAULT_LABEL_COLOR = getColor(INFO_DEFAULT_LABEL_COLOR.get()); 209 210 /** Specifies the valid field color. */ 211 public static final Color FIELD_VALID_COLOR = getColor(INFO_FIELD_VALID_COLOR.get()); 212 213 /** Specifies the invalid field color. */ 214 public static final Color FIELD_INVALID_COLOR = getColor(INFO_FIELD_INVALID_COLOR.get()); 215 216 /** Specifies the read only text color. */ 217 public static final Color READ_ONLY_COLOR = getColor(INFO_READ_ONLY_COLOR.get()); 218 219 /** Specifies the check box text color. */ 220 public static final Color CHECKBOX_COLOR = getColor(INFO_CHECKBOX_COLOR.get()); 221 222 /** Specifies the progress text color. */ 223 public static final Color PROGRESS_COLOR = getColor(INFO_PROGRESS_COLOR.get()); 224 225 /** Specifies the instructions text color. */ 226 public static final Color INSTRUCTIONS_COLOR = getColor(INFO_INSTRUCTIONS_COLOR.get()); 227 228 /** Specifies the text field text color. */ 229 public static final Color TEXTFIELD_COLOR = getColor(INFO_TEXTFIELD_COLOR.get()); 230 231 /** Specifies the password field text color. */ 232 public static final Color PASSWORDFIELD_COLOR = getColor(INFO_PASSWORDFIELD_COLOR.get()); 233 234 /** Specifies the in-line help text color. */ 235 public static final Color INLINE_HELP_COLOR = getColor(INFO_INLINE_HELP_COLOR.get()); 236 237 /** Specifies the panel border color. */ 238 public static final Color PANEL_BORDER_COLOR = getColor(INFO_PANEL_BORDER_COLOR.get()); 239 240 /** Specifies the current step panel border. */ 241 public static final Border CURRENT_STEP_PANEL_BORDER = 242 BorderFactory.createMatteBorder(0, 2, 2, 0, PANEL_BORDER_COLOR); 243 244 /** Specifies the text area border. */ 245 public static final Border TEXT_AREA_BORDER = 246 BorderFactory.createMatteBorder(1, 1, 1, 1, getColor(INFO_TEXT_AREA_BORDER_COLOR.get())); 247 248 /** Specifies the dialog border. */ 249 public static final Border DIALOG_PANEL_BORDER = BorderFactory.createMatteBorder(0, 0, 2, 0, PANEL_BORDER_COLOR); 250 251 private static Font DEFAULT_FONT; 252 static 253 { 254 try 255 { 256 DEFAULT_FONT = UIManager.getFont("Label.font").deriveFont(Font.PLAIN).deriveFont(12f); 257 } 258 catch (Throwable t) 259 { 260 DEFAULT_FONT = Font.decode("SansSerif-PLAIN-12"); 261 } 262 } 263 264 /** 265 * Specifies the font for the step which is not the current one in the steps 266 * panel. 267 */ 268 public static final Font NOT_CURRENT_STEP_FONT = DEFAULT_FONT.deriveFont(14f); 269 270 /** 271 * Specifies the font for the step which is the current one in the steps 272 * panel. 273 */ 274 public static final Font CURRENT_STEP_FONT = DEFAULT_FONT.deriveFont(14f).deriveFont(Font.BOLD); 275 276 /** Specifies the font for the title of the current panel. */ 277 public static final Font TITLE_FONT = DEFAULT_FONT.deriveFont(14f).deriveFont(Font.BOLD); 278 279 /** Specifies the font for the instructions of the current panel. */ 280 public static final Font INSTRUCTIONS_FONT = DEFAULT_FONT; 281 282 /** Specifies the font for the instructions of the current panel. */ 283 public static final Font INSTRUCTIONS_MONOSPACE_FONT = Font.decode("Monospaced-PLAIN-14"); 284 285 /** Specifies the font for the primary valid field. */ 286 public static final Font PRIMARY_FIELD_VALID_FONT = DEFAULT_FONT.deriveFont(Font.BOLD); 287 288 /** Specifies the font for the secondary valid field. */ 289 public static final Font SECONDARY_FIELD_VALID_FONT = DEFAULT_FONT; 290 291 /** Specifies the font for the primary invalid field. */ 292 public static final Font PRIMARY_FIELD_INVALID_FONT = DEFAULT_FONT.deriveFont(Font.BOLD | Font.ITALIC); 293 294 /** Specifies the font for the secondary invalid field. */ 295 public static final Font SECONDARY_FIELD_INVALID_FONT = DEFAULT_FONT.deriveFont(Font.ITALIC); 296 297 /** Specifies the font for the secondary status field. */ 298 public static final Font SECONDARY_STATUS_FONT = DEFAULT_FONT.deriveFont(Font.ITALIC); 299 300 /** Specifies the font for read only text. */ 301 public static final Font READ_ONLY_FONT = DEFAULT_FONT; 302 303 /** Specifies the font for the check box text. */ 304 public static final Font CHECKBOX_FONT = DEFAULT_FONT; 305 306 /** Specifies the font for the progress text. */ 307 public static final Font PROGRESS_FONT = DEFAULT_FONT; 308 309 /** Specifies the font for the text field text. */ 310 public static final Font TEXTFIELD_FONT = DEFAULT_FONT; 311 312 /** Specifies the font for the password field text. */ 313 public static final Font PASSWORD_FIELD_FONT = DEFAULT_FONT; 314 315 /** Specifies the font for the points '....' in the progress panel. */ 316 public static final Font PROGRESS_POINTS_FONT = DEFAULT_FONT.deriveFont(Font.BOLD); 317 318 /** Specifies the font for the done text 'Done' in the progress panel. */ 319 public static final Font PROGRESS_DONE_FONT = PROGRESS_POINTS_FONT; 320 321 /** Specifies the font for the log messages in the progress panel. */ 322 public static final Font PROGRESS_LOG_FONT = Font.decode("Monospaced-PLAIN-12"); 323 324 /** Specifies the font for the error log messages in the progress panel. */ 325 public static final Font PROGRESS_LOG_ERROR_FONT = Font.decode("Monospaced-PLAIN-12"); 326 327 /** Specifies the font for the error messages in the progress panel. */ 328 public static final Font PROGRESS_ERROR_FONT = DEFAULT_FONT.deriveFont(Font.BOLD); 329 330 /** Specifies the font for the warning messages in the progress panel. */ 331 public static final Font PROGRESS_WARNING_FONT = DEFAULT_FONT.deriveFont(Font.BOLD); 332 333 /** Specifies the font for the stack trace in the progress panel. */ 334 public static final Font STACK_FONT = DEFAULT_FONT; 335 336 /** Specifies the font for the text in the WebBrowserErrorDialog. */ 337 public static final Font ERROR_DIALOG_FONT = DEFAULT_FONT; 338 339 /** Specifies the font for the text in the in-line help. */ 340 public static final Font INLINE_HELP_FONT = DEFAULT_FONT.deriveFont((float) (DEFAULT_FONT.getSize() - 2)); 341 342 private static final String SPAN_CLOSE = "</span>"; 343 344 private static final String DIV_CLOSE = "</div>"; 345 346 private static final String DIV_OPEN_ERROR_BACKGROUND = 347 "<div style=\"color:#"+ 348 INFO_DIV_OPEN_ERROR_BACKGROUND_1_COLOR.get()+ 349 ";background-color:#"+ 350 INFO_DIV_OPEN_ERROR_BACKGROUND_2_COLOR.get()+ 351 ";padding:10px 10px 10px 10px;"+ 352 "border-style:solid;border-width:3px;border-color:#"+ 353 INFO_DIV_OPEN_ERROR_BACKGROUND_3_COLOR.get()+ 354 ";vertical-align:middle;text-align:left\">"; 355 356 private static final String DIV_OPEN_WARNING_BACKGROUND = DIV_OPEN_ERROR_BACKGROUND; 357 358 private static final String DIV_OPEN_SUCCESSFUL_BACKGROUND = 359 "<div style=\"color:#"+ 360 INFO_DIV_OPEN_SUCCESSFUL_BACKGROUND_1_COLOR.get()+ 361 ";background-color:#"+ 362 INFO_DIV_OPEN_SUCCESSFUL_BACKGROUND_2_COLOR.get()+ 363 ";padding:10px 10px 10px 10px;"+ 364 "border-style:solid;border-width:3px;border-color:#"+ 365 INFO_DIV_OPEN_SUCCESSFUL_BACKGROUND_3_COLOR.get()+ 366 ";vertical-align:middle;text-align:left\">"; 367 368 /** An HTML separator text that can be used in the progress panel. */ 369 public static final String HTML_SEPARATOR = 370 "<div style=\"font-size:1px;background-color:#"+ 371 INFO_HTML_SEPARATOR_COLOR.get()+ 372 ";margin:10px 5px 10px 5px;\"></div>"; 373 374 private static final HashMap<IconType, ImageIcon> hmIcons = new HashMap<>(); 375 376 /** The following enumeration contains the different icons that we can have. */ 377 public enum IconType 378 { 379 /** Splash Icon. */ 380 SPLASH, 381 /** Current Step Icon. */ 382 CURRENT_STEP, 383 /** The icon displayed by the OS when the dialog is minimized. */ 384 MINIMIZED, 385 /** The icon displayed by the Mac OS when the dialog is minimized. */ 386 MINIMIZED_MAC, 387 /** The background icon. */ 388 BACKGROUND, 389 /** The warning icon. */ 390 WARNING, 391 /** The warning large icon. */ 392 WARNING_LARGE, 393 /** The error icon. */ 394 ERROR, 395 /** The error large icon. */ 396 ERROR_LARGE, 397 /** The information icon. */ 398 INFORMATION, 399 /** The information large icon. */ 400 INFORMATION_LARGE, 401 /** Icon to create subsection title in Status Panel. */ 402 SUBSECTION_LEFT, 403 /** Icon to create subsection title in Status Panel. */ 404 SUBSECTION_RIGHT, 405 /** Question icon. */ 406 HELP_SMALL, 407 /** Question medium icon. */ 408 HELP_MEDIUM, 409 /** Hourglass to display when the user must wait. */ 410 WAIT, 411 /** 8 x 8 Hourglass to display when the user must wait. */ 412 WAIT_TINY, 413 /** No icon. */ 414 NO_ICON 415 } 416 417 /** 418 * The following enumeration contains the different text styles that we can 419 * have. A text style basically specifies the font and color to be used to 420 * render the text. 421 */ 422 public enum TextStyle 423 { 424 /** Current Step label style for the steps panel. */ 425 CURRENT_STEP, 426 /** Not current Step label style for the steps panel. */ 427 NOT_CURRENT_STEP, 428 /** Title label style for the current step panel. */ 429 TITLE, 430 /** Primary field valid label style for the current step panel. */ 431 PRIMARY_FIELD_VALID, 432 /** Primary field invalid text style for the current step panel. */ 433 PRIMARY_FIELD_INVALID, 434 /** Secondary field valid text style for the current step panel. */ 435 SECONDARY_FIELD_VALID, 436 /** Secondary field invalid text style for the current step panel. */ 437 SECONDARY_FIELD_INVALID, 438 /** Status messages that appear near components. */ 439 SECONDARY_STATUS, 440 /** Textfield text style for the current step panel. */ 441 TEXTFIELD, 442 /** Password text style for the current step panel. */ 443 PASSWORD_FIELD, 444 /** Read only text style for the current step panel. */ 445 READ_ONLY, 446 /** Check box text text style for the current step panel. */ 447 CHECKBOX, 448 /** Progress messages text style for the current step panel. */ 449 PROGRESS, 450 /** Text style for the instructions. */ 451 INSTRUCTIONS, 452 /** In-line help style. */ 453 INLINE_HELP, 454 /** No text style. */ 455 NO_STYLE 456 } 457 458 /** 459 * This method initialize the look and feel. 460 * 461 * @throws Throwable 462 * if there is a problem initializing the look and feel. 463 */ 464 public static void initializeLookAndFeel() throws Throwable 465 { 466 final Throwable[] ts = { null }; 467 Runnable r = new Runnable() 468 { 469 @Override 470 public void run() 471 { 472 System.setProperty("swing.aatext", "true"); 473 try 474 { 475 String lf = UIManager.getSystemLookAndFeelClassName(); 476 if ("com.sun.java.swing.plaf.motif.MotifLookAndFeel".equalsIgnoreCase(lf)) 477 { 478 lf = UIManager.getCrossPlatformLookAndFeelClassName(); 479 } 480 UIManager.setLookAndFeel(lf); 481 } 482 catch (Throwable t) 483 { 484 ts[0] = t; 485 } 486 JFrame.setDefaultLookAndFeelDecorated(false); 487 } 488 }; 489 if (SwingUtilities.isEventDispatchThread()) 490 { 491 r.run(); 492 } 493 else 494 { 495 try 496 { 497 SwingUtilities.invokeAndWait(r); 498 } 499 catch (Throwable t) 500 { 501 ts[0] = t; 502 } 503 } 504 if (ts[0] != null) 505 { 506 throw ts[0]; 507 } 508 } 509 510 /** 511 * This method initialize the look and feel and UI settings specific to quick 512 * setup. 513 * 514 * @throws Throwable 515 * if there is a problem initializing the look and feel. 516 */ 517 public static void initialize() throws Throwable 518 { 519 if (!initialized) 520 { 521 try 522 { 523 UIManager.put("OptionPane.background", getColor(INFO_OPTIONPANE_BACKGROUND_COLOR.get())); 524 UIManager.put("Panel.background", getColor(INFO_PANEL_BACKGROUND_COLOR.get())); 525 UIManager.put("ComboBox.background", getColor(INFO_COMBOBOX_BACKGROUND_COLOR.get())); 526 } 527 catch (Throwable t) 528 { 529 // This might occur when we do not get the display 530 logger.warn(LocalizableMessage.raw("Error updating UIManager: " + t, t)); 531 } 532 initializeLookAndFeel(); 533 initialized = true; 534 } 535 } 536 537 /** 538 * Creates a new JPanel. 539 * 540 * @return JPanel newly created 541 */ 542 public static JPanel makeJPanel() 543 { 544 JPanel pnl = new JPanel(); 545 pnl.setOpaque(false); 546 return pnl; 547 } 548 549 /** 550 * Creates a JButton with the given label and tooltip. 551 * 552 * @param label 553 * the text of the button. 554 * @param tooltip 555 * the tooltip of the button. 556 * @return a JButton with the given label and tooltip. 557 */ 558 public static JButton makeJButton(LocalizableMessage label, LocalizableMessage tooltip) 559 { 560 JButton b = new JButton(); 561 562 if (label != null) 563 { 564 b.setText(label.toString()); 565 } 566 567 if (tooltip != null) 568 { 569 b.setToolTipText(tooltip.toString()); 570 } 571 572 b.setOpaque(false); 573 574 return b; 575 } 576 577 /** 578 * Commodity method that returns a JLabel based on a LabelFieldDescriptor. 579 * 580 * @param desc 581 * the LabelFieldDescriptor describing the JLabel. 582 * @return a JLabel based on a LabelFieldDescriptor. 583 */ 584 public static JLabel makeJLabel(LabelFieldDescriptor desc) 585 { 586 UIFactory.TextStyle style; 587 if (desc.getLabelType() == LabelFieldDescriptor.LabelType.PRIMARY) 588 { 589 style = UIFactory.TextStyle.PRIMARY_FIELD_VALID; 590 } 591 else 592 { 593 style = UIFactory.TextStyle.SECONDARY_FIELD_VALID; 594 } 595 return makeJLabel(UIFactory.IconType.NO_ICON, desc.getLabel(), style); 596 } 597 598 /** 599 * Creates a JLabel with the given icon, text and text style. 600 * 601 * @param iconName 602 * the icon. 603 * @param text 604 * the label text. 605 * @param style 606 * the text style. 607 * @return a JLabel with the given icon, text and text style. 608 */ 609 public static JLabel makeJLabel(IconType iconName, LocalizableMessage text, TextStyle style) 610 { 611 JLabel l = new JLabel(); 612 613 if (text != null) 614 { 615 l.setText(text.toString()); 616 } 617 618 ImageIcon icon = getImageIcon(iconName); 619 l.setIcon(icon); 620 LocalizableMessage tooltip = getIconTooltip(iconName); 621 622 if (tooltip != null) 623 { 624 l.setToolTipText(tooltip.toString()); 625 } 626 627 setTextStyle(l, style); 628 return l; 629 } 630 631 /** 632 * Commodity method that returns a JTextComponent based on a 633 * LabelFieldDescriptor. 634 * 635 * @param desc 636 * the LabelFieldDescriptor describing the JTextField. 637 * @param defaultValue 638 * the default value used to initialize the JTextComponent. 639 * @return a JTextComponent based on a LabelFieldDescriptor. 640 */ 641 public static JTextComponent makeJTextComponent(LabelFieldDescriptor desc, String defaultValue) 642 { 643 if (defaultValue == null) 644 { 645 defaultValue = ""; 646 } 647 switch (desc.getType()) 648 { 649 case TEXTFIELD: 650 return makeJTextField( 651 LocalizableMessage.raw(defaultValue), desc.getTooltip(), desc.getSize(), TextStyle.TEXTFIELD); 652 653 case PASSWORD: 654 return makeJPasswordField( 655 LocalizableMessage.raw(defaultValue), desc.getTooltip(), desc.getSize(), TextStyle.PASSWORD_FIELD); 656 657 case READ_ONLY: 658 return makeTextPane(LocalizableMessage.raw(defaultValue), TextStyle.READ_ONLY); 659 660 default: 661 throw new IllegalArgumentException("Unknown type: " + desc.getType()); 662 } 663 } 664 665 /** 666 * Creates a JTextField with the given icon, tooltip text, size and text 667 * style. 668 * 669 * @param text 670 * the text. 671 * @param tooltip 672 * the tooltip text. 673 * @param size 674 * the number of columns of the JTextField. 675 * @param style 676 * the text style. 677 * @return a JTextField with the given icon, tooltip text, size and text 678 * style. 679 */ 680 public static JTextField makeJTextField( 681 LocalizableMessage text, LocalizableMessage tooltip, int size, TextStyle style) 682 { 683 JTextField f = new JTextField(); 684 updateTextFieldComponent(f, text, tooltip, size, style); 685 f.addFocusListener(new TextFieldFocusListener(f)); 686 return f; 687 } 688 689 /** 690 * Creates a JPasswordField with the given icon, tooltip text, size and text 691 * style. 692 * 693 * @param text 694 * the text. 695 * @param tooltip 696 * the tooltip text. 697 * @param size 698 * the number of columns of the JPasswordField. 699 * @param style 700 * the text style. 701 * @return a JPasswordField with the given icon, tooltip text, size and text 702 * style. 703 */ 704 public static JPasswordField makeJPasswordField( 705 LocalizableMessage text, LocalizableMessage tooltip, int size, TextStyle style) 706 { 707 JPasswordField f = new JPasswordField(); 708 updateTextFieldComponent(f, text, tooltip, size, style); 709 f.addFocusListener(new TextFieldFocusListener(f)); 710 return f; 711 } 712 713 /** 714 * Creates a JRadioButton with the given text, tooltip text and text style. 715 * 716 * @param text 717 * the text of the radio button. 718 * @param tooltip 719 * the tooltip text. 720 * @param style 721 * the text style. 722 * @return a JRadioButton with the given text, tooltip text and text style. 723 */ 724 public static JRadioButton makeJRadioButton(LocalizableMessage text, LocalizableMessage tooltip, TextStyle style) 725 { 726 JRadioButton rb = new JRadioButton(); 727 rb.setOpaque(false); 728 if (text != null) 729 { 730 rb.setText(text.toString()); 731 } 732 733 if (tooltip != null) 734 { 735 rb.setToolTipText(tooltip.toString()); 736 } 737 738 setTextStyle(rb, style); 739 return rb; 740 } 741 742 /** 743 * Creates a JCheckBox with the given text, tooltip text and text style. 744 * 745 * @param text 746 * the text of the radio button. 747 * @param tooltip 748 * the tooltip text. 749 * @param style 750 * the text style. 751 * @return a JCheckBox with the given text, tooltip text and text style. 752 */ 753 public static JCheckBox makeJCheckBox(LocalizableMessage text, LocalizableMessage tooltip, TextStyle style) 754 { 755 JCheckBox cb = new JCheckBox(); 756 cb.setOpaque(false); 757 if (text != null) 758 { 759 cb.setText(text.toString()); 760 } 761 762 if (tooltip != null) 763 { 764 cb.setToolTipText(tooltip.toString()); 765 } 766 767 setTextStyle(cb, style); 768 return cb; 769 } 770 771 /** 772 * Creates a JList. 773 * 774 * @param textStyle 775 * the style to be used for the renderer. 776 * @param <T> 777 * The type of the JList elements 778 * @return a JList. 779 */ 780 public static <T> JList<T> makeJList(TextStyle textStyle) 781 { 782 final JList<T> list = new JList<>(); 783 list.setCellRenderer(makeCellRenderer(textStyle)); 784 return list; 785 } 786 787 /** 788 * Sets the specified text style to the component passed as parameter. 789 * 790 * @param l 791 * the component to update. 792 * @param style 793 * the text style to use. 794 */ 795 public static void setTextStyle(JComponent l, TextStyle style) 796 { 797 switch (style) 798 { 799 case NOT_CURRENT_STEP: 800 l.setFont(UIFactory.NOT_CURRENT_STEP_FONT); 801 l.setForeground(DEFAULT_LABEL_COLOR); 802 break; 803 804 case CURRENT_STEP: 805 l.setFont(UIFactory.CURRENT_STEP_FONT); 806 l.setForeground(DEFAULT_LABEL_COLOR); 807 break; 808 809 case TITLE: 810 l.setFont(UIFactory.TITLE_FONT); 811 l.setForeground(DEFAULT_LABEL_COLOR); 812 break; 813 814 case PRIMARY_FIELD_VALID: 815 l.setFont(UIFactory.PRIMARY_FIELD_VALID_FONT); 816 l.setForeground(FIELD_VALID_COLOR); 817 break; 818 819 case PRIMARY_FIELD_INVALID: 820 l.setFont(UIFactory.PRIMARY_FIELD_INVALID_FONT); 821 l.setForeground(FIELD_INVALID_COLOR); 822 break; 823 824 case SECONDARY_FIELD_VALID: 825 l.setFont(UIFactory.SECONDARY_FIELD_VALID_FONT); 826 l.setForeground(FIELD_VALID_COLOR); 827 break; 828 829 case SECONDARY_FIELD_INVALID: 830 l.setFont(UIFactory.SECONDARY_FIELD_INVALID_FONT); 831 l.setForeground(FIELD_INVALID_COLOR); 832 break; 833 834 case SECONDARY_STATUS: 835 l.setFont(UIFactory.SECONDARY_STATUS_FONT); 836 l.setForeground(FIELD_VALID_COLOR); 837 break; 838 839 case READ_ONLY: 840 l.setFont(UIFactory.READ_ONLY_FONT); 841 l.setForeground(READ_ONLY_COLOR); 842 break; 843 844 case CHECKBOX: 845 l.setFont(UIFactory.CHECKBOX_FONT); 846 l.setForeground(CHECKBOX_COLOR); 847 break; 848 849 case PROGRESS: 850 l.setFont(UIFactory.PROGRESS_FONT); 851 l.setForeground(PROGRESS_COLOR); 852 break; 853 854 case INSTRUCTIONS: 855 l.setFont(INSTRUCTIONS_FONT); 856 l.setForeground(INSTRUCTIONS_COLOR); 857 break; 858 859 case TEXTFIELD: 860 l.setFont(UIFactory.TEXTFIELD_FONT); 861 l.setForeground(TEXTFIELD_COLOR); 862 break; 863 864 case PASSWORD_FIELD: 865 l.setFont(UIFactory.PASSWORD_FIELD_FONT); 866 l.setForeground(PASSWORDFIELD_COLOR); 867 break; 868 869 case INLINE_HELP: 870 l.setFont(INLINE_HELP_FONT); 871 l.setForeground(INLINE_HELP_COLOR); 872 break; 873 874 case NO_STYLE: 875 // Do nothing 876 break; 877 878 default: 879 throw new IllegalArgumentException("Unknown textStyle: " + style); 880 } 881 } 882 883 /** 884 * Returns the HTML string representing the provided IconType. 885 * 886 * @param iconType 887 * the IconType for which we want the HTML representation. 888 * @return the HTML string representing the provided IconType. 889 */ 890 public static String getIconHtml(IconType iconType) 891 { 892 String url = String.valueOf(UIFactory.class.getClassLoader().getResource(getIconPath(iconType))); 893 LocalizableMessage description = getIconDescription(iconType); 894 LocalizableMessage title = getIconTooltip(iconType); 895 return "<img src=\"" + url + "\" alt=\"" + description + "\" align=\"middle\" title=\"" + title + "\" >"; 896 } 897 898 /** 899 * Returns an ImageIcon object for the provided IconType. 900 * 901 * @param iconType 902 * the IconType for which we want to obtain the ImageIcon. 903 * @return the ImageIcon. 904 */ 905 public static ImageIcon getImageIcon(IconType iconType) 906 { 907 if (iconType == null) 908 { 909 iconType = IconType.NO_ICON; 910 } 911 ImageIcon icon = hmIcons.get(iconType); 912 if (icon == null && iconType != IconType.NO_ICON) 913 { 914 String path = getIconPath(iconType); 915 LocalizableMessage description = getIconDescription(iconType); 916 try 917 { 918 Image im = Toolkit.getDefaultToolkit().createImage(UIFactory.class.getClassLoader().getResource(path)); 919 icon = new ImageIcon(im); 920 String ds = description != null ? description.toString() : null; 921 icon.setDescription(ds); 922 923 hmIcons.put(iconType, icon); 924 } 925 catch (Exception ex) 926 { 927 ex.printStackTrace(); // A bug: this should not happen 928 throw new IllegalStateException("Could not load icon for path " + path, ex); 929 } 930 } 931 932 return icon; 933 } 934 935 /** 936 * Returns a JEditorPane that works with the provided scroll. 937 * 938 * @see ProgressJEditorPane 939 * @param scroll 940 * the scroll that will contain the JEditorPane. 941 * @return a JEditorPane that works with the provided scroll. 942 */ 943 public static JEditorPane makeProgressPane(JScrollPane scroll) 944 { 945 return new ProgressJEditorPane(scroll); 946 } 947 948 /** 949 * Returns a read only JEditorPane containing the provided text with the 950 * provided font. The JEditorPane will assume that the text is HTML text. 951 * 952 * @param text 953 * the text to be used to initialize the JEditorPane contents. 954 * @param font 955 * the font to be used. 956 * @return a read only JEditorPane containing the provided text with the 957 * provided font. 958 */ 959 public static JEditorPane makeHtmlPane(LocalizableMessage text, Font font) 960 { 961 return makeHtmlPane(text, null, font); 962 } 963 964 /** 965 * Returns a read only JEditorPane containing the provided text with the 966 * provided font. The JEditorPane will assume that the text is HTML text. 967 * 968 * @param text 969 * the text to be used to initialize the JEditorPane contents. 970 * @param ek 971 * HTMLEditor kit used for the new HTML pane 972 * @param font 973 * the font to be used. 974 * @return a read only JEditorPane containing the provided text with the 975 * provided font. 976 */ 977 public static JEditorPane makeHtmlPane(LocalizableMessage text, HTMLEditorKit ek, Font font) 978 { 979 JEditorPane pane = new JEditorPane(); 980 if (ek != null) { 981 pane.setEditorKit(ek); 982 } 983 pane.setContentType("text/html"); 984 String s = text != null ? String.valueOf(text) : null; 985 pane.setText(applyFontToHtmlWithDiv(s, font)); 986 pane.setEditable(false); 987 pane.setBorder(new EmptyBorder(0, 0, 0, 0)); 988 return pane; 989 } 990 991 /** 992 * Returns a read only JEditorPane containing the provided text with the 993 * provided TextStyle. The JEditorPane will assume that the text is plain 994 * text. 995 * 996 * @param text 997 * the text to be used to initialize the JEditorPane contents. 998 * @param style 999 * the TextStyle to be used. 1000 * @return a read only JEditorPane containing the provided text with the 1001 * provided TextStyle. 1002 */ 1003 public static JEditorPane makeTextPane(LocalizableMessage text, TextStyle style) 1004 { 1005 String s = text != null ? String.valueOf(text) : null; 1006 JEditorPane pane = new JEditorPane("text/plain", s); 1007 setTextStyle(pane, style); 1008 pane.setEditable(false); 1009 pane.setBorder(new EmptyBorder(0, 0, 0, 0)); 1010 pane.setOpaque(false); 1011 return pane; 1012 } 1013 1014 /** 1015 * Returns a JScrollPane that contains the provided component. The scroll pane 1016 * will not contain any border. 1017 * 1018 * @param comp 1019 * the component contained in the scroll pane. 1020 * @return a JScrollPane that contains the provided component. The scroll pane 1021 * will not contain any border. 1022 */ 1023 public static JScrollPane createBorderLessScrollBar(Component comp) 1024 { 1025 JScrollPane scroll = new JScrollPane(comp); 1026 scroll.setBorder(new EmptyBorder(0, 0, 0, 0)); 1027 scroll.setViewportBorder(new EmptyBorder(0, 0, 0, 0)); 1028 scroll.setOpaque(false); 1029 scroll.getViewport().setOpaque(false); 1030 scroll.getViewport().setBackground(DEFAULT_BACKGROUND); 1031 scroll.setBackground(DEFAULT_BACKGROUND); 1032 setScrollIncrementUnit(scroll); 1033 return scroll; 1034 } 1035 1036 /** 1037 * Sets the scroll increment unit for the scroll. 1038 * 1039 * @param scroll 1040 * the scroll to be updated. 1041 */ 1042 public static void setScrollIncrementUnit(JScrollPane scroll) 1043 { 1044 if (scroll.getVerticalScrollBar() != null) 1045 { 1046 int increment = scroll.getVerticalScrollBar().getUnitIncrement(); 1047 if (increment < 16) 1048 { 1049 scroll.getVerticalScrollBar().setUnitIncrement(16); 1050 } 1051 } 1052 } 1053 1054 /** 1055 * Return empty insets. 1056 * 1057 * @return empty insets. 1058 */ 1059 public static Insets getEmptyInsets() 1060 { 1061 return (Insets) EMPTY_INSETS.clone(); 1062 } 1063 1064 /** 1065 * Returns the insets to be used for the button panel. 1066 * 1067 * @return the insets to be used for the button panel. 1068 */ 1069 public static Insets getButtonsPanelInsets() 1070 { 1071 return (Insets) BUTTONS_PANEL_INSETS.clone(); 1072 } 1073 1074 /** 1075 * Returns the insets to be used for the steps panel. 1076 * 1077 * @return the insets to be used for the steps panel. 1078 */ 1079 public static Insets getStepsPanelInsets() 1080 { 1081 return (Insets) STEPS_PANEL_INSETS.clone(); 1082 } 1083 1084 /** 1085 * Returns the insets to be used for the current step panel. 1086 * 1087 * @return the insets to be used for the current step panel. 1088 */ 1089 public static Insets getCurrentStepPanelInsets() 1090 { 1091 return (Insets) CURRENT_STEP_PANEL_INSETS.clone(); 1092 } 1093 1094 /** 1095 * Returns a String that contains the html passed as parameter with a span 1096 * applied. The span style corresponds to the Font specified as parameter. The 1097 * goal of this method is to be able to specify a font for an HTML string. 1098 * 1099 * @param html 1100 * the original html text. 1101 * @param font 1102 * the font to be used to generate the new HTML. 1103 * @return a string that represents the original HTML with the font specified 1104 * as parameter. 1105 */ 1106 public static String applyFontToHtml(String html, Font font) 1107 { 1108 StringBuilder buf = new StringBuilder(); 1109 1110 buf.append("<span style=\"").append(getFontStyle(font)).append("\">").append(html).append(SPAN_CLOSE); 1111 1112 return buf.toString(); 1113 } 1114 1115 /** 1116 * Returns a String that contains the html passed as parameter with a div 1117 * applied. The div style corresponds to the Font specified as parameter. The 1118 * goal of this method is to be able to specify a font for an HTML string. 1119 * 1120 * @param html 1121 * the original html text. 1122 * @param font 1123 * the font to be used to generate the new HTML. 1124 * @return a string that represents the original HTML with the font specified 1125 * as parameter. 1126 */ 1127 public static String applyFontToHtmlWithDiv(String html, Font font) 1128 { 1129 StringBuilder buf = new StringBuilder(); 1130 1131 buf.append("<div style=\"").append(getFontStyle(font)).append("\">").append(html).append(DIV_CLOSE); 1132 1133 return buf.toString(); 1134 } 1135 1136 /** 1137 * Returns the HTML style representation for the given font. 1138 * 1139 * @param font 1140 * the font for which we want to get an HTML style representation. 1141 * @return the HTML style representation for the given font. 1142 */ 1143 private static String getFontStyle(Font font) 1144 { 1145 StringBuilder buf = new StringBuilder(); 1146 1147 buf.append("font-family:").append(font.getName()).append(";font-size:").append(font.getSize()).append("pt"); 1148 1149 if (font.isItalic()) 1150 { 1151 buf.append(";font-style:italic"); 1152 } 1153 1154 if (font.isBold()) 1155 { 1156 buf.append(";font-weight:bold;"); 1157 } 1158 1159 return buf.toString(); 1160 } 1161 1162 /** 1163 * Returns the html text passed as parameter with the error background applied 1164 * to it. 1165 * 1166 * @param html 1167 * the original html. 1168 * @return the html text passed as parameter with the error background applied 1169 * to it. 1170 */ 1171 public static String applyErrorBackgroundToHtml(String html) 1172 { 1173 return DIV_OPEN_ERROR_BACKGROUND + html + DIV_CLOSE; 1174 } 1175 1176 /** 1177 * Returns the html text passed as parameter with the warning background 1178 * applied to it. 1179 * 1180 * @param html 1181 * the original html. 1182 * @return the html text passed as parameter with the warning background 1183 * applied to it. 1184 */ 1185 public static String applyWarningBackgroundToHtml(String html) 1186 { 1187 return DIV_OPEN_WARNING_BACKGROUND + html + DIV_CLOSE; 1188 } 1189 1190 /** 1191 * Returns the html text passed as parameter with the success background 1192 * applied to it. 1193 * 1194 * @param html 1195 * the original html. 1196 * @return the html text passed as parameter with the success background 1197 * applied to it. 1198 */ 1199 public static String applySuccessfulBackgroundToHtml(String html) 1200 { 1201 return DIV_OPEN_SUCCESSFUL_BACKGROUND + html + DIV_CLOSE; 1202 } 1203 1204 /** 1205 * Returns the html text passed as parameter with some added margin. 1206 * 1207 * @param html 1208 * the original html text. 1209 * @param top 1210 * the top margin. 1211 * @param right 1212 * the right margin. 1213 * @param bottom 1214 * the bottom margin. 1215 * @param left 1216 * the left margin. 1217 * @return the html text passed as parameter with some added margin. 1218 */ 1219 public static String applyMargin(String html, int top, int right, int bottom, int left) 1220 { 1221 return "<div style=\"margin:" + top + "px " + right + "px " + bottom + "px " + left + "px;\">" + html + DIV_CLOSE; 1222 } 1223 1224 /** 1225 * Updates the provided field with all the other arguments. 1226 * 1227 * @param field 1228 * the field to be modified. 1229 * @param text 1230 * the new text of the field. 1231 * @param tooltip 1232 * the new tooltip text of the field. 1233 * @param size 1234 * the new size of the field. 1235 * @param textStyle 1236 * the new TextStyle of the field. 1237 */ 1238 private static void updateTextFieldComponent( 1239 JTextField field, LocalizableMessage text, LocalizableMessage tooltip, int size, TextStyle textStyle) 1240 { 1241 field.setColumns(size); 1242 if (text != null) 1243 { 1244 field.setText(text.toString()); 1245 } 1246 if (tooltip != null) 1247 { 1248 field.setToolTipText(tooltip.toString()); 1249 } 1250 if (textStyle != null) 1251 { 1252 setTextStyle(field, textStyle); 1253 } 1254 } 1255 1256 private static Color getColor(LocalizableMessage l) 1257 { 1258 String s = String.valueOf(l); 1259 String[] colors = s.split(","); 1260 int r = Integer.parseInt(colors[0].trim()); 1261 int g = Integer.parseInt(colors[1].trim()); 1262 int b = Integer.parseInt(colors[2].trim()); 1263 1264 return new Color(r, g, b); 1265 } 1266 1267 /** 1268 * Returns the parent package path. This is used to retrieve the icon 1269 * qualified names. 1270 * 1271 * @return the parent package path. 1272 */ 1273 private static String getParentPackagePath() 1274 { 1275 if (parentPackagePath == null) 1276 { 1277 String packageName = UIFactory.class.getPackage().getName(); 1278 int lastDot = packageName.lastIndexOf('.'); 1279 String parentPackage = packageName.substring(0, lastDot); 1280 parentPackagePath = parentPackage.replace(".", "/"); 1281 } 1282 return parentPackagePath; 1283 } 1284 1285 /** 1286 * Returns the path of the icon for the given IconType. 1287 * 1288 * @param iconType 1289 * the IconType for which we want to get the path. 1290 * @return the path of the icon for the given IconType. 1291 */ 1292 private static String getIconPath(IconType iconType) 1293 { 1294 return getParentPackagePath() + "/" + getKey(iconType); 1295 } 1296 1297 private static LocalizableMessage getKey(IconType iconType) 1298 { 1299 switch (iconType) 1300 { 1301 case CURRENT_STEP: 1302 return INFO_CURRENT_STEP_ICON.get(); 1303 case SPLASH: 1304 return INFO_SPLASH_ICON.get(); 1305 case BACKGROUND: 1306 return INFO_BACKGROUND_ICON.get(); 1307 case MINIMIZED: 1308 return INFO_MINIMIZED_ICON.get(); 1309 case MINIMIZED_MAC: 1310 return INFO_MINIMIZED_MAC_ICON.get(); 1311 case WARNING: 1312 return INFO_WARNING_ICON.get(); 1313 case WARNING_LARGE: 1314 return INFO_WARNING_LARGE_ICON.get(); 1315 case INFORMATION: 1316 return INFO_INFORMATION_ICON.get(); 1317 case INFORMATION_LARGE: 1318 return INFO_INFORMATION_LARGE_ICON.get(); 1319 case SUBSECTION_LEFT: 1320 return INFO_SUBSECTION_LEFT_ICON.get(); 1321 case SUBSECTION_RIGHT: 1322 return INFO_SUBSECTION_RIGHT_ICON.get(); 1323 case HELP_SMALL: 1324 return INFO_HELP_SMALL_ICON.get(); 1325 case HELP_MEDIUM: 1326 return INFO_HELP_MEDIUM_ICON.get(); 1327 case ERROR: 1328 return INFO_ERROR_ICON.get(); 1329 case ERROR_LARGE: 1330 return INFO_ERROR_LARGE_ICON.get(); 1331 case WAIT_TINY: 1332 return INFO_WAIT_TINY.get(); 1333 case WAIT: 1334 return INFO_WAIT.get(); 1335 default: 1336 throw new IllegalArgumentException("Unknown iconName: " + iconType); 1337 } 1338 } 1339 1340 /** 1341 * Returns the icon description for the given IconType. 1342 * 1343 * @param iconType 1344 * the IconType for which we want to get the description. 1345 * @return the icon description for the given IconType. 1346 */ 1347 private static LocalizableMessage getIconDescription(IconType iconType) 1348 { 1349 switch (iconType) 1350 { 1351 case CURRENT_STEP: 1352 return INFO_CURRENT_STEP_ICON_DESCRIPTION.get(); 1353 1354 case SPLASH: 1355 return INFO_SPLASH_ICON_DESCRIPTION.get(); 1356 1357 case BACKGROUND: 1358 return INFO_BACKGROUND_ICON_DESCRIPTION.get(); 1359 1360 case MINIMIZED: 1361 return INFO_MINIMIZED_ICON_DESCRIPTION.get(); 1362 1363 case MINIMIZED_MAC: 1364 return INFO_MINIMIZED_ICON_DESCRIPTION.get(); 1365 1366 case WARNING: 1367 return INFO_WARNING_ICON_DESCRIPTION.get(); 1368 1369 case WARNING_LARGE: 1370 return INFO_WARNING_ICON_DESCRIPTION.get(); 1371 1372 case ERROR: 1373 return INFO_ERROR_ICON_DESCRIPTION.get(); 1374 1375 case ERROR_LARGE: 1376 return INFO_ERROR_ICON_DESCRIPTION.get(); 1377 1378 case INFORMATION: 1379 return INFO_INFORMATION_ICON_DESCRIPTION.get(); 1380 1381 case INFORMATION_LARGE: 1382 return INFO_INFORMATION_ICON_DESCRIPTION.get(); 1383 1384 case SUBSECTION_LEFT: 1385 return INFO_SUBSECTION_LEFT_ICON_DESCRIPTION.get(); 1386 1387 case SUBSECTION_RIGHT: 1388 return INFO_SUBSECTION_RIGHT_ICON_DESCRIPTION.get(); 1389 1390 case HELP_SMALL: 1391 case HELP_MEDIUM: 1392 return INFO_HELP_SMALL_ICON_DESCRIPTION.get(); 1393 1394 case WAIT_TINY: 1395 return INFO_HELP_WAIT_DESCRIPTION.get(); 1396 1397 case WAIT: 1398 return INFO_HELP_WAIT_DESCRIPTION.get(); 1399 1400 case NO_ICON: 1401 return null; 1402 1403 default: 1404 throw new IllegalArgumentException("Unknown iconName: " + iconType); 1405 } 1406 } 1407 1408 /** 1409 * Returns the icon tooltip text for the given IconType. 1410 * 1411 * @param iconType 1412 * the IconType for which we want to get the tooltip text. 1413 * @return the icon tooltip text for the given IconType. 1414 */ 1415 private static LocalizableMessage getIconTooltip(IconType iconType) 1416 { 1417 if (iconType == null) 1418 { 1419 iconType = IconType.NO_ICON; 1420 } 1421 switch (iconType) 1422 { 1423 case CURRENT_STEP: 1424 return INFO_CURRENT_STEP_ICON_TOOLTIP.get(); 1425 1426 case SPLASH: 1427 return INFO_SPLASH_ICON_TOOLTIP.get(); 1428 1429 case BACKGROUND: 1430 return INFO_BACKGROUND_ICON_TOOLTIP.get(); 1431 1432 case MINIMIZED: 1433 return INFO_MINIMIZED_ICON_TOOLTIP.get(); 1434 1435 case MINIMIZED_MAC: 1436 return INFO_MINIMIZED_ICON_TOOLTIP.get(); 1437 1438 case WARNING: 1439 return INFO_WARNING_ICON_TOOLTIP.get(); 1440 1441 case WARNING_LARGE: 1442 return INFO_WARNING_ICON_TOOLTIP.get(); 1443 1444 case ERROR: 1445 return INFO_ERROR_ICON_TOOLTIP.get(); 1446 1447 case ERROR_LARGE: 1448 return INFO_ERROR_ICON_TOOLTIP.get(); 1449 1450 case INFORMATION: 1451 return INFO_INFORMATION_ICON_TOOLTIP.get(); 1452 1453 case INFORMATION_LARGE: 1454 return INFO_INFORMATION_ICON_TOOLTIP.get(); 1455 1456 case SUBSECTION_LEFT: 1457 case SUBSECTION_RIGHT: 1458 case HELP_SMALL: 1459 case HELP_MEDIUM: 1460 case WAIT_TINY: 1461 case WAIT: 1462 case NO_ICON: 1463 return null; 1464 1465 default: 1466 throw new IllegalArgumentException("Unknown iconName: " + iconType); 1467 } 1468 } 1469 1470 private static <T> ListCellRenderer<T> makeCellRenderer(final TextStyle textStyle) 1471 { 1472 return new ListCellRenderer<T>() 1473 { 1474 @Override 1475 public Component getListCellRendererComponent(JList<? extends T> list, T value, int index, boolean isSelected, 1476 boolean cellHasFocus) 1477 { 1478 final JLabel l = makeJLabel(IconType.NO_ICON, LocalizableMessage.raw(value.toString()), textStyle); 1479 l.setBorder(new EmptyBorder(TOP_INSET_SECONDARY_FIELD, 0, 0, 0)); 1480 return l; 1481 } 1482 }; 1483 } 1484} 1485 1486/** 1487 * This class has been written to have a better behaviour with the scroll pane 1488 * than the one we have by default in the case of the progress panel. 1489 * <p> 1490 * With the default scroll pane behaviour when we set a new text in a 1491 * JEditorPane the scroll bar goes systematically up. With this implementation 1492 * the expected behaviour is: 1493 * <p> 1494 * If the scroll bar is at the bottom we will display the latest text contained 1495 * in the pane. 1496 * <p> 1497 * If the scroll bar is not at the bottom we will keep on displaying the same 1498 * thing that the user is viewing. 1499 * <p> 1500 * This behaviour allows the user to check the log content even when the 1501 * installation/uninstallation is still running and sending new log messages. 1502 */ 1503class ProgressJEditorPane extends JEditorPane 1504{ 1505 private static final long serialVersionUID = 1221976708322628818L; 1506 1507 private final JScrollPane scroll; 1508 1509 private boolean ignoreScrollToVisible; 1510 1511 /** 1512 * Constructor for the ProgressJEditorPane. 1513 * 1514 * @param scroll 1515 * the JScrollPane that will contain this editor pane. 1516 */ 1517 public ProgressJEditorPane(JScrollPane scroll) 1518 { 1519 super("text/html", null); 1520 this.scroll = scroll; 1521 setEditable(false); 1522 setBorder(new EmptyBorder(3, 3, 3, 3)); 1523 } 1524 1525 @Override 1526 public void setText(String text) 1527 { 1528 // Scroll can be null in constructor 1529 if (scroll != null) 1530 { 1531 /* 1532 * We apply the following policy: if the user is displaying the latest 1533 * part of the JTextArea we assume that when we add text (s)he wants to 1534 * see the text that is added, if not we assume that (s)he want to keep 1535 * viewing what is visible and so we ignore the next scrollRectToVisible 1536 * call (that will be done inside JTextArea.setText method). 1537 */ 1538 JScrollBar vBar = scroll.getVerticalScrollBar(); 1539 ignoreScrollToVisible = 1540 vBar != null && vBar.getValue() + vBar.getVisibleAmount() < 0.97 * vBar.getMaximum(); 1541 super.setText(text); 1542 } 1543 } 1544 1545 @Override 1546 public void scrollRectToVisible(Rectangle rect) 1547 { 1548 if (!ignoreScrollToVisible) 1549 { 1550 super.scrollRectToVisible(rect); 1551 ignoreScrollToVisible = false; 1552 } 1553 } 1554} 1555 1556/** 1557 * A class used to be able to select the contents of the text field when it gets 1558 * the focus. 1559 */ 1560class TextFieldFocusListener implements FocusListener 1561{ 1562 private final JTextField tf; 1563 1564 /** 1565 * The constructor for this listener. 1566 * 1567 * @param tf 1568 * the text field associated with this listener. 1569 */ 1570 TextFieldFocusListener(JTextField tf) 1571 { 1572 this.tf = tf; 1573 } 1574 1575 @Override 1576 public void focusGained(FocusEvent e) 1577 { 1578 if (tf.getText() == null || "".equals(tf.getText())) 1579 { 1580 tf.setText(" "); 1581 tf.selectAll(); 1582 tf.setText(""); 1583 } 1584 else 1585 { 1586 tf.selectAll(); 1587 } 1588 } 1589 1590 @Override 1591 public void focusLost(FocusEvent e) 1592 { 1593 } 1594}