package bibliothek.gui.dock.util.swing; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import javax.swing.Icon; import javax.swing.border.EmptyBorder; import bibliothek.gui.dock.util.ConfiguredBackgroundPanel; import bibliothek.gui.dock.util.DockUtilities; import bibliothek.gui.dock.util.Transparency; import bibliothek.gui.dock.util.font.FontModifier; /** * A label which draws some text, and can change the layout of the text * between horizontal and vertical. * @author Benjamin Sigg */ public class OrientedLabel extends ConfiguredBackgroundPanel{ /** The label which really paints the text */ private DLabel label = new DLabel(); /** the original font of {@link #label} */ private Font originalFont; /** icon painted on this label */ private Icon icon; /** icon painted when this label is disabled */ private Icon disabledIcon; /** distance between icon and border */ private int iconOffset = 2; /** distance between icon and text */ private int iconTextDistance = 2; /** whether the {@link #originalFont} has been set */ private boolean originalFontSet = false; /** The text on the label */ private String text; /** the current angle of this label */ private Rotation rotation = Rotation.DEGREE_0; /** if <code>true</code>, then the {@link #icon} is not painted */ private boolean hideIcon = false; /** * Creates a new label with no text */ public OrientedLabel(){ super( Transparency.DEFAULT ); label.setOpaque( false ); label.setAlignmentX( 0 ); label.setBorder( new EmptyBorder( 0, 5, 0, 0 ) ); } /** * Sets the icon which will be painted on the left or on the top side. * @param icon the icon, can be <code>null</code> */ public void setIcon( Icon icon ){ this.icon = icon; disabledIcon = null; revalidate(); repaint(); } /** * Gets the icon of this label * @return the icon, can be <code>null</code> */ public Icon getIcon(){ return icon; } /** * Sets the distance between icon and the three adjacent borders. * @param iconOffset the distance */ public void setIconOffset( int iconOffset ){ this.iconOffset = iconOffset; revalidate(); repaint(); } /** * Gets the distance between icon and the tree adjacent borders. * @return the distance */ public int getIconOffset(){ return iconOffset; } /** * Sets the distance between icon and text. * @param iconTextDistance the gap */ public void setIconTextDistance( int iconTextDistance ){ this.iconTextDistance = iconTextDistance; revalidate(); repaint(); } /** * Gets the distance between icon and text. * @return the gap */ public int getIconTextDistance(){ return iconTextDistance; } /** * Sets the orientation of this label. * @param rotation the orientation, not <code>null</code> */ public void setRotation( Rotation rotation ){ if( rotation == null ){ throw new IllegalArgumentException( "rotation must not be null" ); } this.rotation = rotation; revalidate(); } /** * Sets the orientation. If <code>horizontal</code>, then the rotation is set * to 0 degrees, otherwise the rotation is set to 90 degrees. * @param horizontal whether the label is painted horizontal */ public void setHorizontal( boolean horizontal ){ if( horizontal ){ setRotation( Rotation.DEGREE_0 ); } else{ setRotation( Rotation.DEGREE_90 ); } } /** * Tells whether the content of this label is painted horizontally. * @return whether the label is horizontal */ public boolean isHorizontal(){ return rotation == Rotation.DEGREE_0 || rotation == Rotation.DEGREE_180; } /** * Tells whether the content of this label is painted vertically. * @return whether the label is vertical */ public boolean isVertical(){ return !isHorizontal(); } /** * Sets the text of this label * @param text the text, <code>null</code> is allowed */ public void setText( String text ){ this.text = text; label.setText( (text == null || text.length() == 0) ? null : text ); revalidate(); repaint(); } /** * Gets the text of this label * @return the text, may be <code>null</code> */ public String getText(){ return text; } @Override public void setEnabled( boolean enabled ){ super.setEnabled( enabled ); if( label != null ){ label.setEnabled( enabled ); } } @Override public void setForeground( Color fg ) { super.setForeground(fg); if( label != null ) label.setForeground( fg ); } @Override public Color getForeground(){ if( label == null ){ return null; } return label.getForeground(); } @Override public void setBackground( Color bg ) { super.setBackground(bg); if( label != null ) label.setBackground( bg ); } @Override public Color getBackground(){ if( label == null ){ return null; } return label.getBackground(); } /** * Tells whether the icon is not painted. * @return whether the icon is hidden * @see #setIconHidden(boolean) */ public boolean isIconHidden(){ return hideIcon; } /** * Tells whether the {@link #setIcon(Icon) icon} is hidden. If the icon is hidden, it is not painted * and does not take any space. It is however treated normally when serving calls to {@link #getPreferredSize()}. * @param hideIcon whether to hide the icon */ public void setIconHidden( boolean hideIcon ){ if( this.hideIcon != hideIcon ){ this.hideIcon = hideIcon; repaint(); } } @Override public void updateUI() { super.updateUI(); if( label != null ){ originalFontSet = false; originalFont = null; label.setFont( null ); label.updateUI(); updateFonts(); } } /** * Called by {@link #updateUI()} if the fonts need to be * updated, the default implementation does nothing */ protected void updateFonts(){ // nothing } @Override public void setFont( Font font ) { super.setFont( font ); if( label != null ){ if( !originalFontSet ){ originalFontSet = true; originalFont = label.getFont(); } if( font != null ){ label.setFont( font ); } else{ label.setFont( originalFont ); originalFont = null; originalFontSet = false; } revalidate(); repaint(); } } /** * Sets the modifier for the current font. * @param modifier the modifier * @see DLabel#setFontModifier(FontModifier) */ public void setFontModifier( FontModifier modifier ) { label.setFontModifier( modifier ); revalidate(); repaint(); } /** * Gets the font modifier of this label. * @return the modifier */ public FontModifier getFontModifier(){ return label.getFontModifier(); } /** * Gets direct access to the label that is used by this {@link OrientedLabel} to paint its content. This method * should be treated with care, modifications to the underlying label may have unexpected side effects. * @return the label that paints the content */ public DLabel getLabel(){ return label; } @Override public Dimension getMinimumSize() { return getPreferredSize(); } @Override public Dimension getPreferredSize() { Dimension size = label.getPreferredSize(); String text = getText(); if( (text == null || text.length() == 0) && icon != null ){ return new Dimension( icon.getIconWidth() + 2*iconOffset, icon.getIconHeight()+2*iconOffset ); } if( isHorizontal() ){ if( icon == null ) return new Dimension( size.width+5, size.height ); return new Dimension( size.width+5+iconOffset+iconTextDistance+icon.getIconWidth(), Math.max( size.height, icon.getIconHeight()+2*iconOffset )); } else{ if( icon == null ) return new Dimension( size.height, size.width+5 ); return new Dimension( Math.max( size.height, icon.getIconWidth()+2*iconOffset ), size.width+5+iconOffset+iconTextDistance+icon.getIconHeight() ); } } @Override public void paint( Graphics g ){ paintComponent( g ); } @Override public void paintForeground( Graphics g ){ if( rotation == Rotation.DEGREE_0 ){ if( icon == null || isIconHidden() ){ label.paint( g ); } else{ Icon icon = this.icon; if( !isEnabled() ){ if( disabledIcon == null ){ disabledIcon = DockUtilities.disabledIcon( this, icon ); } icon = disabledIcon; } int width = getWidth(); int height = getHeight(); int iconWidth = icon.getIconWidth(); int iconHeight = icon.getIconHeight(); icon.paintIcon( this, g, iconOffset, (height-iconHeight)/2 ); int usedUp = iconWidth + iconOffset + iconTextDistance; if( usedUp < width ){ g = g.create( usedUp, 0, width-usedUp, height ); label.paint( g ); g.dispose(); } } } else if( rotation == Rotation.DEGREE_90 ){ double angle = Math.PI/2.0; if( icon == null || isIconHidden() ){ Graphics2D g2 = (Graphics2D)g.create(); g2.rotate( angle, 0, 0 ); g2.translate( 0, -getWidth() ); label.paint( g2 ); g2.dispose(); } else { int width = getWidth(); int height = getHeight(); int iconWidth = icon.getIconWidth(); int iconHeight = icon.getIconHeight(); icon.paintIcon( this, g, (width-iconWidth)/2, iconOffset ); int usedUp = iconHeight + iconOffset + iconTextDistance; if( usedUp < height ){ Graphics2D g2 = (Graphics2D)g.create( 0, usedUp, width, height-usedUp ); g2.rotate( angle, 0, 0 ); g2.translate( 0, -getWidth() ); label.paint( g2 ); g2.dispose(); } } } else if( rotation == Rotation.DEGREE_180 ){ double angle = Math.PI; if( icon == null || isIconHidden() ){ Graphics2D g2 = (Graphics2D)g.create(); g2.rotate( angle, 0, 0 ); g2.translate( -getWidth(), -getHeight() ); label.paint( g2 ); g2.dispose(); } else{ int width = getWidth(); int height = getHeight(); int iconWidth = icon.getIconWidth(); int iconHeight = icon.getIconHeight(); icon.paintIcon( this, g, iconOffset, (height-iconHeight)/2 ); int usedUp = iconWidth + iconOffset + iconTextDistance; if( usedUp < width ){ Graphics2D g2 = (Graphics2D)g.create( usedUp, 0, width-usedUp, height ); g2.rotate( angle, 0, 0 ); g2.translate( -width+usedUp, height ); label.paint( g2 ); g2.dispose(); } } } else{ double angle = Math.PI+Math.PI/2.0; if( icon == null || isIconHidden() ){ Graphics2D g2 = (Graphics2D)g.create(); g2.rotate( angle, 0, 0 ); g2.translate( -getHeight(), 0 ); label.paint( g2 ); g2.dispose(); } else { int width = getWidth(); int height = getHeight(); int iconWidth = icon.getIconWidth(); int iconHeight = icon.getIconHeight(); icon.paintIcon( this, g, (width-iconWidth)/2, iconOffset ); int usedUp = iconHeight + iconOffset + iconTextDistance; if( usedUp < height ){ Graphics2D g2 = (Graphics2D)g.create( 0, usedUp, width, height-usedUp ); g2.rotate( angle, 0, 0 ); g2.translate( -height, 0 ); label.paint( g2 ); g2.dispose(); } } } } @Override public void update( Graphics g ) { // do nothing } @Override public void setBounds( int x, int y, int w, int h ) { super.setBounds(x, y, w, h); if( isHorizontal() ) label.setBounds( 0, 0, w+30, h ); else label.setBounds( 0, 0, h+30, w ); } }