de.swm.commons.mobile.client.widgets.tab.TabPanel Maven / Gradle / Ivy
/*
* Copyright 2011 SWM Services GmbH.
*
* 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 de.swm.commons.mobile.client.widgets.tab;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Widget;
import de.swm.commons.mobile.client.SWMMobile;
import de.swm.commons.mobile.client.page.Transition;
import de.swm.commons.mobile.client.widgets.LoadingIndicatorPopup;
import de.swm.commons.mobile.client.widgets.SWMMobileWidgetBase;
import de.swm.commons.mobile.client.widgets.itf.ISpinnerStarted;
import java.util.Iterator;
import java.util.logging.Logger;
/**
* A Tab panel containts several {@link Tab}s. Each Tab has a {@link TabHeader} and a {@link TabContent}.
*/
public class TabPanel extends SWMMobileWidgetBase implements HasWidgets, ClickHandler {
private static final Logger LOGGER = Logger.getLogger(TabPanel.class.getName());
public static final int SPINNER_DELAY_MILLIS = 500;
private final FlowPanel myPanel = new FlowPanel();
private final FlowPanel myTabHeaderPanel = new FlowPanel();
private final FlowPanel myTabContentPanel = new FlowPanel();
private int mySelectedTabIndex = -1;
private Transition transition = Transition.SLIDE;
/**
* True if every tab transition should have an spinner page.
*/
private boolean showSpinnerBetweenTransitions = false;
private boolean isSpinnerStarted = false;
private final LoadingIndicatorPopup spinner = new LoadingIndicatorPopup();
/**
* Default constructor.
*/
public TabPanel() {
initWidget(myPanel);
setStyleName(SWMMobile.getTheme().getMGWTCssBundle().getTabPanelCss().tabPanel());
myPanel.add(myTabHeaderPanel);
myPanel.add(myTabContentPanel);
myTabHeaderPanel.addDomHandler(this, ClickEvent.getType());
}
public Transition getTransition() {
return transition;
}
/**
* Sets the transition effect shown when switching between the tabs. Default is Transition.SLIDE.
*
* @param transition transition effect; if set to {code}null{code}, no transition effect is shown.
*/
public void setTransition(Transition transition) {
this.transition = transition;
}
@Override
public void add(Widget w) {
assert w instanceof Tab : "Can only place Tab widgets inside a Tab Panel.";
myTabHeaderPanel.add(w);
}
@Override
public void onInitialLoad() {
if (myTabHeaderPanel.getWidgetCount() > 0) {
// FIXME:allow a different default tab to be set?
selectTab(0);
}
}
/**
* Selects a tab by his index position.
*
* @param index the index
*/
public void selectTab(int index) {
if (mySelectedTabIndex == index) {
LOGGER.info("same tab");
return;
}
Tab from = unselectCurrentTab();
Tab to = (Tab) myTabHeaderPanel.getWidget(index);
to.addStyleName(SWMMobile.getTheme().getMGWTCssBundle().getTabPanelCss().selected());
if (from == null) {
myTabContentPanel.add(to.getContent());
} else if (transition == null) {
myTabContentPanel.remove(from.getContent());
myTabContentPanel.add(to.getContent());
} else {
transition.start(from.getContent(), to.getContent(), myTabContentPanel, index < mySelectedTabIndex);
}
mySelectedTabIndex = index;
}
public int getSelectedTabIndex() {
return mySelectedTabIndex;
}
@Override
public void onClick(ClickEvent event) {
if (this.showSpinnerBetweenTransitions) {
if (!isSpinnerStarted) {
final int index = getClickedTabHeaderIndex(event);
this.startPopup(new ISpinnerStarted() {
@Override
public void spinnerStarted() {
isSpinnerStarted = true;
if (index != -1) {
selectTab(index);
}
Timer timer = new Timer(){
@Override
public void run() {
stopSpinnerIfRunning();
}
};
timer.schedule(SPINNER_DELAY_MILLIS);
}
});
}
} else {
int index = getClickedTabHeaderIndex(event);
if (index != -1) {
selectTab(index);
}
}
}
/**
* True, if a spinner will be shown betreen transisitions.
* @param showSpinnerBetweenTransitions true if spinner wil be shown between transitions.
*/
public void setShowSpinnerBetweenTransitions(boolean showSpinnerBetweenTransitions) {
this.showSpinnerBetweenTransitions = showSpinnerBetweenTransitions;
}
/**
* Will hide a loading indicator popup.
*/
private void stopSpinnerIfRunning() {
if (showSpinnerBetweenTransitions && isSpinnerStarted) {
isSpinnerStarted = false;
this.spinner.setVisible(false);
}
}
@Override
public void clear() {
myPanel.clear();
}
@Override
public Iterator iterator() {
return myPanel.iterator();
}
@Override
public boolean remove(Widget w) {
return myPanel.remove(w);
}
/**
* Un-selects the current Tab.
*
* @return the tab previously selected
*/
private Tab unselectCurrentTab() {
if (mySelectedTabIndex == -1) {
return null;
}
Tab tab = (Tab) myTabHeaderPanel.getWidget(mySelectedTabIndex);
tab.removeStyleName(SWMMobile.getTheme().getMGWTCssBundle().getTabPanelCss().selected());
return tab;
}
/**
* Returns the index of clicked tab panel.
*
* @param e the click event
* @return the index
*/
private int getClickedTabHeaderIndex(ClickEvent e) {
Element div = Element.as(e.getNativeEvent().getEventTarget());
if (div == myTabHeaderPanel.getElement()) {
LOGGER.info("TabClicked: " + e.toString());
return -1;
}
while (div.getParentElement() != myTabHeaderPanel.getElement()) {
div = div.getParentElement();
}
return DOM.getChildIndex((com.google.gwt.user.client.Element) myTabHeaderPanel.getElement(),
(com.google.gwt.user.client.Element) div);
}
/**
* Starts a propgress bar.
*
* @param spinnerStarted spinner is started
* @return the loading indicator.
*/
private LoadingIndicatorPopup startPopup(final ISpinnerStarted spinnerStarted) {
this.spinner.showCentered(true);
final Timer timer = new Timer() {
@Override
public void run() {
isSpinnerStarted = true;
spinnerStarted.spinnerStarted();
}
};
timer.schedule(50);
return this.spinner;
}
}