PageRenderTime 47ms CodeModel.GetById 20ms app.highlight 22ms RepoModel.GetById 1ms app.codeStats 1ms

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

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