All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.ultreia.java4all.jaxx.widgets.list.ListHeaderHandler Maven / Gradle / Ivy

/*
 * #%L
 * JAXX :: Widgets
 * %%
 * Copyright (C) 2008 - 2024 Code Lutin, Ultreia.io
 * %%
 * This program 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 (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 General Lesser Public License for more details.
 *
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

package io.ultreia.java4all.jaxx.widgets.list;

import io.ultreia.java4all.decoration.Decorated;
import io.ultreia.java4all.decoration.Decorator;
import io.ultreia.java4all.jaxx.widgets.BeanUIUtil;
import org.apache.commons.collections.primitives.ArrayIntList;
import org.apache.commons.collections.primitives.IntList;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.nuiton.jaxx.runtime.spi.UIHandler;
import org.nuiton.jaxx.runtime.swing.JAXXButtonGroup;
import org.nuiton.jaxx.runtime.swing.renderer.DecoratorListCellRenderer;

import javax.swing.AbstractButton;
import javax.swing.DefaultListModel;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.JPopupMenu;
import javax.swing.ListModel;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import java.util.Vector;

/**
 * Note: ce handler n'est pas stateless et n'est donc pas partageable entre
 * plusieurs ui.
 *
 * @param  le type des objet contenus dans le modèle du composant.
 * @author Tony Chemit - [email protected]
 * @see ListHeader
 * @since 2.2
 */
public class ListHeaderHandler implements PropertyChangeListener, UIHandler> {

    public static final Logger log = LogManager.getLogger(ListHeaderHandler.class);

    protected ListHeader ui;
    private final BeanUIUtil.PopupHandler popupHandler = new BeanUIUtil.PopupHandler() {

        @Override
        public JPopupMenu getPopup() {
            return ui.getPopup();
        }

        @Override
        public JComponent getInvoker() {
            return ui.getChangeDecorator();
        }
    };
    /**
     * the decorator of data
     */
    protected Decorator decorator;
    /**
     * flag to mark when handler was init (it can be init only once).
     */
    protected boolean init;

    /**
     * Initialise le handler de l'ui
     *
     * @param decorator le decorateur a utiliser
     * @param data      la liste des données a gérer
     */
    public void init(Decorator decorator, List data) {

        if (init) {
            throw new IllegalStateException("can not init the handler twice");
        }
        init = true;

        if (decorator == null) {
            throw new NullPointerException("decorator can not be null (for type " + ui.getBeanType() + ")");
        }

        // list could have changed and the complex binding is not registered...
        ui.removeDataBinding(ListHeader.BINDING_RESET_SELECTION_ENABLED);
        ui.applyDataBinding(ListHeader.BINDING_RESET_SELECTION_ENABLED);

        JAXXButtonGroup indexes = ui.getIndexes();

        this.decorator = decorator.copy();

        // init combobox renderer base on given decorator
        ui.getList().setCellRenderer(new DecoratorListCellRenderer<>(this.decorator));

        // build popup
        popupHandler.preparePopup(ui.getSelectedToolTipText(),
                                  ui.getNotSelectedToolTipText(),
                                  ui.getI18nPrefix(),
                                  ui.getPopupTitleText(),
                                  indexes,
                                  ui.getPopupSeparator(),
                                  ui.getPopupLabel(),
                                  ui.getSortUp(),
                                  ui.getSortDown(),
                                  this.decorator);

        ui.addPropertyChangeListener(this);

        // set data
        ui.setData(data);

        // select sort button
        indexes.setSelectedButton(ui.getIndex());
    }

    /**
     * Toggle the popup visible state.
     */
    public void togglePopup() {
        popupHandler.togglePopup();
    }

    /**
     * Modifie l'index du décorateur
     *
     * @param oldValue l'ancienne valeur
     * @param newValue la nouvelle valeur
     */
    protected void setIndex(Integer oldValue, Integer newValue) {
        if (newValue == null || newValue.equals(oldValue)) {
            return;
        }
        if (log.isDebugEnabled()) {
            log.debug("check state : <" + oldValue + " to " + newValue + ">");
        }
        AbstractButton button = ui.getIndexes().getButton(newValue);
        if (button != null) {
            button.setSelected(true);
        }
        updateUI(newValue, ui.isReverseSort());
    }

    /**
     * Modifie l'index du décorateur
     *
     * @param oldValue l'ancienne valeur
     * @param newValue la nouvelle valeur
     */

    protected void setSortOrder(Boolean oldValue, Boolean newValue) {

        if (newValue == null || newValue.equals(oldValue)) {
            return;
        }
        if (log.isDebugEnabled()) {
            log.debug("check state : <" + oldValue + " to " + newValue + ">");
        }

        updateUI(ui.getIndex(), newValue);
    }

    protected void updateUI(int index, boolean reverseSort) {

        // change decorator context
        decorator.setIndex(index);

        // get the current selection in list
        List selection = ui.getList().getSelectedValuesList();

        List datas = ui.getData();
        try {

            // Sort data with the decorator jxpath tokens.
            decorator.sort(datas, index, reverseSort);
        } catch (Exception e) {
            log.warn(e.getMessage(), e);
        }

        ui.getList().setValueIsAdjusting(true);
        try {

            // reload the model
            ListModel listModel = ui.getList().getModel();

            if (listModel instanceof DefaultListModel) {
                DefaultListModel model = (DefaultListModel) listModel;
                model.removeAllElements();
                for (O data : datas) {
                    model.addElement(data);
                }

            } else {

                ui.getList().setListData(new Vector<>(datas));
            }

            // re-apply selection
            if (selection.size() > 0) {

                // re compute selection (the new data could not contains some
                // previously selected items)
                IntList newSelection = new ArrayIntList();
                for (O o : selection) {
                    if (datas.contains(o)) {

                        newSelection.add(datas.indexOf(o));
                    }
                }

                if (!newSelection.isEmpty()) {

                    // there is still a selection to re-apply
                    int[] ints = newSelection.toArray(new int[newSelection.size()]);
                    newSelection.clear();
                    ui.getList().setSelectedIndices(ints);
                }
            }

        } finally {
            ui.getList().setValueIsAdjusting(false);
            ui.getList().repaint();
        }
    }

    public Decorator getDecorator() {
        return decorator;
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        String propertyName = evt.getPropertyName();

        if (ListHeader.PROPERTY_INDEX.equals(propertyName)) {

            // decorator index has changed, force reload of data in ui
            setIndex((Integer) evt.getOldValue(),
                     (Integer) evt.getNewValue());
            return;
        }

        if (ListHeader.PROPERTY_REVERSE_SORT.equals(propertyName)) {

            // sort order has changed, force reload of data in ui
            setSortOrder((Boolean) evt.getOldValue(),
                         (Boolean) evt.getNewValue());
            return;
        }

        if (ListHeader.PROPERTY_DATA.equals(propertyName)) {
            if (decorator != null && ui.getData() != null) {
                ui.getData().forEach(datum -> ((Decorated) datum).registerDecorator(decorator));
            }
            // list has changed, force reload of index
            setIndex(-1, ui.getIndex());
        }

//        if (ListHeader.PROPERTY_LIST.equals(propertyName)) {
//
//            // ui list has changed, replace  binding
//            ui.removeDataBinding(ListHeader.BINDING_RESET_SELECTION_ENABLED);
//            ui.applyDataBinding(ListHeader.BINDING_RESET_SELECTION_ENABLED);
//        }
    }

    public O getSelectedValue() {
        JList list = ui.getList();
        return list == null ? null : list.getSelectedValue();
    }

    @Override
    public void beforeInit(ListHeader ui) {
        this.ui = ui;
    }

    @Override
    public void afterInit(ListHeader ui) {

    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy