/*
* Rapid Beans Framework: EditorBeanSwing.java
*
* Copyright (C) 2009 Martin Bluemel
*
* Creation Date: 02/13/2006
*
* 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 Lesser General Public License for more details.
* You should have received a copies of the GNU Lesser General Public License and the
* GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
package org.rapidbeans.presentation.swing;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import org.rapidbeans.core.basic.Property;
import org.rapidbeans.core.basic.PropertyCollection;
import org.rapidbeans.core.basic.RapidBean;
import org.rapidbeans.core.basic.ThreadLocalValidationSettings;
import org.rapidbeans.core.exception.ValidationException;
import org.rapidbeans.core.exception.ValidationReadonlyException;
import org.rapidbeans.presentation.Application;
import org.rapidbeans.presentation.DocumentView;
import org.rapidbeans.presentation.EditorBean;
import org.rapidbeans.presentation.EditorProperty;
/**
* the bean editor GUI.
*
* @author Martin Bluemel
*/
// TODO Framework 21) introduce null selection for enum choices and
// 1 : 0..1 collections
public class EditorBeanSwing extends EditorBean {
/**
* the tree view's scroll pane.
*/
private JScrollPane scrollPane = new JScrollPane();
/**
* the panel.
*/
private JPanel panel = new JPanel();
/**
* the north panel. The construct to stick a further panel into the "NORTH"
* section of the main panel with BIrderLayout causes the editor to be
* aligned to the upper window boundary.
*/
private JPanel panelProps = new JPanel();
/**
* the button panel.
*/
private JPanel panelButtons = new JPanel();
/**
* the OK button.
*/
private JButton buttonOk = new JButton();
/**
* getter for testing reasons.
*
* @return the apply button.
*/
protected JButton getButtonOk() {
return this.buttonOk;
}
/**
* the OK button.
*/
private JButton buttonApply = new JButton();
/**
* getter for testing reasons.
*
* @return the apply button.
*/
protected JButton getButtonApply() {
return this.buttonApply;
}
/**
* the OK button.
*/
private JButton buttonClose = new JButton();
/**
* getter for testing reasons.
*
* @return the close button.
*/
protected JButton getButtonClose() {
return this.buttonClose;
}
/**
* @return the view's widget
*/
public Object getWidget() {
return this.panel;
}
/**
* constructor.
*
* @param client
* the client
* @param docView
* the parent document view
* @param bizBean
* the bean to edit
* @param newBeanParentColProp
* a new Bean's parent collection property. Is not null if a new
* Bean is to be created Is null if an existing bean is simply
* edited
*/
public EditorBeanSwing(final Application client, final DocumentView docView, final RapidBean bizBean,
final PropertyCollection newBeanParentColProp) {
super(client, docView, bizBean, newBeanParentColProp);
int i = 0;
this.panel.setLayout(new BorderLayout());
this.panelProps.setLayout(new GridBagLayout());
boolean editorWithYExtension = false;
for (EditorProperty propEditor : this.getPropEditors()) {
this.panelProps.add((Component) propEditor.getLabelWidget(), new GridBagConstraints(0, i, 1, 1, 0.0, 0.0,
GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
if (propEditor instanceof EditorPropertyListSwing) {
editorWithYExtension = true;
this.panelProps.add((Component) propEditor.getWidget(), new GridBagConstraints(1, i++, 1, 1, 1.0, 1.0,
GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0));
} else {
this.panelProps.add((Component) propEditor.getWidget(), new GridBagConstraints(1, i++, 1, 1, 1.0, 0.0,
GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0));
}
}
this.panelButtons.setLayout(new GridBagLayout());
this.buttonOk.setText(client.getCurrentLocale().getStringGui("commongui.text.ok"));
this.buttonOk.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
handleActionOk();
}
});
this.buttonOk.setEnabled(false);
this.buttonApply.setText(client.getCurrentLocale().getStringGui("commongui.text.apply"));
this.buttonApply.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
handleActionApply();
}
});
this.buttonApply.setEnabled(false);
this.buttonClose.setText(client.getCurrentLocale().getStringGui("commongui.text.close"));
this.buttonClose.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
handleActionClose();
}
});
this.panelButtons.add(this.buttonOk, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER,
GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
this.panelButtons.add(this.buttonApply, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER,
GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
this.panelButtons.add(this.buttonClose, new GridBagConstraints(2, 0, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER,
GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
final JPanel p = new JPanel();
p.setLayout(new GridBagLayout());
if (editorWithYExtension) {
p.add(this.panelProps, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.NORTH,
GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
} else {
p.add(this.panelProps, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.NORTH,
GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
}
this.scrollPane.getViewport().add(p);
this.panel.add(this.scrollPane, BorderLayout.CENTER);
this.panel.add(this.panelButtons, BorderLayout.SOUTH);
validateAndUpdateButtons();
}
/**
* validate and update the GUI. - the buttons enabled - the text of the
* close button
*
* @param propEditor
* the propEditor where the input field has been changed. Give a
* null if an OK, Apply or Close button has been pressed instead.
*/
private void validateAndUpdateButtons() {
try {
for (EditorProperty ped : this.getPropEditors()) {
ped.validateInputField();
}
updateButtons(true);
} catch (ValidationReadonlyException e) {
try {
ThreadLocalValidationSettings.readonlyOff();
for (EditorProperty ped : this.getPropEditors()) {
ped.validateInputField();
}
updateButtons(true);
} catch (ValidationException e1) {
updateButtons(false);
} finally {
ThreadLocalValidationSettings.remove();
}
} catch (ValidationException e) {
updateButtons(false);
}
}
/**
* validate and update the GUI. - the buttons enabled - the text of the
* close button
*
* @param propEditor
* the propEditor where the input field has been changed. Give a
* null if an OK, Apply or Close button has been pressed instead.
*/
public void validateAndUpdateButtons(final EditorProperty propEditor) {
try {
ThreadLocalValidationSettings.readonlyOff();
super.validateInputAndUpdateBean(false, false, false, true, propEditor);
updateButtons(true);
} catch (ValidationException e) {
updateButtons(false);
} finally {
ThreadLocalValidationSettings.remove();
}
}
/**
* update the GUI. - the buttons enabled - the text of the close button
*
* @param valid
* if all input values are valid or not
*/
private void updateButtons(final boolean valid) {
if (valid) {
if (super.isAnyInputFieldChanged()) {
this.buttonOk.setEnabled(true);
this.buttonApply.setEnabled(true);
this.buttonApply.setText(this.getLocale().getStringGui("commongui.text.apply"));
this.buttonClose.setText(this.getLocale().getStringGui("commongui.text.cancel"));
} else {
this.buttonOk.setEnabled(false);
this.buttonApply.setEnabled(false);
this.buttonApply.setText(this.getLocale().getStringGui("commongui.text.apply"));
this.buttonClose.setText(this.getLocale().getStringGui("commongui.text.close"));
}
} else { // invalid
this.buttonOk.setEnabled(false);
this.buttonApply.setEnabled(true);
this.buttonApply.setText(this.getLocale().getStringGui("commongui.text.check"));
if (super.isAnyInputFieldChanged()) {
this.buttonClose.setText(this.getLocale().getStringGui("commongui.text.cancel"));
} else {
this.buttonClose.setText(this.getLocale().getStringGui("commongui.text.close"));
}
}
// } else {
// this.buttonOk.setEnabled(false);
// this.buttonApply.setEnabled(false);
// this.buttonApply.setText(this.getLocale().getStringGui(
// "commongui.text.apply"));
// this.buttonClose.setText(this.getLocale().getStringGui(
// "commongui.text.close"));
// }
}
/**
* action handler for OK button.
*/
public void handleActionOk() {
super.handleActionOk();
}
/**
* action handler for Appply button.
*/
public void handleActionApply() {
super.handleActionApply();
}
/**
* for white box testing.
*
* @return a HashMap with button wigets. The keys are the button names ok,
* apply and close
*/
public HashMap<String, Object> getButtonWidgets() {
HashMap<String, Object> buttons = new HashMap<String, Object>();
buttons.put("ok", this.buttonOk);
buttons.put("apply", this.buttonApply);
buttons.put("close", this.buttonClose);
return buttons;
}
/**
* @return the panelButtons
*/
public JPanel getPanelButtons() {
return panelButtons;
}
/**
* @return the panelProps
*/
public JPanel getPanelProps() {
return panelProps;
}
@Override
public void rotateFocus(final Property property, final int direction) {
EditorProperty nextEditor = getNextEditor(property);
if (direction == EditorBean.DIRECTION_UP) {
nextEditor = getPreviousEditor(property);
} else {
nextEditor = getNextEditor(property);
}
((JComponent) nextEditor.getWidget()).requestFocus();
}
}