package com.vitco.util.components.dialog;
import com.vitco.layout.content.console.ConsoleInterface;
import com.vitco.util.components.dialog.components.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
/**
* UserInputDialog
*
* This is a custom dialog popup that allows the user to enter specific information.
*
* There are object and buttons that can be added to this dialog. Buttons are displayed
* to "finish" the dialog. The listener of this dialog will be notified with the
* result state of the button.
* The components are used by the user to enter information. Their value is accessible
* through this class by using their id tree.
*
* Note: If the window was closed by using the "X" button the passed cancelFlag is returned.
*/
public class UserInputDialog extends JDialog {
// cancel flag for this dialog
private final int cancelFlag;
// reference to this instance
private UserInputDialog thisInstance = this;
// right side (where the buttons are)
private final JPanel buttons = new JPanel();
// right side (bottom)
private final JPanel links = new JPanel();
// main content (where user enters information)
private final BlankDialogModule content = new BlankDialogModule("root");
// list of all "non cancel" buttons (used to en/disable them)
private final ArrayList<DialogButton> nonCancelButtons = new ArrayList<DialogButton>();
// listener of this dialog
private UserInputDialogListener userInputDialogListener = null;
// set a listener for this dialog (will overwrite existing listener if present)
public final void setListener(UserInputDialogListener userInputDialogListener) {
this.userInputDialogListener = userInputDialogListener;
}
// constructor
public UserInputDialog(Frame owner, String title, final int cancelFlag) {
// make this dialog block all user content (that is behind it)
super(owner, title, Dialog.ModalityType.DOCUMENT_MODAL);
// set layout for the dialog
setLayout(new BorderLayout());
// store cancel flag
this.cancelFlag = cancelFlag;
// prevent resize
setResizable(false);
// create formatting for and add right side (buttons)
JPanel buttonWrapperPanel = new JPanel();
buttonWrapperPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
buttonWrapperPanel.setLayout(new BorderLayout());
JPanel innerWrapper = new JPanel();
innerWrapper.setLayout(new BorderLayout());
innerWrapper.add(buttons, BorderLayout.NORTH);
innerWrapper.add(links, BorderLayout.SOUTH);
buttons.setLayout(new GridBagLayout());
links.setBorder(BorderFactory.createEmptyBorder(44, 0, 6, 10));
links.setLayout(new GridBagLayout());
buttonWrapperPanel.add(innerWrapper, BorderLayout.NORTH);
this.add(buttonWrapperPanel, BorderLayout.EAST);
// create formatting for and add left side (user content)
JPanel contentWrapperPanel = new JPanel();
contentWrapperPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
contentWrapperPanel.setLayout(new BorderLayout());
contentWrapperPanel.add(content, BorderLayout.NORTH);
this.add(contentWrapperPanel, BorderLayout.CENTER);
content.setLayout(new GridBagLayout());
// listen to state change events
content.addListener(new DialogModuleChangeAdapter() {
@Override
public void onReadyStateChanged() {
refreshButtonEnabled();
}
@Override
public void onContentChanged() {
// refresh the state of all components
content.refreshState(content);
}
});
// add "close" listener (when "X" button is pressed)
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
super.windowClosing(e);
if (userInputDialogListener != null) {
userInputDialogListener.onClose(cancelFlag);
}
}
});
}
// recheck if the "submit" buttons of this form should be enabled or not
private void refreshButtonEnabled() {
// check if there is a component that is currently disabled
boolean globalReady = content.isReady();
// set buttons
for (DialogButton button : nonCancelButtons) {
button.setEnabled(globalReady);
}
}
// --------------------------
// display/hide this dialog
@Override
public void setVisible(boolean flag) {
if (flag) {
// minimize the size (especially the height!)
this.pack();
// set default size
this.setSize(630, getHeight());
// set position to center
this.setLocationRelativeTo(getParent());
// check if buttons are enabled or not
refreshButtonEnabled();
// check states
content.refreshState(content);
}
// show/hide
super.setVisible(flag);
}
// get a value of a contained object (or return null if the
// object was not found). This uses the fieldSet identifier
// together with the object identifier, separated by a dot.
// E.g. "fieldD=SetId.objectId.objectId...."
// Can not return null
public final String getValue(String identifier) {
String result = content.getValue(identifier);
return result == null ? "" : result;
}
// check that an expression is true (simple equal)
public final boolean is(String expression) {
String[] pair = expression.split("=", 2);
if (pair.length == 2) {
String actualValue = getValue(pair[0]);
if (pair[1].equals(actualValue)) {
return true;
}
}
return false;
}
// ---------------------
// add a button to this dialog (buttons are used to close
// the dialog (and notify the listeners)
public void addButton(String caption, final int resultFlag) {
final DialogButton button = new DialogButton(caption);
if (resultFlag != cancelFlag) {
nonCancelButtons.add(button);
}
// create "close" action that notifies the listener
button.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
if (button.isEnabled()) {
// allow the onClose action to "abort" closing
if (userInputDialogListener == null
|| userInputDialogListener.onClose(resultFlag)
|| resultFlag == cancelFlag) {
thisInstance.setVisible(false);
}
}
}
});
// add to this dialog (button pane)
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.insets = new Insets(5,0,5,0);
buttons.add(button, gbc);
}
public void addLink(ConsoleInterface console, String caption, String url) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
if (links.getComponents().length == 0) {
links.add(new SeparatorModule("Links"), gbc);
}
links.add(new LinkButton(console, "", caption, url), gbc);
}
// add a fieldSet to this input dialog (a fieldSet holds a set of components
// that can be used by the user to enter information into this dialog)
public void addFieldSet(FieldSet fieldSet) {
// add to internal list (for later access) but don't display
// (the wrapper will be used to display instead)
content.addModule(fieldSet, false);
// set border with title
FieldSetWrapper fieldSetWrapper = new FieldSetWrapper(fieldSet);
// add to this dialog (content pane)
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
content.add(fieldSetWrapper, gbc);
}
// add several fieldSets that are displayed as a dropdown menu
public void addComboBox(String identifier, FieldSet[] comboBoxFieldSets, int selected) {
// add to internal list (for later access) but don't display
// (the wrapper will be used to display instead)
for (FieldSet fieldSet : comboBoxFieldSets) {
content.addModule(fieldSet, false);
}
// create a drop down field set
FieldSetWrapper fieldSetWrapper = new FieldSetWrapper(identifier, comboBoxFieldSets, selected);
// listen to the wrapper select events (when a combo title box changes)
// this can update the enabled buttons
fieldSetWrapper.addListener(new DialogModuleChangeAdapter() {
@Override
public void onContentChanged() {
refreshButtonEnabled();
}
});
// add to this dialog (content pane)
content.addModule(fieldSetWrapper, true);
}
// retrieve serialization of this object
public final ArrayList<String[]> getSerialization() {
return content.getSerialization("");
}
// load serialization
public final void loadSerialization(ArrayList<String[]> ser) {
for (String[] pair : ser) {
if (pair.length == 2) {
content.loadValue(pair);
}
}
}
}