001: /**
002: * ===========================================
003: * JFreeReport : a free Java reporting library
004: * ===========================================
005: *
006: * Project Info: http://reporting.pentaho.org/
007: *
008: * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
009: *
010: * This library is free software; you can redistribute it and/or modify it under the terms
011: * of the GNU Lesser General Public License as published by the Free Software Foundation;
012: * either version 2.1 of the License, or (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
015: * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016: * See the GNU Lesser General Public License for more details.
017: *
018: * You should have received a copy of the GNU Lesser General Public License along with this
019: * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
020: * Boston, MA 02111-1307, USA.
021: *
022: * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
023: * in the United States and other countries.]
024: *
025: * ------------
026: * NumericInputDialog.java
027: * ------------
028: * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
029: */package org.jfree.report.modules.gui.base.internal;
030:
031: import java.awt.Component;
032: import java.awt.Dialog;
033: import java.awt.FlowLayout;
034: import java.awt.Frame;
035: import java.awt.GridBagConstraints;
036: import java.awt.GridBagLayout;
037: import java.awt.GridLayout;
038: import java.awt.Window;
039: import java.awt.event.ActionEvent;
040: import java.awt.event.KeyEvent;
041: import java.awt.event.WindowAdapter;
042: import java.awt.event.WindowEvent;
043: import java.util.ResourceBundle;
044: import javax.swing.AbstractAction;
045: import javax.swing.Action;
046: import javax.swing.BorderFactory;
047: import javax.swing.Icon;
048: import javax.swing.JButton;
049: import javax.swing.JComponent;
050: import javax.swing.JDialog;
051: import javax.swing.JLabel;
052: import javax.swing.JPanel;
053: import javax.swing.JSlider;
054: import javax.swing.JTextField;
055: import javax.swing.KeyStroke;
056: import javax.swing.SwingConstants;
057: import javax.swing.UIManager;
058: import javax.swing.event.ChangeEvent;
059: import javax.swing.event.ChangeListener;
060: import javax.swing.event.DocumentEvent;
061: import javax.swing.event.DocumentListener;
062:
063: import org.jfree.report.modules.gui.commonswing.FormValidator;
064: import org.jfree.report.modules.gui.commonswing.NumericDocument;
065: import org.jfree.report.modules.gui.commonswing.SwingCommonModule;
066: import org.jfree.report.modules.gui.commonswing.SwingUtil;
067: import org.jfree.ui.RefineryUtilities;
068: import org.jfree.ui.action.ActionButton;
069: import org.jfree.ui.action.ActionDowngrade;
070:
071: /**
072: * Creation-Date: 29.10.2007, 18:36:13
073: *
074: * @author Thomas Morgner
075: */
076: public class NumericInputDialog extends JDialog {
077: private class SyncValuesHandler implements DocumentListener,
078: ChangeListener {
079: private boolean inStateChange;
080:
081: public SyncValuesHandler() {
082: }
083:
084: public void insertUpdate(final DocumentEvent e) {
085: if (inStateChange) {
086: return;
087: }
088: inStateChange = true;
089: try {
090: final Integer i = getInputValue();
091: if (i != null) {
092: valueSlider.setValue(i.intValue());
093: valueMessage.setText(String.valueOf(i));
094: }
095: } finally {
096: inStateChange = false;
097: }
098: }
099:
100: public void removeUpdate(final DocumentEvent e) {
101: if (inStateChange) {
102: return;
103: }
104: inStateChange = true;
105: try {
106: final Integer i = getInputValue();
107: if (i != null) {
108: valueSlider.setValue(i.intValue());
109: valueMessage.setText(String.valueOf(i));
110: }
111: } finally {
112: inStateChange = false;
113: }
114: }
115:
116: public void changedUpdate(final DocumentEvent e) {
117: if (inStateChange) {
118: return;
119: }
120: inStateChange = true;
121: try {
122: final Integer i = getInputValue();
123: if (i != null) {
124: valueSlider.setValue(i.intValue());
125: valueMessage.setText(String.valueOf(i));
126: }
127: } finally {
128: inStateChange = false;
129: }
130: }
131:
132: public void stateChanged(final ChangeEvent e) {
133: if (inStateChange) {
134: return;
135: }
136: inStateChange = true;
137: try {
138: final String text = String.valueOf(valueSlider
139: .getValue());
140: textField.setText(text);
141: valueMessage.setText(text);
142: } finally {
143: inStateChange = false;
144: }
145: }
146: }
147:
148: /**
149: * Internal action class to confirm the dialog and to validate the input.
150: */
151: private class ConfirmAction extends AbstractAction {
152: /**
153: * Default constructor.
154: */
155: protected ConfirmAction(final ResourceBundle resources) {
156: putValue(Action.NAME, resources
157: .getString("OptionPane.okButtonText")); //$NON-NLS-1$
158: }
159:
160: /**
161: * Receives notification that the action has occurred.
162: *
163: * @param e the action event.
164: */
165: public void actionPerformed(final ActionEvent e) {
166: if (performValidate()) {
167: setConfirmed(true);
168: setVisible(false);
169: }
170: }
171: }
172:
173: /**
174: * Internal action class to cancel the report processing.
175: */
176: private class CancelAction extends AbstractAction {
177: /**
178: * Default constructor.
179: */
180: protected CancelAction(final ResourceBundle resources) {
181: putValue(Action.NAME, resources
182: .getString("OptionPane.cancelButtonText")); //$NON-NLS-1$
183: putValue(ActionDowngrade.ACCELERATOR_KEY, KeyStroke
184: .getKeyStroke(KeyEvent.VK_ESCAPE, 0));
185: }
186:
187: /**
188: * Receives notification that the action has occurred.
189: *
190: * @param e the action event.
191: */
192: public void actionPerformed(final ActionEvent e) {
193: setConfirmed(false);
194: setVisible(false);
195: }
196: }
197:
198: private class DialogValidator extends FormValidator {
199: protected DialogValidator() {
200: }
201:
202: public boolean performValidate() {
203: return NumericInputDialog.this .performValidate();
204: }
205:
206: public Action getConfirmAction() {
207: return NumericInputDialog.this .getConfirmAction();
208: }
209: }
210:
211: private class WindowCloseHandler extends WindowAdapter {
212: protected WindowCloseHandler() {
213: }
214:
215: /**
216: * Invoked when a window is in the process of being closed. The close operation can be overridden at this point.
217: */
218: public void windowClosing(final WindowEvent e) {
219: final Action cancelAction = getCancelAction();
220: if (cancelAction != null) {
221: cancelAction.actionPerformed(null);
222: } else {
223: setConfirmed(false);
224: setVisible(false);
225: }
226: }
227: }
228:
229: private Action cancelAction;
230: private Action confirmAction;
231: private boolean boundedRange;
232:
233: private JLabel icon;
234: private JLabel message;
235: private JLabel valueMessage;
236: private JSlider valueSlider;
237: private JTextField textField;
238: private boolean confirmed;
239: private FormValidator formValidator;
240:
241: public NumericInputDialog() {
242: initialize();
243: }
244:
245: public NumericInputDialog(final Frame owner) {
246: super (owner);
247: initialize();
248: }
249:
250: public NumericInputDialog(final Frame owner, final boolean modal) {
251: super (owner, modal);
252: initialize();
253: }
254:
255: public NumericInputDialog(final Frame owner, final String title) {
256: super (owner, title);
257: initialize();
258: }
259:
260: public NumericInputDialog(final Dialog owner) {
261: super (owner);
262: initialize();
263: }
264:
265: public NumericInputDialog(final Dialog owner, final boolean modal) {
266: super (owner, modal);
267: initialize();
268: }
269:
270: public NumericInputDialog(final Dialog owner, final String title) {
271: super (owner, title);
272: initialize();
273: }
274:
275: public NumericInputDialog(final Frame owner, final String title,
276: final boolean modal) {
277: super (owner, title, modal);
278: initialize();
279: }
280:
281: public NumericInputDialog(final Dialog owner, final String title,
282: final boolean modal) {
283: super (owner, title, modal);
284: initialize();
285: }
286:
287: private void initialize() {
288: final ResourceBundle resources = ResourceBundle
289: .getBundle(SwingCommonModule.BUNDLE_NAME);
290:
291: addWindowListener(new WindowCloseHandler());
292:
293: cancelAction = new CancelAction(resources);
294: confirmAction = new ConfirmAction(resources);
295:
296: final SyncValuesHandler syncValuesHandler = new SyncValuesHandler();
297: message = new JLabel();
298: icon = new JLabel();
299: icon.setVisible(false);
300: icon.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));
301:
302: valueMessage = new JLabel();
303: valueMessage.setVisible(false);
304:
305: valueSlider = new JSlider();
306: textField = new JTextField();
307: textField.setDocument(new NumericDocument());
308: textField.setColumns(10);
309: textField.setHorizontalAlignment(SwingConstants.TRAILING);
310:
311: textField.getDocument().addDocumentListener(syncValuesHandler);
312: valueSlider.addChangeListener(syncValuesHandler);
313:
314: final JPanel contentPane = new JPanel();
315: contentPane.setLayout(new GridBagLayout());
316: contentPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5,
317: 5));
318:
319: GridBagConstraints gbc = new GridBagConstraints();
320: gbc.gridx = 0;
321: gbc.gridy = 0;
322: gbc.gridheight = 5;
323: gbc.gridwidth = 1;
324: gbc.anchor = GridBagConstraints.CENTER;
325: contentPane.add(icon, gbc);
326:
327: gbc = new GridBagConstraints();
328: gbc.gridx = 1;
329: gbc.gridy = 0;
330: gbc.gridheight = 1;
331: gbc.gridwidth = 1;
332: gbc.fill = GridBagConstraints.HORIZONTAL;
333: contentPane.add(message, gbc);
334:
335: gbc = new GridBagConstraints();
336: gbc.gridx = 1;
337: gbc.gridy = 1;
338: gbc.gridheight = 1;
339: gbc.gridwidth = 1;
340: gbc.fill = GridBagConstraints.HORIZONTAL;
341: contentPane.add(valueSlider, gbc);
342:
343: gbc = new GridBagConstraints();
344: gbc.gridx = 1;
345: gbc.gridy = 2;
346: gbc.gridheight = 1;
347: gbc.gridwidth = 1;
348: gbc.fill = GridBagConstraints.HORIZONTAL;
349: contentPane.add(textField, gbc);
350:
351: gbc = new GridBagConstraints();
352: gbc.gridx = 1;
353: gbc.gridy = 3;
354: gbc.gridheight = 1;
355: gbc.gridwidth = 1;
356: gbc.anchor = GridBagConstraints.EAST;
357: contentPane.add(valueMessage, gbc);
358:
359: gbc = new GridBagConstraints();
360: gbc.gridx = 1;
361: gbc.gridy = 4;
362: gbc.gridheight = 1;
363: gbc.gridwidth = 1;
364: contentPane.add(createButtonPanel(), gbc);
365:
366: formValidator = new DialogValidator();
367: formValidator.setEnabled(true);
368: formValidator.registerTextField(textField);
369:
370: setContentPane(contentPane);
371: }
372:
373: private JPanel createButtonPanel() {
374: final JButton btnCancel = new ActionButton(getCancelAction());
375: final JButton btnConfirm = new ActionButton(getConfirmAction());
376: final JPanel buttonPanel = new JPanel();
377: buttonPanel.setLayout(new GridLayout(1, 2, 5, 5));
378: buttonPanel.add(btnConfirm);
379: buttonPanel.add(btnCancel);
380: btnConfirm.setDefaultCapable(true);
381: getRootPane().setDefaultButton(btnConfirm);
382: buttonPanel.registerKeyboardAction(getConfirmAction(),
383: KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),
384: JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
385:
386: final JPanel buttonCarrier = new JPanel();
387: buttonCarrier.setLayout(new FlowLayout(FlowLayout.RIGHT));
388: buttonCarrier.add(buttonPanel);
389: return buttonCarrier;
390: }
391:
392: public boolean getPaintTicks() {
393: return valueSlider.getPaintTicks();
394: }
395:
396: public void setPaintTicks(final boolean b) {
397: valueSlider.setPaintTicks(b);
398: }
399:
400: public void setSnapToTicks(final boolean b) {
401: valueSlider.setSnapToTicks(b);
402: }
403:
404: public boolean getSnapToTicks() {
405: return valueSlider.getSnapToTicks();
406: }
407:
408: public Action getCancelAction() {
409: return cancelAction;
410: }
411:
412: public Action getConfirmAction() {
413: return confirmAction;
414: }
415:
416: public void setIcon(final Icon icon) {
417: this .icon.setIcon(icon);
418: this .icon.setVisible(icon != null);
419: }
420:
421: public Icon getIcon() {
422: return icon.getIcon();
423: }
424:
425: public String getMessage() {
426: return message.getText();
427: }
428:
429: public void setMessage(final String message) {
430: this .message.setText(message);
431: }
432:
433: public int getSliderValue() {
434: return valueSlider.getValue();
435: }
436:
437: public void setSliderValue(final int n) {
438: valueSlider.setValue(n);
439: }
440:
441: public int getMinimum() {
442: return valueSlider.getMinimum();
443: }
444:
445: public void setMinimum(final int minimum) {
446: valueSlider.setMinimum(minimum);
447: }
448:
449: public int getMaximum() {
450: return valueSlider.getMaximum();
451: }
452:
453: public void setMaximum(final int maximum) {
454: valueSlider.setMaximum(maximum);
455: }
456:
457: public boolean isConfirmed() {
458: return confirmed;
459: }
460:
461: public void setConfirmed(final boolean confirmed) {
462: this .confirmed = confirmed;
463: }
464:
465: private boolean performValidate() {
466: final Integer value = getInputValue();
467: if (value == null) {
468: return false;
469: }
470: if (isBoundedRange() == false) {
471: return true;
472: }
473: final int iVal = value.intValue();
474: if (iVal < valueSlider.getMinimum()
475: || iVal > valueSlider.getMaximum()) {
476: return false;
477: }
478: return true;
479: }
480:
481: public void setInputValue(final Integer value) {
482: if (value == null) {
483: textField.setText("");
484: } else {
485: textField.setText(String.valueOf(value));
486: }
487: }
488:
489: public Integer getInputValue() {
490: try {
491: return new Integer(textField.getText());
492: } catch (NumberFormatException nfe) {
493: return null;
494: }
495: }
496:
497: public boolean isBoundedRange() {
498: return boundedRange;
499: }
500:
501: public void setBoundedRange(final boolean boundedRange) {
502: this .boundedRange = boundedRange;
503: }
504:
505: public boolean isSliderVisible() {
506: return valueSlider.isVisible();
507: }
508:
509: public void setSliderVisible(final boolean b) {
510: valueSlider.setVisible(b);
511: }
512:
513: public boolean isTextInputVisible() {
514: return textField.isVisible();
515: }
516:
517: public void setTextInputVisible(final boolean b) {
518: textField.setVisible(b);
519: valueMessage.setVisible(!b);
520: }
521:
522: private static NumericInputDialog createDialog(
523: final Component parent) {
524: if (parent != null) {
525: final Window window = SwingUtil.getWindowAncestor(parent);
526: if (window instanceof Dialog) {
527: return new NumericInputDialog((Dialog) window, true);
528: }
529: if (window instanceof Frame) {
530: return new NumericInputDialog((Frame) window, true);
531: }
532: }
533:
534: final NumericInputDialog dialog = new NumericInputDialog();
535: dialog.setModal(true);
536: return dialog;
537: }
538:
539: public static Integer showInputDialog(final Component parent,
540: final int icon, final String title, final String message,
541: final int minimum, final int maximum,
542: final int initialValue, final boolean bounded) {
543: final NumericInputDialog dialog = createDialog(parent);
544: if (title != null) {
545: dialog.setTitle(title);
546: }
547: if (message != null) {
548: dialog.setMessage(message);
549: }
550: dialog.setIcon(createDefaultIcon(icon));
551: dialog.setMinimum(minimum);
552: dialog.setMaximum(maximum);
553: dialog.setInputValue(new Integer(initialValue));
554: dialog.setBoundedRange(bounded);
555: dialog.setPaintTicks(true);
556: dialog.pack();
557: RefineryUtilities.centerDialogInParent(dialog);
558: dialog.setVisible(true);
559: if (dialog.isConfirmed()) {
560: return dialog.getInputValue();
561: }
562: return null;
563: }
564:
565: public static Integer showInputDialog(final Component parent,
566: final int icon, final String title, final String message,
567: final int initialValue, final boolean bounded) {
568: final NumericInputDialog dialog = createDialog(parent);
569: if (title != null) {
570: dialog.setTitle(title);
571: }
572: if (message != null) {
573: dialog.setMessage(message);
574: }
575: dialog.setIcon(createDefaultIcon(icon));
576: dialog.setInputValue(new Integer(initialValue));
577: dialog.setSliderVisible(false);
578: dialog.setBoundedRange(bounded);
579: dialog.pack();
580: RefineryUtilities.centerDialogInParent(dialog);
581: dialog.setVisible(true);
582: if (dialog.isConfirmed()) {
583: return dialog.getInputValue();
584: }
585: return null;
586: }
587:
588: public static Integer showSliderDialog(final Component parent,
589: final int icon, final String title, final String message,
590: final int minimum, final int maximum, final int initialValue) {
591: final NumericInputDialog dialog = createDialog(parent);
592: if (title != null) {
593: dialog.setTitle(title);
594: }
595: if (message != null) {
596: dialog.setMessage(message);
597: }
598: dialog.setIcon(createDefaultIcon(icon));
599: dialog.setMinimum(minimum);
600: dialog.setMaximum(maximum);
601: dialog.setInputValue(new Integer(initialValue));
602: dialog.setBoundedRange(true);
603: dialog.setTextInputVisible(false);
604: dialog.pack();
605: RefineryUtilities.centerDialogInParent(dialog);
606: dialog.setVisible(true);
607: if (dialog.isConfirmed()) {
608: return dialog.getInputValue();
609: }
610: return null;
611: }
612:
613: /**
614: * Returns the icon to use for the passed in type.
615: */
616: private static Icon createDefaultIcon(final int messageType) {
617: final String propertyName;
618: switch (messageType) {
619: case 0:
620: propertyName = "OptionPane.errorIcon";
621: break;
622: case 1:
623: propertyName = "OptionPane.informationIcon";
624: break;
625: case 2:
626: propertyName = "OptionPane.warningIcon";
627: break;
628: case 3:
629: propertyName = "OptionPane.questionIcon";
630: break;
631: default:
632: return null;
633: }
634: return UIManager.getIcon(propertyName);
635: }
636:
637: public static void main(final String[] args) {
638: System.out.println(showSliderDialog(null, 1, "Title",
639: "Message", 0, 100, 50));
640: System.out.println(showInputDialog(null, 2, "Title", "Message",
641: 0, 100, 50, true));
642: }
643: }
|