org.libreplan.web.common.components.bandboxsearch.BandboxSearch.java Source code

Java tutorial

Introduction

Here is the source code for org.libreplan.web.common.components.bandboxsearch.BandboxSearch.java

Source

/*
 * This file is part of LibrePlan
 *
 * Copyright (C) 2009-2010 Fundacin para o Fomento da Calidade Industrial e
 *                         Desenvolvemento Tecnolxico de Galicia
 * Copyright (C) 2010-2012 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.common.components.bandboxsearch;

import static org.libreplan.web.I18nHelper._;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.libreplan.business.common.BaseEntity;
import org.libreplan.business.labels.entities.Label;
import org.libreplan.web.common.Util;
import org.libreplan.web.common.components.finders.IBandboxFinder;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.HtmlMacroComponent;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.event.InputEvent;
import org.zkoss.zkplus.databind.DataBinder;
import org.zkoss.zul.Bandbox;
import org.zkoss.zul.Constraint;
import org.zkoss.zul.ListModel;
import org.zkoss.zul.Listhead;
import org.zkoss.zul.Listheader;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.SimpleListModel;
import org.zkoss.zul.Listbox;

@SuppressWarnings("serial")
public class BandboxSearch extends HtmlMacroComponent {

    private final String SELECTED_ELEMENT_ATTRIBUTE = "selectedElement";

    private Listbox listbox;

    private Listhead listhead;

    private Bandbox bandbox;

    private IBandboxFinder finder;

    private String widthBandbox;

    private String widthListbox;

    private List<? extends BaseEntity> model;

    @Override
    public void afterCompose() {
        super.afterCompose();
        listbox = (Listbox) getFellowIfAny("listbox");

        if (model != null) {
            setModel(new SimpleListModel<>(model));
        } else {
            listbox.setModel(finder.getModel());
        }

        listbox.setItemRenderer(finder.getItemRenderer());

        listhead = (Listhead) listbox.getFellowIfAny("listhead");
        bandbox = (Bandbox) getFellowIfAny("bandbox");

        /* Search for matching elements while typing on bandbox */
        bandbox.addEventListener("onChanging", event -> {
            clearSelectedElement();
            final String inputText = ((InputEvent) event).getValue();
            listbox.setModel(getSubModel(inputText));
            listbox.invalidate();
        });

        bandbox.setCtrlKeys("#down");

        bandbox.addEventListener(Events.ON_CTRL_KEY, event -> {
            int selectedItemIndex = listbox.getSelectedIndex();
            if (selectedItemIndex != -1) {
                listbox.getItemAtIndex(selectedItemIndex).setFocus(true);
            } else {
                List<Listitem> items = listbox.getItems();

                if (!items.isEmpty()) {
                    listbox.setSelectedIndex(0);
                    pickElementFromList();
                    items.get(0).setFocus(true);
                }
            }
        });

        /* Pick element from list when selecting */
        listbox.addEventListener(Events.ON_SELECT, event -> pickElementFromList());

        // Close bandbox for events onClick and onOK
        listbox.addEventListener(Events.ON_CLICK, event -> close());
        listbox.addEventListener(Events.ON_OK, event -> {
            pickElementFromList();
            close();
        });

        addHeaders();
        updateWidth();
    }

    public static BandboxSearch create(String finderClassName, List<? extends BaseEntity> model) {
        BandboxSearch bandboxSearch = new BandboxSearch();
        bandboxSearch.setFinder(finderClassName);
        bandboxSearch.afterCompose();
        bandboxSearch.setModel(model);

        return bandboxSearch;
    }

    public static BandboxSearch create(String finderClassName) {
        BandboxSearch bandboxSearch = new BandboxSearch();
        bandboxSearch.setFinder(finderClassName);
        bandboxSearch.afterCompose();

        return bandboxSearch;
    }

    public void pickElementFromList() {
        final Object object = getSelectedItem().getValue();
        bandbox.setValue(finder.objectToString(object));
        setSelectedElement(object);
        Util.getBinder(this).saveAttribute(this, SELECTED_ELEMENT_ATTRIBUTE);
    }

    private void clearSelectedElement() {
        setSelectedElement(null);
    }

    public void setSelectedElement(Object obj) {
        bandbox.setAttribute(SELECTED_ELEMENT_ATTRIBUTE, obj, true);

        if (obj != null) {
            bandbox.setValue(finder.objectToString(obj));
        } else {
            bandbox.setValue("");
        }

        /* TODO resolve deprecated */
        DataBinder binder = Util.getBinder(this);

        if (binder != null) {
            binder.saveAttribute(this, SELECTED_ELEMENT_ATTRIBUTE);
        }
    }

    public Object getSelectedElement() {
        return bandbox.getAttribute(SELECTED_ELEMENT_ATTRIBUTE, true);
    }

    /**
     * Find {@link Label} which name or type start with prefix.
     *
     * @param inputText
     */
    @SuppressWarnings("unchecked")
    private ListModel<Object> getSubModel(String inputText) {
        List<Object> result = new ArrayList<>();

        final ListModel finderModel = finder.getModel();
        for (int i = 0; i < finderModel.getSize(); i++) {
            Object obj = finderModel.getElementAt(i);
            if (finder.entryMatchesText(obj, inputText)) {
                result.add(obj);
            }
        }
        return new SimpleListModel<>(result);
    }

    /**
     * Append headers to listbox header list.
     */
    @SuppressWarnings("unchecked")
    private void addHeaders() {
        clearHeaderIfNecessary();
        final String[] headers = finder.getHeaders();

        for (String header : headers) {
            listhead.getChildren().add(new Listheader(_(header)));
        }
    }

    private void clearHeaderIfNecessary() {
        if (listhead.getChildren() != null) {
            listhead.getChildren().clear();
        }
    }

    public Listitem getSelectedItem() {
        return (listbox == null || listbox.getSelectedItems().isEmpty()) ? null
                : listbox.getSelectedItems().iterator().next();
    }

    public String getFinder() {
        return finder.getClass().toString();
    }

    public void setFinder(String classname) {
        finder = (IBandboxFinder) getBean(StringUtils.uncapitalize(classname));
        finder.resetModel();
    }

    public List<? extends BaseEntity> getModel() {
        return model;
    }

    public void setModel(List<? extends BaseEntity> model) {
        this.model = model;
        setModel(new SimpleListModel<>(model));
    }

    private void setModel(ListModel<Object> model) {
        finder.setModel(model);
        listbox.setModel(model);
    }

    public void setDisabled(boolean disabled) {
        bandbox.setDisabled(disabled);
    }

    private Object getBean(String classname) {
        HttpServletRequest servletRequest = (HttpServletRequest) Executions.getCurrent().getNativeRequest();
        ServletContext servletContext = servletRequest.getSession().getServletContext();

        WebApplicationContext webApplicationContext = WebApplicationContextUtils
                .getWebApplicationContext(servletContext);

        return webApplicationContext.getBean(classname);
    }

    /**
     * Clears {@link Bandbox}.
     *
     * Fills bandbox list model, clear bandbox textbox, and set selected label to null.
     */
    public void clear() {
        listbox.setModel(finder.getModel());
        bandbox.setValue("");
        clearSelectedElement();
    }

    /**
     * Adds a new element to list of elements.
     *
     * @param obj
     */
    public void addElement(Object obj) {
        List<Object> list = asList(finder.getModel());
        list.add(obj);
        setModel(new SimpleListModel<>(list));
        Util.reloadBindings(listbox);
    }

    public List<Object> asList(ListModel model) {
        List<Object> result = new ArrayList<>();

        for (int i = 0; i < model.getSize(); i++) {
            result.add(model.getElementAt(i));
        }

        return result;
    }

    public void setListboxEventListener(String event, EventListener listener) {
        listbox.addEventListener(event, listener);
    }

    public void setBandboxEventListener(String event, EventListener listener) {
        bandbox.addEventListener(event, listener);
    }

    public void foucusOnInput() {
        bandbox.setFocus(true);
    }

    public String getWidthBandbox() {
        return widthBandbox;
    }

    public void setWidthBandbox(String widthBandbox) {
        this.widthBandbox = widthBandbox;
    }

    public String getWidthListbox() {
        return widthListbox;
    }

    public void setWidthListbox(String widthListbox) {
        this.widthListbox = widthListbox;
    }

    private void updateWidth() {
        if ((widthBandbox != null) && (!widthBandbox.isEmpty())) {
            this.bandbox.setWidth(widthBandbox);
            this.listbox.setWidth(widthListbox);
        }
    }

    public void setListboxWidth(String width) {
        if (listbox != null) {
            listbox.setWidth(width);
        }
    }

    public void close() {
        if (bandbox != null) {
            bandbox.close();
        }
    }

    public void setBandboxConstraint(String constraint) {
        bandbox.setConstraint(constraint);
    }

    public void setBandboxConstraint(Constraint constraint) {
        bandbox.setConstraint(constraint);
    }
}