com.codename1.designer.PickMIDlet Maven / Gradle / Ivy
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores
* CA 94065 USA or visit www.oracle.com if you need additional information or
* have any questions.
*/
package com.codename1.designer;
import com.codename1.ui.Display;
import com.codename1.ui.Form;
import com.codename1.impl.javase.JavaSEPortWithSVGSupport;
import com.codename1.ui.plaf.Accessor;
import com.codename1.ui.util.EditableResources;
import com.codename1.ui.util.UIBuilderOverride;
import java.io.IOException;
import java.util.jar.Attributes.Name;
import java.awt.BorderLayout;
import java.awt.Component;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.prefs.Preferences;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
/**
* UI and logic allowing us to pick the MIDlet which will appear in the preview
* pane
*
* @author Shai Almog
*/
public class PickMIDlet extends javax.swing.JPanel {
private static CustomComponent[] customComponents;
/** Creates new form PickMIDlet */
public PickMIDlet() {
initComponents();
midletPicker.setRenderer(new DefaultListCellRenderer() {
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
if(value == null) {
value = "";
} else {
String s = (String)value;
value = s.substring(0, s.indexOf(','));
}
return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
}
});
Preferences pref = Preferences.userNodeForPackage(ResourceEditorView.class);
jarFile.setText(pref.get("jar", ""));
updateMIDletList();
midletPicker.setSelectedItem(pref.get("midlet", null));
customComponents = null;
}
public static void showPickMIDletDialog(JComponent parent) {
JDialog dlg = new JDialog((JFrame)SwingUtilities.getWindowAncestor(parent));
dlg.setTitle("Pick MIDlet");
dlg.getContentPane().setLayout(new BorderLayout());
dlg.getContentPane().add(BorderLayout.CENTER, new PickMIDlet());
dlg.setLocationByPlatform(true);
dlg.pack();
dlg.setVisible(true);
}
public static CustomComponent[] getCustomComponents() {
if(customComponents == null) {
Preferences pref = Preferences.userNodeForPackage(ResourceEditorView.class);
String jar = pref.get("jar", null);
if(jar != null) {
try {
File jarFile = new File(jar);
URLClassLoader cl = URLClassLoader.newInstance(new URL[]{jarFile.toURI().toURL()}, PickMIDlet.class.getClassLoader());
JarFile zip = new JarFile(jarFile);
Enumeration en = zip.entries();
List customList = new ArrayList();
while(en.hasMoreElements()) {
JarEntry e = en.nextElement();
String className = e.getName().replace("/", ".");
if(className.endsWith(".class") && !className.startsWith("com.codename1.ui.") && className.indexOf('$') < 0) {
className = className.substring(0, className.length() - 6);
try {
CustomComponent current = new CustomComponent();
current.setCls(cl.loadClass(className));
if(!current.getCls().getName().startsWith("com.codename1.ui")) {
// check that it has a default constructor
com.codename1.ui.Component cmp = (com.codename1.ui.Component)current.getCls().newInstance();
current.setClassName(current.getCls().getName());
current.setCodenameOneBaseClass(current.getCls().getName());
current.setType(cmp.getUIID());
customList.add(current);
UIBuilderOverride.registerCustomComponent(cmp.getUIID(), current.getCls());
}
} catch (Throwable ex) {
}
}
}
customComponents = new CustomComponent[customList.size()];
customList.toArray(customComponents);
} catch (IOException ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(JFrame.getFrames()[0], "IO Error when accessing MIDlet JAR File: " + ex, "IO Error", JOptionPane.ERROR_MESSAGE);
}
}
}
return customComponents;
}
public static void resetSettings() {
Preferences pref = Preferences.userNodeForPackage(ResourceEditorView.class);
pref.remove("jar");
pref.remove("midlet");
}
public static void startMIDlet(Hashtable themeHash) {
Accessor.setTheme(themeHash);
Preferences pref = Preferences.userNodeForPackage(ResourceEditorView.class);
String jar = pref.get("jar", null);
String midlet = pref.get("midlet", null);
if(jar != null && midlet != null) {
File jarFile = new File(jar);
if(jarFile.exists()) {
try {
URLClassLoader cl = URLClassLoader.newInstance(new URL[]{jarFile.toURI().toURL()}, PickMIDlet.class.getClassLoader());
StringTokenizer tokenizer = new StringTokenizer((String) midlet, " ,");
String s = tokenizer.nextToken();
while(tokenizer.hasMoreTokens()) {
s = tokenizer.nextToken();
}
Class cls = cl.loadClass(s);
JavaSEPortWithSVGSupport.setClassLoader(cls);
EditableResources.setResourcesClassLoader(cls);
Accessor.setTheme(themeHash);
Object app = cls.newInstance();
JarFile zip = new JarFile(jarFile);
Attributes m = zip.getManifest().getMainAttributes();
cls.getDeclaredMethod("init", new Class[] {Object.class}).invoke(app, new Object[] {null});
cls.getDeclaredMethod("start", new Class[0]).invoke(app, new Object[0]);
// there might be an ongoing transition and the form.show() method is serial
Display.getInstance().callSerially(new Runnable() {
public void run() {
if(Display.getInstance().getCurrent() != null) {
Display.getInstance().getCurrent().refreshTheme();
return;
} else {
new Thread() {
public void run() {
try {
sleep(100);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
Display.getInstance().callSerially(this);
}
}.start();
}
}
});
return;
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
JavaSEPortWithSVGSupport.setClassLoader(PickMIDlet.class);
LiveDemo l = new LiveDemo();
l.init(null);
l.start();
Accessor.setTheme(themeHash);
Form current = Display.getInstance().getCurrent();
if(current != null) {
current.refreshTheme();
}
}
/** 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() {
jLabel2 = new javax.swing.JLabel();
jarFile = new javax.swing.JTextField();
pickJarFile = new javax.swing.JButton();
jLabel3 = new javax.swing.JLabel();
midletPicker = new javax.swing.JComboBox();
okButton = new javax.swing.JButton();
cancelButton = new javax.swing.JButton();
jScrollPane1 = new javax.swing.JScrollPane();
jTextPane1 = new javax.swing.JTextPane();
FormListener formListener = new FormListener();
setName("Form"); // NOI18N
jLabel2.setText("JAR File");
jLabel2.setName("jLabel2"); // NOI18N
jarFile.setEditable(false);
jarFile.setName("jarFile"); // NOI18N
pickJarFile.setText("...");
pickJarFile.setName("pickJarFile"); // NOI18N
pickJarFile.addActionListener(formListener);
jLabel3.setText("MIDlet");
jLabel3.setName("jLabel3"); // NOI18N
midletPicker.setName("midletPicker"); // NOI18N
okButton.setText("OK");
okButton.setEnabled(false);
okButton.setName("okButton"); // NOI18N
okButton.addActionListener(formListener);
cancelButton.setText("Cancel");
cancelButton.setName("cancelButton"); // NOI18N
cancelButton.addActionListener(formListener);
jScrollPane1.setName("jScrollPane1"); // NOI18N
jTextPane1.setContentType("text/html");
jTextPane1.setEditable(false);
jTextPane1.setText("\r\n \r\n\r\n \r\n \r\n \r\n Allows selecting an Application to execute within the preview window of the theme view when\ncreating a theme for a specific Application. The preview might not reflect the full set of changes \nfrom the theme but would provide a good estimate for a designer. This application can also expose\nadditional custom components to the GUI designer view simply by creating valid Codename One component\nsubclasses with default constructors.\r\n
\r\n \n The picked Application MUST NOT be obfuscated, this allows the Codename One Designer to replace the \nApplications CodenameOne version with its own. \n
\n \n To debug pick Application run the Codename One Designer with a console or from command line and look at the\nerrors printed out when opening a theme.\n
\n \r\n\r\n"); // NOI18N
jTextPane1.setName("jTextPane1"); // NOI18N
jScrollPane1.setViewportView(jTextPane1);
org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(layout.createSequentialGroup()
.addContainerGap()
.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(jLabel2)
.add(jLabel3))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(midletPicker, 0, 274, Short.MAX_VALUE)
.add(jarFile, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 274, Short.MAX_VALUE)
.add(layout.createSequentialGroup()
.add(okButton)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(cancelButton)))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(pickJarFile)
.addContainerGap())
.add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 452, Short.MAX_VALUE)
);
layout.linkSize(new java.awt.Component[] {cancelButton, okButton}, org.jdesktop.layout.GroupLayout.HORIZONTAL);
layout.setVerticalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(layout.createSequentialGroup()
.addContainerGap()
.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(jLabel2)
.add(jarFile, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.add(pickJarFile))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(jLabel3)
.add(midletPicker, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(okButton)
.add(cancelButton))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 247, Short.MAX_VALUE))
);
}
// Code for dispatching events from components to event handlers.
private class FormListener implements java.awt.event.ActionListener {
FormListener() {}
public void actionPerformed(java.awt.event.ActionEvent evt) {
if (evt.getSource() == pickJarFile) {
PickMIDlet.this.pickJarFileActionPerformed(evt);
}
else if (evt.getSource() == okButton) {
PickMIDlet.this.okButtonActionPerformed(evt);
}
else if (evt.getSource() == cancelButton) {
PickMIDlet.this.cancelButtonActionPerformed(evt);
}
}
}// //GEN-END:initComponents
private void updateMIDletList() {
String j = jarFile.getText();
if(j != null && j.length() > 0) {
File file = new File(j);
if(file.exists() && file.isFile()) {
try {
JarFile zip = new JarFile(file);
Attributes m = zip.getManifest().getMainAttributes();
Vector v = new Vector();
for (int i = 1 ; m.getValue("MIDlet-" + i) != null ; i++) {
v.addElement(m.getValue("MIDlet-" + i));
}
midletPicker.setModel(new DefaultComboBoxModel(v));
} catch (IOException ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(this, "An IO Error occured while accessing\n" +
"the MIDlet JAR:\n" + ex.getMessage(), "IO Error", JOptionPane.ERROR_MESSAGE);
}
}
}
}
private void selectFile(JTextField field, String type) {
JFileChooser c = ResourceEditorView.createFileChooser("*" + type, type);
if(JFileChooser.APPROVE_OPTION == c.showDialog(this, "Select")) {
File f = c.getSelectedFile();
field.setText(f.getAbsolutePath());
Preferences.userNodeForPackage(ResourceEditorView.class).put("lastDir", f.getParentFile().getAbsolutePath());
}
updateMIDletList();
if(midletPicker.getModel().getSize() > 0) {
midletPicker.setSelectedIndex(0);
}
updateOKEnabled();
}
private void updateOKEnabled() {
if(new File(jarFile.getText()).exists()) {
okButton.setEnabled(true);
}
}
private void pickJarFileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pickJarFileActionPerformed
selectFile(jarFile, ".jar");
}//GEN-LAST:event_pickJarFileActionPerformed
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
SwingUtilities.windowForComponent(this).dispose();
Preferences pref = Preferences.userNodeForPackage(ResourceEditorView.class);
pref.put("jar", jarFile.getText());
pref.put("midlet", (String)midletPicker.getSelectedItem());
}//GEN-LAST:event_okButtonActionPerformed
private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
SwingUtilities.windowForComponent(this).dispose();
}//GEN-LAST:event_cancelButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton cancelButton;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTextPane jTextPane1;
private javax.swing.JTextField jarFile;
private javax.swing.JComboBox midletPicker;
private javax.swing.JButton okButton;
private javax.swing.JButton pickJarFile;
// End of variables declaration//GEN-END:variables
}