Java tutorial
/******************************************************************************* * Copyright (c) 2011 - 2013 by Timotei Dolean <timotei21@gmail.com> * * This program and the accompanying materials are made available * under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ package org.wesnoth.preferences; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jface.preference.DirectoryFieldEditor; import org.eclipse.jface.preference.FileFieldEditor; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.StringFieldEditor; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.VerifyEvent; import org.eclipse.swt.events.VerifyListener; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.Text; import org.eclipse.xtext.ui.editor.preferences.fields.LabelFieldEditor; import org.wesnoth.Constants; import org.wesnoth.Messages; import org.wesnoth.WesnothPlugin; import org.wesnoth.installs.WesnothInstall; import org.wesnoth.installs.WesnothInstallsUtils; import org.wesnoth.templates.ReplaceableParameter; import org.wesnoth.templates.TemplateProvider; import org.wesnoth.utils.GUIUtils; import org.wesnoth.utils.StringUtils; /** * Preference page that manages the Wesnoth installs */ public class WesnothInstallsPage extends AbstractPreferencePage { private Text txtInstallName_; private Combo cmbVersion_; private Map<String, WesnothInstall> installs_; private Table installsTable_; private TableViewer installsTableViewer_; private DirectoryFieldEditor wmlToolsField_; private DirectoryFieldEditor wesnothWorkingDirField_; private DirectoryFieldEditor wesnothUserDirField_; private FileFieldEditor wesnothExecutableField_; private static List<String> wmlToolsList_; private static String[] wesnothExecutablePaths_; private static String[] wesnothDataDirPaths_; private static String[] wesnothUserDirPaths_; private Composite parentComposite_; static { wmlToolsList_ = new ArrayList<String>(); wmlToolsList_.add("wmllint"); //$NON-NLS-1$ wmlToolsList_.add("wmlindent"); //$NON-NLS-1$ wmlToolsList_.add("wmlscope"); //$NON-NLS-1$ wmlToolsList_.add("wesnoth_addon_manager"); //$NON-NLS-1$ String os = "linux"; //$NON-NLS-1$ if (Constants.IS_MAC_MACHINE) { os = "mac"; //$NON-NLS-1$ } else if (Constants.IS_WINDOWS_MACHINE) { os = "windows"; //$NON-NLS-1$ } List<ReplaceableParameter> params = new ArrayList<ReplaceableParameter>(); params.add(new ReplaceableParameter("$$home_path", System.getProperty("user.home"))); //$NON-NLS-1$ //$NON-NLS-2$ wesnothExecutablePaths_ = StringUtils .getLines(TemplateProvider.getInstance().getProcessedTemplate(os + "_exec", params)); //$NON-NLS-1$ wesnothDataDirPaths_ = StringUtils .getLines(TemplateProvider.getInstance().getProcessedTemplate(os + "_data", params)); //$NON-NLS-1$ wesnothUserDirPaths_ = StringUtils .getLines(TemplateProvider.getInstance().getProcessedTemplate(os + "_user", params)); //$NON-NLS-1$ } /** * Creates a grid-style {@link WesnothInstallPage} */ public WesnothInstallsPage() { super(GRID); setPreferenceStore(WesnothPlugin.getDefault().getPreferenceStore()); setTitle(Messages.WesnothInstallsPage_0); installs_ = new HashMap<String, WesnothInstall>(); List<WesnothInstall> installs = WesnothInstallsUtils.getInstalls(); for (WesnothInstall wesnothInstall : installs) { installs_.put(wesnothInstall.getName(), wesnothInstall); } setValid(true); } @Override protected void createFieldEditors() { ModifyListener modifyListener = new ModifyListener() { @Override public void modifyText(ModifyEvent e) { guessDefaultPaths(); } }; wesnothExecutableField_ = new FileFieldEditor("", //$NON-NLS-1$ Messages.WesnothPreferencesPage_5, getFieldEditorParent()); wesnothExecutableField_.getTextControl(getFieldEditorParent()).addFocusListener(new FocusListener() { @Override public void focusLost(FocusEvent e) { guessDefaultPaths(); } @Override public void focusGained(FocusEvent e) { } }); wesnothExecutableField_.getTextControl(getFieldEditorParent()).addModifyListener(modifyListener); addField(wesnothExecutableField_, Messages.WesnothPreferencesPage_6); wesnothWorkingDirField_ = new DirectoryFieldEditor("", //$NON-NLS-1$ Messages.WesnothPreferencesPage_7, getFieldEditorParent()); wesnothWorkingDirField_.getTextControl(getFieldEditorParent()).addModifyListener(modifyListener); addField(wesnothWorkingDirField_, Messages.WesnothPreferencesPage_8); wesnothUserDirField_ = new DirectoryFieldEditor("", //$NON-NLS-1$ Messages.WesnothPreferencesPage_9, getFieldEditorParent()); addField(wesnothUserDirField_, Messages.WesnothPreferencesPage_10); wmlToolsField_ = new DirectoryFieldEditor("", //$NON-NLS-1$ Messages.WesnothPreferencesPage_11, getFieldEditorParent()); addField(wmlToolsField_, Messages.WesnothPreferencesPage_12); addField(new FileFieldEditor(Preferences.PYTHON_PATH, Messages.WesnothPreferencesPage_13, getFieldEditorParent())); addField(new LabelFieldEditor(Messages.WesnothPreferencesPage_14, getFieldEditorParent())); // update the default updateInterface(installs_.get(Preferences.getDefaultInstallName())); guessDefaultPaths(); } @Override protected Control createContents(Composite parent) { Composite installComposite = new Composite(parent, 0); installComposite.setLayout(new GridLayout(2, false)); installComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); // create install manager installsTableViewer_ = new TableViewer(installComposite, SWT.BORDER | SWT.FULL_SELECTION); installsTable_ = installsTableViewer_.getTable(); installsTable_.addMouseListener(new MouseAdapter() { @Override public void mouseDown(MouseEvent e) { updateInterface(getSelectedInstall()); } }); installsTable_.setHeaderVisible(true); installsTable_.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); TableColumn tblclmnName = new TableColumn(installsTable_, SWT.NONE); tblclmnName.setWidth(150); tblclmnName.setText(Messages.WesnothInstallsPage_5); TableColumn tblclmnWesnothVersion = new TableColumn(installsTable_, SWT.NONE); tblclmnWesnothVersion.setWidth(70); tblclmnWesnothVersion.setText(Messages.WesnothInstallsPage_6); TableColumn tblclmnIsDefault = new TableColumn(installsTable_, SWT.NONE); tblclmnIsDefault.setWidth(70); tblclmnIsDefault.setText(Messages.WesnothInstallsPage_7); installsTableViewer_.setContentProvider(new ArrayContentProvider()); installsTableViewer_.setLabelProvider(new TableLabelProvider()); installsTableViewer_.setInput(installs_.values()); Composite composite = new Composite(installComposite, SWT.NONE); FillLayout fl_composite = new FillLayout(SWT.VERTICAL); fl_composite.spacing = 10; fl_composite.marginHeight = 10; composite.setLayout(fl_composite); GridData gd_composite = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1); gd_composite.widthHint = 80; composite.setLayoutData(gd_composite); Button btnNew = new Button(composite, SWT.NONE); btnNew.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { newInstall(); } }); btnNew.setText(Messages.WesnothInstallsPage_8); Button btnRemove = new Button(composite, SWT.NONE); btnRemove.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { removeInstall(getSelectedInstall()); } }); btnRemove.setText(Messages.WesnothInstallsPage_9); Button btnSetAsDefault = new Button(composite, SWT.NONE); btnSetAsDefault.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { setInstallAsDefault(getSelectedInstall()); } }); btnSetAsDefault.setText(Messages.WesnothInstallsPage_10); Label lblInstallName = new Label(parent, SWT.NONE); lblInstallName.setText(Messages.WesnothInstallsPage_11); txtInstallName_ = new Text(parent, SWT.SINGLE); txtInstallName_.setText(Messages.WesnothInstallsPage_12); txtInstallName_.setEditable(false); txtInstallName_.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1)); txtInstallName_.addVerifyListener(new VerifyListener() { private boolean isCharOk(char character) { return (character >= 'a' && character <= 'z') || (character >= 'A' && character <= 'Z') || (character >= '0' && character <= '9'); } @Override public void verifyText(VerifyEvent e) { if (e.character == 0) { // we got a text copied. Check for invalid chars. for (int index = e.text.length() - 1; index >= 0; --index) { if (isCharOk(e.text.charAt(index)) == false) { e.doit = false; break; } } } else { e.doit = isCharOk(e.character) || e.keyCode == SWT.BS || e.keyCode == SWT.ARROW_LEFT || e.keyCode == SWT.ARROW_RIGHT || e.keyCode == SWT.DEL; } } }); Label lblVersion = new Label(parent, SWT.NONE); lblVersion.setText(Messages.WesnothInstallsPage_13); cmbVersion_ = new Combo(parent, SWT.READ_ONLY); cmbVersion_.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); cmbVersion_.add("1.9.x"); //$NON-NLS-1$ cmbVersion_.add("1.10.x"); //$NON-NLS-1$ cmbVersion_.add("trunk"); //$NON-NLS-1$ cmbVersion_.select(0); // create fields parentComposite_ = (Composite) super.createContents(parent); // Fixes the path to the Wesnoth executable on the Mac OS X systems IPropertyChangeListener macApplicationPathCorrecter = new IPropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent event) { if (event.getProperty() != FileFieldEditor.VALUE || !Constants.IS_MAC_MACHINE) { return; } String newPath = (String) event.getNewValue(); if (newPath.replace("/", "").endsWith(".app")) { wesnothExecutableField_.setStringValue(newPath + "/Contents/MacOS/Wesnoth"); } } }; wesnothExecutableField_.setPropertyChangeListener(macApplicationPathCorrecter); return parentComposite_; } protected void newInstall() { updateInterface(null); } protected void setInstallAsDefault(WesnothInstall install) { if (install != null) { Preferences.setDefaultInstallName(install.getName()); installsTableViewer_.refresh(); } } protected void removeInstall(WesnothInstall install) { if (install != null) { installs_.remove(install.getName()); installsTableViewer_.refresh(); // unset all settings. IPreferenceStore prefs = Preferences.getPreferences(); String installPrefix = Preferences.getInstallPrefix(install.getName()); prefs.setToDefault(installPrefix + Preferences.WESNOTH_EXEC_PATH); prefs.setToDefault(installPrefix + Preferences.WESNOTH_USER_DIR); prefs.setToDefault(installPrefix + Preferences.WESNOTH_WMLTOOLS_DIR); prefs.setToDefault(installPrefix + Preferences.WESNOTH_WORKING_DIR); // unset the default install if this was that // and select another one (the first) - if any - as default if (install.getName().equals(Preferences.getDefaultInstallName())) { Preferences.setDefaultInstallName(""); //$NON-NLS-1$ if (!installs_.isEmpty()) { // get the first item from the iterator Iterator<WesnothInstall> itor = installs_.values().iterator(); setInstallAsDefault(itor.next()); } } // clear the current info newInstall(); } } private WesnothInstall getSelectedInstall() { if (installsTable_.getSelectionIndex() == -1) { return null; } return installs_.get(installsTable_.getSelection()[0].getText(0)); } /** * Updates the interface with the specified install * * @param install * The install */ private void updateInterface(WesnothInstall install) { txtInstallName_.setText(install == null ? "" : install.getName()); //$NON-NLS-1$ txtInstallName_.setEditable(install == null ? true : false); cmbVersion_.setText(install == null ? "" : install.getVersion()); //$NON-NLS-1$ setFieldsPreferenceName(install == null ? "" : Preferences.getInstallPrefix(install.getName()), //$NON-NLS-1$ true); } /** * Sets the fields's internal preference name based on the installPrefix * * @param installPrefix * The install prefix * @param loadPreferences * True to load the current stored preference */ private void setFieldsPreferenceName(String installPrefix, boolean loadPreferences) { wesnothExecutableField_.setPreferenceName(installPrefix + Preferences.WESNOTH_EXEC_PATH); wesnothUserDirField_.setPreferenceName(installPrefix + Preferences.WESNOTH_USER_DIR); wesnothWorkingDirField_.setPreferenceName(installPrefix + Preferences.WESNOTH_WORKING_DIR); wmlToolsField_.setPreferenceName(installPrefix + Preferences.WESNOTH_WMLTOOLS_DIR); if (loadPreferences) { wesnothUserDirField_.setStringValue(""); //$NON-NLS-1$ wesnothWorkingDirField_.setStringValue(""); //$NON-NLS-1$ wesnothExecutableField_.setStringValue(""); //$NON-NLS-1$ wmlToolsField_.setStringValue(""); //$NON-NLS-1$ wesnothUserDirField_.load(); wesnothWorkingDirField_.load(); wesnothExecutableField_.load(); wmlToolsField_.load(); } } /** * Tries the list of available paths for current os */ private void guessDefaultPaths() { testAndSetPaths(wesnothExecutablePaths_, wesnothExecutableField_); testAndSetPaths(wesnothDataDirPaths_, wesnothWorkingDirField_); testAndSetPaths(wesnothUserDirPaths_, wesnothUserDirField_); // guess the working dir based on the executable's path Text textControl = wesnothWorkingDirField_.getTextControl(getFieldEditorParent()); String workingDirValue = wesnothWorkingDirField_.getStringValue(); String wesnothExecValue = wesnothExecutableField_.getStringValue(); IPath guessedWorkingDir = new Path(wesnothExecValue); // remove the filename guessedWorkingDir = guessedWorkingDir.removeLastSegments(1); // The working dir should contain the data directory guessedWorkingDir = guessedWorkingDir.append("/data/"); if (workingDirValue.isEmpty() && !wesnothExecValue.isEmpty() && new File(guessedWorkingDir.toOSString()).exists()) { workingDirValue = guessedWorkingDir.removeLastSegments(1).toOSString(); // don't retain the /data/ directory textControl.setText(workingDirValue); } // guess the wmltools path if (wmlToolsField_.getStringValue().isEmpty() && !workingDirValue.isEmpty()) { String path = workingDirValue + "/data/tools"; //$NON-NLS-1$ if (testWMLToolsPath(path)) { wmlToolsField_.setStringValue(path); } } String userDirValue = wesnothUserDirField_.getStringValue(); // guess the userdata path if (userDirValue.isEmpty() && !workingDirValue.isEmpty()) { String path = workingDirValue + "/userdata"; //$NON-NLS-1$ testAndSetPaths(new String[] { path }, wesnothUserDirField_); } } /** * Tests for wmltools in the specified path * * @param path * @return */ private boolean testWMLToolsPath(String path) { for (String tool : wmlToolsList_) { if (!(new File(path + IPath.SEPARATOR + tool).exists())) { setErrorMessage(String.format(Messages.WesnothPreferencesPage_24, tool)); return false; } } return true; } /** * Tests the list of paths and if any path exists it will * set it as the string value to the field editor * if the field editor value is empty * * @param list * The list to search in * @param field * The field to put the path in */ private void testAndSetPaths(String[] list, StringFieldEditor field) { if (!(field.getStringValue().isEmpty())) { return; } for (String path : list) { if (new File(path).exists()) { field.setStringValue(path); return; } } } /** * Checks whether the fields are empty (contain no text) * and the combobox/name don't have any values also * (the user doesn't create a new install) * * @return */ private boolean isFieldsEmpty() { return wmlToolsField_.getStringValue().isEmpty() && wesnothExecutableField_.getStringValue().isEmpty() && wesnothUserDirField_.getStringValue().isEmpty() && wesnothWorkingDirField_.getStringValue().isEmpty() && txtInstallName_.getText().isEmpty(); } /** * Saves the current install * * @return true if the save was successfully, false otherwise */ private boolean saveInstall() { String installName = txtInstallName_.getText(); // if it's editable, it means we are creating a new install if (txtInstallName_.getEditable()) { boolean isFieldsEmpty = isFieldsEmpty(); if (installName.isEmpty() == true) { // if we haven't completed anything, // we can skip the saving without alerting the user. if (!isFieldsEmpty) { GUIUtils.showErrorMessageBox(Messages.WesnothInstallsPage_19); } // we consider successfully save if the fields are all // empty return isFieldsEmpty; } if (cmbVersion_.getText().isEmpty() == true) { GUIUtils.showErrorMessageBox(Messages.WesnothInstallsPage_20); return false; } // update the fields preferences names setFieldsPreferenceName(Preferences.getInstallPrefix(installName), false); WesnothInstall newInstall = new WesnothInstall(installName, cmbVersion_.getText()); installs_.put(installName, newInstall); // if there is not any install set as default, set this one if (Preferences.getDefaultInstallName().isEmpty()) { setInstallAsDefault(newInstall); } // we are creating a new install. Clear the editable // flag after we save it, to prevent renaming. txtInstallName_.setEditable(false); } else if (getSelectedInstall() != null) { // just saving // the fields are automatically saved by Eclipse. // we just need to save the new version. getSelectedInstall().setVersion(cmbVersion_.getText()); } installsTableViewer_.refresh(); return true; } /** * This method will unset invalid properties's values, * and saving only valid ones. */ private boolean savePreferences() { if (!wesnothExecutableField_.isValid()) { wesnothExecutableField_.setStringValue(""); //$NON-NLS-1$ } if (!wesnothUserDirField_.isValid()) { wesnothUserDirField_.setStringValue(""); //$NON-NLS-1$ } if (!wesnothWorkingDirField_.isValid()) { wesnothWorkingDirField_.setStringValue(""); //$NON-NLS-1$ } if (!wmlToolsField_.isValid()) { wmlToolsField_.setStringValue(""); //$NON-NLS-1$ } if (saveInstall() == false) { return false; } WesnothInstallsUtils.setInstalls(installs_.values()); return true; } @Override public boolean performOk() { return savePreferences() && super.performOk(); } @Override protected void checkState() { super.checkState(); // we won't stop the user saving wrong values. setValid(true); } private static class TableLabelProvider extends LabelProvider implements ITableLabelProvider { @Override public Image getColumnImage(Object element, int columnIndex) { return null; } @Override public String getColumnText(Object element, int columnIndex) { if (element instanceof WesnothInstall) { WesnothInstall install = (WesnothInstall) element; if (columnIndex == 0) { // name return install.getName(); } else if (columnIndex == 1) { // version return install.getVersion(); } else if (columnIndex == 2) { // is Default ? if (install.getName().equals(Preferences.getDefaultInstallName())) { return Messages.WesnothInstallsPage_21; } return ""; //$NON-NLS-1$ } } return ""; //$NON-NLS-1$ } } }