/*
* 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
* rvguillaume@hotmail.com
* FR - France
*
* Benjamin Sigg
* benjamin_sigg@gmx.ch
* CH - Switzerland
*/
package bibliothek.gui.dock.station.toolbar.menu;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JPanel;
import bibliothek.gui.DockController;
/**
* The grouped customization menu is a panel showing groups of other {@link CustomizationMenuContent}. The panel
* can insert titles and separators between its children
* @author Benjamin Sigg
*/
public class GroupedCustomizationMenuContent implements CustomizationMenuContent{
/** how many children to present on one line */
private int columns = 5;
/** The grouped children */
private List<Group> groups = new ArrayList<GroupedCustomizationMenuContent.Group>();
/** the panel showing all the children of this menu */
private JPanel view;
/** the controller in whose realm this menu is shown */
private DockController controller;
/** callback to the component showing the menu */
private CustomizationMenuCallback callback;
/** insets added to all components */
private Insets insets = new Insets( 2, 2, 2, 2 );
/**
* Creates a new {@link Group} with a new {@link GroupedCustomizationMenuTitle}, and
* {@link #addGroup(Group) adds} this group to this menu.
* @param title the title of the group, can be <code>null</code>
* @return the new group
*/
public Group addGroup( String title ){
Group group = new Group( new GroupedCustomizationMenuTitle( title ) );
addGroup( group );
return group;
}
/**
* Adds a new group to this menu.
* @param group the new group, not <code>null</code>
*/
public void addGroup( Group group ){
if( group == null ){
throw new IllegalArgumentException( "group is null" );
}
if( groups.contains( group )){
throw new IllegalArgumentException( "group was already added to this menu" );
}
if( group.getOwner() != this ){
throw new IllegalArgumentException( "group was not created using this menu object" );
}
groups.add( group );
}
/**
* Gets the number of {@link Group}s of this menu.
* @return the number of groups
*/
public int getGroupCount(){
return groups.size();
}
/**
* Gets the <code>index</code>'th group of this menu.
* @param index the index of the group
* @return
*/
public Group getGroup( int index ){
return groups.get( index );
}
/**
* Removes <code>group</code> from this menu. Nothing happens if this menu is currently shown.
* @param group the group to remove
*/
public void removeGroup( Group group ){
groups.remove( group );
}
/**
* Removes the <code>index</code>'th group from this menu. Nothing happens if this menu is currently shown.
* @param index the index of the group to remove
*/
public void removeGroup( int index ){
groups.remove( index );
}
@Override
public Component getView(){
return view;
}
@Override
public void setController( DockController controller ){
if( this.controller != controller ){
this.controller = controller;
if( callback != null ){
for( Group group : groups ){
group.setController( controller );
}
}
}
}
@Override
public void bind( CustomizationMenuCallback callback ){
this.callback = callback;
for( Group group : groups ){
group.setController( controller );
group.bind( callback );
}
view = new JPanel( new GridBagLayout() );
int offset = 0;
for( Group group : groups ){
offset += group.insertItems( offset );
}
}
@Override
public void unbind(){
for( Group group : groups ){
group.unbind();
group.setController( null );
}
}
/**
* One group of {@link CustomizationMenuContent}s
* @author Benjamin Sigg
*/
public class Group{
private CustomizationMenuContent title;
/** the children of this group */
private List<CustomizationMenuContent> items = new ArrayList<CustomizationMenuContent>();
/**
* Creates a new group using <code>title</code> as title component.
* @param title a component shown at the top as header, can be <code>null</code>
*/
public Group( CustomizationMenuContent title ){
this.title = title;
}
/**
* Sets the title component. Nothing happens if the menu is currently shown.
* @param title the new title, can be <code>null</code>
*/
public void setTitle( CustomizationMenuContent title ){
this.title = title;
}
/**
* Gets the current title component.
* @return the current title, may be <code>null</code>
*/
public CustomizationMenuContent getTitle(){
return title;
}
private GroupedCustomizationMenuContent getOwner(){
return GroupedCustomizationMenuContent.this;
}
private void setController( DockController controller ){
if( title != null ){
title.setController( controller );
}
for( CustomizationMenuContent item : items ){
item.setController( controller );
}
}
private void bind( CustomizationMenuCallback callback ){
if( title != null ){
title.bind( callback );
}
for( CustomizationMenuContent item : items ){
item.bind( callback );
}
}
/**
* Adds a set of {@link Component}s to the current view, using some
* {@link GridBagConstraints}.
* @param offset in which row to start
* @return how many rows were used up
*/
private int insertItems( int offset ){
int begin = offset;
if( title != null ){
view.add( title.getView(), new GridBagConstraints( 0, offset, columns, 1, 1.0, 0.01, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, insets, 0, 0 ) );
offset++;
}
int index = 0;
int length = items.size();
while( index < length ){
for( int i = 0; i < columns && index < length; i++ ){
view.add( items.get( index++ ).getView(), new GridBagConstraints( i, offset, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, insets, 0, 0 ));
}
offset++;
}
return offset - begin;
}
private void unbind(){
if( title != null ){
title.unbind();
}
for( CustomizationMenuContent item : items ){
item.unbind();
}
}
/**
* Adds <code>item</code> to this group, there is no effect if the menu is currently showing.
* @param item the item to add, not <code>null</code>
*/
public void add( CustomizationMenuContent item ){
add( getItemCount(), item );
}
/**
* Adds <code>item</code> to this group, there is no effect if the menu is currently showing.
* @param index to location where to add <code>item</code>
* @param item the item to add, not <code>null</code>
*/
public void add( int index, CustomizationMenuContent item ){
items.add( index, item );
}
/**
* Removes <code>item</code> from this group. There is no effect it the menu is currently showing.
* @param item the item to remove
*/
public void remove( CustomizationMenuContent item ){
if( items.remove( item ) ){
}
}
/**
* Removes <code>index</code>'th item from this group. There is no effect it the menu is currently showing.
* @param index the index of the item to remove
*/
public void remove( int index ){
items.remove( index );
}
/**
* Gets the number of icons in this group
* @return the number of icons
*/
public int getItemCount(){
return items.size();
}
/**
* Gets the <code>index</code>'th item of this group.
* @param index the index of the item
* @return the item at <code>index</code>
*/
public CustomizationMenuContent getItem( int index ){
return items.get( index );
}
}
}