Skip to content

Instantly share code, notes, and snippets.

@alump
Created May 8, 2017 20:43
Show Gist options
  • Save alump/21234dbc45a612ba00b200eef714c395 to your computer and use it in GitHub Desktop.
Save alump/21234dbc45a612ba00b200eef714c395 to your computer and use it in GitHub Desktop.
package org.vaadin.alump.extendedtabsheet.demo;
import com.vaadin.icons.VaadinIcons;
import com.vaadin.server.Resource;
import com.vaadin.shared.ui.tabsheet.TabsheetClientRpc;
import com.vaadin.ui.Component;
import com.vaadin.ui.Label;
import com.vaadin.ui.TabSheet;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* Tab Sheet with plus tab for adding new tabs. Allows to close tabs if there are more than 1 open tab. Should not be
* used without any actual tabs.
*/
public class TabSheetWithAdd extends TabSheet {
private Tab plusTab;
private boolean plusTabEnabled = true;
private AddTabHandler addTabHandler;
@FunctionalInterface
public interface AddTabHandler {
/**
* Method called when user has clicked "new tab" tab
* @param source TabSheet that was clicked
* @return Tab handler added to Tabsheet, receive this by calling addTab method
*/
Tab newTabRequested(TabSheetWithAdd source);
}
public TabSheetWithAdd() {
super();
addStyleName("tabsheet-with-add");
super.setCloseHandler(this::onClose);
}
public TabSheetWithAdd(AddTabHandler addTabHandler) {
this();
setAddTabHandler(Objects.requireNonNull(addTabHandler));
}
@Override
public void attach() {
super.attach();
}
@Override
public void beforeClientResponse(boolean initial) {
updateStateBeforeClientResponse();
super.beforeClientResponse(initial);
}
private void onClose(TabSheet tabSheet, Component component) {
removeComponent(component);
if(getTabs().size() < 2) {
getTabs().stream().forEach(t -> t.setClosable(false));
}
}
protected void updateStateBeforeClientResponse() {
List<Tab> tabs = getTabs();
// Never allow to close the last tab
if(tabs.size() <= 1) {
tabs.stream().forEach(t -> t.setClosable(false));
} else {
tabs.stream().forEach(t -> t.setClosable(true));
}
// Never allow plus tab to be selected
if(plusTab != null && getSelectedTab() == plusTab.getComponent()) {
setSelectedTab(0);
}
}
@Override
public Tab addTab(Component c, String caption) {
removePlusTab();
Tab tab = super.addTab(c, caption);
addPlusTab();
return tab;
}
@Override
public Tab addTab(Component c, String caption, Resource icon) {
removePlusTab();
Tab tab = super.addTab(c, caption, icon);
addPlusTab();
return tab;
}
@Override
public Tab addTab(Component tabComponent, String caption, Resource icon,
int position) {
removePlusTab();
Tab tab = super.addTab(tabComponent, caption, icon, position);
addPlusTab();
return tab;
}
@Override
public Tab addTab(Component component) {
removePlusTab();
Tab tab = super.addTab(component);
addPlusTab();
return tab;
}
@Override
public Tab addTab(Component component, int position) {
removePlusTab();
Tab tab = super.addTab(component, position);
addPlusTab();
return tab;
}
@Override
public void setSelectedTab(Component c) {
if(plusTab != null && c == plusTab.getComponent()) {
if(addTabHandler != null) {
Tab tab = addTabHandler.newTabRequested(this);
if(tab != null) {
setSelectedTab(tab);
} else {
getRpcProxy(TabsheetClientRpc.class).revertToSharedStateSelection();
}
} else {
removePlusTab();
}
} else {
super.setSelectedTab(c);
}
}
protected void removePlusTab() {
if(plusTab != null) {
boolean wasPlusSelected = getSelectedTab() == plusTab.getComponent();
super.removeTab(plusTab);
plusTab = null;
if(wasPlusSelected && getComponentCount() > 0) {
setSelectedTab(0);
}
}
}
protected void addPlusTab() {
removePlusTab();
if(plusTabEnabled) {
plusTab = super.addTab(createPlusComponent(), null, VaadinIcons.PLUS, getComponentCount());
}
}
/**
* Get tabs on TabSheet (plus tab is filtered out of this list)
* @return
*/
public List<Tab> getTabs() {
List<Tab> tabs = new ArrayList<>();
Tab tab = getTab(0);
for(int i = 1; tab != null; ++i) {
if(tab != plusTab) {
tabs.add(tab);
}
tab = getTab(i);
}
return tabs;
}
/**
* Get filtered list of children inside tabs
* @return
*/
public List<Component> getTabChildren() {
return getTabs().stream().map(t -> t.getComponent()).collect(Collectors.toList());
}
/**
* Add new handler for New tab requests
* @param addTabHandler Handler used to add new tabs
*/
public void setAddTabHandler(AddTabHandler addTabHandler) {
this.addTabHandler = addTabHandler;
}
/**
* Component placed inside close tab, it should not be shown to user evernd
* @return
*/
protected Component createPlusComponent() {
return new Label("User should not see this");
}
public void setPlusTabEnabled(boolean enabled) {
plusTabEnabled = enabled;
addPlusTab();
}
public boolean isPlusTabEnabled() {
return plusTabEnabled;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment