/*
* Copyright (c) 2010 Lockheed Martin Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eurekastreams.web.client.ui.common.tabs;
import java.util.HashMap;
import org.eurekastreams.web.client.events.Observer;
import org.eurekastreams.web.client.events.UpdatedHistoryParametersEvent;
import org.eurekastreams.web.client.ui.Session;
import org.eurekastreams.web.client.ui.pages.master.StaticResourceBundle;
import com.allen_sauer.gwt.dnd.client.DragHandler;
import com.allen_sauer.gwt.dnd.client.PickupDragController;
import com.allen_sauer.gwt.dnd.client.drop.DropController;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.IndexedPanel;
/**
* Manages tabs. Stores the state in the history. Supports dragging and dropping.
*
*/
public class TabContainerPanel extends AbsolutePanel
{
/**
* The tab contents.
*/
FlowPanel tabContents = new FlowPanel();
/**
* The dictionary of tabs.
*/
HashMap<String, SimpleTab> tabs = new HashMap<String, SimpleTab>();
/**
* The active tab.
*/
SimpleTab activeTab = null;
/**
* The first tab. Dictionaries aren't indexed.
*/
String firstTab = null;
/**
* The tab drop zone.
*/
HorizontalPanel tabDropZone = new HorizontalPanel();
/**
* The tab boundary panel. Absolute panel is needed because gwt-dnd only accepts them.
*/
AbsolutePanel tabBoundaryPanel = new AbsolutePanel();
/**
* The tab drag controller.
*/
private PickupDragController tabDragController;
/**
* The default drag sensitivity.
*/
private static final int DRAG_SENSITIVITY = 10;
/**
* Are we draggable?
*/
private boolean draggable = false;
/**
* The history token key. Default to StaticResourceBundle.INSTANCE.coreCss().tab().
*/
private String key;
/**
* Default constructor.
*/
public TabContainerPanel()
{
this("tab");
}
/**
* Constructor specifiying the key, or the history token key associated with this tab container.
*
* @param inKey
* the history token key.
*/
public TabContainerPanel(final String inKey)
{
key = inKey;
tabBoundaryPanel.setWidth("100%");
tabBoundaryPanel.add(tabDropZone);
tabBoundaryPanel.addStyleName(StaticResourceBundle.INSTANCE.coreCss().tabContainer());
this.addStyleName(StaticResourceBundle.INSTANCE.coreCss().tabContainerParent());
this.add(tabBoundaryPanel);
this.add(tabContents);
}
/**
* init *MUST* be called after all the tabs are added. This can not be done in the constructor because it looks into
* the history to see which tab to select. This obviously can't be done until we have all the tabs.
*/
public void init()
{
Session.getInstance().getEventBus().addObserver(UpdatedHistoryParametersEvent.class,
new Observer<UpdatedHistoryParametersEvent>()
{
public void update(final UpdatedHistoryParametersEvent event)
{
if (null != event.getParameters().get(key))
{
switchToTab(event.getParameters().get(key));
}
else if (null != firstTab)
{
switchToTab(firstTab);
}
}
}, true);
}
/**
* Make the tabs draggable. Just give me a draghandler so I know what to do when its over.
*
* @param dragHandler
* the draghandler.
* @param dropController
* the drop controller.
*/
public void makeTabsDraggable(final DragHandler dragHandler, final DropController dropController)
{
draggable = true;
tabDragController = new PickupDragController(tabBoundaryPanel, false);
tabDragController.setBehaviorConstrainedToBoundaryPanel(true);
tabDragController.setBehaviorMultipleSelection(false);
tabDragController.setBehaviorDragStartSensitivity(DRAG_SENSITIVITY);
tabDragController.addDragHandler(dragHandler);
tabDragController.registerDropController(dropController);
}
/**
* Get the tab drop zone. May be necessary for making drop controllers.
*
* @return the tab drop zone.
*/
public IndexedPanel getTabDropZone()
{
return tabDropZone;
}
/**
* Switch to a tab by it's unique identifier.
*
* @param identifier
* the tab's identifier.
*/
public void switchToTab(final String identifier)
{
if (activeTab == null || !activeTab.getIdentifier().equals(identifier))
{
if (tabs.containsKey(identifier))
{
activateTab(identifier);
}
else if (firstTab != null)
{
activateTab(firstTab);
}
}
}
/**
* Selects and activates a given tab, if possible.
*
* @param tab
* the tab name/identifier to activate
*/
private void activateTab(final String tab)
{
if (activeTab != null)
{
activeTab.unSelect();
}
activeTab = tabs.get(tab);
activeTab.select();
tabContents.clear();
tabContents.add(activeTab.getContents());
}
/**
* Add a tab.
*
* @param tab
* the tab.
*/
public void addTab(final SimpleTab tab)
{
insertTab(tab, tabs.size());
}
/**
* Insert a tab. Like add a tab only with an index.
*
* @param tab
* the tab.
* @param index
* the index.
*/
public void insertTab(final SimpleTab tab, final int index)
{
if (firstTab == null)
{
firstTab = tab.getIdentifier();
}
tabs.put(tab.getIdentifier(), tab);
tabDropZone.insert(tab, index);
if (draggable)
{
tab.makeTabDraggable(tabDragController);
}
tab.init(key);
}
/**
* Gets the number of tabs.
*
* @return the tabs.
*/
public int getSize()
{
return tabs.size();
}
/**
* Remove a tab by identifier.
*
* @param identifier
* the identifier.
*/
public void removeTab(final String identifier)
{
tabDropZone.remove(tabs.get(identifier));
tabs.remove(identifier);
}
/**
* Gets a tab.
*
* @param index
* the index.
* @return the tab.
*/
public SimpleTab getTab(final int index)
{
return (SimpleTab) tabDropZone.getWidget(index);
}
}