/*
* 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.preferences;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
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.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
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;
/**
* @author Vincent Wiencek <vwiencek@gmail.com>
* @author Philipp C. Heckel <philipp.heckel@gmail.com>
*/
public class PreferencesDialog extends Dialog {
private static final String NAV_ICON_RESOURCE_FORMAT = "/" + PreferencesDialog.class.getPackage().getName().replace('.', '/') + "/nav-%s.png";
private enum NavSelection {
GENERAL, PLUGINS, NETWORK, ABOUT
}
private Shell trayShell;
private Shell windowShell;
private Composite stackComposite;
private StackLayout stackLayout;
private Table navTable;
private GeneralPanel generalPanel;
private PluginsPanel pluginsPanel;
private NetworkPanel networkPanel;
private AboutPanel aboutPanel;
private Panel currentPanel;
public static void main(String[] a) {
Logging.init();
String intlPackage = I18n.class.getPackage().getName().replace(".", "/");
I18n.registerBundleName(intlPackage + "/i18n/messages");
Shell shell = new Shell();
PreferencesDialog dialog = new PreferencesDialog(shell);
dialog.open();
shell.dispose();
}
public PreferencesDialog(Shell trayShell) {
this.trayShell = trayShell;
}
public void open() {
// Create controls
createContents();
buildPanels();
setCurrentPanel(generalPanel);
// 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 = 0;
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 | SWT.DOUBLE_BUFFERED);
windowShell.setToolTipText("");
windowShell.setBackground(WidgetDecorator.COLOR_WIDGET);
windowShell.setSize(640, 480);
windowShell.setText(I18n.getText("org.syncany.gui.preferences.PreferencesDialog.title"));
windowShell.setLayout(shellGridLayout);
windowShell.addListener(SWT.Close, new Listener() {
public void handleEvent(Event event) {
safeDispose();
}
});
// Navigation table (row 1, column 1) and stack composite (row 1, column 2)
createNavTable();
createStackComposite();
// Button composite (row 2, column 1+2)
createButtonComposite();
}
private void createNavTable() {
GridData navTableGridData = new GridData(SWT.LEFT, SWT.FILL, true, true);
navTableGridData.verticalIndent = 0;
navTableGridData.horizontalIndent = 0;
navTableGridData.minimumWidth = 120;
navTable = new Table(windowShell, SWT.SINGLE | SWT.FULL_SELECTION);
navTable.setHeaderVisible(false);
navTable.setBackground(WidgetDecorator.WHITE);
navTable.setLayoutData(navTableGridData);
navTable.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
if (navTable.getSelectionIndex() >= 0) {
TableItem tableItem = navTable.getItem(navTable.getSelectionIndex());
NavSelection panelSelection = (NavSelection) tableItem.getData();
switch (panelSelection) {
case GENERAL:
setCurrentPanel(generalPanel);
break;
case PLUGINS:
setCurrentPanel(pluginsPanel);
break;
case NETWORK:
setCurrentPanel(networkPanel);
break;
case ABOUT:
setCurrentPanel(aboutPanel);
break;
}
}
}
});
navTable.addListener(SWT.MeasureItem, new Listener() {
public void handleEvent(Event event) {
event.height = 30; // Row height workaround
}
});
TableColumn navTableColumnEmpty = new TableColumn(navTable, SWT.CENTER);
navTableColumnEmpty.setWidth(5);
TableColumn navTableColumnImage = new TableColumn(navTable, SWT.CENTER);
navTableColumnImage.setWidth(30);
TableColumn navTableColumnText = new TableColumn(navTable, SWT.LEFT);
navTableColumnText.setWidth(85);
// Entry 'General'
String navGeneralImageResource = String.format(NAV_ICON_RESOURCE_FORMAT, "general");
Image navGeneralImage = SWTResourceManager.getImage(navGeneralImageResource);
TableItem navGeneralTableItem = new TableItem(navTable, SWT.NONE);
navGeneralTableItem.setImage(1, navGeneralImage);
navGeneralTableItem.setText(2, I18n.getText("org.syncany.gui.preferences.PreferencesDialog.nav.general"));
navGeneralTableItem.setData(NavSelection.GENERAL);
// Entry 'Plugins'
String navPluginsImageResource = String.format(NAV_ICON_RESOURCE_FORMAT, "plugins");
Image navPluginsImage = SWTResourceManager.getImage(navPluginsImageResource);
TableItem navPluginsTableItem = new TableItem(navTable, SWT.NONE);
navPluginsTableItem.setImage(1, navPluginsImage);
navPluginsTableItem.setText(2, I18n.getText("org.syncany.gui.preferences.PreferencesDialog.nav.plugins"));
navPluginsTableItem.setData(NavSelection.PLUGINS);
// Entry 'Network'
String navNetworkImageResource = String.format(NAV_ICON_RESOURCE_FORMAT, "network");
Image navNetworkImage = SWTResourceManager.getImage(navNetworkImageResource);
TableItem navNetworkTableItem = new TableItem(navTable, SWT.NONE);
navNetworkTableItem.setImage(1, navNetworkImage);
navNetworkTableItem.setText(2, I18n.getText("org.syncany.gui.preferences.PreferencesDialog.nav.network"));
navNetworkTableItem.setData(NavSelection.NETWORK);
// Entry 'About'
String navAboutImageResource = String.format(NAV_ICON_RESOURCE_FORMAT, "about");
Image navAboutImage = SWTResourceManager.getImage(navAboutImageResource);
TableItem navAboutTableItem = new TableItem(navTable, SWT.NONE);
navAboutTableItem.setImage(1, navAboutImage);
navAboutTableItem.setText(2, I18n.getText("org.syncany.gui.preferences.PreferencesDialog.nav.about"));
navAboutTableItem.setData(NavSelection.ABOUT);
// Select 'General'
navTable.select(0);
}
private void createStackComposite() {
stackLayout = new StackLayout();
stackLayout.marginHeight = 0;
stackLayout.marginWidth = 0;
GridData stackCompositeGridData = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1);
stackCompositeGridData.minimumWidth = 500;
stackComposite = new Composite(windowShell, SWT.DOUBLE_BUFFERED);
stackComposite.setLayout(stackLayout);
stackComposite.setLayoutData(stackCompositeGridData);
// 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);
}
private void createButtonComposite() {
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
Button closeButton = new Button(buttonComposite, SWT.NONE);
closeButton.setLayoutData(new RowData(WidgetDecorator.DEFAULT_BUTTON_WIDTH, WidgetDecorator.DEFAULT_BUTTON_HEIGHT));
closeButton.setText(I18n.getText("org.syncany.gui.preferences.PreferencesDialog.button.close"));
closeButton.addListener(SWT.Selection, new Listener() {
@Override
public void handleEvent(Event event) {
safeDispose();
}
});
windowShell.setDefaultButton(closeButton);
WidgetDecorator.normal(closeButton);
}
private void buildPanels() {
generalPanel = new GeneralPanel(this, stackComposite, SWT.NONE);
pluginsPanel = new PluginsPanel(this, stackComposite, SWT.NONE);
networkPanel = new NetworkPanel(this, stackComposite, SWT.NONE);
aboutPanel = new AboutPanel(this, stackComposite, SWT.NONE);
}
public Panel getCurrentPanel() {
return currentPanel;
}
public Shell getTrayShell() {
return trayShell;
}
public Shell getWindowShell() {
return windowShell;
}
public void setCurrentPanel(final Panel newPanel) {
Display.getDefault().syncExec(new Runnable() {
@Override
public void run() {
currentPanel = newPanel;
stackLayout.topControl = currentPanel;
stackComposite.layout();
currentPanel.setFocus();
}
});
}
public void safeDispose() {
Display.getDefault().syncExec(new Runnable() {
@Override
public void run() {
if (!generalPanel.isDisposed()) {
generalPanel.dispose();
}
if (!pluginsPanel.isDisposed()) {
pluginsPanel.dispose();
}
if (!windowShell.isDisposed()) {
windowShell.dispose();
}
}
});
}
}