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.forms.components.separator;
031:
032: import java.awt.Color;
033: import java.awt.Component;
034: import java.awt.Container;
035: import java.awt.Dimension;
036: import java.awt.Font;
037: import java.awt.Insets;
038:
039: import javax.swing.JLabel;
040: import javax.swing.JPanel;
041: import javax.swing.JSeparator;
042: import javax.swing.SwingConstants;
043: import javax.swing.UIManager;
044:
045: import com.jgoodies.forms.layout.Sizes;
046:
047: /**
048: * <code>TitledSeparator</code> is a component that can be used as a
049: * replacement for a titled border. It is composed of a JLabel with a horizontal
050: * line (JSeparator) either to the left or right of the label. It is useful when
051: * nested panels are not appropriate but a visual separator is required between
052: * different parts of a GUI. It is derived from the JGoodies separator
053: * component.
054: *
055: * @see com.jgoodies.forms.factories.DefaultComponentFactory#createSeparator(String)
056: *
057: * @author Jeff Tassin
058: */
059: public class TitledSeparator extends JPanel {
060: /**
061: * The font for the title text.
062: */
063: private Font m_title_font;
064:
065: /**
066: * The color of the title text.
067: */
068: private Color m_title_color;
069:
070: /**
071: * The underlying JLabel component.
072: */
073: private JLabel m_label;
074:
075: /**
076: * Creates a default TitledSeparator instance
077: */
078: public TitledSeparator() {
079: this ("Title", SwingConstants.LEFT);
080: }
081:
082: /**
083: * Creates and returns a labeled separator with the label in the left-hand
084: * side. Useful to separate paragraphs in a panel; often a better choice
085: * than a <code>TitledBorder</code>.
086: *
087: * @param text
088: * the title's text
089: * @return a title label with separator on the right side
090: */
091: public TitledSeparator(String text) {
092: this (text, SwingConstants.LEFT);
093: }
094:
095: /**
096: * Creates and returns a labeled separator. Useful to separate paragraphs in
097: * a panel, which is often a better choice than a <code>TitledBorder</code>.
098: *
099: * @param text
100: * the title's text
101: * @param alignment
102: * text alignment: left, center, right
103: * @return a separator with title label
104: */
105: public TitledSeparator(String text, int alignment) {
106: setLayout(new TitledSeparatorLayout());
107:
108: if (text == null)
109: m_label = new TitleLabel();
110: else
111: m_label = new TitleLabel(text);
112:
113: m_label.setForeground(UIManager
114: .getColor("TitledBorder.titleColor"));
115: m_label.setFont(UIManager.getFont("TitledBorder.font"));
116: m_label.setVerticalAlignment(SwingConstants.CENTER);
117: m_label.setHorizontalAlignment(alignment);
118:
119: createSeparator(m_label);
120: }
121:
122: /**
123: * Creates and returns a labeled separator. Useful to separate paragraphs in
124: * a panel, which is often a better choice than a <code>TitledBorder</code>.
125: * <p>
126: *
127: * The label's position is determined by the label's horizontal alignment.
128: *
129: * @param label
130: * the title label component
131: * @return a separator with title label
132: * @throws NullPointerException
133: * if the label is <code>null</code>
134: */
135: private void createSeparator(JLabel label) {
136: removeAll();
137: setOpaque(false);
138:
139: add(label);
140: add(new JSeparator());
141:
142: if (label != null
143: && label.getHorizontalAlignment() == SwingConstants.CENTER) {
144: add(new JSeparator());
145: }
146: }
147:
148: /**
149: * Returns the alignment of the separator line relative to the label.
150: *
151: * @return the separator alignment. SwingConstants.LEFT, CENTER, or RIGHT
152: */
153: public int getAlignment() {
154: return m_label.getHorizontalAlignment();
155: }
156:
157: /**
158: * Returns the color of the title text
159: *
160: * @return the color used for title text
161: */
162: public Color getTitleColor() {
163: return m_title_color == null ? UIManager
164: .getColor("TitledBorder.titleColor") : m_title_color;
165: }
166:
167: /**
168: * Returns the font of the title text.
169: *
170: * @return the font used for title text.
171: */
172: public Font getTitleFont() {
173: return m_title_font == null ? UIManager
174: .getFont("TitledBorder.font") : m_title_font;
175: }
176:
177: /**
178: * Returns the title text.
179: *
180: * @return the title text.
181: */
182: public String getText() {
183: return m_label.getText();
184: }
185:
186: /**
187: * Sets the alignment of the separator line relative to the label.
188: *
189: * @param alignment
190: * the alignment to set. SwingConstants.LEFT, CENTER, or RIGHT
191: */
192: public void setAlignment(int alignment) {
193: if (m_label.getHorizontalAlignment() == alignment)
194: return;
195:
196: m_label.setHorizontalAlignment(alignment);
197: createSeparator(m_label);
198: }
199:
200: /**
201: * Sets the color of the title text
202: *
203: * @param c
204: * the color used for title text
205: */
206: public void setTitleColor(Color c) {
207: m_title_color = c;
208: if (m_label != null)
209: m_label.setForeground(c);
210: }
211:
212: /**
213: * Sets the font of the title text.
214: *
215: * @param font
216: * the font used for title text.
217: */
218: public void setTitleFont(Font font) {
219: m_title_font = font;
220: if (m_label != null)
221: m_label.setFont(font);
222: }
223:
224: /**
225: * Sets the title text.
226: *
227: * @param title
228: * the title text to set.
229: */
230: public void setText(String title) {
231: m_label.setText(title);
232: }
233:
234: // A label that uses the TitleBorder font and color
235: private class TitleLabel extends JLabel {
236: private TitleLabel() {
237: // Just invoke the super constructor.
238: }
239:
240: private TitleLabel(String text) {
241: super (text);
242: }
243:
244: /**
245: * Override so we can update the title text and color based on the
246: * current look and feel (if needed)
247: */
248: public void updateUI() {
249: super .updateUI();
250: if (m_label != null) {
251: m_label.setForeground(getTitleColor());
252: m_label.setFont(getTitleFont());
253: }
254: }
255: }
256:
257: // A layout for the title label and separator(s) in titled separators.
258: private class TitledSeparatorLayout implements
259: java.awt.LayoutManager {
260: /**
261: * Constructs a TitledSeparatorLayout that centers the separators
262: *
263: */
264: private TitledSeparatorLayout() {
265:
266: }
267:
268: /**
269: * Does nothing. This layout manager looks up the components from the
270: * layout container and used the component's index in the child array to
271: * identify the label and separators.
272: *
273: * @param name
274: * the string to be associated with the component
275: * @param comp
276: * the component to be added
277: */
278: public void addLayoutComponent(String name, Component comp) {
279: // Does nothing.
280: }
281:
282: /**
283: * Does nothing. This layout manager looks up the components from the
284: * layout container and used the component's index in the child array to
285: * identify the label and separators.
286: *
287: * @param comp
288: * the component to be removed
289: */
290: public void removeLayoutComponent(Component comp) {
291: // Does nothing.
292: }
293:
294: /**
295: * Computes and returns the minimum size dimensions for the specified
296: * container. Forwards this request to <code>#preferredLayoutSize</code>.
297: *
298: * @param parent
299: * the component to be laid out
300: * @return the container's minimum size.
301: * @see #preferredLayoutSize(Container)
302: */
303: public Dimension minimumLayoutSize(Container parent) {
304: return preferredLayoutSize(parent);
305: }
306:
307: /**
308: * Computes and returns the preferred size dimensions for the specified
309: * container. Returns the title label's preferred size.
310: *
311: * @param parent
312: * the component to be laid out
313: * @return the container's preferred size.
314: * @see #minimumLayoutSize(Container)
315: */
316: public Dimension preferredLayoutSize(Container parent) {
317: Component label = getLabel(parent);
318: Dimension labelSize = label.getPreferredSize();
319: Insets insets = parent.getInsets();
320: int width = Math.max(1, labelSize.width + insets.left
321: + insets.right);
322: int height = Math.max(1, labelSize.height + insets.top
323: + insets.bottom);
324: return new Dimension(width, height);
325: }
326:
327: /**
328: * Lays out the specified container.
329: *
330: * @param parent
331: * the container to be laid out
332: */
333: public void layoutContainer(Container parent) {
334: synchronized (parent.getTreeLock()) {
335: // Look up the parent size and insets
336: Dimension size = parent.getSize();
337: Insets insets = parent.getInsets();
338: int width = size.width - insets.left - insets.right;
339:
340: // Look up components and their sizes
341: JLabel label = getLabel(parent);
342: Dimension labelSize = label.getPreferredSize();
343: int labelWidth = labelSize.width;
344: int labelHeight = labelSize.height;
345:
346: Component separator1 = parent.getComponent(1);
347: int separatorHeight = separator1.getPreferredSize().height;
348:
349: java.awt.FontMetrics metrics = label
350: .getFontMetrics(label.getFont());
351: int ascent = metrics.getMaxAscent();
352: int hGapDlu = 3;
353: int hGap = Sizes.dialogUnitXAsPixel(hGapDlu, label);
354: int vOffset = 1 + (labelHeight - separatorHeight) / 2;
355:
356: int alignment = label.getHorizontalAlignment();
357: int y = insets.top;
358: if (alignment == JLabel.LEFT) {
359: int x = insets.left;
360: label.setBounds(x, y, labelWidth, labelHeight);
361: x += labelWidth;
362: x += hGap;
363: int separatorWidth = size.width - insets.right - x;
364: separator1.setBounds(x, y + vOffset,
365: separatorWidth, separatorHeight);
366: } else if (alignment == JLabel.RIGHT) {
367: int x = insets.left + width - labelWidth;
368: label.setBounds(x, y, labelWidth, labelHeight);
369: x -= hGap;
370: x--;
371: int separatorWidth = x - insets.left;
372: separator1.setBounds(insets.left, y + vOffset,
373: separatorWidth, separatorHeight);
374: } else {
375: int xOffset = (width - labelWidth - 2 * hGap) / 2;
376: int x = insets.left;
377: separator1.setBounds(x, y + vOffset, xOffset - 1,
378: separatorHeight);
379: x += xOffset;
380: x += hGap;
381: label.setBounds(x, y, labelWidth, labelHeight);
382: x += labelWidth;
383: x += hGap;
384: Component separator2 = parent.getComponent(2);
385: int separatorWidth = size.width - insets.right - x;
386: separator2.setBounds(x, y + vOffset,
387: separatorWidth, separatorHeight);
388: }
389: }
390: }
391:
392: private JLabel getLabel(Container parent) {
393: return m_label;
394: }
395:
396: }
397: }
|