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

fr.ird.observe.client.action.UIActionSupport Maven / Gradle / Ivy

/*
 * #%L
 * ObServe Toolkit :: Common Client
 * %%
 * Copyright (C) 2008 - 2017 IRD, Ultreia.io
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU 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 Public License for more details.
 * 
 * You should have received a copy of the GNU General Public 
 * License along with this program.  If not, see
 * .
 * #L%
 */
package fr.ird.observe.client.action;

import com.google.common.collect.ImmutableMap;
import fr.ird.observe.client.MainUI;
import fr.ird.observe.client.ObserveKeyStrokes;
import fr.ird.observe.client.form.FormUI;
import io.ultreia.java4all.lang.GetterProducer;
import io.ultreia.java4all.lang.SetterProducer;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.beans.PropertyChangeListener;
import java.util.Objects;
import java.util.function.BiConsumer;
import java.util.function.Function;
import javax.swing.AbstractButton;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.Icon;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.KeyStroke;
import javax.swing.event.SwingPropertyChangeSupport;
import org.nuiton.jaxx.runtime.JAXXObject;
import org.nuiton.jaxx.runtime.swing.SwingUtil;


import static org.nuiton.i18n.I18n.t;

/**
 * Pour implanter les actions communes.
 *
 * @author Tony Chemit - [email protected]
 * @since 1.4
 */
public abstract class UIActionSupport implements Action, GetterProducer, SetterProducer {

    public static final String EDITOR = "editor";
    private static final String ENABLED = "enabled";
    public static final String CLIENT_PROPERTY_UI = "ui";

    private static final ImmutableMap> GETTERS =
            ImmutableMap.>builder()
                    .put(ACTION_COMMAND_KEY, UIActionSupport::getActionCommandKey)
                    .put(NAME, UIActionSupport::getText)
                    .put(SHORT_DESCRIPTION, UIActionSupport::getTooltipText)
                    .put(ACCELERATOR_KEY, UIActionSupport::getAcceleratorKey)
                    .put(SMALL_ICON, UIActionSupport::getIcon)
                    .put(MNEMONIC_KEY, UIActionSupport::getMnemonic)
                    .put(EDITOR, UIActionSupport::getEditor)
                    .build();

    private static final ImmutableMap> SETTERS =
            ImmutableMap.>builder()
                    .put(ACTION_COMMAND_KEY, (e, v) -> e.setName((String) v))
                    .put(NAME, (e, v) -> e.setText((String) v))
                    .put(SHORT_DESCRIPTION, (e, v) -> e.setTooltipText((String) v))
                    .put(ACCELERATOR_KEY, (e, v) -> e.setKeyStroke((KeyStroke) v))
                    .put(SMALL_ICON, (e, v) -> e.setIcon((Icon) v))
                    .put(MNEMONIC_KEY, (e, v) -> e.setMnemonic((char) v))
                    .build();

    private final MainUI mainUI;

    private String name;
    private String text;
    private String tooltipText;
    private KeyStroke keyStroke;
    private char mnemonic;
    private Icon icon;
    private JComponent editor;
    private boolean enabled;
    private SwingPropertyChangeSupport changeSupport;

    public interface Update {
        void updateAction(JAXXObject ui, AbstractButton editor);
    }

    @SuppressWarnings("unchecked")
    @Override
    public  O get(String propertyName) {
        Function getter = (Function) GETTERS.get(propertyName);
        Objects.requireNonNull(getter, String.format("Can't find a getter for property: %s on %s", propertyName, getClass().getName()));
        return getter.apply(this);
    }

    @SuppressWarnings("unchecked")
    @Override
    public  void set(String propertyName, O o) {
        BiConsumer setter = (BiConsumer) SETTERS.get(propertyName);
        Objects.requireNonNull(setter, String.format("Can't find a setter for property: %s on %s", propertyName, getClass().getName()));
        setter.accept(this, o);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getText() {
        return text;
    }

    public String getTooltipText() {
        return tooltipText;
    }

    public KeyStroke getKeyStroke() {
        return keyStroke;
    }

    public char getMnemonic() {
        return mnemonic;
    }

    public Icon getIcon() {
        return icon;
    }

    public void setKeyStroke(KeyStroke keyStroke) {
        this.keyStroke = keyStroke;
    }

    public void setText(String text) {
        this.text = text;
    }

    public void setTooltipText(String tooltipText) {
        this.tooltipText = tooltipText;
    }

    @Override
    public Object getValue(String key) {
        return get(key);
    }

    @Override
    public void putValue(String key, Object value) {
        set(key, value);
    }

    public void setIcon(Icon icon) {
        this.icon = icon;
    }

    public void setMnemonic(char mnemonic) {
        this.mnemonic = mnemonic;
    }

    protected UIActionSupport(MainUI mainUI, String actionCommandKey, String label, String shortDescription, String actionIcon, KeyStroke acceleratorKey) {
        this(mainUI, actionCommandKey, label, shortDescription, actionIcon, acceleratorKey, true);
    }

    protected UIActionSupport(MainUI mainUI, String actionCommandKey, String label, String shortDescription, String actionIcon, char acceleratorKey) {
//        super(t(label), SwingUtil.getUIManagerActionIcon(actionIcon));
        this.name = actionCommandKey;
        this.text = t(label);
        this.mainUI = mainUI;
        if (actionIcon != null) {
            icon = SwingUtil.getUIManagerActionIcon(actionIcon);
        }
        this.mnemonic = acceleratorKey;
        ObserveKeyStrokes.addKeyStore(this, KeyStroke.getKeyStroke(acceleratorKey, InputEvent.ALT_MASK), label, shortDescription);
    }

    protected UIActionSupport(MainUI mainUI, String actionCommandKey, String label, String shortDescription, String actionIcon, KeyStroke acceleratorKey, boolean addKeyStroke) {
//        super(t(label), SwingUtil.getUIManagerActionIcon(actionIcon));
        this.name = actionCommandKey;
        this.mainUI = mainUI;
        this.text = t(label);
        if (actionIcon != null) {
            icon = SwingUtil.getUIManagerActionIcon(actionIcon);
        }
        if (addKeyStroke) {
            ObserveKeyStrokes.addKeyStore(this, acceleratorKey, label, shortDescription);
        } else if (acceleratorKey != null) {
            keyStroke = acceleratorKey;
        }
    }

    public KeyStroke getAcceleratorKey() {
        return keyStroke;
    }

    public String getActionCommandKey() {
        return name;
    }

    public MainUI getMainUI() {
        return mainUI;
    }

    public JComponent getEditor() {
        return editor;
    }

    public void initAction(JComponent ui, AbstractButton editor) {
        editor.setAction(this);
        editor.putClientProperty(CLIENT_PROPERTY_UI, ui);
        //FIXME Attention on introduit un état dans l'action et si l'action est utilisée plusieurs fois dans un même écran
        //FIXME cela va introduire des effets de bord
        this.editor = editor;
        ObserveKeyStrokes.addKeyStroke2(getMainUI(), editor, getAcceleratorKey());
        register(ui.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW), ui.getActionMap());
    }

    public void initForMainUi(AbstractButton editor) {

        initForMainUi(editor, getMainUI().getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW), getMainUI().getRootPane().getActionMap());
        getMainUI().registerAction(editor);
    }

    public void initForMainUi(AbstractButton editor, InputMap inputMap, ActionMap actionMap) {
        String text = editor.getText();
        String tip = editor.getToolTipText();

        editor.setAction(this);
        if (text != null && editor.getText() == null) {
            editor.setText(text);
        }
        if (tip != null && editor.getToolTipText() == null) {
            editor.setToolTipText(tip);
        }
        editor.putClientProperty(CLIENT_PROPERTY_UI, getMainUI());
        //FIXME Attention on introduit un état dans l'action et si l'action est utilisée plusieurs fois dans un même écran
        //FIXME cela va introduire des effets de bord
        this.editor = editor;
        register(inputMap, actionMap);
    }

    public void register(InputMap inputMap, ActionMap actionMap) {
        KeyStroke keyStroke = getAcceleratorKey();
        if (keyStroke != null) {
            String actionCommandKey = getActionCommandKey();
            register(this, inputMap, actionMap, keyStroke, actionCommandKey);
        }
    }

    public static void register(Action action, InputMap inputMap, ActionMap actionMap, KeyStroke keyStroke, String actionCommandKey) {
        if (keyStroke != null) {
            inputMap.put(keyStroke, actionCommandKey);
            actionMap.put(actionCommandKey, action);
        }
    }

    protected UIActionContext getActionContext() {
        return mainUI.getActionContext();
    }

    @Override
    public synchronized void addPropertyChangeListener(PropertyChangeListener listener) {
        if (changeSupport == null) {
            changeSupport = new SwingPropertyChangeSupport(this);
        }
        changeSupport.addPropertyChangeListener(listener);
    }

    @Override
    public synchronized void removePropertyChangeListener(PropertyChangeListener listener) {
        if (changeSupport == null) {
            return;
        }
        changeSupport.removePropertyChangeListener(listener);
    }

    public synchronized PropertyChangeListener[] getPropertyChangeListeners() {
        if (changeSupport == null) {
            return new PropertyChangeListener[0];
        }
        return changeSupport.getPropertyChangeListeners();
    }

    protected FormUI getContentUI(ActionEvent e) {
        JComponent c = (JComponent) e.getSource();
        FormUI ui;

        //FIXME On devrait peut-être toujours se baser sur le contentui manager
        //FIXME et ne plus rien attacher aux editeurs ?
        if (c instanceof FormUI) {
            ui = (FormUI) c;
        } else if (c.getParent() instanceof FormUI) {
            ui = (FormUI) c.getParent();
        } else {
            ui = (FormUI) c.getClientProperty(CLIENT_PROPERTY_UI);
        }
        if (ui == null) {
            ui = getMainUI().getContentUIManager().getSelectedContentUI();
        }
        return ui;
    }

    protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
        if (changeSupport == null ||
                (oldValue != null && newValue != null && oldValue.equals(newValue))) {
            return;
        }
        changeSupport.firePropertyChange(propertyName, oldValue, newValue);
    }

    @Override
    public boolean isEnabled() {
        return enabled;
    }

    @Override
    public void setEnabled(boolean enabled) {
        boolean oldValue = isEnabled();
        this.enabled = enabled;
        firePropertyChange(ENABLED, oldValue, enabled);
    }

    public void displayInfo(String text) {
        getMainUI().displayInfo(text);
    }

    public void displayInfo(String title, String text) {
        getMainUI().displayInfo(title, text);
    }

    public void displayWarning(String title, String text) {
        getMainUI().displayWarning(title, text);
    }

    public int askUser(String title, String message, int typeMessage, Object[] options, int defaultOption) {
        return getMainUI().askUser(title, message, typeMessage, options, defaultOption);
    }

    public int askUser(String title, Object message, int typeMessage, Object[] options, int defaultOption) {
        return getMainUI().askUser(title, message, typeMessage, options, defaultOption);
    }

    public int askUser(JOptionPane pane, String title, Object[] options) {
        return getMainUI().askUser(pane, title, options);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy