All Downloads are FREE. Search and download functionalities are using the official Maven repository.

bibliothek.gui.dock.station.toolbar.menu.CustomizationToolbarButton Maven / Gradle / Ivy

/*
 * 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) 2012 Herve Guillaume, 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
 * 
 * Herve Guillaume
 * [email protected]
 * FR - France
 *
 * Benjamin Sigg
 * [email protected]
 * CH - Switzerland
 */
package bibliothek.gui.dock.station.toolbar.menu;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.LayoutManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.Icon;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JToggleButton;

import bibliothek.gui.DockController;
import bibliothek.gui.DockStation;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.util.icon.DockIcon;

/**
 * The {@link CustomizationToolbarButton} is a button that allows to add one
 * {@link Dockable} to a {@link DockStation}. This button also offers an
 * indication telling whether the {@link Dockable} is already shown on another
 * station.
 * 
 * @author Benjamin Sigg
 */
public abstract class CustomizationToolbarButton implements
		CustomizationMenuContent{
	/**
	 * The different locations where a {@link Dockable} can be in respect to
	 * this button
	 */
	public static enum ItemLocation{
		/** The {@link Dockable} is not visible anywhere */
		INVISIBLE,
		/**
		 * The {@link Dockable} is visible, but it is part of another
		 * {@link DockStation}
		 */
		ELSEWHERE,
		/**
		 * The {@link Dockable} is visible and it is part of this
		 * {@link DockStation}
		 */
		HERE
	}

	private DockController controller;

	private Icon icon;
	private String description;
	private String text;

	private JLayeredPane base;
	private JToggleButton button;
	private JLabel elsewhere;

	private CustomizationMenuCallback callback;

	/** the icon of {@link #here} */
	private DockIcon elsewhereIcon = new DockIcon(
			"toolbar.customization.check", DockIcon.KIND_ICON){
		@Override
		protected void changed( Icon oldValue, Icon newValue ){
			if (elsewhere != null){
				elsewhere.setIcon(newValue);
			}
		}
	};
	
	@Override
	public void setController( DockController controller ){
		this.controller = controller;
		if (callback != null){
		elsewhereIcon.setController(controller);
		}
	}

	@Override
	public Component getView(){
		return base;
	}

	@Override
	public void bind( CustomizationMenuCallback callback ){
		this.callback = callback;
		button = new JToggleButton();
		button.setIcon(icon);
		button.setToolTipText(description);
		button.setText(text);
		button.setOpaque(false);
		
		elsewhere = new JLabel();
		elsewhereIcon.setController(controller);
		elsewhere.setIcon(elsewhereIcon.value());
		elsewhere.setVisible(false);

		base = new JLayeredPane();
		base.add(button);
		base.add(elsewhere);
		base.setLayer(button, JLayeredPane.DEFAULT_LAYER);
		base.setLayer(elsewhere, JLayeredPane.MODAL_LAYER);
		base.setLayout(new LayoutManager(){
			@Override
			public void removeLayoutComponent( Component comp ){
				// ignore
			}

			@Override
			public Dimension preferredLayoutSize( Container parent ){
				return new Dimension(button.getPreferredSize().width
						+ elsewhere.getPreferredSize().width + 1, button
						.getPreferredSize().height);
			}

			@Override
			public Dimension minimumLayoutSize( Container parent ){
				return button.getMinimumSize();
			}

			@Override
			public void layoutContainer( Container parent ){
				if (parent.getComponentCount() == 2){
					int width = parent.getWidth();
					int height = parent.getHeight();
					Dimension preferred = elsewhere.getPreferredSize();
					int labelWidth = Math.min(preferred.width, width - 1);
					int labelHeight = Math.min(preferred.height, height - 1);
					button.setBounds(labelWidth + 2, 0, width - labelWidth - 2, height);
					elsewhere.setBounds(1, 0, labelWidth,
							labelHeight);
				}
			}

			@Override
			public void addLayoutComponent( String name, Component comp ){
				// ignore
			}
		});

		button.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed( ActionEvent e ){
				ItemLocation location = getItemLocation();
				setItemVisible(location != ItemLocation.HERE);
			}
		});

		select();
	}

	private void select(){
		ItemLocation location = getItemLocation();
		elsewhere.setVisible(location == ItemLocation.HERE || location == ItemLocation.ELSEWHERE);
		button.setSelected(location == ItemLocation.HERE);
	}

	/**
	 * Gets the current location of the {@link Dockable} that is described by
	 * this button.
	 * 
	 * @return the current location
	 * @throws IllegalStateException
	 *             if {@link #bind(CustomizationMenuCallback)} was not called
	 */
	protected ItemLocation getItemLocation(){
		if (callback == null){
			throw new IllegalStateException(
					"this information is only available if the button has been bound");
		}

		if (!hasDockable()){
			return ItemLocation.INVISIBLE;
		}
		Dockable item = getDockable();
		DockStation parent = item.getDockParent();
		if (parent == null){
			return ItemLocation.INVISIBLE;
		}
		DockStation owner = callback.getOwner();
		while (parent != null){
			if (parent == owner){
				return ItemLocation.HERE;
			}
			item = parent.asDockable();
			if (item == null){
				parent = null;
			} else{
				parent = item.getDockParent();
			}
		}
		return ItemLocation.ELSEWHERE;
	}

	/**
	 * Removes the {@link Dockable} from its current parent and maybe appends it
	 * to the owner of this button.
	 * 
	 * @param visible
	 *            whether the item should be visible or not
	 */
	protected void setItemVisible( boolean visible ){
		Dockable item = getDockable();
		DockStation parent = item.getDockParent();
		if (parent != null){
			parent.drag(item);
		}

		if (visible){
			CustomizationToolbarButton.this.callback.append(item);
		}

		select();
	}

	@Override
	public void unbind(){
		base = null;
		button = null;
		elsewhere = null;
		elsewhereIcon.setController(null);
	}

	/**
	 * Sets the icon which should be shown on the button.
	 * 
	 * @param icon
	 *            the new icon, can be null
	 */
	public void setIcon( Icon icon ){
		this.icon = icon;
		if (button != null){
			button.setIcon(icon);
		}
	}
	
	/**
	 * Sets the text which should be shown on the button.
	 * 
	 * @param icon
	 *            the new text, can be null
	 */
	public void setText( String text){
		this.text = text;
		if (button != null){
			button.setText(text);
		}
	}

	/**
	 * Sets a text which describes the meaning of the button.
	 * 
	 * @param description
	 *            the description, can be null
	 */
	public void setDescription( String description ){
		this.description = description;
		if (button != null){
			button.setToolTipText(description);
		}
	}

	/**
	 * Tells whether the {@link Dockable} of this button, accessible by calling
	 * {@link #getDockable()}, is already present. If the item is not yet
	 * present, then it cannot be visible or selected at this time.
	 * 
	 * @return whether the {@link Dockable} already exists
	 */
	protected abstract boolean hasDockable();

	/**
	 * Gets the element that is put onto a toolbar. This method may create the
	 * {@link Dockable} lazily in the very moment it is used the first time.
	 * 
	 * @return the item to show on the toolbar
	 */
	protected abstract Dockable getDockable();
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy