org.web4thejob.web.panel.DefaultMenuAuthorizationPanel.java Source code

Java tutorial

Introduction

Here is the source code for org.web4thejob.web.panel.DefaultMenuAuthorizationPanel.java

Source

/*
 * Copyright (c) 2012-2014 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 <http://www.gnu.org/licenses/>.
 */

package org.web4thejob.web.panel;

import nu.xom.Element;
import org.springframework.context.annotation.Scope;
import org.springframework.util.StringUtils;
import org.web4thejob.command.Command;
import org.web4thejob.command.CommandEnum;
import org.web4thejob.context.ContextUtil;
import org.web4thejob.message.Message;
import org.web4thejob.message.MessageArgEnum;
import org.web4thejob.message.MessageEnum;
import org.web4thejob.util.L10nString;
import org.web4thejob.util.XMLUtil;
import org.web4thejob.web.dialog.DefaultValueInputDialog;
import org.web4thejob.web.dialog.ValueInputDialog;
import org.web4thejob.web.panel.base.zk.AbstractZkContentPanel;
import org.web4thejob.web.util.ZkUtil;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.DropEvent;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zul.*;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
 * @author Veniamin Isaias
 * @since 1.0.0
 */

@org.springframework.stereotype.Component
@Scope("prototype")
public class DefaultMenuAuthorizationPanel extends AbstractZkContentPanel
        implements MenuAuthorizationPanel<Treeitem>, EventListener<Event> {
    // ------------------------------ FIELDS ------------------------------

    public static final L10nString L10N_HEADER_PANELS = new L10nString(DefaultMenuAuthorizationPanel.class,
            "list_header_panels", "Panels");
    public static final L10nString L10N_TREE_ITEM_ROOT = new L10nString(DefaultMenuAuthorizationPanel.class,
            "tree_item_root", "Start Menu");
    public static final L10nString L10N_COLUMN_ITEMS = new L10nString(DefaultMenuAuthorizationPanel.class,
            "tree_col_menu_items", "Menu items");

    private static final String ITEM_ROOT = "root";
    private final Treeitem rootItem;
    private final Tree tree;
    private final Listbox listbox;
    private final boolean readOnly;

    // --------------------------- CONSTRUCTORS ---------------------------

    public DefaultMenuAuthorizationPanel() {
        this(true);
    }

    public DefaultMenuAuthorizationPanel(boolean readOnly) {
        Borderlayout regions = new Borderlayout();
        ZkUtil.setParentOfChild((Component) base, regions);
        regions.setWidth("100%");
        regions.setVflex("true");
        this.readOnly = readOnly;
        arrangeForReadOnly();

        final West west = new West();
        west.setParent(regions);
        //west.setFlex(true);
        west.setBorder("none");
        if (!readOnly) {
            west.setWidth("50%");
        } else {
            west.setWidth("100%");
        }
        west.setSplittable(true);
        west.setCollapsible(false);
        west.setOpen(true);
        tree = new Tree();
        tree.setParent(west);
        tree.setVflex("true");
        tree.setHflex("true");
        tree.setSpan(true);
        tree.addEventListener(Events.ON_SELECT, this);

        Treecols treecols = new Treecols();
        treecols.setSizable(true);
        treecols.setParent(tree);
        new Treecol(L10N_COLUMN_ITEMS.toString()).setParent(treecols);

        new Treechildren().setParent(tree);
        rootItem = getNewTreeitem(L10N_TREE_ITEM_ROOT.toString(), null);

        rootItem.setParent(tree.getTreechildren());
        rootItem.setDroppable(ELEMENT_PANEL);
        rootItem.addEventListener(Events.ON_DROP, this);
        rootItem.setAttribute(ITEM_ROOT, true);
        rootItem.setAttribute(ELEMENT_MENU, true);

        if (!readOnly) {
            final Center center = new Center();
            center.setParent(regions);
            center.setBorder("none");
            listbox = new Listbox();
            listbox.setParent(center);
            listbox.setVflex("true");
            listbox.setHflex("true");
            listbox.setSpan(true);
            listbox.addEventListener(Events.ON_SELECT, this);
            final Listhead listhead = new Listhead();
            listhead.setParent(listbox);
            final Listheader header = new Listheader(L10N_HEADER_PANELS.toString());
            header.setParent(listhead);
        } else {
            listbox = null;
        }

        arrangeForState(PanelState.READY);
    }

    protected void arrangeForReadOnly() {
        if (!readOnly) {
            super.registerCommands();
            registerCommand(ContextUtil.getDefaultCommand(CommandEnum.ADD, this));
            registerCommand(ContextUtil.getDefaultCommand(CommandEnum.EDIT, this));
            registerCommand(ContextUtil.getDefaultCommand(CommandEnum.REMOVE, this));
            registerCommand(ContextUtil.getDefaultCommand(CommandEnum.MOVE_LEFT, this));
            registerCommand(ContextUtil.getDefaultCommand(CommandEnum.MOVE_UP, this));
            registerCommand(ContextUtil.getDefaultCommand(CommandEnum.MOVE_DOWN, this));
        }
    }

    @Override
    protected void arrangeForState(PanelState newState) {
        if (!readOnly) {
            super.arrangeForState(newState);
            if (newState == PanelState.FOCUSED) {
                boolean selected = tree.getSelectedItem() != null;
                getCommand(CommandEnum.ADD).setActivated(canAddMenu());
                getCommand(CommandEnum.EDIT).setActivated(canAddMenu());
                getCommand(CommandEnum.REMOVE)
                        .setActivated(selected && (tree.getSelectedItem().hasAttribute(ELEMENT_MENU)
                                || tree.getSelectedItem().hasAttribute(ELEMENT_PANEL)));
                getCommand(CommandEnum.MOVE_LEFT).setActivated(canAddMenu() && listbox.getSelectedItem() != null);
                getCommand(CommandEnum.MOVE_UP).setActivated(selected);
                getCommand(CommandEnum.MOVE_DOWN).setActivated(selected);
            }
        }
    }

    private boolean canAddMenu() {
        if (tree.getSelectedItem() != null) {
            if (tree.getSelectedItem().hasAttribute(ELEMENT_MENU)) {
                return true;
            }
        }
        return false;
    }

    // --------------------- GETTER / SETTER METHODS ---------------------

    @Override
    public boolean isReadOnly() {
        return readOnly;
    }

    // ------------------------ INTERFACE METHODS ------------------------

    // --------------------- Interface CommandAware ---------------------

    @Override
    public Set<CommandEnum> getSupportedCommands() {
        Set<CommandEnum> supported = new HashSet<CommandEnum>(super.getSupportedCommands());
        supported.add(CommandEnum.ADD);
        supported.add(CommandEnum.EDIT);
        supported.add(CommandEnum.REMOVE);
        supported.add(CommandEnum.MOVE_LEFT);
        supported.add(CommandEnum.MOVE_UP);
        supported.add(CommandEnum.MOVE_DOWN);
        return Collections.unmodifiableSet(supported);
    }

    // --------------------- Interface EventListener ---------------------

    @Override
    public void onEvent(Event event) throws Exception {
        if (Events.ON_SELECT.equals(event.getName())) {
            arrangeForState(PanelState.FOCUSED);
        } else if (Events.ON_DROP.equals(event.getName())) {
            Treeitem target = (Treeitem) event.getTarget();
            Listitem source = (Listitem) ((DropEvent) event).getDragged();
            renderAddedPanel(target,
                    (org.web4thejob.web.panel.Panel) listbox.getModel().getElementAt(source.getIndex()));
        }
    }

    // --------------------- Interface MessageListener ---------------------

    @Override
    public void processMessage(Message message) {
        if (MessageEnum.AFFIRMATIVE_RESPONSE == message.getId()
                && ValueInputDialog.class.isInstance(message.getSender())) {
            if (message.getArgs().containsKey(MessageArgEnum.ARG_NEW_ITEM)) {
                updateTreeitemLabel(tree.getSelectedItem(),
                        message.getArgs().get(MessageArgEnum.ARG_NEW_ITEM).toString());
            } else {
                renderAddedMenu(tree.getSelectedItem(), message.getArgs().get(MessageArgEnum.ARG_ITEM).toString());
            }
        } else {
            super.processMessage(message);
        }
    }

    // --------------------- Interface Panel ---------------------

    @Override
    public void render() {
        super.render();

        if (listbox != null && listbox.getModel() == null) {
            ListModelList<org.web4thejob.web.panel.Panel> panels = new ListModelList<org.web4thejob.web.panel.Panel>();
            for (org.web4thejob.web.panel.Panel panel : ContextUtil.getSessionContext()
                    .getPanels(org.web4thejob.web.panel.Panel.class)) {
                if (panel.isPersisted() && !DesktopLayoutPanel.class.isInstance(panel)) {
                    panels.add(panel);
                }
            }
            listbox.setModel(panels);
            listbox.setItemRenderer(new ListitemRenderer<org.web4thejob.web.panel.Panel>() {
                @Override
                public void render(Listitem item, org.web4thejob.web.panel.Panel data, int index) throws Exception {
                    Listcell cell = new Listcell();
                    cell.setStyle("white-space:nowrap;");
                    cell.setImage(data.getImage());
                    cell.setParent(item);
                    Html html = new Html(data.toString());
                    html.setParent(cell);
                    html.setStyle("margin-left: 5px;");

                    item.setValue(data);
                    item.setDraggable(ELEMENT_PANEL);
                }
            });
        }
    }

    @Override
    public String getDefinition() {
        final Element userMenu = new Element(ROOT_ELEMENT);
        appendXMLNode(userMenu, rootItem);
        String xml = userMenu.toXML();
        return xml;
    }

    @Override
    public void setDefinition(String xml) {
        if (rootItem.getTreechildren() != null) {
            rootItem.getTreechildren().detach();
            new Treechildren().setParent(rootItem);
        }
        if (!StringUtils.hasText(xml))
            return;

        Element rootElement = XMLUtil.getRootElement(xml);
        if (rootElement == null || !rootElement.getLocalName().equals(ROOT_ELEMENT)) {
            throw new IllegalArgumentException();
        } else if (rootElement.getChildElements().size() != 1) {
            throw new IllegalArgumentException();
        }

        Element startMenu = rootElement.getChildElements().get(0);
        for (int i = 0; i < startMenu.getChildElements().size(); i++) {
            appendTreeNode(startMenu.getChildElements().get(i), rootItem);
        }
    }

    // -------------------------- OTHER METHODS --------------------------

    private void appendTreeNode(Element node, Treeitem parentItem) {
        Treeitem item = null;
        if (ELEMENT_MENU.equals(node.getLocalName())) {
            item = renderAddedMenu(parentItem, XMLUtil.getTextualValue(node));
        } else if (ELEMENT_PANEL.equals(node.getLocalName())) {
            org.web4thejob.web.panel.Panel panel = getPanelSafe(XMLUtil.getTextualValue(node));
            if (panel != null) {
                item = renderAddedPanel(parentItem, panel);
            }
        } else {
            return;
        }

        if (item != null) {
            for (int i = 0; i < node.getChildElements().size(); i++) {
                appendTreeNode(node.getChildElements().get(i), item);
            }
        }
    }

    @Override
    public Treeitem renderAddedMenu(Treeitem parent, String name) {
        Treeitem item = getNewTreeitem(name, "img/FOLDER.png");
        if (parent.getTreechildren() == null) {
            new Treechildren().setParent(parent);
        }
        item.setParent(parent.getTreechildren());
        item.addEventListener(Events.ON_DROP, this);
        item.setAttribute(ELEMENT_MENU, true);
        item.setDroppable(ELEMENT_PANEL);

        return item;
    }

    private org.web4thejob.web.panel.Panel getPanelSafe(String beanid) {
        org.web4thejob.web.panel.Panel panel = null;
        try {
            panel = ContextUtil.getPanel(beanid);
        } catch (Exception ignore) {
        }
        return panel;
    }

    @Override
    public Treeitem renderAddedPanel(Treeitem parent, org.web4thejob.web.panel.Panel panel) {
        Treeitem item = getNewTreeitem(panel.toString(), panel.getImage());
        if (parent.getTreechildren() == null) {
            new Treechildren().setParent(parent);
        }
        parent.setOpen(true);
        item.setParent(parent.getTreechildren());
        item.setDroppable(null);
        item.setAttribute(ELEMENT_PANEL, panel.getBeanName());

        return item;
    }

    private void appendXMLNode(Element parentNode, Treeitem item) {
        Element childElement;
        if (item.hasAttribute(ELEMENT_MENU)) {
            childElement = new Element(ELEMENT_MENU);
            childElement.appendChild(getTreeitemLabel(item));
        } else if (item.hasAttribute(ELEMENT_PANEL)) {
            childElement = new Element(ELEMENT_PANEL);
            childElement.appendChild(item.getAttribute(ELEMENT_PANEL).toString());
        } else {
            throw new IllegalStateException();
        }

        parentNode.appendChild(childElement);

        if (item.getTreechildren() != null) {
            for (Treeitem childItem : item.getTreechildren().getItems()) {
                if (childItem.getParentItem().equals(item)) {
                    appendXMLNode(childElement, childItem);
                }
            }
        }
    }

    @SuppressWarnings("rawtypes")
    @Override
    protected void processValidCommand(Command command) {
        if (CommandEnum.ADD.equals(command.getId())) {
            if (canAddMenu()) {
                final ValueInputDialog dialog = ContextUtil.getDialog(DefaultValueInputDialog.class);
                dialog.setL10nMode(getL10nMode());
                dialog.show(this);
            }
        } else if (CommandEnum.EDIT.equals(command.getId())) {
            if (canAddMenu()) {
                String name = getTreeitemLabel(tree.getSelectedItem());
                final ValueInputDialog dialog = ContextUtil.getDialog(DefaultValueInputDialog.class, name);
                dialog.setL10nMode(getL10nMode());
                dialog.show(this);
            }
        } else if (CommandEnum.REMOVE.equals(command.getId())) {
            if (tree.getSelectedItem() != null) {
                if (!tree.getSelectedItem().hasAttribute(ITEM_ROOT)
                        && (tree.getSelectedItem().hasAttribute(ELEMENT_MENU)
                                || tree.getSelectedItem().hasAttribute(ELEMENT_PANEL))) {
                    tree.getSelectedItem().detach();
                    arrangeForState(PanelState.READY);
                }
            }
        } else if (CommandEnum.MOVE_LEFT.equals(command.getId())) {
            if (tree.getSelectedItem() != null && listbox.getSelectedItem() != null) {
                if (tree.getSelectedItem().hasAttribute(ELEMENT_MENU)) {
                    renderAddedPanel(tree.getSelectedItem(),
                            (org.web4thejob.web.panel.Panel) ((ListModelList) listbox.getModel()).getSelection()
                                    .iterator().next());
                }
            }
        } else if (CommandEnum.MOVE_UP.equals(command.getId())) {
            if (tree.getSelectedItem() != null) {
                Treeitem item = tree.getSelectedItem();
                Treeitem sibling = (Treeitem) item.getPreviousSibling();
                swap(sibling, item);
                tree.setSelectedItem(item);
            }
        } else if (CommandEnum.MOVE_DOWN.equals(command.getId())) {
            if (tree.getSelectedItem() != null) {
                Treeitem item = tree.getSelectedItem();
                Treeitem sibling = (Treeitem) item.getNextSibling();
                swap(item, sibling);
                tree.setSelectedItem(item);
            }
        } else {
            super.processValidCommand(command);
        }
    }

    private void swap(Treeitem item1, Treeitem item2) {
        if (item1 != null && item2 != null) {
            item2.detach();
            item1.getParentItem().getTreechildren().insertBefore(item2, item1);
        }
    }

    @Override
    public Treeitem getRootItem() {
        return rootItem;
    }

    protected Treeitem getNewTreeitem(String label, String img) {
        Treeitem item = new Treeitem();
        new Treerow().setParent(item);

        Treecell cell = new Treecell();
        cell.setStyle("white-space: nowrap;");
        cell.setParent(item.getTreerow());
        cell.setImage(img);

        Html html = new Html(label);
        html.setParent(cell);
        html.setStyle("margin-left: 5px;");

        return item;
    }

    protected String getTreeitemLabel(Treeitem item) {
        return ((Html) item.getTreerow().getFirstChild().getFirstChild()).getContent();
    }

    protected void updateTreeitemLabel(Treeitem item, String label) {
        ((Html) item.getTreerow().getFirstChild().getFirstChild()).setContent(label);
    }

}