001: package jimm.datavision.gui.parameter;
002:
003: import jimm.datavision.Parameter;
004: import jimm.datavision.gui.Designer;
005: import jimm.datavision.gui.EditWin;
006: import jimm.datavision.gui.cmd.ParamEditCommand;
007: import jimm.util.I18N;
008: import java.awt.*;
009: import java.awt.event.ActionEvent;
010: import java.util.Iterator;
011: import java.util.Enumeration;
012: import java.util.ArrayList;
013: import javax.swing.*;
014: import com.toedter.calendar.JCalendar;
015:
016: /**
017: * A parameter editing dialog box.
018: * <p>
019: *
020: * @author Jim Menard, <a href="mailto:jimm@io.com">jimm@io.com</a>
021: */
022: public class ParamEditWin extends EditWin {
023:
024: protected static final int HORIZ_GAP = 20;
025: protected static final int VERT_GAP = 20;
026: protected static final int TEXT_FIELD_COLS = 24;
027: protected static final String CARD_NAME_SINGLE = "single";
028: protected static final String CARD_NAME_SINGLE_BOOL = "single-bool";
029: protected static final String CARD_NAME_RANGE = "range";
030: protected static final String CARD_NAME_LIST = "list";
031: protected static final String CARD_NAME_DATE = "date";
032:
033: protected Parameter param;
034: protected JTextField nameField;
035: protected JTextField questionField;
036: protected JRadioButton boolRButton;
037: protected JRadioButton stringRButton;
038: protected JRadioButton numericRButton;
039: protected JRadioButton dateRButton;
040: protected JRadioButton singleRButton;
041: protected JRadioButton rangeRButton;
042: protected JRadioButton listSingleRButton;
043: protected JRadioButton listMultipleRButton;
044: protected JPanel cardPanel;
045: protected JTextField singleField;
046: protected JCalendar singleDate;
047: protected JTextField rangeFromField;
048: protected JTextField rangeToField;
049: protected JCalendar rangeFromDate;
050: protected JCalendar rangeToDate;
051: protected JRadioButton boolYesRButton;
052: protected JRadioButton boolNoRButton;
053: protected JList list;
054: protected JTextField listAddField;
055:
056: /**
057: * Constructor.
058: *
059: * @param designer the design window to which this dialog belongs
060: * @param p a parameter
061: */
062: public ParamEditWin(Designer designer, Parameter p) {
063: super (designer, I18N.get("ParamEditWin.title"),
064: "ParamEditCommand.name");
065:
066: param = p;
067:
068: buildWindow();
069: pack();
070: setVisible(true);
071: }
072:
073: /**
074: * Builds the window contents.
075: */
076: protected void buildWindow() {
077: // Add edit panes and buttons to window
078: getContentPane().add(buildPromptPanel(), BorderLayout.NORTH);
079: getContentPane().add(buildCenterPanel(), BorderLayout.CENTER);
080:
081: // Add OK, Apply, Revert, and Cancel Buttons
082: getContentPane().add(closeButtonPanel(), BorderLayout.SOUTH);
083:
084: fillEditWidgets();
085: }
086:
087: protected JPanel buildPromptPanel() {
088:
089: JPanel panel = new JPanel();
090: panel.setLayout(new BorderLayout());
091:
092: // Labels
093: JPanel labelPanel = new JPanel();
094: labelPanel.setLayout(new GridLayout(0, 1));
095: JLabel label;
096: labelPanel
097: .add(label = new JLabel(I18N.get("ParamEditWin.name")));
098: label.setHorizontalAlignment(SwingConstants.RIGHT);
099: labelPanel.add(label = new JLabel(I18N
100: .get("ParamEditWin.question")));
101: label.setHorizontalAlignment(SwingConstants.RIGHT);
102:
103: // Edit values
104: JPanel fieldPanel = new JPanel();
105: fieldPanel.setLayout(new GridLayout(0, 1));
106: fieldPanel.add(nameField = new JTextField(TEXT_FIELD_COLS));
107: fieldPanel.add(questionField = new JTextField(TEXT_FIELD_COLS));
108:
109: panel.add(labelPanel, BorderLayout.WEST);
110: panel.add(fieldPanel, BorderLayout.CENTER);
111:
112: JPanel nonStretchyPanel = new JPanel();
113: nonStretchyPanel.add(panel);
114: return nonStretchyPanel;
115: }
116:
117: protected JPanel buildCenterPanel() {
118: JPanel panel = new JPanel();
119: Box box = Box.createHorizontalBox();
120:
121: box.add(buildRadioButtonsPanel());
122: box.add(buildCardPanel());
123:
124: panel.add(box);
125: return panel;
126: }
127:
128: protected JPanel buildRadioButtonsPanel() {
129: JPanel panel = new JPanel();
130:
131: // Type radio buttons
132: Box box = Box.createVerticalBox();
133: ButtonGroup bg = new ButtonGroup();
134: box.add(new JLabel("Type"));
135: boolRButton = addRadioButton(I18N.get("ParamEditWin.bool"),
136: box, bg);
137: stringRButton = addRadioButton(I18N.get("ParamEditWin.text"),
138: box, bg);
139: numericRButton = addRadioButton(
140: I18N.get("ParamEditWin.number"), box, bg);
141: dateRButton = addRadioButton(I18N.get("ParamEditWin.date"),
142: box, bg);
143: panel.add(box);
144:
145: // Arity radio buttons
146: box = Box.createVerticalBox();
147: box.add(new JLabel(I18N.get("ParamEditWin.arity")));
148: bg = new ButtonGroup();
149: singleRButton = addRadioButton(I18N.get("ParamEditWin.single"),
150: box, bg);
151: rangeRButton = addRadioButton(I18N.get("ParamEditWin.range"),
152: box, bg);
153: listSingleRButton = addRadioButton(I18N
154: .get("ParamEditWin.list_single"), box, bg);
155: listMultipleRButton = addRadioButton(I18N
156: .get("ParamEditWin.list_mult"), box, bg);
157: panel.add(box);
158:
159: return panel;
160: }
161:
162: protected JPanel buildCardPanel() {
163: cardPanel = new JPanel();
164: cardPanel.setLayout(new CardLayout(HORIZ_GAP, VERT_GAP));
165:
166: cardPanel.add(boolCard(), CARD_NAME_SINGLE_BOOL);
167: cardPanel.add(singleCard(), CARD_NAME_SINGLE);
168: cardPanel.add(rangeCard(), CARD_NAME_RANGE);
169: cardPanel.add(listCard(), CARD_NAME_LIST);
170: cardPanel.add(dateCard(), CARD_NAME_DATE);
171:
172: return cardPanel;
173: }
174:
175: protected JPanel dateCard() {
176: JPanel panel = new JPanel();
177: panel.add(new JLabel(I18N.get("ParamEditWin.date_default")));
178: return panel;
179: }
180:
181: protected JPanel boolCard() {
182: JPanel panel = new JPanel();
183: panel
184: .setBorder(BorderFactory.createEmptyBorder(20, 20, 20,
185: 20));
186:
187: Box box = Box.createVerticalBox();
188: ButtonGroup bg = new ButtonGroup();
189:
190: boolYesRButton = new JRadioButton(I18N.get("GUI.yes"));
191: box.add(boolYesRButton);
192: bg.add(boolYesRButton);
193:
194: boolNoRButton = new JRadioButton(I18N.get("GUI.no"));
195: box.add(boolNoRButton);
196: bg.add(boolNoRButton);
197:
198: panel.add(box);
199: return panel;
200: }
201:
202: protected JPanel singleCard() {
203: JPanel panel = new JPanel();
204: panel
205: .setBorder(BorderFactory.createEmptyBorder(20, 20, 20,
206: 20));
207:
208: panel.add(new JLabel(I18N.get("ParamEditWin.default_value")));
209: panel.add(singleField = new JTextField(TEXT_FIELD_COLS));
210:
211: return panel;
212: }
213:
214: protected JPanel rangeCard() {
215: JPanel panel = new JPanel();
216: panel.setLayout(new BorderLayout());
217:
218: // Labels
219: JPanel labelPanel = new JPanel();
220: labelPanel.setLayout(new GridLayout(0, 1));
221: JLabel label;
222: labelPanel.add(label = new JLabel(I18N.get("GUI.from")));
223: label.setHorizontalAlignment(SwingConstants.RIGHT);
224: labelPanel.add(label = new JLabel(I18N.get("GUI.to")));
225: label.setHorizontalAlignment(SwingConstants.RIGHT);
226:
227: // Edit values
228: JPanel fieldPanel = new JPanel();
229: fieldPanel.setLayout(new GridLayout(0, 1));
230:
231: // From and to fields
232: fieldPanel
233: .add(rangeFromField = new JTextField(TEXT_FIELD_COLS));
234: fieldPanel.add(rangeToField = new JTextField(TEXT_FIELD_COLS));
235:
236: panel.add(labelPanel, BorderLayout.CENTER);
237: panel.add(fieldPanel, BorderLayout.EAST);
238:
239: return panel;
240: }
241:
242: protected JPanel listCard() {
243: JPanel panel = new JPanel();
244: Box box = Box.createVerticalBox();
245: panel.add(box);
246:
247: list = new JList(new DefaultListModel());
248: list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
249: box.add(new JScrollPane(list));
250:
251: JPanel addPanel = new JPanel();
252: JButton button = new JButton(I18N
253: .get("ParamEditWin.add_to_list"));
254: button.addActionListener(this );
255: addPanel.add(button);
256: addPanel.add(listAddField = new JTextField(TEXT_FIELD_COLS));
257: box.add(addPanel);
258:
259: button = new JButton(I18N.get("ParamEditWin.remove_from_list"));
260: button.addActionListener(this );
261: box.add(button);
262:
263: return panel;
264: }
265:
266: /**
267: * Creates and adds a radio buton
268: *
269: * @param name the button name (label)
270: * @param parent a container
271: * @param group the button group
272: * @return the new radio button
273: */
274: protected JRadioButton addRadioButton(String name,
275: Container parent, ButtonGroup group) {
276: JRadioButton button = new JRadioButton(name);
277: button.addActionListener(this );
278: parent.add(button);
279: group.add(button);
280: return button;
281: }
282:
283: /**
284: * Fills all widgets except name and question.
285: */
286: protected void fillEditWidgets() {
287: nameField.setText(param.getName());
288: questionField.setText(param.getQuestion());
289:
290: // Select type radio button.
291: int type = param.getType();
292: switch (type) {
293: case Parameter.TYPE_BOOLEAN:
294: boolRButton.setSelected(true);
295: break;
296: case Parameter.TYPE_STRING:
297: stringRButton.setSelected(true);
298: break;
299: case Parameter.TYPE_NUMERIC:
300: numericRButton.setSelected(true);
301: break;
302: case Parameter.TYPE_DATE:
303: dateRButton.setSelected(true);
304: break;
305: }
306:
307: // Based on arity, select the appropriate radio button.
308: switch (param.getArity()) {
309: case Parameter.ARITY_ONE:
310: singleRButton.setSelected(true);
311: break;
312: case Parameter.ARITY_RANGE:
313: rangeRButton.setSelected(true);
314: break;
315: case Parameter.ARITY_LIST_SINGLE:
316: listSingleRButton.setSelected(true);
317: break;
318: case Parameter.ARITY_LIST_MULTIPLE:
319: listMultipleRButton.setSelected(true);
320: break;
321: }
322:
323: selectAndFillCard(); // Select card and fill card contents
324: }
325:
326: /**
327: * Returns one of the <code>Parameter</code> constants
328: * <code>TYPE_BOOLEAN</code>, <code>TYPE_STRING</code>,
329: * <code>TYPE_NUMERIC</code>, or <code>TYPE_DATE</code> based on the state
330: * of the GUI.
331: *
332: * @return one of the <code>Parameter</code> constants
333: * <code>TYPE_BOOLEAN</code>, <code>TYPE_STRING</code>,
334: * <code>TYPE_NUMERIC</code>, or <code>TYPE_DATE</code> based on the state
335: * of the GUI
336: */
337: protected int typeFromWidgets() {
338: if (boolRButton.isSelected())
339: return Parameter.TYPE_BOOLEAN;
340: if (stringRButton.isSelected())
341: return Parameter.TYPE_STRING;
342: if (numericRButton.isSelected())
343: return Parameter.TYPE_NUMERIC;
344: else
345: return Parameter.TYPE_DATE;
346: }
347:
348: /**
349: * Returns one of the {@link Parameter} constants <code>ARITY_ONE</code>,
350: * <code>ARITY_RANGE</code>, <code>ARITY_LIST_SINGLE</code>, or
351: * <code>ARITY_LIST_MULTIPLE</code> based on the state of the GUI.
352: *
353: * @return one of the <code>Parameter</code> constants <code>ARITY_ONE</code>,
354: * <code>ARITY_RANGE</code>, <code>ARITY_LIST_SINGLE</code>, or
355: * <code>ARITY_LIST_MULTIPLE</code> based on the state of the GUI
356: */
357: protected int arityFromWidgets() {
358: if (singleRButton.isSelected())
359: return Parameter.ARITY_ONE;
360: if (rangeRButton.isSelected())
361: return Parameter.ARITY_RANGE;
362: if (listSingleRButton.isSelected())
363: return Parameter.ARITY_LIST_SINGLE;
364: else
365: return Parameter.ARITY_LIST_MULTIPLE;
366: }
367:
368: /**
369: * Enables only legal arity radio buttons.
370: */
371: protected void enableLegalArityButtons() {
372: int type = typeFromWidgets();
373: singleRButton.setEnabled(param.isLegal(type,
374: Parameter.ARITY_ONE));
375: rangeRButton.setEnabled(param.isLegal(type,
376: Parameter.ARITY_RANGE));
377: listSingleRButton.setEnabled(param.isLegal(type,
378: Parameter.ARITY_LIST_SINGLE));
379: listMultipleRButton.setEnabled(param.isLegal(type,
380: Parameter.ARITY_LIST_MULTIPLE));
381: }
382:
383: /**
384: * Based on type and arity, selects proper card and fills card contents.
385: * Enables/disables the arity radion buttons based on legal choices.
386: * <p>
387: * Since we could be switching from one parameter type to another, we
388: * have to do some checking along the way to see if the parameter's default
389: * value is of the correct type.
390: */
391: protected void selectAndFillCard() {
392: enableLegalArityButtons();
393:
394: CardLayout cardLayout = (CardLayout) cardPanel.getLayout();
395: Object objVal;
396: int type = typeFromWidgets();
397:
398: switch (arityFromWidgets()) {
399: case Parameter.ARITY_ONE:
400: switch (type) {
401: case Parameter.TYPE_BOOLEAN:
402: cardLayout.show(cardPanel, CARD_NAME_SINGLE_BOOL);
403: objVal = param.getDefaultValue(0);
404: Boolean val = null;
405: val = (objVal instanceof Boolean) ? (Boolean) objVal
406: : (Boolean) param.getDefaultForType(type);
407: if (val != null && val.booleanValue())
408: boolYesRButton.setSelected(true);
409: else
410: boolNoRButton.setSelected(true);
411: break;
412: case Parameter.TYPE_DATE:
413: cardLayout.show(cardPanel, CARD_NAME_DATE);
414: break;
415: default:
416: cardLayout.show(cardPanel, CARD_NAME_SINGLE);
417: setField(singleField, 0);
418: break;
419: }
420: break;
421: case Parameter.ARITY_RANGE:
422: if (type == Parameter.TYPE_DATE)
423: cardLayout.show(cardPanel, CARD_NAME_DATE);
424: else
425: cardLayout.show(cardPanel, CARD_NAME_RANGE);
426: setField(rangeFromField, 0);
427: setField(rangeToField, 1);
428: break;
429: case Parameter.ARITY_LIST_SINGLE:
430: case Parameter.ARITY_LIST_MULTIPLE:
431: cardLayout.show(cardPanel, CARD_NAME_LIST);
432:
433: // Erase list and re-fill it
434: DefaultListModel model = (DefaultListModel) list.getModel();
435: model.clear();
436: for (Iterator iter = param.defaultValues(); iter.hasNext();)
437: model.addElement(iter.next());
438: break;
439: }
440: }
441:
442: /**
443: * Fills the specified text field with the nth parameter default value.
444: * If the value is <code>null</code>, "fill" the text field with the
445: * empty string.
446: *
447: * @param f the text field
448: * @param which n
449: */
450: protected void setField(JTextField f, int which) {
451: Object obj = param.getDefaultValue(which); // Default value
452: f.setText(obj == null ? "" : obj.toString());
453: }
454:
455: /**
456: * Handles radio buttons.
457: */
458: public void actionPerformed(ActionEvent e) {
459: String cmd = e.getActionCommand();
460: int type = typeFromWidgets();
461: int arity = arityFromWidgets();
462: boolean refill = false;
463:
464: // Type changes. When the type changes, make sure the new type and
465: // selected arity are a legal combination. If not, change the arity.
466: if (cmd.equals(I18N.get("ParamEditWin.bool"))
467: || cmd.equals(I18N.get("ParamEditWin.text"))
468: || cmd.equals(I18N.get("ParamEditWin.number"))
469: || cmd.equals(I18N.get("ParamEditWin.date"))) {
470: refill = true;
471: if (!param.isLegal(type, arity))
472: singleRButton.setSelected(true);
473: }
474:
475: // Arity changes. The user can't pick an illegal combination because
476: // we make sure of that in selectAndFillCard().
477: else if (cmd.equals(I18N.get("ParamEditWin.single"))
478: || cmd.equals(I18N.get("ParamEditWin.range"))
479: || cmd.equals(I18N.get("ParamEditWin.list_single"))
480: || cmd.equals(I18N.get("ParamEditWin.list_mult")))
481: refill = true;
482:
483: else if (cmd.equals(I18N.get("ParamEditWin.add_to_list"))) {
484: ((DefaultListModel) list.getModel())
485: .addElement(listAddField.getText());
486: listAddField.setText("");
487: }
488:
489: else if (cmd.equals(I18N.get("ParamEditWin.remove_from_list"))) {
490: ((DefaultListModel) list.getModel()).removeElement(list
491: .getSelectedValue());
492: } else {
493: super .actionPerformed(e);
494: }
495:
496: if (refill)
497: selectAndFillCard();
498: }
499:
500: protected void doSave() {
501: ArrayList defaultValues = new ArrayList();
502: int type = typeFromWidgets();
503: int arity = arityFromWidgets();
504:
505: // Create list of new default values.
506: switch (arity) {
507: case Parameter.ARITY_ONE:
508: switch (type) {
509: case Parameter.TYPE_BOOLEAN:
510: defaultValues.add(Boolean.valueOf(boolYesRButton
511: .isSelected()));
512: case Parameter.TYPE_DATE:
513: break;
514: default:
515: defaultValues.add(singleField.getText());
516: break;
517: }
518: break;
519: case Parameter.ARITY_RANGE:
520: defaultValues.add(rangeFromField.getText());
521: defaultValues.add(rangeToField.getText());
522: break;
523: case Parameter.ARITY_LIST_SINGLE:
524: case Parameter.ARITY_LIST_MULTIPLE:
525: DefaultListModel model = (DefaultListModel) list.getModel();
526: for (Enumeration e = model.elements(); e.hasMoreElements();)
527: defaultValues.add(e.nextElement());
528: break;
529: }
530:
531: ParamEditCommand cmd = new ParamEditCommand(param, nameField
532: .getText(), questionField.getText(), type, arity,
533: defaultValues);
534: cmd.perform();
535: commands.add(cmd);
536: }
537:
538: protected void doRevert() {
539: fillEditWidgets();
540: }
541:
542: }
|