/* * Bibliothek - DockingFrames * Library built on Java/Swing, allows the user to "drag and drop" * panels containing any Swing-Component the developer likes to add. * * Copyright (C) 2007 Benjamin Sigg * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Benjamin Sigg * benjamin_sigg@gmx.ch * CH - Switzerland */ package bibliothek.gui.dock.common; import java.awt.Font; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import bibliothek.gui.dock.common.event.FontMapListener; import bibliothek.gui.dock.common.intern.CDockable; import bibliothek.gui.dock.util.font.ConstantFontModifier; import bibliothek.gui.dock.util.font.FontModifier; import bibliothek.gui.dock.util.font.GenericFontModifier; /** * A map containing {@link FontModifier}s. Each <code>FontMap</code> is associated * with exactly one {@link CDockable}. This map is used to set the font * of various elements like titles or tabs. Changes in the map will * immediately be forwarded and applied. * @author Benjamin Sigg */ public class FontMap { /** key for font used in titles */ public static final String FONT_KEY_TITLE = "dock.title"; /** key for font used in titles if the title is focused */ public static final String FONT_KEY_TITLE_FOCUSED = "dock.title.focused"; /** key for font used on the button for a minimized dockable */ public static final String FONT_KEY_MINIMIZED_BUTTON = "dock.minimized"; /** key for font used on the focused button for a minimized dockable */ public static final String FONT_KEY_MINIMIZED_BUTTON_FOCUSED = "dock.minimized.focused"; /** key for font used on a tab */ public static final String FONT_KEY_TAB = "dock.tab"; /** key for font used on a selected tab */ public static final String FONT_KEY_TAB_SELECTED = "dock.tab.selected"; /** key for font used on a focused tab */ public static final String FONT_KEY_TAB_FOCUSED = "dock.tab.focused"; /** the map of fonts associated with {@link #dockable} */ private Map<String, FontModifier> fonts = new HashMap<String, FontModifier>(); /** listeners to be informed when {@link #fonts} changes */ private List<FontMapListener> listeners = new ArrayList<FontMapListener>(); /** the element for which this map is used */ private CDockable dockable; /** * Creates a new map * @param dockable the owner of this map */ public FontMap( CDockable dockable ){ if( dockable == null ) throw new IllegalArgumentException( "Dockable must not be null" ); this.dockable = dockable; } /** * Gets the owner of this map. * @return the owner */ public CDockable getDockable() { return dockable; } /** * Adds a listener to this map. * @param listener the new listener */ public void addListener( FontMapListener listener ){ if( listener == null ) throw new NullPointerException( "listener must not be null" ); listeners.add( listener ); } /** * Removes <code>listener</code> from this map. * @param listener the listener to remove */ public void removeListener( FontMapListener listener ){ listeners.remove( listener ); } /** * Gets the font which is associated with <code>key</code>. * @param key the key of the font * @return the font or <code>null</code> */ public FontModifier getFont( String key ){ return fonts.get( key ); } /** * Sets the font which should be used for <code>key</code>. * @param key the key of the font * @param font the new font, can be <code>null</code> */ public void setFont( String key, Font font ){ if( font == null ) setFont( key, (FontModifier)null ); else setFont( key, new ConstantFontModifier( font ) ); } /** * Tells to use a font that is derived from the original font of * <code>key</code>. There are different modifications possible, all * have to be supplied in the same form: <code>key=value</code>.<br> * Example: <code>setFont( x, "i=!", "b=+", s=14" );</code> would * create a modification that reverses the italic flag, sets any font * to bold and creates only fonts of size 14 * <ul> * <li>'i': italic * <ul> * <li>'+': make the font italic</li> * <li>'-': make the font not italic</li> * <li>'!': reverse the italic property of the font</li> * </ul> * </li> * <li>'b': bold * <ul> * <li>'+': make the font bold</li> * <li>'-': make the font not bold</li> * <li>'!': reverse the bold property of the font</li> * </ul> * </li> * <li>'s': size * <ul> * <li>'+number': increase the size by <code>number</code></li> * <li>'-number': decrease the size by <code>number</code></li> * <li>'number': set the size to <code>number</code></li> * </ul> * </li> * </ul> * @param key the key for the font * @param modifications a set of modifications */ public void setFont( String key, String... modifications ){ if( modifications.length == 0 ){ setFont( key, (FontModifier)null ); } else{ GenericFontModifier modifier = new GenericFontModifier(); for( String modification : modifications ){ String[] entry = split( modification ); String entryKey = entry[0]; String entryValue = entry[1]; boolean italic = "i".equals( entryKey ); boolean bold = "b".equals( entryKey ); boolean size = "s".equals( entryKey ); if( italic || bold ){ GenericFontModifier.Modify modify; if( "+".equals( entryValue )){ modify = GenericFontModifier.Modify.ON; } else if( "-".equals( entryValue )){ modify = GenericFontModifier.Modify.OFF; } else if( "!".equals( entryValue )){ modify = GenericFontModifier.Modify.REVERSE; } else{ throw new IllegalArgumentException( "illegal value, must be one of '+', '-' or '!': " + modification ); } if( italic ) modifier.setItalic( modify ); else modifier.setBold( modify ); } else if( size ){ String number; if( entryValue.startsWith( "+" )){ modifier.setSizeDelta( true ); number = entryValue.substring( 1 ).trim(); } else if( entryValue.startsWith( "-" )){ modifier.setSizeDelta( true ); number = entryValue.substring( 1 ).trim(); } else{ modifier.setSizeDelta( false ); number = entryValue; } int parsed = Integer.parseInt( number ); if( entryValue.startsWith( "-" )){ parsed = -parsed; } modifier.setSize( parsed ); } else{ throw new IllegalArgumentException( "unknown key: " + modification ); } } setFont( key, modifier ); } } private String[] split( String modification ){ int index = modification.indexOf( '=' ); if( index < 0 ) throw new IllegalArgumentException( "not in the form 'key'='value': " + modification ); String key = modification.substring( 0, index ); String value = modification.substring( index+1 ); key = key.trim(); value = value.trim(); if( key.length() == 0 ) throw new IllegalArgumentException( "missing key in: " + modification ); if( value.length() == 0 ) throw new IllegalArgumentException( "missing value in: " + modification ); return new String[]{ key, value }; } /** * Ensures that the original font is used for <code>key</code> * @param key the key which should no longer use a modified font */ public void removeFont( String key ){ setFont( key, (FontModifier)null ); } /** * Sets the font for <code>key</code>. * @param key the key of the font * @param font the new value or <code>null</code> to set * the default value */ public void setFont( String key, FontModifier font ){ FontModifier old; if( font == null ) old = fonts.remove( key ); else old = fonts.put( key, font ); if( (old == null && font != null) || (old != null && !old.equals( font )) ){ for( FontMapListener listener : listeners.toArray( new FontMapListener[ listeners.size() ] )) listener.fontChanged( this, key, font ); } } }