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

org.wings.SDefaultCellEditor Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2000,2005 wingS development team.
 *
 * This file is part of wingS (http://wingsframework.org).
 *
 * wingS 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 2.1
 * of the License, or (at your option) any later version.
 *
 * Please see COPYING for the complete licence.
 */
package org.wings;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.Serializable;
import java.util.EventObject;

import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.EventListenerList;

import org.wings.resource.ResourceManager;
import org.wings.table.STableCellEditor;

/**
 * Default table cell editor.
 *
 * @author Holger Engels
 */
public class SDefaultCellEditor
        implements STableCellEditor {
    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    /**
     * The default ok button icon.
     */
    private static final SIcon OK_BUTTON_ICON = (SIcon) ResourceManager.getObject("SDefaultCellEditor.okIcon", SIcon.class);

    /**
     * The default cancel button icon.
     */
    private static final SIcon CANCEL_BUTTON_ICON = (SIcon) ResourceManager.getObject("SDefaultCellEditor.cancelIcon", SIcon.class);

    /**
     * Label for displaying (error)-messages. It is unvisible, until a message
     * is set.
     */
    protected final SLabel messageLabel;

    /**
     * Panel for edit fields.
     */
    protected final EditorPanel editorPanel;

    /**
     * If this button is pressed, editing is tried to stop. If input validation
     * found no error, editing is stopped, else an error message is displayed
     */
    protected final SClickable ok;

    /**
     * If this button is pressed, editing is canceled.
     */
    protected final SClickable cancel;

    /**
     * Store here the CellEditorListener
     */
    protected final EventListenerList listenerList;

    /**
     * Fast edit support is editing with reduced interaction. E.g. a boolean
     * value can only have to states, true or false. So if editing is started,
     * the editor just flips the state and fires editing stopped.
     */
    private boolean fastEditSupport = true;

    protected EditorDelegate delegate;

    protected SComponent editorComponent;

    /**
     * Initialize the DefaultCellEditor with an editor component (like an text
     * field for instance). After calling this constructor, the
     * {@link EditorDelegate}, that links the CellEditor and the
     * editorComponent has to be passed to the delegate instance variable.
     *
     * @param editorComponent   the component used
     * @param initializeButtons flag to indicate if the button texts and icons
     *                          should be initialized.
     */
    protected SDefaultCellEditor(SComponent editorComponent,
                                 boolean initializeButtons) {
        this.messageLabel = new SLabel();
        this.editorPanel = new EditorPanel();
        this.ok = new SClickable();
        this.cancel = new SClickable();
        this.listenerList = new EventListenerList();
        this.editorComponent = editorComponent;

        editorPanel.add(messageLabel);
        editorPanel.add(editorComponent);
        if (initializeButtons) {
            initButtons();
        }
    }

    /**
     * Constructs a DefaultCellEditor that uses a text field.
     *
     * @param x a STextField object ...
     */
    public SDefaultCellEditor(STextField x) {
        this(x, true);
        this.delegate = new EditorDelegate() {
            @Override
            public void setValue(Object v) {
                super.setValue(v);
                ((STextField) editorComponent).setText(v !=  null ? v.toString() : null);
            }

            @Override
            public Object getCellEditorValue() {
                String text = ((STextField) editorComponent).getText();
                return text != null && text.isEmpty() ? null : text;
            }

            @Override
            public boolean shouldSelectCell(EventObject anEvent) {
                return true;
            }
        };
    }

    /**
     * Constructs a DefaultCellEditor object that uses a check box.
     *
     * @param x a SCheckBox object ...
     */
    public SDefaultCellEditor(SCheckBox x) {
        this(x, true);
        this.delegate = new EditorDelegate() {
            @Override
            public void setValue(Object v) {
                // Try my best to do the right thing with v
                boolean bool;
                if (v instanceof Boolean) {
                    bool = (Boolean) v;
                } else if (v instanceof String) {
                    Boolean b = Boolean.valueOf((String) v);
                    bool = b;
                } else {
                    bool = false;
                }

                if (fastEditSupport) {
                    ((SCheckBox) editorComponent).setSelected(!bool);
                    SDefaultCellEditor.this.stopCellEditing();
                } else {
                    ((SCheckBox) editorComponent).setSelected(bool);
                }
            }

            @Override
            public Object getCellEditorValue() {
                return ((SCheckBox) editorComponent).isSelected();
            }

            @Override
            public boolean shouldSelectCell(EventObject anEvent) {
                return false;
            }
        };
    }

    /**
     * Intializes the buttons with default icons, tooltip text and listener.
     */
    protected void initButtons() {
        ok.setEvent("ok");
        ok.setIcon(OK_BUTTON_ICON);
        ok.setToolTipText("ok");
        ok.setEventTarget(editorPanel);

        cancel.setEvent("cancel");
        cancel.setIcon(CANCEL_BUTTON_ICON);
        cancel.setToolTipText("cancel");
        cancel.setEventTarget(editorPanel);

        editorPanel.add(ok);
        editorPanel.add(cancel);
    }

    /**
     * Returns a reference to the editor component.
     *
     * @return the editor Component
     */
    public final SComponent getComponent() {
        return editorComponent;
    }

    public final SClickable getOKButton() {
        return ok;
    }

    public final SClickable getCancelButton() {
        return cancel;
    }

    /**
     * Fast edit support is editing with reduced interaction. E.g. a boolean
     * value can only have to states, true or false. So if editing is started,
     * the editor just flips the state and fires editing stopped.
     *
     * @param b a boolean value
     */
    public final void setFastEdit(boolean b) {
        fastEditSupport = b;
    }

    /**
     * Return if fast edit is activated.
     *
     * @return a boolean value
     * @see #setFastEdit
     */
    public final boolean getFastEdit() {
        return fastEditSupport;
    }

    @Override
    public Object getCellEditorValue() {
        return delegate.getCellEditorValue();
    }

    @Override
    public boolean isCellEditable(EventObject anEvent) {
        return delegate.isCellEditable(anEvent);
    }

    @Override
    public boolean shouldSelectCell(EventObject anEvent) {
        return delegate.shouldSelectCell(anEvent);
    }

    @Override
    public boolean stopCellEditing() {
        if (delegate.stopCellEditing()) {
            fireEditingStopped();
            return true;
        }

        return false;
    }

    @Override
    public void cancelCellEditing() {
        delegate.cancelCellEditing();
        fireEditingCanceled();
    }

    @Override
    public void addCellEditorListener(CellEditorListener l) {
        listenerList.add(CellEditorListener.class, l);
    }

    @Override
    public void removeCellEditorListener(CellEditorListener l) {
        listenerList.remove(CellEditorListener.class, l);
    }

    private ChangeEvent changeEvent = null;

    /*
     * Notify all listeners that have registered interest for
     * notification on this event type.  The event instance
     * is lazily created using the parameters passed into
     * the fire method.
     * @see EventListenerList
     */
    protected void fireEditingStopped() {
        Object[] listeners = listenerList.getListenerList();
        for (int i = listeners.length - 2; i >= 0; i -= 2) {
            if (listeners[i] == CellEditorListener.class) {
                if (changeEvent == null)
                    changeEvent = new ChangeEvent(this);
                ((CellEditorListener) listeners[i + 1]).editingStopped(changeEvent);
            }
        }
    }


    /*
     * Notify all listeners that have registered interest for
     * notification on this event type.  The event instance
     * is lazily created using the parameters passed into
     * the fire method.
     * @see EventListenerList
     */
    protected void fireEditingCanceled() {
        Object[] listeners = listenerList.getListenerList();
        for (int i = listeners.length - 2; i >= 0; i -= 2) {
            if (listeners[i] == CellEditorListener.class) {
                if (changeEvent == null)
                    changeEvent = new ChangeEvent(this);
                ((CellEditorListener) listeners[i + 1]).editingCanceled(changeEvent);
            }
        }
    }

    public SComponent getTreeCellEditorComponent(STree tree, Object value,
                                                 boolean isSelected,
                                                 boolean expanded,
                                                 boolean leaf, int row) {

        delegate.setValue(value);
        tree.getParentFrame().setFocus( editorComponent );
        return editorPanel;
    }

    @Override
    public SComponent getTableCellEditorComponent(STable table, Object value,
                                                  boolean isSelected,
                                                  int row, int column) {
        delegate.setValue(value);
        table.getParentFrame().setFocus( editorComponent );
        return editorPanel;
    }


    //
    //  Protected EditorDelegate class
    //

    /**
     * The interface all editing boils down to: setting the value for
     * the editor and retrieve its value.
     */
    protected static class EditorDelegate {
        protected Object value;

        /**
         * Retrieve the value from the component used as Editor.
         * This method is called by the CellEditor to retrieve the
         * value after editing.
         *
         * @return the value managed by the Editor.
         */
        public Object getCellEditorValue() {
            return value;
        }

        /**
         * Set the Editors value. The task of this method is to
         * pass the value to the editor component so that editing
         * can be started.
         *
         * @param x the value to be edited.
         */
        public void setValue(Object x) {
            this.value = x;
        }

        public boolean isCellEditable(EventObject anEvent) {
            return true;
        }

        public boolean stopCellEditing() {
            return true;
        }

        public void cancelCellEditing() {
        }

        public boolean shouldSelectCell(EventObject anEvent) {
            return true;
        }
    }

    private final class FireEventListener implements ActionListener, Serializable {
        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        @Override
        public void actionPerformed(ActionEvent e) {
            if (e.getSource() == ok) {
                stopCellEditing();
            } else if (e.getSource() == cancel) {
                cancelCellEditing();
            }
        }
    }

    private class EditorPanel extends SPanel
        implements LowLevelEventListener
    {
        boolean okFinalEvents;
        boolean cancelFinalEvents;

        public EditorPanel() {
            super(new SBoxLayout(null, SBoxLayout.HORIZONTAL));
        }

        @Override
        public void processLowLevelEvent(String name, String... values) {
            if (name.endsWith("_panel")) {
                if ("ok".equals(values[0]))
                    okFinalEvents = true;
                else if ("cancel".equals(values[0]))
                    cancelFinalEvents = true;
            }
            else if (name.endsWith("_ed") && editorComponent instanceof LowLevelEventListener) {
                LowLevelEventListener lowLevelEventListener = (LowLevelEventListener) editorComponent;
                lowLevelEventListener.processLowLevelEvent(name, values);
            }

            SForm.addArmedComponent(this);
        }

        @Override
        public void fireIntermediateEvents() {
            if (okFinalEvents)
                stopCellEditing();
            if (cancelFinalEvents)
                cancelCellEditing();
            okFinalEvents = false;
            cancelFinalEvents = false;
        }

        @Override
        public void fireFinalEvents() {
            if (editorComponent instanceof LowLevelEventListener) {
                LowLevelEventListener lowLevelEventListener = (LowLevelEventListener) editorComponent;
                lowLevelEventListener.fireFinalEvents();
            }
        }

        @Override
        public void setNameRaw(String uncheckedName) {
            super.setNameRaw(uncheckedName + "_panel");
            editorComponent.setNameRaw(uncheckedName + "_ed");
            ok.setNameRaw(uncheckedName + "_ok");
            cancel.setNameRaw(uncheckedName + "_cl");
        }

        @Override
        public boolean isEpochCheckEnabled() {
            return true;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy