001: /*
002: * Copyright (c) 2004 JETA Software, Inc. All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without modification,
005: * are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of JETA Software nor the names of its contributors may
015: * be used to endorse or promote products derived from this software without
016: * specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
021: * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
022: * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
023: * INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
024: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
025: * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
026: * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: */
029:
030: package com.jeta.open.gui.utils;
031:
032: import java.awt.Component;
033: import java.awt.Dialog;
034: import java.awt.Dimension;
035: import java.awt.Font;
036: import java.awt.FontMetrics;
037: import java.awt.Frame;
038: import java.awt.Toolkit;
039: import java.awt.Window;
040: import java.awt.datatransfer.Clipboard;
041: import java.awt.datatransfer.StringSelection;
042: import java.lang.reflect.Constructor;
043:
044: import javax.swing.JComboBox;
045: import javax.swing.JComponent;
046: import javax.swing.SwingUtilities;
047:
048: import com.jeta.open.gui.framework.JETADialog;
049: import com.jeta.open.gui.framework.JETAPanel;
050: import com.jeta.open.registry.JETARegistry;
051:
052: /**
053: * Some common utility functions for GUI stuff.
054: *
055: * @author Jeff Tassin
056: */
057: public class JETAToolbox {
058: /** used for calculating average char widths */
059: private static final String AVG_STR = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
060:
061: public static final String APPLICATION_FRAME = "application.frame.window";
062: public static final String WINDOWS_LF = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
063:
064: /**
065: * Adds an array or collection of items to a combo box
066: */
067: public static void addItems(JComboBox cbox, Object[] items) {
068: assert (cbox != null);
069: if (items == null || cbox == null)
070: return;
071:
072: for (int index = 0; index < items.length; index++) {
073: cbox.addItem(items[index]);
074: }
075: }
076:
077: /**
078: * Converts an Array of JComponents to an array of Components
079: */
080: private static Component[] toComponentArray(JComponent[] components) {
081: Component[] result = new Component[components.length];
082: for (int index = 0; index < components.length; index++) {
083: result[index] = components[index];
084: }
085: return result;
086: }
087:
088: /**
089: * Calculates the width of an average string of text.
090: *
091: * @param comp
092: * the component whose font metrics will determine the width
093: * @param numCharacters
094: * the number of characters to use to calculate the length
095: */
096: public static int calculateAverageTextWidth(Component comp,
097: int numCharacters) {
098: if (comp == null)
099: return 0;
100:
101: Font f = comp.getFont();
102: FontMetrics metrics = comp.getFontMetrics(f);
103: return metrics.stringWidth(AVG_STR) * numCharacters
104: / AVG_STR.length();
105: }
106:
107: /**
108: * Sets the size of the dimension to some reasonable value. If the given
109: * dimension is larger than the screen size, then we set the window to 80%
110: * of the screen size. Otherwise, we leave it alone
111: *
112: * @param d
113: * the dimension of the window to set
114: */
115: public static void calculateReasonableComponentSize(Dimension d) {
116: Dimension screensize = Toolkit.getDefaultToolkit()
117: .getScreenSize();
118: if (d.width > screensize.width)
119: d.width = screensize.width * 8 / 10;
120:
121: if (d.height > screensize.height)
122: d.height = screensize.height * 8 / 10;
123: }
124:
125: /**
126: * This method centers and sizes a frame window on the screen. The caller
127: * must pass the x and y percentages of screen width/height.
128: */
129: public static void centerFrame(Window frame, float xpctWidth,
130: float ypctWidth) {
131: Dimension screenSize = Toolkit.getDefaultToolkit()
132: .getScreenSize();
133: int frame_width = (int) (screenSize.width * xpctWidth);
134: int frame_height = (int) (screenSize.height * ypctWidth);
135: int left = (screenSize.width - frame_width) / 2;
136: int top = (screenSize.height - frame_height) / 2;
137: frame.setBounds(left, top, frame_width, frame_height);
138: }
139:
140: /**
141: * This method centers a window window on the screen. The caller must pass
142: * the x and y percentages of screen width/height.
143: */
144: public static void centerWindow(Window frame) {
145: float width = (float) frame.getWidth();
146: float height = (float) frame.getHeight();
147: Dimension screenSize = Toolkit.getDefaultToolkit()
148: .getScreenSize();
149: float pctwidth = width / (float) screenSize.getWidth();
150: float pctheight = height / (float) screenSize.getHeight();
151: centerFrame(frame, pctwidth, pctheight);
152: }
153:
154: /**
155: * This method centers a window window and changes the width on the screen.
156: * The caller must pass the x percentages of screen width. The height
157: * remains unchanged
158: */
159: public static void centerWindowChangeWidth(Window frame,
160: float xpctWidth) {
161: float height = (float) frame.getHeight();
162: Dimension screenSize = Toolkit.getDefaultToolkit()
163: .getScreenSize();
164: float pctheight = height / (float) screenSize.getHeight();
165: centerFrame(frame, xpctWidth, pctheight);
166: }
167:
168: /**
169: * Copies to the clipboard the given string
170: */
171: public static void copyToClipboard(String str) {
172: Toolkit kit = Toolkit.getDefaultToolkit();
173: Clipboard clipboard = kit.getSystemClipboard();
174: StringSelection ss = new StringSelection(str);
175: clipboard.setContents(ss, ss);
176: }
177:
178: /**
179: * This method creates a dialog of the type class. It assumes that the
180: * dialog will have constructors that have the following form: ctor( JDialog
181: * owner, boolean bmodal ) ctor( Frame owner, boolean bmodal )
182: *
183: * This method interogates the owner object. If this object is a JDialog or
184: * Frame, then we call the appropriate constructor for the class. If this
185: * object is a JComponent, then we get the objects owner window and
186: * determine if that is a JDialog or Frame.
187: *
188: * @param dlgclass
189: * the class of the dialog we want to create
190: * @param owner
191: * the owner of the new dialog. This object can be indirectly an
192: * owner. For example, you can pass in a JPanel as the owner.
193: * This method will detect this and get the appropriate owner of
194: * the JPanel
195: * @param bModal
196: * true if you want the dialog to be modal
197: *
198: */
199: public static Dialog createDialog(Class dlgclass, Component owner,
200: boolean bModal) {
201: Class[] cparams = new Class[2];
202: Object[] params = new Object[2];
203:
204: if (owner == null) {
205: // try the registry
206: Object comp = JETARegistry.lookup(APPLICATION_FRAME);
207: if (comp instanceof Component)
208: owner = (Component) comp;
209: }
210:
211: if (owner instanceof Dialog) {
212: cparams[0] = Dialog.class;
213: params[0] = owner;
214: } else if (owner instanceof Frame) {
215: cparams[0] = Frame.class;
216: params[0] = owner;
217: } else {
218: if (owner == null) {
219: cparams[0] = Frame.class;
220: params[0] = null;
221: } else {
222: Window win = SwingUtilities.getWindowAncestor(owner);
223: if (win instanceof Dialog) {
224: cparams[0] = Dialog.class;
225: params[0] = win;
226: } else if (win instanceof Frame) {
227: cparams[0] = Frame.class;
228: params[0] = win;
229: } else {
230: cparams[0] = Frame.class;
231: params[0] = null;
232: }
233: }
234: }
235: cparams[1] = boolean.class;
236: params[1] = Boolean.valueOf(bModal);
237:
238: try {
239: Constructor ctor = dlgclass.getConstructor(cparams);
240: return (Dialog) ctor.newInstance(params);
241: } catch (Exception e) {
242: System.out
243: .println("Unable to construct dialg parent class: "
244: + cparams[0] + " owner = " + owner);
245: e.printStackTrace();
246: }
247: return null;
248: }
249:
250: /**
251: * @return the thickness (in pixels) of the border on a frame or dialog
252: * window Currently, this is hard coded until I figure out a way to
253: * get this value.
254: */
255: public static int getFrameBorderThickness() {
256: if (isOSX())
257: return 0;
258: else
259: return 4; // temporary
260: }
261:
262: /**
263: * @return the height (in pixels) of the titlebar on a frame or dialog
264: * window Currently, this is hard coded until I figure out a way to
265: * get this value.
266: */
267: public static int getTitleBarHeight() {
268: return 20;
269: }
270:
271: /**
272: * Creates and displays a model JETADialog using the given view as the
273: * content pane. The dialog is centered on the screen and it's modal parent
274: * is set to null.
275: *
276: */
277: public static JETADialog invokeDialog(JETAPanel view,
278: Component owner, String title) {
279: JETADialog dlg = (JETADialog) JETAToolbox.createDialog(
280: JETADialog.class, owner, true);
281: dlg.setPrimaryPanel(view);
282: dlg.setTitle(title);
283: dlg.setSize(dlg.getPreferredSize());
284: dlg.showCenter();
285: return dlg;
286: }
287:
288: /**
289: * Creates and displays a model JETADialog using the given view as the
290: * content pane. The dialog is centered on the screen and it's modal parent
291: * is set to null.
292: *
293: * @param view
294: * the main content panel for the dialog
295: * @param title
296: * the dialog's title
297: * @param initialFocus
298: * the component that will have the initial focus
299: */
300: public static JETADialog invokeDialog(JETAPanel view,
301: Component owner, String title, JComponent initialFocus) {
302: JETADialog dlg = (JETADialog) JETAToolbox.createDialog(
303: JETADialog.class, owner, true);
304: dlg.setPrimaryPanel(view);
305: dlg.setTitle(title);
306: dlg.setSize(dlg.getPreferredSize());
307: dlg.setInitialFocusComponent(initialFocus);
308: dlg.showCenter();
309: return dlg;
310: }
311:
312: /**
313: * Returns true if running OS X Aqua look and feel.
314: */
315: public static boolean isAquaLookAndFeel() {
316: javax.swing.LookAndFeel laf = javax.swing.UIManager
317: .getLookAndFeel();
318: return laf.getName().startsWith("Mac OS X");
319: }
320:
321: /**
322: * @return true if running Mac OS X
323: */
324: public static boolean isOSX() {
325: try {
326: return (System.getProperty("mrj.version") != null);
327: } catch (Exception e) {
328:
329: }
330: return false;
331: }
332:
333: /**
334: * @return true if running Windows
335: */
336: public static boolean isWindows() {
337: try {
338: String result = System.getProperty("os.name");
339: if (result != null) {
340: result = result.toLowerCase();
341: if (result.indexOf("windows") >= 0)
342: return true;
343: }
344: } catch (Exception e) {
345:
346: }
347: return false;
348: }
349:
350: /**
351: * @return true if we are currently in the windows look and feel. This L&F
352: * has different focus issues with the popup
353: */
354: public static boolean isWindowsLookAndFeel() {
355: return (WINDOWS_LF.equals(javax.swing.UIManager
356: .getLookAndFeel().getClass().getName()));
357: }
358:
359: /**
360: * Sets the size of the given window to the passed in dimension. However, if
361: * the given dimension is larger than the screen size, then we set the
362: * window to 80% of the screen size
363: *
364: * @param window
365: * the window whose size we are setting
366: * @param d
367: * the dimension of the window to set
368: */
369: public static void setReasonableWindowSize(Component window,
370: Dimension d) {
371: calculateReasonableComponentSize(d);
372: window.setSize(d);
373: }
374: }
|