io.ultreia.java4all.jaxx.widgets.combobox.JaxxComboBoxHandler Maven / Gradle / Ivy
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