diff --git a/engine/build.xml b/engine/build.xml
index 71a77a0aa..f0ee518c5 100644
--- a/engine/build.xml
+++ b/engine/build.xml
@@ -206,6 +206,9 @@
+
+
+
diff --git a/sdk/build.xml b/sdk/build.xml
index c0607bdcc..c03647783 100644
--- a/sdk/build.xml
+++ b/sdk/build.xml
@@ -96,7 +96,7 @@
-->
-
+
diff --git a/sdk/jme3-android/build.xml b/sdk/jme3-android/build.xml
new file mode 100644
index 000000000..d6b52841a
--- /dev/null
+++ b/sdk/jme3-android/build.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+ Builds, tests, and runs the project com.jme3.gde.android.
+
+
diff --git a/sdk/jme3-android/manifest.mf b/sdk/jme3-android/manifest.mf
new file mode 100644
index 000000000..491b5d310
--- /dev/null
+++ b/sdk/jme3-android/manifest.mf
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+OpenIDE-Module: com.jme3.gde.android
+OpenIDE-Module-Implementation-Version: 0
+OpenIDE-Module-Layer: com/jme3/gde/android/layer.xml
+OpenIDE-Module-Localizing-Bundle: com/jme3/gde/android/Bundle.properties
+
diff --git a/sdk/jme3-android/nbproject/build-impl.xml b/sdk/jme3-android/nbproject/build-impl.xml
new file mode 100644
index 000000000..2ceedc0a8
--- /dev/null
+++ b/sdk/jme3-android/nbproject/build-impl.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ You must set 'suite.dir' to point to your containing module suite
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sdk/jme3-android/nbproject/genfiles.properties b/sdk/jme3-android/nbproject/genfiles.properties
new file mode 100644
index 000000000..f96117573
--- /dev/null
+++ b/sdk/jme3-android/nbproject/genfiles.properties
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=018d14a3
+build.xml.script.CRC32=6461359b
+build.xml.stylesheet.CRC32=a56c6a5b@1.46.1
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=018d14a3
+nbproject/build-impl.xml.script.CRC32=abd1e01a
+nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.46.1
diff --git a/sdk/jme3-android/nbproject/platform.properties b/sdk/jme3-android/nbproject/platform.properties
new file mode 100644
index 000000000..efa13224b
--- /dev/null
+++ b/sdk/jme3-android/nbproject/platform.properties
@@ -0,0 +1,89 @@
+cluster.path=\
+ ${nbplatform.active.dir}/extra:\
+ ${nbplatform.active.dir}/harness:\
+ ${nbplatform.active.dir}/ide:\
+ ${nbplatform.active.dir}/java:\
+ ${nbplatform.active.dir}/platform
+disabled.modules=\
+ org.netbeans.libs.bugtracking,\
+ org.netbeans.libs.bugzilla,\
+ org.netbeans.libs.jsr223,\
+ org.netbeans.libs.smack,\
+ org.netbeans.libs.springframework,\
+ org.netbeans.libs.swingx,\
+ org.netbeans.modules.apisupport.apidocs,\
+ org.netbeans.modules.bugtracking,\
+ org.netbeans.modules.bugtracking.bridge,\
+ org.netbeans.modules.bugzilla,\
+ org.netbeans.modules.db,\
+ org.netbeans.modules.db.core,\
+ org.netbeans.modules.db.dataview,\
+ org.netbeans.modules.db.drivers,\
+ org.netbeans.modules.db.kit,\
+ org.netbeans.modules.db.metadata.model,\
+ org.netbeans.modules.db.mysql,\
+ org.netbeans.modules.db.sql.editor,\
+ org.netbeans.modules.db.sql.visualeditor,\
+ org.netbeans.modules.dbapi,\
+ org.netbeans.modules.dbschema,\
+ org.netbeans.modules.derby,\
+ org.netbeans.modules.form,\
+ org.netbeans.modules.form.binding,\
+ org.netbeans.modules.form.j2ee,\
+ org.netbeans.modules.form.kit,\
+ org.netbeans.modules.form.nb,\
+ org.netbeans.modules.form.refactoring,\
+ org.netbeans.modules.glassfish.common,\
+ org.netbeans.modules.hibernate,\
+ org.netbeans.modules.hibernatelib,\
+ org.netbeans.modules.hudson,\
+ org.netbeans.modules.hudson.ant,\
+ org.netbeans.modules.hudson.git,\
+ org.netbeans.modules.hudson.maven,\
+ org.netbeans.modules.hudson.mercurial,\
+ org.netbeans.modules.hudson.subversion,\
+ org.netbeans.modules.hudson.tasklist,\
+ org.netbeans.modules.i18n.form,\
+ org.netbeans.modules.j2ee.core.utilities,\
+ org.netbeans.modules.j2ee.jpa.refactoring,\
+ org.netbeans.modules.j2ee.jpa.verification,\
+ org.netbeans.modules.j2ee.persistence,\
+ org.netbeans.modules.j2ee.persistence.kit,\
+ org.netbeans.modules.j2ee.toplinklib,\
+ org.netbeans.modules.jellytools,\
+ org.netbeans.modules.jellytools.ide,\
+ org.netbeans.modules.jellytools.java,\
+ org.netbeans.modules.jellytools.platform,\
+ org.netbeans.modules.jemmy,\
+ org.netbeans.modules.languages,\
+ org.netbeans.modules.maven,\
+ org.netbeans.modules.maven.checkstyle,\
+ org.netbeans.modules.maven.coverage,\
+ org.netbeans.modules.maven.embedder,\
+ org.netbeans.modules.maven.grammar,\
+ org.netbeans.modules.maven.graph,\
+ org.netbeans.modules.maven.hints,\
+ org.netbeans.modules.maven.indexer,\
+ org.netbeans.modules.maven.junit,\
+ org.netbeans.modules.maven.kit,\
+ org.netbeans.modules.maven.model,\
+ org.netbeans.modules.maven.osgi,\
+ org.netbeans.modules.maven.persistence,\
+ org.netbeans.modules.maven.refactoring,\
+ org.netbeans.modules.maven.repository,\
+ org.netbeans.modules.maven.search,\
+ org.netbeans.modules.maven.spring,\
+ org.netbeans.modules.server,\
+ org.netbeans.modules.spellchecker,\
+ org.netbeans.modules.spellchecker.bindings.htmlxml,\
+ org.netbeans.modules.spellchecker.bindings.properties,\
+ org.netbeans.modules.spellchecker.dictionary_en,\
+ org.netbeans.modules.spellchecker.kit,\
+ org.netbeans.modules.spring.beans,\
+ org.netbeans.modules.websvc.saas.codegen.java,\
+ org.netbeans.modules.xml.wsdl.model,\
+ org.openide.compat,\
+ org.openide.options,\
+ org.openide.util.enumerations
+nbjdk.active=default
+nbplatform.active=default
diff --git a/sdk/jme3-android/nbproject/project.properties b/sdk/jme3-android/nbproject/project.properties
new file mode 100644
index 000000000..b07245a53
--- /dev/null
+++ b/sdk/jme3-android/nbproject/project.properties
@@ -0,0 +1,5 @@
+#Updated by build script
+#Thu, 25 Aug 2011 21:00:54 +0200
+javac.source=1.6
+javac.compilerargs=-Xlint -Xlint\:-serial
+spec.version.base=3.0.0
diff --git a/sdk/jme3-android/nbproject/project.xml b/sdk/jme3-android/nbproject/project.xml
new file mode 100644
index 000000000..b6d6925f7
--- /dev/null
+++ b/sdk/jme3-android/nbproject/project.xml
@@ -0,0 +1,143 @@
+
+
+ org.netbeans.modules.apisupport.project
+
+
+ com.jme3.gde.android
+
+
+
+ com.jme3.gde.core
+
+
+
+ 1
+ 3.0
+
+
+
+ org.netbeans.api.progress
+
+
+
+ 1
+ 1.24
+
+
+
+ org.netbeans.modules.java.j2seproject
+
+
+
+ 1
+
+
+
+
+ org.netbeans.modules.java.project
+
+
+
+ 1
+ 1.29.1
+
+
+
+ org.netbeans.modules.options.api
+
+
+
+ 1
+ 1.22
+
+
+
+ org.netbeans.modules.project.ant
+
+
+
+ 1
+ 1.37
+
+
+
+ org.netbeans.modules.projectapi
+
+
+
+ 1
+ 1.20
+
+
+
+ org.netbeans.modules.projectuiapi
+
+
+
+ 1
+ 1.30
+
+
+
+ org.openide.awt
+
+
+
+ 7.31
+
+
+
+ org.openide.dialogs
+
+
+
+ 7.10
+
+
+
+ org.openide.filesystems
+
+
+
+ 7.20
+
+
+
+ org.openide.loaders
+
+
+
+ 7.21
+
+
+
+ org.openide.nodes
+
+
+
+ 7.21
+
+
+
+ org.openide.util
+
+
+
+ 8.0
+
+
+
+ org.openide.util.lookup
+
+
+
+ 8.8
+
+
+
+
+ com.jme3.gde.android
+
+
+
+
diff --git a/sdk/jme3-android/nbproject/suite.properties b/sdk/jme3-android/nbproject/suite.properties
new file mode 100644
index 000000000..29d7cc9bd
--- /dev/null
+++ b/sdk/jme3-android/nbproject/suite.properties
@@ -0,0 +1 @@
+suite.dir=${basedir}/..
diff --git a/sdk/jme3-android/release/libs/jMonkeyEngine3-android.jar b/sdk/jme3-android/release/libs/jMonkeyEngine3-android.jar
new file mode 100644
index 000000000..f0abfcc86
Binary files /dev/null and b/sdk/jme3-android/release/libs/jMonkeyEngine3-android.jar differ
diff --git a/sdk/jme3-android/src/com/jme3/gde/android/AndroidSdkTool.java b/sdk/jme3-android/src/com/jme3/gde/android/AndroidSdkTool.java
new file mode 100644
index 000000000..9e8185010
--- /dev/null
+++ b/sdk/jme3-android/src/com/jme3/gde/android/AndroidSdkTool.java
@@ -0,0 +1,357 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.jme3.gde.android;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.util.ArrayList;
+import java.util.List;
+import org.netbeans.api.project.Project;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
+import org.openide.NotifyDescriptor.Message;
+import org.openide.filesystems.FileChooserBuilder;
+import org.openide.filesystems.FileLock;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.util.Exceptions;
+import org.openide.util.NbPreferences;
+import org.openide.util.Utilities;
+
+/**
+ *
+ * @author normenhansen
+ */
+public class AndroidSdkTool {
+
+ /**
+ * Starts the Android target configuration utility.
+ */
+ public static void startAndroidTool() {
+ startAndroidTool(false);
+ }
+
+ public static void startAndroidTool(boolean modal) {
+ final String path = getAndroidToolPath();
+ if (path == null) {
+ return;
+ }
+ Thread thread = new Thread(new Runnable() {
+
+ @Override
+ public void run() {
+ String[] command = new String[]{path};
+ ProcessBuilder builder = new ProcessBuilder(command);
+ try {
+ Process proc = builder.start();
+ OutputReader outReader = new OutputReader(proc.getInputStream());
+ OutputReader errReader = new OutputReader(proc.getErrorStream());
+ outReader.start();
+ errReader.start();
+ proc.waitFor();
+ } catch (InterruptedException ex) {
+ Exceptions.printStackTrace(ex);
+ } catch (IOException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+ });
+ if (modal) {
+ thread.run();
+ } else {
+ thread.start();
+ }
+ }
+
+ /**
+ * Returns a FileObject for the android SDK folder, null if none is specified
+ * @return
+ */
+ public static FileObject getSdkFolder() {
+ String path = getSdkPath();
+ if (path == null) {
+ return null;
+ }
+ FileObject fileObj = FileUtil.toFileObject(new File(path));
+ if (fileObj == null) {
+ return null;
+ }
+ return fileObj;
+ }
+
+ /**
+ * Returns a String with the path to the SDK or null if none is specified.
+ * @return
+ */
+ public static String getSdkPath() {
+ String path = NbPreferences.forModule(AndroidSdkTool.class).get("sdk_path", null);
+ if (path == null) {
+ FileChooserBuilder builder = new FileChooserBuilder(AndroidSdkTool.class);
+ builder.setTitle("Please select Android SDK Folder");
+ builder.setDirectoriesOnly(true);
+ File file = builder.showOpenDialog();
+ if (file != null) {
+ FileObject folder = FileUtil.toFileObject(file);
+ if (folder.getFileObject("tools") == null) {
+ Message msg = new NotifyDescriptor.Message(
+ "Not a valid SDK folder!",
+ NotifyDescriptor.ERROR_MESSAGE);
+ DialogDisplayer.getDefault().notifyLater(msg);
+
+ } else {
+ String name = file.getPath();
+ NbPreferences.forModule(AndroidSdkTool.class).put("sdk_path", name);
+ return name;
+ }
+ }
+ } else {
+ return path;
+ }
+ return null;
+ }
+
+ /**
+ * Returns a string with the path to the android tool, specific for platform (.exe for windows)
+ * @return
+ */
+ public static String getAndroidToolPath() {
+ FileObject executable = null;
+ FileObject folder = getSdkFolder();
+ if (folder == null) {
+ return null;
+ }
+ if (Utilities.isWindows()) {
+ executable = folder.getFileObject("tools/android.exe");
+ } else {
+ executable = folder.getFileObject("tools/android");
+ }
+ return FileUtil.toFile(executable).getPath();
+ }
+
+ /**
+ * Gets a list of android targets registered in the SDK
+ * @return
+ */
+ public static List getTargetList() {
+ ArrayList list = new ArrayList();
+ final String path = getAndroidToolPath();
+ if (path == null) {
+ return list;
+ }
+ String[] command = new String[]{path, "list", "targets"};
+ ProcessBuilder builder = new ProcessBuilder(command);
+ try {
+ Process proc = builder.start();
+ ListReader outReader = new ListReader(proc.getInputStream(), list);
+ OutputReader errReader = new OutputReader(proc.getErrorStream());
+ outReader.start();
+ errReader.start();
+ proc.waitFor();
+ } catch (InterruptedException ex) {
+ Exceptions.printStackTrace(ex);
+ } catch (IOException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ return list;
+ }
+
+ //TODO: check mainJmeClass
+ public static void checkProject(Project project, String target, String name, String activity, String packag, String mainJmeClass) {
+ final String path = getAndroidToolPath();
+ if (path == null) {
+ return;
+ }
+ FileObject folder = project.getProjectDirectory().getFileObject("mobile");
+ if (folder == null) {
+ try {
+ folder = project.getProjectDirectory().createFolder("mobile");
+ createProject(project, target, name, activity, packag, mainJmeClass);
+ } catch (IOException ex) {
+ Exceptions.printStackTrace(ex);
+ return;
+ }
+ } else {
+ updateProject(project, target, name);
+ }
+ }
+
+ public static void createProject(Project project, String target, String name, String activity, String packag, String mainJmeClass) {
+ final String path = getAndroidToolPath();
+ if (path == null) {
+ return;
+ }
+ FileObject folder = project.getProjectDirectory().getFileObject("mobile");
+ if (folder == null) {
+ try {
+ folder = project.getProjectDirectory().createFolder("mobile");
+ } catch (IOException ex) {
+ Exceptions.printStackTrace(ex);
+ return;
+ }
+ }
+ String[] command = new String[]{path, "create", "project",
+ "--target", target,
+ "--name", name,
+ "--path", FileUtil.toFile(folder).getPath(),
+ "--activity", activity,
+ "--package", packag};
+ ProcessBuilder builder = new ProcessBuilder(command);
+ FileLock lock = null;
+ try {
+ Process proc = builder.start();
+ OutputReader outReader = new OutputReader(proc.getInputStream());
+ OutputReader errReader = new OutputReader(proc.getErrorStream());
+ outReader.start();
+ errReader.start();
+ proc.waitFor();
+ String mainActName = "mobile/src/" + packag.replaceAll("\\.", "/") + "/MainActivity.java";
+ FileObject mainAct = project.getProjectDirectory().getFileObject(mainActName);
+ if (mainAct != null) {
+ lock = mainAct.lock();
+ OutputStreamWriter out = new OutputStreamWriter(new BufferedOutputStream(mainAct.getOutputStream(lock)));
+ out.write(mainActivityString(mainJmeClass));
+ out.close();
+ lock.releaseLock();
+ } else {
+ throw new IOException("Cannot find " + mainAct);
+ }
+ } catch (InterruptedException ex) {
+ Exceptions.printStackTrace(ex);
+ } catch (IOException ex) {
+ if (lock != null) {
+ lock.releaseLock();
+ }
+ Exceptions.printStackTrace(ex);
+ }
+ }
+
+ public static void updateProject(Project project, String target, String name) {
+ final String path = getAndroidToolPath();
+ if (path == null) {
+ return;
+ }
+ FileObject folder = project.getProjectDirectory().getFileObject("mobile");
+ if (folder == null) {
+ return;
+ }
+ String[] command = new String[]{path, "update", "project",
+ "--target", target,
+ "--name", name,
+ "--path", FileUtil.toFile(folder).getPath()};
+ ProcessBuilder builder = new ProcessBuilder(command);
+ try {
+ Process proc = builder.start();
+ OutputReader outReader = new OutputReader(proc.getInputStream());
+ OutputReader errReader = new OutputReader(proc.getErrorStream());
+ outReader.start();
+ errReader.start();
+ proc.waitFor();
+ } catch (InterruptedException ex) {
+ Exceptions.printStackTrace(ex);
+ } catch (IOException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+
+ private static String mainActivityString(String mainClass) {
+ String str = "import com.jme3.app.AndroidHarness;\n"
+ + "import android.content.pm.ActivityInfo;"
+ + "import com.jme3.system.android.AndroidConfigChooser.ConfigType;"
+ + "public class MainActivity extends AndroidHarness{\n"
+ + " public MainActivity(){\n"
+ + " // Set the application class to run\n"
+ + " appClass = \"" + mainClass + "\";\n"
+ + " //eglConfigType = ConfigType.FASTEST; // Default\n"
+ + " eglConfigType = ConfigType.BEST;\n"
+ + " // Exit Dialog title & message\n"
+ + " exitDialogTitle = \"Exit?\";\n"
+ + " exitDialogMessage = \"Press Yes\";\n"
+ + " // Edit: 25.06.2011: Enable verbose logging\n"
+ + " eglConfigVerboseLogging= true;\n"
+ + " // Edit: 30.06.2011: Choose screen orientation\n"
+ + " screenOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;\n"
+ + " // Edit 12.07.2011: Invert the MouseEvents X (default = true)\n"
+ + " mouseEventsInvertX = true;\n"
+ + " // Edit 05.07.2011: Invert the MouseEvents Y (default = true)\n"
+ + " mouseEventsInvertY = true;\n"
+ + " }\n"
+ + "}\n";
+ return str;
+ }
+
+ public static class AndroidTarget {
+
+ private int id;
+ private String name;
+ private String title;
+ private String platform;
+ private int apiLevel;
+ private int revision;
+ private String skins;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getPlatform() {
+ return platform;
+ }
+
+ public void setPlatform(String platform) {
+ this.platform = platform;
+ }
+
+ public int getApiLevel() {
+ return apiLevel;
+ }
+
+ public void setApiLevel(int apiLevel) {
+ this.apiLevel = apiLevel;
+ }
+
+ public int getRevision() {
+ return revision;
+ }
+
+ public void setRevision(int revision) {
+ this.revision = revision;
+ }
+
+ public String getSkins() {
+ return skins;
+ }
+
+ public void setSkins(String skins) {
+ this.skins = skins;
+ }
+
+ @Override
+ public String toString() {
+ return getTitle();
+ }
+ }
+}
diff --git a/sdk/jme3-android/src/com/jme3/gde/android/Bundle.properties b/sdk/jme3-android/src/com/jme3/gde/android/Bundle.properties
new file mode 100644
index 000000000..17b42b3f2
--- /dev/null
+++ b/sdk/jme3-android/src/com/jme3/gde/android/Bundle.properties
@@ -0,0 +1,12 @@
+jme3-android=jme3-android
+OpenIDE-Module-Display-Category=jMonkeyEngine
+OpenIDE-Module-Name=Android Support
+OpenIDE-Module-Short-Description=Provides Android deployment for jMonkeyEngine SDK
+LBL_Category_Mobile=Mobile
+MobileCustomizerPanel.jLabel2.text=Mobile Deployment
+MobileCustomizerPanel.jCheckBox1.text=Enable Android Deployment
+MobileCustomizerPanel.jLabel1.text=Android Target
+MobileCustomizerPanel.jLabel3.text=Application Package
+MobileCustomizerPanel.jTextField1.text=jTextField1
+MobileCustomizerPanel.jButton2.text=Run Android Target Configuration Utility
+MobileCustomizerPanel.jTextArea1.text=Tip:\nTo recreate the android build project, uncheck the checkbox and press OK, then open this window again and re-enable the checkbox.
diff --git a/sdk/jme3-android/src/com/jme3/gde/android/ImportantFilesNode.java b/sdk/jme3-android/src/com/jme3/gde/android/ImportantFilesNode.java
new file mode 100644
index 000000000..8fb6de704
--- /dev/null
+++ b/sdk/jme3-android/src/com/jme3/gde/android/ImportantFilesNode.java
@@ -0,0 +1,84 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.jme3.gde.android;
+
+import org.netbeans.api.project.Project;
+import org.netbeans.spi.project.LookupProvider;
+import org.netbeans.spi.project.ui.support.NodeFactory;
+import org.netbeans.spi.project.ui.support.NodeFactorySupport;
+import org.netbeans.spi.project.ui.support.NodeList;
+import org.openide.filesystems.FileObject;
+import org.openide.loaders.DataObject;
+import org.openide.loaders.DataObjectNotFoundException;
+import org.openide.nodes.FilterNode;
+import org.openide.nodes.Node;
+import org.openide.util.Exceptions;
+import org.openide.util.Lookup;
+import org.openide.util.lookup.Lookups;
+
+/**
+ *
+ * @author normenhansen
+ */
+public class ImportantFilesNode extends FilterNode {
+
+ public ImportantFilesNode(Project proj) throws DataObjectNotFoundException {
+// super(DataObject.find(proj.getProjectDirectory().getFileObject("mobile/AndroidManifest.xml")).getNodeDelegate());
+ super(Node.EMPTY);
+ }
+
+ @Override
+ public String getDisplayName() {
+ return "Android Manifest";
+ }
+
+ public static class LookupProviderImpl implements LookupProvider {
+
+ public Lookup createAdditionalLookup(Lookup lookup) {
+
+ Project prj = lookup.lookup(Project.class);
+
+ //create node if lookup has important files node
+ FileObject folder = prj.getProjectDirectory().getFileObject("mobile");
+ if (folder != null && folder.isFolder()) {
+ return Lookups.fixed(new ImportantFilesLookupItem(prj));
+ }
+
+ return Lookups.fixed();
+
+ }
+ }
+
+ public static class ImportantFilesNodeFactoryImpl implements NodeFactory {
+
+ public NodeList createNodes(Project project) {
+
+// this.proj = project;
+
+ //If our item is in the project's lookup,
+ //return a new node in the node list:
+ ImportantFilesLookupItem item = project.getLookup().lookup(ImportantFilesLookupItem.class);
+ if (item != null) {
+ try {
+ ImportantFilesNode nd = new ImportantFilesNode(project);
+ return NodeFactorySupport.fixedNodeList(nd);
+ } catch (DataObjectNotFoundException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+
+ //If our item isn't in the lookup,
+ //then return an empty list of nodes:
+ return NodeFactorySupport.fixedNodeList();
+
+ }
+ }
+
+ public static class ImportantFilesLookupItem {
+
+ public ImportantFilesLookupItem(Project prj) {
+ }
+ }
+}
\ No newline at end of file
diff --git a/sdk/jme3-android/src/com/jme3/gde/android/ListReader.java b/sdk/jme3-android/src/com/jme3/gde/android/ListReader.java
new file mode 100644
index 000000000..8fa84dcbb
--- /dev/null
+++ b/sdk/jme3-android/src/com/jme3/gde/android/ListReader.java
@@ -0,0 +1,81 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.jme3.gde.android;
+
+import com.jme3.gde.android.AndroidSdkTool.AndroidTarget;
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.netbeans.api.progress.ProgressHandle;
+import org.openide.util.Exceptions;
+
+/**
+ *
+ * @author normenhansen
+ */
+public class ListReader implements Runnable {
+
+ private Thread thread;
+ private BufferedReader in;
+ private ProgressHandle progress;
+ private ArrayList list;
+
+ public ListReader(InputStream in, ArrayList list) {
+ this.in = new BufferedReader(new InputStreamReader(in));
+ this.list = list;
+ }
+
+ public ListReader(BufferedReader in, ArrayList list) {
+ this.in = in;
+ this.list = list;
+ }
+
+ public void start() {
+ thread = new Thread(this);
+ thread.start();
+ }
+
+ public void run() {
+ try {
+ String line;
+ AndroidTarget target = null;
+ while ((line = in.readLine()) != null) {
+ line = line.trim();
+ if (line.length() > 0) {
+ if (line.startsWith("id:")) {
+ target = new AndroidTarget();
+ int idstart = line.indexOf(":") + 1;
+ int idend = line.indexOf("or");
+ int start = line.indexOf("\"") + 1;
+ int end = line.lastIndexOf("\"");
+ target.setId(Integer.parseInt(line.substring(idstart, idend).trim()));
+ target.setName(line.substring(start, end));
+ list.add(target);
+ }
+ if (line.startsWith("Name:") && target != null) {
+ target.setTitle(line.split(":")[1].trim());
+ }
+ if (progress != null) {
+ progress.progress(line);
+ } else {
+ Logger.getLogger(this.getClass().getName()).log(Level.INFO, line);
+ }
+ }
+ }
+ } catch (Exception e) {
+ Exceptions.printStackTrace(e);
+ }
+ }
+
+ /**
+ * @param progress the progress to set
+ */
+ public void setProgress(ProgressHandle progress) {
+ this.progress = progress;
+ }
+}
diff --git a/sdk/jme3-android/src/com/jme3/gde/android/MobileCompositeProvider.java b/sdk/jme3-android/src/com/jme3/gde/android/MobileCompositeProvider.java
new file mode 100644
index 000000000..37f58e6b5
--- /dev/null
+++ b/sdk/jme3-android/src/com/jme3/gde/android/MobileCompositeProvider.java
@@ -0,0 +1,133 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.jme3.gde.android;
+
+import com.jme3.gde.core.j2seproject.ProjectExtensionManager;
+import com.jme3.gde.core.j2seproject.ProjectExtensionProperties;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import javax.swing.JComponent;
+
+import org.netbeans.api.project.Project;
+import org.netbeans.spi.project.ui.support.ProjectCustomizer;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+
+import org.openide.util.Exceptions;
+import org.openide.util.Lookup;
+import org.openide.util.NbBundle;
+
+/**
+ *
+ * @author normenhansen
+ */
+@ProjectCustomizer.CompositeCategoryProvider.Registration(projectType = "org-netbeans-modules-java-j2seproject", category = "Application", position = 400)
+public class MobileCompositeProvider implements ProjectCustomizer.CompositeCategoryProvider {
+
+ private static final String CAT_MOBILE = "MobileDeployment"; // NOI18N
+ private static ProjectExtensionProperties jwsProps = null;
+ private String[] keyList = new String[]{
+ "application.title",
+ "main.class",
+ "mobile.android.enabled",
+ "mobile.android.package",
+ "mobile.android.target"
+ };
+
+ public MobileCompositeProvider() {
+ }
+
+ @Override
+ public ProjectCustomizer.Category createCategory(Lookup context) {
+ return ProjectCustomizer.Category.create(CAT_MOBILE,
+ NbBundle.getMessage(MobileCompositeProvider.class, "LBL_Category_Mobile"), null);
+ }
+
+ @Override
+ public JComponent createComponent(ProjectCustomizer.Category category, Lookup context) {
+ jwsProps = new ProjectExtensionProperties(context.lookup(Project.class), keyList);
+ MobileCustomizerPanel panel = new MobileCustomizerPanel(jwsProps);
+ category.setStoreListener(new SavePropsListener(jwsProps, context.lookup(Project.class)));
+ category.setOkButtonListener(panel);
+ return panel;
+ }
+
+ private class SavePropsListener implements ActionListener {
+
+ private String extensionName = "mobile";
+ private String extensionVersion = "v0.9";
+ private String[] extensionDependencies = new String[]{"jar", "-mobile-deployment"};
+ private ProjectExtensionManager manager = new ProjectExtensionManager(extensionName, extensionVersion, extensionDependencies);
+ private ProjectExtensionProperties properties;
+ private Project project;
+
+ public SavePropsListener(ProjectExtensionProperties props, Project project) {
+ this.properties = props;
+ this.project = project;
+ manager.setAntTaskLibrary("jme3-android");
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ if ("true".equals(properties.getProperty("mobile.android.enabled"))) {
+ manager.loadTargets("nbres:/com/jme3/gde/android/mobile-targets.xml");
+ manager.checkExtension(project);
+ manager.addRunConfiguration(project, "run-android", "Android Emulator", "run-android");
+ AndroidSdkTool.checkProject(project,
+ properties.getProperty("mobile.android.target"),
+ properties.getProperty("application.title"),
+ "MainActivity",
+ properties.getProperty("mobile.android.package"),
+ properties.getProperty("main.class"));
+ } else {
+ manager.removeExtension(project);
+ try {
+ FileObject folder = project.getProjectDirectory().getFileObject("mobile");
+ if (folder != null) {
+ folder.delete();
+ }
+ project.getProjectDirectory().refresh();
+ } catch (IOException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+ try {
+ properties.store();
+ } catch (IOException ioe) {
+ Exceptions.printStackTrace(ioe);
+ }
+ }
+
+ private void unZipFile(InputStream source, FileObject projectRoot) throws IOException {
+ try {
+ ZipInputStream str = new ZipInputStream(source);
+ ZipEntry entry;
+ while ((entry = str.getNextEntry()) != null) {
+ if (entry.isDirectory()) {
+ FileUtil.createFolder(projectRoot, entry.getName());
+ } else {
+ FileObject fo = FileUtil.createData(projectRoot, entry.getName());
+ writeFile(str, fo);
+ }
+ }
+ } finally {
+ source.close();
+ }
+ }
+
+ private void writeFile(ZipInputStream str, FileObject fo) throws IOException {
+ OutputStream out = fo.getOutputStream();
+ try {
+ FileUtil.copy(str, out);
+ } finally {
+ out.close();
+ }
+ }
+ }
+}
diff --git a/sdk/jme3-android/src/com/jme3/gde/android/MobileCustomizerPanel.form b/sdk/jme3-android/src/com/jme3/gde/android/MobileCustomizerPanel.form
new file mode 100644
index 000000000..ac47e8def
--- /dev/null
+++ b/sdk/jme3-android/src/com/jme3/gde/android/MobileCustomizerPanel.form
@@ -0,0 +1,149 @@
+
+
+
diff --git a/sdk/jme3-android/src/com/jme3/gde/android/MobileCustomizerPanel.java b/sdk/jme3-android/src/com/jme3/gde/android/MobileCustomizerPanel.java
new file mode 100644
index 000000000..8b0362bf7
--- /dev/null
+++ b/sdk/jme3-android/src/com/jme3/gde/android/MobileCustomizerPanel.java
@@ -0,0 +1,183 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+/*
+ * LwjglAppletCustomizerPanel.java
+ *
+ * Created on 11.11.2010, 16:56:53
+ */
+package com.jme3.gde.android;
+
+import com.jme3.gde.android.AndroidSdkTool.AndroidTarget;
+import com.jme3.gde.core.j2seproject.ProjectExtensionProperties;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ *
+ * @author normenhansen
+ */
+public class MobileCustomizerPanel extends javax.swing.JPanel implements ActionListener {
+
+ private ProjectExtensionProperties properties;
+
+ /** Creates new form LwjglAppletCustomizerPanel */
+ public MobileCustomizerPanel(ProjectExtensionProperties properties) {
+ this.properties = properties;
+ initComponents();
+ updateTargetList();
+ loadProperties();
+ }
+
+ private void updateTargetList() {
+ jComboBox1.removeAllItems();
+ List targets = AndroidSdkTool.getTargetList();
+ for (Iterator it = targets.iterator(); it.hasNext();) {
+ AndroidTarget androidTarget = it.next();
+ jComboBox1.addItem(androidTarget);
+ }
+ }
+
+ private void loadProperties() {
+ String str = properties.getProperty("mobile.android.enabled");
+ if ("true".equals(str)) {
+ jCheckBox1.setSelected(true);
+ } else {
+ jCheckBox1.setSelected(false);
+ }
+ if (properties.getProperty("mobile.android.target") != null) {
+ jComboBox1.setSelectedItem(properties.getProperty("mobile.android.target"));
+ }
+ if (properties.getProperty("mobile.android.package") != null) {
+ jTextField1.setText(properties.getProperty("mobile.android.package"));
+ }else{
+ jTextField1.setText("com.mycompany.mygame");
+ }
+ }
+
+ private void saveProperties() {
+ if (jCheckBox1.isSelected()) {
+ properties.setProperty("mobile.android.enabled", "true");
+ } else {
+ properties.setProperty("mobile.android.enabled", "");
+ }
+ //TODO: check properties
+ properties.setProperty("mobile.android.target", ((AndroidTarget) jComboBox1.getSelectedItem()).getName());
+ properties.setProperty("mobile.android.package", jTextField1.getText());
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ saveProperties();
+ }
+
+ /** This method is called from within the constructor to
+ * initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is
+ * always regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ jCheckBox1 = new javax.swing.JCheckBox();
+ jLabel1 = new javax.swing.JLabel();
+ jLabel2 = new javax.swing.JLabel();
+ jComboBox1 = new javax.swing.JComboBox();
+ jLabel3 = new javax.swing.JLabel();
+ jTextField1 = new javax.swing.JTextField();
+ jButton2 = new javax.swing.JButton();
+ jScrollPane1 = new javax.swing.JScrollPane();
+ jTextArea1 = new javax.swing.JTextArea();
+
+ jCheckBox1.setText(org.openide.util.NbBundle.getMessage(MobileCustomizerPanel.class, "MobileCustomizerPanel.jCheckBox1.text")); // NOI18N
+
+ jLabel1.setText(org.openide.util.NbBundle.getMessage(MobileCustomizerPanel.class, "MobileCustomizerPanel.jLabel1.text")); // NOI18N
+
+ jLabel2.setText(org.openide.util.NbBundle.getMessage(MobileCustomizerPanel.class, "MobileCustomizerPanel.jLabel2.text")); // NOI18N
+
+ jComboBox1.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
+
+ jLabel3.setText(org.openide.util.NbBundle.getMessage(MobileCustomizerPanel.class, "MobileCustomizerPanel.jLabel3.text")); // NOI18N
+
+ jTextField1.setText(org.openide.util.NbBundle.getMessage(MobileCustomizerPanel.class, "MobileCustomizerPanel.jTextField1.text")); // NOI18N
+
+ jButton2.setText(org.openide.util.NbBundle.getMessage(MobileCustomizerPanel.class, "MobileCustomizerPanel.jButton2.text")); // NOI18N
+ jButton2.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ jButton2ActionPerformed(evt);
+ }
+ });
+
+ jScrollPane1.setEnabled(false);
+
+ jTextArea1.setColumns(20);
+ jTextArea1.setLineWrap(true);
+ jTextArea1.setRows(5);
+ jTextArea1.setText(org.openide.util.NbBundle.getMessage(MobileCustomizerPanel.class, "MobileCustomizerPanel.jTextArea1.text")); // NOI18N
+ jTextArea1.setWrapStyleWord(true);
+ jTextArea1.setDisabledTextColor(new java.awt.Color(0, 0, 0));
+ jScrollPane1.setViewportView(jTextArea1);
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jCheckBox1, javax.swing.GroupLayout.DEFAULT_SIZE, 394, Short.MAX_VALUE)
+ .addComponent(jLabel2, javax.swing.GroupLayout.DEFAULT_SIZE, 394, Short.MAX_VALUE)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(jLabel1)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(jComboBox1, 0, 278, Short.MAX_VALUE)
+ .addContainerGap())
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(jLabel3)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(jTextField1, javax.swing.GroupLayout.DEFAULT_SIZE, 237, Short.MAX_VALUE)
+ .addContainerGap())
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 394, Short.MAX_VALUE)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(jButton2)
+ .addContainerGap())
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(jLabel2)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(jCheckBox1)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel1)
+ .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel3)
+ .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 62, Short.MAX_VALUE)
+ .addComponent(jButton2)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ );
+ }// //GEN-END:initComponents
+
+private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
+ AndroidSdkTool.startAndroidTool(true);
+ updateTargetList();
+}//GEN-LAST:event_jButton2ActionPerformed
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton jButton2;
+ private javax.swing.JCheckBox jCheckBox1;
+ private javax.swing.JComboBox jComboBox1;
+ private javax.swing.JLabel jLabel1;
+ private javax.swing.JLabel jLabel2;
+ private javax.swing.JLabel jLabel3;
+ private javax.swing.JScrollPane jScrollPane1;
+ private javax.swing.JTextArea jTextArea1;
+ private javax.swing.JTextField jTextField1;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/sdk/jme3-android/src/com/jme3/gde/android/OutputReader.java b/sdk/jme3-android/src/com/jme3/gde/android/OutputReader.java
new file mode 100644
index 000000000..5f03ebc2e
--- /dev/null
+++ b/sdk/jme3-android/src/com/jme3/gde/android/OutputReader.java
@@ -0,0 +1,61 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.jme3.gde.android;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.netbeans.api.progress.ProgressHandle;
+import org.openide.util.Exceptions;
+
+/**
+ *
+ * @author normenhansen
+ */
+public class OutputReader implements Runnable {
+
+ private Thread thread;
+ private BufferedReader in;
+ private ProgressHandle progress;
+
+ public OutputReader(InputStream in) {
+ this.in = new BufferedReader(new InputStreamReader(in));
+ }
+
+ public OutputReader(BufferedReader in) {
+ this.in = in;
+ }
+
+ public void start() {
+ thread = new Thread(this);
+ thread.start();
+ }
+
+ public void run() {
+ try {
+ String line;
+ while ((line = in.readLine()) != null) {
+ if (line.trim().length() > 0) {
+ if (progress != null) {
+ progress.progress(line);
+ } else {
+ Logger.getLogger(this.getClass().getName()).log(Level.INFO, line);
+ }
+ }
+ }
+ } catch (Exception e) {
+ Exceptions.printStackTrace(e);
+ }
+ }
+
+ /**
+ * @param progress the progress to set
+ */
+ public void setProgress(ProgressHandle progress) {
+ this.progress = progress;
+ }
+}
diff --git a/sdk/jme3-android/src/com/jme3/gde/android/jme3-android.xml b/sdk/jme3-android/src/com/jme3/gde/android/jme3-android.xml
new file mode 100644
index 000000000..fed65b2ea
--- /dev/null
+++ b/sdk/jme3-android/src/com/jme3/gde/android/jme3-android.xml
@@ -0,0 +1,21 @@
+
+
+
+
+ jme3-android
+ j2se
+ com.jme3.gde.android.Bundle
+
+ classpath
+ jar:nbinst://com.jme3.gde.android/libs/jMonkeyEngine3-android.jar!/
+
+
+ src
+
+
+ javadoc
+
+
diff --git a/sdk/jme3-android/src/com/jme3/gde/android/layer.xml b/sdk/jme3-android/src/com/jme3/gde/android/layer.xml
new file mode 100644
index 000000000..61e92eda9
--- /dev/null
+++ b/sdk/jme3-android/src/com/jme3/gde/android/layer.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/sdk/jme3-android/src/com/jme3/gde/android/mobile-targets.xml b/sdk/jme3-android/src/com/jme3/gde/android/mobile-targets.xml
new file mode 100644
index 000000000..f8e8f4535
--- /dev/null
+++ b/sdk/jme3-android/src/com/jme3/gde/android/mobile-targets.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sdk/jme3-android/src/com/jme3/gde/android/properties/Bundle.properties b/sdk/jme3-android/src/com/jme3/gde/android/properties/Bundle.properties
new file mode 100644
index 000000000..a347d714f
--- /dev/null
+++ b/sdk/jme3-android/src/com/jme3/gde/android/properties/Bundle.properties
@@ -0,0 +1,6 @@
+OptionsCategory_Keywords_Mobile=Mobile
+OptionsCategory_Name_Mobile=Mobile
+MobilePanel.jLabel1.text=SDK Path:
+MobilePanel.jTextField1.text=jTextField1
+MobilePanel.jButton1.text=set..
+MobilePanel.jButton2.text=Run Android Target Configuration Utility
diff --git a/sdk/jme3-android/src/com/jme3/gde/android/properties/MobileOptionsPanelController.java b/sdk/jme3-android/src/com/jme3/gde/android/properties/MobileOptionsPanelController.java
new file mode 100644
index 000000000..da7a2058c
--- /dev/null
+++ b/sdk/jme3-android/src/com/jme3/gde/android/properties/MobileOptionsPanelController.java
@@ -0,0 +1,76 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.jme3.gde.android.properties;
+
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import javax.swing.JComponent;
+import org.netbeans.spi.options.OptionsPanelController;
+import org.openide.util.HelpCtx;
+import org.openide.util.Lookup;
+
+@OptionsPanelController.TopLevelRegistration(categoryName = "#OptionsCategory_Name_Mobile",
+iconBase = "com/jme3/gde/android/properties/Phone_16.gif",
+keywords = "#OptionsCategory_Keywords_Mobile",
+keywordsCategory = "Mobile")
+public final class MobileOptionsPanelController extends OptionsPanelController {
+
+ private MobilePanel panel;
+ private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
+ private boolean changed;
+
+ public void update() {
+ getPanel().load();
+ changed = false;
+ }
+
+ public void applyChanges() {
+ getPanel().store();
+ changed = false;
+ }
+
+ public void cancel() {
+ // need not do anything special, if no changes have been persisted yet
+ }
+
+ public boolean isValid() {
+ return getPanel().valid();
+ }
+
+ public boolean isChanged() {
+ return changed;
+ }
+
+ public HelpCtx getHelpCtx() {
+ return null; // new HelpCtx("...ID") if you have a help set
+ }
+
+ public JComponent getComponent(Lookup masterLookup) {
+ return getPanel();
+ }
+
+ public void addPropertyChangeListener(PropertyChangeListener l) {
+ pcs.addPropertyChangeListener(l);
+ }
+
+ public void removePropertyChangeListener(PropertyChangeListener l) {
+ pcs.removePropertyChangeListener(l);
+ }
+
+ private MobilePanel getPanel() {
+ if (panel == null) {
+ panel = new MobilePanel(this);
+ }
+ return panel;
+ }
+
+ void changed() {
+ if (!changed) {
+ changed = true;
+ pcs.firePropertyChange(OptionsPanelController.PROP_CHANGED, false, true);
+ }
+ pcs.firePropertyChange(OptionsPanelController.PROP_VALID, null, null);
+ }
+}
diff --git a/sdk/jme3-android/src/com/jme3/gde/android/properties/MobilePanel.form b/sdk/jme3-android/src/com/jme3/gde/android/properties/MobilePanel.form
new file mode 100644
index 000000000..c65cdbaa2
--- /dev/null
+++ b/sdk/jme3-android/src/com/jme3/gde/android/properties/MobilePanel.form
@@ -0,0 +1,87 @@
+
+
+
diff --git a/sdk/jme3-android/src/com/jme3/gde/android/properties/MobilePanel.java b/sdk/jme3-android/src/com/jme3/gde/android/properties/MobilePanel.java
new file mode 100644
index 000000000..e08e40a6f
--- /dev/null
+++ b/sdk/jme3-android/src/com/jme3/gde/android/properties/MobilePanel.java
@@ -0,0 +1,153 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.jme3.gde.android.properties;
+
+import com.jme3.gde.android.AndroidSdkTool;
+import java.io.File;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
+import org.openide.NotifyDescriptor.Message;
+import org.openide.filesystems.FileChooserBuilder;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.util.NbPreferences;
+
+final class MobilePanel extends javax.swing.JPanel {
+
+ private final MobileOptionsPanelController controller;
+
+ MobilePanel(MobileOptionsPanelController controller) {
+ this.controller = controller;
+ initComponents();
+ // TODO listen to changes in form fields and call controller.changed()
+ }
+
+ /** This method is called from within the constructor to
+ * initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is
+ * always regenerated by the Form Editor.
+ */
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ jLabel1 = new javax.swing.JLabel();
+ jTextField1 = new javax.swing.JTextField();
+ jButton1 = new javax.swing.JButton();
+ jButton2 = new javax.swing.JButton();
+
+ org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(MobilePanel.class, "MobilePanel.jLabel1.text")); // NOI18N
+
+ jTextField1.setText(org.openide.util.NbBundle.getMessage(MobilePanel.class, "MobilePanel.jTextField1.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(MobilePanel.class, "MobilePanel.jButton1.text")); // NOI18N
+ jButton1.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ jButton1ActionPerformed(evt);
+ }
+ });
+
+ org.openide.awt.Mnemonics.setLocalizedText(jButton2, org.openide.util.NbBundle.getMessage(MobilePanel.class, "MobilePanel.jButton2.text")); // NOI18N
+ jButton2.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ jButton2ActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(jLabel1)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(jTextField1, javax.swing.GroupLayout.DEFAULT_SIZE, 318, Short.MAX_VALUE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(jButton1))
+ .addComponent(jButton2))
+ .addContainerGap())
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel1)
+ .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(jButton1))
+ .addGap(18, 18, 18)
+ .addComponent(jButton2)
+ .addContainerGap(122, Short.MAX_VALUE))
+ );
+ }// //GEN-END:initComponents
+
+private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
+ FileChooserBuilder builder = new FileChooserBuilder(AndroidSdkTool.class);
+ builder.setTitle("Please select Android SDK Folder");
+ builder.setDirectoriesOnly(true);
+ File file = builder.showOpenDialog();
+ if (file != null) {
+ FileObject folder = FileUtil.toFileObject(file);
+ if (folder.getFileObject("tools") == null) {
+ Message msg = new NotifyDescriptor.Message(
+ "Not a valid SDK folder!",
+ NotifyDescriptor.ERROR_MESSAGE);
+ DialogDisplayer.getDefault().notifyLater(msg);
+
+ } else {
+ String name = file.getPath();
+ jTextField1.setText(name);
+ }
+ }
+}//GEN-LAST:event_jButton1ActionPerformed
+
+private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
+ AndroidSdkTool.startAndroidTool();
+}//GEN-LAST:event_jButton2ActionPerformed
+
+ void load() {
+// jTextField2.setText(NbPreferences.forModule(AndroidSdkTool.class).get("assetpack_path", null));
+ jTextField1.setText(NbPreferences.forModule(AndroidSdkTool.class).get("sdk_path", null));
+// jPasswordField1.setText(NbPreferences.forModule(AndroidSdkTool.class).get("assetpack_pass", null));
+ }
+
+ void store() {
+// NbPreferences.forModule(AndroidSdkTool.class).put("assetpack_path", jTextField2.getText());
+ NbPreferences.forModule(AndroidSdkTool.class).put("sdk_path", jTextField1.getText());
+// NbPreferences.forModule(AndroidSdkTool.class).put("assetpack_pass", new String(jPasswordField1.getPassword()));
+ }
+// void load() {
+// // TODO read settings and initialize GUI
+// // Example:
+// // someCheckBox.setSelected(Preferences.userNodeForPackage(MobilePanel.class).getBoolean("someFlag", false));
+// // or for org.openide.util with API spec. version >= 7.4:
+// // someCheckBox.setSelected(NbPreferences.forModule(MobilePanel.class).getBoolean("someFlag", false));
+// // or:
+// // someTextField.setText(SomeSystemOption.getDefault().getSomeStringProperty());
+// }
+//
+// void store() {
+// // TODO store modified settings
+// // Example:
+// // Preferences.userNodeForPackage(MobilePanel.class).putBoolean("someFlag", someCheckBox.isSelected());
+// // or for org.openide.util with API spec. version >= 7.4:
+// // NbPreferences.forModule(MobilePanel.class).putBoolean("someFlag", someCheckBox.isSelected());
+// // or:
+// // SomeSystemOption.getDefault().setSomeStringProperty(someTextField.getText());
+// }
+
+ boolean valid() {
+ // TODO check whether form is consistent and complete
+ return true;
+ }
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton jButton1;
+ private javax.swing.JButton jButton2;
+ private javax.swing.JLabel jLabel1;
+ private javax.swing.JTextField jTextField1;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/sdk/jme3-android/src/com/jme3/gde/android/properties/Phone_16.gif b/sdk/jme3-android/src/com/jme3/gde/android/properties/Phone_16.gif
new file mode 100644
index 000000000..40bb42dff
Binary files /dev/null and b/sdk/jme3-android/src/com/jme3/gde/android/properties/Phone_16.gif differ
diff --git a/sdk/nbproject/project.properties b/sdk/nbproject/project.properties
index 42525be26..bcaff72e4 100644
--- a/sdk/nbproject/project.properties
+++ b/sdk/nbproject/project.properties
@@ -43,7 +43,8 @@ modules=\
${project.com.jme3.gde.codecheck}:\
${project.com.jme3.gde.obfuscate}:\
${project.com.jme3.gde.blender}:\
- ${project.com.jme3.gde.angelfont}
+ ${project.com.jme3.gde.angelfont}:\
+ ${project.com.jme3.gde.android}
project.com.jme3.gde.android=jme3-android
project.com.jme3.gde.angelfont=jme3-angelfont
project.com.jme3.gde.blender=jme3-blender