package com.limegroup.gnutella.gui.init;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JDialog;
import javax.swing.JPanel;
import com.limegroup.gnutella.gui.GUIMediator;
import com.limegroup.gnutella.gui.GUIUtils;
import com.limegroup.gnutella.gui.SplashWindow;
import com.limegroup.gnutella.settings.ApplicationSettings;
import com.limegroup.gnutella.settings.InstallSettings;
import com.limegroup.gnutella.settings.SettingsHandler;
import com.limegroup.gnutella.util.CommonUtils;
/**
* This class manages the setup wizard. It constructs all of the primary
* classes and acts as the mediator between the various objects in the
* setup windows.
*/
//2345678|012345678|012345678|012345678|012345678|012345678|012345678|012345678|
public class SetupManager {
/**
* the dialog window that holds all other gui elements for the setup.
*/
private JDialog _dialog;
/**
* the class that handles the buttons for the setup panels.
*/
private SetupButtons _setupButtons;
/**
* the holder for the setup windows
*/
private SetupWindowHolder _setupWindowHolder;
/**
* holder for the current setup window.
*/
private SetupWindow _currentWindow;
/**
* The array of scanned directory path names.
*/
private String[] _scannedPaths;
/**
* Flag for whether or not a scan has already been completed.
*/
private boolean _scanned = false;
/**
* Construts SetupManager, which can be used to determine which portions
* of setup need to be run, etc.
*/
public SetupManager() {
// Must set legacy values to true.
if( ApplicationSettings.INSTALLED.getValue() ) {
InstallSettings.SAVE_DIRECTORY.setValue(true);
InstallSettings.SPEED.setValue(true);
InstallSettings.SCAN_FILES.setValue(true);
}
}
/**
* Determines if the 'start on startup' window should be shown.
*/
private boolean shouldShowStartOnStartupWindow() {
if(InstallSettings.START_STARTUP.getValue())
return false;
return GUIUtils.shouldShowStartOnStartupWindow();
}
/**
* Determines if the 'a firewall warning may be displayed' window should be shown.
*/
public boolean shouldShowFirewallWindow() {
if(InstallSettings.FIREWALL_WARNING.getValue())
return false;
return CommonUtils.isWindows();
}
/**
* Constructs the appropriate setup windows if needed.
*/
public void createIfNeeded() {
List windows = new LinkedList();
if( !InstallSettings.LANGUAGE_CHOICE.getValue())
windows.add(new LanguageWindow(this));
if( !InstallSettings.SAVE_DIRECTORY.getValue() )
windows.add(new SaveWindow(this));
if( !InstallSettings.SPEED.getValue() )
windows.add(new SpeedWindow(this));
if( shouldShowStartOnStartupWindow() )
windows.add(new StartupWindow(this));
if( shouldShowFirewallWindow() ) {
windows.add(new FirewallWindowOne(this));
windows.add(new FirewallWindowTwo(this));
}
if( !InstallSettings.FILTER_OPTION.getValue() ) {
windows.add(new FilterWindow(this));
}
// SCAN WINDOW MUST BE LAST BECAUSE ITS FORWARD-BACK
// MOVING IS DEPENDENT ON USER OPTIONS.
if( !InstallSettings.SCAN_FILES.getValue() ) {
windows.add(new ScanWindow(this));
windows.add(new WaitWindow(this));
windows.add(new ScanConfirmWindow(this));
}
// Nothing to install?.. Begone.
if( windows.size() == 0 )
return;
// If the INSTALLED value is set, that means that a previous
// installer has already been run.
boolean partial = ApplicationSettings.INSTALLED.getValue();
// We need to ask the user's language very very first,
// so make sure that if the LanguageWindow is the first item,
// that the WelcomeWindow is inserted second.
// It's a little more tricky than that, though, because
// it could be possible that the LanguageWindow was the only
// item to be installed -- if that's the case, don't even
// insert the WelcomeWindow & FinishWindow at all.
if(windows.get(0) instanceof LanguageWindow) {
if(windows.size() > 1) {
windows.add(1, new WelcomeWindow(this, partial));
windows.add(new FinishWindow(this));
}
} else {
windows.add(0, new WelcomeWindow(this, partial));
windows.add(new FinishWindow(this));
}
// Create the setup window holder, which switches
// between the panels using a card layout.
_setupWindowHolder = new SetupWindowHolder();
// Iterate through each displayed window and set them up
// correctly. Note the special handling with the ScanWindow,
// which requires different windows for the 'Yes' and 'No'
// responses.
SetupWindow prior = null;
SetupWindow current = null;
ScanWindow scanner = null;
for(Iterator i = windows.iterator(); i.hasNext(); ) {
current = (SetupWindow)i.next();
_setupWindowHolder.add(current);
if(prior == null)
current.setPrevious(current);
else
current.setPrevious(prior);
// ScanWindow must be treated specially,
// with the 'Yes' going to the 'wait' window and the
// 'No' going to the next available window.
if(current instanceof ScanWindow)
scanner = (ScanWindow)current;
else if(current instanceof WaitWindow)
scanner.setYesWindow(current);
else if(current instanceof ScanConfirmWindow)
current.setPrevious(scanner);
if(prior != null)
prior.setNext(current);
prior = current;
}
if(scanner != null)
scanner.setNoWindow((SetupWindow)windows.get(windows.size()-1));
current.setNext(current);
// Actually display the setup dialog.
createDialog((SetupWindow)windows.get(0));
}
/*
* Creates the main <tt>JDialog</tt> instance and
* creates all of the setup window classes, buttons, etc.
*/
private void createDialog(SetupWindow firstWindow) {
_dialog = new JDialog();
_dialog.setModal(true);
// JDialog sizing seems to work differently with some Unix
// systems, so we'll just make it resizable.
if(!CommonUtils.isUnix())
_dialog.setResizable(false);
_dialog.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
cancelSetup();
}
});
// set the layout of the content pane
Container container = _dialog.getContentPane();
BoxLayout containerLayout = new BoxLayout(container, BoxLayout.Y_AXIS);
container.setLayout(containerLayout);
// create the main panel
JPanel setupPanel = new JPanel();
BoxLayout layout = new BoxLayout(setupPanel, BoxLayout.Y_AXIS);
setupPanel.setLayout(layout);
// compare against a little bit less than the screen size,
// as the screen size includes the taskbar
Dimension d = new Dimension(SetupWindow.SETUP_WIDTH,
SetupWindow.SETUP_HEIGHT);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
_dialog.setLocation((screenSize.width-d.width)/2,
(screenSize.height-d.height)/2);
// create the setup buttons panel
_setupButtons = new SetupButtons(this);
setupPanel.add(_setupWindowHolder);
setupPanel.add(Box.createVerticalStrut(17));
setupPanel.add(_setupButtons);
show(firstWindow);
// add the panel and make it visible
container.add(setupPanel);
_dialog.pack();
_dialog.toFront();
SplashWindow.instance().toBack();
_dialog.setVisible(true);
}
/**
* Displays the next window in the setup sequence.
*/
public void next() {
SetupWindow newWindow = _currentWindow.getNext();
try {
_currentWindow.applySettings();
show(newWindow);
} catch(ApplySettingsException ase) {
// there was a problem applying the settings from
// the current window, so display the error message
// to the user.
GUIMediator.showError(ase.getMessage());
}
}
/**
* Displays the previous window in the setup sequence.
*/
public void previous() {
SetupWindow newWindow = _currentWindow.getPrevious();
show(newWindow);
}
/**
* Sets the array of scanned path names.
*/
public void scan() {
if(!_scanned) {
_scannedPaths = scanDrive();
_scanned = true;
}
}
/**
* Returns the array of potential directory paths to share
* based on the hard drive scan.
*
* @return the array of scanned directory paths containing
* potential files to share
*/
public String[] getScannedPaths() {
return _scannedPaths;
}
/**
* Cancels the setup.
*/
public void cancelSetup() {
_dialog.dispose();
System.exit(0);
}
/**
* Completes the setup.
*/
public void finishSetup() {
_dialog.dispose();
ApplicationSettings.INSTALLED.setValue(true);
InstallSettings.SAVE_DIRECTORY.setValue(true);
InstallSettings.SPEED.setValue(true);
InstallSettings.SCAN_FILES.setValue(true);
InstallSettings.LANGUAGE_CHOICE.setValue(true);
InstallSettings.FILTER_OPTION.setValue(true);
if(GUIUtils.shouldShowStartOnStartupWindow());
InstallSettings.START_STARTUP.setValue(true);
if(CommonUtils.isWindows())
InstallSettings.FIREWALL_WARNING.setValue(true);
SettingsHandler.save();
}
/**
* Instructs the buttons to redo their text.
*/
public void remakeButtons() {
_setupButtons.reconstruct(this);
}
/**
* Mediator method for changing the buttons in the setup button class
* to show the finish button.
*/
public void goToFinishButtons() {
_setupButtons.goToFinishButtons();
}
/**
* Mediator method for changing the buttons in the setup button class
* to show the cancel button.
*/
public void goToCancelButtons() {
_setupButtons.goToCancelButtons();
}
/**
* Mediator method for changing the buttons in the setup button class
* to show its standard buttons
*/
public void goToStandardButtons() {
_setupButtons.goToStandardButtons();
}
/**
* Mediator method for changing the buttons in the setup button class
* to show its next buttons.
*/
public void goToNextButtons() {
_setupButtons.goToNextButtons();
}
/**
* Show the specified window
*/
private void show(SetupWindow window) {
window.handleWindowOpeningEvent();
_setupWindowHolder.show(window.getKey());
_dialog.setTitle(window.getName());
_currentWindow = window;
}
/**
* Scans the user's hard drive for media files, and returns,
* at most, the top 5 directories as an array of Strings.
*
* @return the array of pathname <tt>String</tt>s of the directories
* containing media files
*/
private String[] scanDrive() {
FileScan fs = new FileScan();
String[] filters = {
"Recycle","Incomplete","LimeWire","Microsoft", "bin",
"system","WINNT"
};
fs.setFilters(filters);
// get the root directory of the current directory.
// scan that directory for files.
File root = getRoot(CommonUtils.getCurrentDirectory());
try {
fs.scan( root.getCanonicalPath() );
} catch(IOException ioe) {
}
return fs.getListAsArray();
}
/**
* Recursively travels up the path pf the file until it finds
* the root directory.
*
* @return the <tt>File</tt> instance denoting the abstract pathname
* of the root directory
*/
private File getRoot(File f) {
String parent;
parent = f.getParent();
if (parent == null)
return f;
else
return getRoot( new File(parent) );
}
}