001: /*
002: * The contents of this file are subject to the Mozilla Public License
003: * Version 1.1 (the "License"); you may not use this file except in
004: * compliance with the License. You may obtain a copy of the License at
005: * http://www.mozilla.org/MPL/
006: *
007: * Software distributed under the License is distributed on an "AS IS"
008: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
009: * License for the specific language governing rights and limitations
010: * under the License.
011: *
012: * The Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
013: *
014: * The Initial Developer of the Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
015: * Portions created by Mark A. Kobold are Copyright (C) 2000-2007. All Rights Reserved.
016: *
017: * Contributor(s):
018: * Mark A. Kobold [mkobold <at> isqlviewer <dot> com].
019: *
020: * If you didn't download this code from the following link, you should check
021: * if you aren't using an obsolete version: http://www.isqlviewer.com
022: */
023: package org.isqlviewer.ui.wizards;
024:
025: import java.awt.Color;
026: import java.awt.Component;
027: import java.util.Collection;
028: import java.util.Enumeration;
029: import java.util.Hashtable;
030:
031: import javax.swing.JOptionPane;
032: import javax.swing.JPanel;
033: import javax.swing.UIManager;
034: import javax.swing.plaf.basic.BasicEditorPaneUI;
035: import javax.swing.plaf.basic.BasicTextAreaUI;
036: import javax.swing.plaf.basic.BasicTextFieldUI;
037: import javax.swing.plaf.basic.BasicTextUI;
038: import javax.swing.text.JTextComponent;
039:
040: import org.apache.log4j.Logger;
041: import org.isqlviewer.swing.action.SwingEventManager;
042: import org.isqlviewer.ui.ThrowableView;
043:
044: /**
045: * Context to support custom wizards by providing common functionality.
046: * <p>
047: * This object is in the same spirit of a ServletContext, this class represents common functionality for all custom
048: * wizards.
049: *
050: * @author Mark A. Kobold <mkobold at isqlviewer dot com>
051: * @version 1.0
052: */
053: public abstract class WizardContext {
054:
055: private Logger logger = Logger.getLogger(getClass());
056: private Hashtable<String, Object> attributes = new Hashtable<String, Object>();
057: private SwingEventManager eventManager;
058:
059: protected WizardContext(SwingEventManager eventManager) {
060:
061: this .eventManager = eventManager;
062: }
063:
064: /**
065: * Logs informational error and supplementary message.
066: * <p>
067: * if informational messages are enabled the message and exception will be logged to designated destination.
068: *
069: * @param message informational message to log.
070: * @param error exception associated with the message.
071: */
072: public void info(Object message, Throwable error) {
073:
074: if (logger.isInfoEnabled()) {
075: logger.info(message, error);
076: }
077: }
078:
079: /**
080: * Logs an informational message.
081: * <p>
082: * if informational loggins is enabled the message will be logged to designated destination.
083: *
084: * @param message informational message to log.
085: */
086: public void info(Object message) {
087:
088: if (logger.isInfoEnabled()) {
089: logger.info(message);
090: }
091: }
092:
093: /**
094: * Logs debugging messages and supplementary exception.
095: * <p>
096: * if debug messages are enabled the message and exception will be logged to designated destination.
097: *
098: * @param message debug message to log.
099: * @param error exception associated with the message.
100: */
101: public void debug(Object message, Throwable error) {
102:
103: if (logger.isDebugEnabled()) {
104: logger.debug(message, error);
105: }
106: }
107:
108: /**
109: * Logs message for debugging purposes.
110: * <p>
111: * if debugging is enabled the message will be logged to designated destination.
112: *
113: * @param message debug information to log.
114: */
115: public void debug(Object message) {
116:
117: if (logger.isDebugEnabled()) {
118: logger.debug(message);
119: }
120: }
121:
122: /**
123: * Logs error messages and supplementary exception.
124: * <p>
125: * if error messages are enabled the message and exception will be logged to designated destination.
126: *
127: * @param message error message to log.
128: * @param error exception associated with the message.
129: */
130: public void error(Object message, Throwable error) {
131:
132: logger.error(message, error);
133: }
134:
135: /**
136: * Logs an error message.
137: * <p>
138: * if error logging is enabled the message will be logged to designated destination.
139: *
140: * @param message error message to log.
141: */
142: public void error(Object message) {
143:
144: logger.error(message);
145: }
146:
147: /**
148: * Logs warning messages and supplementary exception.
149: * <p>
150: *
151: * @param message warning message to log.
152: * @param error exception associated with the message.
153: */
154: public void warn(Object message, Throwable error) {
155:
156: logger.warn(message, error);
157: }
158:
159: /**
160: * Logs warning messages.
161: * <p>
162: *
163: * @param message warning information to log.
164: */
165: public void warn(Object message) {
166:
167: logger.warn(message);
168: }
169:
170: /**
171: * Marks a text component as invalid to the user.
172: * <p>
173: * If a text field has invalid input than this method should be called to provide consistent feedback to the user
174: * with the notion of invalid input.
175: *
176: * @param textArea to mark as incorrect or invalid.
177: * @see #unmarkTextComponentIncorrect(JTextComponent)
178: */
179: public void markTextComponentIncorrect(JTextComponent textArea) {
180:
181: textArea
182: .setForeground(UIManager.getColor("ToolTip.foreground"));
183: textArea
184: .setBackground(UIManager.getColor("ToolTip.background"));
185: }
186:
187: /**
188: * Restores an invalid text component to its original state.
189: * <p>
190: * Use this method in conjunction with markTextComponentIncorrect() when the user input has become valid.
191: *
192: * @param textArea to restore and mark as valid.
193: * @see #markTextComponentIncorrect(JTextComponent)
194: */
195: public void unmarkTextComponentIncorrect(JTextComponent textArea) {
196:
197: String prefix = null;
198: BasicTextUI uiClass = (BasicTextUI) textArea.getUI();
199: // Why they didn't make the property prefix public in the UI is beyond me >.>
200: if (uiClass instanceof BasicTextAreaUI) {
201: prefix = "TextArea";
202: } else if (uiClass instanceof BasicTextFieldUI) {
203: prefix = "TextField";
204: } else if (uiClass instanceof BasicEditorPaneUI) {
205: prefix = "EditorPane";
206: }
207: if (prefix == null) {
208: textArea.setForeground(Color.BLACK);
209: textArea.setBackground(Color.WHITE);
210: } else {
211: textArea.setForeground(UIManager.getColor(prefix
212: + ".foreground"));
213: textArea.setBackground(UIManager.getColor(prefix
214: + ".background"));
215: }
216: }
217:
218: /**
219: * Sets an attribute in this context.
220: * <p>
221: * If an attribute already exists with the given name it will override it with the new value.
222: *
223: * @param name of the object to bound to this context.
224: * @param attribute the value being bound to this context by the given name.
225: * @throws NullPointerException if name or attribute are null;
226: */
227: public void setAttribute(String name, Object attribute) {
228:
229: String normalized = name.toLowerCase().trim();
230: attributes.put(normalized, attribute);
231: }
232:
233: /**
234: * Removes the selected attribute by name from this context.
235: * <p>
236: * Once the attribute has been removed it will no longer be accesible from this context.
237: *
238: * @param name of the attribute to remove.
239: * @throws NullPointerException if name is null.
240: */
241: public void removeAttribute(String name) {
242:
243: String normalized = name.toLowerCase().trim();
244: attributes.remove(normalized);
245: }
246:
247: /**
248: * Provides an enumeration of all available attributes in the current context.
249: * <p>
250: *
251: * @return enumeration of all the attribute names currently bound in this context.
252: */
253: public Enumeration<String> getAttributeNames() {
254:
255: return attributes.keys();
256: }
257:
258: /**
259: * Returns the context attribute with the given name, or null if there is no attribute by that name.
260: * <p>
261: * An attribute allows a wizard runner instance to give the custom wizard additional information inbetween steps.
262: *
263: * @return an Object containing the value of the attribute, or null if no attribute exists matching the given name
264: * @throws NullPointerException if name is null
265: */
266: public Object getAttribute(String name) {
267:
268: String normalized = name.toLowerCase().trim();
269: return attributes.get(normalized);
270: }
271:
272: /**
273: * Shows a generic error dialog to the user with an error and message.
274: * <p>
275: * This implementation allows wizard code to notify the user of an error without having to have a reference to an
276: * actual visual component.
277: *
278: * @param error with an accompanying stack-trace the display can be null.
279: * @param message descriptive message as to the source of error.
280: */
281: public abstract void showErrorDialog(Throwable error, String message);
282:
283: /**
284: * Updates the list of setps after the current step.
285: * <p>
286: * Often wizards will allow a user to take different action leading to different set of steps. this function allows
287: * a wizard to change the steps following the current step. So that the user will see the new steps they will be
288: * taking as part of thier choice in the wizard.
289: *
290: * @param newSteps collection of steps to modify after the current step.
291: */
292: public abstract void updateSteps(Collection<Step> newSteps);
293:
294: /**
295: * Shows a generic error dialog to the user with an error and message.
296: * <p>
297: * This implementation allows wizard code to notify the user of an error without having to have a reference to an
298: * actual visual component.
299: *
300: * @param error with an accompanying stack-trace the display can be null.
301: * @param message descriptive message as to the source of error.
302: * @param owner component owner to show the error dialog from.
303: */
304: public void showErrorDialog(Component owner, Throwable error,
305: String message) {
306:
307: ThrowableView view = new ThrowableView(error, message);
308: JPanel container = new JPanel();
309: view.doLayout(container, null, null);
310: view.initializeView();
311: container.invalidate();
312: try {
313: error(message, error);
314: JOptionPane.showMessageDialog(owner, container, null,
315: JOptionPane.ERROR_MESSAGE);
316: } finally {
317: view.disposeView(null);
318: }
319: }
320:
321: /**
322: * Shows a generic information dialog to the user with a message
323: * <p>
324: * This implementation allows wizard code to notify the user informational message without having to have a
325: * reference to an actual visual component.
326: *
327: * @param message descriptive message to the user.
328: */
329: public abstract void showInformationDialog(String message);
330:
331: /**
332: * Allows pragmatic navigation through other events beyond clicking 'Next' in a wizard.
333: * <p>
334: */
335: public abstract void invokeNext();
336:
337: /**
338: * Shows a generic information dialog to the user with a message
339: * <p>
340: *
341: * @param message descriptive message to the user.
342: * @param owner component owner to show the informational dialog from.
343: */
344: public void showInformationDialog(Component owner, String message) {
345:
346: String html = null;
347: if (message != null && !message.startsWith("<html>")) {
348: html = "<html>".concat(message.trim());
349: } else if (message == null) {
350: html = "";
351: }
352: JOptionPane.showMessageDialog(owner, html, null,
353: JOptionPane.INFORMATION_MESSAGE);
354: }
355:
356: public SwingEventManager getEventManager() {
357:
358: return eventManager;
359: }
360:
361: }
|