/**
* Copyright (c) 2005-2013 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Eclipse Public License (EPL).
* Please see the license.txt included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package org.python.pydev.customizations.app_engine.wizards;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
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.Text;
import org.python.pydev.core.log.Log;
import org.python.pydev.customizations.CustomizationsPlugin;
import org.python.pydev.shared_core.callbacks.ICallback;
import org.python.pydev.shared_core.io.FileUtils;
import org.python.pydev.shared_core.string.StringUtils;
import org.python.pydev.shared_core.structure.Tuple;
/**
* This page is used to configure templates for google app engine.
*/
public class AppEngineTemplatePage extends WizardPage {
/**
* Constant for forcing the user to choose a template
*/
protected static final String CHOOSE_ONE = "-- Choose One --";
/**
* Constant for creating an empty project
*/
protected static final String EMPTY_PROJECT = "Empty Project";
/**
* The names of the templates and the related description to be shown to the user
*/
protected Map<String, Tuple<String, File>> templateNamesAndDescriptions;
/**
* Combo-box with the template names for the user to choose.
*/
protected Combo comboTemplateNames;
/**
* A label to show the description for the selected template
*/
protected Label templateDescription;
/**
* A string with the last choice the user has done in the combo
*/
protected String lastTemplateChoice = "";
/**
* The UI for entering the text
*/
private Text appIdText;
/**
* The lastAppId used by the user (the value here is the default)
*/
private String lastAppIdText = "sample-app";
protected AppEngineTemplatePage(String pageName) {
super(pageName);
setChooseOneErrorMessage();
}
private void setChooseOneErrorMessage() {
setErrorMessage("Please select the template to use to create the project");
}
@Override
public void createControl(Composite parent) {
Font font = parent.getFont();
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayout(new GridLayout());
setFillHorizontalLayoutDataAndFont(composite, font);
//---- Application id
Label appIdLabel = new Label(composite, SWT.NONE);
appIdLabel.setText("What's the application id registered for this project?");
setFillHorizontalLayoutDataAndFont(appIdLabel, font);
appIdText = new Text(composite, SWT.BORDER);
appIdText.setText(lastAppIdText);
setFillHorizontalLayoutDataAndFont(appIdText, font);
appIdText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
handleChange();
}
});
//---- Template label / combo
Label templateLabel = new Label(composite, SWT.NONE);
templateLabel.setText("From which template do you want to create your new Google App Project?");
setFillHorizontalLayoutDataAndFont(templateLabel, font);
comboTemplateNames = new Combo(composite, SWT.BORDER);
templateNamesAndDescriptions = new HashMap<String, Tuple<String, File>>();
try {
loadTemplates();
} catch (CoreException e1) {
Log.log(e1);
}
ArrayList<String> keys = new ArrayList<String>(templateNamesAndDescriptions.keySet());
Collections.sort(keys);
keys.add(0, EMPTY_PROJECT);
keys.add(0, CHOOSE_ONE);
comboTemplateNames.setItems(keys.toArray(new String[0]));
comboTemplateNames.setText(CHOOSE_ONE);
setFillHorizontalLayoutDataAndFont(comboTemplateNames, font);
comboTemplateNames.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
handleChange();
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
});
templateDescription = new Label(composite, SWT.NONE);
templateDescription.setText("");
setFillHorizontalLayoutDataAndFont(templateDescription, font);
setControl(composite);
}
/**
* Sets the font and the grid data for some control.
*/
private void setFillHorizontalLayoutDataAndFont(Control control, Font font) {
GridData data = new GridData();
data.horizontalAlignment = GridData.FILL;
data.grabExcessHorizontalSpace = true;
control.setLayoutData(data);
control.setFont(font);
}
/**
* Loads the templates from the filesystem.
*/
private void loadTemplates() throws CoreException {
File relativePath = CustomizationsPlugin.getBundleInfo().getRelativePath(
new Path("templates/google_app_engine"));
File[] files = relativePath.listFiles();
if (files != null) {
for (File dir : files) {
if (dir.isDirectory()) {
File[] secondLevelFiles = dir.listFiles();
if (secondLevelFiles != null) {
for (File file2 : secondLevelFiles) {
if (file2.getName().equals("description.txt")) {
String fileContents = FileUtils.getFileContents(file2).trim();
Tuple<String, String> nameAndDesc = StringUtils.splitOnFirst(fileContents, ':');
templateNamesAndDescriptions.put(nameAndDesc.o1, new Tuple<String, File>(
nameAndDesc.o2, dir));
break;
}
}
}
}
}
}
}
/**
* When the selection changes, we update the last choice, description and the error message.
*/
protected void handleChange() {
lastTemplateChoice = this.comboTemplateNames.getText();
lastAppIdText = this.appIdText.getText();
Tuple<String, File> description = templateNamesAndDescriptions.get(lastTemplateChoice);
templateDescription.setText(description != null ? description.o1 : "");
boolean hasError = false;
if (lastTemplateChoice.equals(CHOOSE_ONE)) {
setChooseOneErrorMessage();
hasError = true;
} else if (lastAppIdText == null || lastAppIdText.trim().length() == 0) {
setErrorMessage("Please fill the application id (registered in Google App Engine).");
hasError = true;
}
if (!hasError) {
setErrorMessage(null);
}
}
/**
* Called so that the initial structure is filled, given the source folder to fill.
*/
public void fillSourceFolder(IContainer sourceFolder) {
if (lastTemplateChoice == null || lastTemplateChoice.equals(CHOOSE_ONE)
|| lastTemplateChoice.equals(EMPTY_PROJECT)) {
//Do nothing
} else {
Tuple<String, File> tuple = templateNamesAndDescriptions.get(lastTemplateChoice);
if (tuple != null && tuple.o2.isDirectory()) {
try {
//copy all but the description.txt file.
FileUtils.copyDirectory(tuple.o2, sourceFolder.getLocation().toFile(),
new ICallback<Boolean, File>() {
@Override
public Boolean call(File arg) {
//we don't want to copy description.txt
String filename = arg.getName().toLowerCase();
if (filename.equals("description.txt") || filename.equals(".svn")
|| filename.equals("cvs")) {
return true;
}
return false;
}
}, new ICallback<String, String>() {
@Override
public String call(String contents) {
//We want to change any references to ${app_id} for the app id entered by the user
return StringUtils.replaceAll(contents,
"${app_id}", lastAppIdText);
}
});
} catch (IOException e) {
Log.log(e);
}
try {
sourceFolder.refreshLocal(IResource.DEPTH_INFINITE, null);
} catch (CoreException e) {
Log.log(e);
}
}
}
}
}