Java tutorial
/* * Copyright (c) 2008-2017 Haulmont. * * 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.haulmont.cuba.web.toolkit.ui; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import com.haulmont.cuba.core.global.AppBeans; import com.haulmont.cuba.core.global.Configuration; import com.haulmont.cuba.web.App; import com.haulmont.cuba.web.WebConfig; import com.haulmont.cuba.web.WebWindowManager; import com.haulmont.cuba.web.gui.components.mainwindow.WebAppWorkArea; import com.vaadin.event.Action; import com.vaadin.event.FieldEvents; import com.vaadin.server.ErrorMessage; import com.vaadin.server.Resource; import com.vaadin.ui.*; import fi.jasoft.dragdroplayouts.client.ui.LayoutDragMode; import java.io.Serializable; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.BiConsumer; import static com.haulmont.cuba.web.toolkit.ui.ContentSwitchMode.HIDE; import static com.haulmont.cuba.web.toolkit.ui.ContentSwitchMode.UNLOAD; public class CubaManagedTabSheet extends CssLayout implements Component.Focusable, FieldEvents.FocusNotifier, FieldEvents.BlurNotifier, HasTabSheetBehaviour { private static final long serialVersionUID = 1425920612516520121L; protected static final String MANAGED_TABSHEET_STYLENAME = "c-managed-tabsheet"; protected static final String HIDDEN_TAB = "hidden-tab"; protected static final String VISIBLE_TAB = "visible-tab"; protected static final Method SELECTED_TAB_CHANGE_METHOD; protected ManagedMainTabSheetMode tabSheetMode = ManagedMainTabSheetMode.HIDE_TABS; static { try { SELECTED_TAB_CHANGE_METHOD = SelectedTabChangeListener.class.getDeclaredMethod("selectedTabChange", SelectedTabChangeEvent.class); } catch (final java.lang.NoSuchMethodException e) { throw new java.lang.RuntimeException("Internal error finding methods in CubaManagedTabSheet"); } } protected final CubaTabSheet tabbedHeader; protected final TabSheetBehaviour behaviour; // tabbedHeader Label to TabImpl protected final BiMap<Component, Component> tabToContentMap = HashBiMap.create(); // Content CssLayout to TabImpl protected final Map<Component, Tab> tabs = new HashMap<>(); protected final Map<String, Tab> tabIds = new HashMap<>(); protected final List<Component> tabComponents = new ArrayList<>(); protected Component selected = null; protected CloseHandler closeHandler; public CubaManagedTabSheet() { setPrimaryStyleName(MANAGED_TABSHEET_STYLENAME); setSizeFull(); setImmediate(true); tabSheetMode = AppBeans.get(Configuration.class).getConfig(WebConfig.class).getManagedMainTabSheetMode(); closeHandler = (tabSheet1, tabContent) -> _closeTab(tabContent); tabbedHeader = new CubaTabSheet() { @Override protected Component getActionTarget(Tab tab) { return getContentTab(tab.getComponent()).getComponent(); } }; tabbedHeader.setVisible(false); tabbedHeader.addStyleName("framed padded-tabbar"); tabbedHeader.setCloseHandler((tabsheet, tabContent) -> closeHandler.onTabClose(CubaManagedTabSheet.this, getContentTab(tabContent).getComponent())); tabbedHeader.addSelectedTabChangeListener(event -> { setSelected(tabToContentMap.get(tabbedHeader.getSelectedTab())); fireSelectedTabChange(); }); addComponent(tabbedHeader); behaviour = new TabSheetBehaviourImpl(this); } @Override public void removeComponent(Component c) { Tab tab = tabs.get(c); //noinspection RedundantCast Component tabComponent = getTabComponent((Component) tab); tabToContentMap.inverse().remove(tab); tabIds.remove(tab.getId()); tabs.remove(c); tabbedHeader.removeComponent(tabComponent); tabComponents.remove(c); ((TabImpl) tab).setCloseHandler(null); super.removeComponent(((TabImpl) tab)); } protected TabImpl getContentTab(Component tabContent) { return (TabImpl) tabToContentMap.get(tabContent); } protected Component getTabComponent(Component contentComponent) { return tabToContentMap.inverse().get(contentComponent); } protected void _closeTab(Component tabContent) { CloseHandler closeHandler = ((TabImpl) tabs.get(tabContent)).getCloseHandler(); closeHandler.onTabClose(this, tabContent); } @Override public TabSheetBehaviour getTabSheetBehaviour() { return behaviour; } public Tab addTab(Component c, String caption, Resource icon) { return addTab(c, caption, icon, tabComponents.size()); } public Tab addTab(Component tabComponent, String caption, Resource icon, int position) { if (tabComponent == null) return null; TabImpl tab = new TabImpl(tabComponent); Label tabbarTabComponent = new Label(); tabToContentMap.put(tabbarTabComponent, tab); tabs.put(tabComponent, tab); TabSheet.Tab tabbarTab = tabbedHeader.addTab(tabbarTabComponent, caption, icon, position); tab.setTabbarTab(tabbarTab); addComponent(tab); tabbedHeader.setVisible(true); if (tabComponents.isEmpty()) setSelected(tab); tabComponents.add(position, tabComponent); return tab; } protected void setSelected(Component component) { if (component == null || component == selected) return; if (selected != null) unselectTab(selected); selected = component; selectTab(component); tabbedHeader.setSelectedTab(getTabComponent(component)); } protected void unselectTab(Component component) { ContentSwitchMode switchMode = ((TabImpl) component).getContentSwitchMode(); if (switchMode == ContentSwitchMode.HIDE) { hideTabContent(component); return; } else if (switchMode == ContentSwitchMode.UNLOAD) { unloadTabContent(component); return; } if (tabSheetMode == ManagedMainTabSheetMode.HIDE_TABS) { hideTabContent(component); } else { unloadTabContent(component); } } protected void unloadTabContent(Component component) { super.removeComponent(component); } protected void hideTabContent(Component component) { component.removeStyleName(VISIBLE_TAB); component.addStyleName(HIDDEN_TAB); } protected void selectTab(Component component) { ContentSwitchMode contentSwitchMode = ((TabImpl) component).getContentSwitchMode(); if (contentSwitchMode == HIDE) { showTabContent(component); return; } else if (contentSwitchMode == UNLOAD) { loadTabContent(component); return; } if (tabSheetMode == ManagedMainTabSheetMode.HIDE_TABS) { showTabContent(component); } else { loadTabContent(component); } } protected void loadTabContent(Component component) { // in case of new tab it will be added later if (!components.contains(component) && tabComponents.contains(((TabImpl) component).getComponent())) { addComponent(component); } } protected void showTabContent(Component component) { component.removeStyleName(HIDDEN_TAB); component.addStyleName(VISIBLE_TAB); } public void setSelectedTab(Tab tab) { if (tab != null) { setSelected((Component) tab); } } @Override public void replaceComponent(Component oldComponent, Component newComponent) { Tab tab = tabs.get(oldComponent); if (tab != null) { ((TabImpl) tab).setComponent(newComponent); } } public void closeTab(Component tab) { if (closeHandler != null) { closeHandler.onTabClose(this, tab); } } public void closeOtherTabs(Component currentTab) { WebWindowManager windowManager = App.getInstance().getWindowManager(); windowManager.closeAllTabbedWindowsExcept((ComponentContainer) currentTab); } public void closeAllTabs() { WebWindowManager windowManager = App.getInstance().getWindowManager(); windowManager.closeAllTabbedWindows(); } @Override public void setStyleName(String style) { tabbedHeader.addStyleName(style); } public void setDragMode(LayoutDragMode mode) { tabbedHeader.setDragMode(mode); } public void setDropHandler(WebAppWorkArea.TabSheetReorderingDropHandler dropHandler) { tabbedHeader.setDropHandler(dropHandler); } public void addActionHandler(Action.Handler actionHandler) { tabbedHeader.addActionHandler(actionHandler); } public static class SelectedTabChangeEvent extends Component.Event { public SelectedTabChangeEvent(Component source) { super(source); } public CubaManagedTabSheet getTabSheet() { return (CubaManagedTabSheet) getSource(); } } public interface SelectedTabChangeListener extends Serializable { void selectedTabChange(CubaManagedTabSheet.SelectedTabChangeEvent event); } public void addSelectedTabChangeListener(CubaManagedTabSheet.SelectedTabChangeListener listener) { addListener(CubaManagedTabSheet.SelectedTabChangeEvent.class, listener, SELECTED_TAB_CHANGE_METHOD); } @Deprecated public void addListener(CubaManagedTabSheet.SelectedTabChangeListener listener) { addSelectedTabChangeListener(listener); } public void removeSelectedTabChangeListener(CubaManagedTabSheet.SelectedTabChangeListener listener) { removeListener(CubaManagedTabSheet.SelectedTabChangeEvent.class, listener, SELECTED_TAB_CHANGE_METHOD); } @Deprecated public void removeListener(CubaManagedTabSheet.SelectedTabChangeListener listener) { removeSelectedTabChangeListener(listener); } protected void fireSelectedTabChange() { fireEvent(new CubaManagedTabSheet.SelectedTabChangeEvent(this)); } public interface CloseHandler extends Serializable { void onTabClose(final CubaManagedTabSheet tabSheet, final Component tabContent); } @Override public void addBlurListener(FieldEvents.BlurListener listener) { addListener(FieldEvents.BlurEvent.EVENT_ID, FieldEvents.BlurEvent.class, listener, FieldEvents.BlurListener.blurMethod); } @Override @Deprecated public void addListener(FieldEvents.BlurListener listener) { addBlurListener(listener); } @Override public void removeBlurListener(FieldEvents.BlurListener listener) { removeListener(FieldEvents.BlurEvent.EVENT_ID, FieldEvents.BlurEvent.class, listener); } @Override @Deprecated public void removeListener(FieldEvents.BlurListener listener) { removeBlurListener(listener); } @Override public void addFocusListener(FieldEvents.FocusListener listener) { addListener(FieldEvents.FocusEvent.EVENT_ID, FieldEvents.FocusEvent.class, listener, FieldEvents.FocusListener.focusMethod); } @Override @Deprecated public void addListener(FieldEvents.FocusListener listener) { addFocusListener(listener); } @Override public void removeFocusListener(FieldEvents.FocusListener listener) { removeListener(FieldEvents.FocusEvent.EVENT_ID, FieldEvents.FocusEvent.class, listener); } @Override @Deprecated public void removeListener(FieldEvents.FocusListener listener) { removeFocusListener(listener); } @Override public void focus() { tabbedHeader.focus(); } @Override public int getTabIndex() { return tabbedHeader.getTabIndex(); } @Override public void setTabIndex(int tabIndex) { tabbedHeader.setTabIndex(tabIndex); } public interface Tab extends Serializable { void setId(String id); String getId(); Resource getIcon(); void setIcon(Resource icon); String getDescription(); void setDescription(String description); String getCaption(); void setCaption(String caption); boolean isEnabled(); void setEnabled(boolean enabled); boolean isVisible(); void setVisible(boolean visible); boolean isClosable(); void setClosable(boolean closable); String getStyleName(); void setStyleName(String styleName); void setComponentError(ErrorMessage componentError); ErrorMessage getComponentError(); Component getComponent(); } public static class TabImpl extends CssLayout implements Tab { protected String id; protected static final String MANAGED_TAB_STYLENAME = "c-managed-tab"; protected CloseHandler closeHandler; protected boolean closable; protected Component component; protected TabSheet.Tab tabbarTab; protected ContentSwitchMode contentSwitchMode = ContentSwitchMode.DEFAULT; protected TabImpl(Component component) { this.component = component; addComponent(component); setSizeFull(); setPrimaryStyleName(MANAGED_TAB_STYLENAME); } protected CloseHandler getCloseHandler() { return closeHandler; } protected void setCloseHandler(CloseHandler closeHandler) { this.closeHandler = closeHandler; } @Override public void setId(String id) { this.id = id; } @Override public String getId() { return id; } @Override public void setEnabled(boolean enabled) { tabbarTab.setEnabled(enabled); } @Override public boolean isEnabled() { return tabbarTab.isEnabled(); } @Override public boolean isVisible() { return tabbarTab.isVisible(); } @Override public void setVisible(boolean visible) { tabbarTab.setVisible(visible); } @Override public void setCaption(String caption) { tabbarTab.setCaption(caption); } @Override public String getCaption() { return tabbarTab.getCaption(); } protected TabSheet.Tab getTabbarTab() { return tabbarTab; } protected void setTabbarTab(TabSheet.Tab tabbarTab) { this.tabbarTab = tabbarTab; } @Override public boolean isClosable() { return closable; } @Override public void setClosable(boolean closable) { this.closable = closable; tabbarTab.setClosable(closable); } @Override public void setStyleName(String style) { super.setStyleName(style); tabbarTab.setStyleName(style); } @Override public void setIcon(Resource icon) { tabbarTab.setIcon(icon); } @Override public Resource getIcon() { return tabbarTab.getIcon(); } @Override public Component getComponent() { return component; } protected void setComponent(Component component) { this.removeComponent(this.component); this.component = component; addComponent(component); } protected void setContentSwitchMode(ContentSwitchMode contentSwitchMode) { this.contentSwitchMode = contentSwitchMode; } protected ContentSwitchMode getContentSwitchMode() { return contentSwitchMode; } } protected static class TabSheetBehaviourImpl implements TabSheetBehaviour { protected final CubaManagedTabSheet tabSheet; public TabSheetBehaviourImpl(CubaManagedTabSheet tabSheet) { this.tabSheet = tabSheet; } @Override public void setTabCaption(String tabId, String caption) { getTabById(tabId).setCaption(caption); } protected Tab getTabById(String tabId) { return tabSheet.tabIds.get(tabId); } @Override public void setTabDescription(String tabId, String description) { getTabById(tabId).setDescription(description); } @Override public Component getTabComponent(String tabId) { return getTabById(tabId).getComponent(); } @Override public void setTabIcon(String tabId, Resource icon) { getTabById(tabId).setIcon(icon); } @Override public void setTabClosable(String tabId, boolean closable) { getTabById(tabId).setClosable(closable); } @Override public void setContentSwitchMode(String tabId, ContentSwitchMode contentSwitchMode) { ((TabImpl) getTabById(tabId)).setContentSwitchMode(contentSwitchMode); } @Override public void setSelectedTab(String tabId) { tabSheet.setSelectedTab(getTabById(tabId)); } @Override public void addTab(Component component, String tabId) { Tab tab = tabSheet.addTab(component, null, null); tab.setId(tabId); tabSheet.tabIds.put(tabId, tab); } @Override public String getTab(Component component) { TabImpl tab = (TabImpl) tabSheet.tabs.get(component); return tab.getId(); } @Override public void closeTab(Component target) { tabSheet.closeTab(target); } @Override public void closeOtherTabs(Component target) { tabSheet.closeOtherTabs(target); } @Override public void closeAllTabs() { tabSheet.closeAllTabs(); } @Override public String getTab(int position) { return tabSheet.tabbedHeader.getTab(position).getId(); } @Override public Component getSelectedTab() { return ((TabImpl) tabSheet.selected).getComponent(); } @Override public void setSelectedTab(Component component) { tabSheet.setSelectedTab(tabSheet.tabs.get(component)); } @Override public void replaceComponent(Component oldComponent, Component newComponent) { tabSheet.tabbedHeader.replaceComponent(oldComponent, newComponent); } @Override public void removeComponent(Component component) { tabSheet.removeComponent(component); } @Override public Component getPreviousTab(Component tab) { return tabSheet.tabbedHeader.getPreviousTab(tab); } @Override public void setTabTestId(String tabId, String testId) { TabImpl tabImpl = (TabImpl) getTabById(tabId); tabSheet.tabbedHeader.setTestId(tabImpl.getTabbarTab(), testId); } @Override public void setTabCubaId(String tabId, String id) { Tab tab = getTabById(tabId); tabSheet.tabbedHeader.setCubaId(((TabImpl) tab).getTabbarTab(), id); } @Override public void setTabCloseHandler(Component tabContent, BiConsumer<HasTabSheetBehaviour, Component> closeHandler) { Tab tab = tabSheet.tabs.get(tabContent); if (tab != null) { ((TabImpl) tab) .setCloseHandler((tabSheet1, tabContent1) -> closeHandler.accept(tabSheet, tabContent1)); } } @Override public int getTabPosition(String tabId) { Tab tab = getTabById(tabId); return tabSheet.tabbedHeader.getTabPosition(((TabImpl) tab).getTabbarTab()); } @Override public int getComponentCount() { return tabSheet.tabbedHeader.getComponentCount(); } @Override public void moveTab(Component c, int position) { Component tabComponent = tabSheet.getTabComponent((Component) tabSheet.tabs.get(c)); tabSheet.tabbedHeader.moveTab(tabComponent, position); } @Override public void focus() { tabSheet.tabbedHeader.focus(); } @Override public void silentCloseTabAndSelectPrevious(Component tab) { Component tabComponent = tabSheet.getTabComponent((Component) tabSheet.tabs.get(tab)); tabSheet.tabbedHeader.silentCloseTabAndSelectPrevious(tabComponent); } } }