Package org.libreplan.web.resources.criterion

Source Code of org.libreplan.web.resources.criterion.CriterionTreeController

/*
* This file is part of LibrePlan
*
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
*                         Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package org.libreplan.web.resources.criterion;
import static org.libreplan.web.I18nHelper._;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.apache.commons.lang.Validate;
import org.libreplan.business.common.exceptions.ValidationException;
import org.libreplan.business.common.exceptions.ValidationException.InvalidValue;
import org.libreplan.business.costcategories.entities.CostCategory;
import org.libreplan.web.common.IMessagesForUser;
import org.libreplan.web.common.Level;
import org.libreplan.web.common.MessagesForUser;
import org.libreplan.web.common.Util;
import org.libreplan.web.common.components.Autocomplete;
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.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Button;
import org.zkoss.zul.Checkbox;
import org.zkoss.zul.Comboitem;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.TreeModel;
import org.zkoss.zul.Treecell;
import org.zkoss.zul.Treeitem;
import org.zkoss.zul.TreeitemRenderer;
import org.zkoss.zul.Treerow;
import org.zkoss.zul.Vbox;
import org.zkoss.zul.api.Tree;

public class CriterionTreeController extends GenericForwardComposer {

    private Tree tree;

    private CriterionTreeitemRenderer renderer = new CriterionTreeitemRenderer();

    private TreeViewStateSnapshot snapshotOfOpenedNodes;

    private Component messagesContainer;

    private IMessagesForUser messagesForUser;

    private final ICriterionsModel criterionsModel;

    private Textbox criterionName;

    private boolean codeEditionDisabled;

    public CriterionTreeitemRenderer getRenderer() {
        return renderer;
    }

    public CriterionTreeController(ICriterionsModel _criterionsModel) {
        Validate.notNull(_criterionsModel);
        this.criterionsModel = _criterionsModel;
    }

    @Override
    public void doAfterCompose(Component comp) throws Exception {
        super.doAfterCompose(comp);
        messagesForUser = new MessagesForUser(messagesContainer);
        comp.setVariable("criterionTreeController", this, true);
        criterionName = (Textbox) ((Vbox) self).getFellowIfAny("criterionName");
        clearCriterionName();
    }

    private void clearCriterionName() {
        criterionName.setValue("");
    }

    public TreeModel getCriterionTreeModel() {
        if (getModel() == null) {
            return null;
        }
        return getModel().asTree();
    }

    private ICriterionTreeModel getModel() {
        return criterionsModel.getCriterionTreeModel();
    }

    public class CriterionTreeitemRenderer implements TreeitemRenderer {

        public CriterionTreeitemRenderer() {
        }

        @Override
        public void render(Treeitem item, Object data) {
            final CriterionDTO criterionForThisRow = (CriterionDTO) data;
            item.setValue(data);

            if (snapshotOfOpenedNodes != null) {
                snapshotOfOpenedNodes.openIfRequired(item);
            }

            Treecell cellForName = new Treecell();
            Textbox textboxName= new Textbox();
            textboxName.setWidth("400px");
            cellForName.appendChild(Util.bind(textboxName,
                    new Util.Getter<String>() {

                        @Override
                        public String get() {
                            return criterionForThisRow.getName();
                        }
                    }, new Util.Setter<String>() {

                        @Override
                        public void set(String value) {
                            criterionForThisRow.setName(value);
                        }
                    }));
            String message = _("cannot be empty");
            textboxName
                    .setConstraint("no empty:"+message);

            Treecell cellForActive = new Treecell();
            cellForActive.setStyle("center");
            Checkbox checkboxActive = new Checkbox();
            cellForActive.appendChild(Util.bind(checkboxActive,
                    new Util.Getter<Boolean>() {

                        @Override
                        public Boolean get() {
                            return criterionForThisRow.isActive();
                        }
                    }, new Util.Setter<Boolean>() {

                        @Override
                        public void set(Boolean value) {
                            criterionForThisRow.setActive(value);
                        }
                    }));

            checkboxActive.addEventListener(Events.ON_CHECK,new EventListener() {
                @Override
                        public void onEvent(Event event) {
                    getModel().updateEnabledCriterions(criterionForThisRow.isActive(),criterionForThisRow);
                    reloadTree();
                }
            });

            Treerow tr = null;
            /*
             * Since only one treerow is allowed, if treerow is not null, append
             * treecells to it. If treerow is null, contruct a new treerow and
             * attach it to item.
             */
            if (item.getTreerow() == null) {
                tr = new Treerow();
                tr.setParent(item);
            } else {
                tr = item.getTreerow();
                tr.getChildren().clear();
            }
            // Attach treecells to treerow
            tr.setDraggable("true");
            tr.setDroppable("true");

            // Treecell with the cost category of the Criterion
            Treecell cellForCostCategory = new Treecell();
            criterionForThisRow.getCriterion().getCostCategory();
            cellForCostCategory.appendChild(appendAutocompleteType(item));

            // Treecell with the code of the Criterion
            Treecell cellForCode = new Treecell();
            cellForCode.setStyle("center");
            Textbox codeLabel = new Textbox();
            codeLabel.setDisabled(codeEditionDisabled);
            cellForCode.appendChild(Util.bind(codeLabel,
                    new Util.Getter<String>() {

                @Override
                public String get() {
                    return criterionForThisRow.getCriterion().getCode();
                }
            }, new Util.Setter<String>() {

                @Override
                public void set(String value) {
                    criterionForThisRow.getCriterion().setCode(value);
                }
            }));

            cellForName.setParent(tr);
            cellForCostCategory.setParent(tr);
            cellForCode.setParent(tr);
            cellForActive.setParent(tr);

            Treecell tcOperations = new Treecell();
            Button upbutton = new Button("", "/common/img/ico_bajar1.png");
            upbutton.setHoverImage("/common/img/ico_bajar.png");
            upbutton.setParent(tcOperations);
            upbutton.setSclass("icono");
            upbutton.addEventListener(Events.ON_CLICK, new EventListener() {
                @Override
                public void onEvent(Event event) {
                    getModel().down(criterionForThisRow);
                    reloadTree();
                }
            });

            Button downbutton = new Button("", "/common/img/ico_subir1.png");
            downbutton.setHoverImage("/common/img/ico_subir.png");
            downbutton.setParent(tcOperations);
            downbutton.setSclass("icono");
            downbutton.addEventListener(Events.ON_CLICK, new EventListener() {
                @Override
                public void onEvent(Event event) {
                    getModel().up(criterionForThisRow);
                    reloadTree();
                }
            });

            Button indentbutton = createButtonIndent();
            indentbutton.setParent(tcOperations);
            if(getModel().getCriterionType().allowHierarchy()){
                    indentbutton.addEventListener(Events.ON_CLICK, new EventListener() {
                @Override
                            public void onEvent(Event event) {
                    getModel().indent(criterionForThisRow);
                    reloadTree();
                }
                });
            }

            Button unindentbutton = createButtonUnindent();
            unindentbutton.setParent(tcOperations);
            if(getModel().getCriterionType().allowHierarchy()){
                unindentbutton.addEventListener(Events.ON_CLICK,
                    new EventListener() {
                        @Override
                            public void onEvent(Event event) {
                            getModel().unindent(criterionForThisRow);
                            reloadTree();
                        }
                    });
            }

            Button removebutton = createButtonRemove(criterionForThisRow);
            removebutton.setParent(tcOperations);
            if (criterionsModel.isDeletable(criterionForThisRow.getCriterion())) {
            removebutton.addEventListener(Events.ON_CLICK, new EventListener() {
            @Override
                            public void onEvent(Event event) {
                getModel().removeNode(criterionForThisRow);
                                if (!criterionForThisRow.isNewObject()) {
                                    criterionsModel
                                            .addForRemoval(criterionForThisRow
                                                    .getCriterion());
                                }
                reloadTree();
                }
            });
        }

            tcOperations.setParent(tr);
            tr.addEventListener("onDrop", new EventListener() {

                @Override
                public void onEvent(org.zkoss.zk.ui.event.Event arg0)
{
                    DropEvent dropEvent = (DropEvent) arg0;
                    move((Component) dropEvent.getTarget(),
                            (Component) dropEvent.getDragged());
                }
            });
        }
    }

    private CostCategory getCostCategory(Treeitem listitem) {

        return ((CriterionDTO) listitem.getValue()).getCriterion()
                .getCostCategory();
    }

    private Autocomplete appendAutocompleteType(final Treeitem row) {
        final Autocomplete autocomplete = new Autocomplete();
        autocomplete.setAutodrop(true);
        autocomplete.applyProperties();
        autocomplete.setFinder("CostCategoryFinder");

        // Getter, show type selected
        if (getCostCategory(row) != null) {
            autocomplete.setSelectedItem(getCostCategory(row));
        }

        // Setter, set type selected to HourCost.type
        autocomplete.addEventListener("onSelect", new EventListener() {

            @Override
            public void onEvent(Event event) {
                final Comboitem comboitem = autocomplete.getSelectedItem();

                if (comboitem != null) {
                    // Update resourcesCostCategoryAssignment
                    CriterionDTO assignment = (CriterionDTO) row
                            .getValue();
                    assignment.getCriterion().setCostCategory(
                            (CostCategory) comboitem
                            .getValue());
                    row.setValue(assignment);
                }
            }
        });

        autocomplete.addEventListener("onBlur", new EventListener() {

            @Override
            public void onEvent(Event event) {
                if (autocomplete.getText().isEmpty()) {
                    autocomplete.clear();
                    CriterionDTO assignment = (CriterionDTO) row.getValue();
                    assignment.getCriterion().setCostCategory(null);
                }
            }
        });

        return autocomplete;
    }

    private Button createButtonUnindent(){
        Button unindentbutton;
        if( this.criterionsModel.getCriterionType().allowHierarchy()){
            unindentbutton = new Button("", "/common/img/ico_izq1.png");
            unindentbutton.setHoverImage("/common/img/ico_izq.png");
            unindentbutton.setTooltiptext(_("Unindent"));
        }else{
            unindentbutton = new Button("", "/common/img/ico_izq_out.png");
            unindentbutton.setTooltiptext(_("Not indentable"));
        }
        unindentbutton.setSclass("icono");
        return unindentbutton;
    }

    private Button createButtonIndent(){
        Button indentbutton;
        if( this.criterionsModel.getCriterionType().allowHierarchy()){
            indentbutton = new Button("", "/common/img/ico_derecha1.png");
            indentbutton.setHoverImage("/common/img/ico_derecha.png");
            indentbutton.setTooltiptext(_("Indent"));
        }else{
            indentbutton = new Button("", "/common/img/ico_derecha_out.png");
            indentbutton.setTooltiptext(_("Not indentable"));
        }
        indentbutton.setSclass("icono");
        return indentbutton;
    }

    private Button createButtonRemove(CriterionDTO criterion){
        Button removebutton;

        int num = criterionsModel.numberOfRelatedEntities(criterion
                .getCriterion());

        if (criterionsModel.isDeletable(criterion.getCriterion())) {
            removebutton = new Button("", "/common/img/ico_borrar1.png");
            removebutton.setHoverImage("/common/img/ico_borrar.png");
            removebutton.setTooltiptext(_("Delete"));
        } else {
            removebutton = new Button("", "/common/img/ico_borrar_out.png");
            removebutton.setTooltiptext(criterion.getCriterion().getChildren()
                    .isEmpty() ? (num + " " + _("references"))
                    : _("Criterion has subelements"));
        }

        removebutton.setSclass("icono");
        return removebutton;
    }

    public void up() {
        snapshotOfOpenedNodes = TreeViewStateSnapshot.snapshotOpened(tree);
        if (tree.getSelectedCount() == 1) {
            getModel().up(getSelectedNode());
        }
    }

    public void down() {
        snapshotOfOpenedNodes = TreeViewStateSnapshot.snapshotOpened(tree);
        if (tree.getSelectedCount() == 1) {
            getModel().down(getSelectedNode());
        }
    }

    public void move(Component dropedIn, Component dragged) {
        snapshotOfOpenedNodes = TreeViewStateSnapshot.snapshotOpened(tree);
        Treerow from = (Treerow) dragged;
        CriterionDTO fromNode = (CriterionDTO) ((Treeitem) from.getParent())
                .getValue();
        if (dropedIn instanceof Tree) {
            getModel().moveToRoot(fromNode,0);
        }
        if (dropedIn instanceof Treerow) {
            Treerow to = (Treerow) dropedIn;
            CriterionDTO toNode = (CriterionDTO) ((Treeitem) to.getParent())
                    .getValue();
            getModel().move(fromNode, toNode,0);
        }
        reloadTree();
    }

    public void addCriterion() {
        snapshotOfOpenedNodes = TreeViewStateSnapshot.snapshotOpened(tree);
        try {
            if((tree.getSelectedCount() == 1)
                && (this.criterionsModel.getAllowHierarchy())){
                getModel().addCriterionAt(getSelectedNode(),getName());
            } else {
                getModel().addCriterion(getName());
            }
            clearCriterionName();
            reloadTree();
        } catch (ValidationException e) {
            for (InvalidValue invalidValue : e.getInvalidValues()) {
                messagesForUser.showMessage(Level.ERROR, invalidValue
                        .getMessage());
            }
        }
    }

    public void disabledHierarchy() {
        snapshotOfOpenedNodes = TreeViewStateSnapshot.snapshotOpened(tree);
        getModel().flattenTree();
        reloadTree();
    }

    public void updateEnabledCriterions(boolean isChecked){
        snapshotOfOpenedNodes = TreeViewStateSnapshot.snapshotOpened(tree);
        getModel().updateEnabledCriterions(isChecked);
        reloadTree();
    }

    public void setCriterionCodeEditionDisabled(boolean disabled) {
        codeEditionDisabled = disabled;
    }

    public void regenerateCodeForUnsavedCriteria(int numberOfDigits) {
        getModel().regenerateCodeForUnsavedCriteria(numberOfDigits);
    }

    public void reloadTree(){
        Util.reloadBindings(tree);
    }

    private String getName() {
        String name = criterionName.getValue();
        getModel().thereIsOtherWithSameNameAndType(name);
        getModel().validateNameNotEmpty(name);
        return name;
    }

    private CriterionDTO getSelectedNode() {
        return (CriterionDTO) tree.getSelectedItemApi().getValue();
    }

    private static class TreeViewStateSnapshot {
        private final Set<Object> all;
        private final Set<Object> dataOpen;

        private TreeViewStateSnapshot(Set<Object> dataOpen, Set<Object> all) {
            this.dataOpen = dataOpen;
            this.all = all;
        }

        public static TreeViewStateSnapshot snapshotOpened(Tree tree) {
            Set<Object> dataOpen = new HashSet<Object>();
            Set<Object> all = new HashSet<Object>();
            if (tree != null && tree.getTreechildrenApi() != null) {
                Iterator<Treeitem> itemsIterator = tree.getTreechildrenApi()
                        .getItems().iterator();
                while (itemsIterator.hasNext()) {
                    Treeitem treeitem = (Treeitem) itemsIterator.next();
                    Object value = getAssociatedValue(treeitem);
                    if (treeitem.isOpen()) {
                        dataOpen.add(value);
                    }
                    all.add(value);
                }
            }
            return new TreeViewStateSnapshot(dataOpen, all);
        }

        private static Object getAssociatedValue(Treeitem treeitem) {
            return treeitem.getValue();
        }

        public void openIfRequired(Treeitem item) {
            Object value = getAssociatedValue(item);
            item.setOpen(isNewlyCreated(value) || wasOpened(value));
        }

        private boolean wasOpened(Object value) {
            return dataOpen.contains(value);
        }

        private boolean isNewlyCreated(Object value) {
            return !all.contains(value);
        }
    }
}
TOP

Related Classes of org.libreplan.web.resources.criterion.CriterionTreeController

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.