diff options
| -rw-r--r-- | src/cuchaz/enigma/Controller.java | 83 | ||||
| -rw-r--r-- | src/cuchaz/enigma/Deobfuscator.java | 5 | ||||
| -rw-r--r-- | src/cuchaz/enigma/Main.java | 33 | ||||
| -rw-r--r-- | src/cuchaz/enigma/analysis/SourceIndex.java | 30 | ||||
| -rw-r--r-- | src/cuchaz/enigma/gui/ClassSelectionListener.java (renamed from src/cuchaz/enigma/gui/ClassSelectionHandler.java) | 2 | ||||
| -rw-r--r-- | src/cuchaz/enigma/gui/Gui.java | 228 | ||||
| -rw-r--r-- | src/cuchaz/enigma/gui/RenameListener.java | 18 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/ArgumentEntry.java | 3 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/ClassEntry.java | 3 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/Entry.java | 16 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/FieldEntry.java | 3 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/MethodEntry.java | 3 |
12 files changed, 362 insertions, 65 deletions
diff --git a/src/cuchaz/enigma/Controller.java b/src/cuchaz/enigma/Controller.java new file mode 100644 index 00000000..debc5e38 --- /dev/null +++ b/src/cuchaz/enigma/Controller.java | |||
| @@ -0,0 +1,83 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * Copyright (c) 2014 Jeff Martin. | ||
| 3 | * All rights reserved. This program and the accompanying materials | ||
| 4 | * are made available under the terms of the GNU Public License v3.0 | ||
| 5 | * which accompanies this distribution, and is available at | ||
| 6 | * http://www.gnu.org/licenses/gpl.html | ||
| 7 | * | ||
| 8 | * Contributors: | ||
| 9 | * Jeff Martin - initial API and implementation | ||
| 10 | ******************************************************************************/ | ||
| 11 | package cuchaz.enigma; | ||
| 12 | |||
| 13 | import javax.swing.event.CaretEvent; | ||
| 14 | import javax.swing.event.CaretListener; | ||
| 15 | |||
| 16 | import cuchaz.enigma.analysis.Analyzer; | ||
| 17 | import cuchaz.enigma.analysis.SourceIndex; | ||
| 18 | import cuchaz.enigma.gui.ClassSelectionListener; | ||
| 19 | import cuchaz.enigma.gui.Gui; | ||
| 20 | import cuchaz.enigma.gui.RenameListener; | ||
| 21 | import cuchaz.enigma.mapping.Entry; | ||
| 22 | |||
| 23 | public class Controller implements ClassSelectionListener, CaretListener, RenameListener | ||
| 24 | { | ||
| 25 | private Deobfuscator m_deobfuscator; | ||
| 26 | private Gui m_gui; | ||
| 27 | private SourceIndex m_index; | ||
| 28 | |||
| 29 | public Controller( Deobfuscator deobfuscator, Gui gui ) | ||
| 30 | { | ||
| 31 | m_deobfuscator = deobfuscator; | ||
| 32 | m_gui = gui; | ||
| 33 | m_index = null; | ||
| 34 | |||
| 35 | // update GUI | ||
| 36 | gui.setTitle( deobfuscator.getJarName() ); | ||
| 37 | gui.setObfClasses( deobfuscator.getObfuscatedClasses() ); | ||
| 38 | |||
| 39 | // handle events | ||
| 40 | gui.setClassSelectionListener( this ); | ||
| 41 | gui.setCaretListener( this ); | ||
| 42 | gui.setRenameListener( this ); | ||
| 43 | } | ||
| 44 | |||
| 45 | @Override | ||
| 46 | public void classSelected( final ClassFile classFile ) | ||
| 47 | { | ||
| 48 | m_gui.setSource( "(deobfuscating...)" ); | ||
| 49 | |||
| 50 | // run the deobfuscator in a separate thread so we don't block the GUI event queue | ||
| 51 | new Thread( ) | ||
| 52 | { | ||
| 53 | @Override | ||
| 54 | public void run( ) | ||
| 55 | { | ||
| 56 | // deobfuscate the bytecode | ||
| 57 | String source = m_deobfuscator.getSource( classFile ); | ||
| 58 | m_gui.setSource( source ); | ||
| 59 | |||
| 60 | // index the source file | ||
| 61 | m_index = Analyzer.analyze( classFile.getName(), source ); | ||
| 62 | m_gui.highlightTokens( m_index.tokens() ); | ||
| 63 | } | ||
| 64 | }.start(); | ||
| 65 | } | ||
| 66 | |||
| 67 | @Override | ||
| 68 | public void caretUpdate( CaretEvent event ) | ||
| 69 | { | ||
| 70 | if( m_index != null ) | ||
| 71 | { | ||
| 72 | int pos = event.getDot(); | ||
| 73 | m_gui.showEntry( m_index.getEntry( pos ) ); | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | @Override | ||
| 78 | public void rename( Entry entry, String newName ) | ||
| 79 | { | ||
| 80 | // TEMP | ||
| 81 | System.out.println( "Rename " + entry + " to " + newName ); | ||
| 82 | } | ||
| 83 | } | ||
diff --git a/src/cuchaz/enigma/Deobfuscator.java b/src/cuchaz/enigma/Deobfuscator.java index 83a21719..97c57505 100644 --- a/src/cuchaz/enigma/Deobfuscator.java +++ b/src/cuchaz/enigma/Deobfuscator.java | |||
| @@ -62,6 +62,11 @@ public class Deobfuscator | |||
| 62 | m_settings.setShowSyntheticMembers( true ); | 62 | m_settings.setShowSyntheticMembers( true ); |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | public String getJarName( ) | ||
| 66 | { | ||
| 67 | return m_file.getName(); | ||
| 68 | } | ||
| 69 | |||
| 65 | public List<ClassFile> getObfuscatedClasses( ) | 70 | public List<ClassFile> getObfuscatedClasses( ) |
| 66 | { | 71 | { |
| 67 | List<ClassFile> classes = new ArrayList<ClassFile>(); | 72 | List<ClassFile> classes = new ArrayList<ClassFile>(); |
diff --git a/src/cuchaz/enigma/Main.java b/src/cuchaz/enigma/Main.java index e08c16ed..4842e208 100644 --- a/src/cuchaz/enigma/Main.java +++ b/src/cuchaz/enigma/Main.java | |||
| @@ -12,9 +12,6 @@ package cuchaz.enigma; | |||
| 12 | 12 | ||
| 13 | import java.io.File; | 13 | import java.io.File; |
| 14 | 14 | ||
| 15 | import cuchaz.enigma.analysis.Analyzer; | ||
| 16 | import cuchaz.enigma.analysis.SourceIndex; | ||
| 17 | import cuchaz.enigma.gui.ClassSelectionHandler; | ||
| 18 | import cuchaz.enigma.gui.Gui; | 15 | import cuchaz.enigma.gui.Gui; |
| 19 | 16 | ||
| 20 | public class Main | 17 | public class Main |
| @@ -28,36 +25,10 @@ public class Main | |||
| 28 | private static void startGui( ) | 25 | private static void startGui( ) |
| 29 | throws Exception | 26 | throws Exception |
| 30 | { | 27 | { |
| 31 | final Gui gui = new Gui(); | ||
| 32 | |||
| 33 | // settings | 28 | // settings |
| 34 | final File jarFile = new File( "/home/jeff/.minecraft/versions/1.7.10/1.7.10.jar" ); | 29 | final File jarFile = new File( "/home/jeff/.minecraft/versions/1.7.10/1.7.10.jar" ); |
| 35 | gui.setTitle( jarFile.getName() ); | ||
| 36 | |||
| 37 | // init the deobfuscator | ||
| 38 | final Deobfuscator deobfuscator = new Deobfuscator( jarFile ); | ||
| 39 | gui.setObfClasses( deobfuscator.getObfuscatedClasses() ); | ||
| 40 | 30 | ||
| 41 | // handle events | 31 | // start the GUI and tie it to the deobfuscator |
| 42 | gui.setClassSelectionHandler( new ClassSelectionHandler( ) | 32 | new Controller( new Deobfuscator( jarFile ), new Gui() ); |
| 43 | { | ||
| 44 | @Override | ||
| 45 | public void classSelected( final ClassFile classFile ) | ||
| 46 | { | ||
| 47 | gui.setSource( "(deobfuscating...)" ); | ||
| 48 | |||
| 49 | // run the deobfuscator in a separate thread so we don't block the GUI event queue | ||
| 50 | new Thread( ) | ||
| 51 | { | ||
| 52 | @Override | ||
| 53 | public void run( ) | ||
| 54 | { | ||
| 55 | String source = deobfuscator.getSource( classFile ); | ||
| 56 | SourceIndex index = Analyzer.analyze( classFile.getName(), source ); | ||
| 57 | gui.setSource( source, index ); | ||
| 58 | } | ||
| 59 | }.start(); | ||
| 60 | } | ||
| 61 | } ); | ||
| 62 | } | 33 | } |
| 63 | } | 34 | } |
diff --git a/src/cuchaz/enigma/analysis/SourceIndex.java b/src/cuchaz/enigma/analysis/SourceIndex.java index a4b5329b..ee92d1ed 100644 --- a/src/cuchaz/enigma/analysis/SourceIndex.java +++ b/src/cuchaz/enigma/analysis/SourceIndex.java | |||
| @@ -19,10 +19,12 @@ import jsyntaxpane.Token; | |||
| 19 | import com.google.common.collect.BiMap; | 19 | import com.google.common.collect.BiMap; |
| 20 | import com.google.common.collect.HashBiMap; | 20 | import com.google.common.collect.HashBiMap; |
| 21 | 21 | ||
| 22 | public class SourceIndex implements Iterable<Map.Entry<Object,Token>> | 22 | import cuchaz.enigma.mapping.Entry; |
| 23 | |||
| 24 | public class SourceIndex implements Iterable<Map.Entry<Entry,Token>> | ||
| 23 | { | 25 | { |
| 24 | private BiMap<Object,Token> m_entryToToken; | 26 | private BiMap<Entry,Token> m_entryToToken; |
| 25 | private BiMap<Token,Object> m_tokenToEntry; | 27 | private BiMap<Token,Entry> m_tokenToEntry; |
| 26 | 28 | ||
| 27 | public SourceIndex( ) | 29 | public SourceIndex( ) |
| 28 | { | 30 | { |
| @@ -30,12 +32,12 @@ public class SourceIndex implements Iterable<Map.Entry<Object,Token>> | |||
| 30 | m_tokenToEntry = m_entryToToken.inverse(); | 32 | m_tokenToEntry = m_entryToToken.inverse(); |
| 31 | } | 33 | } |
| 32 | 34 | ||
| 33 | public void add( Object entry, Token token ) | 35 | public void add( Entry entry, Token token ) |
| 34 | { | 36 | { |
| 35 | m_entryToToken.put( entry, token ); | 37 | m_entryToToken.put( entry, token ); |
| 36 | } | 38 | } |
| 37 | 39 | ||
| 38 | public Iterator<Map.Entry<Object,Token>> iterator( ) | 40 | public Iterator<Map.Entry<Entry,Token>> iterator( ) |
| 39 | { | 41 | { |
| 40 | return m_entryToToken.entrySet().iterator(); | 42 | return m_entryToToken.entrySet().iterator(); |
| 41 | } | 43 | } |
| @@ -45,12 +47,26 @@ public class SourceIndex implements Iterable<Map.Entry<Object,Token>> | |||
| 45 | return m_entryToToken.values(); | 47 | return m_entryToToken.values(); |
| 46 | } | 48 | } |
| 47 | 49 | ||
| 48 | public Object getEntry( Token token ) | 50 | public Entry getEntry( Token token ) |
| 49 | { | 51 | { |
| 50 | return m_tokenToEntry.get( token ); | 52 | return m_tokenToEntry.get( token ); |
| 51 | } | 53 | } |
| 52 | 54 | ||
| 53 | public Object getToken( Object entry ) | 55 | public Entry getEntry( int pos ) |
| 56 | { | ||
| 57 | // linear search is fast enough for now | ||
| 58 | for( Map.Entry<Entry,Token> entry : this ) | ||
| 59 | { | ||
| 60 | Token token = entry.getValue(); | ||
| 61 | if( pos >= token.start && pos <= token.end() ) | ||
| 62 | { | ||
| 63 | return entry.getKey(); | ||
| 64 | } | ||
| 65 | } | ||
| 66 | return null; | ||
| 67 | } | ||
| 68 | |||
| 69 | public Token getToken( Entry entry ) | ||
| 54 | { | 70 | { |
| 55 | return m_entryToToken.get( entry ); | 71 | return m_entryToToken.get( entry ); |
| 56 | } | 72 | } |
diff --git a/src/cuchaz/enigma/gui/ClassSelectionHandler.java b/src/cuchaz/enigma/gui/ClassSelectionListener.java index a50cf6a3..4a2aa8d0 100644 --- a/src/cuchaz/enigma/gui/ClassSelectionHandler.java +++ b/src/cuchaz/enigma/gui/ClassSelectionListener.java | |||
| @@ -12,7 +12,7 @@ package cuchaz.enigma.gui; | |||
| 12 | 12 | ||
| 13 | import cuchaz.enigma.ClassFile; | 13 | import cuchaz.enigma.ClassFile; |
| 14 | 14 | ||
| 15 | public interface ClassSelectionHandler | 15 | public interface ClassSelectionListener |
| 16 | { | 16 | { |
| 17 | void classSelected( ClassFile classFile ); | 17 | void classSelected( ClassFile classFile ); |
| 18 | } | 18 | } |
diff --git a/src/cuchaz/enigma/gui/Gui.java b/src/cuchaz/enigma/gui/Gui.java index e0d53d83..d1a3cb21 100644 --- a/src/cuchaz/enigma/gui/Gui.java +++ b/src/cuchaz/enigma/gui/Gui.java | |||
| @@ -12,11 +12,20 @@ package cuchaz.enigma.gui; | |||
| 12 | 12 | ||
| 13 | import java.awt.BorderLayout; | 13 | import java.awt.BorderLayout; |
| 14 | import java.awt.Container; | 14 | import java.awt.Container; |
| 15 | import java.awt.Dimension; | ||
| 16 | import java.awt.FlowLayout; | ||
| 17 | import java.awt.Font; | ||
| 18 | import java.awt.GridLayout; | ||
| 19 | import java.awt.event.ActionEvent; | ||
| 20 | import java.awt.event.ActionListener; | ||
| 15 | import java.awt.event.MouseAdapter; | 21 | import java.awt.event.MouseAdapter; |
| 16 | import java.awt.event.MouseEvent; | 22 | import java.awt.event.MouseEvent; |
| 17 | import java.util.List; | 23 | import java.util.List; |
| 18 | import java.util.Vector; | 24 | import java.util.Vector; |
| 19 | 25 | ||
| 26 | import javax.swing.BorderFactory; | ||
| 27 | import javax.swing.BoxLayout; | ||
| 28 | import javax.swing.JButton; | ||
| 20 | import javax.swing.JEditorPane; | 29 | import javax.swing.JEditorPane; |
| 21 | import javax.swing.JFrame; | 30 | import javax.swing.JFrame; |
| 22 | import javax.swing.JLabel; | 31 | import javax.swing.JLabel; |
| @@ -24,14 +33,21 @@ import javax.swing.JList; | |||
| 24 | import javax.swing.JPanel; | 33 | import javax.swing.JPanel; |
| 25 | import javax.swing.JScrollPane; | 34 | import javax.swing.JScrollPane; |
| 26 | import javax.swing.JSplitPane; | 35 | import javax.swing.JSplitPane; |
| 36 | import javax.swing.JTextField; | ||
| 27 | import javax.swing.ListSelectionModel; | 37 | import javax.swing.ListSelectionModel; |
| 28 | import javax.swing.WindowConstants; | 38 | import javax.swing.WindowConstants; |
| 39 | import javax.swing.event.CaretListener; | ||
| 29 | import javax.swing.text.BadLocationException; | 40 | import javax.swing.text.BadLocationException; |
| 30 | 41 | ||
| 31 | import jsyntaxpane.DefaultSyntaxKit; | 42 | import jsyntaxpane.DefaultSyntaxKit; |
| 32 | import jsyntaxpane.Token; | 43 | import jsyntaxpane.Token; |
| 33 | import cuchaz.enigma.ClassFile; | 44 | import cuchaz.enigma.ClassFile; |
| 34 | import cuchaz.enigma.analysis.SourceIndex; | 45 | import cuchaz.enigma.analysis.SourceIndex; |
| 46 | import cuchaz.enigma.mapping.ArgumentEntry; | ||
| 47 | import cuchaz.enigma.mapping.ClassEntry; | ||
| 48 | import cuchaz.enigma.mapping.Entry; | ||
| 49 | import cuchaz.enigma.mapping.FieldEntry; | ||
| 50 | import cuchaz.enigma.mapping.MethodEntry; | ||
| 35 | 51 | ||
| 36 | public class Gui | 52 | public class Gui |
| 37 | { | 53 | { |
| @@ -42,11 +58,18 @@ public class Gui | |||
| 42 | private JList<ClassFile> m_obfClasses; | 58 | private JList<ClassFile> m_obfClasses; |
| 43 | private JList<ClassFile> m_deobfClasses; | 59 | private JList<ClassFile> m_deobfClasses; |
| 44 | private JEditorPane m_editor; | 60 | private JEditorPane m_editor; |
| 61 | private JPanel m_actionPanel; | ||
| 62 | private JPanel m_renamePanel; | ||
| 63 | private JLabel m_typeLabel; | ||
| 64 | private JTextField m_nameField; | ||
| 65 | private JButton m_renameButton; | ||
| 45 | 66 | ||
| 46 | // handlers | 67 | // listeners |
| 47 | private ClassSelectionHandler m_classSelectionHandler; | 68 | private ClassSelectionListener m_classSelectionListener; |
| 69 | private RenameListener m_renameListener; | ||
| 48 | 70 | ||
| 49 | private BoxHighlightPainter m_highlightPainter; | 71 | private BoxHighlightPainter m_highlightPainter; |
| 72 | private Entry m_selectedEntry; | ||
| 50 | 73 | ||
| 51 | public Gui( ) | 74 | public Gui( ) |
| 52 | { | 75 | { |
| @@ -66,12 +89,12 @@ public class Gui | |||
| 66 | { | 89 | { |
| 67 | if( event.getClickCount() == 2 ) | 90 | if( event.getClickCount() == 2 ) |
| 68 | { | 91 | { |
| 69 | if( m_classSelectionHandler != null ) | 92 | if( m_classSelectionListener != null ) |
| 70 | { | 93 | { |
| 71 | ClassFile selected = m_obfClasses.getSelectedValue(); | 94 | ClassFile selected = m_obfClasses.getSelectedValue(); |
| 72 | if( selected != null ) | 95 | if( selected != null ) |
| 73 | { | 96 | { |
| 74 | m_classSelectionHandler.classSelected( selected ); | 97 | m_classSelectionListener.classSelected( selected ); |
| 75 | } | 98 | } |
| 76 | } | 99 | } |
| 77 | } | 100 | } |
| @@ -93,6 +116,34 @@ public class Gui | |||
| 93 | deobfPanel.add( new JLabel( "De-obfuscated Classes" ), BorderLayout.NORTH ); | 116 | deobfPanel.add( new JLabel( "De-obfuscated Classes" ), BorderLayout.NORTH ); |
| 94 | deobfPanel.add( deobfScroller, BorderLayout.CENTER ); | 117 | deobfPanel.add( deobfScroller, BorderLayout.CENTER ); |
| 95 | 118 | ||
| 119 | // init action panel | ||
| 120 | m_actionPanel = new JPanel(); | ||
| 121 | m_actionPanel.setLayout( new BoxLayout( m_actionPanel, BoxLayout.Y_AXIS ) ); | ||
| 122 | m_actionPanel.setPreferredSize( new Dimension( 0, 120 ) ); | ||
| 123 | m_actionPanel.setBorder( BorderFactory.createTitledBorder( "Identifier Info" ) ); | ||
| 124 | m_nameField = new JTextField( 26 ); | ||
| 125 | m_renameButton = new JButton( "Rename" ); | ||
| 126 | m_renameButton.addActionListener( new ActionListener( ) | ||
| 127 | { | ||
| 128 | @Override | ||
| 129 | public void actionPerformed( ActionEvent event ) | ||
| 130 | { | ||
| 131 | if( m_renameListener != null && m_selectedEntry != null ) | ||
| 132 | { | ||
| 133 | m_renameListener.rename( m_selectedEntry, m_nameField.getText() ); | ||
| 134 | } | ||
| 135 | } | ||
| 136 | } ); | ||
| 137 | m_renamePanel = new JPanel(); | ||
| 138 | m_renamePanel.setLayout( new FlowLayout( FlowLayout.LEFT, 6, 0 ) ); | ||
| 139 | m_typeLabel = new JLabel( "LongName:", JLabel.RIGHT ); | ||
| 140 | // NOTE: this looks ridiculous, but it fixes the label size to the size of current text | ||
| 141 | m_typeLabel.setPreferredSize( m_typeLabel.getPreferredSize() ); | ||
| 142 | m_renamePanel.add( m_typeLabel ); | ||
| 143 | m_renamePanel.add( m_nameField ); | ||
| 144 | m_renamePanel.add( m_renameButton ); | ||
| 145 | clearEntry(); | ||
| 146 | |||
| 96 | // init editor | 147 | // init editor |
| 97 | DefaultSyntaxKit.initKit(); | 148 | DefaultSyntaxKit.initKit(); |
| 98 | m_editor = new JEditorPane(); | 149 | m_editor = new JEditorPane(); |
| @@ -102,17 +153,23 @@ public class Gui | |||
| 102 | 153 | ||
| 103 | // layout controls | 154 | // layout controls |
| 104 | JSplitPane splitLeft = new JSplitPane( JSplitPane.VERTICAL_SPLIT, true, obfPanel, deobfPanel ); | 155 | JSplitPane splitLeft = new JSplitPane( JSplitPane.VERTICAL_SPLIT, true, obfPanel, deobfPanel ); |
| 105 | JSplitPane splitMain = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT, true, splitLeft, sourceScroller ); | 156 | JPanel rightPanel = new JPanel(); |
| 157 | rightPanel.setLayout( new BorderLayout() ); | ||
| 158 | rightPanel.add( m_actionPanel, BorderLayout.NORTH ); | ||
| 159 | rightPanel.add( sourceScroller, BorderLayout.CENTER ); | ||
| 160 | JSplitPane splitMain = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT, true, splitLeft, rightPanel ); | ||
| 106 | pane.add( splitMain, BorderLayout.CENTER ); | 161 | pane.add( splitMain, BorderLayout.CENTER ); |
| 107 | 162 | ||
| 108 | // show the frame | 163 | // show the frame |
| 109 | pane.doLayout(); | 164 | pane.doLayout(); |
| 110 | m_frame.setSize( 800, 600 ); | 165 | m_frame.setSize( 800, 600 ); |
| 166 | m_frame.setMinimumSize( new Dimension( 640, 480 ) ); | ||
| 111 | m_frame.setVisible( true ); | 167 | m_frame.setVisible( true ); |
| 112 | m_frame.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE ); | 168 | m_frame.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE ); |
| 113 | 169 | ||
| 114 | // init handlers | 170 | // init listeners |
| 115 | m_classSelectionHandler = null; | 171 | m_classSelectionListener = null; |
| 172 | m_renameListener = null; | ||
| 116 | 173 | ||
| 117 | m_highlightPainter = new BoxHighlightPainter(); | 174 | m_highlightPainter = new BoxHighlightPainter(); |
| 118 | } | 175 | } |
| @@ -135,29 +192,156 @@ public class Gui | |||
| 135 | public void setSource( String source, SourceIndex index ) | 192 | public void setSource( String source, SourceIndex index ) |
| 136 | { | 193 | { |
| 137 | m_editor.setText( source ); | 194 | m_editor.setText( source ); |
| 138 | 195 | } | |
| 196 | |||
| 197 | public void highlightTokens( Iterable<Token> tokens ) | ||
| 198 | { | ||
| 139 | // remove any old highlighters | 199 | // remove any old highlighters |
| 140 | m_editor.getHighlighter().removeAllHighlights();; | 200 | m_editor.getHighlighter().removeAllHighlights(); |
| 141 | 201 | ||
| 142 | if( index != null ) | 202 | if( tokens == null ) |
| 143 | { | 203 | { |
| 144 | // color things based on the index | 204 | return; |
| 145 | for( Token token : index.tokens() ) | 205 | } |
| 206 | |||
| 207 | // color things based on the index | ||
| 208 | for( Token token : tokens ) | ||
| 209 | { | ||
| 210 | try | ||
| 146 | { | 211 | { |
| 147 | try | 212 | m_editor.getHighlighter().addHighlight( token.start, token.end(), m_highlightPainter ); |
| 148 | { | 213 | } |
| 149 | m_editor.getHighlighter().addHighlight( token.start, token.end(), m_highlightPainter ); | 214 | catch( BadLocationException ex ) |
| 150 | } | 215 | { |
| 151 | catch( BadLocationException ex ) | 216 | throw new IllegalArgumentException( ex ); |
| 152 | { | ||
| 153 | throw new Error( ex ); | ||
| 154 | } | ||
| 155 | } | 217 | } |
| 156 | } | 218 | } |
| 219 | |||
| 220 | redraw(); | ||
| 221 | } | ||
| 222 | |||
| 223 | public void setClassSelectionListener( ClassSelectionListener val ) | ||
| 224 | { | ||
| 225 | m_classSelectionListener = val; | ||
| 226 | } | ||
| 227 | |||
| 228 | public void setRenameListener( RenameListener val ) | ||
| 229 | { | ||
| 230 | m_renameListener = val; | ||
| 231 | } | ||
| 232 | |||
| 233 | public void setCaretListener( CaretListener listener ) | ||
| 234 | { | ||
| 235 | // remove any old listeners | ||
| 236 | for( CaretListener oldListener : m_editor.getCaretListeners() ) | ||
| 237 | { | ||
| 238 | m_editor.removeCaretListener( oldListener ); | ||
| 239 | } | ||
| 240 | |||
| 241 | m_editor.addCaretListener( listener ); | ||
| 242 | } | ||
| 243 | |||
| 244 | public void clearEntry( ) | ||
| 245 | { | ||
| 246 | m_actionPanel.removeAll(); | ||
| 247 | JLabel label = new JLabel( "No identifier selected" ); | ||
| 248 | unboldLabel( label ); | ||
| 249 | label.setHorizontalAlignment( JLabel.CENTER ); | ||
| 250 | m_actionPanel.add( label ); | ||
| 251 | |||
| 252 | redraw(); | ||
| 253 | } | ||
| 254 | |||
| 255 | public void showEntry( Entry entry ) | ||
| 256 | { | ||
| 257 | if( entry == null ) | ||
| 258 | { | ||
| 259 | clearEntry(); | ||
| 260 | return; | ||
| 261 | } | ||
| 262 | |||
| 263 | // layout the action panel | ||
| 264 | m_actionPanel.removeAll(); | ||
| 265 | m_actionPanel.add( m_renamePanel ); | ||
| 266 | m_nameField.setText( entry.getName() ); | ||
| 267 | |||
| 268 | // layout the dynamic section | ||
| 269 | JPanel dynamicPanel = new JPanel(); | ||
| 270 | dynamicPanel.setLayout( new GridLayout( 3, 1, 0, 0 ) ); | ||
| 271 | m_actionPanel.add( dynamicPanel ); | ||
| 272 | if( entry instanceof ClassEntry ) | ||
| 273 | { | ||
| 274 | showEntry( (ClassEntry)entry, dynamicPanel ); | ||
| 275 | } | ||
| 276 | else if( entry instanceof FieldEntry ) | ||
| 277 | { | ||
| 278 | showEntry( (FieldEntry)entry, dynamicPanel ); | ||
| 279 | } | ||
| 280 | else if( entry instanceof MethodEntry ) | ||
| 281 | { | ||
| 282 | showEntry( (MethodEntry)entry, dynamicPanel ); | ||
| 283 | } | ||
| 284 | else if( entry instanceof ArgumentEntry ) | ||
| 285 | { | ||
| 286 | showEntry( (ArgumentEntry)entry, dynamicPanel ); | ||
| 287 | } | ||
| 288 | else | ||
| 289 | { | ||
| 290 | throw new Error( "Unknown entry type: " + entry.getClass().getName() ); | ||
| 291 | } | ||
| 292 | |||
| 293 | redraw(); | ||
| 294 | } | ||
| 295 | |||
| 296 | public void showEntry( ClassEntry entry, JPanel panel ) | ||
| 297 | { | ||
| 298 | m_typeLabel.setText( "Class: " ); | ||
| 299 | } | ||
| 300 | |||
| 301 | public void showEntry( FieldEntry entry, JPanel panel ) | ||
| 302 | { | ||
| 303 | m_typeLabel.setText( "Field: " ); | ||
| 304 | addNameValue( panel, "Class", entry.getClassEntry().getName() ); | ||
| 305 | } | ||
| 306 | |||
| 307 | public void showEntry( MethodEntry entry, JPanel panel ) | ||
| 308 | { | ||
| 309 | m_typeLabel.setText( "Method: " ); | ||
| 310 | addNameValue( panel, "Class", entry.getClassEntry().getName() ); | ||
| 311 | addNameValue( panel, "Signature", entry.getSignature() ); | ||
| 312 | } | ||
| 313 | |||
| 314 | public void showEntry( ArgumentEntry entry, JPanel panel ) | ||
| 315 | { | ||
| 316 | m_typeLabel.setText( "Argument: " ); | ||
| 317 | addNameValue( panel, "Class", entry.getMethodEntry().getClassEntry().getName() ); | ||
| 318 | addNameValue( panel, "Method", entry.getMethodEntry().getName() ); | ||
| 319 | addNameValue( panel, "Index", Integer.toString( entry.getIndex() ) ); | ||
| 320 | } | ||
| 321 | |||
| 322 | private void addNameValue( JPanel container, String name, String value ) | ||
| 323 | { | ||
| 324 | JPanel panel = new JPanel(); | ||
| 325 | panel.setLayout( new FlowLayout( FlowLayout.LEFT, 6, 0 ) ); | ||
| 326 | container.add( panel ); | ||
| 327 | |||
| 328 | JLabel label = new JLabel( name + ":", JLabel.RIGHT ); | ||
| 329 | label.setPreferredSize( new Dimension( 80, label.getPreferredSize().height ) ); | ||
| 330 | panel.add( label ); | ||
| 331 | |||
| 332 | panel.add( unboldLabel( new JLabel( value, JLabel.LEFT ) ) ); | ||
| 333 | } | ||
| 334 | |||
| 335 | private JLabel unboldLabel( JLabel label ) | ||
| 336 | { | ||
| 337 | Font font = label.getFont(); | ||
| 338 | label.setFont( font.deriveFont( font.getStyle() & ~Font.BOLD ) ); | ||
| 339 | return label; | ||
| 157 | } | 340 | } |
| 158 | 341 | ||
| 159 | public void setClassSelectionHandler( ClassSelectionHandler val ) | 342 | private void redraw( ) |
| 160 | { | 343 | { |
| 161 | m_classSelectionHandler = val; | 344 | m_frame.validate(); |
| 345 | m_frame.repaint(); | ||
| 162 | } | 346 | } |
| 163 | } | 347 | } |
diff --git a/src/cuchaz/enigma/gui/RenameListener.java b/src/cuchaz/enigma/gui/RenameListener.java new file mode 100644 index 00000000..58cdadb0 --- /dev/null +++ b/src/cuchaz/enigma/gui/RenameListener.java | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * Copyright (c) 2014 Jeff Martin. | ||
| 3 | * All rights reserved. This program and the accompanying materials | ||
| 4 | * are made available under the terms of the GNU Public License v3.0 | ||
| 5 | * which accompanies this distribution, and is available at | ||
| 6 | * http://www.gnu.org/licenses/gpl.html | ||
| 7 | * | ||
| 8 | * Contributors: | ||
| 9 | * Jeff Martin - initial API and implementation | ||
| 10 | ******************************************************************************/ | ||
| 11 | package cuchaz.enigma.gui; | ||
| 12 | |||
| 13 | import cuchaz.enigma.mapping.Entry; | ||
| 14 | |||
| 15 | public interface RenameListener | ||
| 16 | { | ||
| 17 | void rename( Entry entry, String newName ); | ||
| 18 | } | ||
diff --git a/src/cuchaz/enigma/mapping/ArgumentEntry.java b/src/cuchaz/enigma/mapping/ArgumentEntry.java index 6c108d7c..dc3b4df7 100644 --- a/src/cuchaz/enigma/mapping/ArgumentEntry.java +++ b/src/cuchaz/enigma/mapping/ArgumentEntry.java | |||
| @@ -14,7 +14,7 @@ import java.io.Serializable; | |||
| 14 | 14 | ||
| 15 | import cuchaz.enigma.Util; | 15 | import cuchaz.enigma.Util; |
| 16 | 16 | ||
| 17 | public class ArgumentEntry implements Serializable | 17 | public class ArgumentEntry implements Entry, Serializable |
| 18 | { | 18 | { |
| 19 | private static final long serialVersionUID = 4472172468162696006L; | 19 | private static final long serialVersionUID = 4472172468162696006L; |
| 20 | 20 | ||
| @@ -52,6 +52,7 @@ public class ArgumentEntry implements Serializable | |||
| 52 | return m_index; | 52 | return m_index; |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | @Override | ||
| 55 | public String getName( ) | 56 | public String getName( ) |
| 56 | { | 57 | { |
| 57 | return m_name; | 58 | return m_name; |
diff --git a/src/cuchaz/enigma/mapping/ClassEntry.java b/src/cuchaz/enigma/mapping/ClassEntry.java index 7e78d4c0..3a757675 100644 --- a/src/cuchaz/enigma/mapping/ClassEntry.java +++ b/src/cuchaz/enigma/mapping/ClassEntry.java | |||
| @@ -13,7 +13,7 @@ package cuchaz.enigma.mapping; | |||
| 13 | import java.io.Serializable; | 13 | import java.io.Serializable; |
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | public class ClassEntry implements Serializable | 16 | public class ClassEntry implements Entry, Serializable |
| 17 | { | 17 | { |
| 18 | private static final long serialVersionUID = 4235460580973955811L; | 18 | private static final long serialVersionUID = 4235460580973955811L; |
| 19 | 19 | ||
| @@ -33,6 +33,7 @@ public class ClassEntry implements Serializable | |||
| 33 | m_name = className; | 33 | m_name = className; |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | @Override | ||
| 36 | public String getName( ) | 37 | public String getName( ) |
| 37 | { | 38 | { |
| 38 | return m_name; | 39 | return m_name; |
diff --git a/src/cuchaz/enigma/mapping/Entry.java b/src/cuchaz/enigma/mapping/Entry.java new file mode 100644 index 00000000..14435324 --- /dev/null +++ b/src/cuchaz/enigma/mapping/Entry.java | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * Copyright (c) 2014 Jeff Martin. | ||
| 3 | * All rights reserved. This program and the accompanying materials | ||
| 4 | * are made available under the terms of the GNU Public License v3.0 | ||
| 5 | * which accompanies this distribution, and is available at | ||
| 6 | * http://www.gnu.org/licenses/gpl.html | ||
| 7 | * | ||
| 8 | * Contributors: | ||
| 9 | * Jeff Martin - initial API and implementation | ||
| 10 | ******************************************************************************/ | ||
| 11 | package cuchaz.enigma.mapping; | ||
| 12 | |||
| 13 | public interface Entry | ||
| 14 | { | ||
| 15 | String getName( ); | ||
| 16 | } | ||
diff --git a/src/cuchaz/enigma/mapping/FieldEntry.java b/src/cuchaz/enigma/mapping/FieldEntry.java index 15a93520..25b665ab 100644 --- a/src/cuchaz/enigma/mapping/FieldEntry.java +++ b/src/cuchaz/enigma/mapping/FieldEntry.java | |||
| @@ -14,7 +14,7 @@ import java.io.Serializable; | |||
| 14 | 14 | ||
| 15 | import cuchaz.enigma.Util; | 15 | import cuchaz.enigma.Util; |
| 16 | 16 | ||
| 17 | public class FieldEntry implements Serializable | 17 | public class FieldEntry implements Entry, Serializable |
| 18 | { | 18 | { |
| 19 | private static final long serialVersionUID = 3004663582802885451L; | 19 | private static final long serialVersionUID = 3004663582802885451L; |
| 20 | 20 | ||
| @@ -41,6 +41,7 @@ public class FieldEntry implements Serializable | |||
| 41 | return m_classEntry; | 41 | return m_classEntry; |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | @Override | ||
| 44 | public String getName( ) | 45 | public String getName( ) |
| 45 | { | 46 | { |
| 46 | return m_name; | 47 | return m_name; |
diff --git a/src/cuchaz/enigma/mapping/MethodEntry.java b/src/cuchaz/enigma/mapping/MethodEntry.java index e71a4664..4afc099b 100644 --- a/src/cuchaz/enigma/mapping/MethodEntry.java +++ b/src/cuchaz/enigma/mapping/MethodEntry.java | |||
| @@ -14,7 +14,7 @@ import java.io.Serializable; | |||
| 14 | 14 | ||
| 15 | import cuchaz.enigma.Util; | 15 | import cuchaz.enigma.Util; |
| 16 | 16 | ||
| 17 | public class MethodEntry implements Serializable | 17 | public class MethodEntry implements Entry, Serializable |
| 18 | { | 18 | { |
| 19 | private static final long serialVersionUID = 4770915224467247458L; | 19 | private static final long serialVersionUID = 4770915224467247458L; |
| 20 | 20 | ||
| @@ -47,6 +47,7 @@ public class MethodEntry implements Serializable | |||
| 47 | return m_classEntry; | 47 | return m_classEntry; |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | @Override | ||
| 50 | public String getName( ) | 51 | public String getName( ) |
| 51 | { | 52 | { |
| 52 | return m_name; | 53 | return m_name; |