Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.nuiton.jaxx.application.swing.AbstractApplicationUIHandler Maven / Gradle / Ivy
package org.nuiton.jaxx.application.swing;
/*
* #%L
* JAXX :: Application Swing
* %%
* Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit
* %%
* This program 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 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 Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import jaxx.runtime.JAXXUtil;
import jaxx.runtime.SwingUtil;
import jaxx.runtime.spi.UIHandler;
import jaxx.runtime.swing.JAXXWidgetUtil;
import jaxx.runtime.swing.editor.FileEditor;
import jaxx.runtime.swing.editor.NumberEditor;
import jaxx.runtime.swing.editor.SimpleTimeEditor;
import jaxx.runtime.swing.editor.bean.BeanComboBox;
import jaxx.runtime.swing.editor.bean.BeanDoubleList;
import jaxx.runtime.swing.editor.bean.BeanFilterableComboBox;
import jaxx.runtime.swing.editor.bean.BeanUIUtil;
import jaxx.runtime.swing.editor.cell.NumberCellEditor;
import jaxx.runtime.swing.editor.gis.DmdCoordinateEditor;
import jaxx.runtime.swing.editor.gis.DmsCoordinateEditor;
import jaxx.runtime.swing.renderer.DecoratorListCellRenderer;
import jaxx.runtime.swing.renderer.DecoratorTableCellRenderer;
import jaxx.runtime.validator.swing.SwingValidator;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdesktop.swingx.JXDatePicker;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.autocomplete.ComboBoxCellEditor;
import org.jdesktop.swingx.autocomplete.ObjectToStringConverter;
import org.jdesktop.swingx.table.TableColumnExt;
import org.nuiton.decorator.Decorator;
import org.nuiton.decorator.JXPathDecorator;
import org.nuiton.jaxx.application.ApplicationConfiguration;
import org.nuiton.jaxx.application.bean.JavaBeanObjectUtil;
import org.nuiton.jaxx.application.swing.action.AbstractApplicationAction;
import org.nuiton.jaxx.application.swing.action.ApplicationActionUI;
import org.nuiton.jaxx.application.swing.action.ApplicationUIAction;
import org.nuiton.jaxx.application.swing.table.ColumnIdentifier;
import org.nuiton.jaxx.application.swing.util.ApplicationUIUtil;
import org.nuiton.jaxx.application.swing.util.Cancelable;
import org.nuiton.jaxx.application.type.ApplicationProgressionModel;
import org.nuiton.validator.bean.AbstractValidator;
import org.nuiton.validator.bean.list.BeanListValidator;
import org.nuiton.validator.bean.simple.SimpleBeanValidator;
import javax.swing.AbstractAction;
import javax.swing.AbstractButton;
import javax.swing.Action;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JRootPane;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JViewport;
import javax.swing.KeyStroke;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.LineBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;
import javax.swing.text.JTextComponent;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.awt.event.ItemEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.Serializable;
import java.text.ParseException;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.nuiton.i18n.I18n.t;
/**
* Handler of any ui.
*
* Created on 11/23/13.
*
* @author Tony Chemit - [email protected]
* @since 2.8
*/
public abstract class AbstractApplicationUIHandler> implements UIHandler {
/** Logger. */
private static final Log log =
LogFactory.getLog(AbstractApplicationUIHandler.class);
public abstract void onCloseUI();
/**
* @return a single validator :(
* @deprecated since 2.10, prefer use now the {@link #getSimpleValidators()} and {@link #getListValidators()} initialized in {@link #initUI(ApplicationUI)} method.
*/
@Deprecated
public abstract SwingValidator getValidator();
public abstract Component getTopestUI();
public abstract Decorator getDecorator(Class beanType, String decoratorContext);
/**
* Hook to prepare popup just before showing it.
*
* The right place to update actions accessibility; a quite better design
* than trying to update each time something change in the table...
*
* @param modelRowIndex selected row index (or lowest selected one)
* @param modelColumnIndex selected column index
* @since 2.6
*/
protected void beforeOpenPopup(int modelRowIndex, int modelColumnIndex) {
// by default do nothing
}
/**
* Global application context.
*/
private ApplicationUIContext context;
/**
* UI handled.
*/
protected UI ui;
/**
* Simple validators detected in {@link #initUI(ApplicationUI)} method.
*
* @since 2.10
*/
private Set simpleValidators;
/**
* List validators detected in {@link #initUI(ApplicationUI)} method.
*
* @since 2.10
*/
private Set listValidators;
//------------------------------------------------------------------------//
//-- Public methods --//
//------------------------------------------------------------------------//
/**
* @deprecated since 2.10, should move this to {@link SwingUtil#newComboModel(Object...)}
*/
@Deprecated
public DefaultComboBoxModel newComboModel(Object... items) {
return SwingUtil.newComboModel(items);
}
public final M getModel() {
return ui.getModel();
}
public final UI getUI() {
return ui;
}
public Set getSimpleValidators() {
return simpleValidators;
}
public Set getListValidators() {
return listValidators;
}
@Override
public void beforeInit(UI ui) {
this.ui = ui;
}
public ApplicationUIContext getContext() {
if (context == null) {
context = ApplicationUIUtil.getApplicationContext(ui);
}
return context;
}
public void setText(KeyEvent event, String property) {
JTextComponent field = (JTextComponent) event.getSource();
String value = field.getText();
JavaBeanObjectUtil.setProperty(getModel(), property, value);
}
public void setFile(ActionEvent event, String property) {
FileEditor field = (FileEditor) event.getSource();
File value = field.getSelectedFile();
JavaBeanObjectUtil.setProperty(getModel(), property, value);
}
public void setBoolean(ItemEvent event, String property) {
boolean value = event.getStateChange() == ItemEvent.SELECTED;
JavaBeanObjectUtil.setProperty(getModel(), property, value);
}
public void setDate(ActionEvent event, String property) {
JXDatePicker field = (JXDatePicker) event.getSource();
Date value = field.getDate();
JavaBeanObjectUtil.setProperty(getModel(), property, value);
}
public void selectListData(ListSelectionEvent event, String property) {
if (!event.getValueIsAdjusting()) {
JList list = (JList) event.getSource();
ListSelectionModel selectionModel = list.getSelectionModel();
selectionModel.setValueIsAdjusting(true);
try {
List selectedList = Lists.newLinkedList();
for (int index : list.getSelectedIndices()) {
Object o = list.getModel().getElementAt(index);
selectedList.add(o);
}
JavaBeanObjectUtil.setProperty(getModel(), property, selectedList);
} finally {
selectionModel.setValueIsAdjusting(false);
}
}
}
public void openDialog(ApplicationUI dialogContent,
String title, Dimension dim) {
Component topestUI = getTopestUI();
JDialog result;
if (topestUI instanceof Frame) {
result = new JDialog((Frame) topestUI, title, true);
} else {
result = new JDialog((Dialog) topestUI, title, true);
}
result.add((Component) dialogContent);
result.setResizable(true);
result.setSize(dim);
final AbstractApplicationUIHandler handler = dialogContent.getHandler();
if (handler instanceof Cancelable) {
// add a auto-close action
JRootPane rootPane = result.getRootPane();
KeyStroke shortcutClosePopup = getContext().getConfiguration().getShortcutClosePopup();
rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
shortcutClosePopup, "close");
rootPane.getActionMap().put("close", new AbstractAction() {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e) {
((Cancelable) handler).cancel();
}
});
}
result.addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
Component ui = (Component) e.getSource();
if (log.isDebugEnabled()) {
log.debug("Destroy ui " + ui);
}
JAXXUtil.destroy(ui);
}
});
SwingUtil.center(getContext().getMainUI(), result);
result.setVisible(true);
}
public void closeDialog() {
getParentContainer(JDialog.class).setVisible(false);
}
public U getParentContainer(Class uiType) {
return SwingUtil.getParentContainer(ui, uiType);
}
public static final String CONFIRMATION_FORMAT = "%s %s";
public int askSaveBeforeLeaving(String message) {
String htmlMessage = String.format(
CONFIRMATION_FORMAT,
message,
t("jaxx.application.common.askSaveBeforeLeaving.help"));
return JOptionPane.showConfirmDialog(
getTopestUI(),
htmlMessage,
t("jaxx.application.common.askSaveBeforeLeaving.title"),
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE);
}
public boolean askCancelEditBeforeLeaving(String message) {
String htmlMessage = String.format(
CONFIRMATION_FORMAT,
message,
t("jaxx.application.common.askCancelEditBeforeLeaving.help"));
int i = JOptionPane.showConfirmDialog(
getTopestUI(),
htmlMessage,
t("jaxx.application.common.askCancelEditBeforeLeaving.title"),
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE);
return i == JOptionPane.OK_OPTION;
}
public void showSuccessMessage(String title, String message) {
Component topestUI = getTopestUI();
boolean alwaysOnTop = false;
if (topestUI instanceof JDialog) {
alwaysOnTop = ((JDialog) topestUI).isAlwaysOnTop();
}
if (alwaysOnTop) {
((JDialog) topestUI).setAlwaysOnTop(false);
}
try {
JOptionPane.showMessageDialog(
topestUI,
message,
title,
JOptionPane.INFORMATION_MESSAGE,
UIManager.getIcon("info")
);
} finally {
if (alwaysOnTop) {
((JDialog) topestUI).setAlwaysOnTop(true);
}
}
}
protected void addHighlighters(final JXTable table) {
}
public void autoSelectRowInTable(MouseEvent e, JPopupMenu popup) {
boolean rightClick = SwingUtilities.isRightMouseButton(e);
if (rightClick || SwingUtilities.isLeftMouseButton(e)) {
// get the coordinates of the mouse click
Point p = e.getPoint();
JXTable source = (JXTable) e.getSource();
int[] selectedRows = source.getSelectedRows();
int[] selectedColumns = source.getSelectedColumns();
// get the row index at this point
int rowIndex = source.rowAtPoint(p);
// get the column index at this point
int columnIndex = source.columnAtPoint(p);
if (log.isDebugEnabled()) {
log.debug("At point [" + p + "] found Row " + rowIndex + ", Column " + columnIndex);
}
boolean canContinue = true;
if (source.isEditing()) {
// stop editing
boolean stopEdit = source.getCellEditor().stopCellEditing();
if (!stopEdit) {
if (log.isWarnEnabled()) {
log.warn("Could not stop edit cell...");
}
canContinue = false;
}
}
if (canContinue) {
// select row (could empty selection)
if (rowIndex == -1) {
source.clearSelection();
} else if (!ArrayUtils.contains(selectedRows, rowIndex)) {
if (ListSelectionModel.MULTIPLE_INTERVAL_SELECTION == source.getSelectionMode()) {
// add to selection
source.addRowSelectionInterval(rowIndex, rowIndex);
} else {
// set selection
source.setRowSelectionInterval(rowIndex, rowIndex);
}
}
// select column (could empty selection)
if (columnIndex == -1) {
source.clearSelection();
} else if (!ArrayUtils.contains(selectedColumns, columnIndex)) {
source.setColumnSelectionInterval(columnIndex, columnIndex);
}
if (rightClick) {
// use now model coordinate
int modelRowIndex = rowIndex == -1 ? -1 : source.convertRowIndexToModel(rowIndex);
int modelColumnIndex = columnIndex == -1 ? -1 : source.convertColumnIndexToModel(columnIndex);
beforeOpenPopup(modelRowIndex, modelColumnIndex);
// on right click show popup
popup.show(source, e.getX(), e.getY());
}
}
}
}
public void openRowMenu(KeyEvent e, JPopupMenu popup) {
if (e.getKeyCode() == KeyEvent.VK_CONTEXT_MENU) {
JXTable source = (JXTable) e.getSource();
// get the lowest selected row
int[] selectedRows = source.getSelectedRows();
int lowestRow = -1;
for (int row : selectedRows) {
lowestRow = Math.max(lowestRow, row);
}
// get the selected column
int selectedColumn = source.getSelectedColumn();
Rectangle r = source.getCellRect(lowestRow, selectedColumn, true);
// get the point in the middle lower of the cell
Point p = new Point(r.x + r.width / 2, r.y + r.height);
if (log.isDebugEnabled()) {
log.debug("Row " + lowestRow + " found t point [" + p + "]");
}
boolean canContinue = true;
if (source.isEditing()) {
// stop editing
boolean stopEdit = source.getCellEditor().stopCellEditing();
if (!stopEdit) {
if (log.isWarnEnabled()) {
log.warn("Could not stop edit cell...");
}
canContinue = false;
}
}
if (canContinue) {
// use now model coordinate
int rowIndex = source.convertRowIndexToModel(lowestRow);
int columnIndex = source.convertColumnIndexToModel(selectedColumn);
beforeOpenPopup(rowIndex, columnIndex);
popup.show(source, p.x, p.y);
}
}
}
//------------------------------------------------------------------------//
//-- Init methods --//
//------------------------------------------------------------------------//
protected void initUIComponent(Object component) {
if (component instanceof NumberEditor) {
initNumberEditor((NumberEditor) component);
} else if (component instanceof JXDatePicker) {
initDatePicker((JXDatePicker) component);
} else if (component instanceof SimpleTimeEditor) {
initTimeEditor((SimpleTimeEditor) component);
} else if (component instanceof JLabel) {
initLabel((JLabel) component);
} else if (component instanceof JTextField) {
initTextField((JTextField) component);
} else if (component instanceof AbstractButton) {
initButton((AbstractButton) component);
} else if (component instanceof JScrollPane) {
initScrollPane((JScrollPane) component);
} else if (component instanceof DmsCoordinateEditor) {
initCoordinateDMSEditor((DmsCoordinateEditor) component);
} else if (component instanceof DmdCoordinateEditor) {
initCoordinateDMDEditor((DmdCoordinateEditor) component);
} else if (component instanceof SimpleBeanValidator) {
simpleValidators.add((SimpleBeanValidator) component);
} else if (component instanceof BeanListValidator) {
listValidators.add((BeanListValidator) component);
}
}
protected void initUI(UI ui) {
simpleValidators = Sets.newHashSet();
listValidators = Sets.newHashSet();
for (Map.Entry entry : ui.get$objectMap().entrySet()) {
Object component = entry.getValue();
initUIComponent(component);
}
simpleValidators = Collections.unmodifiableSet(simpleValidators);
listValidators = Collections.unmodifiableSet(listValidators);
initValidators(simpleValidators, listValidators);
//FIXME This does not work if there is more than one ui
initComponentToFocus((Component) ui);
}
protected void initComponentToFocus(Component ui) {
ui.addHierarchyListener(new HierarchyListener() {
@Override
public void hierarchyChanged(HierarchyEvent e) {
JComponent component = getComponentToFocus();
if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) > 0
&& e.getChanged().isShowing()
&& component != null) {
component.requestFocus();
}
}
});
}
protected abstract JComponent getComponentToFocus();
protected void initTextField(JTextField jTextField) {
if (isAutoSelectOnFocus(jTextField)) {
addAutoSelectOnFocus(jTextField);
}
}
protected void initLabel(JLabel jLabel) {
// by default do nothing more
}
protected void initButton(AbstractButton abstractButton) {
Class actionName = (Class) abstractButton.getClientProperty("applicationAction");
if (actionName != null) {
Action action = getContext().getActionFactory().createUIAction(this, abstractButton, actionName);
abstractButton.setAction(action);
}
if (abstractButton.getAction() != null) {
// get the _applicationActionKey property
String key = (String) abstractButton.getClientProperty("applicationActionKey");
if (key != null) {
affectKeyStroke(abstractButton, key);
}
}
}
protected void affectKeyStroke(AbstractButton abstractButton, String key) {
if (abstractButton.getAction() == null) {
log.warn("the buton '" + abstractButton.getName() + "' has no action. can't affect key stroke.");
return;
}
KeyStroke keyStroke = KeyStroke.getKeyStroke(key);
if (keyStroke == null) {
if (log.isWarnEnabled()) {
log.warn("Could not transform keyStroke: " + key);
}
} else {
// affect this key stroke to the button's action
abstractButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(keyStroke, key);
abstractButton.getActionMap().put(key, abstractButton.getAction());
boolean modifyText = true;
boolean modifyTip = false;
ApplicationConfiguration configuration = context.getConfiguration();
if (configuration instanceof ApplicationUIConfiguration) {
ApplicationUIConfiguration applicationUIConfiguration = (ApplicationUIConfiguration) configuration;
modifyText = applicationUIConfiguration.isShowKeyStrokeOnText();
modifyTip = applicationUIConfiguration.isShowKeyStrokeOnTip();
}
// modify text
String text = abstractButton.getText();
if (modifyText && !StringUtils.isBlank(text)) {
text += " (" + key.toUpperCase() + ")";
abstractButton.setText(text);
}
// modify tip
String tip = abstractButton.getToolTipText();
if (modifyTip && !StringUtils.isBlank(tip)) {
tip += " (" + key.toUpperCase() + ")";
abstractButton.setToolTipText(tip);
}
}
}
/**
* Prépare un component de choix d'entités pour un type d'entité donné et
* pour un service de persistance donné.
*
* @param comboBox le component graphique à initialiser
*/
protected void initBeanFilterableComboBox(
BeanFilterableComboBox comboBox,
List data,
E selectedData) {
initBeanFilterableComboBox(comboBox, data, selectedData, null);
}
protected void initBeanFilterableComboBox(
BeanFilterableComboBox comboBox,
List data,
E selectedData,
String decoratorContext) {
Preconditions.checkNotNull(comboBox, "No comboBox!");
Class beanType = comboBox.getBeanType();
Preconditions.checkNotNull(beanType, "No beanType on the combobox!");
Decorator decorator = getDecorator(beanType, decoratorContext);
if (data == null) {
data = Lists.newArrayList();
}
if (log.isDebugEnabled()) {
log.debug("entity comboBox list [" + beanType.getName() + "] : " + data.size());
}
comboBox.setI18nPrefix(getContext().getI18nPrefix());
// add data list to combo box
comboBox.init((JXPathDecorator) decorator, data);
comboBox.setSelectedItem(selectedData);
if (log.isDebugEnabled()) {
log.debug("combo [" + beanType.getName() + "] : " +
comboBox.getData().size());
}
}
protected void initBeanComboBox(BeanComboBox comboBox,
List data,
E selectedData) {
initBeanComboBox(comboBox, data, selectedData, null);
}
protected void initBeanComboBox(BeanComboBox comboBox,
List data,
E selectedData,
String decoratorContext) {
Preconditions.checkNotNull(comboBox, "No comboBox!");
Class beanType = comboBox.getBeanType();
Preconditions.checkNotNull(beanType, "No beanType on the combobox!");
Decorator decorator = getDecorator(beanType, decoratorContext);
if (data == null) {
data = Lists.newArrayList();
}
if (log.isDebugEnabled()) {
log.debug("entity comboBox list [" + beanType.getName() + "] : " + data.size());
}
comboBox.setI18nPrefix(getContext().getI18nPrefix());
// add data list to combo box
comboBox.init((JXPathDecorator) decorator, data);
comboBox.setSelectedItem(selectedData);
if (log.isDebugEnabled()) {
log.debug("combo [" + beanType.getName() + "] : " +
comboBox.getData().size());
}
}
/**
* Prépare un component de choix d'entités pour un type d'entité donné et
* pour un service de persistance donné.
*
* @param list le component graphique à initialiser
* @param data la liste des données à mettre dans la liste de gauche
* @param selectedData la liste des données à mettre dans la liste de droite
*/
protected void initBeanList(BeanDoubleList list,
List data,
List selectedData,
Decorator selectedDecorator) {
Preconditions.checkNotNull(list, "No list!");
Class beanType = list.getBeanType();
Preconditions.checkNotNull(beanType, "No beanType on the double list!");
Decorator decorator = getDecorator(beanType, null);
if (log.isDebugEnabled()) {
log.debug("entity list [" + beanType.getName() + "] : " +
(data == null ? 0 : data.size()));
}
list.setI18nPrefix(getContext().getI18nPrefix());
// add data list to combo box
list.init((JXPathDecorator) decorator,
(JXPathDecorator) selectedDecorator,
data,
selectedData);
if (log.isDebugEnabled()) {
log.debug("Jlist [" + beanType.getName() + "] : " +
list.getUniverseList().getModel().getSize());
}
}
/**
* Prépare un component de choix d'entités pour un type d'entité donné et
* pour un service de persistance donné.
*
* @param list le component graphique à initialiser
* @param data la liste des données à mettre dans la liste de gauche
* @param selectedData la liste des données à mettre dans la liste de droite
*/
protected void initBeanList(BeanDoubleList list,
List data,
List selectedData) {
initBeanList(list, data, selectedData, null);
}
protected void initNumberEditor(NumberEditor editor) {
if (log.isDebugEnabled()) {
log.debug("init number editor " + editor.getName());
}
editor.init();
// Force binding if value is already in model
Number model = editor.getModel();
if (model != null) {
editor.setModel(null);
editor.setModel(model);
}
if (isAutoSelectOnFocus(editor)) {
addAutoSelectOnFocus(editor.getTextField());
}
}
protected void initTimeEditor(SimpleTimeEditor editor) {
if (log.isDebugEnabled()) {
log.debug("init time editor " + editor.getName() +
" for property " + editor.getModel().getProperty());
}
editor.init();
if (isAutoSelectOnFocus(editor)) {
addAutoSelectOnFocus(((JSpinner.DefaultEditor) editor.getHour().getEditor()).getTextField());
addAutoSelectOnFocus(((JSpinner.DefaultEditor) editor.getMinute().getEditor()).getTextField());
}
}
protected void initCoordinateDMSEditor(DmsCoordinateEditor editor) {
Object property = editor.getClientProperty("longitudeEditor");
boolean longitudeEditor = property != null && Boolean.valueOf(property.toString());
editor.init(longitudeEditor);
}
protected void initCoordinateDMDEditor(DmdCoordinateEditor editor) {
Object property = editor.getClientProperty("longitudeEditor");
boolean longitudeEditor = property != null && Boolean.valueOf(property.toString());
editor.init(longitudeEditor);
}
protected void initDatePicker(final JXDatePicker picker) {
if (log.isDebugEnabled()) {
log.debug("disable JXDatePicker editor" + picker.getName());
}
String dateFormat = getContext().getDateFormat();
picker.setFormats(dateFormat);
picker.setToolTipText(t("jaxx.application.common.datefield.tip", dateFormat));
picker.getEditor().addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent e) {
try {
picker.commitEdit();
} catch (ParseException ex) {
if (log.isDebugEnabled()) {
log.debug("format error", ex);
}
picker.requestFocus();
}
}
});
if (isAutoSelectOnFocus(picker)) {
addAutoSelectOnFocus(picker.getEditor());
}
}
protected void initScrollPane(JScrollPane scrollPane) {
Boolean onlyVerticalScrollable = (Boolean) scrollPane.getClientProperty("onlyVerticalScrollable");
if (onlyVerticalScrollable != null && onlyVerticalScrollable) {
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
final JViewport viewport = scrollPane.getViewport();
viewport.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
Dimension newDimension = new Dimension(viewport.getExtentSize().width,
viewport.getViewSize().height);
viewport.setViewSize(newDimension);
}
});
}
}
protected void initValidators(Set simpleValidators, Set listValidators) {
M model = getModel();
if (useSimpleValidators() || useListValidators()) {
Set validators = Sets.newHashSet();
validators.addAll(simpleValidators);
validators.addAll(listValidators);
ValidatorsValidPropertyChangeListener listener = new ValidatorsValidPropertyChangeListener((AbstractApplicationFormUIModel) model, validators);
for (AbstractValidator validator : validators) {
if (log.isInfoEnabled()) {
log.info("Listen valid state of validator: " + validator);
}
validator.addPropertyChangeListener(SimpleBeanValidator.VALID_PROPERTY, listener);
}
}
}
protected boolean useListValidators() {
return getModel() instanceof AbstractApplicationFormUIModel && !listValidators.isEmpty();
}
protected boolean useSimpleValidators() {
return getModel() instanceof AbstractApplicationFormUIModel && !simpleValidators.isEmpty();
}
protected boolean isAutoSelectOnFocus(JComponent comp) {
Object selectOnFocus = comp.getClientProperty("selectOnFocus");
return selectOnFocus != null && Boolean.valueOf(selectOnFocus.toString());
}
protected void addAutoSelectOnFocus(JTextField jTextField) {
jTextField.addFocusListener(new FocusAdapter() {
@Override
public void focusGained(final FocusEvent e) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JTextField source = (JTextField) e.getSource();
source.selectAll();
}
});
}
});
}
/**
* @deprecated since 2.11, use now {@link #quitScreen(boolean, boolean, String, String, Action, boolean)}
*/
@Deprecated
protected boolean quitScreen(boolean modelIsValid,
boolean modelIsModify,
String askGiveUpMessage,
String askSaveMessage,
Action saveAction) {
return quitScreen(modelIsValid,
modelIsModify,
askGiveUpMessage,
askSaveMessage,
saveAction,
false);
}
/**
* @deprecated since 2.11, use now {@link #quitScreen(boolean, boolean, String, String, Action, boolean)}
*/
@Deprecated
protected boolean quitInternalScreen(boolean modelIsValid,
boolean modelIsModify,
String askGiveUpMessage,
String askSaveMessage,
Action saveAction) {
return quitScreen(modelIsValid,
modelIsModify,
askGiveUpMessage,
askSaveMessage,
saveAction,
true);
}
protected boolean quitScreen(boolean modelIsValid,
boolean modelIsModify,
String askGiveUpMessage,
String askSaveMessage,
Action saveAction,
boolean runInternal) {
boolean result;
if (!modelIsValid) {
// model is not valid
// ask user to qui or not
result = askCancelEditBeforeLeaving(askGiveUpMessage);
} else if (modelIsModify) {
// something is modify ask user what to do
int answer = askSaveBeforeLeaving(askSaveMessage);
switch (answer) {
case JOptionPane.YES_OPTION:
// ok save
if (runInternal) {
ApplicationUIAction uiAction = (ApplicationUIAction) saveAction;
getContext().getActionEngine().runFullInternalAction(uiAction.getLogicAction());
} else {
saveAction.actionPerformed(null);
}
result = true;
break;
case JOptionPane.NO_OPTION:
// do not save but can still quit the screen (so nothing to do)
result = true;
break;
default:
// do not save and stay here (so nothing to do)
result = false;
}
} else {
// model is valid and not modify, can safely quit screen
result = true;
}
return result;
}
//------------------------------------------------------------------------//
//-- Decorator API --//
//------------------------------------------------------------------------//
protected String decorate(Serializable object) {
return decorate(object, null);
}
protected String decorate(Serializable object, String context) {
String result = "";
if (object != null) {
result = getDecorator(object.getClass(), context).toString(object);
}
return result;
}
//------------------------------------------------------------------------//
//-- List API --//
//------------------------------------------------------------------------//
protected ListCellRenderer newListCellRender(Class type) {
return newListCellRender(type, null);
}
protected ListCellRenderer newListCellRender(Class type, String name) {
Decorator decorator = getDecorator(type, name);
return newListCellRender(decorator);
}
protected ListCellRenderer newListCellRender(Decorator decorator) {
Preconditions.checkNotNull(decorator);
return new DecoratorListCellRenderer(decorator);
}
//FIXME Move this in JAXX
protected void changeValidatorContext(String newContext,
SwingValidator validator) {
B bean = validator.getBean();
validator.setContext(newContext);
validator.setBean(bean);
}
//------------------------------------------------------------------------//
//-- Table API --//
//------------------------------------------------------------------------//
protected TableColumnExt addColumnToModel(TableColumnModel model,
TableCellEditor editor,
TableCellRenderer renderer,
ColumnIdentifier identifier) {
TableColumnExt col = new TableColumnExt(model.getColumnCount());
col.setCellEditor(editor);
col.setCellRenderer(renderer);
String label = t(identifier.getHeaderI18nKey());
col.setHeaderValue(label);
String tip = t(identifier.getHeaderTipI18nKey());
col.setToolTipText(tip);
col.setIdentifier(identifier);
model.addColumn(col);
// by default no column is sortable, must specify it
col.setSortable(false);
return col;
}
protected TableColumnExt addColumnToModel(TableColumnModel model,
ColumnIdentifier identifier) {
return addColumnToModel(model, null, null, identifier);
}
protected TableColumnExt addFloatColumnToModel(TableColumnModel model,
ColumnIdentifier identifier,
String numberPattern,
boolean sign,
JTable table) {
NumberCellEditor editor =
JAXXWidgetUtil.newNumberTableCellEditor(Float.class, sign);
editor.getNumberEditor().setSelectAllTextOnError(true);
editor.getNumberEditor().getTextField().setBorder(new LineBorder(Color.GRAY, 2));
editor.getNumberEditor().setNumberPattern(numberPattern);
TableCellRenderer renderer =
newNumberCellRenderer(table.getDefaultRenderer(Number.class));
return addColumnToModel(model, editor, renderer, identifier);
}
protected TableColumnExt addFloatColumnToModel(TableColumnModel model,
ColumnIdentifier identifier,
String numberPattern,
JTable table) {
return addFloatColumnToModel(model, identifier, numberPattern, false, table);
}
protected TableColumnExt addIntegerColumnToModel(TableColumnModel model,
ColumnIdentifier identifier,
String numberPattern,
boolean sign,
JTable table) {
NumberCellEditor editor =
JAXXWidgetUtil.newNumberTableCellEditor(Integer.class, sign);
editor.getNumberEditor().setSelectAllTextOnError(true);
editor.getNumberEditor().getTextField().setBorder(new LineBorder(Color.GRAY, 2));
editor.getNumberEditor().setNumberPattern(numberPattern);
TableCellRenderer renderer = newNumberCellRenderer(table.getDefaultRenderer(Number.class));
return addColumnToModel(model, editor, renderer, identifier);
}
protected TableColumnExt addIntegerColumnToModel(TableColumnModel model,
ColumnIdentifier identifier,
String numberPattern,
JTable table) {
return addIntegerColumnToModel(model, identifier, numberPattern, false, table);
}
protected TableCellRenderer newNumberCellRenderer(final TableCellRenderer defaultRenderer) {
return new TableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component result1 = defaultRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (result1 instanceof JLabel) {
JLabel jLabel = (JLabel) result1;
jLabel.setHorizontalTextPosition(SwingConstants.RIGHT);
}
return result1;
}
};
}
protected TableColumnExt addBooleanColumnToModel(TableColumnModel model,
ColumnIdentifier identifier,
JTable table) {
return addColumnToModel(model,
table.getDefaultEditor(Boolean.class),
table.getDefaultRenderer(Boolean.class),
identifier);
}
protected TableColumnExt addComboDataColumnToModel(TableColumnModel model,
ColumnIdentifier identifier,
Decorator decorator,
List data) {
JComboBox comboBox = new JComboBox();
comboBox.setRenderer(newListCellRender(decorator));
List dataToList = Lists.newArrayList(data);
// add a null value at first position
if (!dataToList.isEmpty() && dataToList.get(0) != null) {
dataToList.add(0, null);
}
SwingUtil.fillComboBox(comboBox, dataToList, null);
ObjectToStringConverter converter = BeanUIUtil.newDecoratedObjectToStringConverter(decorator);
BeanUIUtil.decorate(comboBox, converter);
ComboBoxCellEditor editor = new ComboBoxCellEditor(comboBox);
return addColumnToModel(model,
editor,
newTableCellRender(decorator),
identifier);
}
protected TableCellRenderer newTableCellRender(Class type) {
return newTableCellRender(type, null);
}
protected TableCellRenderer newTableCellRender(Class type, String name) {
Decorator decorator = getDecorator(type, name);
return newTableCellRender(decorator);
}
protected TableCellRenderer newTableCellRender(Decorator decorator) {
Preconditions.checkNotNull(decorator);
return new DecoratorTableCellRenderer(decorator, true);
}
protected void incrementsMessage(String message) {
ApplicationActionUI actionUI = getContext().getActionUI();
if (actionUI != null) {
ApplicationProgressionModel progressionModel = actionUI.getModel().getProgressionModel();
if (progressionModel != null)
progressionModel.increments(message);
}
}
/**
*
*/
private static class ValidatorsValidPropertyChangeListener implements PropertyChangeListener {
private final AbstractApplicationFormUIModel model;
private final Set validators;
public ValidatorsValidPropertyChangeListener(AbstractApplicationFormUIModel model,
Set validators) {
this.model = model;
this.validators = validators;
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
boolean valid = true;
for (AbstractValidator validator : validators) {
if (!validator.isValid()) {
valid = false;
break;
}
}
model.setValid(valid);
}
}
protected static class RunFullInternalActionListener implements PropertyChangeListener {
private final ApplicationUIContext context;
private final AbstractApplicationAction uiAction;
public RunFullInternalActionListener(ApplicationUIContext context, AbstractApplicationUIHandler handler, Class actionName) {
this.context = context;
this.uiAction = context.getActionFactory().createLogicAction(handler, actionName);
}
protected boolean doPropertyChange(PropertyChangeEvent evt) {
return true;
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
boolean doPropertyChange = doPropertyChange(evt);
if (doPropertyChange) {
if (log.isInfoEnabled()) {
log.info("Execute action start: " + uiAction);
}
context.getActionEngine().runFullInternalAction(uiAction);
if (log.isInfoEnabled()) {
log.info("Execute action end: " + uiAction);
}
}
}
}
}