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