View Javadoc

1   /*
2    * Copyright 2006 - 2012 Christina Bohk and Roland Ewald
3    *  
4    * Licensed under the Apache License, Version 2.0 (the "License"); 
5    * you may not use this file except in compliance with the License. 
6    * You may obtain a copy of the License at 
7    *  
8    *  http://www.apache.org/licenses/LICENSE-2.0
9    *  
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
13   * See the License for the specific language governing permissions and 
14   * limitations under the License. 
15   */
16  package p3j.misc.gui;
17  
18  import james.SimSystem;
19  
20  import java.awt.BorderLayout;
21  import java.awt.Component;
22  import java.awt.Font;
23  import java.awt.Toolkit;
24  import java.awt.Window;
25  import java.util.List;
26  import java.util.logging.Level;
27  
28  import javax.swing.DefaultListModel;
29  import javax.swing.JComponent;
30  import javax.swing.JFileChooser;
31  import javax.swing.JLabel;
32  import javax.swing.JOptionPane;
33  import javax.swing.JPanel;
34  
35  import p3j.gui.P3J;
36  
37  import com.jgoodies.forms.layout.CellConstraints;
38  
39  /**
40   * Class to store static GUI helper functions.
41   * 
42   * Created on 4 February 4, 2007
43   * 
44   * @author Roland Ewald
45   */
46  public final class GUI {
47  
48  	/** Number of pixels in the gaps of the standard border layout. */
49  	public static final int STD_LAYOUT_GAP = 5;
50  
51  	/** The font-size of the wait-message. */
52  	private static final int FONT_SIZE_WAIT_MSG = 25;
53  
54  	/**
55  	 * The number of rows used for a single 'content' row in the layout (for
56  	 * stand-alone dialogs).
57  	 */
58  	public static final int ROW_SKIP_LAYOUT = 2;
59  
60  	/**
61  	 * The index of the column at which the keys are added to the content panel
62  	 * (for stand-alone dialogs).
63  	 */
64  	public static final int KEYS_COLUMN_INDEX = 2;
65  
66  	/**
67  	 * The index of the column at which the input elements (textfields etc.) are
68  	 * added to the content panel (for stand-alone dialogs).
69  	 */
70  	public static final int INPUT_COLUMN_INDEX = 4;
71  
72  	/**
73  	 * Flag to determine whether we are in head-less mode (no GUI, therefore no
74  	 * need to display error messages in dialogs). This is particularly convenient
75  	 * for GUI tests.
76  	 */
77  	private static boolean headless = false;
78  
79  	/**
80  	 * This class should not be instantiated.
81  	 */
82  	private GUI() {
83  	}
84  
85  	/**
86  	 * Get standard border layout. With 5 pixels gaps vertically/horizontally.
87  	 * 
88  	 * @return standard border layout
89  	 */
90  	public static BorderLayout getStdBorderLayout() {
91  		return new BorderLayout(STD_LAYOUT_GAP, STD_LAYOUT_GAP);
92  	}
93  
94  	/**
95  	 * Centre a given window on the screen.
96  	 * 
97  	 * @param window
98  	 *          a Window
99  	 */
100 	public static void centerOnScreen(Window window) {
101 		int locationX = (int) Math.round((Toolkit.getDefaultToolkit()
102 		    .getScreenSize().getWidth() - window.getWidth()) / 2);
103 		int locationY = (int) Math.round((Toolkit.getDefaultToolkit()
104 		    .getScreenSize().getHeight() - window.getHeight()) / 2);
105 		window.setLocation(locationX, locationY);
106 	}
107 
108 	/**
109 	 * Sets the head-less mode.
110 	 * 
111 	 * @param headless
112 	 *          the new head-less mode
113 	 */
114 	public static void setHeadless(boolean headless) {
115 		GUI.headless = headless;
116 	}
117 
118 	/**
119 	 * Checks the headless mode.
120 	 * 
121 	 * @return true if currently running head-less
122 	 */
123 	public static boolean isHeadless() {
124 		return GUI.headless;
125 	}
126 
127 	/**
128 	 * Prints an error message.
129 	 * 
130 	 * @param parent
131 	 *          the parent component for the dialog
132 	 * @param title
133 	 *          the title of the error dialog
134 	 * @param message
135 	 *          the message to be displayed
136 	 */
137 	public static void printErrorMessage(Component parent, String title,
138 	    Object message) {
139 		if (isHeadless()) {
140 			return;
141 		}
142 		JOptionPane.showMessageDialog(parent, message, title,
143 		    JOptionPane.ERROR_MESSAGE);
144 	}
145 
146 	/**
147 	 * Prints an error message and the stack trace of the corresponding exception.
148 	 * 
149 	 * @param parent
150 	 *          the parent component for the dialog
151 	 * @param title
152 	 *          the title of the error dialog
153 	 * @param message
154 	 *          the message to be displayed
155 	 * @param throwable
156 	 *          the throwable (may provide additional info)
157 	 */
158 	public static void printErrorMessage(Component parent, String title,
159 	    Object message, Throwable throwable) {
160 		SimSystem.report(Level.SEVERE, title, throwable);
161 		printErrorMessage(parent, title, message);
162 	}
163 
164 	/**
165 	 * Prints an error message with the P3J main window as parent instance. Uses
166 	 * {@link P3J#getInstance()} to retrieve it.
167 	 * 
168 	 * @param title
169 	 *          the title of the error dialog
170 	 * @param throwable
171 	 *          the throwable (may provide additional info)
172 	 */
173 	public static void printErrorMessage(String title, Throwable throwable) {
174 		SimSystem.report(Level.SEVERE, title, throwable);
175 		printErrorMessage(P3J.getInstance(), title, throwable.getMessage(),
176 		    throwable);
177 	}
178 
179 	/**
180 	 * Prints a message.
181 	 * 
182 	 * @param parent
183 	 *          the parent component for the dialog
184 	 * @param title
185 	 *          the title of the error dialog
186 	 * @param message
187 	 *          the message to be displayed
188 	 */
189 	public static void printMessage(Component parent, String title, Object message) {
190 		if (isHeadless()) {
191 			return;
192 		}
193 		JOptionPane.showMessageDialog(parent, message, title,
194 		    JOptionPane.INFORMATION_MESSAGE);
195 	}
196 
197 	/**
198 	 * Prints a question message.
199 	 * 
200 	 * @param parent
201 	 *          the parent component for the dialog
202 	 * @param title
203 	 *          the title of the dialog
204 	 * @param message
205 	 *          the question
206 	 * 
207 	 * @return true, if user chose yes, otherwise false
208 	 */
209 	public static boolean printQuestion(Component parent, String title,
210 	    Object message) {
211 
212 		if (isHeadless()) {
213 			throw new UnsupportedOperationException(
214 			    "Cannot print question while in head-less mode.");
215 		}
216 
217 		int decision = JOptionPane.showConfirmDialog(parent, message, title,
218 		    JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
219 
220 		if (decision == JOptionPane.YES_OPTION) {
221 			return true;
222 		}
223 
224 		return false;
225 	}
226 
227 	/**
228 	 * Replaces the contents o a default list model.
229 	 * 
230 	 * @param model
231 	 *          the list model to be filled
232 	 * @param newContent
233 	 *          the list containing the content
234 	 */
235 	public static void replaceListContents(DefaultListModel model,
236 	    List<?> newContent) {
237 		model.clear();
238 		if (newContent != null) {
239 			for (Object element : newContent) {
240 				model.addElement(element);
241 			}
242 		}
243 	}
244 
245 	/**
246 	 * Gets a file chooser configured to select a directory.
247 	 * 
248 	 * @param dialogTitle
249 	 *          the dialog title
250 	 * 
251 	 * @return the directory chooser
252 	 */
253 	public static JFileChooser getDirectoryChooser(String dialogTitle) {
254 		JFileChooser fileChooser = new JFileChooser();
255 		fileChooser.setMultiSelectionEnabled(false);
256 		fileChooser.setDialogTitle(dialogTitle);
257 		fileChooser.setDialogType(JFileChooser.CUSTOM_DIALOG);
258 		fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
259 		return fileChooser;
260 	}
261 
262 	/**
263 	 * Gets the label to wait.
264 	 * 
265 	 * @return the label to wait
266 	 */
267 	public static JLabel getLabelToWait() {
268 		JLabel msg = new JLabel("This may take a while. Please be patient...");
269 		msg.setFont(new Font("Sans", Font.BOLD, FONT_SIZE_WAIT_MSG));
270 		return msg;
271 	}
272 
273 	/**
274 	 * Adds a pair of key and input components to the given panel panel.
275 	 * 
276 	 * @param panel
277 	 *          the panel
278 	 * @param key
279 	 *          the name of the label to be used
280 	 * @param input
281 	 *          the input component
282 	 * @param currentRow
283 	 *          the current row in the layout
284 	 * @return the new row in the layout
285 	 */
286 	public static int addRowToPanel(JPanel panel, String key, JComponent input,
287 	    int currentRow) {
288 		CellConstraints c = new CellConstraints();
289 		panel.add(new JLabel(key), c.xy(KEYS_COLUMN_INDEX, currentRow));
290 		panel.add(input, c.xy(INPUT_COLUMN_INDEX, currentRow));
291 		return currentRow + ROW_SKIP_LAYOUT;
292 	}
293 }