PageRenderTime 52ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-2-pre4/installer/SwingInstall.java

#
Java | 594 lines | 474 code | 99 blank | 21 comment | 31 complexity | dcb751b59510d7631b248b7d2ee04cc7 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. /*
  2. * SwingInstall.java
  3. *
  4. * Originally written by Slava Pestov for the jEdit installer project. This work
  5. * has been placed into the public domain. You may use this work in any way and
  6. * for any purpose you wish.
  7. *
  8. * THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, NOT EVEN THE
  9. * IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE, ASSUMES
  10. * _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE RESULTING FROM THE USE, MODIFICATION,
  11. * OR REDISTRIBUTION OF THIS SOFTWARE.
  12. */
  13. package installer;
  14. import javax.swing.border.*;
  15. import javax.swing.*;
  16. import java.awt.event.*;
  17. import java.awt.*;
  18. import java.io.File;
  19. import java.util.*;
  20. /*
  21. * Graphical front-end to installer.
  22. */
  23. public class SwingInstall extends JFrame
  24. {
  25. public SwingInstall()
  26. {
  27. installer = new Install();
  28. osTasks = OperatingSystem.getOperatingSystem().getOSTasks(installer);
  29. appName = installer.getProperty("app.name");
  30. appVersion = installer.getProperty("app.version");
  31. setTitle(appName + " " + appVersion + " installer");
  32. JPanel content = new JPanel(new WizardLayout());
  33. setContentPane(content);
  34. caption = new JLabel();
  35. caption.setFont(new Font("SansSerif",Font.BOLD,18));
  36. ActionHandler actionHandler = new ActionHandler();
  37. cancelButton = new JButton("Cancel");
  38. cancelButton.setRequestFocusEnabled(false);
  39. cancelButton.addActionListener(actionHandler);
  40. prevButton = new JButton("Previous");
  41. prevButton.setRequestFocusEnabled(false);
  42. prevButton.addActionListener(actionHandler);
  43. nextButton = new JButton();
  44. nextButton.setRequestFocusEnabled(false);
  45. nextButton.addActionListener(actionHandler);
  46. content.add(caption);
  47. content.add(cancelButton);
  48. content.add(prevButton);
  49. content.add(nextButton);
  50. String clazz = OperatingSystem.getOperatingSystem()
  51. .getClass().getName();
  52. String completedInfo = "done-" + clazz.substring(
  53. clazz.indexOf('$') + 1) + ".html";
  54. pages = new Component[] {
  55. new TextPanel(installer.getProperty("app.readme")),
  56. new TextPanel(installer.getProperty("app.license")),
  57. chooseDirectory = new ChooseDirectory(),
  58. selectComponents = new SelectComponents(),
  59. progress = new SwingProgress(),
  60. new TextPanel(completedInfo)
  61. };
  62. for(int i = 0; i < pages.length; i++)
  63. content.add(pages[i]);
  64. pageChanged();
  65. setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
  66. addWindowListener(new WindowHandler());
  67. Dimension screen = getToolkit().getScreenSize();
  68. pack();
  69. setLocation((screen.width - getSize().width) / 2,
  70. (screen.height - getSize().height) / 2);
  71. show();
  72. }
  73. // package-private members
  74. // package-private, not private, for speedy access by inner classes
  75. Install installer;
  76. OperatingSystem.OSTask[] osTasks;
  77. String appName;
  78. String appVersion;
  79. JLabel caption;
  80. ChooseDirectory chooseDirectory;
  81. SelectComponents selectComponents;
  82. SwingProgress progress;
  83. JButton cancelButton;
  84. JButton prevButton;
  85. JButton nextButton;
  86. Component[] pages;
  87. int currentPage;
  88. private static final int PADDING = 12;
  89. void install()
  90. {
  91. Vector components = new Vector();
  92. int size = 0;
  93. JPanel comp = selectComponents.comp;
  94. Vector ids = selectComponents.filesets;
  95. for(int i = 0; i < comp.getComponentCount(); i++)
  96. {
  97. if(((JCheckBox)comp.getComponent(i))
  98. .getModel().isSelected())
  99. {
  100. size += installer.getIntegerProperty(
  101. "comp." + ids.elementAt(i) + ".real-size");
  102. components.addElement(installer.getProperty(
  103. "comp." + ids.elementAt(i) + ".fileset"));
  104. }
  105. }
  106. String installDir = chooseDirectory.installDir.getText();
  107. Map osTaskDirs = chooseDirectory.osTaskDirs;
  108. Iterator keys = osTaskDirs.keySet().iterator();
  109. while(keys.hasNext())
  110. {
  111. OperatingSystem.OSTask osTask = (OperatingSystem.OSTask)keys.next();
  112. String dir = ((JTextField)osTaskDirs.get(osTask)).getText();
  113. if(dir != null && dir.length() != 0)
  114. {
  115. osTask.setEnabled(true);
  116. osTask.setDirectory(dir);
  117. }
  118. else
  119. osTask.setEnabled(false);
  120. }
  121. InstallThread thread = new InstallThread(
  122. installer,progress,
  123. installDir,osTasks,
  124. size,components);
  125. progress.setThread(thread);
  126. thread.start();
  127. }
  128. private void pageChanged()
  129. {
  130. switch(currentPage)
  131. {
  132. case 0:
  133. caption.setText("Installing " + appName);
  134. nextButton.setText("Next");
  135. prevButton.setEnabled(false);
  136. break;
  137. case 1:
  138. caption.setText(installer.getProperty("app.license.title"));
  139. nextButton.setText("Next");
  140. prevButton.setEnabled(true);
  141. break;
  142. case 2:
  143. caption.setText("Specify where " + appName
  144. + " is to be installed");
  145. nextButton.setText("Next");
  146. prevButton.setEnabled(true);
  147. break;
  148. case 3:
  149. caption.setText("Choose components to install");
  150. nextButton.setText("Install");
  151. prevButton.setEnabled(true);
  152. break;
  153. case 4:
  154. caption.setText("Installing " + appName);
  155. nextButton.setText("Finish");
  156. prevButton.setEnabled(false);
  157. nextButton.setEnabled(false);
  158. install();
  159. break;
  160. case 5:
  161. caption.setText("Installation complete");
  162. nextButton.setText("Finish");
  163. prevButton.setEnabled(false);
  164. nextButton.setEnabled(true);
  165. break;
  166. }
  167. getRootPane().invalidate();
  168. getRootPane().validate();
  169. }
  170. class ActionHandler implements ActionListener
  171. {
  172. public void actionPerformed(ActionEvent evt)
  173. {
  174. Object source = evt.getSource();
  175. if(source == cancelButton)
  176. System.exit(0);
  177. else if(source == prevButton)
  178. {
  179. currentPage--;
  180. pageChanged();
  181. }
  182. else if(source == nextButton)
  183. {
  184. if(currentPage == pages.length - 1)
  185. System.exit(0);
  186. else
  187. {
  188. currentPage++;
  189. pageChanged();
  190. }
  191. }
  192. }
  193. }
  194. class WindowHandler extends WindowAdapter
  195. {
  196. public void windowClosing(WindowEvent evt)
  197. {
  198. System.exit(0);
  199. }
  200. }
  201. class WizardLayout implements LayoutManager
  202. {
  203. public void addLayoutComponent(String name, Component comp)
  204. {
  205. }
  206. public void removeLayoutComponent(Component comp)
  207. {
  208. }
  209. public Dimension preferredLayoutSize(Container parent)
  210. {
  211. Dimension dim = new Dimension();
  212. Dimension captionSize = caption.getPreferredSize();
  213. dim.width = captionSize.width;
  214. for(int i = 0; i < pages.length; i++)
  215. {
  216. Dimension _dim = pages[i].getPreferredSize();
  217. dim.width = Math.max(_dim.width,dim.width);
  218. dim.height = Math.max(_dim.height,dim.height);
  219. }
  220. dim.width += PADDING * 2;
  221. dim.height += PADDING * 2;
  222. dim.height += nextButton.getPreferredSize().height;
  223. dim.height += captionSize.height;
  224. return dim;
  225. }
  226. public Dimension minimumLayoutSize(Container parent)
  227. {
  228. return preferredLayoutSize(parent);
  229. }
  230. public void layoutContainer(Container parent)
  231. {
  232. Dimension size = parent.getSize();
  233. Dimension captionSize = caption.getPreferredSize();
  234. caption.setBounds(PADDING,PADDING,captionSize.width,
  235. captionSize.height);
  236. // make all buttons the same size
  237. Dimension buttonSize = cancelButton.getPreferredSize();
  238. buttonSize.width = Math.max(buttonSize.width,prevButton.getPreferredSize().width);
  239. buttonSize.width = Math.max(buttonSize.width,nextButton.getPreferredSize().width);
  240. // cancel button goes on far left
  241. cancelButton.setBounds(
  242. PADDING,
  243. size.height - buttonSize.height - PADDING,
  244. buttonSize.width,
  245. buttonSize.height);
  246. // prev and next buttons are on the right
  247. prevButton.setBounds(
  248. size.width - buttonSize.width * 2 - 6 - PADDING,
  249. size.height - buttonSize.height - PADDING,
  250. buttonSize.width,
  251. buttonSize.height);
  252. nextButton.setBounds(
  253. size.width - buttonSize.width - PADDING,
  254. size.height - buttonSize.height - PADDING,
  255. buttonSize.width,
  256. buttonSize.height);
  257. // calculate size for current page
  258. Rectangle currentPageBounds = new Rectangle();
  259. currentPageBounds.x = PADDING;
  260. currentPageBounds.y = PADDING * 2 + captionSize.height;
  261. currentPageBounds.width = size.width - currentPageBounds.x
  262. - PADDING;
  263. currentPageBounds.height = size.height - buttonSize.height
  264. - currentPageBounds.y - PADDING * 2;
  265. for(int i = 0; i < pages.length; i++)
  266. {
  267. Component page = pages[i];
  268. page.setBounds(currentPageBounds);
  269. page.setVisible(i == currentPage);
  270. }
  271. }
  272. }
  273. class TextPanel extends JPanel
  274. {
  275. TextPanel(String file)
  276. {
  277. super(new BorderLayout());
  278. JEditorPane text = new JEditorPane();
  279. try
  280. {
  281. text.setPage(TextPanel.this.getClass().getResource(file));
  282. }
  283. catch(Exception e)
  284. {
  285. text.setText("Error loading '" + file + "'");
  286. e.printStackTrace();
  287. }
  288. text.setEditable(false);
  289. JScrollPane scrollPane = new JScrollPane(text);
  290. Dimension dim = new Dimension();
  291. dim.width = 450;
  292. dim.height = 200;
  293. scrollPane.setPreferredSize(dim);
  294. TextPanel.this.add(BorderLayout.CENTER,scrollPane);
  295. }
  296. }
  297. class ChooseDirectory extends JPanel
  298. {
  299. JTextField installDir;
  300. Map osTaskDirs;
  301. ChooseDirectory()
  302. {
  303. super(new BorderLayout());
  304. osTaskDirs = new HashMap();
  305. JPanel directoryPanel = new JPanel(new VariableGridLayout(
  306. VariableGridLayout.FIXED_NUM_COLUMNS,3,12,12));
  307. installDir = addField(directoryPanel,"Install program in:",
  308. OperatingSystem.getOperatingSystem()
  309. .getInstallDirectory(appName,appVersion));
  310. for(int i = 0; i < osTasks.length; i++)
  311. {
  312. OperatingSystem.OSTask osTask = osTasks[i];
  313. String label = osTask.getLabel();
  314. if(label != null)
  315. {
  316. JTextField field = addField(directoryPanel,label,
  317. osTask.getDirectory());
  318. osTaskDirs.put(osTask,field);
  319. }
  320. }
  321. ChooseDirectory.this.add(BorderLayout.NORTH,directoryPanel);
  322. }
  323. private JTextField addField(JPanel directoryPanel, String label,
  324. String defaultText)
  325. {
  326. JTextField field = new JTextField(defaultText);
  327. directoryPanel.add(new JLabel(label,SwingConstants.RIGHT));
  328. Box fieldBox = new Box(BoxLayout.Y_AXIS);
  329. fieldBox.add(Box.createGlue());
  330. Dimension dim = field.getPreferredSize();
  331. dim.width = Integer.MAX_VALUE;
  332. field.setMaximumSize(dim);
  333. fieldBox.add(field);
  334. fieldBox.add(Box.createGlue());
  335. directoryPanel.add(fieldBox);
  336. JButton choose = new JButton("Choose...");
  337. choose.setRequestFocusEnabled(false);
  338. choose.addActionListener(new ActionHandler(field));
  339. directoryPanel.add(choose);
  340. return field;
  341. }
  342. class ActionHandler implements ActionListener
  343. {
  344. JTextField field;
  345. ActionHandler(JTextField field)
  346. {
  347. this.field = field;
  348. }
  349. public void actionPerformed(ActionEvent evt)
  350. {
  351. File directory = new File(field.getText());
  352. JFileChooser chooser = new JFileChooser(directory.getParent());
  353. chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
  354. chooser.setSelectedFile(directory);
  355. if(chooser.showOpenDialog(SwingInstall.this)
  356. == JFileChooser.APPROVE_OPTION)
  357. field.setText(chooser.getSelectedFile().getPath());
  358. }
  359. }
  360. }
  361. class SelectComponents extends JPanel
  362. implements ActionListener
  363. {
  364. JPanel comp;
  365. JLabel sizeLabel;
  366. Vector filesets;
  367. SelectComponents()
  368. {
  369. super(new BorderLayout());
  370. comp = createCompPanel();
  371. SelectComponents.this.add(BorderLayout.NORTH,comp);
  372. sizeLabel = new JLabel("",SwingConstants.LEFT);
  373. SelectComponents.this.add(BorderLayout.SOUTH,sizeLabel);
  374. updateSize();
  375. }
  376. public void actionPerformed(ActionEvent evt)
  377. {
  378. updateSize();
  379. }
  380. private JPanel createCompPanel()
  381. {
  382. filesets = new Vector();
  383. int count = installer.getIntegerProperty("comp.count");
  384. JPanel panel = new JPanel(new GridLayout(count,1));
  385. String osClass = OperatingSystem.getOperatingSystem()
  386. .getClass().getName();
  387. osClass = osClass.substring(osClass.indexOf('$') + 1);
  388. for(int i = 0; i < count; i++)
  389. {
  390. String os = installer.getProperty("comp." + i + ".os");
  391. if(os != null && !osClass.equals(os))
  392. continue;
  393. JCheckBox checkBox = new JCheckBox(
  394. installer.getProperty("comp." + i + ".name")
  395. + " (" + installer.getProperty("comp." + i
  396. + ".disk-size") + "Kb)");
  397. checkBox.getModel().setSelected(true);
  398. checkBox.addActionListener(this);
  399. checkBox.setRequestFocusEnabled(false);
  400. filesets.addElement(new Integer(i));
  401. panel.add(checkBox);
  402. }
  403. Dimension dim = panel.getPreferredSize();
  404. dim.width = Integer.MAX_VALUE;
  405. panel.setMaximumSize(dim);
  406. return panel;
  407. }
  408. private void updateSize()
  409. {
  410. int size = 0;
  411. for(int i = 0; i < filesets.size(); i++)
  412. {
  413. if(((JCheckBox)comp.getComponent(i))
  414. .getModel().isSelected())
  415. {
  416. size += installer.getIntegerProperty("comp."
  417. + filesets.elementAt(i)
  418. + ".disk-size");
  419. }
  420. }
  421. sizeLabel.setText("Estimated disk usage of selected"
  422. + " components: " + size + "Kb");
  423. }
  424. }
  425. class SwingProgress extends JPanel implements Progress
  426. {
  427. JProgressBar progress;
  428. InstallThread thread;
  429. SwingProgress()
  430. {
  431. super(new BorderLayout());
  432. progress = new JProgressBar();
  433. progress.setStringPainted(true);
  434. SwingProgress.this.add(BorderLayout.NORTH,progress);
  435. }
  436. public void setMaximum(final int max)
  437. {
  438. SwingUtilities.invokeLater(new Runnable()
  439. {
  440. public void run()
  441. {
  442. progress.setMaximum(max);
  443. }
  444. });
  445. }
  446. public void advance(final int value)
  447. {
  448. try
  449. {
  450. SwingUtilities.invokeAndWait(new Runnable()
  451. {
  452. public void run()
  453. {
  454. progress.setValue(progress
  455. .getValue() + value);
  456. }
  457. });
  458. Thread.yield();
  459. }
  460. catch(Exception e)
  461. {
  462. }
  463. }
  464. public void done()
  465. {
  466. SwingUtilities.invokeLater(new Runnable()
  467. {
  468. public void run()
  469. {
  470. currentPage++;
  471. pageChanged();
  472. }
  473. });
  474. }
  475. public void error(final String message)
  476. {
  477. SwingUtilities.invokeLater(new Runnable()
  478. {
  479. public void run()
  480. {
  481. dispose();
  482. JOptionPane.showMessageDialog(null,
  483. message,
  484. "Installation aborted",
  485. JOptionPane.ERROR_MESSAGE);
  486. System.exit(1);
  487. }
  488. });
  489. }
  490. public void setThread(InstallThread thread)
  491. {
  492. this.thread = thread;
  493. }
  494. }
  495. }