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

io.ultreia.java4all.jaxx.widgets.combobox.JaxxComboBoxHandler Maven / Gradle / Ivy

There is a newer version: 3.1.5
Show newest version
package io.ultreia.java4all.jaxx.widgets.combobox;

/*-
 * #%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%
 */

import io.ultreia.java4all.bean.JavaBean;
import io.ultreia.java4all.decoration.Decorated;
import io.ultreia.java4all.decoration.Decorator;
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.SwingUtil;
import io.ultreia.java4all.jaxx.widgets.BeanUIUtil;

import javax.swing.AbstractButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.JPopupMenu;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import java.util.Objects;

public class JaxxComboBoxHandler implements PropertyChangeListener, UIHandler> {

    public static final Logger log = LogManager.getLogger(JaxxComboBoxHandler.class);
    protected JaxxComboBox ui;
    private final BeanUIUtil.PopupHandler popupHandler = new BeanUIUtil.PopupHandler() {

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

        @Override
        public JComponent getInvoker() {
            return ui.getDisplayDecorator();
        }
    };
    protected boolean init;
    private JaxxComboBoxEditor editor;
    private JList jList;
    private int selectedIndex;
    private JComboBox combobox;
    private JaxxComboBoxModel model;
    private JaxxComboBoxConfig config;

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

    @Override
    public void afterInit(JaxxComboBox ui) {
        model = ui.getModel();
        config = model.getConfig();
    }

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

        if (JaxxComboBoxModel.PROPERTY_SELECTED_ITEM.equals(propertyName)) {
            setSelectedItem(ui.getBeanType().cast(evt.getOldValue()), ui.getBeanType().cast(evt.getNewValue()));
            return;
        }

        if (JaxxComboBoxModel.PROPERTY_INDEX.equals(propertyName)) {
            // decorator index has changed, force reload of data in ui
            setIndex((Integer) evt.getOldValue(), (Integer) evt.getNewValue());
            return;
        }

        if (JaxxComboBoxModel.PROPERTY_REVERSE_SORT.equals(propertyName)) {
            // sort order has changed, force reload of data in ui
            setSortOrder((Boolean) evt.getOldValue(), (Boolean) evt.getNewValue());
            return;
        }

        if (JaxxComboBoxModel.PROPERTY_DATA.equals(propertyName)) {
            // list has changed, force reload of index
            setIndex(null, model.getIndex());
            // list has changed, fire empty property
            List list = (List) evt.getOldValue();
            model.fireEmpty(list == null || list.isEmpty());
        }
    }

    /**
     * Initialise le handler de l'ui
     *
     * @param decorator decorator to use
     * @param data      incoming data to push in the model
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public void init(Decorator decorator, List data) {

        if (init) {
            throw new IllegalStateException("can not init the handler twice");
        }
        init = true;
        config.setDecorator(Objects.requireNonNull(decorator, String.format("decorator can not be null (for type %s)", ui.getBeanType())).copy());
        if (config.getBeanType() == null) {
            config.setBeanType((Class) decorator.definition().type());
        }
        this.combobox = ui.getCombobox();
        this.combobox.setUI(new JaxxBasicComboBoxUI());
        jList = (JList) ((JaxxBasicComboBoxUI) combobox.getUI()).getListBox();
        jList.addListSelectionListener(e -> {
            selectedIndex = jList.getSelectedIndex();
            log.trace(String.format("%s - Selected index: %d - %s", ui.getName(), selectedIndex, jList.getSelectedValue()));
        });

        // create editor
        this.editor = new JaxxComboBoxEditor<>(ui);
        combobox.setEditor(editor);

        // build popup
        popupHandler.preparePopup(config.getSelectedToolTipText(),
                                  config.getNotSelectedToolTipText(),
                                  config.getI18nPrefix(),
                                  config.getPopupTitleText(),
                                  ui.getIndexes(),
                                  ui.getPopupSeparator(),
                                  ui.getPopupLabel(),
                                  ui.getSortUp(),
                                  ui.getSortDown(),
                                  config.getDecorator());

        // list model modification
        model.addPropertyChangeListener(this);

        // set data
        model.setData(data);

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

    int getSelectedIndex() {
        return selectedIndex;
    }

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

    /**
     * Reset the combo-box; says remove any selected item and filter text.
     */
    public void reset() {
        model.setSelectedItem(null);
        editor.resetFilter(true);
        if (combobox.isShowing()) {
            combobox.hidePopup();
        }
    }

    /**
     * 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 || Objects.equals(newValue, oldValue)) {
            return;
        }
        log.debug(String.format("%s → change index state : <%d to %d>", ui.getName(), oldValue, newValue));
        AbstractButton button = ui.getIndexes().getButton(newValue);
        if (button != null) {
            button.setSelected(true);
        }
        updateUI(newValue, model.getReverseSort());
    }

    /**
     * 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 || Objects.equals(newValue, oldValue)) {
            return;
        }
        log.debug(String.format("%s → change reverse sort state : <%s to %s>", ui.getName(), oldValue, newValue));
        updateUI(model.getIndex(), newValue);
    }

    /**
     * Modifie la valeur sélectionnée dans la liste déroulante.
     *
     * @param oldValue l'ancienne valeur
     * @param newValue la nouvelle valeur
     */
    protected void setSelectedItem(O oldValue, O newValue) {
        if (oldValue == null && newValue == null) {
            return;
        }
        if (!config.getBeanType().isInstance(newValue)) {
            newValue = null;
        }
        if (Objects.equals(oldValue, newValue)) {
            return;
        }
        if (newValue != null) {
            if (config.isBeanDecoratorAware()) {
                ((Decorated) newValue).registerDecorator(config.getDecorator());
            }
            // got a not null value selected, remove filter
            editor.resetFilter(false);
        }
        log.debug(String.format("%s → change selected item state <%s to %s>", ui.getName(), oldValue, newValue));
        model.mutateBeanProperty(newValue);
    }


    private void updateUI(int index, boolean reverseSort) {

        // change decorator context
        Decorator decorator = config.getDecorator();
        decorator.setIndex(index);

        // keep selected item
        O previousSelectedItem = model.getSelectedItem();

        // remove autocomplete
        if (previousSelectedItem != null) {
            ui.getCombobox().setSelectedItem(null);
            model.selectedItem = null;
        }

        List data = model.getData();
        if (config.isBeanDecoratorAware()) {
            data.forEach(datum -> ((Decorated) datum).registerDecorator(decorator));
            if (previousSelectedItem != null) {
                ((Decorated) previousSelectedItem).registerDecorator(decorator);
            }
        }
        if (config.isSortable() && data != null && !data.isEmpty()) {
            try {
                decorator.sort(data, index, reverseSort);
            } catch (Exception eee) {
                log.warn(eee.getMessage(), eee);
            }
        }

        // reload the model
        SwingUtil.fillComboBox(ui.getCombobox(), data, null);
        if (previousSelectedItem != null) {
            model.setSelectedItem(previousSelectedItem);
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy