/*
* SwingInstall.java
*
* Originally written by Slava Pestov for the jEdit installer project. This work
* has been placed into the public domain. You may use this work in any way and
* for any purpose you wish.
*
* THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, NOT EVEN THE
* IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE, ASSUMES
* _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE RESULTING FROM THE USE, MODIFICATION,
* OR REDISTRIBUTION OF THIS SOFTWARE.
*/
package installer;
import javax.swing.border.*;
import javax.swing.*;
import javax.swing.text.JTextComponent;
import java.awt.event.*;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.*;
/*
* Graphical front-end to installer.
*/
public class SwingInstall extends JFrame
{
public SwingInstall()
{
installer = new Install();
osTasks = OperatingSystem.getOperatingSystem().getOSTasks(installer);
appName = installer.getProperty("app.name");
appVersion = installer.getProperty("app.version");
setTitle(appName + " " + appVersion + " installer");
JPanel content = new JPanel(new WizardLayout());
setContentPane(content);
caption = new JLabel();
caption.setFont(new Font("SansSerif",Font.BOLD,18));
ActionHandler actionHandler = new ActionHandler();
cancelButton = new JButton("Cancel");
cancelButton.setRequestFocusEnabled(false);
cancelButton.addActionListener(actionHandler);
prevButton = new JButton("Previous");
prevButton.setRequestFocusEnabled(false);
prevButton.addActionListener(actionHandler);
nextButton = new JButton();
nextButton.setRequestFocusEnabled(false);
nextButton.addActionListener(actionHandler);
content.add(caption);
content.add(cancelButton);
content.add(prevButton);
content.add(nextButton);
String clazz = OperatingSystem.getOperatingSystem()
.getClass().getName();
String completedInfo = "done-" + clazz.substring(
clazz.indexOf('$') + 1) + ".html";
pages = new Component[] {
new TextPanel(installer.getProperty("app.readme")),
new TextPanel(installer.getProperty("app.license")),
chooseDirectory = new ChooseDirectory(),
selectComponents = new SelectComponents(),
progress = new SwingProgress(),
new TextPanel(completedInfo)
};
for(int i = 0; i < pages.length; i++)
content.add(pages[i]);
pageChanged();
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowHandler());
Dimension screen = getToolkit().getScreenSize();
pack();
setLocation((screen.width - getSize().width) / 2,
(screen.height - getSize().height) / 2);
setVisible(true);
}
// package-private members
// package-private, not private, for speedy access by inner classes
Install installer;
OperatingSystem.OSTask[] osTasks;
String appName;
String appVersion;
JLabel caption;
ChooseDirectory chooseDirectory;
SelectComponents selectComponents;
SwingProgress progress;
JButton cancelButton;
JButton prevButton;
JButton nextButton;
Component[] pages;
int currentPage;
private static final int PADDING = 12;
void install()
{
Vector components = new Vector();
int size = 0;
JPanel comp = selectComponents.comp;
Vector ids = selectComponents.filesets;
for(int i = 0; i < comp.getComponentCount(); i++)
{
if(((JCheckBox)comp.getComponent(i))
.getModel().isSelected())
{
size += installer.getIntegerProperty(
"comp." + ids.elementAt(i) + ".real-size");
components.addElement(installer.getProperty(
"comp." + ids.elementAt(i) + ".fileset"));
}
}
String installDir = chooseDirectory.installDir.getText();
Map osTaskDirs = chooseDirectory.osTaskDirs;
Iterator keys = osTaskDirs.keySet().iterator();
while(keys.hasNext())
{
OperatingSystem.OSTask osTask = (OperatingSystem.OSTask)keys.next();
String dir = ((JTextField)osTaskDirs.get(osTask)).getText();
if(dir != null && dir.trim().length() != 0)
{
osTask.setEnabled(true);
osTask.setDirectory(dir);
}
else
osTask.setEnabled(false);
}
InstallThread thread = new InstallThread(
installer,progress,
installDir,osTasks,
size,components);
progress.setThread(thread);
thread.start();
}
private void pageChanged()
{
switch(currentPage)
{
case 0:
caption.setText("Installing " + appName);
nextButton.setText("Next");
prevButton.setEnabled(false);
nextButton.setEnabled(true);
break;
case 1:
caption.setText(installer.getProperty("app.license.title"));
nextButton.setText("Next");
prevButton.setEnabled(true);
nextButton.setEnabled(true);
break;
case 2:
caption.setText("Specify where " + appName
+ " is to be installed");
nextButton.setText("Next");
prevButton.setEnabled(true);
if(!chooseDirectory.isOK())nextButton.setEnabled(false);
break;
case 3:
caption.setText("Choose components to install");
nextButton.setText("Install");
prevButton.setEnabled(true);
nextButton.setEnabled(true);
break;
case 4:
caption.setText("Installing " + appName);
nextButton.setText("Finish");
prevButton.setEnabled(false);
nextButton.setEnabled(false);
install();
break;
case 5:
caption.setText("Installation complete");
nextButton.setText("Finish");
prevButton.setEnabled(false);
nextButton.setEnabled(true);
cancelButton.setEnabled(false);
break;
}
getRootPane().invalidate();
getRootPane().validate();
}
class ActionHandler implements ActionListener
{
public void actionPerformed(ActionEvent evt)
{
Object source = evt.getSource();
if(source == cancelButton)
System.exit(0);
else if(source == prevButton)
{
currentPage--;
pageChanged();
}
else if(source == nextButton)
{
if(currentPage == pages.length - 1)
System.exit(0);
else
{
currentPage++;
pageChanged();
}
}
}
}
class WindowHandler extends WindowAdapter
{
public void windowClosing(WindowEvent evt)
{
System.exit(0);
}
}
class WizardLayout implements LayoutManager
{
public void addLayoutComponent(String name, Component comp)
{
}
public void removeLayoutComponent(Component comp)
{
}
public Dimension preferredLayoutSize(Container parent)
{
Dimension dim = new Dimension();
Dimension captionSize = caption.getPreferredSize();
dim.width = captionSize.width;
for(int i = 0; i < pages.length; i++)
{
Dimension _dim = pages[i].getPreferredSize();
dim.width = Math.max(_dim.width,dim.width);
dim.height = Math.max(_dim.height,dim.height);
}
dim.width += PADDING * 2;
dim.height += PADDING * 2;
dim.height += nextButton.getPreferredSize().height;
dim.height += captionSize.height;
return dim;
}
public Dimension minimumLayoutSize(Container parent)
{
return preferredLayoutSize(parent);
}
public void layoutContainer(Container parent)
{
Dimension size = parent.getSize();
Dimension captionSize = caption.getPreferredSize();
caption.setBounds(PADDING,PADDING,captionSize.width,
captionSize.height);
// make all buttons the same size
Dimension buttonSize = cancelButton.getPreferredSize();
buttonSize.width = Math.max(buttonSize.width,prevButton.getPreferredSize().width);
buttonSize.width = Math.max(buttonSize.width,nextButton.getPreferredSize().width);
// cancel button goes on far left
cancelButton.setBounds(
PADDING,
size.height - buttonSize.height - PADDING,
buttonSize.width,
buttonSize.height);
// prev and next buttons are on the right
prevButton.setBounds(
size.width - buttonSize.width * 2 - 6 - PADDING,
size.height - buttonSize.height - PADDING,
buttonSize.width,
buttonSize.height);
nextButton.setBounds(
size.width - buttonSize.width - PADDING,
size.height - buttonSize.height - PADDING,
buttonSize.width,
buttonSize.height);
// calculate size for current page
Rectangle currentPageBounds = new Rectangle();
currentPageBounds.x = PADDING;
currentPageBounds.y = PADDING * 2 + captionSize.height;
currentPageBounds.width = size.width - currentPageBounds.x
- PADDING;
currentPageBounds.height = size.height - buttonSize.height
- currentPageBounds.y - PADDING * 2;
for(int i = 0; i < pages.length; i++)
{
Component page = pages[i];
page.setBounds(currentPageBounds);
page.setVisible(i == currentPage);
}
}
}
class TextPanel extends JPanel
{
TextPanel(String file)
{
super(new BorderLayout());
JEditorPane text = new JEditorPane();
try
{
text.setPage(TextPanel.this.getClass().getResource(file));
}
catch(Exception e)
{
text.setText("Error loading '" + file + "'");
e.printStackTrace();
}
text.setEditable(false);
JScrollPane scrollPane = new JScrollPane(text);
Dimension dim = new Dimension();
dim.width = 450;
dim.height = 200;
scrollPane.setPreferredSize(dim);
TextPanel.this.add(BorderLayout.CENTER,scrollPane);
}
}
class DirVerifier extends InputVerifier
{
private JTextComponent message;
private Object pos;
private JComponent parent;
public DirVerifier(JComponent parent, Object pos)
{
super();
message = new JTextArea(" ");
message.setEditable(false);
message.setBackground(parent.getBackground());
this.parent = parent;
this.pos = pos;
}
public boolean shouldYieldFocus(JComponent input)
{
return verify(input);
}
public boolean verify(JComponent input)
{
if(input instanceof JTextComponent)
{
String dir = ((JTextComponent)input).getText();
if(checkNull(dir) &&
checkExistNotDirectory(dir) &&
checkExistNotEmpty(dir) &&
checkRelative(dir))
{
//everything is perfect, clean label
if(message.getParent()!=null)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
parent.remove(message);
parent.revalidate();
parent.repaint();
}
});
}
}
else
{
if(message.getParent()==null)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
parent.add(message,pos);
parent.revalidate();
parent.repaint();
}
});
}
else message.repaint();
}
}
return true;
}
private boolean checkNull(String file)
{
if(file.trim().length()==0)
{
message.setForeground(Color.red);
message.setText(installer.getProperty("dir.null"));
return false;
}
else return true;
}
private boolean checkRelative(String dir)
{
File f = new File(dir);
if(!f.isAbsolute())
{
String msg = installer.getProperty("dir.relative");
try
{
String full = f.getCanonicalPath();
message.setForeground(Color.orange);
message.setText(msg+'\n'+full);
}
catch(IOException ioe)
{
message.setForeground(Color.red);
msg = installer.getProperty("dir.cant-resolve");
message.setText(msg);
}
return false;
}
else return true;
}
private boolean checkExistNotDirectory(String dir)
{
File f = new File(dir);
if(f.exists() && !f.isDirectory())
{
message.setForeground(Color.red);
message.setText(installer.getProperty("dir.not-directory"));
return false;
}
else return true;
}
private boolean checkExistNotEmpty(String dir)
{
File f = new File(dir);
String[]cnt = f.list();
if(cnt!=null && cnt.length>0)
{
message.setForeground(Color.orange);
message.setText(installer.getProperty("dir.not-empty"));
return false;
}
else return true;
}
}
/**
* only install directory is required, as it's necessary to scripts, etc.
* If one uses the installer only for OS tasks, then one deselects all components
* and that's all.
*/
class ChooseDirectory extends JPanel
{
JTextField installDir;
Map osTaskDirs;
ChooseDirectory()
{
super(new BorderLayout());
osTaskDirs = new HashMap();
JPanel directoryPanel = new JPanel(new GridBagLayout());
installDir = addField(directoryPanel,"Install program in:",
OperatingSystem.getOperatingSystem()
.getInstallDirectory(appName,appVersion));
installDir.addFocusListener(new FocusAdapter()
{
public void focusLost(FocusEvent fe)
{
nextButton.setEnabled(isOK());
}
});
for(int i = 0; i < osTasks.length; i++)
{
OperatingSystem.OSTask osTask = osTasks[i];
String label = osTask.getLabel();
if(label != null)
{
JTextField field = addField(directoryPanel,label,
osTask.getDirectory());
osTaskDirs.put(osTask,field);
}
}
ChooseDirectory.this.add(BorderLayout.NORTH,directoryPanel);
}
boolean isOK()
{
if(installDir.getText().length()==0)return false;
File f = new File(installDir.getText());
return !(f.exists()&&!f.isDirectory());
}
private GridBagConstraints c = new GridBagConstraints();
private JTextField addField(JPanel directoryPanel, String label,
String defaultText)
{
//new line
c.gridy++;
//message
JTextField field = new JTextField(defaultText);
c.insets.bottom=3;
c.gridx=0;
c.gridwidth=3;
c.insets.left=0;
c.insets.right=0;
c.anchor=GridBagConstraints.LINE_START;
DirVerifier verif = new DirVerifier(directoryPanel,c.clone());
field.setInputVerifier(verif);
c.insets.bottom=12;
c.gridx=0;
c.gridy++;
c.gridwidth=1;
c.anchor=GridBagConstraints.LINE_END;
directoryPanel.add(new JLabel(label,SwingConstants.RIGHT),c);
c.gridx=1;
c.fill=GridBagConstraints.HORIZONTAL;
c.anchor=GridBagConstraints.CENTER;
c.insets.left=12;
c.insets.right=12;
c.weightx=1.0;
directoryPanel.add(field,c);
JButton choose = new JButton("Choose...");
choose.setRequestFocusEnabled(false);
choose.addActionListener(new ActionHandler(field));
c.gridx=2;
c.insets.left=0;
c.insets.right=0;
c.fill=GridBagConstraints.NONE;
c.weightx=0;
directoryPanel.add(choose,c);
return field;
}
class ActionHandler implements ActionListener
{
JTextField field;
ActionHandler(JTextField field)
{
this.field = field;
}
public void actionPerformed(ActionEvent evt)
{
File directory = new File(field.getText());
JFileChooser chooser = new JFileChooser(directory.getParent());
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
chooser.setSelectedFile(directory);
if(chooser.showOpenDialog(SwingInstall.this)
== JFileChooser.APPROVE_OPTION)
{
field.setText(chooser.getSelectedFile().getPath());
field.getInputVerifier().verify(field);
}
}
}
}
class SelectComponents extends JPanel
implements ActionListener
{
JPanel comp;
JLabel sizeLabel;
Vector filesets;
SelectComponents()
{
super(new BorderLayout());
comp = createCompPanel();
SelectComponents.this.add(BorderLayout.NORTH,comp);
sizeLabel = new JLabel("",SwingConstants.LEFT);
SelectComponents.this.add(BorderLayout.SOUTH,sizeLabel);
updateSize();
}
public void actionPerformed(ActionEvent evt)
{
updateSize();
}
private JPanel createCompPanel()
{
filesets = new Vector();
int count = installer.getIntegerProperty("comp.count");
JPanel panel = new JPanel(new GridLayout(count,1));
String osClass = OperatingSystem.getOperatingSystem()
.getClass().getName();
osClass = osClass.substring(osClass.indexOf('$') + 1);
for(int i = 0; i < count; i++)
{
String os = installer.getProperty("comp." + i + ".os");
if(os != null && !osClass.equals(os))
continue;
JCheckBox checkBox = new JCheckBox(
installer.getProperty("comp." + i + ".name")
+ " (" + installer.getProperty("comp." + i
+ ".disk-size") + "Kb)");
checkBox.getModel().setSelected(true);
checkBox.addActionListener(this);
checkBox.setRequestFocusEnabled(false);
filesets.addElement(new Integer(i));
panel.add(checkBox);
}
Dimension dim = panel.getPreferredSize();
dim.width = Integer.MAX_VALUE;
panel.setMaximumSize(dim);
return panel;
}
private void updateSize()
{
int size = 0;
for(int i = 0; i < filesets.size(); i++)
{
if(((JCheckBox)comp.getComponent(i))
.getModel().isSelected())
{
size += installer.getIntegerProperty("comp."
+ filesets.elementAt(i)
+ ".disk-size");
}
}
sizeLabel.setText("Estimated disk usage of selected"
+ " components: " + size + "Kb");
}
}
class SwingProgress extends JPanel implements Progress
{
JProgressBar progress;
InstallThread thread;
SwingProgress()
{
super(new BorderLayout());
progress = new JProgressBar();
progress.setStringPainted(true);
SwingProgress.this.add(BorderLayout.NORTH,progress);
}
public void setMaximum(final int max)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
progress.setMaximum(max);
}
});
}
public void advance(final int value)
{
try
{
SwingUtilities.invokeAndWait(new Runnable()
{
public void run()
{
progress.setValue(progress
.getValue() + value);
}
});
Thread.yield();
}
catch(Exception e)
{
}
}
public void done()
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
currentPage++;
pageChanged();
}
});
}
public void error(final String message)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
dispose();
JOptionPane.showMessageDialog(null,
message,
"Installation aborted",
JOptionPane.ERROR_MESSAGE);
System.exit(1);
}
});
}
public void message(final String message)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
progress.setString(message);
}
});
}
public void setThread(InstallThread thread)
{
this.thread = thread;
}
}
}
¤ Dauer der Verarbeitung: 0.31 Sekunden
(vorverarbeitet)
¤
|
Haftungshinweis
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.
|