/*******************************************************************************
*
* Copyright 2011 Spiffy UI Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
package org.spiffyui.spsample.client;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.spiffyui.client.JSUtil;
import org.spiffyui.client.widgets.FormFeedback;
import org.spiffyui.client.widgets.button.SimpleButton;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
/**
* This is the landing panel
*
*/
public class ProjectCreatorPanel extends HTMLPanel implements KeyUpHandler, KeyPressHandler
{
private static final SPSampleStrings STRINGS = (SPSampleStrings) GWT.create(SPSampleStrings.class);
private static final String WIDE_TEXT_FIELD = "wideTextField";
private static final String[] JAVA_KEYWORDS =
{"abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const",
"continue", "default", "do", "double", "else", "enum", "extends", "final", "finally", "float",
"for", "goto", "if", "implements", "import", "instanceof", "int", "interface", "long", "native",
"new", "package", "private", "protected", "public", "return", "short", "static", "strictfp", "super",
"switch", "synchronized", "this", "throw", "throws", "transient", "try", "void", "volatile", "while",
"false", "null", "true" };
private TextBox m_projectName;
private FormFeedback m_projectNameFeedback;
private TextBox m_packageName;
private FormFeedback m_packageNameFeedback;
private List<FormFeedback> m_feedbacks = new ArrayList<FormFeedback>();
private SimpleButton m_submit;
private InlineLabel m_buildType;
private RadioButton m_maven;
private RadioButton m_ant;
private static final String TYPE_MAVEN = "maven";
private static final String TYPE_ANT = "ant";
private String m_type = TYPE_MAVEN;
/**
* Creates a new panel
* @param id - the ID of the parent panel or some other way to uniquely prefix IDs on within this HTML fragment
*/
public ProjectCreatorPanel(String id)
{
super("div", getHTML(id));
/*
* Add project and package fields and button
*/
m_projectName = new TextBox();
m_projectName.setTitle(Index.getStrings().projectName_tt());
m_projectName.addKeyUpHandler(this);
m_projectName.addKeyPressHandler(this);
m_projectName.getElement().setId(id + "projectNameTxt");
m_projectName.getElement().addClassName(WIDE_TEXT_FIELD);
add(m_projectName, id + "projectName");
m_projectNameFeedback = new FormFeedback();
m_feedbacks.add(m_projectNameFeedback);
add(m_projectNameFeedback, id + "projectNameRow");
m_packageName = new TextBox();
m_packageName.setTitle(Index.getStrings().packageName_tt());
m_packageName.addKeyUpHandler(this);
m_packageName.addKeyPressHandler(this);
m_packageName.getElement().setId(id + "packageNameTxt");
m_packageName.getElement().addClassName(WIDE_TEXT_FIELD);
add(m_packageName, id + "packageName");
m_packageNameFeedback = new FormFeedback();
m_feedbacks.add(m_packageNameFeedback);
add(m_packageNameFeedback, id + "packageNameRow");
addBuildTypes(id);
m_submit = new SimpleButton(Index.getStrings().projectCreatorSubmit());
m_submit.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event)
{
event.preventDefault();
createProject();
}
});
add(m_submit, id + "projectCreatorButtons");
Anchor backToCreate = new Anchor(Index.getStrings().backToCreate(), "#");
backToCreate.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event)
{
event.preventDefault();
JSUtil.hide(getElement().getId() + "createFormInst");
JSUtil.show(getElement().getId() + "createForm");
}
});
add(backToCreate, id + "backToCreateAnchor");
getElement().setId(id);
updateFormStatus(null);
}
private void addBuildTypes(String id)
{
String radioGroup = HTMLPanel.createUniqueId();
m_ant = new RadioButton(radioGroup, Index.getStrings().buildWithAnt());
m_ant.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event)
{
m_type = TYPE_ANT;
}
});
add(m_ant, id + "buildTypes");
m_maven = new RadioButton(radioGroup, Index.getStrings().buildWithMaven());
m_maven.addStyleName("radioOption");
m_maven.setValue(true);
m_maven.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event)
{
m_type = TYPE_MAVEN;
}
});
add(m_maven, id + "buildTypes");
}
@Override
public void onKeyPress(KeyPressEvent event)
{
/*
We want to submit the request if the user pressed enter
*/
if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER &&
m_submit.isEnabled()) {
createProject();
}
}
@Override
public void onKeyUp(KeyUpEvent event)
{
if (event.getNativeKeyCode() != KeyCodes.KEY_TAB) {
updateFormStatus((Widget) event.getSource());
if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
if (enableCreateButton()) {
JSUtil.hide(getElement().getId() + "createForm");
JSUtil.show(getElement().getId() + "createFormInst");
createProject();
}
}
}
}
private void updateFormStatus(Widget w)
{
if (w == m_projectName) {
validateProjectName();
} else if (w == m_packageName) {
validatePackageName();
}
enableCreateButton();
}
/**
* Validate that the project name field is filled in and valid
* It must contain only alpha numeric characters, and length must be at least 2
*/
private void validateProjectName()
{
if (m_projectName.getText() != null && m_projectName.getText().length() > 1) {
if (isAlphaNumericUnderscore(m_projectName.getText())) {
m_projectNameFeedback.setStatus(FormFeedback.VALID);
m_projectNameFeedback.setTitle("");
} else {
m_projectNameFeedback.setStatus(FormFeedback.ERROR);
m_projectNameFeedback.setTitle(Index.getStrings().projNameInValidChar_tt());
}
} else {
m_projectNameFeedback.setStatus(FormFeedback.WARNING);
m_projectNameFeedback.setTitle(Index.getStrings().projNameTooShort_tt());
}
}
private boolean isAlphaNumericUnderscore(String str)
{
for (int i = 0; i < str.length(); i++) {
//If we find a non-alphanumeric or non-underscore character we return false.
if ((!Character.isLetterOrDigit(str.charAt(i))) && (!(Character.toString(str.charAt(i)).equals("_")))) {
return false;
}
}
return true;
}
private boolean isDigit(String str)
{
for (int i = 0; i < str.length(); i++) {
if (!Character.isDigit(str.charAt(i))) {
return false;
}
}
return true;
}
/**
* Validate that the package name field is filled in with a valid package name.
* Package name cannot start or end with dot
* Each package component part can not start with or contain only number, or be empty (2 consecutive dots)
* Each package component part can only contain alpha numeric and underscore characters
* Each package component part can not be the same name as reserved java keywords
* Package name can not be org.spiffyui
* Package string will be converted to all lowercase
*/
private void validatePackageName()
{
if (m_packageName.getText() != null && m_packageName.getText().length() > 0) {
if (m_packageName.getText().startsWith(".") || (m_packageName.getText().endsWith("."))) {
m_packageNameFeedback.setStatus(FormFeedback.ERROR);
m_packageNameFeedback.setTitle(Index.getStrings().packageNameDot_tt());
} else if (m_packageName.getText().trim().toLowerCase().equals("org.spiffyui")) {
m_packageNameFeedback.setStatus(FormFeedback.ERROR);
m_packageNameFeedback.setTitle(Index.getStrings().packageNameSpiffy_tt());
} else {
String[] result = m_packageName.getText().split("\\.");
for (int i = 0; i < result.length; i++) {
String packageToken = result[i];
if (packageToken.length() <= 0) {
m_packageNameFeedback.setStatus(FormFeedback.ERROR);
m_packageNameFeedback.setTitle(Index.getStrings().packageNameEmpty_tt());
break;
} else if (isDigit(packageToken) || isDigit(Character.toString(packageToken.charAt(0)))) {
m_packageNameFeedback.setStatus(FormFeedback.ERROR);
m_packageNameFeedback.setTitle(Index.getStrings().packageNameDigit_tt());
break;
} else if (!isAlphaNumericUnderscore(packageToken)) {
m_packageNameFeedback.setStatus(FormFeedback.ERROR);
m_packageNameFeedback.setTitle(Index.getStrings().packageNameInvalidChar_tt());
break;
} else if (Arrays.asList(JAVA_KEYWORDS).contains(packageToken)) {
m_packageNameFeedback.setStatus(FormFeedback.ERROR);
m_packageNameFeedback.setTitle(Index.getStrings().packageNameKeyword_tt());
break;
} else {
m_packageNameFeedback.setStatus(FormFeedback.VALID);
m_packageNameFeedback.setTitle("");
m_packageName.setText((m_packageName.getText().toLowerCase()));
}
}
}
} else { //no package name, which is fine
m_packageNameFeedback.setStatus(FormFeedback.VALID);
m_packageNameFeedback.setTitle("");
}
}
/**
* Enable or disable the create project button based on the state of the fields.
* and return a flag indicating if the create button is enabled or not
*/
private boolean enableCreateButton()
{
/*
* We only want to enable the create button if every field is valid
*/
for (FormFeedback feedback : m_feedbacks) {
if (feedback.getStatus() != FormFeedback.VALID) {
m_submit.setEnabled(false);
return false;
}
}
m_submit.setEnabled(true);
return true;
}
private void createProject()
{
setProjectName(m_projectName.getText());
JSUtil.hide(getElement().getId() + "createForm");
JSUtil.show(getElement().getId() + "createFormInst");
logToGoogleAnalytics();
Window.Location.replace("/createProject?type=" + m_type + "&projectName=" + m_projectName.getText() +
"&packagePath=" + m_packageName.getText());
}
@Override
public void onLoad()
{
super.onLoad();
/*
Let's set focus into the text field when the page first loads
*/
m_projectName.setFocus(true);
}
private static native void logToGoogleAnalytics() /*-{
$wnd._gaq.push(['_trackPageview', '/createProject']);
}-*/;
/**
* Set the name of the project in the instructions.
*
* @param name the project name
*/
private void setProjectName(String name)
{
getElementById(getElement().getId() + "createFormInst1").setInnerHTML(
Index.getStrings().downloadProjInstr1(name, name));
getElementById(getElement().getId() + "createFormInst2").setInnerHTML(
TYPE_ANT.equals(m_type) ? Index.getStrings().downloadProjInstr2a(name) : Index.getStrings().downloadProjInstr2(name));
}
private static String getHTML(String id)
{
return
"<div class=\"createForm\" id=\"" + id + "createForm\">" +
"<h2 id=\"" + id + "createFormH2\" title=\"" + Index.getStrings().projectCreatorTitle_tt() + "\">" + Index.getStrings().projectCreatorTitle() + "</h2>" +
"<fieldset class=\"projectCreatorFields\">" +
"<ol class=\"dialogformsection\">" +
"<li id=\"" + id + "projectNameRow\" class=\"dialogformrow\">" +
"<label class=\"dialogformlabel\" for=\"" + id + "projectNameTxt\">" + Index.getStrings().projectName() + "</label>" +
"<div id=\"" + id + "projectName\" class=\"formcontrolssection\"></div>" +
"</li>" +
"<li id=\"" + id + "packageNameRow\" class=\"dialogformrow\">" +
"<label class=\"dialogformlabel\" for=\"" + id + "packageNameTxt\">" + Index.getStrings().packageName() + "</label>" +
"<div id=\"" + id + "packageName\" class=\"formcontrolssection\"></div>" +
"</li>" +
"<li id=\"" + id + "buildTypeRow\" class=\"dialogformrow\">" +
"<label class=\"dialogformlabel\" for=\"" + id + "buildTypes\">" + Index.getStrings().buildTypes() + "</label>" +
"<div id=\"" + id + "buildTypes\" class=\"formcontrolssection\"></div>" +
"</li>" +
"<li id=\"" + id + "projectCreatorButtonsRow\" class=\"dialogformrow\">" +
"<div id=\"" + id + "projectCreatorButtons\" class=\"formcontrolssection formbuttons\"></div>" +
"</li>" +
"</ol>" +
"</fieldset>" +
"</div>" +
"<div class=\"createFormInst createForm\" id=\"" + id + "createFormInst\">" +
"<h2>" + Index.getStrings().downloadProjInstr() + "</h2>" +
"<ol>" +
"<li id=\"" + id + "createFormInst1\">" + Index.getStrings().downloadProjInstr1("", "") + "</li>" +
"<li id=\"" + id + "createFormInst2\">" + Index.getStrings().downloadProjInstr2("") + "</li>" +
"<li>" + Index.getStrings().downloadProjInstr3() + "</li>" +
"</ol>" +
"<p>" + Index.getStrings().downloadProjInstr4() + "</p>" +
"<h3 class=\"backToCreateAnchor\" id=\"" + id + "backToCreateAnchor\"></h3>" +
"</div>";
}
}