org.web4thejob.web.util.ToolbarRenderer Maven / Gradle / Ivy
/*
* Copyright (c) 2012-2013 Veniamin Isaias.
*
* This file is part of web4thejob.
*
* Web4thejob 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 3 of the License, or any later version.
*
* Web4thejob 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.
*
* You should have received a copy of the GNU Lesser General Public License
* along with web4thejob. If not, see .
*/
package org.web4thejob.web.util;
import org.springframework.context.annotation.Scope;
import org.web4thejob.command.*;
import org.web4thejob.message.Message;
import org.web4thejob.message.MessageAware;
import org.web4thejob.setting.SettingEnum;
import org.web4thejob.web.panel.BorderedLayoutPanel;
import org.web4thejob.web.panel.HtmlViewPanel;
import org.web4thejob.web.panel.PlaceholderPanel;
import org.zkoss.zk.ui.Component;
import org.zkoss.zul.Panel;
import org.zkoss.zul.Separator;
import org.zkoss.zul.Space;
import org.zkoss.zul.Toolbar;
import java.util.*;
/**
* @author Veniamin Isaias
* @since 1.0.0
*/
@org.springframework.stereotype.Component
@Scope("prototype")
public class ToolbarRenderer implements CommandRenderer {
// ------------------------------ FIELDS ------------------------------
private static final CommandsSorter COMMANDS_SORTER = new CommandsSorter();
private final Set commandOwners = new LinkedHashSet(0);
private Component container;
private Toolbar toolbar;
private String align;
private boolean supressed;
// --------------------- GETTER / SETTER METHODS ---------------------
@Override
public String getAlign() {
return align;
}
@Override
public void setAlign(String align) {
this.align = align;
}
@Override
public boolean isSupressed() {
return supressed;
}
// ------------------------ INTERFACE METHODS ------------------------
// --------------------- Interface CommandRenderer ---------------------
@Override
public void render() {
final boolean isEmpty = isEmpty();
if (toolbar != null && isEmpty) {
reset();
return;
} else if (toolbar != null || isEmpty) {
return;
}
toolbar = new Toolbar();
toolbar.setAlign(align);
container.insertBefore(toolbar, container.getFirstChild());
if (!HtmlViewPanel.class.isInstance(getPrimaryOwner())) {
toolbar.setStyle("border-width: 0;");
}
SortedMap> map = mergeCommands();
for (final CommandEnum id : map.keySet()) {
CommandDecorator commandDecorator = null;
if (map.get(id).size() == 1) {
commandDecorator = getDecorator(map.get(id).get(0));
} else {
for (Command command : map.get(id)) {
if (commandDecorator == null) {
commandDecorator = new DefaultDropdownCommandDecorator(command);
} else {
((DropdownCommandDecorator) commandDecorator).add(command);
}
}
}
if (id.isRequiresStartSeparator() && id != map.firstKey() && !isPreviousSeparator()) {
addSeparator();
}
if (commandDecorator != null) {
commandDecorator.attach(toolbar);
commandDecorator.addMessageListener(this);
commandDecorator.render();
}
if (id.isRequiresEndSeparator() && id != map.lastKey()) {
addSeparator();
}
Space space = new Space();
space.setSpacing("8px");
space.setParent(toolbar);
}
}
private boolean isPreviousSeparator() {
Component component = toolbar.getLastChild();
while (component != null) {
if (Space.class.isInstance(component)) {
component = component.getPreviousSibling();
} else {
break;
}
}
return Separator.class.isInstance(component);
}
private void addSeparator() {
Separator separator = new Separator("vertical");
separator.setParent(toolbar);
separator.setSclass("z-toolbarbutton");
separator.setBar(true);
}
@Override
public void reset() {
if (toolbar != null) {
List decorators = new ArrayList();
for (Object item : toolbar.getChildren()) {
CommandDecorator decorator = ((CommandDecorator) ((Component) item).getAttribute(CommandDecorator
.ATTRIB_DECORATOR));
if (decorator != null) {
decorators.add(decorator);
}
}
for (CommandDecorator decorator : decorators) {
decorator.dettach();
}
toolbar.detach();
toolbar = null;
}
}
@Override
public void setContainer(Object container) {
if (this.container != null) throw new IllegalStateException("container can only be set once");
if (container instanceof Panel) {
container = ((Panel) container).getPanelchildren();
}
this.container = (Component) container;
}
@Override
public void supress(boolean supress) {
if (supressed != supress) {
supressed = supress;
reset();
}
}
@Override
public void addCommandOwner(CommandAware commandAware) {
commandOwners.add(commandAware);
}
@Override
public void removeCommandOwner(CommandAware commandAware) {
commandOwners.remove(commandAware);
}
@Override
public Set getCommandOwners() {
return Collections.unmodifiableSet(commandOwners);
}
// --------------------- Interface MessageAware ---------------------
@Override
public boolean addMessageListener(MessageAware messageAware) {
throw new UnsupportedOperationException();
}
@Override
public void dispatchMessage(Message message) {
processMessage(message);
}
@Override
public boolean removeMessageListener(MessageAware messageAware) {
throw new UnsupportedOperationException();
}
@Override
public Set getListeners() {
throw new UnsupportedOperationException();
}
// --------------------- Interface MessageListener ---------------------
@Override
public void processMessage(Message message) {
switch (message.getId()) {
case AFTER_ADD:
reset();
render();
break;
case AFTER_REMOVE:
if (toolbar != null && isEmpty()) {
reset();
}
break;
default:
break;
}
}
// -------------------------- OTHER METHODS --------------------------
private CommandDecorator getDecorator(Command command) {
if (CommandEnum.QUERY_LOOKUP == command.getId()) {
return new QueryLookupCommandDecorator(command);
} else if (CommandEnum.RENDER_SCHEME_LOOKUP == command.getId()) {
return new RenderSchemeLookupCommandDecorator(command);
} else if (CommandEnum.RELATED_PANELS == command.getId()) {
return new DefaultArbitraryDropdownCommandDecorator(command);
} else if (!command.getId().getSubcommands().isEmpty()) {
return new DefaultSubcommandsCommandDecorator(command);
} else {
return new DefaultToolbarbuttonCommandDecorator(command);
}
}
private boolean isEmpty() {
CommandAware primaryOwner = getPrimaryOwner();
if (primaryOwner.hasCommand(CommandEnum.DESIGN) || primaryOwner.hasCommand(CommandEnum.LOCALIZE) ||
(!primaryOwner.isCommandsSupressed() && !primaryOwner.getCommands().isEmpty())) {
return false;
} else if (!primaryOwner.isCommandsSupressed()) {
for (CommandAware owner : commandOwners) {
if (owner instanceof CommandMerger) {
if (!((CommandMerger) owner).getMergedCommands().isEmpty()) {
return false;
}
} else {
if (!owner.getCommands().isEmpty()) {
return false;
}
}
}
}
return true;
}
@Override
public CommandAware getPrimaryOwner() {
if (!commandOwners.isEmpty()) {
return commandOwners.iterator().next();
}
return null;
}
protected boolean isMergable(Command command) {
boolean isPrimaryOwner = command.getOwner().equals(getPrimaryOwner());
if (supressed && command.getId() != CommandEnum.DESIGN && command.getId() != CommandEnum.LOCALIZE) {
// always show settiings and localization commands
return false;
} else if ((command.getId() == CommandEnum.DESIGN || command.getId() == CommandEnum.LOCALIZE) &&
!isPrimaryOwner) {
// don't integrate settings and localization command for child panels
return false;
} else if (command instanceof Subcommand) {
return false;
} else if (!isPrimaryOwner && command.getId().isCrud() && command.getOwner() instanceof org.web4thejob.web.panel
.Panel) {
// special toolbar rendering hint
if (getPrimaryOwner() instanceof BorderedLayoutPanel && command.getArg(CommandMerger
.ATTRIB_COMMAND_MERGER, CommandMerger.class) != null) {
CommandMerger commandMerger = command.getArg(CommandMerger.ATTRIB_COMMAND_MERGER, CommandMerger.class);
if (commandMerger.equals(((BorderedLayoutPanel) getPrimaryOwner()).getNorth())) {
return !((BorderedLayoutPanel) getPrimaryOwner()).getSettingValue(SettingEnum
.NORTH_EXCLUDE_CRUD_COMMANDS, false);
} else if (commandMerger.equals(((BorderedLayoutPanel) getPrimaryOwner()).getSouth())) {
return !((BorderedLayoutPanel) getPrimaryOwner()).getSettingValue(SettingEnum
.SOUTH_EXCLUDE_CRUD_COMMANDS, false);
} else if (commandMerger.equals(((BorderedLayoutPanel) getPrimaryOwner()).getCenter())) {
return !((BorderedLayoutPanel) getPrimaryOwner()).getSettingValue(SettingEnum
.CENTER_EXCLUDE_CRUD_COMMANDS, false);
} else if (commandMerger.equals(((BorderedLayoutPanel) getPrimaryOwner()).getWest())) {
return !((BorderedLayoutPanel) getPrimaryOwner()).getSettingValue(SettingEnum
.WEST_EXCLUDE_CRUD_COMMANDS, false);
} else if (commandMerger.equals(((BorderedLayoutPanel) getPrimaryOwner()).getEast())) {
return !((BorderedLayoutPanel) getPrimaryOwner()).getSettingValue(SettingEnum
.EAST_EXCLUDE_CRUD_COMMANDS, false);
}
} else {
Object val = (((org.web4thejob.web.panel.Panel) command.getOwner()).getAttribute(CommandRenderer
.ATTRIB_SUPPRESS_CRUD_COMMANDS));
if (val instanceof Boolean) {
return !((Boolean) val);
}
}
}
return true;
}
private SortedMap> mergeCommands() {
SortedMap> map = new TreeMap>(COMMANDS_SORTER);
for (CommandAware owner : commandOwners) {
if (owner instanceof PlaceholderPanel && !owner.equals(getPrimaryOwner())) {
continue;
}
SortedSet commands;
if (owner instanceof CommandMerger) {
commands = ((CommandMerger) owner).getMergedCommands();
} else {
commands = owner.getCommands();
}
for (final Command command : commands) {
if (isMergable(command)) {
if (map.containsKey(command.getId())) {
if (!map.get(command.getId()).contains(command)) {
map.get(command.getId()).add(command);
}
} else {
List list = new ArrayList();
list.add(command);
map.put(command.getId(), list);
}
}
}
}
return map;
}
private static class CommandsSorter implements Comparator {
@Override
public int compare(CommandEnum o1, CommandEnum o2) {
Integer i1 = (o1.getSubcommands().isEmpty() ? 10000 : 0) + o1.ordinal();
Integer i2 = (o2.getSubcommands().isEmpty() ? 10000 : 0) + o2.ordinal();
return i1.compareTo(i2);
}
}
}