001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU General
007: * Public License Version 2 only ("GPL") or the Common Development and Distribution
008: * License("CDDL") (collectively, the "License"). You may not use this file except in
009: * compliance with the License. You can obtain a copy of the License at
010: * http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP. See the
011: * License for the specific language governing permissions and limitations under the
012: * License. When distributing the software, include this License Header Notice in
013: * each file and include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Sun
014: * designates this particular file as subject to the "Classpath" exception as
015: * provided by Sun in the GPL Version 2 section of the License file that
016: * accompanied this code. If applicable, add the following below the License Header,
017: * with the fields enclosed by brackets [] replaced by your own identifying
018: * information: "Portions Copyrighted [year] [name of copyright owner]"
019: *
020: * Contributor(s):
021: *
022: * The Original Software is NetBeans. The Initial Developer of the Original Software
023: * is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All
024: * Rights Reserved.
025: *
026: * If you wish your version of this file to be governed by only the CDDL or only the
027: * GPL Version 2, indicate your decision by adding "[Contributor] elects to include
028: * this software in this distribution under the [CDDL or GPL Version 2] license." If
029: * you do not indicate a single choice of license, a recipient has the option to
030: * distribute your version of this file under either the CDDL, the GPL Version 2 or
031: * to extend the choice of license to its licensees as provided above. However, if
032: * you add GPL Version 2 code and therefore, elected the GPL Version 2 license, then
033: * the option applies only if the new code is made subject to such option by the
034: * copyright holder.
035: */
036:
037: package org.netbeans.installer.wizard.components.panels;
038:
039: import java.awt.Color;
040: import java.awt.GridBagConstraints;
041: import java.awt.Insets;
042: import javax.swing.Icon;
043: import javax.swing.ImageIcon;
044: import javax.swing.event.DocumentEvent;
045: import javax.swing.event.DocumentListener;
046: import org.netbeans.installer.utils.ErrorManager;
047: import org.netbeans.installer.utils.ResourceUtils;
048: import org.netbeans.installer.utils.UiUtils;
049: import org.netbeans.installer.utils.helper.NbiThread;
050: import org.netbeans.installer.utils.helper.swing.NbiLabel;
051: import org.netbeans.installer.wizard.ui.SwingUi;
052: import org.netbeans.installer.wizard.ui.WizardUi;
053: import org.netbeans.installer.wizard.components.WizardPanel;
054: import org.netbeans.installer.wizard.components.WizardPanel.WizardPanelSwingUi;
055: import org.netbeans.installer.wizard.components.WizardPanel.WizardPanelUi;
056: import org.netbeans.installer.wizard.containers.SwingContainer;
057:
058: /**
059: *
060: * @author Kirill Sorokin
061: */
062: public class ErrorMessagePanel extends WizardPanel {
063: /////////////////////////////////////////////////////////////////////////////////
064: // Instance
065: public ErrorMessagePanel() {
066: setProperty(CANCEL_DIALOG_MESSAGE_PROPERTY,
067: DEFAULT_CANCEL_DIALOG_MESSAGE_TEXT);
068: setProperty(CANCEL_DIALOG_TITLE_PROPERTY,
069: DEFAULT_CANCEL_DIALOG_TITLE_TEXT);
070: setProperty(ERROR_FAILED_VERIFY_INPUT_PROPERTY,
071: DEFAULT_ERROR_FAILED_VERIFY_INPUT_TEXT);
072: }
073:
074: @Override
075: public WizardUi getWizardUi() {
076: if (wizardUi == null) {
077: wizardUi = new ErrorMessagePanelUi(this );
078: }
079:
080: return wizardUi;
081: }
082:
083: /////////////////////////////////////////////////////////////////////////////////
084: // Inner Classes
085: public static class ErrorMessagePanelUi extends WizardPanelUi {
086: protected ErrorMessagePanel component;
087:
088: public ErrorMessagePanelUi(ErrorMessagePanel component) {
089: super (component);
090:
091: this .component = component;
092: }
093:
094: public SwingUi getSwingUi(SwingContainer container) {
095: if (swingUi == null) {
096: swingUi = new ErrorMessagePanelSwingUi(component,
097: container);
098: }
099:
100: return super .getSwingUi(container);
101: }
102: }
103:
104: public static class ErrorMessagePanelSwingUi extends
105: WizardPanelSwingUi {
106: /////////////////////////////////////////////////////////////////////////////
107: // Constants
108: public static final String ERROR_ICON = "org/netbeans/installer/wizard/components/panels/error.png"; // NOI18N
109: public static final String WARNING_ICON = "org/netbeans/installer/wizard/components/panels/warning.png"; // NOI18N
110: public static final String INFO_ICON = "org/netbeans/installer/wizard/components/panels/info.png"; // NOI18N
111: public static final String EMPTY_ICON = "org/netbeans/installer/wizard/components/panels/empty.png"; // NOI18N
112:
113: public static final Color ERROR_COLOR = Color.BLACK;
114: public static final Color WARNING_COLOR = Color.BLACK;
115: public static final Color INFO_COLOR = Color.BLACK;
116: public static final Color EMPTY_COLOR = Color.BLACK;
117:
118: /////////////////////////////////////////////////////////////////////////////
119: // Instance
120: protected ErrorMessagePanel component;
121:
122: private Icon errorIcon;
123: private Icon warningIcon;
124: private Icon infoIcon;
125: private Icon emptyIcon;
126:
127: private Color errorColor;
128: private Color warningColor;
129: private Color infoColor;
130: private Color emptyColor;
131:
132: private NbiLabel errorLabel;
133:
134: private ValidatingThread validatingThread;
135:
136: public ErrorMessagePanelSwingUi(
137: final ErrorMessagePanel component,
138: final SwingContainer container) {
139: super (component, container);
140:
141: this .component = component;
142:
143: errorIcon = new ImageIcon(getClass().getClassLoader()
144: .getResource(ERROR_ICON));
145: warningIcon = new ImageIcon(getClass().getClassLoader()
146: .getResource(WARNING_ICON));
147: infoIcon = new ImageIcon(getClass().getClassLoader()
148: .getResource(INFO_ICON));
149: emptyIcon = new ImageIcon(getClass().getClassLoader()
150: .getResource(EMPTY_ICON));
151:
152: errorColor = ERROR_COLOR;
153: warningColor = WARNING_COLOR;
154: infoColor = INFO_COLOR;
155: emptyColor = EMPTY_COLOR;
156:
157: initComponents();
158: }
159:
160: @Override
161: public void evaluateBackButtonClick() {
162: if (validatingThread != null) {
163: validatingThread.pause();
164: }
165:
166: super .evaluateBackButtonClick();
167: }
168:
169: @Override
170: public void evaluateNextButtonClick() {
171: if (validatingThread != null) {
172: validatingThread.pause();
173: }
174:
175: final String errorMessage = validateInput();
176:
177: if (errorMessage == null) {
178: saveInput();
179: component.getWizard().next();
180: } else {
181: ErrorManager.notifyError(errorMessage);
182: if (validatingThread != null) {
183: validatingThread.play();
184: }
185: }
186: }
187:
188: @Override
189: public void evaluateCancelButtonClick() {
190: if (validatingThread != null) {
191: validatingThread.pause();
192: }
193:
194: if (!UiUtils
195: .showYesNoDialog(
196: component
197: .getProperty(CANCEL_DIALOG_TITLE_PROPERTY),
198: component
199: .getProperty(CANCEL_DIALOG_MESSAGE_PROPERTY))) {
200: if (validatingThread != null) {
201: validatingThread.play();
202: }
203: return;
204: }
205:
206: component.getWizard().getFinishHandler().cancel();
207: }
208:
209: // protected ////////////////////////////////////////////////////////////////
210: @Override
211: protected void initialize() {
212: updateErrorMessage();
213:
214: if (validatingThread == null) {
215: validatingThread = new ValidatingThread(this );
216: validatingThread.start();
217: } else {
218: validatingThread.play();
219: }
220: }
221:
222: protected String getWarningMessage() {
223: return null;
224: }
225:
226: protected String getInformationalMessage() {
227: return null;
228: }
229:
230: protected synchronized final void updateErrorMessage() {
231: String message;
232:
233: try {
234: message = validateInput();
235: if (message != null) {
236: errorLabel.setIcon(errorIcon);
237: errorLabel.setText(message);
238: errorLabel.setForeground(errorColor);
239: container.getNextButton().setEnabled(false);
240:
241: return;
242: }
243:
244: message = getWarningMessage();
245: if (message != null) {
246: errorLabel.setIcon(warningIcon);
247: errorLabel.setText(message);
248: errorLabel.setForeground(warningColor);
249: container.getNextButton().setEnabled(true);
250:
251: return;
252: }
253:
254: message = getInformationalMessage();
255: if (message != null) {
256: errorLabel.setIcon(infoIcon);
257: errorLabel.setText(message);
258: errorLabel.setForeground(infoColor);
259: container.getNextButton().setEnabled(true);
260:
261: return;
262: }
263:
264: errorLabel.setIcon(emptyIcon);
265: errorLabel.clearText();
266: errorLabel.setForeground(emptyColor);
267: container.getNextButton().setEnabled(true);
268: } catch (Exception e) {
269: // we have a good reason to catch Exception here, as most of the
270: // code that is called is not under the engine's control
271: // (validateInput() is component-specific) and we do not want to
272: // propagate unexpected exceptions that could otherwise be handled
273: // normally
274:
275: ErrorManager
276: .notifyError(
277: component
278: .getProperty(ERROR_FAILED_VERIFY_INPUT_PROPERTY),
279: e);
280: }
281: }
282:
283: // private //////////////////////////////////////////////////////////////////
284: private void initComponents() {
285: // errorLabel ///////////////////////////////////////////////////////////
286: errorLabel = new NbiLabel();
287: errorLabel.setFocusable(true);
288:
289: // this /////////////////////////////////////////////////////////////////
290: add(errorLabel, new GridBagConstraints(0, 99, // x, y
291: 99, 1, // width, height
292: 1.0, 0.0, // weight-x, weight-y
293: GridBagConstraints.CENTER, // anchor
294: GridBagConstraints.HORIZONTAL, // fill
295: new Insets(11, 11, 11, 11), // padding
296: 0, 0)); // ??? (padx, pady)
297: }
298:
299: /////////////////////////////////////////////////////////////////////////////
300: // Inner Classes
301: public static class ValidatingThread extends NbiThread {
302: /////////////////////////////////////////////////////////////////////////
303: // Instance
304: private ErrorMessagePanelSwingUi swingUi;
305: private boolean paused;
306:
307: public ValidatingThread(
308: final ErrorMessagePanelSwingUi swingUi) {
309: super ();
310:
311: this .swingUi = swingUi;
312: this .paused = false;
313: }
314:
315: public void run() {
316: while (true) {
317: if (!paused) {
318: swingUi.updateErrorMessage();
319: }
320:
321: try {
322: sleep(VALIDATION_DELAY);
323: } catch (InterruptedException e) {
324: ErrorManager.notifyDebug("Interrupted", e);
325: }
326: }
327: }
328:
329: public void pause() {
330: paused = true;
331: }
332:
333: public void play() {
334: paused = false;
335: }
336:
337: /////////////////////////////////////////////////////////////////////////
338: // Constants
339: public static final long VALIDATION_DELAY = 2000;
340: }
341:
342: public static class ValidatingDocumentListener implements
343: DocumentListener {
344: /////////////////////////////////////////////////////////////////////////
345: // Instance
346: private ErrorMessagePanelSwingUi swingUi;
347:
348: public ValidatingDocumentListener(
349: ErrorMessagePanelSwingUi swingUi) {
350: this .swingUi = swingUi;
351: }
352:
353: public void insertUpdate(DocumentEvent event) {
354: swingUi.updateErrorMessage();
355: }
356:
357: public void removeUpdate(DocumentEvent event) {
358: swingUi.updateErrorMessage();
359: }
360:
361: public void changedUpdate(DocumentEvent event) {
362: swingUi.updateErrorMessage();
363: }
364: }
365: }
366:
367: public static final String CANCEL_DIALOG_MESSAGE_PROPERTY = "cancel.dialog.message";//NOI18N
368: public static final String CANCEL_DIALOG_TITLE_PROPERTY = "cancel.dialog.title";//NOI18N
369: public static final String ERROR_FAILED_VERIFY_INPUT_PROPERTY = "error.failed.verify.input";//NOI18N
370:
371: public static final String DEFAULT_CANCEL_DIALOG_MESSAGE_TEXT = ResourceUtils
372: .getString(ErrorMessagePanel.class,
373: "EMP.cancel.dialog.message");//NOI18N
374: public static final String DEFAULT_CANCEL_DIALOG_TITLE_TEXT = ResourceUtils
375: .getString(ErrorMessagePanel.class,
376: "EMP.cancel.dialog.title");//NOI18N
377: public static final String DEFAULT_ERROR_FAILED_VERIFY_INPUT_TEXT = ResourceUtils
378: .getString(ErrorMessagePanel.class,
379: "EMP.error.failed.input.verify");//NOI18N
380: }
|