org.opencms.gwt.client.ui.CmsTabbedPanel Maven / Gradle / Ivy
Show all versions of opencms-gwt Show documentation
/*
* This library is part of OpenCms -
* the Open Source Content Management System
*
* Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
*
* 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.
*
* For further information about Alkacon Software, please see the
* company website: http://www.alkacon.com
*
* For further information about OpenCms, please see the
* project website: http://www.opencms.org
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.opencms.gwt.client.ui;
import org.opencms.gwt.client.I_CmsDescendantResizeHandler;
import org.opencms.gwt.client.ui.css.I_CmsLayoutBundle;
import org.opencms.gwt.client.util.CmsDebugLog;
import org.opencms.gwt.client.util.CmsDomUtil;
import org.opencms.util.CmsStringUtil;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Overflow;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.logical.shared.AttachEvent;
import com.google.gwt.event.logical.shared.BeforeSelectionHandler;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DeckLayoutPanel;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.LayoutPanel;
import com.google.gwt.user.client.ui.TabLayoutPanel;
import com.google.gwt.user.client.ui.Widget;
/**
* Wrapper class for @see com.google.user.client.ui.TabLayoutPanel.
*
* Layout class for a panel with several tabs. The tabbed panel should be set inside a widget with given width and height.
* For table based layouts the height of the parent cell should be set explicitly.
*
* As layout options two height for the tabbar are provided: 32px("standard") and 25px("small").
*
* @param the tab widget type
*
* @since 8.0.0
*
*/
public class CmsTabbedPanel extends Composite implements I_CmsDescendantResizeHandler, Iterable {
/** Enumeration with layout keys. */
public enum CmsTabbedPanelStyle {
/** Button style. */
buttonTabs(30, I_CmsLayoutBundle.INSTANCE.tabbedPanelCss().buttonTabs(), I_CmsLayoutBundle.INSTANCE.tabbedPanelCss().black()),
/** Classic style. */
classicTabs(28, I_CmsLayoutBundle.INSTANCE.tabbedPanelCss().classicTabs(), null);
/** The default tabbar height. */
public static final CmsTabbedPanelStyle DEFAULT = buttonTabs;
/** Property name. */
private int m_barHeight;
/** The general panel style name. */
private String m_styleClass;
/** The tab color style name. */
private String m_tabColorClass;
/**
* Constructor.
*
* @param barHeight the height of the bar
* @param styleClass the tab style class
* @param tabColorClass the tab color
*/
private CmsTabbedPanelStyle(int barHeight, String styleClass, String tabColorClass) {
m_barHeight = barHeight;
m_styleClass = styleClass;
m_tabColorClass = tabColorClass;
}
/**
* Returns the barHeight.
*
* @return the barHeight
*/
public int getBarHeight() {
return m_barHeight;
}
/**
* Returns the styleClass.
*
* @return the styleClass
*/
public String getStyleClass() {
return m_styleClass;
}
/**
* Returns the tabColorClass.
*
* @return the tabColorClass
*/
public String getTabColorClass() {
return m_tabColorClass;
}
}
/**
* Extending the TabLayoutPanel class to allow height adjustments to the tab bar.
*/
protected class TabPanel extends TabLayoutPanel {
/** The tab content panel. */
private DeckLayoutPanel m_contentPanel;
/** The tab bar. */
private FlowPanel m_tabBar;
/**
* Constructor.
*
* @param barHeight the tab bar height
* @param barUnit the height unit
*/
public TabPanel(double barHeight, Unit barUnit) {
super(barHeight, barUnit);
LayoutPanel tabLayout = (LayoutPanel)getWidget();
// Find the tab bar, which is the first flow panel in the LayoutPanel
for (int i = 0; i < tabLayout.getWidgetCount(); ++i) {
Widget widget = tabLayout.getWidget(i);
if (widget instanceof FlowPanel) {
m_tabBar = (FlowPanel)widget;
break; // tab bar found
}
}
for (int i = 0; i < tabLayout.getWidgetCount(); ++i) {
Widget widget = tabLayout.getWidget(i);
if (widget instanceof DeckLayoutPanel) {
m_contentPanel = (DeckLayoutPanel)widget;
break; // tab bar found
}
}
}
/**
* Checks the tab bar for necessary height adjustments.
*/
protected void checkTabOverflow() {
int height = m_tabBar.getOffsetHeight();
m_contentPanel.getElement().getParentElement().getStyle().setTop(height, Unit.PX);
}
}
/** The TabLayoutPanel widget. */
TabPanel m_tabPanel;
/** Auto resize mode. */
private boolean m_autoResize;
/** Offset which is added to the measured tab content height to resize the panel. */
private int m_autoResizeHeightDelta;
/** Stores the indexes and the title of disabled tabs. */
private Map m_disabledTabIndexes = new HashMap();
/** The tab panel style. */
private CmsTabbedPanelStyle m_panelStyle;
/** A map from ids to tabs. */
private Map m_tabsById = new HashMap();
/**
* The default constructor for an empty tabbed panel.
*/
public CmsTabbedPanel() {
this(CmsTabbedPanelStyle.DEFAULT);
}
/**
* The constructor for an empty tabbed panel.
*
* @param tabbedPanelStyle the pre-defined height of the tabbar, can be "small" or "standard"
*/
public CmsTabbedPanel(CmsTabbedPanelStyle tabbedPanelStyle) {
m_tabPanel = new TabPanel(tabbedPanelStyle.getBarHeight(), Unit.PX);
m_panelStyle = tabbedPanelStyle;
// All composites must call initWidget() in their constructors.
initWidget(m_tabPanel);
Element tabRootEl = m_tabPanel.getElement();
// set an additional css class for the parent element of the .gwt-TabLayoutPanelTabs element
List tabBarDivs = CmsDomUtil.getElementsByClass(
I_CmsLayoutBundle.INSTANCE.tabbedPanelCss().cmsTabLayoutPanelTabs(),
CmsDomUtil.Tag.div,
tabRootEl);
if (tabBarDivs.size() == 1) {
tabBarDivs.get(0).getParentElement().setClassName(
I_CmsLayoutBundle.INSTANCE.tabbedPanelCss().cmsTabLayoutPanelTabBar()
+ " "
+ I_CmsLayoutBundle.INSTANCE.generalCss().cornerTop());
if (m_panelStyle.getTabColorClass() != null) {
tabBarDivs.get(0).getParentElement().addClassName(m_panelStyle.getTabColorClass());
}
}
m_tabPanel.setStyleName(m_panelStyle.getStyleClass());
m_tabPanel.addStyleName(I_CmsLayoutBundle.INSTANCE.tabbedPanelCss().cmsTabLayoutPanel());
m_tabPanel.addStyleName(
I_CmsLayoutBundle.INSTANCE.generalCss().cornerAll()
+ " "
+ I_CmsLayoutBundle.INSTANCE.generalCss().textMedium());
m_tabPanel.addAttachHandler(new AttachEvent.Handler() {
/**
* @see com.google.gwt.event.logical.shared.AttachEvent.Handler#onAttachOrDetach(com.google.gwt.event.logical.shared.AttachEvent)
*/
public void onAttachOrDetach(AttachEvent event) {
setOverflowVisibleToContent();
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
public void execute() {
m_tabPanel.checkTabOverflow();
}
});
}
});
}
/**
* Add a new tab with the provided name and content.
*
* Wrapper function for {@link com.google.gwt.user.client.ui.TabLayoutPanel#add(Widget, String)}
*
* @param tabContent the widget to add as a tab
* @param tabName the name of the tab to display in the tabbar
*/
public void add(E tabContent, String tabName) {
tabContent.addStyleName(I_CmsLayoutBundle.INSTANCE.generalCss().cornerAll());
m_tabPanel.add(tabContent, CmsDomUtil.stripHtml(tabName));
Element tabRootEl = m_tabPanel.getElement();
// set an additional css class for the parent element of the .gwt-TabLayoutPanelTabs element
List tabDivs = CmsDomUtil.getElementsByClass(
I_CmsLayoutBundle.INSTANCE.tabbedPanelCss().cmsTabLayoutPanelTab(),
CmsDomUtil.Tag.div,
tabRootEl);
Iterator it = tabDivs.iterator();
boolean first = true;
while (it.hasNext()) {
Element e = it.next();
e.removeClassName(I_CmsLayoutBundle.INSTANCE.tabbedPanelCss().cornerLeft());
e.removeClassName(I_CmsLayoutBundle.INSTANCE.tabbedPanelCss().cornerRight());
if (first) {
e.addClassName(I_CmsLayoutBundle.INSTANCE.tabbedPanelCss().cornerLeft());
first = false;
}
if (!it.hasNext()) {
e.addClassName(I_CmsLayoutBundle.INSTANCE.tabbedPanelCss().cornerRight());
}
}
m_tabPanel.checkTabOverflow();
}
/**
* Add the before selection handler to the tabbed panel.
*
* Wrapper function for {@link com.google.gwt.user.client.ui.TabLayoutPanel#addBeforeSelectionHandler(BeforeSelectionHandler)}
*
* @param handler the before selection handler
* @return the registration for the event
*/
public HandlerRegistration addBeforeSelectionHandler(BeforeSelectionHandler handler) {
return m_tabPanel.addBeforeSelectionHandler(handler);
}
/**
* Adds a tab with a user-defined id.
*
* @param tabContent the tab content
* @param tabName the tab name
* @param tabId the tab id
*/
public void addNamed(E tabContent, String tabName, String tabId) {
add(tabContent, tabName);
m_tabsById.put(tabId, tabContent);
}
/**
* Adds a SelectionEvent handler to the tabbed panel.
*
* Wrapper function for {@link com.google.gwt.user.client.ui.TabLayoutPanel#addSelectionHandler(SelectionHandler)}
*
* @param handler the selection handler
* @return the registration for the event
*/
public HandlerRegistration addSelectionHandler(SelectionHandler handler) {
return m_tabPanel.addSelectionHandler(handler);
}
/**
* Add a new tab with the provided name and content and additional left margin.
*
* @param tabContent the widget to add as a tab
* @param tabName the name of the tab to display in the tabbar
*/
public void addWithLeftMargin(E tabContent, String tabName) {
tabContent.addStyleName(I_CmsLayoutBundle.INSTANCE.generalCss().cornerAll());
m_tabPanel.add(tabContent, CmsDomUtil.stripHtml(tabName));
int tabIndex = m_tabPanel.getWidgetIndex(tabContent);
Element tabElement = getTabElement(tabIndex);
if (tabElement != null) {
tabElement.addClassName(I_CmsLayoutBundle.INSTANCE.tabbedPanelCss().tabLeftMargin());
if (!m_panelStyle.equals(CmsTabbedPanelStyle.classicTabs)) {
tabElement.addClassName(I_CmsLayoutBundle.INSTANCE.generalCss().buttonCornerAll());
tabElement.addClassName(I_CmsLayoutBundle.INSTANCE.tabbedPanelCss().borderAll());
}
}
m_tabPanel.checkTabOverflow();
}
/**
* Disables the tab with the given index.
*
* @param tabContent the content of the tab that should be disabled
* @param reason the reason why the tab is disabled
*/
public void disableTab(E tabContent, String reason) {
Integer index = new Integer(m_tabPanel.getWidgetIndex(tabContent));
Element tab = getTabElement(index.intValue());
if ((tab != null) && !m_disabledTabIndexes.containsKey(index)) {
if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(tab.getTitle())) {
m_disabledTabIndexes.put(index, tab.getTitle());
} else {
m_disabledTabIndexes.put(index, "");
}
tab.addClassName(I_CmsLayoutBundle.INSTANCE.tabbedPanelCss().tabDisabled());
tab.setTitle(reason);
}
}
/**
* Enables the tab with the given index.
*
* @param tabContent the content of the tab that should be enabled
*/
public void enableTab(E tabContent) {
Integer index = new Integer(m_tabPanel.getWidgetIndex(tabContent));
Element tab = getTabElement(index.intValue());
if ((tab != null) && m_disabledTabIndexes.containsKey(index)) {
tab.removeClassName(I_CmsLayoutBundle.INSTANCE.tabbedPanelCss().tabDisabled());
tab.setTitle(m_disabledTabIndexes.get(index));
m_disabledTabIndexes.remove(index);
}
}
/**
* Gets the index of the currently-selected tab.
*
* Wrapper function for {@link com.google.gwt.user.client.ui.TabLayoutPanel#getSelectedIndex()}
*
* @return the selected index, or -1 if none is selected.
*/
public int getSelectedIndex() {
return m_tabPanel.getSelectedIndex();
}
/**
* Measures the height of the tab bar.
*
* @return the tab bar height
*/
public int getTabBarHeight() {
@SuppressWarnings("synthetic-access")
int result = m_tabPanel.m_tabBar.getOffsetHeight();
return result;
}
/**
* Finds a tab with a given id.
*
* @param tabId a tab id
*
* @return the tab with the given id
*/
public E getTabById(String tabId) {
return m_tabsById.get(tabId);
}
/**
* Gets the number of child widgets in this panel.
*
* Wrapper function for {@link com.google.gwt.user.client.ui.TabLayoutPanel#getWidgetCount()}
*
* @return the number of children
*/
public int getTabCount() {
return m_tabPanel.getWidgetCount();
}
/**
* Returns the index of the tab to the given child element.
*
* @param child the tab child
*
* @return the tab index
*/
public int getTabIndex(Element child) {
int index = 0;
for (Widget tab : m_tabPanel) {
if (tab.getElement().isOrHasChild(child)) {
return index;
}
index++;
}
return -1;
}
/**
* Returns the tab text for a given tab.
*
* @param pos the index of the tab
*
* @return the text of the tab
*/
public String getTabText(int pos) {
return m_tabPanel.getTabWidget(pos).getElement().getInnerText();
}
/**
* Returns the tab widget.
* This will not be the tab content but the tab itself.
*
* @param index the tab index
*
* @return the tab widget
*/
public Widget getTabWidget(int index) {
return m_tabPanel.getTabWidget(index);
}
/**
* Gets the child widget at the specified index.
*
* Wrapper function for {@link com.google.gwt.user.client.ui.TabLayoutPanel#getWidget(int)}
*
* @param tabIndex the child widget's index
* @return the child widget
*/
@SuppressWarnings("unchecked")
public E getWidget(int tabIndex) {
return (E)m_tabPanel.getWidget(tabIndex);
}
/**
* Inserts a widget into the panel. If the Widget is already attached, it will be moved to the requested index.
*
* Wrapper function for {@link com.google.gwt.user.client.ui.TabLayoutPanel#insert(Widget, String, int)}
*
* @param tabContent the widget to be added
* @param tabName the text to be shown on its tab
* @param beforeIndex the index before which it will be inserted
*/
public void insert(E tabContent, String tabName, int beforeIndex) {
m_tabPanel.insert(tabContent, tabName, beforeIndex);
m_tabPanel.checkTabOverflow();
}
/**
* Returns true
if the tab with the given index is disabled, false
otherwise.
*
* @param tabIndex the tab index
*
* @return true
if the tab with the given index is disabled, false
otherwise
*/
public boolean isDisabledTab(int tabIndex) {
return m_disabledTabIndexes.containsKey(new Integer(tabIndex));
}
/**
* Returns an iterator over all tabs.
*
* @return the iterator
*/
@SuppressWarnings("unchecked")
public Iterator iterator() {
return (Iterator)m_tabPanel.iterator();
}
/**
* @see org.opencms.gwt.client.I_CmsDescendantResizeHandler#onResizeDescendant()
*/
public void onResizeDescendant() {
if (m_autoResize) {
Widget w = m_tabPanel.getWidget(getSelectedIndex());
if (w instanceof CmsTabContentWrapper) {
w = ((CmsTabContentWrapper)w).getWidget();
}
int h = w.getOffsetHeight() + m_autoResizeHeightDelta;
setHeight(h + "px");
}
}
/**
* Removes the tab with the given index.
*
* @param tabIndex the index of the tab which should be removed
*/
public void removeTab(int tabIndex) {
m_tabPanel.remove(tabIndex);
m_tabPanel.checkTabOverflow();
}
/**
* Delegate method.
*
* @see com.google.gwt.user.client.ui.TabLayoutPanel#selectTab(Widget index)
*
* @param tabWidget the tab widget to select
*/
public void selectTab(E tabWidget) {
m_tabPanel.selectTab(tabWidget);
}
/**
* Delegate method.
*
* @see com.google.gwt.user.client.ui.TabLayoutPanel#selectTab(Widget index)
*
* @param tabWidget the tab widget to select
* @param fireEvent true
to fire the tab event
*/
public void selectTab(E tabWidget, boolean fireEvent) {
m_tabPanel.selectTab(tabWidget, fireEvent);
}
/**
* Delegate method.
*
* @see com.google.gwt.user.client.ui.TabLayoutPanel#selectTab(int index)
*
* @param tabIndex the index of the tab to be selected
*/
public void selectTab(int tabIndex) {
m_tabPanel.selectTab(tabIndex);
}
/**
* Delegate method.
*
* @see com.google.gwt.user.client.ui.TabLayoutPanel#selectTab(int index)
*
* @param tabIndex the index of the tab to be selected
* @param fireEvent true
to fire the tab event
*/
public void selectTab(int tabIndex, boolean fireEvent) {
m_tabPanel.selectTab(tabIndex, fireEvent);
}
/**
* Enables or disables auto-resizing.
*
* @param autoResize the auto resize flag value
*/
public void setAutoResize(boolean autoResize) {
m_autoResize = autoResize;
}
/**
* Sets a value which is added to the height of a tab content to change the tabbed panel height.
*
* @param heightDelta the height difference
*/
public void setAutoResizeHeightDelta(int heightDelta) {
m_autoResizeHeightDelta = heightDelta;
}
/**
* Sets the text of a given tab.
*
* @param pos the index of the tab
* @param text the new text for the tab
*/
public void setTabText(int pos, String text) {
m_tabPanel.setTabText(pos, text);
}
/**
* Returns the tab layout panel.
*
* @return the tab layout panel
*/
protected TabLayoutPanel getTabPanel() {
return m_tabPanel;
}
/**
* @see com.google.gwt.user.client.ui.Widget#onLoad()
*/
@Override
protected void onLoad() {
super.onLoad();
m_tabPanel.checkTabOverflow();
// force layout after insertion into DOM to deal with IE layout problems
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
public void execute() {
getTabPanel().forceLayout();
}
});
}
/**
* Sets the overflow of the tab layout content's parent to visible.
*/
protected void setOverflowVisibleToContent() {
Element tabRoot = m_tabPanel.getElement();
// set an additional css class for the parent element of the .gwt-TabLayoutPanelTabs element
List tabContentDivs = CmsDomUtil.getElementsByClass(
I_CmsLayoutBundle.INSTANCE.tabbedPanelCss().cmsTabLayoutPanelContent(),
CmsDomUtil.Tag.div,
tabRoot);
tabContentDivs.addAll(
CmsDomUtil.getElementsByClass("gwt-TabLayoutPanelContentContainer", CmsDomUtil.Tag.div, tabRoot));
for (Element e : tabContentDivs) {
e.getParentElement().getStyle().setOverflow(Overflow.VISIBLE);
}
}
/**
* Returns the tab element for the given index.
*
* @param tabIndex the tab index to get the tab element for
*
* @return the tab element for the given index
*/
private Element getTabElement(int tabIndex) {
Element tabRootEl = m_tabPanel.getElement();
// set an additional css class for the parent element of the .gwt-TabLayoutPanelTabs element
List tabDivs = CmsDomUtil.getElementsByClass(
I_CmsLayoutBundle.INSTANCE.tabbedPanelCss().cmsTabLayoutPanelTab(),
CmsDomUtil.Tag.div,
tabRootEl);
if ((tabDivs != null) && (tabDivs.size() > tabIndex)) {
return tabDivs.get(tabIndex);
}
return null;
}
}