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 2014-2016 ForgeRock AS. 016 */ 017package org.opends.quicksetup.ui; 018 019import static com.forgerock.opendj.util.OperatingSystem.isMacOS; 020 021import java.awt.Component; 022import java.awt.Dimension; 023import java.awt.GridBagConstraints; 024import java.awt.GridBagLayout; 025import java.awt.Toolkit; 026import java.awt.Window; 027import java.util.StringTokenizer; 028 029import javax.swing.Box; 030import javax.swing.JButton; 031import javax.swing.JFrame; 032import javax.swing.JLabel; 033import javax.swing.JOptionPane; 034import javax.swing.JPanel; 035import javax.swing.text.JTextComponent; 036 037import org.forgerock.i18n.LocalizableMessage; 038 039/** 040 * A set of utilities specific to GUI QuickSetup applications. 041 */ 042public class Utilities { 043 044 /** 045 * Creates a panel with a field and a browse button. 046 * @param lbl JLabel for the field 047 * @param tf JTextField for holding the browsed data 048 * @param but JButton for invoking browse action 049 * @return the created panel. 050 */ 051 public static JPanel createBrowseButtonPanel(JLabel lbl, 052 JTextComponent tf, 053 JButton but) 054 { 055 GridBagConstraints gbc = new GridBagConstraints(); 056 057 JPanel panel = UIFactory.makeJPanel(); 058 panel.setLayout(new GridBagLayout()); 059 060 gbc.insets = UIFactory.getEmptyInsets(); 061 gbc.gridwidth = 4; 062 gbc.weightx = 0.0; 063 gbc.fill = GridBagConstraints.HORIZONTAL; 064 panel.add(lbl, gbc); 065 066 gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD; 067 gbc.gridwidth--; 068 gbc.weightx = 0.1; 069 panel.add(tf, gbc); 070 071 gbc.insets.left = UIFactory.LEFT_INSET_BROWSE; 072 gbc.gridwidth = GridBagConstraints.RELATIVE; 073 panel.add(but, gbc); 074 075 gbc.weightx = 1.0; 076 gbc.gridwidth = GridBagConstraints.REMAINDER; 077 panel.add(Box.createHorizontalGlue(), gbc); 078 079 return panel; 080 } 081 082 /** 083 * Sets a frames image icon to the standard OpenDS icon appropriate 084 * for the running platform. 085 * 086 * @param frame for which the icon will be set 087 */ 088 public static void setFrameIcon(JFrame frame) 089 { 090 UIFactory.IconType ic; 091 if (isMacOS()) { 092 ic = UIFactory.IconType.MINIMIZED_MAC; 093 } else { 094 ic = UIFactory.IconType.MINIMIZED; 095 } 096 frame.setIconImage(UIFactory.getImageIcon(ic).getImage()); 097 } 098 099 /** 100 * Center the component location based on its preferred size. The code 101 * considers the particular case of 2 screens and puts the component on the 102 * center of the left screen 103 * 104 * @param comp the component to be centered. 105 */ 106 public static void centerOnScreen(Component comp) 107 { 108 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 109 110 int width = (int) comp.getPreferredSize().getWidth(); 111 int height = (int) comp.getPreferredSize().getHeight(); 112 113 boolean multipleScreen = screenSize.width / screenSize.height >= 2; 114 115 if (multipleScreen) 116 { 117 comp.setLocation(screenSize.width / 4 - width / 2, 118 (screenSize.height - height) / 2); 119 } else 120 { 121 comp.setLocation((screenSize.width - width) / 2, 122 (screenSize.height - height) / 2); 123 } 124 } 125 126 /** 127 * Center the component location of the ref component. 128 * 129 * @param comp the component to be centered. 130 * @param ref the component to be used as reference. 131 * 132 */ 133 public static void centerOnComponent(Window comp, Component ref) 134 { 135 comp.setLocationRelativeTo(ref); 136 } 137 138 /** 139 * Displays a confirmation message dialog. 140 * 141 * @param parent 142 * the parent frame of the confirmation dialog. 143 * @param msg 144 * the confirmation message. 145 * @param title 146 * the title of the dialog. 147 * @return <CODE>true</CODE> if the user confirms the message, or 148 * <CODE>false</CODE> if not. 149 */ 150 public static boolean displayConfirmation(Component parent, LocalizableMessage msg, 151 LocalizableMessage title) 152 { 153 return JOptionPane.YES_OPTION == JOptionPane.showOptionDialog( 154 parent, wrapMsg(String.valueOf(msg), 100), String.valueOf(title), 155 JOptionPane.YES_NO_OPTION, 156 JOptionPane.QUESTION_MESSAGE, 157 null, // don't use a custom Icon 158 null, // the titles of buttons 159 null); // default button title 160 } 161 162 /** 163 * Displays an error message dialog. 164 * 165 * @param parent 166 * the parent component of the error dialog. 167 * @param msg 168 * the error message. 169 * @param title 170 * the title for the dialog. 171 */ 172 public static void displayError(Component parent, LocalizableMessage msg, LocalizableMessage title) 173 { 174 JOptionPane.showMessageDialog(parent, 175 wrapMsg(String.valueOf(msg), 100), 176 String.valueOf(title), JOptionPane.ERROR_MESSAGE); 177 } 178 179 /** 180 * Displays an information message dialog. 181 * 182 * @param parent 183 * the parent frame of the information dialog. 184 * @param msg 185 * the error message. 186 * @param title 187 * the title for the dialog. 188 */ 189 public static void displayInformationMessage(JFrame parent, LocalizableMessage msg, 190 LocalizableMessage title) 191 { 192 JOptionPane.showMessageDialog(parent, 193 wrapMsg(String.valueOf(msg), 100), String.valueOf(title), 194 JOptionPane.INFORMATION_MESSAGE); 195 } 196 197 /** 198 * Private method used to wrap the messages that are displayed in dialogs 199 * of type JOptionPane. 200 * @param msg the message. 201 * @param width the maximum width of the column. 202 * @return the wrapped message. 203 */ 204 private static String wrapMsg(String msg, int width) 205 { 206 StringBuilder buffer = new StringBuilder(); 207 StringTokenizer lineTokenizer = new StringTokenizer(msg, "\n", true); 208 while (lineTokenizer.hasMoreTokens()) 209 { 210 String line = lineTokenizer.nextToken(); 211 if (line.equals("\n")) 212 { 213 // It's an end-of-line character, so append it as-is. 214 buffer.append(line); 215 } 216 else if (line.length() < width) 217 { 218 // The line fits in the specified width, so append it as-is. 219 buffer.append(line); 220 } 221 else 222 { 223 // The line doesn't fit in the specified width, so it needs to be 224 // wrapped. Do so at space boundaries. 225 StringBuilder lineBuffer = new StringBuilder(); 226 StringBuilder delimBuffer = new StringBuilder(); 227 StringTokenizer wordTokenizer = new StringTokenizer(line, " ", true); 228 while (wordTokenizer.hasMoreTokens()) 229 { 230 String word = wordTokenizer.nextToken(); 231 if (word.equals(" ")) 232 { 233 // It's a space, so add it to the delim buffer only if the line 234 // buffer is not empty. 235 if (lineBuffer.length() > 0) 236 { 237 delimBuffer.append(word); 238 } 239 } 240 else if (word.length() > width) 241 { 242 // This is a long word that can't be wrapped, so we'll just have to 243 // make do. 244 if (lineBuffer.length() > 0) 245 { 246 buffer.append(lineBuffer); 247 buffer.append("\n"); 248 lineBuffer = new StringBuilder(); 249 } 250 buffer.append(word); 251 252 if (wordTokenizer.hasMoreTokens()) 253 { 254 // The next token must be a space, so remove it. If there are 255 // still more tokens after that, then append an EOL. 256 wordTokenizer.nextToken(); 257 if (wordTokenizer.hasMoreTokens()) 258 { 259 buffer.append("\n"); 260 } 261 } 262 263 if (delimBuffer.length() > 0) 264 { 265 delimBuffer = new StringBuilder(); 266 } 267 } 268 else 269 { 270 // It's not a space, so see if we can fit it on the current line. 271 int newLineLength = lineBuffer.length() + delimBuffer.length() + 272 word.length(); 273 if (newLineLength < width) 274 { 275 // It does fit on the line, so add it. 276 lineBuffer.append(delimBuffer).append(word); 277 } 278 else 279 { 280 // It doesn't fit on the line, so end the current line and start 281 // a new one. 282 buffer.append(lineBuffer); 283 buffer.append("\n"); 284 285 lineBuffer = new StringBuilder(); 286 lineBuffer.append(word); 287 } 288 289 if (delimBuffer.length() > 0) 290 { 291 delimBuffer = new StringBuilder(); 292 } 293 } 294 } 295 296 // If there's anything left in the line buffer, then add it to the 297 // final buffer. 298 buffer.append(lineBuffer); 299 } 300 } 301 return buffer.toString(); 302 } 303}