package ilarkesto.form.swing;
import ilarkesto.core.logging.Log;
import ilarkesto.form.FileFormField;
import ilarkesto.form.Form;
import ilarkesto.form.FormButton;
import ilarkesto.form.FormField;
import ilarkesto.form.TextFormField;
import ilarkesto.form.ValidationException;
import ilarkesto.swing.FileField;
import ilarkesto.swing.PanelBuilder;
import ilarkesto.swing.Swing;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class FormDialog {
private static final Log LOG = Log.get(FormDialog.class);
private static final FormButton WINDOW_CLOSED_BUTTON = new FormButton(Form.ABORT_BUTTON_NAME);
private Form form;
private PanelBuilder pb;
private JDialog dialog;
private FormButton clickedButton;
private boolean loop;
private Map<String, JComponent> fieldComponents;
public FormDialog(Form form) {
this.form = form;
}
public static final FormButton showDialog(Window owner, Form form) {
FormDialog fd = new FormDialog(form);
return fd.showDialog(owner);
}
public FormButton showDialog(Window owner) {
loop = true;
while (loop) {
loop = false;
dialog = new JDialog(owner);
dialog.setTitle(form.getFormTitle());
dialog.setModal(true);
dialog.add(createPanel());
dialog.pack();
if (owner == null) {
Swing.center(dialog);
} else {
Swing.placeBest(dialog, owner);
}
dialog.setVisible(true);
}
return clickedButton != null ? clickedButton : WINDOW_CLOSED_BUTTON;
}
private void updateForm() {
Map<String, String> data = new HashMap<String, String>();
for (String name : fieldComponents.keySet()) {
if (!name.startsWith("_")) {
data.put(name, getComponentValue(fieldComponents.get(name)));
}
}
form.update(data, Collections.EMPTY_LIST);
}
private String getComponentValue(JComponent c) {
if (c instanceof JTextField) return ((JTextField) c).getText();
if (c instanceof FileField) return ((FileField) c).getPath();
throw new RuntimeException("Unsupported component: " + c.getClass().getName());
}
public JPanel createPanel() {
pb = new PanelBuilder();
pb.setDefaultPadding(2, 2, 5, 5);
form.initialize();
// TODO hidden fields
String errorMessage = form.getErrorMessage();
if (errorMessage != null) {
if (!errorMessage.startsWith("<html>")) {
errorMessage = "<html><font color='red'>" + errorMessage + "</font>";
}
pb.add(Swing.createMessageComponent(errorMessage)).setFillToHorizontal();
pb.nl();
}
String sideImage = form.getSideImage();
// TODO sideImage
fieldComponents = new HashMap<String, JComponent>();
for (FormField field : form.getVisibleFields()) {
addField(field);
}
// buttons
pb.addEmpty();
for (FormButton button : form.getSubmitButtons()) {
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
panel.add(createButton(button));
pb.add(panel);
}
pb.nl();
return pb.toPanel();
}
private JButton createButton(FormButton button) {
JButton b = new JButton(button.getLabel());
b.addActionListener(new ButtonActionListener(button));
b.setIcon(Swing.getIcon16(button.getIcon()));
return b;
}
private void addField(FormField field) {
String label = field.getLabel();
String hintText = field.getHintText();
if (field.isRequired()) label += "*";
JLabel l = new JLabel(label);
l.setToolTipText(hintText);
Font font = l.getFont();
l.setFont(new Font(font.getFamily(), Font.PLAIN, font.getSize()));
l.setForeground(Color.GRAY);
pb.add(l).setAnchorToNorthEast();
JComponent f;
if (field instanceof TextFormField) {
f = createTextField((TextFormField) field);
} else if (field instanceof FileFormField) {
f = createFileField((FileFormField) field);
} else {
throw new RuntimeException("Unsupported field: " + field.getClass());
}
fieldComponents.put(field.getName(), f);
String errorMessage = field.getErrorMessage();
if (errorMessage != null) {
if (!errorMessage.startsWith("<html>")) {
errorMessage = "<html><font color='red'>" + errorMessage + "</font>";
}
JPanel panel = new JPanel(new BorderLayout(2, 2));
panel.add(Swing.createMessageComponent(errorMessage), BorderLayout.NORTH);
panel.add(f);
pb.add(panel).setAnchorToWest();
} else {
pb.add(f).setAnchorToWest();
}
pb.nl();
}
private JComponent createTextField(TextFormField field) {
JTextField f = new JTextField(field.getWidth());
f.setText(field.getValueAsString());
return f;
}
private JComponent createFileField(FileFormField field) {
FileField f = field.isFolder() ? FileField.createForDirectory() : FileField.createForFile();
f.setFile(field.getValue());
return f;
}
private boolean handleButtonClick(FormButton button) throws ValidationException {
// if (button instanceof ItemFormField.SelectButton) {
// showSelectItemDialog(((ItemFormField.SelectButton) button).getField());
// return true;
// }
//
// if (button instanceof ItemFormField.ClearButton) {
// ItemFormField field = ((ItemFormField.ClearButton) button).getField();
// field.setValue(null);
// return true;
// }
//
// if (button instanceof MultiItemFormField.AddButton) {
// MultiItemFormField field = ((MultiItemFormField.AddButton) button).getField();
// Collection items = field.getSelectableItems();
// Collection multiItems = field.getSelectableMultiItems();
// Collection payloads;
//
// OptionAction action = beanProvider.autowire(new OptionAction());
// action.setHorizontal(false);
// action.setMessage(getString(form.getStringKeyPrefix() + "." + field.getName() +
// ".select.message"));
// IdGenerator itemIdGenerator = new CountingIdGenerator("item");
// for (Object o : field.getSelectableMultiItems()) {
// MultiItem item = (MultiItem) o;
// IOption option = new Option(itemIdGenerator.generateId(), item.toString(), "multiItem", item);
// option.setGroup(true);
// action.addOption(option);
// }
// for (Object item : field.getSelectableItems()) {
// action.addOption(new Option(itemIdGenerator.generateId(), item.toString(),
// iconResolver.getIcon(item),
// item));
// }
//
// try {
// actionPerformer.perform(action, this);
// } catch (ActionAbortedException ex) {
// return true;
// }
// Object item = action.getSelectedOption().getPayload();
// if (item instanceof MultiItem) {
// for (Object o : ((MultiItem) item).getItems()) {
// field.addValueItem(o);
// }
// } else {
// field.addValueItem(item);
// }
// return true;
// }
//
// if (button instanceof MultiItemFormField.RemoveButton) {
// MultiItemFormField field = ((MultiItemFormField.RemoveButton) button).getField();
// Object item = ((MultiItemFormField.RemoveButton) button).getItem();
// field.removeValueItem(item);
// return true;
// }
//
// if (button instanceof MultiItemFormField.RemoveAllButton) {
// MultiItemFormField field = ((MultiItemFormField.RemoveAllButton) button).getField();
// field.removeAllItems();
// return true;
// }
//
// if (button instanceof MultiComplexFormField.AddButton) {
// MultiComplexFormField.AddButton b = (MultiComplexFormField.AddButton) button;
// final MultiComplexFormField field = b.getField();
// final BeanForm form = field.createSubform();
// beanProvider.autowire(form);
// form.setBean(field.getItemFactory().getBean());
// FormAction action = new FormAction();
// action.setForm(form);
// try {
// actionPerformer.perform(action, this);
// } catch (ActionAbortedException ex) {
// return true;
// }
// if (!action.isClickedButtonAbort()) {
// field.addValueItem(form.getBean());
// }
// return true;
// }
//
// if (button instanceof MultiComplexFormField.EditButton) {
// MultiComplexFormField.EditButton b = (MultiComplexFormField.EditButton) button;
// final MultiComplexFormField field = b.getField();
// final BeanForm form = field.createSubform();
// beanProvider.autowire(form);
// form.setBean(b.getItem());
// FormAction action = new FormAction();
// action.setForm(form);
// try {
// actionPerformer.perform(action, this);
// } catch (ActionAbortedException ex) {}
// return true;
//
// }
//
// if (button instanceof MultiComplexFormField.RemoveButton) {
// MultiComplexFormField field = ((MultiComplexFormField.RemoveButton) button).getField();
// Object item = ((MultiComplexFormField.RemoveButton) button).getItem();
// field.removeValueItem(item);
// return true;
// }
if (button.isAbort()) return false;
// user defined button
return false;
}
class ButtonActionListener implements ActionListener {
private FormButton button;
public ButtonActionListener(FormButton button) {
this.button = button;
}
public void actionPerformed(ActionEvent e) {
clickedButton = button;
if (clickedButton.isUpdateFields()) {
updateForm();
}
if (clickedButton.isValidateForm()) {
try {
form.validate();
} catch (ValidationException ex) {
LOG.debug("Form is not valid:", ex);
form.setErrorMessage(ex.getMessage());
loop = true;
dialog.dispose();
return;
}
}
try {
loop = handleButtonClick(clickedButton);
} catch (ValidationException ex) {
LOG.debug("Form is not valid:", ex);
form.setErrorMessage(ex.getMessage());
loop = true;
}
dialog.dispose();
return;
}
}
}