001: /*
002: * Copyright (c) 2002-2007 JGoodies Karsten Lentzsch. All Rights Reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, 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 JGoodies Karsten Lentzsch nor the names of
015: * its contributors may be used to endorse or promote products derived
016: * from this software without 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,
020: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
022: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
027: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030:
031: package com.jgoodies.forms.builder;
032:
033: import java.awt.Component;
034:
035: import javax.swing.JComponent;
036: import javax.swing.JLabel;
037: import javax.swing.JPanel;
038:
039: import com.jgoodies.forms.layout.CellConstraints;
040: import com.jgoodies.forms.layout.FormLayout;
041:
042: /**
043: * An abstract panel builder class that uses the {@link FormLayout}
044: * to lay out <code>JPanel</code>s. In addition to its superclass
045: * {@link PanelBuilder} this class provides convenience behavior to map
046: * resource keys to their associated internationalized (i15d) strings
047: * when adding labels, titles and titled separators.<p>
048: *
049: * The localized texts used in methods <code>#addI15dLabel</code>
050: * and <code>#addI15dTitle</code> can contain an optional mnemonic marker.
051: * The mnemonic and mnemonic index are indicated by a single ampersand
052: * (<tt>&</tt>). For example <tt>"&Save"</tt>, or
053: * <tt>"Save &as"</tt>. To use the ampersand itself,
054: * duplicate it, for example <tt>"Look&&Feel"</tt>.<p>
055: *
056: * For debugging purposes you can automatically set a tooltip for the
057: * created labels that show its resource key. In case of an inproper
058: * resource localization, the label will show the wrong text, and the tooltip
059: * will help you identify the resource key with the broken localization.
060: * This feature can be enabled by calling <code>setDebugToolTipsEnabled</code>.
061: * If you want to enable it in a deployed application, you can set the system
062: * parameter <code>I15dPanelBuilder.debugToolTipsEnabled</code> to "true".<p>
063: *
064: * Subclasses must implement the conversion from resource key
065: * to the localized string in <code>#getI15dString(String)</code>.
066: * For example class I15dPanelBuilder gets a ResourceBundle on
067: * construction, and requests strings from that bundle.
068: *
069: * @author Karsten Lentzsch
070: * @version $Revision: 1.1 $
071: *
072: * @since 1.1
073: */
074: public abstract class AbstractI15dPanelBuilder extends PanelBuilder {
075:
076: private static final String DEBUG_TOOL_TIPS_ENABLED_KEY = "I15dPanelBuilder.debugToolTipsEnabled";
077:
078: private static boolean debugToolTipsEnabled = getDebugToolTipSystemProperty();
079:
080: // Instance Creation ****************************************************
081:
082: /**
083: * Constructs an <code>AbstractI15dPanelBuilder</code> for the given
084: * layout. Uses an instance of <code>JPanel</code> as layout container.
085: *
086: * @param layout the <code>FormLayout</code> used to layout the container
087: */
088: protected AbstractI15dPanelBuilder(FormLayout layout) {
089: super (layout);
090: }
091:
092: /**
093: * Constructs an <code>AbstractI15dPanelBuilder</code>
094: * for the given FormLayout and layout container.
095: *
096: * @param layout the <code>FormLayout</code> used to layout the container
097: * @param panel the layout container
098: */
099: protected AbstractI15dPanelBuilder(FormLayout layout, JPanel panel) {
100: super (layout, panel);
101: }
102:
103: // Debug ToolTip Settings *************************************************
104:
105: private static boolean getDebugToolTipSystemProperty() {
106: try {
107: String value = System
108: .getProperty(DEBUG_TOOL_TIPS_ENABLED_KEY);
109: return "true".equalsIgnoreCase(value);
110: } catch (SecurityException e) {
111: return false;
112: }
113: }
114:
115: /**
116: * Returns whether the debug tool tips are enabled or not.
117: *
118: * @return true if debug tool tips are enabled, false if disabled
119: */
120: public static boolean isDebugToolTipsEnabled() {
121: return debugToolTipsEnabled;
122: }
123:
124: /**
125: * Enables or disables the debug tool tips.
126: *
127: * @param b true to enable, false to disable
128: */
129: public static void setDebugToolTipsEnabled(boolean b) {
130: debugToolTipsEnabled = b;
131: }
132:
133: // Adding Labels and Separators *****************************************
134:
135: /**
136: * Adds an internationalized (i15d) textual label to the form using the
137: * specified constraints.
138: *
139: * @param resourceKey the resource key for the label's text
140: * @param constraints the label's cell constraints
141: * @return the added label
142: */
143: public final JLabel addI15dLabel(String resourceKey,
144: CellConstraints constraints) {
145: JLabel label = addLabel(getI15dString(resourceKey), constraints);
146: if (isDebugToolTipsEnabled()) {
147: label.setToolTipText(resourceKey);
148: }
149: return label;
150: }
151:
152: /**
153: * Adds an internationalized (i15d) textual label to the form using the
154: * specified constraints.
155: *
156: * @param resourceKey the resource key for the label's text
157: * @param encodedConstraints a string representation for the constraints
158: * @return the added label
159: */
160: public final JLabel addI15dLabel(String resourceKey,
161: String encodedConstraints) {
162: return addI15dLabel(resourceKey, new CellConstraints(
163: encodedConstraints));
164: }
165:
166: /**
167: * Adds an internationalized (i15d) label and component to the panel using
168: * the given cell constraints. Sets the label as <i>the</i> component label
169: * using {@link JLabel#setLabelFor(java.awt.Component)}.<p>
170: *
171: * <strong>Note:</strong> The {@link CellConstraints} objects for the label
172: * and the component must be different. Cell constraints are implicitly
173: * cloned by the <code>FormLayout</code> when added to the container.
174: * However, in this case you may be tempted to reuse a
175: * <code>CellConstraints</code> object in the same way as with many other
176: * builder methods that require a single <code>CellConstraints</code>
177: * parameter.
178: * The pitfall is that the methods <code>CellConstraints.xy**(...)</code>
179: * just set the coordinates but do <em>not</em> create a new instance.
180: * And so the second invocation of <code>xy***(...)</code> overrides
181: * the settings performed in the first invocation before the object
182: * is cloned by the <code>FormLayout</code>.<p>
183: *
184: * <strong>Wrong:</strong><pre>
185: * builder.add("name.key",
186: * cc.xy(1, 7), // will be modified by the code below
187: * nameField,
188: * cc.xy(3, 7) // sets the single instance to (3, 7)
189: * );
190: * </pre>
191: * <strong>Correct:</strong><pre>
192: * builder.add("name.key",
193: * cc.xy(1, 7).clone(), // cloned before the next modification
194: * nameField,
195: * cc.xy(3, 7) // sets this instance to (3, 7)
196: * );
197: * </pre>
198: *
199: * @param resourceKey the resource key for the label
200: * @param labelConstraints the label's cell constraints
201: * @param component the component to add
202: * @param componentConstraints the component's cell constraints
203: * @return the added label
204: * @throws IllegalArgumentException if the same cell constraints instance
205: * is used for the label and the component
206: * @see JLabel#setLabelFor(java.awt.Component)
207: */
208: public final JLabel addI15dLabel(String resourceKey,
209: CellConstraints labelConstraints, Component component,
210: CellConstraints componentConstraints) {
211:
212: JLabel label = addLabel(getI15dString(resourceKey),
213: labelConstraints, component, componentConstraints);
214: if (isDebugToolTipsEnabled()) {
215: label.setToolTipText(resourceKey);
216: }
217: return label;
218: }
219:
220: /**
221: * Adds an internationalized (i15d) titled separator to the form using the
222: * specified constraints.
223: *
224: * @param resourceKey the resource key for the separator title
225: * @param constraints the separator's cell constraints
226: * @return the added titled separator
227: */
228: public final JComponent addI15dSeparator(String resourceKey,
229: CellConstraints constraints) {
230: JComponent component = addSeparator(getI15dString(resourceKey),
231: constraints);
232: if (isDebugToolTipsEnabled()) {
233: component.setToolTipText(resourceKey);
234: }
235: return component;
236: }
237:
238: /**
239: * Adds an internationalized (i15d) titled separator to the form using
240: * the specified constraints.
241: *
242: * @param resourceKey the resource key for the separator titel
243: * @param encodedConstraints a string representation for the constraints
244: * @return the added titled separator
245: */
246: public final JComponent addI15dSeparator(String resourceKey,
247: String encodedConstraints) {
248: return addI15dSeparator(resourceKey, new CellConstraints(
249: encodedConstraints));
250: }
251:
252: /**
253: * Adds a title to the form using the specified constraints.
254: *
255: * @param resourceKey the resource key for the separator title
256: * @param constraints the separator's cell constraints
257: * @return the added title label
258: */
259: public final JLabel addI15dTitle(String resourceKey,
260: CellConstraints constraints) {
261: JLabel label = addTitle(getI15dString(resourceKey), constraints);
262: if (isDebugToolTipsEnabled()) {
263: label.setToolTipText(resourceKey);
264: }
265: return label;
266: }
267:
268: /**
269: * Adds a title to the form using the specified constraints.
270: *
271: * @param resourceKey the resource key for the separator titel
272: * @param encodedConstraints a string representation for the constraints
273: * @return the added title label
274: */
275: public final JLabel addI15dTitle(String resourceKey,
276: String encodedConstraints) {
277: return addI15dTitle(resourceKey, new CellConstraints(
278: encodedConstraints));
279: }
280:
281: // Abstract Behavior ******************************************************
282:
283: /**
284: * Looks up and returns the internationalized (i15d) string for the given
285: * resource key from the <code>ResourceMap</code>.
286: *
287: * @param resourceKey the key to look for in the resource map
288: * @return the associated internationalized string, or the resource key
289: * itself in case of a missing resource
290: * @throws IllegalStateException if no <code>ResourceBundle</code>
291: * has been set
292: */
293: protected abstract String getI15dString(String resourceKey);
294:
295: }
|