/*
* Copyright 2010 Daniel Kurka
*
* 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 com.googlecode.mgwt.ui.client.widget.tabbar;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.event.logical.shared.HasSelectionHandlers;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.uibinder.client.UiChild;
import com.google.gwt.uibinder.client.UiFactory;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Widget;
import com.googlecode.mgwt.dom.client.event.tap.TapEvent;
import com.googlecode.mgwt.dom.client.event.tap.TapHandler;
import com.googlecode.mgwt.ui.client.util.HandlerRegistrationConverter;
import com.googlecode.mgwt.ui.client.widget.carousel.Carousel;
import com.googlecode.mgwt.ui.client.widget.panel.flex.FlexPanel;
import java.util.ArrayList;
import java.util.List;
/**
*
*
* At the moment theres no support for custom parsers:
* http://code.google.com/p/google-web-toolkit/issues/detail?id=4461
*
* So if you want to use TabPanel in UIBinder its a bit choppy:
*
* <pre>
* <mgwt:TabPanel>
* <mgwt:tabs>
* <mgwt:Tab>
* <mgwt:button>
* <mgwt:DownloadsTabBarButton></mgwt:DownloadsTabBarButton>
* </mgwt:button>
* <mgwt:widget>
* <!-- content for that tab -->
* </mgwt:widget>
* </mgwt:Tab>
* </mgwt:tabs>
* </mgwt:TabPanel>
* </pre>
*
* @author Daniel Kurka
*/
public class TabPanel extends Composite implements HasSelectionHandlers<Integer> {
public static class TabBar extends Composite implements HasSelectionHandlers<Integer> {
private class InternalTouchHandler implements TapHandler {
private final TabBarButtonBase button;
public InternalTouchHandler(TabBarButtonBase button) {
this.button = button;
}
@Override
public void onTap(TapEvent event) {
setSelectedButton(getIndexForWidget(button));
}
}
@UiField
public FlowPanel container;
private List<TabBarButtonBase> children = new ArrayList<TabBarButtonBase>();;
private List<HandlerRegistration> handlers = new ArrayList<HandlerRegistration>();
public TabBar() {
this(DEFAULT_APPEARANCE);
}
public TabBar(TabBarAppearance appearance) {
initWidget(appearance.barBinder().createAndBindUi(this));
}
public void add(TabBarButtonBase w) {
if (children.size() == 0) {
w.setSelected(true);
}
container.add(w);
children.add(w);
handlers.add(w.addTapHandler(new InternalTouchHandler(w)));
}
public void clear() {
container.clear();
children.clear();
handlers.clear();
}
int getIndexForWidget(TabBarButtonBase w) {
return children.indexOf(w);
}
public boolean remove(TabBarButtonBase w) {
int indexForWidget = getIndexForWidget(w);
children.remove(w);
if (indexForWidget != -1) {
handlers.get(indexForWidget).removeHandler();
handlers.remove(indexForWidget);
}
return container.remove(w);
}
public void setSelectedButton(int index) {
setSelectedButton(index, true);
}
public void setSelectedButton(int index, boolean issueEvent) {
if (index < 0 || index >= children.size()) {
throw new IllegalArgumentException("invalid index");
}
int count = 0;
for (TabBarButtonBase button : children) {
if (count == index) {
button.setSelected(true);
} else {
button.setSelected(false);
}
count++;
}
if (issueEvent) {
SelectionEvent.fire(this, Integer.valueOf(index));
}
}
@Override
public com.google.gwt.event.shared.HandlerRegistration addSelectionHandler(
SelectionHandler<Integer> handler) {
return addHandler(handler, SelectionEvent.getType());
}
public void remove(int index) {
TabBarButtonBase w = getWidgetForIndex(index);
remove(w);
}
private TabBarButtonBase getWidgetForIndex(int index) {
return children.get(index);
}
}
public static final TabBarAppearance DEFAULT_APPEARANCE = GWT.create(TabBarAppearance.class);
@UiField
public FlexPanel container;
@UiField(provided=true)
public Carousel tabContainer;
@UiField(provided=true)
public TabBar tabBar;
protected final TabBarAppearance appearance;
public TabPanel() {
this(DEFAULT_APPEARANCE);
}
public TabPanel(TabBarAppearance appearance) {
this.appearance = appearance;
tabContainer = new Carousel();
tabContainer.setShowCarouselIndicator(false);
tabBar = new TabBar(appearance);
initWidget(appearance.panelBinder().createAndBindUi(this));
tabBar.addSelectionHandler(new SelectionHandler<Integer>() {
@Override
public void onSelection(SelectionEvent<Integer> event) {
tabContainer.setSelectedPage(event.getSelectedItem(), false);
}
});
tabContainer.addSelectionHandler(new SelectionHandler<Integer>() {
@Override
public void onSelection(SelectionEvent<Integer> event) {
tabBar.setSelectedButton(event.getSelectedItem(), false);
}
});
}
public void setSelectedChild(int index) {
tabBar.setSelectedButton(index, true);
tabContainer.setSelectedPage(index);
}
public void add(TabBarButtonBase button, Widget child) {
tabContainer.add(child);
tabBar.add(button);
}
/**
* at the moment there is no support for custom parsers:
* http://code.google.com/p/google-web-toolkit/issues/detail?id=4461 this is a workaround to allow
* use with UIBinder
*
* {@link TabPanel#add(TabBarButtonBase, Widget)} if you are writing java code
*
* @param b the tab to add
*/
@UiChild(tagname = "tabs")
public void addTab(Tab b) {
Widget w = b.getWidget();
TabBarButtonBase button = b.getButton();
if (button == null) {
throw new IllegalArgumentException("button can not be null");
}
if (w == null) {
throw new IllegalArgumentException("widget can not be null");
}
add(button, w);
}
@Override
public com.google.gwt.event.shared.HandlerRegistration addSelectionHandler(
SelectionHandler<Integer> handler) {
return new HandlerRegistrationConverter(tabBar.addSelectionHandler(handler));
}
@UiFactory
public TabBarAppearance getAppearance() {
return appearance;
}
}