001/* 002 * $Id: JXTitledSeparator.java 4147 2012-02-01 17:13:24Z kschaefe $ 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 022package org.jdesktop.swingx; 023 024import java.awt.Color; 025import java.awt.ComponentOrientation; 026import java.awt.Font; 027import java.awt.GridBagConstraints; 028import java.awt.GridBagLayout; 029import java.awt.Insets; 030 031import javax.swing.Box; 032import javax.swing.Icon; 033import javax.swing.JLabel; 034import javax.swing.JSeparator; 035import javax.swing.SwingConstants; 036import javax.swing.UIManager; 037import javax.swing.plaf.ColorUIResource; 038import javax.swing.plaf.FontUIResource; 039 040import org.jdesktop.beans.JavaBean; 041 042/** 043 * <p>A simple horizontal separator that contains a title.<br/> 044 * 045 * <p>JXTitledSeparator allows you to specify the title via the {@link #setTitle} method. 046 * The title alignment may be specified by using the {@link #setHorizontalAlignment} 047 * method, and accepts all the same arguments as the {@link javax.swing.JLabel#setHorizontalAlignment} 048 * method.</p> 049 * 050 * <p>In addition, you may specify an Icon to use with this separator. The icon 051 * will appear "leading" the title (on the left in left-to-right languages, 052 * on the right in right-to-left languages). To change the position of the 053 * title with respect to the icon, call {@link #setHorizontalTextPosition}.</p> 054 * 055 * <p>The default font and color of the title comes from the <code>LookAndFeel</code>, mimicking 056 * the font and color of the {@link javax.swing.border.TitledBorder}</p> 057 * 058 * <p>Here are a few example code snippets: 059 * <pre><code> 060 * //create a plain separator 061 * JXTitledSeparator sep = new JXTitledSeparator(); 062 * sep.setTitle("Customer Info"); 063 * 064 * //create a separator with an icon 065 * sep = new JXTitledSeparator(); 066 * sep.setTitle("Customer Info"); 067 * sep.setIcon(new ImageIcon("myimage.png")); 068 * 069 * //create a separator with an icon to the right of the title, 070 * //center justified 071 * sep = new JXTitledSeparator(); 072 * sep.setTitle("Customer Info"); 073 * sep.setIcon(new ImageIcon("myimage.png")); 074 * sep.setHorizontalAlignment(SwingConstants.CENTER); 075 * sep.setHorizontalTextPosition(SwingConstants.TRAILING); 076 * </code></pre> 077 * 078 * @status REVIEWED 079 * @author rbair 080 */ 081@JavaBean 082public class JXTitledSeparator extends JXPanel { 083 /** 084 * Implementation detail: the label used to display the title 085 */ 086 private JLabel label; 087 /** 088 * Implementation detail: a separator to use on the left of the 089 * title if alignment is centered or right justified 090 */ 091 private JSeparator leftSeparator; 092 /** 093 * Implementation detail: a separator to use on the right of the 094 * title if alignment is centered or left justified 095 */ 096 private JSeparator rightSeparator; 097 098 /** 099 * Creates a new instance of <code>JXTitledSeparator</code>. The default title is simply 100 * an empty string. Default justification is <code>LEADING</code>, and the default 101 * horizontal text position is <code>TRAILING</code> (title follows icon) 102 */ 103 public JXTitledSeparator() { 104 this("Untitled"); 105 } 106 107 /** 108 * Creates a new instance of <code>JXTitledSeparator</code> with the specified 109 * title. Default horizontal alignment is <code>LEADING</code>, and the default 110 * horizontal text position is <code>TRAILING</code> (title follows icon) 111 */ 112 public JXTitledSeparator(String title) { 113 this(title, SwingConstants.LEADING, null); 114 } 115 116 /** 117 * Creates a new instance of <code>JXTitledSeparator</code> with the specified 118 * title and horizontal alignment. The default 119 * horizontal text position is <code>TRAILING</code> (title follows icon) 120 */ 121 public JXTitledSeparator(String title, int horizontalAlignment) { 122 this(title, horizontalAlignment, null); 123 } 124 125 /** 126 * Creates a new instance of <code>JXTitledSeparator</code> with the specified 127 * title, icon, and horizontal alignment. The default 128 * horizontal text position is <code>TRAILING</code> (title follows icon) 129 */ 130 public JXTitledSeparator(String title, int horizontalAlignment, Icon icon) { 131 setLayout(new GridBagLayout()); 132 133 label = new JLabel(title) { 134 @Override 135 public void updateUI(){ 136 super.updateUI(); 137 updateTitle(); 138 } 139 }; 140 label.setIcon(icon); 141 label.setHorizontalAlignment(horizontalAlignment); 142 leftSeparator = new JSeparator(); 143 rightSeparator = new JSeparator(); 144 145 layoutSeparator(); 146 147 updateTitle(); 148 setOpaque(false); 149 } 150 151 /** 152 * Implementation detail. Handles updates of title color and font on LAF change. For more 153 * details see swingx#451. 154 */ 155 //TODO remove this method in favor of UI delegate -- kgs 156 protected void updateTitle() 157 { 158 if (label == null) return; 159 160 Color c = label.getForeground(); 161 if (c == null || c instanceof ColorUIResource) 162 setForeground(UIManager.getColor("TitledBorder.titleColor")); 163 164 Font f = label.getFont(); 165 if (f == null || f instanceof FontUIResource) 166 setFont(UIManager.getFont("TitledBorder.font")); 167 } 168 169 /** 170 * Implementation detail. lays out this component, showing/hiding components 171 * as necessary. Actually changes the containment (removes and adds components). 172 * <code>JXTitledSeparator</code> is treated as a single component rather than 173 * a container. 174 */ 175 private void layoutSeparator() { 176 removeAll(); 177 178 //SwingX #304 fix alignment issues 179 //this is really a hacky fix, but a fix nonetheless 180 //we need a better layout approach for this class 181 int alignment = getHorizontalAlignment(); 182 183 if (!getComponentOrientation().isLeftToRight()) { 184 switch (alignment) { 185 case SwingConstants.LEFT: 186 alignment = SwingConstants.RIGHT; 187 break; 188 case SwingConstants.RIGHT: 189 alignment = SwingConstants.LEFT; 190 break; 191 case SwingConstants.EAST: 192 alignment = SwingConstants.WEST; 193 break; 194 case SwingConstants.WEST: 195 alignment = SwingConstants.EAST; 196 break; 197 default: 198 break; 199 } 200 } 201 202 switch (alignment) { 203 case SwingConstants.LEFT: 204 case SwingConstants.LEADING: 205 case SwingConstants.WEST: 206 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)); 207 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)); 208 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)); 209 break; 210 case SwingConstants.RIGHT: 211 case SwingConstants.TRAILING: 212 case SwingConstants.EAST: 213 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)); 214 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)); 215 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)); 216 break; 217 case SwingConstants.CENTER: 218 default: 219 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)); 220 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)); 221 add(label, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0,0,0,0), 0, 0)); 222 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)); 223 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)); 224 } 225 } 226 227 /** 228 * Sets the title for the separator. This may be simple html, or plain 229 * text. 230 * 231 * @param title the new title. Any string input is acceptable 232 */ 233 public void setTitle(String title) { 234 String old = getTitle(); 235 label.setText(title); 236 firePropertyChange("title", old, getTitle()); 237 } 238 239 /** 240 * Gets the title. 241 * 242 * @return the title being used for this <code>JXTitledSeparator</code>. 243 * This will be the raw title text, and so may include html tags etc 244 * if they were so specified in #setTitle. 245 */ 246 public String getTitle() { 247 return label.getText(); 248 } 249 250 /** 251 * <p>Sets the alignment of the title along the X axis. If leading, then 252 * the title will lead the separator (in left-to-right languages, 253 * the title will be to the left and the separator to the right). If centered, 254 * then a separator will be to the left, followed by the title (centered), 255 * followed by a separator to the right. Trailing will have the title 256 * on the right with a separator to its left, in left-to-right languages.</p> 257 * 258 * <p>LEFT and RIGHT always position the text left or right of the separator, 259 * respectively, regardless of the language orientation.</p> 260 * 261 * @param alignment One of the following constants 262 * defined in <code>SwingConstants</code>: 263 * <code>LEFT</code>, 264 * <code>CENTER</code>, 265 * <code>RIGHT</code>, 266 * <code>LEADING</code> (the default) or 267 * <code>TRAILING</code>. 268 * 269 * @throws IllegalArgumentException if the alignment does not match one of 270 * the accepted inputs. 271 * @see SwingConstants 272 * @see #getHorizontalAlignment 273 */ 274 public void setHorizontalAlignment(int alignment) { 275 int old = getHorizontalAlignment(); 276 label.setHorizontalAlignment(alignment); 277 if (old != getHorizontalAlignment()) { 278 layoutSeparator(); 279 } 280 firePropertyChange("horizontalAlignment", old, getHorizontalAlignment()); 281 } 282 283 /** 284 * Returns the alignment of the title contents along the X axis. 285 * 286 * @return The value of the horizontalAlignment property, one of the 287 * following constants defined in <code>SwingConstants</code>: 288 * <code>LEFT</code>, 289 * <code>CENTER</code>, 290 * <code>RIGHT</code>, 291 * <code>LEADING</code> or 292 * <code>TRAILING</code>. 293 * 294 * @see #setHorizontalAlignment 295 * @see SwingConstants 296 */ 297 public int getHorizontalAlignment() { 298 return label.getHorizontalAlignment(); 299 } 300 301 /** 302 * Sets the horizontal position of the title's text, 303 * relative to the icon. 304 * 305 * @param position One of the following constants 306 * defined in <code>SwingConstants</code>: 307 * <code>LEFT</code>, 308 * <code>CENTER</code>, 309 * <code>RIGHT</code>, 310 * <code>LEADING</code>, or 311 * <code>TRAILING</code> (the default). 312 * @throws IllegalArgumentException if the position does not match one of 313 * the accepted inputs. 314 */ 315 public void setHorizontalTextPosition(int position) { 316 int old = getHorizontalTextPosition(); 317 label.setHorizontalTextPosition(position); 318 firePropertyChange("horizontalTextPosition", old, getHorizontalTextPosition()); 319 } 320 321 /** 322 * Returns the horizontal position of the title's text, 323 * relative to the icon. 324 * 325 * @return One of the following constants 326 * defined in <code>SwingConstants</code>: 327 * <code>LEFT</code>, 328 * <code>CENTER</code>, 329 * <code>RIGHT</code>, 330 * <code>LEADING</code> or 331 * <code>TRAILING</code>. 332 * 333 * @see SwingConstants 334 */ 335 public int getHorizontalTextPosition() { 336 return label.getHorizontalTextPosition(); 337 } 338 339 /** 340 * {@inheritDoc} 341 */ 342 @Override 343 public ComponentOrientation getComponentOrientation() { 344 return label.getComponentOrientation(); 345 } 346 347 /** 348 * {@inheritDoc} 349 */ 350 @Override 351 public void setComponentOrientation(ComponentOrientation o) { 352 ComponentOrientation old = label.getComponentOrientation(); 353 label.setComponentOrientation(o); 354 firePropertyChange("componentOrientation", old, label.getComponentOrientation()); 355 } 356 357 /** 358 * Defines the icon this component will display. If 359 * the value of icon is null, nothing is displayed. 360 * <p> 361 * The default value of this property is null. 362 * 363 * @see #setHorizontalTextPosition 364 * @see #getIcon 365 */ 366 public void setIcon(Icon icon) { 367 Icon old = getIcon(); 368 label.setIcon(icon); 369 firePropertyChange("icon", old, getIcon()); 370 } 371 372 /** 373 * Returns the graphic image (glyph, icon) that the 374 * <code>JXTitledSeparator</code> displays. 375 * 376 * @return an Icon 377 * @see #setIcon 378 */ 379 public Icon getIcon() { 380 return label.getIcon(); 381 } 382 383 /** 384 * {@inheritDoc} 385 */ 386 @Override 387 public void setForeground(Color foreground) { 388 if (label != null) { 389 label.setForeground(foreground); 390 } 391 super.setForeground(foreground); 392 } 393 394 /** 395 * {@inheritDoc} 396 */ 397 @Override 398 public void setFont(Font font) { 399 if (label != null) { 400 label.setFont(font); 401 } 402 super.setFont(font); 403 } 404}