Source Code Cross Referenced for DefaultComponentFactory.java in  » Swing-Library » abeille-forms-designer » com » jgoodies » forms » factories » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Swing Library » abeille forms designer » com.jgoodies.forms.factories 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright (c) 2002-2004 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.factories;
032:
033:        import java.awt.Color;
034:        import java.awt.Component;
035:        import java.awt.Container;
036:        import java.awt.Dimension;
037:        import java.awt.Font;
038:        import java.awt.FontMetrics;
039:        import java.awt.Insets;
040:        import java.awt.LayoutManager;
041:        import java.beans.PropertyChangeEvent;
042:        import java.beans.PropertyChangeListener;
043:
044:        import javax.swing.JComponent;
045:        import javax.swing.JLabel;
046:        import javax.swing.JPanel;
047:        import javax.swing.JSeparator;
048:        import javax.swing.LookAndFeel;
049:        import javax.swing.SwingConstants;
050:        import javax.swing.UIManager;
051:
052:        import com.jgoodies.forms.layout.Sizes;
053:
054:        /**
055:         * A singleton implementaton of the {@link ComponentFactory} interface that
056:         * creates UI components as required by the
057:         * {@link com.jgoodies.forms.builder.PanelBuilder}.
058:         * <p>
059:         * 
060:         * The texts used in methods <code>#createLabel(String)</code> and
061:         * <code>#createTitle(String)</code> can contain an optional mnemonic marker.
062:         * The mnemonic and mnemonic index are indicated by a single ampersand (<tt>&amp;</tt>).
063:         * For example <tt>&quot;&amp;Save&quot</tt>, or
064:         * <tt>&quot;Save&nbsp;&amp;as&quot</tt>. To use the ampersand itself
065:         * duplicate it, for example <tt>&quot;Look&amp;&amp;Feel&quot</tt>.
066:         * 
067:         * @author Karsten Lentzsch
068:         * @version $Revision: 1.2 $
069:         */
070:
071:        public class DefaultComponentFactory implements  ComponentFactory {
072:
073:            /**
074:             * Holds the single instance of this class.
075:             */
076:            private static final DefaultComponentFactory INSTANCE = new DefaultComponentFactory();
077:
078:            /**
079:             * The character used to indicate the mnemonic position for labels.
080:             */
081:            private static final char MNEMONIC_MARKER = '&';
082:
083:            // Instance *************************************************************
084:
085:            private DefaultComponentFactory() {
086:                // Suppresses default constructor, ensuring non-instantiability.
087:            }
088:
089:            /**
090:             * Returns the sole instance of this factory class.
091:             * 
092:             * @return the sole instance of this factory class
093:             */
094:            public static DefaultComponentFactory getInstance() {
095:                return INSTANCE;
096:            }
097:
098:            // Component Creation ***************************************************
099:
100:            /**
101:             * Creates and returns a label with an optional mnemonic.
102:             * <p>
103:             * 
104:             * <pre>
105:             * createLabel(&quot;Name&quot;); // No mnemonic
106:             * createLabel(&quot;N&amp;ame&quot;); // Mnemonic is 'a'
107:             * createLabel(&quot;Save &amp;as&quot;); // Mnemonic is the second 'a'
108:             * createLabel(&quot;Look&amp;&amp;Feel&quot;); // No mnemonic, text is Look&amp;Feel
109:             * </pre>
110:             * 
111:             * @param textWithMnemonic
112:             *            the label's text - may contain a mnemonic
113:             * @return an label with optional mnemonic
114:             */
115:            public JLabel createLabel(String textWithMnemonic) {
116:                JLabel label = new JLabel();
117:                setTextAndMnemonic(label, textWithMnemonic);
118:                return label;
119:            }
120:
121:            /**
122:             * Creates and returns a label that uses the foreground color and font of a
123:             * <code>TitledBorder</code>.
124:             * <p>
125:             * 
126:             * <pre>
127:             * createTitle(&quot;Name&quot;); // No mnemonic
128:             * createTitle(&quot;N&amp;ame&quot;); // Mnemonic is 'a'
129:             * createTitle(&quot;Save &amp;as&quot;); // Mnemonic is the second 'a'
130:             * createTitle(&quot;Look&amp;&amp;Feel&quot;); // No mnemonic, text is Look&amp;Feel
131:             * </pre>
132:             * 
133:             * @param textWithMnemonic
134:             *            the title's text - may contain a mnemonic
135:             * @return an emphasized title label
136:             */
137:            public JLabel createTitle(String textWithMnemonic) {
138:                JLabel label = new TitleLabel();
139:                setTextAndMnemonic(label, textWithMnemonic);
140:                label.setVerticalAlignment(SwingConstants.CENTER);
141:                return label;
142:            }
143:
144:            /**
145:             * Creates and returns a labeled separator with the label in the left-hand
146:             * side. Useful to separate paragraphs in a panel; often a better choice
147:             * than a <code>TitledBorder</code>.
148:             * 
149:             * @param text
150:             *            the title's text
151:             * @return a title label with separator on the side
152:             */
153:            public JComponent createSeparator(String text) {
154:                return createSeparator(text, SwingConstants.LEFT);
155:            }
156:
157:            /**
158:             * Creates and returns a labeled separator. Useful to separate paragraphs in
159:             * a panel, which is often a better choice than a <code>TitledBorder</code>.
160:             * 
161:             * @param text
162:             *            the title's text
163:             * @param alignment
164:             *            text alignment: left, center, right
165:             * @return a separator with title label
166:             */
167:            public JComponent createSeparator(String text, int alignment) {
168:                if (text == null || text.length() == 0) {
169:                    return new JSeparator();
170:                }
171:                JLabel title = createTitle(text);
172:                title.setHorizontalAlignment(alignment);
173:                return createSeparator(title);
174:            }
175:
176:            /**
177:             * Creates and returns a labeled separator. Useful to separate paragraphs in
178:             * a panel, which is often a better choice than a <code>TitledBorder</code>.
179:             * <p>
180:             * 
181:             * The label's position is determined by the label's horizontal alignment.
182:             * 
183:             * @param label
184:             *            the title label component
185:             * @return a separator with title label
186:             * @throws NullPointerException
187:             *             if the label is <code>null</code>
188:             */
189:            private JComponent createSeparator(JLabel label) {
190:                if (label == null)
191:                    throw new NullPointerException(
192:                            "The label must not be null.");
193:
194:                JPanel panel = new JPanel(new TitledSeparatorLayout(
195:                        !isLafAqua()));
196:                panel.setOpaque(false);
197:                panel.add(label);
198:                panel.add(new JSeparator());
199:                if (label.getHorizontalAlignment() == SwingConstants.CENTER) {
200:                    panel.add(new JSeparator());
201:                }
202:                return panel;
203:            }
204:
205:            // Helper Code ***********************************************************
206:
207:            /**
208:             * Sets the text of the given label and optionally a mnemonic. The given
209:             * text may contain mnemonic markers <b>&&</b>, where such a marker
210:             * indicates that the following character shall be the mnemonic. If you want
211:             * to use the <b>\&</b> charachter, just put two together, for example
212:             * &quot;&&&&&quot;.
213:             * 
214:             * @param label
215:             *            the label that gets a mnemonic
216:             * @param textWithMnemonic
217:             *            the text with optional mnemonic marker
218:             */
219:            private static void setTextAndMnemonic(JLabel label,
220:                    String textWithMnemonic) {
221:                int markerIndex = textWithMnemonic.indexOf(MNEMONIC_MARKER);
222:                // No marker at all
223:                if (markerIndex == -1) {
224:                    label.setText(textWithMnemonic);
225:                    return;
226:                }
227:                int mnemonicIndex = -1;
228:                int begin = 0;
229:                int end;
230:                int length = textWithMnemonic.length();
231:                StringBuffer buffer = new StringBuffer();
232:                do {
233:                    // Check whether the next index has a mnemonic marker, too
234:                    if (markerIndex + 1 < length
235:                            && textWithMnemonic.charAt(markerIndex + 1) == MNEMONIC_MARKER) {
236:                        end = markerIndex + 1;
237:                    } else {
238:                        end = markerIndex;
239:                        if (mnemonicIndex == -1)
240:                            mnemonicIndex = markerIndex;
241:                    }
242:                    buffer.append(textWithMnemonic.substring(begin, end));
243:                    begin = end + 1;
244:                    markerIndex = begin < length ? textWithMnemonic.indexOf(
245:                            MNEMONIC_MARKER, begin) : -1;
246:                } while (markerIndex != -1);
247:                buffer.append(textWithMnemonic.substring(begin));
248:
249:                label.setText(buffer.toString());
250:                if ((mnemonicIndex != -1) && (mnemonicIndex + 1 < length)) {
251:                    label.setDisplayedMnemonic(textWithMnemonic
252:                            .charAt(mnemonicIndex + 1));
253:                    label.setDisplayedMnemonicIndex(mnemonicIndex);
254:                }
255:            }
256:
257:            // A label that uses the TitleBorder font and color
258:            private static class TitleLabel extends JLabel {
259:
260:                private TitleLabel() {
261:                    // Just invoke the super constructor.
262:                }
263:
264:                private TitleLabel(String text) {
265:                    super (text);
266:                }
267:
268:                /**
269:                 * TODO: Consider asking a <code>TitledBorder</code> instance for its
270:                 * font and font color use <code>#getTitleFont</code> and
271:                 * <code>#getTitleColor</code> for the Synth-based looks.
272:                 */
273:                public void updateUI() {
274:                    super .updateUI();
275:                    Color foreground = UIManager
276:                            .getColor("TitledBorder.titleColor");
277:                    if (foreground != null)
278:                        setForeground(foreground);
279:                    setFont(getTitleFont());
280:                }
281:
282:                /**
283:                 * Looks up and returns the font used for title labels. Since Mac Aqua
284:                 * uses an inappropriate titled border font, we use a bold label font
285:                 * instead. Actually if the title is used in a titled separator, the
286:                 * bold weight is questionable. It seems that most native Aqua tools use
287:                 * a plain label in titled separators.
288:                 * 
289:                 * @return the font used for title labels
290:                 */
291:                private Font getTitleFont() {
292:                    return isLafAqua() ? UIManager.getFont("Label.font")
293:                            .deriveFont(Font.BOLD) : UIManager
294:                            .getFont("TitledBorder.font");
295:                }
296:
297:            }
298:
299:            // A layout for the title label and separator(s) in titled separators.
300:            private static class TitledSeparatorLayout implements  LayoutManager {
301:
302:                private final boolean centerSeparators;
303:
304:                /**
305:                 * Constructs a TitledSeparatorLayout that either centers the separators
306:                 * or aligns them along the font baseline of the title label.
307:                 * 
308:                 * @param centerSeparators
309:                 *            true to center, false to align along the font baseline of
310:                 *            the title label
311:                 */
312:                private TitledSeparatorLayout(boolean centerSeparators) {
313:                    this .centerSeparators = centerSeparators;
314:                }
315:
316:                /**
317:                 * Does nothing. This layout manager looks up the components from the
318:                 * layout container and used the component's index in the child array to
319:                 * identify the label and separators.
320:                 * 
321:                 * @param name
322:                 *            the string to be associated with the component
323:                 * @param comp
324:                 *            the component to be added
325:                 */
326:                public void addLayoutComponent(String name, Component comp) {
327:                    // Does nothing.
328:                }
329:
330:                /**
331:                 * Does nothing. This layout manager looks up the components from the
332:                 * layout container and used the component's index in the child array to
333:                 * identify the label and separators.
334:                 * 
335:                 * @param comp
336:                 *            the component to be removed
337:                 */
338:                public void removeLayoutComponent(Component comp) {
339:                    // Does nothing.
340:                }
341:
342:                /**
343:                 * Computes and returns the minimum size dimensions for the specified
344:                 * container. Forwards this request to <code>#preferredLayoutSize</code>.
345:                 * 
346:                 * @param parent
347:                 *            the component to be laid out
348:                 * @return the container's minimum size.
349:                 * @see #preferredLayoutSize(Container)
350:                 */
351:                public Dimension minimumLayoutSize(Container parent) {
352:                    return preferredLayoutSize(parent);
353:                }
354:
355:                /**
356:                 * Computes and returns the preferred size dimensions for the specified
357:                 * container. Returns the title label's preferred size.
358:                 * 
359:                 * @param parent
360:                 *            the component to be laid out
361:                 * @return the container's preferred size.
362:                 * @see #minimumLayoutSize(Container)
363:                 */
364:                public Dimension preferredLayoutSize(Container parent) {
365:                    Component label = getLabel(parent);
366:                    Dimension labelSize = label.getPreferredSize();
367:                    Insets insets = parent.getInsets();
368:                    int width = labelSize.width + insets.left + insets.right;
369:                    int height = labelSize.height + insets.top + insets.bottom;
370:                    return new Dimension(width, height);
371:                }
372:
373:                /**
374:                 * Lays out the specified container.
375:                 * 
376:                 * @param parent
377:                 *            the container to be laid out
378:                 */
379:                public void layoutContainer(Container parent) {
380:                    synchronized (parent.getTreeLock()) {
381:                        // Look up the parent size and insets
382:                        Dimension size = parent.getSize();
383:                        Insets insets = parent.getInsets();
384:                        int width = size.width - insets.left - insets.right;
385:
386:                        // Look up components and their sizes
387:                        JLabel label = getLabel(parent);
388:                        Dimension labelSize = label.getPreferredSize();
389:                        int labelWidth = labelSize.width;
390:                        int labelHeight = labelSize.height;
391:                        Component separator1 = parent.getComponent(1);
392:                        int separatorHeight = separator1.getPreferredSize().height;
393:
394:                        FontMetrics metrics = label.getFontMetrics(label
395:                                .getFont());
396:                        int ascent = metrics.getMaxAscent();
397:                        int hGapDlu = centerSeparators ? 3 : 1;
398:                        int hGap = Sizes.dialogUnitXAsPixel(hGapDlu, label);
399:                        int vOffset = centerSeparators ? 1 + (labelHeight - separatorHeight) / 2
400:                                : ascent - separatorHeight / 2;
401:
402:                        int alignment = label.getHorizontalAlignment();
403:                        int y = insets.top;
404:                        if (alignment == JLabel.LEFT) {
405:                            int x = insets.left;
406:                            label.setBounds(x, y, labelWidth, labelHeight);
407:                            x += labelWidth;
408:                            x += hGap;
409:                            int separatorWidth = size.width - insets.right - x;
410:                            separator1.setBounds(x, y + vOffset,
411:                                    separatorWidth, separatorHeight);
412:                        } else if (alignment == JLabel.RIGHT) {
413:                            int x = insets.left + width - labelWidth;
414:                            label.setBounds(x, y, labelWidth, labelHeight);
415:                            x -= hGap;
416:                            x--;
417:                            int separatorWidth = x - insets.left;
418:                            separator1.setBounds(insets.left, y + vOffset,
419:                                    separatorWidth, separatorHeight);
420:                        } else {
421:                            int xOffset = (width - labelWidth - 2 * hGap) / 2;
422:                            int x = insets.left;
423:                            separator1.setBounds(x, y + vOffset, xOffset - 1,
424:                                    separatorHeight);
425:                            x += xOffset;
426:                            x += hGap;
427:                            label.setBounds(x, y, labelWidth, labelHeight);
428:                            x += labelWidth;
429:                            x += hGap;
430:                            Component separator2 = parent.getComponent(2);
431:                            int separatorWidth = size.width - insets.right - x;
432:                            separator2.setBounds(x, y + vOffset,
433:                                    separatorWidth, separatorHeight);
434:                        }
435:                    }
436:                }
437:
438:                private JLabel getLabel(Container parent) {
439:                    return (JLabel) parent.getComponent(0);
440:                }
441:
442:            }
443:
444:            // TODO: Move the code below this line to a new class
445:            // com.jgoodies.forms.util.Utilities
446:
447:            // Caching and Lazily Computing the Laf State *****************************
448:
449:            /**
450:             * Holds the cached result of the Aqua l&amp;f check. Is invalidated by the
451:             * <code>LookAndFeelChangeHandler</code> if the look&amp;feel changes.
452:             */
453:            private static Boolean cachedIsLafAqua;
454:
455:            /**
456:             * Describes whether the <code>LookAndFeelChangeHandler</code> has been
457:             * registered with the <code>UIManager</code> or not. It is registered
458:             * lazily when the first cached l&amp;f state is computed.
459:             */
460:            private static boolean changeHandlerRegistered = false;
461:
462:            private synchronized static void ensureLookAndFeelChangeHandlerRegistered() {
463:                if (!changeHandlerRegistered) {
464:                    UIManager
465:                            .addPropertyChangeListener(new LookAndFeelChangeHandler());
466:                    changeHandlerRegistered = true;
467:                }
468:            }
469:
470:            /**
471:             * Lazily checks and answers whether the Aqua look&amp;feel is active.
472:             * 
473:             * @return true if the current look&amp;feel is Aqua
474:             */
475:            private static boolean isLafAqua() {
476:                if (cachedIsLafAqua == null) {
477:                    cachedIsLafAqua = Boolean.valueOf(computeIsLafAqua());
478:                    ensureLookAndFeelChangeHandlerRegistered();
479:                }
480:                return cachedIsLafAqua.booleanValue();
481:            }
482:
483:            /**
484:             * Computes and answers whether the Aqua look&amp;feel is active.
485:             * 
486:             * @return true if the current look&amp;feel is Aqua
487:             */
488:            private static boolean computeIsLafAqua() {
489:                LookAndFeel laf = UIManager.getLookAndFeel();
490:                return laf.getName().startsWith("Mac OS X Aqua");
491:            }
492:
493:            // Listens to changes of the Look and Feel and invalidates the cache
494:            private static class LookAndFeelChangeHandler implements 
495:                    PropertyChangeListener {
496:
497:                /**
498:                 * Invalidates the cached laf states if the look&amp;feel changes.
499:                 * 
500:                 * @param evt
501:                 *            describes the property change
502:                 */
503:                public void propertyChange(PropertyChangeEvent evt) {
504:                    cachedIsLafAqua = null;
505:                }
506:            }
507:
508:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.