/*
* 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.facile.menu;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JRadioButtonMenuItem;
import bibliothek.gui.DockController;
import bibliothek.gui.DockTheme;
import bibliothek.gui.DockUI;
import bibliothek.gui.dock.common.theme.ThemeMap;
import bibliothek.gui.dock.common.theme.ThemeMapListener;
import bibliothek.gui.dock.support.menu.BaseMenuPiece;
import bibliothek.gui.dock.support.menu.MenuPiece;
import bibliothek.gui.dock.themes.ThemeFactory;
import bibliothek.gui.dock.themes.ThemeMeta;
import bibliothek.gui.dock.themes.ThemeMetaListener;
import bibliothek.util.ClientOnly;
/**
* A {@link MenuPiece} that can change the {@link DockTheme}.
* @author Benjamin Sigg
*/
@ClientOnly
public class ThemeMenuPiece extends BaseMenuPiece {
/** the controller whose theme might be changed */
private DockController controller;
/** the items shown by this piece */
private List<Item> items = new ArrayList<Item>();
/** the list of available themes */
private ThemeMap themes;
/**
* Whether it is the responsibility of this menu to transfer the changes
* of {@link #themes} to {@link #controller} or not
*/
private boolean transferTheme = true;
/** a listener for {@link #themes} */
private ThemeMapListener listener = new ThemeMapListener(){
public void changed( ThemeMap map, int index, String key, ThemeFactory oldFactory, ThemeFactory newFactory ) {
if( oldFactory != null ){
items.remove( index );
remove( index );
}
if( newFactory != null ){
Item item = new Item( key, newFactory );
items.add( index, item );
insert( index, item );
}
}
public void selectionChanged( ThemeMap map, String oldKey, String newKey ) {
for( Item item : items ){
item.setSelected( item.getKey().equals( newKey ) );
}
if( controller != null && transferTheme ){
ThemeFactory factory = themes.getSelectedFactory();
if( factory != null ){
controller.setTheme( factory.create( controller ) );
}
}
}
};
/**
* Creates a new piece. The {@link #setTransferTheme(boolean) transfer-flag}
* will be set to <code>true</code>.
* @param controller the controller whose theme might be changed, can be <code>null</code>
* @param defaultThemes whether the piece should be filled up with the
* factories that can be obtained through the {@link DockUI}
*/
public ThemeMenuPiece( DockController controller, boolean defaultThemes ) {
setController( controller );
setTransferTheme( true );
ThemeMap themes = new ThemeMap();
if( defaultThemes ){
DockUI ui = DockUI.getDefaultDockUI();
int index = 0;
for( ThemeFactory theme : ui.getThemes() ){
themes.add( String.valueOf( index++ ), theme );
}
themes.select( ui.getDefaultTheme() );
}
setThemes( themes );
}
/**
* Creates a new piece using the themes of <code>map</code>. The
* {@link #setTransferTheme(boolean) transfer-flag} will be set to <code>false</code>.
* @param controller the controller, will just be stored but not used
* unless {@link #setTransferTheme(boolean)} is called with the argument
* <code>true</code>. Can be <code>null</code>
* @param map the list of themes, can be <code>null</code>
*/
public ThemeMenuPiece( DockController controller, ThemeMap map ){
setTransferTheme( false );
setController( controller );
setThemes( map );
}
/**
* Instructs this piece whether it should transfer the {@link DockTheme}
* from its {@link #getThemes() map} to the {@link #getController() controller}.
* @param transferTheme <code>true</code> if this piece should transfer the theme
*/
public void setTransferTheme( boolean transferTheme ) {
this.transferTheme = transferTheme;
}
/**
* Tells whether this piece is transfers the {@link DockTheme} from
* its {@link #getThemes() map} to the {@link #getController() controller}.
* @return <code>true</code> if this piece transfers the theme
* @see #setTransferTheme(boolean)
*/
public boolean isTransferTheme() {
return transferTheme;
}
/**
* Severs all connections of this {@link ThemeMenuPiece} with other objects,
* allowing the garbage collector to remove this.
*/
public void destroy(){
setThemes( null );
setController( null );
}
/**
* Sets the themes which this piece offers
* @param themes the offered themes, can be <code>null</code>
*/
public void setThemes( ThemeMap themes ) {
if( this.themes != themes ){
if( isBound() ){
uninstall();
}
this.themes = themes;
if( isBound() ){
install();
}
}
}
@Override
public void bind(){
if( !isBound() ){
super.bind();
install();
}
}
@Override
public void unbind(){
if( isBound() ){
super.unbind();
uninstall();
}
}
private void install(){
if( themes != null ){
themes.addThemeMapListener( listener );
String selected = themes.getSelectedKey();
for( int i = 0, n = themes.size(); i<n; i++ ){
Item item = new Item( themes.getKey( i ), themes.getFactory( i ));
items.add( item );
add( item );
item.setSelected( item.getKey().equals( selected ) );
}
if( transferTheme ){
if( controller != null ){
ThemeFactory factory = themes.getSelectedFactory();
if( factory != null ){
controller.setTheme( factory.create( controller ) );
}
}
}
}
}
private void uninstall(){
if( this.themes != null ){
this.themes.removeThemeMapListener( listener );
removeAll();
items.clear();
}
}
/**
* Gets the set of themes used by this piece.
* @return the set of themes
*/
public ThemeMap getThemes() {
return themes;
}
/**
* Gets the controller whose theme might be changed by this piece.
* @return the controller
*/
public DockController getController() {
return controller;
}
/**
* Sets the controller whose theme might be changed by this piece. The
* theme of the controller is changed if there is a selection on this
* piece.
* @param controller the new controller, can be <code>null</code>
*/
public void setController( DockController controller ) {
this.controller = controller;
if( controller != null && themes != null && transferTheme ){
ThemeFactory selection = themes.getSelectedFactory();
if( selection != null )
controller.setTheme( selection.create( controller ) );
}
for( Item item : items ){
item.setController( controller );
}
}
/**
* An item that changes the theme when selected.
* @author Benjamin Sigg
*/
private class Item extends JRadioButtonMenuItem implements ActionListener, ThemeMetaListener{
/** the name of this factory */
private String key;
/** the factory represented by this item */
private ThemeFactory factory;
/** information about the current factory */
private ThemeMeta meta;
/**
* Creates a new item.
* @param key the name of the factory
* @param factory the factory used to create a theme
*/
public Item( String key, ThemeFactory factory ){
this.key = key;
this.factory = factory;
addActionListener( this );
setController( getController() );
}
/**
* Sets the controller in whose realm this piece should work.
* @param controller the controller
*/
public void setController( DockController controller ){
if( meta != null ){
meta.removeListener( this );
setText( "" );
setToolTipText( "" );
meta = null;
}
if( controller != null ){
meta = factory.createMeta( controller );
meta.addListener( this );
setText( meta.getName() );
setToolTipText( meta.getDescription() );
}
}
public void actionPerformed( ActionEvent e ) {
themes.select( key );
}
public void authorsChanged( ThemeMeta meta ){
// ignore
}
public void descriptionChanged( ThemeMeta meta ){
setToolTipText( meta.getDescription() );
}
public void nameChanged( ThemeMeta meta ){
setText( meta.getName() );
}
public void webpagesChanged( ThemeMeta meta ){
// ignore
}
/**
* Gets the key of the factory.
* @return the key
*/
public String getKey() {
return key;
}
}
}