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