Implementing the ApplicationLayout interface
The next step is to implement the ApplicationLayout interface and add the required methods:
- void addHeaderComponent(Component)
- void addWorkingAreaComponent(WorkingAreaComponent)
- Collection<Component> getHeaderComponents()
- Collection<WorkingAreaComponent> getWorkingAreaComponents()
- void addMenuOption(MenuOption, SerializableConsumer<MenuOption>)
Implementing the addHeaderComponent(Component) method is quite straightforward:
@Override
public void addHeaderComponent(Component component) {
component.setWidth(null);
header.addComponent(component);
header.setComponentAlignment(component,
Alignment.MIDDLE_RIGHT);
}
The addWorkingAreaComponent(WorkingAreaComponent) method should avoid adding two tabs with the same caption. Instead of adding the same tab twice it should select the corresponding existing tab. A Collection is used to keep track of the added components, as shown in the following code:
public class TabBasedApplicationLayout extends CustomComponent
implements ApplicationLayout {
...
private Collection<WorkingAreaComponent> workingAreaComponents
= new HashSet<>();
@Override
public void addWorkingAreaComponent(WorkingAreaComponent
component) {
addWorkingAreaComponent(component, true);
}
public void addWorkingAreaComponent(WorkingAreaComponent
component, boolean closable) {
if (!workingAreaComponents.contains(component)) {
TabSheet.Tab tab = tabSheet.addTab(
component.getComponent(),
component.getCaption());
tab.setClosable(closable);
tabSheet.setSelectedTab(tab);
workingAreaComponents.add(component);
} else {
showComponent(component.getCaption());
}
}
public void showComponent(String caption) {
IntStream.range(0, tabSheet.getComponentCount())
.mapToObj(tabSheet::getTab)
.filter(tab -> tab.getCaption().equals(caption))
.forEach(tabSheet::setSelectedTab);
}
}
Because this concrete implementation is based on a TabSheet where each tab can or cannot be closed, it makes sense to overload the ApplicationLayout.addWorkingAreaComponent(WorkingAreaComponent) method to allow clients to specify this behavior.
An interesting part of the previous code is the showComponent(String) method, which selects a tab by its caption. This method uses an IntStream to loop through the tabs in the TabSheet. This method is equivalent to the following one:
public void showComponent(String caption) {
for(int i = 0; i < tabSheet.getComponentCount(); i++) {
TabSheet.Tab tab = tabSheet.getTab(i);
if(tab.getCaption().equals(caption)) {
tabSheet.setSelectedTab(tab);
}
}
}
The next method to implement is getHeaderComponents():
@Override
public Collection<Component> getHeaderComponents() {
return IntStream.range(0, header.getComponentCount())
.mapToObj(header::getComponent)
.collect(Collectors.toList());
}
This method uses an IntStream similar to the one in the showComponent(String) method. A Collector is used to create a List containing all the components in the header.
Since we already have a Collection object with all the components in the working area, the getWorkingAreaComponents() method implementation is just a regular getter:
@Override
public Collection<WorkingAreaComponent> getWorkingAreaComponents() {
return workingAreaComponents;
}