/*
 * Created on 17.08.2004
 */
package de.renew.gui;

import java.awt.Component;
import java.awt.event.MouseEvent;
import java.io.Serializable;
import java.util.EventObject;
import javax.swing.JComponent;
import javax.swing.JTable;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.EventListenerList;
import javax.swing.table.TableCellEditor;
import javax.swing.tree.TreeCellEditor;


public class JComponentCellEditor implements TableCellEditor, TreeCellEditor, Serializable {
    protected final EventListenerList listenerList = new EventListenerList();
    protected transient ChangeEvent changeEvent = null;
    protected JComponent editorComponent = null;
    protected JComponent container = null;
    protected TableCellEditor tableCellEditor;
    protected TreeCellEditor treeCellEditor;

    public JComponentCellEditor(TableCellEditor tableEditor, TreeCellEditor treeEditor) {
        this.tableCellEditor = tableEditor;
        this.treeCellEditor = treeEditor;
    }

    public Component getComponent() {
        return editorComponent;
    }

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

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

    @Override
    public boolean shouldSelectCell(EventObject anEvent) {
        if (editorComponent != null && anEvent instanceof MouseEvent e
            && e.getID() == MouseEvent.MOUSE_PRESSED) {
            Component dispatchComponent =
                SwingUtilities.getDeepestComponentAt(editorComponent, 3, 3);
            MouseEvent e2 = new MouseEvent(
                dispatchComponent, MouseEvent.MOUSE_RELEASED, e.getWhen() + 100000,
                e.getModifiersEx(), 3, 3, e.getClickCount(), e.isPopupTrigger());
            dispatchComponent.dispatchEvent(e2);
            e2 = new MouseEvent(
                dispatchComponent, MouseEvent.MOUSE_CLICKED, e.getWhen() + 100001,
                e.getModifiersEx(), 3, 3, 1, e.isPopupTrigger());
            dispatchComponent.dispatchEvent(e2);
        }

        return false;
    }

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

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

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

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

    protected void fireEditingStopped() {
        Object[] listeners = listenerList.getListenerList();


        // Process the listeners last to first, notifying
        // those that are interested in this event
        for (int i = listeners.length - 2; i >= 0; i -= 2) {
            if (listeners[i] == CellEditorListener.class) {
                // Lazily create the event:
                if (changeEvent == null) {
                    changeEvent = new ChangeEvent(this);
                }
                ((CellEditorListener) listeners[i + 1]).editingStopped(changeEvent);
            }
        }
    }

    protected void fireEditingCanceled() {
        Object[] listeners = listenerList.getListenerList();

        // Notify listeners that are interested in this event
        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);
            }
        }
    }

    // implementation of javax.swing.tree.TreeCellEditor
    @Override
    public Component getTreeCellEditorComponent(
        JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row)
    {
        if (value instanceof JComponent component) {
            editorComponent = component;
            container = tree;
            return editorComponent;
        }

        return this.treeCellEditor
            .getTreeCellEditorComponent(tree, value, isSelected, expanded, leaf, row);
    }

    // implementation of javax.swing.table.TableCellEditor
    @Override
    public Component getTableCellEditorComponent(
        JTable table, Object value, boolean isSelected, int row, int column)
    {
        if (value instanceof JComponent component) {
            editorComponent = component;
            container = table;
            return editorComponent;
        }

        return this.tableCellEditor
            .getTableCellEditorComponent(table, value, isSelected, row, column);
    }
}