diff --git a/jode/jode/swingui/Main.java b/jode/jode/swingui/Main.java new file mode 100644 index 0000000..43e0204 --- /dev/null +++ b/jode/jode/swingui/Main.java @@ -0,0 +1,170 @@ +package jode.swingui; +import jode.Decompiler; +import jode.JodeEnvironment; +import jode.decompiler.TabbedPrintWriter; +import com.sun.java.swing.*; +import com.sun.java.swing.event.*; +import com.sun.java.swing.tree.*; +import java.awt.*; +import java.awt.event.*; +import java.io.*; + +public class MainWindow + implements ActionListener, Runnable, TreeSelectionListener { + JTree classTree; + PackagesTreeModel classModel; + TextArea sourcecodeArea, errorArea; + String classpath, lastClassName; + Thread decompileThread; + + public MainWindow(Container frame) { + frame.setLayout(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 1; + c.gridheight = 2; + c.weightx = 0.5; + c.weighty = 1.0; + c.fill = c.BOTH; + classModel = new PackagesTreeModel(); + classTree = new JTree(classModel); + classTree.setRootVisible(false); + DefaultTreeSelectionModel selModel = new DefaultTreeSelectionModel(); + selModel.setSelectionMode(selModel.SINGLE_TREE_SELECTION); + classTree.setSelectionModel(selModel); + classTree.addTreeSelectionListener(this); + JScrollPane sp = new JScrollPane(); + sp.getViewport().add(classTree); + frame.add(sp, c); + c.gridx = 1; + c.gridy = 0; + c.gridwidth = 1; + c.gridheight = 1; + c.weightx = 1.0; + c.weighty = 1.0; + c.fill = c.BOTH; + sourcecodeArea = new TextArea(20, 80); + frame.add(sourcecodeArea, c); + c.gridx = 1; + c.gridy = 1; + c.gridwidth = 1; + c.gridheight = 1; + c.weightx = 1.0; + c.weighty = 0.0; + c.fill = c.BOTH; + errorArea = new TextArea(3, 80); + frame.add(errorArea, c); + Decompiler.err = new PrintStream(new AreaOutputStream(errorArea)); + } + + public void setClasspath(String classpath) { + this.classpath = classpath; + } + + public synchronized void valueChanged(TreeSelectionEvent e) { + if (decompileThread != null) + return; + TreePath path = e.getNewLeadSelectionPath(); + if (path == null) + return; + Object node = path.getLastPathComponent(); + if (node != null && classModel.isLeaf(node)) { + lastClassName = classModel.getFullName(node); + decompileThread = new Thread(this); + sourcecodeArea.setText("Please wait, while decompiling...\n"); + decompileThread.start(); + } + } + + public synchronized void actionPerformed(ActionEvent e) { + if (e.getSource() == classTree && decompileThread == null) { +// startButton.setEnabled(false); + decompileThread = new Thread(this); + sourcecodeArea.setText("Please wait, while decompiling...\n"); + decompileThread.start(); +// } else if (e.getSource() == saveButton) { +// if (frame == null) +// frame = new Frame(); //XXX +// FileDialog fd = new FileDialog(frame, +// "Save decompiled code", +// FileDialog.SAVE); +// fd.setFile(lastClassName.substring +// (lastClassName.lastIndexOf('.')+1).concat(".java")); +// fd.show(); +// String fileName = fd.getFile(); +// if (fileName == null) +// return; +// try { +// File f = new File(new File(fd.getDirectory()), fileName); +// FileWriter out = new FileWriter(f); +// out.write(sourcecodeArea.getText()); +// out.close(); +// } catch (IOException ex) { +// errorArea.setText(""); +// Decompiler.err.println("Couldn't write to file " +// + fileName + ": "); +// ex.printStackTrace(Decompiler.err); +// } + } + } + + public class AreaOutputStream extends OutputStream { + private TextArea area; + + public AreaOutputStream(TextArea a) { + area = a; + } + + public void write(int b) throws IOException { + area.append(String.valueOf((byte)b)); + } + + public void write(byte[] b, int off, int len) throws IOException { + area.append(new String(b, off, len)); + } + } + + public void run() { +// Decompiler.isVerbose = verboseCheck.getState(); +// Decompiler.prettyLocals = prettyCheck.getState(); + errorArea.setText(""); +// saveButton.setEnabled(false); + + String cp = classpath; + cp = cp.replace(':', jode.bytecode.SearchPath.protocolSeparator); + cp = cp.replace(',', File.pathSeparatorChar); + JodeEnvironment env = new JodeEnvironment(cp); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + try { + TabbedPrintWriter writer = new TabbedPrintWriter(out); + env.doClass(lastClassName, writer); + sourcecodeArea.setText(out.toString()); +// saveButton.setEnabled(true); + } catch (Throwable t) { + sourcecodeArea.setText("Didn't succeed.\n" + +"Check the below area for more info."); + t.printStackTrace(); + } finally { + synchronized(this) { + decompileThread = null; +// startButton.setEnabled(true); + } + } + } + + public static void main(String[] params) { + JFrame frame = new JFrame(Decompiler.copyright); + String cp = System.getProperty("java.class.path"); + if (cp != null) + jode.bytecode.ClassInfo.setClassPath(cp); + + MainWindow win = new MainWindow(frame.getContentPane()); + if (cp != null) + win.setClasspath(cp.replace(File.pathSeparatorChar, ',')); + + frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + frame.pack(); + frame.show(); + } +} diff --git a/jode/jode/swingui/PackagesTreeModel.java b/jode/jode/swingui/PackagesTreeModel.java new file mode 100644 index 0000000..d49933a --- /dev/null +++ b/jode/jode/swingui/PackagesTreeModel.java @@ -0,0 +1,97 @@ +package jode.swingui; +import jode.bytecode.ClassInfo; +import com.sun.java.swing.tree.TreeModel; +import com.sun.java.swing.tree.TreePath; +import com.sun.java.swing.event.TreeModelListener; +import java.util.*; + +public class PackagesTreeModel implements TreeModel { + Hashtable cachedChildrens = new Hashtable(); + + class TreeElement { + String fullName; + String name; + + public TreeElement(String prefix, String name) { + this.fullName = prefix+name; + this.name = name; + } + + public String getFullName() { + return fullName; + } + + public String toString() { + return name; + } + + public boolean equals(Object o) { + return (o instanceof TreeElement) + && fullName == ((TreeElement)o).fullName; + } + + public int hashCode() { + return fullName.hashCode(); + } + } + + TreeElement root = new TreeElement("",""); + + public TreeElement[] getChildrens(TreeElement parent) { + TreeElement[] result = + (TreeElement[]) cachedChildrens.get(parent); + if (result == null) { + Vector v = new Vector(); + String prefix = parent == root ? "" : parent.getFullName() + "."; + Enumeration enum = + ClassInfo.getClassesAndPackages(parent.getFullName()); + while (enum.hasMoreElements()) { + v.addElement(new TreeElement(prefix, (String)enum.nextElement())); + } + result = new TreeElement[v.size()]; + v.copyInto(result); + cachedChildrens.put(parent, result); + } + return result; + } + + public void addTreeModelListener(TreeModelListener l) { + // we never change + } + public void removeTreeModelListener(TreeModelListener l) { + // we never change + } + public void valueForPathChanged(TreePath path, Object newValue) { + // we don't allow values + } + + public Object getChild(Object parent, int index) { + return getChildrens((TreeElement) parent)[index]; + } + + public int getChildCount(Object parent) { + return getChildrens((TreeElement) parent).length; + } + + public int getIndexOfChild(Object parent, Object child) { + TreeElement[] childrens = getChildrens((TreeElement) parent); + for (int i=0; i< childrens.length; i++) { + if (childrens[i] == child) + return i; + } + throw new NoSuchElementException + (((TreeElement)parent).getFullName() + "." + child); + } + + public Object getRoot() { + return root; + } + + public boolean isLeaf(Object node) { + return !ClassInfo.isPackage(((TreeElement) node).getFullName()); + } + + public String getFullName(Object node) { + return ((TreeElement) node).getFullName(); + } +}