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