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