/*
*
* * Copyright (c) 2016. David Sowerby
* *
* * 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 uk.q3c.krail.core.view.component;
import com.google.inject.Inject;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.themes.BaseTheme;
import net.engio.mbassy.listener.Handler;
import net.engio.mbassy.listener.Listener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import uk.q3c.krail.core.eventbus.SessionBus;
import uk.q3c.krail.core.eventbus.SubscribeTo;
import uk.q3c.krail.core.eventbus.UIBus;
import uk.q3c.krail.core.i18n.LocaleChangeBusMessage;
import uk.q3c.krail.core.navigate.Navigator;
import uk.q3c.krail.core.navigate.sitemap.UserSitemap;
import uk.q3c.krail.core.navigate.sitemap.UserSitemapNode;
import uk.q3c.util.ID;
import uk.q3c.util.NodeFilter;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
@Listener
@SubscribeTo({UIBus.class, SessionBus.class})
public abstract class NavigationButtonPanel extends HorizontalLayout implements
Button.ClickListener {
private static Logger log = LoggerFactory.getLogger(NavigationButtonPanel.class);
private final List<NavigationButton> buttons = new ArrayList<>();
private final LinkedList<NodeFilter<UserSitemapNode>> sourceFilters = new LinkedList<>();
private final Navigator navigator;
private final UserSitemap sitemap;
protected boolean rebuildRequired = true;
@Inject
protected NavigationButtonPanel(Navigator navigator, UserSitemap sitemap) {
this.navigator = navigator;
this.sitemap = sitemap;
this.setSizeUndefined();
this.setSpacing(true);
String id = ID.getId(Optional.empty(), this);
setId(id);
}
public void moveToNavigationState() {
log.debug("moving to navigation state");
rebuildRequired = true;
build();
}
protected abstract void build();
/**
* Displays buttons to represent the supplied nodes.
*
* @param nodeList
* contains the list of buttons to display. It is assumed that these are in the right order
*/
protected void organiseButtons(List<UserSitemapNode> nodeList) {
log.debug("{} nodes to display before filtering", nodeList.size());
List<UserSitemapNode> filteredList = filteredList(nodeList);
log.debug("{} nodes to display after filtering", filteredList.size());
int maxIndex = (filteredList.size() > buttons.size() ? filteredList.size() : buttons.size());
for (int i = 0; i < maxIndex; i++) {
// nothing left in chain
if (i + 1 > filteredList.size()) {
// but buttons still exist
if (i < buttons.size()) {
buttons.get(i)
.setVisible(false);
}
} else {
// chain continues
NavigationButton button = null;
// steps still exist, re-use
if (i < buttons.size()) {
button = buttons.get(i);
} else {
button = createButton();
}
setupButton(button, filteredList.get(i));
}
}
}
protected NavigationButton createButton() {
NavigationButton button = new NavigationButton();
button.addStyleName(BaseTheme.BUTTON_LINK);
button.addClickListener(this);
buttons.add(button);
String id = ID.getId(Optional.of(buttons.size() - 1), this, button);
button.setId(id);
this.addComponent(button);
return button;
}
private void setupButton(NavigationButton button, UserSitemapNode sitemapNode) {
button.setNode(sitemapNode);
button.setVisible(true);
}
protected List<UserSitemapNode> filteredList(List<UserSitemapNode> list) {
List<UserSitemapNode> newList = new ArrayList<>();
for (UserSitemapNode node : list) {
boolean accept = true;
for (NodeFilter<UserSitemapNode> filter : sourceFilters) {
if (!filter.accept(node)) {
accept = false;
break;
}
}
if (accept) {
newList.add(node);
}
}
return newList;
}
@Handler
public void localeChanged(LocaleChangeBusMessage busMessage) {
log.debug("responding to locale change to {}", busMessage.getNewLocale());
for (NavigationButton button : buttons) {
button.setCaption(button.getNode()
.getLabel());
}
}
@Handler
public void afterViewChange(AfterViewChangeBusMessage busMessage) {
log.debug("Responding to view change");
rebuildRequired = true;
build();
}
public List<NavigationButton> getButtons() {
return buttons;
}
@Override
public void buttonClick(ClickEvent event) {
NavigationButton button = (NavigationButton) event.getButton();
navigator.navigateTo(button.getNode());
}
public Navigator getNavigator() {
return navigator;
}
public UserSitemap getSitemap() {
return sitemap;
}
public void addFilter(NodeFilter<UserSitemapNode> filter) {
sourceFilters.add(filter);
}
public void removeFilter(NodeFilter<UserSitemapNode> filter) {
sourceFilters.remove(filter);
}
public boolean isRebuildRequired() {
return rebuildRequired;
}
}