/* * Syncany, www.syncany.org * Copyright (C) 2011-2013 Philipp C. Heckel <philipp.heckel@gmail.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.syncany.gui.wizard; import java.util.ArrayList; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StackLayout; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.RowData; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.syncany.config.GuiEventBus; import org.syncany.config.Logging; import org.syncany.gui.Dialog; import org.syncany.gui.Panel; import org.syncany.gui.util.DesktopUtil; import org.syncany.gui.util.I18n; import org.syncany.gui.util.SWTResourceManager; import org.syncany.gui.util.WidgetDecorator; import org.syncany.gui.wizard.StartPanel.StartPanelSelection; import com.google.common.collect.Lists; /** * @author Vincent Wiencek <vwiencek@gmail.com> * @author Philipp C. Heckel <philipp.heckel@gmail.com> */ public class WizardDialog extends Dialog { public enum Action { PREVIOUS, NEXT, FINISH }; private Shell trayShell; private Shell windowShell; private Composite stackComposite; private StackLayout stackLayout; private StartPanel startPanel; private FolderSelectPanel folderSelectPanel; private PluginSelectPanel pluginSelectPanel; private ConnectTypeSelectPanel connectTypeSelectPanel; private PluginSettingsPanel pluginSettingsPanel; private ChoosePasswordPanel choosePasswordPanel; private EnterPasswordPanel enterPasswordPanel; private ProgressPanel progressPanel; private InitSuccessPanel initSuccessPanel; private Panel currentPanel; private PanelController panelController; private Button cancelButton; private Button nextButton; private Button previousButton; private GuiEventBus eventBus; public static void main(String[] a) { Logging.init(); String intlPackage = I18n.class.getPackage().getName().replace(".", "/"); I18n.registerBundleName(intlPackage + "/i18n/messages"); Shell shell = new Shell(); WizardDialog wizardDialog = new WizardDialog(shell); wizardDialog.open(); shell.dispose(); } public WizardDialog(Shell trayShell) { this.trayShell = trayShell; this.eventBus = GuiEventBus.getInstance(); this.eventBus.register(this); } public void open() { // Create controls createContents(); buildPanels(); setCurrentPanel(startPanel, Action.NEXT); // Open shell DesktopUtil.centerOnScreen(windowShell); windowShell.open(); windowShell.layout(); // Dispatch loop Display display = Display.getDefault(); while (!windowShell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } } /** * Create contents of the dialog. */ private void createContents() { GridLayout shellGridLayout = new GridLayout(2, false); shellGridLayout.marginTop = 0; shellGridLayout.marginLeft = -2; shellGridLayout.marginHeight = 0; shellGridLayout.marginWidth = 0; shellGridLayout.horizontalSpacing = 0; shellGridLayout.verticalSpacing = 0; shellGridLayout.numColumns = 2; windowShell = new Shell(trayShell, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL); windowShell.setToolTipText(""); windowShell.setBackground(WidgetDecorator.COLOR_WIDGET); windowShell.setSize(640, 480); windowShell.setText(I18n.getText("org.syncany.gui.wizard.WizardDialog.title")); windowShell.setLayout(shellGridLayout); // Row 1, Column 1: Image String leftImageResource = "/" + WizardDialog.class.getPackage().getName().replace(".", "/") + "/wizard-left.png"; Image leftImage = SWTResourceManager.getImage(leftImageResource); Label leftImageLabel = new Label(windowShell, SWT.NONE); leftImageLabel.setLayoutData(new GridData(SWT.LEFT, SWT.FILL, false, true, 1, 2)); leftImageLabel.setImage(leftImage); // Row 1, Column 2: Panel stackLayout = new StackLayout(); stackLayout.marginHeight = 0; stackLayout.marginWidth = 0; stackComposite = new Composite(windowShell, SWT.NONE); stackComposite.setLayout(stackLayout); stackComposite.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true, 1, 1)); // Row 2, Column 1+2: Line GridData horizontalLineGridData = new GridData(GridData.FILL_HORIZONTAL); horizontalLineGridData.horizontalSpan = 2; Label horizontalLine = new Label(windowShell, SWT.SEPARATOR | SWT.HORIZONTAL); horizontalLine.setLayoutData(horizontalLineGridData); // Row 3: Column 1+2: Button Composite RowLayout buttonCompositeRowLayout = new RowLayout(SWT.HORIZONTAL); buttonCompositeRowLayout.marginTop = 15; buttonCompositeRowLayout.marginBottom = 15; buttonCompositeRowLayout.marginRight = 20; GridData buttonCompositeGridData = new GridData(SWT.RIGHT, SWT.FILL, false, false); buttonCompositeGridData.horizontalSpan = 2; buttonCompositeGridData.verticalSpan = 1; Composite buttonComposite = new Composite(windowShell, SWT.NONE); buttonComposite.setLayout(buttonCompositeRowLayout); buttonComposite.setLayoutData(buttonCompositeGridData); buttonComposite.setBackground(WidgetDecorator.COLOR_WIDGET); // Buttons previousButton = new Button(buttonComposite, SWT.NONE); previousButton.setLayoutData(new RowData(WidgetDecorator.DEFAULT_BUTTON_WIDTH, WidgetDecorator.DEFAULT_BUTTON_HEIGHT)); previousButton.setText(I18n.getText("org.syncany.gui.wizard.WizardDialog.button.previous")); previousButton.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { handleFlow(Action.PREVIOUS); } }); nextButton = new Button(buttonComposite, SWT.NONE); nextButton.setLayoutData(new RowData(WidgetDecorator.DEFAULT_BUTTON_WIDTH, WidgetDecorator.DEFAULT_BUTTON_HEIGHT)); nextButton.setText(I18n.getText("org.syncany.gui.wizard.WizardDialog.button.next")); nextButton.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { handleFlow(Action.NEXT); } }); Label spacingLabel = new Label(buttonComposite, SWT.NONE); spacingLabel.setText(" "); cancelButton = new Button(buttonComposite, SWT.NONE); cancelButton.setLayoutData(new RowData(WidgetDecorator.DEFAULT_BUTTON_WIDTH, WidgetDecorator.DEFAULT_BUTTON_HEIGHT)); cancelButton.setText(I18n.getText("org.syncany.gui.wizard.WizardDialog.button.cancel")); cancelButton.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { safeDispose(); } }); windowShell.setDefaultButton(nextButton); windowShell.addListener(SWT.Close, new Listener() { public void handleEvent(Event event) { safeDispose(); } }); WidgetDecorator.normal(nextButton, previousButton, cancelButton); } private void buildPanels() { startPanel = new StartPanel(this, stackComposite, SWT.NONE); folderSelectPanel = new FolderSelectPanel(this, stackComposite, SWT.NONE); pluginSelectPanel = new PluginSelectPanel(this, stackComposite, SWT.NONE); connectTypeSelectPanel = new ConnectTypeSelectPanel(this, stackComposite, SWT.NONE); pluginSettingsPanel = new PluginSettingsPanel(this, stackComposite, SWT.NONE); choosePasswordPanel = new ChoosePasswordPanel(this, stackComposite, SWT.NONE); enterPasswordPanel = new EnterPasswordPanel(this, stackComposite, SWT.NONE); progressPanel = new ProgressPanel(this, stackComposite, SWT.NONE); initSuccessPanel = new InitSuccessPanel(this, stackComposite, SWT.NONE); } private void handleFlow(Action clickAction) { if (stackLayout.topControl == startPanel) { if (panelController != null) { panelController.dispose(); } panelController = createPanelController(startPanel.getSelection()); } if (panelController != null) { panelController.handleFlow(clickAction); } } private PanelController createPanelController(StartPanelSelection startPanelSelection) { switch (startPanelSelection) { case ADD_EXISTING: return new AddExistingPanelController(this, startPanel, folderSelectPanel, progressPanel); case INIT: return new InitPanelController(this, startPanel, folderSelectPanel, pluginSelectPanel, pluginSettingsPanel, choosePasswordPanel, progressPanel, initSuccessPanel); case CONNECT: return new ConnectPanelController(this, startPanel, folderSelectPanel, connectTypeSelectPanel, pluginSettingsPanel, enterPasswordPanel, progressPanel); default: return null; } } public Panel getCurrentPanel() { return currentPanel; } public Shell getTrayShell() { return trayShell; } public Shell getWindowShell() { return windowShell; } public void setCurrentPanel(final Panel newPanel, final Action... allowedActions) { Display.getDefault().syncExec(new Runnable() { @Override public void run() { // Set current panel currentPanel = newPanel; stackLayout.topControl = currentPanel; stackComposite.layout(); currentPanel.setFocus(); // Toggle buttons setAllowedActions(allowedActions); } }); } public void setAllowedActions(final Action... allowedActions) { Display.getDefault().asyncExec(new Runnable() { @Override public void run() { ArrayList<Action> allowedActionsList = Lists.newArrayList(allowedActions); if (!nextButton.isDisposed()) { nextButton.setEnabled(allowedActionsList.contains(Action.NEXT)); } if (!previousButton.isDisposed()) { previousButton.setEnabled(allowedActionsList.contains(Action.PREVIOUS)); } if (allowedActionsList.contains(Action.FINISH)) { if (!windowShell.isDisposed()) { windowShell.setDefaultButton(cancelButton); } if (!cancelButton.isDisposed()) { cancelButton.setText(I18n.getText("org.syncany.gui.wizard.WizardDialog.button.finish")); } } else { if (!cancelButton.isDisposed()) { cancelButton.setText(I18n.getText("org.syncany.gui.wizard.WizardDialog.button.cancel")); } } } }); } public boolean validateAndSetCurrentPanel(Panel panel, Action... allowedActions) { boolean currentPanelValid = currentPanel == null || currentPanel.validatePanel(); if (currentPanelValid) { setCurrentPanel(panel, allowedActions); return true; } else { return false; } } public void safeDispose() { Display.getDefault().syncExec(new Runnable() { @Override public void run() { if (panelController != null) { panelController.dispose(); } if (!windowShell.isDisposed()) { windowShell.dispose(); } Panel[] panels = new Panel[] { startPanel, folderSelectPanel, pluginSelectPanel, connectTypeSelectPanel, pluginSettingsPanel, choosePasswordPanel, enterPasswordPanel, progressPanel, initSuccessPanel }; for (Panel panel : panels) { if (!panel.isDisposed()) { panel.dispose(); } } } }); } }