/* PANDA -- a simple transaction monitor
Copyright (C) 1998-1999 Ogochan.
2000-2003 Ogochan & JMA (Japan Medical Association).
2002-2006 OZAWA Sakuro.
This module is part of PANDA.
PANDA is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
to anyone for the consequences of using it or for whether it serves
any particular purpose or works at all, unless he says so in writing.
Refer to the GNU General Public License for full details.
Everyone is granted permission to copy, modify and redistribute
PANDA, but only under the conditions described in the GNU General
Public License. A copy of this license is supposed to have been given
to you along with PANDA so you can know your rights and
responsibilities. It should be in a file named COPYING. Among other
things, the copyright notice and this notice must be preserved on all
copies.
*/
package org.montsuqi.monsia;
import java.awt.Component;
import java.awt.Window;
import java.awt.event.*;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.JTextComponent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.montsuqi.client.SignalHandler;
import org.montsuqi.client.UIControl;
import org.montsuqi.widgets.*;
/**
* <p>
* A class to connect Gtk+ signal names to signal hender objects.</p>
*/
abstract class Connector {
private static Map<String, Connector> connectors;
protected static final Logger logger = LogManager.getLogger(Connector.class);
abstract void connect(UIControl uiControl, Component target, SignalHandler handler, Object other);
public static Connector getConnector(String signalName) {
if (connectors.containsKey(signalName)) {
final Connector connector = connectors.get(signalName);
logger.exit();
return connector;
}
logger.debug("connector not found for signal {0}", signalName);
final Connector connector = getConnector(null);
return connector;
}
/**
* <p>
* A helper method which invokes handler's handle method.</p>
* <p>
* This method wraps the sequence of invocation of a handler's handle method
* and its eception handling. All IOExceptions are catched and notified via
* exceptionOccured.</p>
*/
static void invoke(final UIControl con, final SignalHandler handler, final Component target, final Object other) {
try {
handler.handle(con, target, other);
} catch (IOException e) {
con.exceptionOccured(e);
}
}
private static void registerConnector(String signalName, Connector connector) {
connectors.put(signalName, connector);
}
static {
connectors = new HashMap<>();
registerConnector(null, new Connector() {
@Override
public void connect(final UIControl con, final Component target, final SignalHandler handler, final Object other) {
// do nothing
}
});
registerConnector("clicked", new Connector() {
@Override
public void connect(final UIControl con, final Component target, final SignalHandler handler, final Object other) {
if (!(target instanceof AbstractButton)) {
return;
}
// RadioButton event happens only on toggled.
if (target instanceof JRadioButton) {
return;
}
AbstractButton button = (AbstractButton) target;
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
invoke(con, handler, target, other);
}
});
}
});
registerConnector("button_press_event", getConnector("clicked")); //$NON-NLS-2$
registerConnector("key_press_event", new Connector() {
@Override
public void connect(final UIControl con, final Component target, final SignalHandler handler, final Object other) {
target.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
invoke(con, handler, target, other);
}
}
});
}
});
registerConnector("changed", new Connector() {
@Override
public void connect(final UIControl con, final Component target, final SignalHandler handler, final Object other) {
if (target instanceof PandaCombo) {
final PandaCombo combo = (PandaCombo) target;
ComboBoxModel model = combo.getModel();
final Component c = combo.getEditor().getEditorComponent();
model.addListDataListener(new ListDataListener() {
@Override
public void contentsChanged(ListDataEvent e) {
invoke(con, handler, c, other);
}
@Override
public void intervalAdded(ListDataEvent e) {
// do nothing
}
@Override
public void intervalRemoved(ListDataEvent e) {
// do nothing
}
});
combo.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
invoke(con, handler, c, other);
}
});
} else if (target instanceof JTextComponent) {
final JTextComponent text = (JTextComponent) target;
text.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent event) {
invoke(con, handler, target, other);
}
@Override
public void removeUpdate(DocumentEvent event) {
invoke(con, handler, target, other);
}
@Override
public void changedUpdate(DocumentEvent event) {
invoke(con, handler, target, other);
}
});
}
}
});
registerConnector("activate", new Connector() {
@Override
public void connect(final UIControl con, final Component target, final SignalHandler handler, final Object other) {
if (target instanceof PandaCombo) {
PandaCombo combo = (PandaCombo) target;
Component c = combo.getEditor().getEditorComponent();
connect(con, c, handler, other);
} else if (target instanceof JTextField) {
final JTextField textField = (JTextField) target;
textField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
invoke(con, handler, target, other);
}
});
} else if (target instanceof JTextArea) {
final JTextArea textArea = (JTextArea) target;
textArea.addKeyListener(new KeyListener() {
@Override
public void keyPressed(KeyEvent e) {
if (e.isControlDown() && e.getKeyCode() == KeyEvent.VK_ENTER) {
invoke(con, handler, target, other);
}
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
}
});
} else if (target instanceof JMenuItem) {
JMenuItem item = (JMenuItem) target;
item.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
invoke(con, handler, target, other);
}
});
}
}
});
registerConnector("enter", getConnector("activate")); //$NON-NLS-2$
registerConnector("focus_in_event", new Connector() {
@Override
public void connect(final UIControl con, final Component target, final SignalHandler handler, final Object other) {
target.addFocusListener(new FocusAdapter() {
@Override
public void focusGained(FocusEvent e) {
invoke(con, handler, target, other);
}
});
}
});
registerConnector("focus_out_event", new Connector() {
@Override
public void connect(final UIControl con, final Component target, final SignalHandler handler, final Object other) {
target.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent e) {
invoke(con, handler, target, other);
}
});
}
});
registerConnector("map_event", new Connector() {
@Override
public void connect(final UIControl con, final Component target, final SignalHandler handler, final Object other) {
if (target instanceof Window) {
Window window = (Window) target;
window.addWindowListener(new WindowAdapter() {
@Override
public void windowOpened(WindowEvent e) {
invoke(con, handler, target, other);
}
});
} else {
target.addComponentListener(new ComponentAdapter() {
@Override
public void componentShown(ComponentEvent e) {
invoke(con, handler, target, other);
}
});
}
}
});
registerConnector("delete_event", new Connector() {
@Override
public void connect(final UIControl con, final Component target, final SignalHandler handler, final Object other) {
if (target instanceof Window) {
Window window = (Window) target;
window.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
invoke(con, handler, target, other);
}
});
} else {
target.addComponentListener(new ComponentAdapter() {
@Override
public void componentHidden(ComponentEvent e) {
invoke(con, handler, target, other);
}
});
}
}
});
registerConnector("destroy", new Connector() {
@Override
public void connect(final UIControl con, final Component target, final SignalHandler handler, final Object other) {
if (target instanceof Window) {
Window window = (Window) target;
window.addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
invoke(con, handler, target, other);
}
});
} else {
target.addComponentListener(new ComponentAdapter() {
@Override
public void componentHidden(ComponentEvent e) {
invoke(con, handler, target, other);
}
});
}
}
});
registerConnector("set_focus", new Connector() {
@Override
public void connect(final UIControl con, final Component target, final SignalHandler handler, final Object other) {
target.addFocusListener(new FocusAdapter() {
@Override
public void focusGained(FocusEvent e) {
invoke(con, handler, target, other);
}
});
}
});
registerConnector("select_row", new Connector() {
@Override
public void connect(final UIControl con, final Component target, final SignalHandler handler, final Object other) {
if (target instanceof PandaCList) {
PandaCList table = (PandaCList) target;
table.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
invoke(con, handler, target, other);
}
});
}
}
});
registerConnector("unselect_row", new Connector() {
@Override
public void connect(UIControl con, Component target, SignalHandler handler, Object other) {
// XxxSelectionModels don't care selection/unselection so use connectSelectRow
// Object[] args = { target, handler, other};
// logger.debug("unselect_row: target={0}, handler={1}, other={2}", args);
// connectSelectRow(target, handler, other);
}
});
registerConnector("selection_changed", getConnector("select_row")); //$NON-NLS-2$
registerConnector("click_column", new Connector() {
@Override
public void connect(UIControl con, Component target, SignalHandler handler, Object other) {
Object[] args = {target, handler, other};
}
});
registerConnector("switch_page", new Connector() {
@Override
public void connect(final UIControl con, final Component target, final SignalHandler handler, final Object other) {
if (!(target instanceof JTabbedPane)) {
return;
}
if (handler.getSignalName().equals("no_switch_page")) {
Notebook notebook = (Notebook) target;
notebook.setSwitchPage(false);
return;
}
JTabbedPane tabbedPane = (JTabbedPane) target;
tabbedPane.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent event) {
invoke(con, handler, target, other);
}
});
}
});
registerConnector("toggled", new Connector() {
@Override
public void connect(final UIControl con, final Component target, final SignalHandler handler, final Object other) {
if (!(target instanceof JToggleButton)) {
return;
}
final JToggleButton toggle = (JToggleButton) target;
if (target instanceof JRadioButton) {
toggle.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
ButtonGroup g = (ButtonGroup) toggle.getClientProperty("group");
JRadioButton deselected = null;
if (g == null) {
return;
}
Enumeration elements = g.getElements();
while (elements.hasMoreElements()) {
JRadioButton radio = (JRadioButton) elements.nextElement();
if (radio.isSelected()) {
deselected = radio;
break;
}
}
if (deselected == null) {
return;
}
JRadioButton none = (JRadioButton) deselected.getClientProperty("none");
none.setSelected(true);
final Object o = "CLICKED";
invoke(con, handler, deselected, o);
SignalHandler sendEvent = SignalHandler.getSignalHandler("send_event");
assert sendEvent != null;
invoke(con, sendEvent, deselected, o);
toggle.setSelected(true);
invoke(con, handler, target, o);
invoke(con, sendEvent, target, o);
}
});
} else {
toggle.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
if (toggle.isSelected()) {
invoke(con, handler, target, other);
}
}
});
}
}
});
registerConnector("timeout", new Connector() {
@Override
public void connect(final UIControl con, final Component target, final SignalHandler handler, final Object other) {
if (!(target instanceof PandaTimer)) {
return;
}
PandaTimer timer = (PandaTimer) target;
timer.addTimerListener(new TimerListener() {
@Override
public void timerSignaled(TimerEvent e) {
invoke(con, handler, target, other);
}
});
}
});
registerConnector("day_selected", new Connector() {
@Override
public void connect(final UIControl con, final Component target, final SignalHandler handler, final Object other) {
if (!(target instanceof Calendar)) {
return;
}
Calendar cal = (Calendar) target;
cal.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
invoke(con, handler, target, other);
}
});
}
});
registerConnector("selection_get", new Connector() {
@Override
public void connect(final UIControl con, final Component target, final SignalHandler handler, final Object other) {
if (target instanceof JMenuItem) {
JMenuItem item = (JMenuItem) target;
item.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
invoke(con, handler, target, other);
}
});
}
}
});
registerConnector("file_set", new Connector() {
@Override
public void connect(final UIControl con, final Component target, final SignalHandler handler, final Object other) {
if (target instanceof FileChooserButton) {
FileChooserButton fcb = (FileChooserButton) target;
fcb.getBrowseButton().addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
invoke(con, handler, target, other);
}
});
}
}
});
registerConnector("color_set", new Connector() {
@Override
public void connect(final UIControl con, final Component target, final SignalHandler handler, final Object other) {
if (target instanceof ColorButton) {
ColorButton cb = (ColorButton) target;
cb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
invoke(con, handler, target, other);
}
});
}
}
});
registerConnector("cell_edited", new Connector() {
@Override
public void connect(final UIControl con, final Component target, final SignalHandler handler, final Object other) {
if (target instanceof PandaTable) {
final PandaTable table = (PandaTable) target;
table.getModel().addTableModelListener(
new TableModelListener() {
@Override
public void tableChanged(TableModelEvent te) {
if (table.isEnterPressed()) {
int row = te.getLastRow();
int col = te.getColumn();
table.setChangedRow(row);
table.setChangedColumn(col);
table.setChangedValue(table.getStringValueAt(row, col));
invoke(con, handler, target, other);
}
table.setEnterPressed(false);
}
});
}
}
});
}
}