001: /*
002: * IzPack - Copyright 2001-2008 Julien Ponge, All Rights Reserved.
003: *
004: * http://izpack.org/
005: * http://izpack.codehaus.org/
006: *
007: * Licensed under the Apache License, Version 2.0 (the "License");
008: * you may not use this file except in compliance with the License.
009: * You may obtain a copy of the License at
010: *
011: * http://www.apache.org/licenses/LICENSE-2.0
012: *
013: * Unless required by applicable law or agreed to in writing, software
014: * distributed under the License is distributed on an "AS IS" BASIS,
015: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016: * See the License for the specific language governing permissions and
017: * limitations under the License.
018: */
019:
020: package com.izforge.izpack.uninstaller;
021:
022: import java.awt.Color;
023: import java.awt.Cursor;
024: import java.awt.Dimension;
025: import java.awt.GraphicsEnvironment;
026: import java.awt.GridBagConstraints;
027: import java.awt.GridBagLayout;
028: import java.awt.Insets;
029: import java.awt.Point;
030: import java.awt.Window;
031: import java.awt.event.ActionEvent;
032: import java.awt.event.ActionListener;
033: import java.awt.event.KeyAdapter;
034: import java.awt.event.MouseAdapter;
035: import java.awt.event.MouseMotionAdapter;
036: import java.awt.event.WindowAdapter;
037: import java.awt.event.WindowEvent;
038: import java.io.BufferedReader;
039: import java.io.InputStream;
040: import java.io.InputStreamReader;
041: import java.net.URL;
042:
043: import javax.swing.ImageIcon;
044: import javax.swing.JButton;
045: import javax.swing.JCheckBox;
046: import javax.swing.JFrame;
047: import javax.swing.JLabel;
048: import javax.swing.JOptionPane;
049: import javax.swing.JPanel;
050: import javax.swing.JProgressBar;
051: import javax.swing.SwingUtilities;
052: import javax.swing.UIManager;
053:
054: import com.izforge.izpack.LocaleDatabase;
055: import com.izforge.izpack.gui.ButtonFactory;
056: import com.izforge.izpack.gui.IconsDatabase;
057: import com.izforge.izpack.util.AbstractUIHandler;
058:
059: /**
060: * The uninstaller frame class.
061: *
062: * @author Julien Ponge
063: */
064: public class UninstallerFrame extends JFrame {
065:
066: /**
067: *
068: */
069: private static final long serialVersionUID = 3257281444152684850L;
070:
071: /** The icons database. */
072: private IconsDatabase icons;
073:
074: /** The language pack. */
075: protected static LocaleDatabase langpack;
076:
077: /** The target destroy checkbox. */
078: protected JCheckBox targetDestroyCheckbox;
079:
080: /** The progress bar. */
081: protected JProgressBar progressBar;
082:
083: /** The destroy button. */
084: protected JButton destroyButton;
085:
086: /** The quit button. */
087: protected JButton quitButton;
088:
089: /** The buttons hover color. */
090: private Color buttonsHColor = new Color(230, 230, 230);
091:
092: /** The installation path. */
093: protected String installPath;
094:
095: /**
096: * The constructor.
097: *
098: * @param displayForceOption If true, display to the user the option permitting to force
099: * all files deletion.
100: * @param forceOptionState If true, force deletion is activated.
101: * @exception Exception Description of the Exception
102: */
103: public UninstallerFrame(boolean displayForceOption,
104: boolean forceOptionState) throws Exception {
105: super ("IzPack - Uninstaller");
106:
107: // Initializations
108: langpack = new LocaleDatabase(UninstallerFrame.class
109: .getResourceAsStream("/langpack.xml"));
110: getInstallPath();
111: icons = new IconsDatabase();
112: loadIcons();
113: UIManager.put("OptionPane.yesButtonText", langpack
114: .getString("installer.yes"));
115: UIManager.put("OptionPane.noButtonText", langpack
116: .getString("installer.no"));
117: UIManager.put("OptionPane.cancelButtonText", langpack
118: .getString("installer.cancel"));
119:
120: // Sets the frame icon
121: setIconImage(icons.getImageIcon("JFrameIcon").getImage());
122:
123: // We build the GUI & show it
124: buildGUI(displayForceOption, forceOptionState);
125: addWindowListener(new WindowHandler());
126: pack();
127: centerFrame(this );
128: setResizable(false);
129: setVisible(true);
130: }
131:
132: /**
133: * Builds the GUI.
134: *
135: * @param displayForceOption If true, display to the user the option permitting to force
136: * all files deletion.
137: * @param forceOptionState If true, force deletion is activated.
138: */
139: private void buildGUI(boolean displayForceOption,
140: boolean forceOptionState) {
141: // We initialize our layout
142: JPanel contentPane = (JPanel) getContentPane();
143: GridBagLayout layout = new GridBagLayout();
144: contentPane.setLayout(layout);
145: GridBagConstraints gbConstraints = new GridBagConstraints();
146: gbConstraints.insets = new Insets(5, 5, 5, 5);
147:
148: // We prepare our action handler
149: ActionsHandler handler = new ActionsHandler();
150:
151: // Prepares the glass pane to block gui interaction when needed
152: JPanel glassPane = (JPanel) getGlassPane();
153: glassPane.addMouseListener(new MouseAdapter() {
154: });
155: glassPane.addMouseMotionListener(new MouseMotionAdapter() {
156: });
157: glassPane.addKeyListener(new KeyAdapter() {
158: });
159:
160: // We set-up the buttons factory
161: ButtonFactory.useButtonIcons();
162: ButtonFactory.useHighlightButtons();
163:
164: // We put our components
165:
166: JLabel warningLabel = new JLabel(langpack
167: .getString("uninstaller.warning"), icons
168: .getImageIcon("warning"), JLabel.TRAILING);
169: buildConstraints(gbConstraints, 0, 0, 2, 1, 1.0, 0.0);
170: gbConstraints.anchor = GridBagConstraints.WEST;
171: gbConstraints.fill = GridBagConstraints.NONE;
172: layout.addLayoutComponent(warningLabel, gbConstraints);
173: contentPane.add(warningLabel);
174:
175: targetDestroyCheckbox = new JCheckBox(langpack
176: .getString("uninstaller.destroytarget")
177: + installPath, forceOptionState);
178: buildConstraints(gbConstraints, 0, 1, 2, 1, 1.0, 0.0);
179: layout.addLayoutComponent(targetDestroyCheckbox, gbConstraints);
180: if (displayForceOption)
181: contentPane.add(targetDestroyCheckbox);
182: gbConstraints.fill = GridBagConstraints.HORIZONTAL;
183:
184: progressBar = new JProgressBar();
185: progressBar.setStringPainted(true);
186: progressBar.setString(langpack.getString("InstallPanel.begin"));
187: buildConstraints(gbConstraints, 0, 2, 2, 1, 1.0, 0.0);
188: layout.addLayoutComponent(progressBar, gbConstraints);
189: contentPane.add(progressBar);
190:
191: destroyButton = ButtonFactory.createButton(langpack
192: .getString("uninstaller.uninstall"), icons
193: .getImageIcon("delete"), buttonsHColor);
194: destroyButton.addActionListener(handler);
195: buildConstraints(gbConstraints, 0, 3, 1, 1, 0.5, 0.0);
196: gbConstraints.fill = GridBagConstraints.NONE;
197: gbConstraints.anchor = GridBagConstraints.WEST;
198: layout.addLayoutComponent(destroyButton, gbConstraints);
199: contentPane.add(destroyButton);
200:
201: quitButton = ButtonFactory.createButton(langpack
202: .getString("installer.quit"), icons
203: .getImageIcon("stop"), buttonsHColor);
204: quitButton.addActionListener(handler);
205: buildConstraints(gbConstraints, 1, 3, 1, 1, 0.5, 0.0);
206: gbConstraints.anchor = GridBagConstraints.EAST;
207: layout.addLayoutComponent(quitButton, gbConstraints);
208: contentPane.add(quitButton);
209:
210: }
211:
212: /**
213: * Centers a window on screen.
214: *
215: * @param frame The window to center.
216: */
217: private void centerFrame(Window frame) {
218: Point center = GraphicsEnvironment
219: .getLocalGraphicsEnvironment().getCenterPoint();
220: Dimension frameSize = frame.getSize();
221: frame.setLocation(center.x - frameSize.width / 2, center.y
222: - frameSize.height / 2 - 10);
223: }
224:
225: /**
226: * Sets the parameters of a GridBagConstraints object.
227: *
228: * @param gbc The constraints object.
229: * @param gx The x coordinates.
230: * @param gy The y coordinates.
231: * @param gw The width.
232: * @param wx The x wheight.
233: * @param wy The y wheight.
234: * @param gh Description of the Parameter
235: */
236: private void buildConstraints(GridBagConstraints gbc, int gx,
237: int gy, int gw, int gh, double wx, double wy) {
238: gbc.gridx = gx;
239: gbc.gridy = gy;
240: gbc.gridwidth = gw;
241: gbc.gridheight = gh;
242: gbc.weightx = wx;
243: gbc.weighty = wy;
244: }
245:
246: /**
247: * Gets the installation path from the log file.
248: *
249: * @exception Exception Description of the Exception
250: */
251: private void getInstallPath() throws Exception {
252: InputStream in = UninstallerFrame.class
253: .getResourceAsStream("/install.log");
254: InputStreamReader inReader = new InputStreamReader(in);
255: BufferedReader reader = new BufferedReader(inReader);
256: installPath = reader.readLine();
257: reader.close();
258: }
259:
260: /**
261: * Loads the icons.
262: *
263: * @exception Exception Description of the Exception
264: */
265: private void loadIcons() throws Exception {
266: // Initialisations
267: icons = new IconsDatabase();
268: URL url;
269: ImageIcon img;
270:
271: // We load it
272: url = UninstallerFrame.class.getResource("/img/trash.png");
273: img = new ImageIcon(url);
274: icons.put("delete", img);
275:
276: url = UninstallerFrame.class.getResource("/img/stop.png");
277: img = new ImageIcon(url);
278: icons.put("stop", img);
279:
280: url = UninstallerFrame.class.getResource("/img/flag.png");
281: img = new ImageIcon(url);
282: icons.put("warning", img);
283:
284: url = UninstallerFrame.class.getResource("/img/JFrameIcon.png");
285: img = new ImageIcon(url);
286: icons.put("JFrameIcon", img);
287: }
288:
289: /** Blocks GUI interaction. */
290: public void blockGUI() {
291: setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
292: getGlassPane().setVisible(true);
293: getGlassPane().setEnabled(true);
294: }
295:
296: /** Releases GUI interaction. */
297: public void releaseGUI() {
298: getGlassPane().setEnabled(false);
299: getGlassPane().setVisible(false);
300: setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
301: }
302:
303: /**
304: * The window events handler.
305: *
306: * @author Julien Ponge
307: */
308: private final class WindowHandler extends WindowAdapter {
309:
310: /**
311: * We can't avoid the exit here, so don't call exit elsewhere.
312: *
313: * @param e The event.
314: */
315: public void windowClosing(WindowEvent e) {
316: System.exit(0);
317: }
318: }
319:
320: /**
321: * The destroyer handler.
322: *
323: * This class also implements the InstallListener because the FileExecutor needs it. TODO: get
324: * rid of the InstallListener - implement generic Listener
325: *
326: * @author Julien Ponge
327: * @author Tino Schwarze
328: */
329: private final class DestroyerHandler implements
330: com.izforge.izpack.util.AbstractUIProgressHandler {
331:
332: /**
333: * The destroyer starts.
334: *
335: * @param name The name of the overall action. Not used here.
336: * @param max The maximum value of the progress.
337: */
338: public void startAction(final String name, final int max) {
339: SwingUtilities.invokeLater(new Runnable() {
340: public void run() {
341: progressBar.setMinimum(0);
342: progressBar.setMaximum(max);
343: blockGUI();
344: }
345: });
346: }
347:
348: /** The destroyer stops. */
349: public void stopAction() {
350: SwingUtilities.invokeLater(new Runnable() {
351: public void run() {
352: progressBar.setString(langpack
353: .getString("InstallPanel.finished"));
354: targetDestroyCheckbox.setEnabled(false);
355: destroyButton.setEnabled(false);
356: releaseGUI();
357: }
358: });
359: }
360:
361: /**
362: * The destroyer progresses.
363: *
364: * @param pos The actual position.
365: * @param message The message.
366: */
367: public void progress(final int pos, final String message) {
368: SwingUtilities.invokeLater(new Runnable() {
369: public void run() {
370: progressBar.setValue(pos);
371: progressBar.setString(message);
372: }
373: });
374: }
375:
376: /**
377: * {@inheritDoc}
378: */
379: public void nextStep(String step_name, int step_no,
380: int no_of_substeps) {
381: // not used
382: }
383:
384: /**
385: * {@inheritDoc}
386: */
387: public void setSubStepNo(int no_of_substeps) {
388: // not used
389: }
390:
391: /**
392: * Output a notification.
393: *
394: * Does nothing here.
395: *
396: * @param text
397: */
398: public void emitNotification(String text) {
399: }
400:
401: /**
402: * Output a warning.
403: *
404: * @param text
405: */
406: public boolean emitWarning(String title, String text) {
407: return (JOptionPane.showConfirmDialog(null, text, title,
408: JOptionPane.OK_CANCEL_OPTION,
409: JOptionPane.WARNING_MESSAGE) == JOptionPane.OK_OPTION);
410: }
411:
412: /**
413: * The destroyer encountered an error.
414: *
415: * @param error The error message.
416: */
417: public void emitError(String title, String error) {
418: progressBar.setString(error);
419: JOptionPane.showMessageDialog(null, error, title,
420: JOptionPane.OK_CANCEL_OPTION);
421: }
422:
423: /**
424: * Ask the user a question.
425: *
426: * @param title Message title.
427: * @param question The question.
428: * @param choices The set of choices to present.
429: *
430: * @return The user's choice.
431: *
432: * @see AbstractUIHandler#askQuestion(String, String, int)
433: */
434: public int askQuestion(String title, String question,
435: int choices) {
436: return askQuestion(title, question, choices, -1);
437: }
438:
439: /**
440: * Ask the user a question.
441: *
442: * @param title Message title.
443: * @param question The question.
444: * @param choices The set of choices to present.
445: * @param default_choice The default choice. (-1 = no default choice)
446: *
447: * @return The user's choice.
448: * @see AbstractUIHandler#askQuestion(String, String, int, int)
449: */
450: public int askQuestion(String title, String question,
451: int choices, int default_choice) {
452: int jo_choices = 0;
453:
454: if (choices == AbstractUIHandler.CHOICES_YES_NO)
455: jo_choices = JOptionPane.YES_NO_OPTION;
456: else if (choices == AbstractUIHandler.CHOICES_YES_NO_CANCEL)
457: jo_choices = JOptionPane.YES_NO_CANCEL_OPTION;
458:
459: int user_choice = JOptionPane.showConfirmDialog(null,
460: question, title, jo_choices,
461: JOptionPane.QUESTION_MESSAGE);
462:
463: if (user_choice == JOptionPane.CANCEL_OPTION)
464: return AbstractUIHandler.ANSWER_CANCEL;
465:
466: if (user_choice == JOptionPane.YES_OPTION)
467: return AbstractUIHandler.ANSWER_YES;
468:
469: if (user_choice == JOptionPane.NO_OPTION)
470: return AbstractUIHandler.ANSWER_NO;
471:
472: return default_choice;
473: }
474:
475: }
476:
477: /**
478: * The actions events handler.
479: *
480: * @author Julien Ponge
481: */
482: class ActionsHandler implements ActionListener {
483:
484: /**
485: * Action handling method.
486: *
487: * @param e The event.
488: */
489: public void actionPerformed(ActionEvent e) {
490: Object src = e.getSource();
491: if (src == quitButton)
492: System.exit(0);
493: else if (src == destroyButton) {
494: destroyButton.setEnabled(false);
495: Destroyer destroyer = new Destroyer(installPath,
496: targetDestroyCheckbox.isSelected(),
497: new DestroyerHandler());
498: destroyer.start();
499: }
500: }
501: }
502:
503: /**
504: * Returns the langpack.
505: *
506: * @return Returns the langpack.
507: */
508: public static LocaleDatabase getLangpack() {
509: return langpack;
510: }
511:
512: }
|