/*
* $Id$
*
* Copyright (c) 2004-2005 by the TeXlapse Team.
* All rights reserved. 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 net.sourceforge.texlipse.wizards;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Arrays;
import java.util.Locale;
import net.sourceforge.texlipse.TexlipsePlugin;
import net.sourceforge.texlipse.builder.BuilderChooser;
import net.sourceforge.texlipse.properties.TexlipseProperties;
import net.sourceforge.texlipse.templates.ProjectTemplateManager;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.fieldassist.AutoCompleteField;
import org.eclipse.jface.fieldassist.TextContentAdapter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Text;
/**
* Prefs-page on the project creation wizard.
*
* @author kpkarlss
*/
public class TexlipseProjectCreationWizardPage extends TexlipseWizardPage {
// textfield for project name
private Text projectNameField;
// project location, if not in workspace
private Text projectLocationField;
// textfield for language
private Text languageField;
// textfield for template preview
private Text descriptionField;
// template chooser
private List templateList;
// template type (system/user)
private Label typeLabel;
// output format / build order chooser
private BuilderChooser outputChooser;
private String workspacePath;
/**
*
* @param attributes Project attributes
*/
public TexlipseProjectCreationWizardPage(TexlipseProjectAttributes attributes) {
super(0, attributes);
}
/**
* Create the layout of the page.
* @param parent parent component in the UI
* @return number of components using a status message
*/
public void createComponents(Composite parent) {
// path to the workspace root directory
workspacePath = ResourcesPlugin.getWorkspace().getRoot().getLocation().addTrailingSeparator().toOSString();
createProjectNameControl(parent);
addSpacer(parent, 2);
createProjectLocationControl(parent);
addSpacer(parent, 2);
createOutputFormatControl(parent);
addSeparator(parent);
addSpacer(parent, 2);
createLabels(parent);
createTemplateControl(parent);
//this updates the template description area and the template type label
updateEntries();
}
/**
* @param parent parent component
*/
private void createOutputFormatControl(Composite parent) {
outputChooser = new BuilderChooser(parent);
GridData ngd = new GridData(GridData.FILL_HORIZONTAL);
ngd.horizontalSpan = 2;
outputChooser.getControl().setLayoutData(ngd);
outputChooser.setSelectedBuilder(TexlipsePlugin.getDefault().getPreferenceStore().getInt(TexlipseProperties.BUILDER_NUMBER));
String o = attributes.getOutputFile();
attributes.setOutputFile(o.substring(0, o.lastIndexOf('.')+1) + outputChooser.getSelectedFormat());
attributes.setOutputFormat(outputChooser.getSelectedFormat());
outputChooser.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
String o = attributes.getOutputFile();
attributes.setOutputFile(o.substring(0, o.lastIndexOf('.')+1) + outputChooser.getSelectedFormat());
attributes.setOutputFormat(outputChooser.getSelectedFormat());
attributes.setBuilder(outputChooser.getSelectedBuilder());
}});
}
/**
* Create project name settings box.
* @param composite the parent container
*/
private void createProjectNameControl(Composite composite) {
Composite c = new Composite(composite, SWT.NULL);
c.setLayout(new GridLayout(2, false));
GridData lgd = new GridData(GridData.FILL_HORIZONTAL);
lgd.horizontalSpan = 2;
c.setLayoutData(lgd);
// add label
Label label = new Label(c, SWT.LEFT);
label.setText(TexlipsePlugin.getResourceString("projectWizardNameLabel"));
label.setToolTipText(TexlipsePlugin.getResourceString("projectWizardNameTooltip"));
label.setLayoutData(new GridData());
// add text field
projectNameField = new Text(c, SWT.SINGLE | SWT.BORDER);
projectNameField.setText(attributes.getProjectName());
projectNameField.setToolTipText(TexlipsePlugin.getResourceString("projectWizardNameTooltip"));
projectNameField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
projectNameField.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
if (!projectNameField.isDisposed()) {
validateProjectName(projectNameField.getText());
if (!projectLocationField.isEnabled()) {
projectLocationField.setText(workspacePath + projectNameField.getText());
}
}
}
});
// add language label
final Label mainLabel = new Label(c, SWT.LEFT);
mainLabel.setText(TexlipsePlugin.getResourceString("propertiesLanguage"));
mainLabel.setToolTipText(TexlipsePlugin.getResourceString("propertiesLanguageDescription"));
mainLabel.setLayoutData(new GridData());
// add text field
languageField = new Text(c, SWT.SINGLE | SWT.BORDER);
languageField.setText(attributes.getLanguageCode());
languageField.setToolTipText(TexlipsePlugin.getResourceString("propertiesLanguageDescription"));
languageField.setLayoutData(new GridData());
new AutoCompleteField(languageField, new TextContentAdapter(), Locale.getISOLanguages());
languageField.setTextLimit(2);
languageField.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
if (!languageField.isDisposed()) {
String text = languageField.getText();
IStatus status = createStatus(IStatus.OK, "");
//Has it exactly two characters
//Is this a valid language code
if (text.length() != 2 || Arrays.binarySearch(Locale.getISOLanguages(), text) < 0) {
status = createStatus(IStatus.WARNING,
TexlipsePlugin.getResourceString("projectWizardLanguageCodeError"));
}
attributes.setLanguageCode(text);
updateStatus(status, languageField);
}
}
});
}
/**
* Create project name settings box.
* @param composite the parent container
*/
private void createProjectLocationControl(Composite parent) {
// create borders
Group group = new Group(parent, SWT.NULL);
group.setText(TexlipsePlugin.getResourceString("projectWizardLocationTitle"));
group.setLayout(new GridLayout());
GridData lgd = new GridData(GridData.FILL_HORIZONTAL);
lgd.horizontalSpan = 2;
group.setLayoutData(lgd);
// add radioButtons
final Button createLocalProjectButton = new Button(group, SWT.RADIO | SWT.LEFT);
createLocalProjectButton.setLayoutData(new GridData());
createLocalProjectButton.setText(TexlipsePlugin.getResourceString("projectWizardLocationLocal"));
createLocalProjectButton.setSelection(true);
createLocalProjectButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
//Only execute if this field becomes selected
if (!createLocalProjectButton.getSelection()) return;
Control[] c = projectLocationField.getParent().getChildren();
for (int i = 0; i < c.length; i++) {
c[i].setEnabled(false);
}
projectLocationField.setText(workspacePath + projectNameField.getText());
attributes.setProjectLocation(null);
updateStatus(createStatus(IStatus.OK, ""), projectLocationField);
}});
final Button createExternalProjectButton = new Button(group, SWT.RADIO | SWT.LEFT);
createExternalProjectButton.setLayoutData(new GridData());
createExternalProjectButton.setText(TexlipsePlugin.getResourceString("projectWizardLocationExternal"));
createExternalProjectButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
//Only execute if this field becomes selected
if (!createExternalProjectButton.getSelection()) return;
Control[] c = projectLocationField.getParent().getChildren();
for (int i = 0; i < c.length; i++) {
c[i].setEnabled(true);
}
projectLocationField.setFocus();
projectLocationField.setText("");
}});
Composite composite = new Composite(group, SWT.NULL);
composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
GridLayout cgl = new GridLayout();
cgl.numColumns = 3;
composite.setLayout(cgl);
// add location label
Label label = new Label(composite, SWT.LEFT);
label.setText(TexlipsePlugin.getResourceString("projectWizardLocationLabel"));
label.setLayoutData(new GridData());
label.setEnabled(false);
// add location field
projectLocationField = new Text(composite, SWT.SINGLE | SWT.BORDER);
projectLocationField.setText(workspacePath);
projectLocationField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
projectLocationField.setEnabled(false);
projectLocationField.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
if (!projectLocationField.isDisposed() && projectLocationField.isEnabled()) {
validateProjectLocation(projectLocationField.getText());
}
}});
Button browseLocationButton = new Button(composite, SWT.PUSH);
browseLocationButton.setText(TexlipsePlugin.getResourceString("openBrowse"));
browseLocationButton.setLayoutData(new GridData());
browseLocationButton.setEnabled(false);
browseLocationButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
DirectoryDialog dialog = new DirectoryDialog(projectLocationField.getShell());
dialog.setMessage(TexlipsePlugin.getResourceString("projectWizardLocationSelect"));
dialog.setText(TexlipsePlugin.getResourceString("projectWizardLocationSelect"));
String current = projectLocationField.getText();
if (current == null || current.length() == 0) {
current = workspacePath;
}
dialog.setFilterPath(current);
String dirStr = dialog.open();
if (dirStr != null) {
File dir = new File(dirStr);
if (dir.exists() && dir.isDirectory()) {
projectLocationField.setText(dir.getAbsolutePath());
}
}
}});
}
/**
* Check if the external project location is valid.
* This method updates the status message for the project location.
* @param text the path to project location
*/
private void validateProjectLocation(String text) {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
String pName = projectNameField.getText();
//Project needs a name, otherwise an exception is thrown. The name is not important for path checking
if ("".equals(pName)) pName = "fdslajflj";
IProject p = workspace.getRoot().getProject(pName);
IStatus status = workspace.validateProjectLocation(p, new Path(text));
if (status.getSeverity() == IStatus.OK) {
attributes.setProjectLocation(text);
}
updateStatus(status, projectLocationField);
}
/**
* Creates labels for the template list and the description text area
* to the given Composite object
*
* @param composite the parent container
*/
private void createLabels(Composite composite) {
// add label for the list of templates
Label label = new Label(composite, SWT.LEFT);
label.setText(TexlipsePlugin.getResourceString("projectWizardTemplateListLabel"));
label.setToolTipText(TexlipsePlugin.getResourceString("projectWizardTemplateListTooltip"));
label.setLayoutData(new GridData());
// add composite containing a label for the description area and templatetype (system/user) label
Composite c = new Composite(composite, SWT.NONE);
c.setLayout(new GridLayout(2,false));
c.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
// add label for the description area
Label l = new Label(c, SWT.LEFT);
l.setText(TexlipsePlugin.getResourceString("projectWizardTemplateDescriptionLabel"));
l.setToolTipText(TexlipsePlugin.getResourceString("projectWizardTemplateDescriptionTooltip"));
l.setLayoutData(new GridData());
// add label for presenting the type of the selected template
typeLabel = new Label(c, SWT.RIGHT);
//Note that thetext of this label is set by updateEntries()
typeLabel.setToolTipText(TexlipsePlugin.getResourceString("projectWizardTemplateTypeTooltip"));
typeLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
}
/**
* Creates a list element containing available templates (system and user)
* and a text area next to it for showing description about the selected template
*
* @param composite the parent container
*/
private void createTemplateControl(Composite composite) {
// add list for templates
templateList = new List(composite, SWT.SINGLE | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
templateList.setItems(ProjectTemplateManager.loadTemplateNames());
templateList.setLayoutData(new GridData(GridData.FILL_VERTICAL));
templateList.setToolTipText(TexlipsePlugin.getResourceString("projectWizardTemplateTooltip"));
templateList.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
attributes.setTemplate(templateList.getSelection()[0]);
updateEntries();
}});
templateList.setSelection(0);
// this has to be done, because setSelection() doesn't generate an event
attributes.setTemplate(templateList.getItem(0));
// add TextField for the selected template's description
descriptionField = new Text(composite, SWT.MULTI | SWT.BORDER);
descriptionField.setToolTipText(TexlipsePlugin.getResourceString("projectWizardTemplateDescriptionTooltip"));
descriptionField.setLayoutData(new GridData(GridData.FILL_BOTH));
descriptionField.setEditable(false);
}
/**
* Updates the description text area and template type label
*
*/
private void updateEntries(){
typeLabel.setText(templateType(attributes.getTemplate()));
readProjectTemplateDescription(attributes.getTemplate());
}
/**
* Returns the type of the given template.
*
* @param template name of a template (should be the selected item from
* the list element containing all available templates).
* @return Either "User defined template" or "System defined template" depending
* wether the given template is found in plugins templates directory (former if not,
* latter if yes).
*/
private String templateType(String template){
URL templateUrl = TexlipsePlugin.getDefault().getBundle().getEntry("templates" + File.separator + template + ".tex");
if(templateUrl==null) return "User defined template";
else return "System template";
}
/**
* Starts to read the given template (assuming it is found
* from either plugins template directory or user's template directory...
* if not, the description is set to "") and puts all lines
* starting with "%%" (excluding "%%") to the description text area.
* Reading is ended, when a line not starting wiht "%%" is encountered
* or the end of file is reached.
*
* @param template name of a template
*/
private void readProjectTemplateDescription(String template) {
//if system template, then it is found here
URL templateUrl = TexlipsePlugin.getDefault().getBundle().getEntry("templates" + File.separator + template + ".tex");
String userTemplate = null;
if (templateUrl==null){
//if not, then the template is user defined
File userTemplateFolder = ProjectTemplateManager.getUserTemplateFolder();
userTemplate = userTemplateFolder.getAbsolutePath()+File.separator+template+".tex";
}
try {
String line = null;
BufferedReader r;
if(templateUrl!=null) r = new BufferedReader(new InputStreamReader(templateUrl.openStream()));
else r = new BufferedReader(new FileReader(userTemplate));
StringBuffer sb = new StringBuffer();
while ((line = r.readLine()) != null) {
if(!line.startsWith("%%")) break;
if(line.length()>2) sb.append(line.substring(2));
sb.append('\n');
}
r.close();
sb.toString();
descriptionField.setText(sb.toString());
} catch (IOException e) {
TexlipsePlugin.log("Reading a description of template file:", e);
descriptionField.setText("");
}
}
/**
* Update the status line when the page becomes visible.
*/
public void setVisible(boolean visible) {
super.setVisible(visible);
if (visible) {
validateProjectName(projectNameField.getText());
}
}
/**
* Check if there already is a project under the given name.
* @param text
*/
private void validateProjectName(String text) {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IStatus status = workspace.validateName(text, IResource.PROJECT);
if (status.isOK()) {
if (workspace.getRoot().getProject(text).exists()) {
status = createStatus(IStatus.ERROR,
TexlipsePlugin.getResourceString("projectWizardNameError"));
}
attributes.setProjectName(text);
}
updateStatus(status, projectNameField);
}
}