001    /*
002     * $Id: JXTitledSeparator.java,v 1.2 2006/05/14 15:55:55 dmouse Exp $
003     *
004     * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
005     * Santa Clara, California 95054, U.S.A. All rights reserved.
006     *
007     * This library is free software; you can redistribute it and/or
008     * modify it under the terms of the GNU Lesser General Public
009     * License as published by the Free Software Foundation; either
010     * version 2.1 of the License, or (at your option) any later version.
011     * 
012     * This library is distributed in the hope that it will be useful,
013     * but WITHOUT ANY WARRANTY; without even the implied warranty of
014     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015     * Lesser General Public License for more details.
016     * 
017     * You should have received a copy of the GNU Lesser General Public
018     * License along with this library; if not, write to the Free Software
019     * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
020     */
021    
022    package org.jdesktop.swingx;
023    
024    import java.awt.Color;
025    import java.awt.Dimension;
026    import java.awt.GridBagConstraints;
027    import java.awt.GridBagLayout;
028    import java.awt.Insets;
029    import javax.swing.Box;
030    import javax.swing.Icon;
031    import javax.swing.JLabel;
032    import javax.swing.JSeparator;
033    import javax.swing.SwingConstants;
034    import javax.swing.UIManager;
035    
036    /**
037     * <p>A simple horizontal separator that contains a title.<br/>
038     * <img src="http://www.jgui.com/SwingLabs/SwingX/JXTitledSeparator/JXTitledSeparator.png"/></p>
039     *
040     * <p>JXTitledSeparator allows you to specify the title via the #setTitle method.
041     * The title alignment may be specified by using the #setHorizontalAlignment
042     * method, and accepts all the same arguments as the JLabel#setHorizontalAlignment
043     * method.</p>
044     *
045     * <p>In addition, you may specify an Icon to use with this separator. The icon
046     * will appear "leading" the title (on the left in left-to-right languages,
047     * on the right in right-to-left languages). To change the position of the
048     * title with respect to the icon, call #setHorizontalTextPosition.</p>
049     *
050     * <p>The default font and color of the title comes from the LookAndFeel, mimicking
051     * the font and color of the TitledBorder</p>
052     *
053     * <p>Here are a few example code snippets:
054     * <pre><code>
055     *  //create a plain separator
056     *  JXTitledSeparator sep = new JXTitledSeparator();
057     *  sep.setText("Customer Info");
058     *
059     *  //create a separator with an icon
060     *  sep = new JXTitledSeparator();
061     *  sep.setText("Customer Info");
062     *  sep.setIcon(new ImageIcon("myimage.png"));
063     *
064     *  //create a separator with an icon to the right of the title,
065     *  //center justified
066     *  sep = new JXTitledSeparator();
067     *  sep.setText("Customer Info");
068     *  sep.setIcon(new ImageIcon("myimage.png"));
069     *  sep.setHorizontalAlignment(SwingConstants.CENTER);
070     *  sep.setHorizontalTextPosition(SwingConstants.TRAILING);
071     * </code></pre>
072     *
073     * @author rbair
074     */
075    public class JXTitledSeparator extends JXPanel {
076        /**
077         * Implementation detail: the label used to display the title
078         */
079        private JLabel label;
080        /**
081         * Implementation detail: a separator to use on the left of the
082         * title if alignment is centered or right justified
083         */
084        private JSeparator leftSeparator;
085        /**
086         * Implementation detail: a separator to use on the right of the
087         * title if alignment is centered or left justified
088         */
089        private JSeparator rightSeparator;
090        
091        /** 
092         * Creates a new instance of JXSeparator. The default title is simply
093         * and empty string. Default justification is LEADING, and the default
094         * horizontal text position is TRAILING (title follows icon)
095         */
096        public JXTitledSeparator() {
097            setLayout(new GridBagLayout());
098            
099            label = new JLabel("");
100            leftSeparator = new JSeparator();
101            rightSeparator = new JSeparator();
102            
103            layoutSeparator();
104            
105            Dimension prefSize = getPreferredSize();
106            prefSize.width = Math.max(prefSize.width, 50);
107            setPreferredSize(prefSize);
108            
109            label.setForeground(UIManager.getColor("TitledBorder.titleColor"));
110            label.setFont(UIManager.getFont("TitledBorder.font"));
111        }
112        
113        /**
114         * Implementation detail. lays out this component, showing/hiding components
115         * as necessary. Actually changes the containment (removes and adds components).
116         * JXTitledSeparator is treated as a single component rather than a container.
117         */
118        private void layoutSeparator() {
119            removeAll();
120            
121            switch (label.getHorizontalAlignment()) {
122                case SwingConstants.LEFT:
123                case SwingConstants.LEADING:
124                case SwingConstants.WEST:
125                    add(label, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(0,0,0,0), 0, 0));
126                    add(Box.createHorizontalStrut(3), new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(0,0,0,0), 0, 0));
127                    add(rightSeparator, new GridBagConstraints(2, 0, 1, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(0,0,0,0), 0, 0));
128                    break;
129                case SwingConstants.RIGHT:
130                case SwingConstants.TRAILING:
131                case SwingConstants.EAST:
132                    add(rightSeparator, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(0,0,0,0), 0, 0));
133                    add(Box.createHorizontalStrut(3), new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(0,0,0,0), 0, 0));
134                    add(label, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(0,0,0,0), 0, 0));
135                    break;
136                case SwingConstants.CENTER:
137                default:
138                    add(leftSeparator, new GridBagConstraints(0, 0, 1, 1, 0.5, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(0,0,0,0), 0, 0));
139                    add(Box.createHorizontalStrut(3), new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(0,0,0,0), 0, 0));
140                    add(label, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0,0,0,0), 0, 0));
141                    add(Box.createHorizontalStrut(3), new GridBagConstraints(3, 0, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(0,0,0,0), 0, 0));
142                    add(rightSeparator, new GridBagConstraints(4, 0, 1, 1, 0.5, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(0,0,0,0), 0, 0));
143            }
144        }
145        
146        /**
147         * Sets the title for the separator. This may be simple html, or plain
148         * text.
149         *
150         * @param title the new title. Any string input is acceptable
151         */
152        public void setTitle(String title) {
153            String old = getTitle();
154            label.setText(title);
155            firePropertyChange("title", old, getTitle());
156        }
157        
158        /**
159         * @return the title being used for this JXTitledSeparator. This will be
160         *         the raw title text, and so may include html tags etc if they
161         *         were so specified in #setTitle.
162         */
163        public String getTitle() {
164            return label.getText();
165        }
166        
167        /**
168         * Sets the alignment of the title along the X axis. If left/leading, then
169         * the title will lead the separator (in left-to-right languages,
170         * the title will be to the left and the separator to the right). If centered,
171         * then a separator will be to the left, followed by the titled (centered),
172         * followed by a separator to the right. Right/trailing will have the title
173         * on the right with a separator to its left.
174         *
175         * @param alignment  One of the following constants
176         *           defined in <code>SwingConstants</code>:
177         *           <code>LEFT</code>,
178         *           <code>CENTER</code>,
179         *           <code>RIGHT</code>,
180         *           <code>LEADING</code> (the default) or
181         *           <code>TRAILING</code>.
182         *
183         * @see SwingConstants
184         * @see #getHorizontalAlignment
185         */
186        public void setHorizontalAlignment(int alignment) {
187            int old = getHorizontalAlignment();
188            label.setHorizontalAlignment(alignment);
189            if (old != getHorizontalAlignment()) {
190                layoutSeparator();
191            }
192            firePropertyChange("horizontalAlignment", old, getHorizontalAlignment());
193        }
194        
195        /**
196         * Returns the alignment of the title contents along the X axis.
197         *
198         * @return   The value of the horizontalAlignment property, one of the 
199         *           following constants defined in <code>SwingConstants</code>:
200         *           <code>LEFT</code>,
201         *           <code>CENTER</code>, 
202         *           <code>RIGHT</code>,
203         *           <code>LEADING</code> or
204         *           <code>TRAILING</code>.
205         *
206         * @see #setHorizontalAlignment
207         * @see SwingConstants
208         */
209        public int getHorizontalAlignment() {
210            return label.getHorizontalAlignment();
211        }
212    
213        /**
214         * Sets the horizontal position of the title's text,
215         * relative to the icon.
216         *
217         * @param position  One of the following constants
218         *           defined in <code>SwingConstants</code>:
219         *           <code>LEFT</code>,
220         *           <code>CENTER</code>,
221         *           <code>RIGHT</code>,
222         *           <code>LEADING</code>, or
223         *           <code>TRAILING</code> (the default).
224         * @exception IllegalArgumentException
225         */
226        public void setHorizontalTextPosition(int position) {
227            int old = getHorizontalTextPosition();
228            label.setHorizontalTextPosition(position);
229            firePropertyChange("horizontalTextPosition", old, getHorizontalTextPosition());
230        }
231        
232        /**
233         * Returns the horizontal position of the title's text,
234         * relative to the icon.
235         *
236         * @return   One of the following constants
237         *           defined in <code>SwingConstants</code>:
238         *           <code>LEFT</code>,
239         *           <code>CENTER</code>, 
240         *           <code>RIGHT</code>,
241         *           <code>LEADING</code> or
242         *           <code>TRAILING</code>.
243         *
244         * @see SwingConstants
245         */
246        public int getHorizontalTextPosition() {
247            return label.getHorizontalTextPosition();
248        }
249        
250        /**
251         * Defines the icon this component will display.  If
252         * the value of icon is null, nothing is displayed.
253         * <p>
254         * The default value of this property is null.
255         * 
256         * @see #setHorizontalTextPosition
257         * @see #getIcon
258         */
259        public void setIcon(Icon icon) {
260            Icon old = getIcon();
261            label.setIcon(icon);
262            firePropertyChange("icon", old, getIcon());
263        }
264        
265        /**
266         * Returns the graphic image (glyph, icon) that the JXTitledSeparator displays.
267         *
268         * @return an Icon
269         * @see #setIcon
270         */
271        public Icon getIcon() {
272            return label.getIcon();
273        }
274    
275        /**
276         * @inheritDoc
277         * Passes the foreground on to the label
278         */
279        @Override
280        public void setForeground(Color foreground) {
281            if (label != null) {
282                label.setForeground(foreground);
283            }
284            super.setForeground(foreground);
285        }
286    }