/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.eas.client.forms.components.model;
import com.eas.client.forms.events.CellRenderEvent;
import com.eas.client.forms.ModelCellEditingListener;
import com.eas.client.forms.Forms;
import com.eas.client.forms.HasComponentEvents;
import com.eas.client.forms.HasOnValueChange;
import com.eas.client.forms.IconCache;
import com.eas.client.forms.Widget;
import com.eas.client.forms.components.rt.HasValue;
import com.eas.client.forms.components.rt.VSpinner;
import com.eas.client.forms.events.ComponentEvent;
import com.eas.client.forms.events.ValueChangeEvent;
import com.eas.client.forms.events.rt.ControlEventsIProxy;
import com.eas.client.forms.layouts.MarginLayout;
import com.eas.design.Designable;
import com.eas.design.Undesignable;
import com.eas.script.AlreadyPublishedException;
import com.eas.script.EventMethod;
import com.eas.script.ScriptFunction;
import com.eas.script.Scripts;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.ParseException;
import java.util.EventObject;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractAction;
import javax.swing.AbstractButton;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.LineBorder;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import jdk.nashorn.api.scripting.AbstractJSObject;
import jdk.nashorn.api.scripting.JSObject;
import jdk.nashorn.internal.runtime.JSType;
/**
*
* @author mg
* @param <D>
* @param <V>
*/
public abstract class ModelComponentDecorator<D extends JComponent, V> extends JPanel implements HasOnValueChange, Widget, ModelWidget<V>, HasComponentEvents {
public static final int EXTRA_BUTTON_WIDTH = 18;
protected JTextField prefSizeCalculator = new JTextField();// DON't move to design!!!
protected JLabel iconLabel = new JLabel(" ");
protected JToolBar extraTools = new JToolBar();
protected Set<CellEditorListener> editorListeners = new HashSet<>();
protected Set<ActionListener> actionListeners = new HashSet<>();
protected D decorated;
protected int align = SwingConstants.LEFT;
protected JLabel gapLabel = new JLabel(" ");
protected Icon icon;
protected boolean selectOnly;
// Model interacting
protected JSObject published;
protected static final Color WDIGETS_BORDER_COLOR = controlsBorderColor();
public static final int WIDGETS_DEFAULT_WIDTH = 100;
public static final int WIDGETS_DEFAULT_HEIGHT = 100;
private static Color controlsBorderColor() {
Color lafGridColor = UIManager.getColor("Table.gridColor");
if (lafGridColor != null) {
return lafGridColor;
} else {
return new Color(103, 144, 185);
}
}
/**
* This class is intended to substitute standard action of "enter" in case
* of in-table controls. There are cases when "enter" action commits edited
* text and no table cell editing stop occurs. We need to get same results
* on enter key in both cases.
*/
protected class TextFieldsCommitAction extends AbstractAction {
public static final String COMMIT_ACTION_NAME = "notify-field-accept";
protected JFormattedTextField field;
public TextFieldsCommitAction(JFormattedTextField aField) {
super(COMMIT_ACTION_NAME);
field = aField;
}
@Override
public void actionPerformed(ActionEvent e) {
try {
field.commitEdit();
fireEditingStopped();
} catch (ParseException ex) {
// no op
}
}
}
public D getDecorated() {
return decorated;
}
protected PropertyChangeListener decoratedValueListener = (PropertyChangeEvent evt) -> {
firePropertyChange(VALUE_PROP_NAME, evt.getOldValue(), evt.getNewValue());
};
public void setDecorated(D aComponent) {
if (decorated != aComponent) {
if (decorated != null) {
decorated.removePropertyChangeListener(VALUE_PROP_NAME, decoratedValueListener);
remove(decorated);
}
decorated = aComponent;
if (decorated != null) {
decorated.setForeground(getForeground());
decorated.setFont(getFont());
decorated.setOpaque(false);
decorated.setBorder(null);
decorated.setInheritsPopupMenu(true);
add(decorated, BorderLayout.CENTER);
checkEvents(decorated);
decorated.addPropertyChangeListener(VALUE_PROP_NAME, decoratedValueListener);
}
}
}
@Override
public void injectPublished(JSObject aValue) {
published = aValue;
}
@Override
public Dimension getPreferredSize() {
int width = super.getPreferredSize().width;
int height = prefSizeCalculator.getPreferredSize().height;
if (width < WIDGETS_DEFAULT_WIDTH) {
width = WIDGETS_DEFAULT_WIDTH;
}
return new Dimension(width, height);
}
public ModelComponentDecorator() {
super();
setLayout(new BorderLayout());
setOpaque(true);
iconLabel.setOpaque(false);
iconLabel.setBorder(null);
iconLabel.setFocusable(false);
iconLabel.setText("");
iconLabel.setInheritsPopupMenu(true);
checkEvents(iconLabel);
//
gapLabel.setOpaque(false);
gapLabel.setBorder(null);
gapLabel.setFocusable(false);
gapLabel.setText("");
gapLabel.setInheritsPopupMenu(true);
checkEvents(gapLabel);
//
extraTools.setBorder(null);
extraTools.setBorderPainted(false);
extraTools.setFloatable(false);
extraTools.setOpaque(false);
extraTools.setFocusable(false);
extraTools.setInheritsPopupMenu(true);
recreateExtraEditingControls();
checkEvents(extraTools);
add(extraTools, BorderLayout.EAST);
//
setBorder(new LineBorder(WDIGETS_BORDER_COLOR));
}
public void fireCellEditingCompleted() {
for (CellEditorListener l : editorListeners.toArray(new CellEditorListener[]{})) {
if (l instanceof ModelCellEditingListener) {
((ModelCellEditingListener) l).cellEditingCompleted();
}
};
}
protected final void checkEvents(Component aComp) {
if (aComp != null) {
ControlEventsIProxy.reflectionInvokeARListener(aComp, "addActionListener", ActionListener.class, (ActionListener) (ActionEvent e) -> {
fireActionPerformed(e);
});
aComp.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
MouseListener[] mls = getMouseListeners();
if (mls != null && e.getSource() instanceof Component) {
e = SwingUtilities.convertMouseEvent((Component) e.getSource(), e, ModelComponentDecorator.this);
for (MouseListener ml : mls) {
ml.mouseClicked(e);
}
}
}
@Override
public void mousePressed(MouseEvent e) {
MouseListener[] mls = getMouseListeners();
if (mls != null && e.getSource() instanceof Component) {
e = SwingUtilities.convertMouseEvent((Component) e.getSource(), e, ModelComponentDecorator.this);
for (MouseListener ml : mls) {
ml.mousePressed(e);
}
}
}
@Override
public void mouseReleased(MouseEvent e) {
MouseListener[] mls = getMouseListeners();
if (mls != null && e.getSource() instanceof Component) {
e = SwingUtilities.convertMouseEvent((Component) e.getSource(), e, ModelComponentDecorator.this);
for (MouseListener ml : mls) {
ml.mouseReleased(e);
}
}
}
@Override
public void mouseEntered(MouseEvent e) {
MouseListener[] mls = getMouseListeners();
if (mls != null && e.getSource() instanceof Component) {
e = SwingUtilities.convertMouseEvent((Component) e.getSource(), e, ModelComponentDecorator.this);
for (MouseListener ml : mls) {
ml.mouseEntered(e);
}
}
}
@Override
public void mouseExited(MouseEvent e) {
MouseListener[] mls = getMouseListeners();
if (mls != null && e.getSource() instanceof Component) {
e = SwingUtilities.convertMouseEvent((Component) e.getSource(), e, ModelComponentDecorator.this);
for (MouseListener ml : mls) {
ml.mouseExited(e);
}
}
}
});
aComp.addMouseMotionListener(new MouseMotionListener() {
@Override
public void mouseDragged(MouseEvent e) {
MouseMotionListener[] mls = getMouseMotionListeners();
if (mls != null && e.getSource() instanceof Component) {
e = SwingUtilities.convertMouseEvent((Component) e.getSource(), e, ModelComponentDecorator.this);
for (MouseMotionListener mml : mls) {
mml.mouseDragged(e);
}
}
}
@Override
public void mouseMoved(MouseEvent e) {
MouseMotionListener[] mls = getMouseMotionListeners();
if (mls != null && e.getSource() instanceof Component) {
e = SwingUtilities.convertMouseEvent((Component) e.getSource(), e, ModelComponentDecorator.this);
for (MouseMotionListener mml : mls) {
mml.mouseMoved(e);
}
}
}
});
aComp.addMouseWheelListener((MouseWheelEvent e) -> {
MouseWheelListener[] mls = getMouseWheelListeners();
if (mls != null && e.getSource() instanceof Component) {
e = (MouseWheelEvent) SwingUtilities.convertMouseEvent((Component) e.getSource(), e, ModelComponentDecorator.this);
for (MouseWheelListener mwl : mls) {
mwl.mouseWheelMoved(e);
}
}
});
aComp.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
FocusListener[] fls = getFocusListeners();
if (fls != null) {
e.setSource(ModelComponentDecorator.this);
for (FocusListener fl : fls) {
fl.focusGained(e);
}
}
}
@Override
public void focusLost(FocusEvent e) {
FocusListener[] fls = getFocusListeners();
if (fls != null) {
e.setSource(ModelComponentDecorator.this);
for (FocusListener fl : fls) {
fl.focusLost(e);
}
}
}
});
aComp.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
KeyListener[] kls = getKeyListeners();
if (kls != null) {
e.setSource(ModelComponentDecorator.this);
for (KeyListener kl : kls) {
kl.keyTyped(e);
}
}
}
@Override
public void keyPressed(KeyEvent e) {
KeyListener[] kls = getKeyListeners();
if (kls != null) {
e.setSource(ModelComponentDecorator.this);
for (KeyListener kl : kls) {
kl.keyPressed(e);
}
}
}
@Override
public void keyReleased(KeyEvent e) {
KeyListener[] kls = getKeyListeners();
if (kls != null) {
e.setSource(ModelComponentDecorator.this);
for (KeyListener kl : kls) {
kl.keyReleased(e);
}
}
}
});
}
}
@ScriptFunction
@Undesignable
@Override
public String getName() {
return super.getName();
}
public int getAlign() {
return align;
}
public void setAlign(int aAlign) {
if (align != aAlign) {
remove(gapLabel);
align = aAlign;
if (align == SwingConstants.RIGHT) {
add(gapLabel, BorderLayout.EAST);
}
}
}
protected static void applySwingAlign2TextAlign(JTextField aTf, int aAlign) {
switch (aAlign) {
case SwingConstants.LEFT:
aTf.setHorizontalAlignment(JTextField.LEFT);
break;
case SwingConstants.RIGHT:
aTf.setHorizontalAlignment(JTextField.RIGHT);
break;
case SwingConstants.CENTER:
aTf.setHorizontalAlignment(JTextField.CENTER);
break;
}
}
@ScriptFunction(jsDoc = COMPONENT_POPUP_MENU_JSDOC)
@Override
public JPopupMenu getComponentPopupMenu() {
return super.getComponentPopupMenu();
}
@ScriptFunction
@Override
public void setComponentPopupMenu(JPopupMenu aMenu) {
super.setComponentPopupMenu(aMenu);
}
@ScriptFunction
@Override
public Cursor getCursor() {
return super.getCursor();
}
@ScriptFunction
@Override
public void setCursor(Cursor cursor) {
super.setCursor(cursor);
decorated.setCursor(cursor);
iconLabel.setCursor(cursor);
gapLabel.setCursor(cursor);
extraTools.setCursor(cursor);
}
@ScriptFunction
@Override
public boolean isFocusable() {
return super.isFocusable() && isEnabled();
}
@ScriptFunction
public Icon getIcon() {
return icon;
}
@ScriptFunction
public void setIcon(Icon aIcon) {
icon = aIcon;
iconLabel.setIcon(icon);
}
protected void addIconLabel() {
add(iconLabel, BorderLayout.WEST);
}
@ScriptFunction(jsDoc = VISIBLE_JSDOC)
@Override
public boolean getVisible() {
return super.isVisible();
}
@ScriptFunction
@Override
public void setVisible(boolean aValue) {
super.setVisible(aValue);
}
@ScriptFunction(jsDoc = FOCUSABLE_JSDOC)
@Override
public boolean getFocusable() {
return super.isFocusable();
}
@ScriptFunction
@Override
public void setFocusable(boolean aValue) {
super.setFocusable(aValue);
decorated.setFocusable(aValue);
}
@ScriptFunction(jsDoc = ENABLED_JSDOC)
@Override
public boolean getEnabled() {
return super.isEnabled();
}
@ScriptFunction
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
gapLabel.setEnabled(enabled);
iconLabel.setEnabled(enabled);
decorated.setEnabled(enabled);
extraTools.setEnabled(enabled);
for (Component comp : extraTools.getComponents()) {
comp.setEnabled(enabled);
}
}
@ScriptFunction(jsDoc = TOOLTIP_TEXT_JSDOC)
@Override
public String getToolTipText() {
return super.getToolTipText();
}
@ScriptFunction
@Override
public void setToolTipText(String text) {
super.setToolTipText(text);
gapLabel.setToolTipText(text);
iconLabel.setToolTipText(text);
decorated.setToolTipText(text);
extraTools.setToolTipText(text);
}
@ScriptFunction(jsDoc = OPAQUE_TEXT_JSDOC)
@Override
public boolean getOpaque() {
return super.isOpaque();
}
@ScriptFunction
@Override
public void setOpaque(boolean aValue) {
super.setOpaque(aValue);
}
@ScriptFunction
@Override
public JComponent getNextFocusableComponent() {
return (JComponent) super.getNextFocusableComponent();
}
@ScriptFunction
@Override
public void setNextFocusableComponent(JComponent aValue) {
super.setNextFocusableComponent(aValue);
}
@ScriptFunction(jsDoc = LEFT_JSDOC)
@Override
public int getLeft() {
return super.getLocation().x;
}
@ScriptFunction
@Override
public void setLeft(int aValue) {
if (super.getParent() != null && super.getParent().getLayout() instanceof MarginLayout) {
MarginLayout.ajustLeft(this, aValue);
}
super.setLocation(aValue, getTop());
}
@ScriptFunction(jsDoc = TOP_JSDOC)
@Override
public int getTop() {
return super.getLocation().y;
}
@ScriptFunction
@Override
public void setTop(int aValue) {
if (super.getParent() != null && super.getParent().getLayout() instanceof MarginLayout) {
MarginLayout.ajustTop(this, aValue);
}
super.setLocation(getLeft(), aValue);
}
@ScriptFunction(jsDoc = WIDTH_JSDOC)
@Override
public int getWidth() {
return super.getWidth();
}
@ScriptFunction
@Override
public void setWidth(int aValue) {
Widget.setWidth(this, aValue);
}
@ScriptFunction(jsDoc = HEIGHT_JSDOC)
@Override
public int getHeight() {
return super.getHeight();
}
@ScriptFunction
@Override
public void setHeight(int aValue) {
Widget.setHeight(this, aValue);
}
@ScriptFunction(jsDoc = FOCUS_JSDOC)
@Override
public void focus() {
super.requestFocus();
}
// Native API
@ScriptFunction(jsDoc = NATIVE_COMPONENT_JSDOC)
@Undesignable
@Override
public JComponent getComponent() {
return this;
}
@ScriptFunction(jsDoc = NATIVE_ELEMENT_JSDOC)
@Undesignable
@Override
public Object getElement() {
return null;
}
// binding
protected JSObject data;
protected String field;
protected JSObject boundToData;
protected PropertyChangeListener boundToValue;
private static final String FIELD_JSDOC = ""
+ "/**\n"
+ " * Model binding field.\n"
+ " */";
@ScriptFunction(jsDoc = FIELD_JSDOC)
@Designable(category = "model")
@Override
public String getField() {
return field;
}
@ScriptFunction
@Override
public void setField(String aField) throws Exception {
if (field == null ? aField != null : !field.equals(aField)) {
unbind();
field = aField;
bind();
}
}
@ScriptFunction(jsDoc = ""
+ "/**\n"
+ " * Object, bound to the widget.\n"
+ " */")
@Designable(category = "model")
@Override
public JSObject getData() {
return data;
}
@ScriptFunction
@Override
public void setData(JSObject aValue) {
if (data != null ? !data.equals(aValue) : aValue != null) {
unbind();
data = aValue;
bind();
}
}
protected boolean settingValueFromJs;
protected boolean settingValueToJs;
protected void bind() {
if (data != null && field != null && !field.isEmpty() && Scripts.isInitialized()) {
boundToData = Scripts.getSpace().listen(data, field, new AbstractJSObject() {
@Override
public Object call(Object thiz, Object... args) {
rebind();
return null;
}
});
Object oData = ModelWidget.getPathData(data, field);
setJsValue(oData);
boundToValue = (PropertyChangeEvent evt) -> {
if (!settingValueFromJs) {
settingValueToJs = true;
try {
ModelWidget.setPathData(data, field, Scripts.getSpace().toJs(evt.getNewValue()));
} finally {
settingValueToJs = false;
}
}
};
addValueChangeListener(boundToValue);
} else {
setJsValue(null);
}
}
private void rebind() {
if (!settingValueToJs) {
settingValueFromJs = true;
try {
Object newValue = ModelWidget.getPathData(data, field);
setJsValue(JSType.nullOrUndefined(newValue) ? null : newValue);
} finally {
settingValueFromJs = false;
}
}
}
protected void unbind() {
boolean wasBoundToData = boundToData != null;
if (boundToData != null) {
Scripts.unlisten(boundToData);
boundToData = null;
}
if (boundToValue != null) {
removeValueChangeListener(boundToValue);
boundToValue = null;
}
if (wasBoundToData) {
setValue(null);
}
}
private static final String ON_SELECT_JSDOC = ""
+ "/**\n"
+ "* Component's selection event handler function.\n"
+ "*/";
@ScriptFunction(jsDoc = ON_SELECT_JSDOC)
@Undesignable
@Override
public JSObject getOnSelect() {
return onSelect;
}
@ScriptFunction
@Override
public void setOnSelect(JSObject aValue) {
if (onSelect != null ? !onSelect.equals(aValue) : aValue != null) {
onSelect = aValue;
recreateExtraEditingControls();
revalidate();
repaint();
}
}
private static final String ON_RENDER_JSDOC = ""
+ "/**\n"
+ "* Component's rendering event handler function.\n"
+ "*/";
@ScriptFunction(jsDoc = ON_RENDER_JSDOC)
@EventMethod(eventClass = CellRenderEvent.class)
@Undesignable
@Override
public JSObject getOnRender() {
return onRender;
}
@ScriptFunction
@Override
public void setOnRender(JSObject aValue) {
onRender = aValue;
}
@Override
public Object getCellEditorValue() {
return getValue();
}
@Undesignable
@Override
public V getValue() {
if (decorated instanceof HasValue<?>) {
return ((HasValue<V>) decorated).getValue();
} else if (decorated instanceof VSpinner) {
return (V) ((VSpinner) decorated).getValue();
}
return null;
}
@Override
public void setValue(V aValue) {
if (decorated instanceof HasValue<?>) {
((HasValue<V>) decorated).setValue(aValue);
} else if (decorated instanceof VSpinner) {
((VSpinner) decorated).setValue((Double) aValue);
}
}
@Override
public Object getJsValue() {
return Scripts.getSpace() != null ? Scripts.getSpace().toJs(getValue()) : getValue();
}
@Override
public abstract void setJsValue(Object aValue);
@Override
public void addValueChangeListener(PropertyChangeListener listener) {
super.removePropertyChangeListener(VALUE_PROP_NAME, listener);
super.addPropertyChangeListener(VALUE_PROP_NAME, listener);
}
@Override
public void removeValueChangeListener(PropertyChangeListener listener) {
super.removePropertyChangeListener(VALUE_PROP_NAME, listener);
}
protected String error;
protected JPanel errorPanel = new JPanel();
@ScriptFunction(jsDoc = ERROR_JSDOC)
@Override
public String getError() {
return error;
}
@ScriptFunction
@Override
public void setError(String aValue) {
if (error == null ? aValue != null : !error.equals(aValue)) {
error = aValue;
remove(errorPanel);
if (error != null) {
errorPanel.setBackground(Color.red);
errorPanel.setToolTipText(aValue);
errorPanel.setPreferredSize(new Dimension(Integer.MAX_VALUE, 2));
add(errorPanel, BorderLayout.SOUTH);
}
revalidate();
repaint();
}
}
@ScriptFunction(jsDoc = BACKGROUND_JSDOC)
@Override
public Color getBackground() {
return super.getBackground();
}
@ScriptFunction
@Override
public void setBackground(Color aValue) {
super.setBackground(aValue);
}
@ScriptFunction(jsDoc = FOREGROUND_JSDOC)
@Override
public Color getForeground() {
return super.getForeground();
}
@ScriptFunction
@Override
public void setForeground(Color aValue) {
super.setForeground(aValue);
if (gapLabel != null) {
gapLabel.setForeground(aValue);
}
if (iconLabel != null) {
iconLabel.setForeground(aValue);
}
if (extraTools != null) {
extraTools.setForeground(aValue);
}
if (decorated != null) {
decorated.setForeground(aValue);
}
}
private static final String REDRAW_JSDOC = ""
+ "/**\n"
+ " * Redraw the component.\n"
+ " */";
@ScriptFunction(jsDoc = REDRAW_JSDOC)
public void redraw() {
rebind();
revalidate();
repaint();
}
protected abstract void setupCellRenderer(JTable table, int row, int column, boolean isSelected);
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
try {
setOpaque(true);
silent = true;
extraTools.setVisible(false);
setJsValue((V) value);
setupCellRenderer(table, row, column, isSelected);
if (hasFocus) {
setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
} else {
setBorder(null);
}
setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
return this;
} catch (Exception ex) {
Logger.getLogger(ModelComponentDecorator.class.getName()).log(Level.SEVERE, ex.getMessage(), ex);
return this;
}
}
protected PropertyChangeListener cellEditingCompletedAlerter = (PropertyChangeEvent evt) -> {
fireCellEditingCompleted();
};
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
try {
removeValueChangeListener(cellEditingCompletedAlerter);
setJsValue((V) value);
addValueChangeListener(cellEditingCompletedAlerter);
extraTools.setVisible(false);
EventQueue.invokeLater(() -> {
extraTools.setVisible(true);
});
return this;
} catch (Exception ex) {
Logger.getLogger(ModelComponentDecorator.class.getName()).log(Level.SEVERE, ex.getMessage(), ex);
return this;
}
}
@Override
public boolean isCellEditable(EventObject event) {
return (event instanceof MouseEvent && ((MouseEvent) event).getClickCount() > 1)
|| (event instanceof KeyEvent && ((KeyEvent) event).getKeyCode() == KeyEvent.VK_F2)
|| (event instanceof ActionEvent);
}
@Override
public boolean shouldSelectCell(EventObject anEvent) {
return true;
}
@Override
public boolean stopCellEditing() {
fireEditingStopped();
return true;
}
@Override
public void cancelCellEditing() {
fireEditingCancelled();
}
protected void fireEditingStopped() {
for (CellEditorListener l : editorListeners.toArray(new CellEditorListener[]{})) {
if (l != null) {
l.editingStopped(new ChangeEvent(this));
}
}
}
protected void fireEditingCancelled() {
for (CellEditorListener l : editorListeners.toArray(new CellEditorListener[]{})) {
if (l != null) {
l.editingCanceled(new ChangeEvent(this));
}
}
}
@Override
public void addCellEditorListener(CellEditorListener l) {
editorListeners.add(l);
}
@Override
public void removeCellEditorListener(CellEditorListener l) {
editorListeners.remove(l);
}
public void addActionListener(ActionListener l) {
actionListeners.add(l);
}
public void removeActionListener(ActionListener l) {
actionListeners.add(l);
}
protected void fireActionPerformed(ActionEvent e) {
e.setSource(this);
actionListeners.stream().forEach((l) -> {
l.actionPerformed(e);
});
}
@ScriptFunction
@Override
public boolean isSelectOnly() {
return selectOnly;
}
@ScriptFunction
@Override
public void setSelectOnly(boolean aValue) {
selectOnly = aValue;
}
@ScriptFunction
@Override
public Font getFont() {
return super.getFont();
}
@ScriptFunction
@Override
public void setFont(Font aValue) {
super.setFont(aValue);
if (gapLabel != null) {
gapLabel.setFont(aValue);
}
if (iconLabel != null) {
iconLabel.setFont(aValue);
}
if (extraTools != null) {
extraTools.setFont(aValue);
}
if (decorated != null) {
decorated.setFont(aValue);
}
Font f = getFont();
if (f != null && prefSizeCalculator != null) {
prefSizeCalculator.setFont(f);
}
}
protected JSObject onSelect;
protected JSObject onRender;
protected boolean nullable = true;
@ScriptFunction
@Override
public boolean getNullable() {
return nullable;
}
@ScriptFunction
@Override
public void setNullable(boolean aValue) {
if (nullable != aValue) {
nullable = aValue;
recreateExtraEditingControls();
}
}
protected void recreateExtraEditingControls() {
extraTools.removeAll();
if (onSelect != null) {
JButton btnSelectingField = new JButton();
btnSelectingField.setAction(new ModelComponentDecorator.ValueSelectorAction(onSelect));
btnSelectingField.setPreferredSize(new Dimension(EXTRA_BUTTON_WIDTH, EXTRA_BUTTON_WIDTH));
btnSelectingField.setFocusable(false);
extraTools.add(btnSelectingField);
}
if (nullable) {
JButton btnNullingField = new JButton();
btnNullingField.setAction(new NullerAction());
btnNullingField.setPreferredSize(new Dimension(EXTRA_BUTTON_WIDTH, EXTRA_BUTTON_WIDTH));
//btnNullingField.setFocusable(false);
extraTools.add(btnNullingField);
}
for (Component comp : extraTools.getComponents()) {
comp.setEnabled(isEnabled());
checkEvents(comp);
}
}
public boolean haveSelectorAction() {
for (Component comp : extraTools.getComponents()) {
if (comp instanceof AbstractButton) {
AbstractButton ab = (AbstractButton) comp;
if (ab.getAction() instanceof ModelComponentDecorator.ValueSelectorAction) {
return true;
}
}
}
return false;
}
public boolean haveNullerAction() {
for (Component comp : extraTools.getComponents()) {
if (comp instanceof AbstractButton) {
AbstractButton ab = (AbstractButton) comp;
if (ab.getAction() instanceof ModelComponentDecorator.NullerAction) {
return true;
}
}
}
return false;
}
private class NullerAction extends AbstractAction {
NullerAction() {
super();
putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 0));
putValue(Action.SHORT_DESCRIPTION, Forms.getLocalizedString(NullerAction.class.getSimpleName()));
putValue(Action.SMALL_ICON, IconCache.getIcon("16x16/delete.png"));
}
@Override
public void actionPerformed(ActionEvent e) {
try {
setValue(null);
} catch (Exception ex) {
Logger.getLogger(ModelComponentDecorator.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private class ValueSelectorAction extends AbstractAction {
protected JSObject selector;
ValueSelectorAction(JSObject aSelector) {
super();
putValue(Action.NAME, "...");
putValue(Action.SHORT_DESCRIPTION, Forms.getLocalizedString(ValueSelectorAction.class.getSimpleName()));
selector = aSelector;
}
@Override
public void actionPerformed(ActionEvent e) {
if (selector != null && getPublished() != null) {
try {
selector.call(getPublished(), new Object[]{getPublished()});
} catch (Exception ex) {
Logger.getLogger(ModelComponentDecorator.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
protected boolean silent;
@Override
protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
if (!silent) {
super.firePropertyChange(propertyName, oldValue, newValue);
}
}
@Override
public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {
if (!silent) {
super.firePropertyChange(propertyName, oldValue, newValue);
}
}
/**
* Overridden for performance reasons. See the <a
* href="#override">Implementation Note</a> for more information.
*/
@Override
public void repaint(long tm, int x, int y, int width, int height) {
if (!silent) {
super.repaint(tm, x, y, width, height);
}
}
public abstract JSObject getPublished();
public void setPublished(JSObject aValue) {
if (published != null) {
throw new AlreadyPublishedException();
}
published = aValue;
}
protected ControlEventsIProxy eventsProxy = new ControlEventsIProxy(this);
@ScriptFunction(jsDoc = ON_MOUSE_CLICKED_JSDOC)
@EventMethod(eventClass = com.eas.client.forms.events.MouseEvent.class)
@Undesignable
@Override
public JSObject getOnMouseClicked() {
return eventsProxy.getHandlers().get(ControlEventsIProxy.mouseClicked);
}
@ScriptFunction
@Override
public void setOnMouseClicked(JSObject aValue) {
eventsProxy.getHandlers().put(ControlEventsIProxy.mouseClicked, aValue);
}
@ScriptFunction(jsDoc = ON_MOUSE_DRAGGED_JSDOC)
@EventMethod(eventClass = com.eas.client.forms.events.MouseEvent.class)
@Undesignable
@Override
public JSObject getOnMouseDragged() {
return eventsProxy.getHandlers().get(ControlEventsIProxy.mouseDragged);
}
@ScriptFunction
@Override
public void setOnMouseDragged(JSObject aValue) {
eventsProxy.getHandlers().put(ControlEventsIProxy.mouseDragged, aValue);
}
@ScriptFunction(jsDoc = ON_MOUSE_ENTERED_JSDOC)
@EventMethod(eventClass = com.eas.client.forms.events.MouseEvent.class)
@Undesignable
@Override
public JSObject getOnMouseEntered() {
return eventsProxy.getHandlers().get(ControlEventsIProxy.mouseEntered);
}
@ScriptFunction
@Override
public void setOnMouseEntered(JSObject aValue) {
eventsProxy.getHandlers().put(ControlEventsIProxy.mouseEntered, aValue);
}
@ScriptFunction(jsDoc = ON_MOUSE_EXITED_JSDOC)
@EventMethod(eventClass = com.eas.client.forms.events.MouseEvent.class)
@Undesignable
@Override
public JSObject getOnMouseExited() {
return eventsProxy.getHandlers().get(ControlEventsIProxy.mouseExited);
}
@ScriptFunction
@Override
public void setOnMouseExited(JSObject aValue) {
eventsProxy.getHandlers().put(ControlEventsIProxy.mouseExited, aValue);
}
@ScriptFunction(jsDoc = ON_MOUSE_MOVED_JSDOC)
@EventMethod(eventClass = com.eas.client.forms.events.MouseEvent.class)
@Undesignable
@Override
public JSObject getOnMouseMoved() {
return eventsProxy.getHandlers().get(ControlEventsIProxy.mouseMoved);
}
@ScriptFunction
@Override
public void setOnMouseMoved(JSObject aValue) {
eventsProxy.getHandlers().put(ControlEventsIProxy.mouseMoved, aValue);
}
@ScriptFunction(jsDoc = ON_MOUSE_PRESSED_JSDOC)
@EventMethod(eventClass = com.eas.client.forms.events.MouseEvent.class)
@Undesignable
@Override
public JSObject getOnMousePressed() {
return eventsProxy.getHandlers().get(ControlEventsIProxy.mousePressed);
}
@ScriptFunction
@Override
public void setOnMousePressed(JSObject aValue) {
eventsProxy.getHandlers().put(ControlEventsIProxy.mousePressed, aValue);
}
@ScriptFunction(jsDoc = ON_MOUSE_RELEASED_JSDOC)
@EventMethod(eventClass = com.eas.client.forms.events.MouseEvent.class)
@Undesignable
@Override
public JSObject getOnMouseReleased() {
return eventsProxy.getHandlers().get(ControlEventsIProxy.mouseReleased);
}
@ScriptFunction
@Override
public void setOnMouseReleased(JSObject aValue) {
eventsProxy.getHandlers().put(ControlEventsIProxy.mouseReleased, aValue);
}
@ScriptFunction(jsDoc = ON_MOUSE_WHEEL_MOVED_JSDOC)
@EventMethod(eventClass = com.eas.client.forms.events.MouseEvent.class)
@Undesignable
@Override
public JSObject getOnMouseWheelMoved() {
return eventsProxy.getOnMouseWheelMoved();
}
@ScriptFunction
@Override
public void setOnMouseWheelMoved(JSObject aValue) {
eventsProxy.setOnMouseWheelMoved(aValue);
}
@ScriptFunction(jsDoc = ON_ACTION_PERFORMED_JSDOC)
@EventMethod(eventClass = com.eas.client.forms.events.ActionEvent.class)
@Undesignable
@Override
public JSObject getOnActionPerformed() {
return eventsProxy.getHandlers().get(ControlEventsIProxy.actionPerformed);
}
@ScriptFunction
@Override
public void setOnActionPerformed(JSObject aValue) {
eventsProxy.getHandlers().put(ControlEventsIProxy.actionPerformed, aValue);
}
@ScriptFunction(jsDoc = ON_COMPONENT_HIDDEN_JSDOC)
@EventMethod(eventClass = ComponentEvent.class)
@Undesignable
@Override
public JSObject getOnComponentHidden() {
return eventsProxy.getHandlers().get(ControlEventsIProxy.componentHidden);
}
@ScriptFunction
@Override
public void setOnComponentHidden(JSObject aValue) {
eventsProxy.getHandlers().put(ControlEventsIProxy.componentHidden, aValue);
}
@ScriptFunction(jsDoc = ON_COMPONENT_MOVED_JSDOC)
@EventMethod(eventClass = ComponentEvent.class)
@Undesignable
@Override
public JSObject getOnComponentMoved() {
return eventsProxy.getHandlers().get(ControlEventsIProxy.componentMoved);
}
@ScriptFunction
@Override
public void setOnComponentMoved(JSObject aValue) {
eventsProxy.getHandlers().put(ControlEventsIProxy.componentMoved, aValue);
}
@ScriptFunction(jsDoc = ON_COMPONENT_RESIZED_JSDOC)
@EventMethod(eventClass = ComponentEvent.class)
@Undesignable
@Override
public JSObject getOnComponentResized() {
return eventsProxy.getHandlers().get(ControlEventsIProxy.componentResized);
}
@ScriptFunction
@Override
public void setOnComponentResized(JSObject aValue) {
eventsProxy.getHandlers().put(ControlEventsIProxy.componentResized, aValue);
}
@ScriptFunction(jsDoc = ON_COMPONENT_SHOWN_JSDOC)
@EventMethod(eventClass = ComponentEvent.class)
@Undesignable
@Override
public JSObject getOnComponentShown() {
return eventsProxy.getHandlers().get(ControlEventsIProxy.componentShown);
}
@ScriptFunction
@Override
public void setOnComponentShown(JSObject aValue) {
eventsProxy.getHandlers().put(ControlEventsIProxy.componentShown, aValue);
}
@ScriptFunction(jsDoc = ON_FOCUS_GAINED_JSDOC)
@EventMethod(eventClass = FocusEvent.class)
@Undesignable
@Override
public JSObject getOnFocusGained() {
return eventsProxy.getHandlers().get(ControlEventsIProxy.focusGained);
}
@ScriptFunction
@Override
public void setOnFocusGained(JSObject aValue) {
eventsProxy.getHandlers().put(ControlEventsIProxy.focusGained, aValue);
}
@ScriptFunction(jsDoc = ON_FOCUS_LOST_JSDOC)
@EventMethod(eventClass = FocusEvent.class)
@Undesignable
@Override
public JSObject getOnFocusLost() {
return eventsProxy != null ? eventsProxy.getHandlers().get(ControlEventsIProxy.focusLost) : null;
}
@ScriptFunction
@Override
public void setOnFocusLost(JSObject aValue) {
eventsProxy.getHandlers().put(ControlEventsIProxy.focusLost, aValue);
}
@ScriptFunction(jsDoc = ON_KEY_PRESSED_JSDOC)
@EventMethod(eventClass = KeyEvent.class)
@Undesignable
@Override
public JSObject getOnKeyPressed() {
return eventsProxy.getHandlers().get(ControlEventsIProxy.keyPressed);
}
@ScriptFunction
@Override
public void setOnKeyPressed(JSObject aValue) {
eventsProxy.getHandlers().put(ControlEventsIProxy.keyPressed, aValue);
}
@ScriptFunction(jsDoc = ON_KEY_RELEASED_JSDOC)
@EventMethod(eventClass = KeyEvent.class)
@Undesignable
@Override
public JSObject getOnKeyReleased() {
return eventsProxy.getHandlers().get(ControlEventsIProxy.keyReleased);
}
@ScriptFunction
@Override
public void setOnKeyReleased(JSObject aValue) {
eventsProxy.getHandlers().put(ControlEventsIProxy.keyReleased, aValue);
}
@ScriptFunction(jsDoc = ON_KEY_TYPED_JSDOC)
@EventMethod(eventClass = KeyEvent.class)
@Undesignable
@Override
public JSObject getOnKeyTyped() {
return eventsProxy.getHandlers().get(ControlEventsIProxy.keyTyped);
}
@ScriptFunction
@Override
public void setOnKeyTyped(JSObject aValue) {
eventsProxy.getHandlers().put(ControlEventsIProxy.keyTyped, aValue);
}
@ScriptFunction(jsDoc = ON_VALUE_CHANED_JSDOC)
@EventMethod(eventClass = ValueChangeEvent.class)
@Undesignable
@Override
public JSObject getOnValueChange() {
return eventsProxy.getHandlers().get(ControlEventsIProxy.valueChanged);
}
@ScriptFunction
@Override
public void setOnValueChange(JSObject aValue) {
eventsProxy.getHandlers().put(ControlEventsIProxy.valueChanged, aValue);
}
// published parent
@ScriptFunction(name = "parent", jsDoc = PARENT_JSDOC)
@Override
public Widget getParentWidget() {
return Forms.lookupPublishedParent(this);
}
}