/* * 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) 2010 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.station.flap.button; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.swing.Icon; import bibliothek.gui.DockStation; import bibliothek.gui.DockTheme; import bibliothek.gui.Dockable; import bibliothek.gui.dock.FlapDockStation; import bibliothek.gui.dock.action.DockAction; import bibliothek.gui.dock.title.DockTitle; /** * Tells what kind of information should be displayed on the buttons of a {@link FlapDockStation}. What is actually * displayed also depends on the {@link DockTitle} that is used, but all the default titles support all the settings * this class offers. * @author Benjamin Sigg */ public class ButtonContent { /** * A {@link ButtonContentCondition} that is always <code>true</code> */ public static final ButtonContentCondition TRUE = new ButtonContentCondition(){ public boolean shouldShow( Dockable dockable, boolean themeSuggestion ){ return true; } public void install( Dockable dockable, ButtonContent content ){ // ignore } public void uninstall( Dockable dockable, ButtonContent content ){ // ignore } }; /** * A {@link ButtonContentCondition} that is always <code>false</code> */ public static final ButtonContentCondition FALSE = new ButtonContentCondition(){ public boolean shouldShow( Dockable dockable, boolean themeSuggestion ){ return false; } public void install( Dockable dockable, ButtonContent content ){ // ignore } public void uninstall( Dockable dockable, ButtonContent content ){ // ignore } }; /** * A {@link ButtonContentCondition} that always returns the value a {@link DockTheme} would choose */ public static final ButtonContentCondition THEME = new ButtonContentCondition(){ public boolean shouldShow( Dockable dockable, boolean themeSuggestion ){ return themeSuggestion; } public void install( Dockable dockable, ButtonContent content ){ // ignore } public void uninstall( Dockable dockable, ButtonContent content ){ // ignore } }; /** * A {@link ButtonContentCondition} that returns <code>true</code> if a {@link Dockable} does not * have an icon. */ public static final ButtonContentCondition NOT_IF_ICON = new AbstractButtonContentCondition(){ public boolean shouldShow( Dockable dockable, boolean themeSuggestion ){ return dockable.getTitleIcon() == null; } public void titleIconChanged( Dockable dockable, Icon oldIcon, Icon newIcon ){ fire( dockable ); } }; /** * A {@link ButtonContentCondition} that returns <code>true</code> if a {@link Dockable} does not * have a title text. */ public static final ButtonContentCondition NOT_IF_TEXT = new AbstractButtonContentCondition(){ public boolean shouldShow( Dockable dockable, boolean themeSuggestion ){ String title = dockable.getTitleText(); return title == null || title.length() == 0; } public void titleTextChanged( Dockable dockable, String oldTitle, String newTitle ){ fire( dockable ); } }; /** * A {@link ButtonContentCondition} that returns <code>true</code> if the element is a {@link DockStation}. */ public static final ButtonContentCondition IF_STATION = new ButtonContentCondition(){ public boolean shouldShow( Dockable dockable, boolean themeSuggestion ){ return dockable.asDockStation() != null; } public void install( Dockable dockable, ButtonContent content ){ // ignore } public void uninstall( Dockable dockable, ButtonContent content ){ // ignore } }; /** * A {@link ButtonContentCondition} that returns <code>true</code> if the element is not a {@link DockStation}. */ public static final ButtonContentCondition IF_DOCKABLE = new ButtonContentCondition(){ public boolean shouldShow( Dockable dockable, boolean themeSuggestion ){ return dockable.asDockStation() == null; } public void install( Dockable dockable, ButtonContent content ){ // ignore } public void uninstall( Dockable dockable, ButtonContent content ){ // ignore } }; /** the look and feel completely depends on the current {@link DockTheme}. */ public static final ButtonContent THEME_DEPENDENT = new ButtonContent( THEME, THEME, THEME, THEME, THEME, THEME ); /** * Only the icon is painted. Please note that this constant only remains for backwards compatibility, * creating a new {@link ButtonContent} would have the exact same effect. */ public static final ButtonContent ICON_ONLY = new ButtonContent( FALSE, TRUE, FALSE, FALSE, FALSE, FALSE ); /** * Only the title text is painted. Please note that this constant only remains for backwards compatibility, * creating a new {@link ButtonContent} would have the exact same effect. */ public static final ButtonContent TEXT_ONLY = new ButtonContent( FALSE, FALSE, TRUE, FALSE, FALSE, FALSE ); /** * Only the icon and the title text are painted. Please note that this constant only remains for backwards compatibility, * creating a new {@link ButtonContent} would have the exact same effect. */ public static final ButtonContent ICON_AND_TEXT_ONLY = new ButtonContent( FALSE, TRUE, TRUE, FALSE, FALSE, FALSE ); /** * The icon, or if not present the title text, is painted. Please note that this constant only remains for backwards compatibility, * creating a new {@link ButtonContent} would have the exact same effect. */ public static final ButtonContent ICON_THEN_TEXT_ONLY = new ButtonContent( FALSE, TRUE, NOT_IF_ICON, FALSE, FALSE, FALSE ); /** * The title text, or if not present the icon, is painted. Please note that this constant only remains for backwards compatibility, * creating a new {@link ButtonContent} would have the exact same effect. */ public static final ButtonContent TEXT_THEN_ICON_ONLY = new ButtonContent( FALSE, NOT_IF_TEXT, TRUE, FALSE, FALSE, FALSE ); /** * Only the icon and the actions are painted. Please note that this constant only remains for backwards compatibility, * creating a new {@link ButtonContent} would have the exact same effect. */ public static final ButtonContent ICON_ACTIONS = new ButtonContent( FALSE, TRUE, FALSE, FALSE, TRUE, FALSE ); /** * Only the title text and the actions are painted. Please note that this constant only remains for backwards compatibility, * creating a new {@link ButtonContent} would have the exact same effect. */ public static final ButtonContent TEXT_ACTIONS = new ButtonContent( FALSE, FALSE, TRUE, FALSE, TRUE, FALSE ); /** * Icon, title text and actions are painted. Please note that this constant only remains for backwards compatibility, * creating a new {@link ButtonContent} would have the exact same effect. */ public static final ButtonContent ICON_AND_TEXT_ACTIONS = new ButtonContent( FALSE, TRUE, TRUE, FALSE, TRUE, FALSE ); /** * The icon, or if not present the title text, and the actions are painted. Please note that this constant only remains for backwards compatibility, * creating a new {@link ButtonContent} would have the exact same effect. */ public static final ButtonContent ICON_THEN_TEXT_ACTIONS = new ButtonContent( FALSE, TRUE, NOT_IF_ICON, FALSE, TRUE, FALSE ); /** * The title text, or if not present the icon, and the actions are painted. Please note that this constant only remains for backwards compatibility, * creating a new {@link ButtonContent} would have the exact same effect. */ public static final ButtonContent TEXT_THEN_ICON_ACTIONS = new ButtonContent( FALSE, NOT_IF_TEXT, TRUE, FALSE, TRUE, FALSE ); private ButtonContentCondition knob; private ButtonContentCondition icon; private ButtonContentCondition text; private ButtonContentCondition actions; private ButtonContentCondition filterActions; private ButtonContentCondition children; private Map<Dockable, List<ButtonContentListener>> listeners = new HashMap<Dockable, List<ButtonContentListener>>(); /** * Creates a new set of properties. All arguments can have a value of <code>null</code>, in which case they default * to {@link #THEME} * @param knob whether to paint a "knob" where the user can grab the title and move around. A knob really is only * required if neither icon nor text is painted * @param icon whether to paint the icon of a <code>Dockable</code> * @param text whether to paint the title text of a <code>Dockable</code> * @param children whether to add a button for each child of a {@link DockStation}. The button allows user to * open the station and focus one of its children with on click. If the represented {@link Dockable} is not a * station, then only one button is painted. * @param actions whether to show the normal {@link DockAction}s of a <code>Dockable</code> * @param filterActions whether only important {@link DockAction}s, as defined by {@link ButtonContentFilter}, should be shown */ public ButtonContent( ButtonContentCondition knob, ButtonContentCondition icon, ButtonContentCondition text, ButtonContentCondition children, ButtonContentCondition actions, ButtonContentCondition filterActions ){ this.knob = get( knob ); this.icon = get( icon ); this.text = get( text ); this.children = get( children ); this.actions = get( actions ); this.filterActions = get( filterActions ); } private ButtonContentCondition get( ButtonContentCondition condition ){ if( condition == null ){ return THEME; } return condition; } /** * Informs this {@link ButtonContent} that any change regarding <code>dockable</code> should * be reported to <code>listener</code>. * @param dockable the element to observe * @param listener the listener that monitors <code>dockable</code> */ public void addListener( Dockable dockable, ButtonContentListener listener ){ List<ButtonContentListener> list = listeners.get( dockable ); if( list == null ){ list = new ArrayList<ButtonContentListener>(); listeners.put( dockable, list ); install( dockable ); } list.add( listener ); } /** * Informs this {@link ButtonContent} that <code>listener</code> no longer has to be observed. * @param dockable the element that was observed * @param listener the listener that is no longer required */ public void removeListener( Dockable dockable, ButtonContentListener listener ){ List<ButtonContentListener> list = listeners.get( dockable ); if( list != null ){ list.remove( listener ); if( list.isEmpty() ){ uninstall( dockable ); listeners.remove( dockable ); } } } /** * Gets all the listeners that are currently monitoring <code>dockable</code>. * @param dockable the element which may be monitored * @return all the listeners, may be an empty array but not <code>null</code> */ protected ButtonContentListener[] listeners( Dockable dockable ){ List<ButtonContentListener> list = listeners.get( dockable ); if( list != null ){ return list.toArray( new ButtonContentListener[ list.size() ] ); } return new ButtonContentListener[]{}; } public void handleChange( Dockable dockable ){ for( ButtonContentListener listener : listeners( dockable )){ listener.changed( this, dockable ); } } private void install( Dockable dockable ){ knob.install( dockable, this ); icon.install( dockable, this ); text.install( dockable, this ); children.install( dockable, this ); actions.install( dockable, this ); filterActions.install( dockable, this ); } private void uninstall( Dockable dockable ){ knob.uninstall( dockable, this ); icon.uninstall( dockable, this ); text.uninstall( dockable, this ); children.uninstall( dockable, this ); actions.uninstall( dockable, this ); filterActions.uninstall( dockable, this ); } /** * Tells whether a knob should be shown * @param dockable the element for which the property is requested * @param theme what the theme would do * @return <code>true</code> if the knob should be visible */ public boolean showKnob( Dockable dockable, boolean theme ){ return knob.shouldShow( dockable, theme ); } /** * Gets the condition that decides the property for {@link #showKnob(Dockable, boolean)} * @return the condition, not <code>null</code> */ public ButtonContentCondition getKnob(){ return knob; } /** * Tells whether actions should be shown on the button of a {@link FlapDockStation} * or not. * @param dockable the element for which the property is requested * @param theme what the theme would do * @return <code>true</code> if the actions should be shown */ public boolean showActions( Dockable dockable, boolean theme ){ return actions.shouldShow( dockable, theme ); } /** * Gets the condition that decides the property for {@link #showActions(Dockable, boolean)} * @return the condition, not <code>null</code> */ public ButtonContentCondition getActions(){ return actions; } /** * Tells whether actions should filtered before showing on the button of a {@link FlapDockStation}. * If {@link #showActions(Dockable, boolean)} returns <code>false</code> for <code>dockable</code>, then * this method is ignored. * @param dockable the element for which the property is requested * @param theme what the theme would do * @return <code>true</code> if the actions should be filtered by the current {@link ButtonContentFilter} */ public boolean filterActions( Dockable dockable, boolean theme ){ return actions.shouldShow( dockable, theme ) && filterActions.shouldShow( dockable, theme ); } /** * Gets the condition that decides the property for {@link #filterActions(Dockable, boolean)} * @return the condition, not <code>null</code> */ public ButtonContentCondition getFilterActions(){ return filterActions; } /** * Tells whether an icon should be shown. * @param dockable the element for which the property is requested * @param theme what the theme would do * @return <code>true</code> if icons should be shown */ public boolean showIcon( Dockable dockable, boolean theme ){ return icon.shouldShow( dockable, theme ); } /** * Gets the condition that decides the property for {@link #showIcon(Dockable, boolean)} * @return the condition, not <code>null</code> */ public ButtonContentCondition getIcon(){ return icon; } /** * Tells whether text should be shown. * @param dockable the element for which the property is requested * @param theme what the theme would do * @return <code>true</code> if text should be shown */ public boolean showText( Dockable dockable, boolean theme ){ return text.shouldShow( dockable, theme ); } /** * Gets the condition that decides the property for {@link #showText(Dockable, boolean)} * @return the condition, not <code>null</code> */ public ButtonContentCondition getText(){ return text; } /** * Tells whether actions to focus a child of a {@link DockStation} should be shown * @param dockable the element for which the property is requested * @param theme what the theme would do * @return <code>true</code> if the buttons should be shown */ public boolean showChildren( Dockable dockable, boolean theme ){ return children.shouldShow( dockable, theme ); } /** * Gets the condition that decides the property for {@link #showChildren(Dockable, boolean)} * @return the condition, not <code>null</code> */ public ButtonContentCondition getChildren(){ return children; } }