summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/gui/ClassSelector.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/cuchaz/enigma/gui/ClassSelector.java')
-rw-r--r--src/cuchaz/enigma/gui/ClassSelector.java181
1 files changed, 181 insertions, 0 deletions
diff --git a/src/cuchaz/enigma/gui/ClassSelector.java b/src/cuchaz/enigma/gui/ClassSelector.java
new file mode 100644
index 0000000..338ad80
--- /dev/null
+++ b/src/cuchaz/enigma/gui/ClassSelector.java
@@ -0,0 +1,181 @@
1package cuchaz.enigma.gui;
2
3import java.awt.event.MouseAdapter;
4import java.awt.event.MouseEvent;
5import java.util.Collection;
6import java.util.Collections;
7import java.util.Comparator;
8import java.util.List;
9import java.util.Map;
10
11import javax.swing.JTree;
12import javax.swing.tree.DefaultMutableTreeNode;
13import javax.swing.tree.DefaultTreeModel;
14import javax.swing.tree.TreePath;
15
16import com.beust.jcommander.internal.Lists;
17import com.beust.jcommander.internal.Maps;
18import com.google.common.collect.ArrayListMultimap;
19import com.google.common.collect.Multimap;
20
21import cuchaz.enigma.mapping.ClassEntry;
22
23public class ClassSelector extends JTree
24{
25 private static final long serialVersionUID = -7632046902384775977L;
26
27 public interface ClassSelectionListener
28 {
29 void onSelectClass( ClassEntry classEntry );
30 }
31
32 public static Comparator<ClassEntry> ObfuscatedClassEntryComparator;
33 public static Comparator<ClassEntry> DeobfuscatedClassEntryComparator;
34
35 static
36 {
37 ObfuscatedClassEntryComparator = new Comparator<ClassEntry>( )
38 {
39 @Override
40 public int compare( ClassEntry a, ClassEntry b )
41 {
42 if( a.getName().length() != b.getName().length() )
43 {
44 return a.getName().length() - b.getName().length();
45 }
46 return a.getName().compareTo( b.getName() );
47 }
48 };
49
50 DeobfuscatedClassEntryComparator = new Comparator<ClassEntry>( )
51 {
52 @Override
53 public int compare( ClassEntry a, ClassEntry b )
54 {
55 return a.getName().compareTo( b.getName() );
56 }
57 };
58 }
59
60 private ClassSelectionListener m_listener;
61 private Comparator<ClassEntry> m_comparator;
62
63 public ClassSelector( Comparator<ClassEntry> comparator )
64 {
65 m_comparator = comparator;
66
67 // configure the tree control
68 setRootVisible( false );
69 setShowsRootHandles( false );
70 setModel( null );
71
72 // hook events
73 addMouseListener( new MouseAdapter()
74 {
75 @Override
76 public void mouseClicked( MouseEvent event )
77 {
78 if( m_listener != null && event.getClickCount() == 2 )
79 {
80 // get the selected node
81 TreePath path = getSelectionPath();
82 if( path != null && path.getLastPathComponent() instanceof ClassSelectorClassNode )
83 {
84 ClassSelectorClassNode node = (ClassSelectorClassNode)path.getLastPathComponent();
85 m_listener.onSelectClass( node.getClassEntry() );
86 }
87 }
88 }
89 } );
90
91 // init defaults
92 m_listener = null;
93 }
94
95 public void setListener( ClassSelectionListener val )
96 {
97 m_listener = val;
98 }
99
100 public void setClasses( Collection<ClassEntry> classEntries )
101 {
102 if( classEntries == null )
103 {
104 setModel( null );
105 return;
106 }
107
108 // build the package names
109 Map<String,ClassSelectorPackageNode> packages = Maps.newHashMap();
110 for( ClassEntry classEntry : classEntries )
111 {
112 packages.put( classEntry.getPackageName(), null );
113 }
114
115 // sort the packages
116 List<String> sortedPackageNames = Lists.newArrayList( packages.keySet() );
117 Collections.sort( sortedPackageNames, new Comparator<String>( )
118 {
119 @Override
120 public int compare( String a, String b )
121 {
122 // I can never keep this rule straight when writing these damn things...
123 // a < b => -1, a == b => 0, a > b => +1
124
125 String[] aparts = a.split( "/" );
126 String[] bparts = b.split( "/" );
127 for( int i=0; true; i++ )
128 {
129 if( i >= aparts.length )
130 {
131 return -1;
132 }
133 else if( i >= bparts.length )
134 {
135 return 1;
136 }
137
138 int result = aparts[i].compareTo( bparts[i] );
139 if( result != 0 )
140 {
141 return result;
142 }
143 }
144 }
145 } );
146
147 // create the root node and the package nodes
148 DefaultMutableTreeNode root = new DefaultMutableTreeNode();
149 for( String packageName : sortedPackageNames )
150 {
151 ClassSelectorPackageNode node = new ClassSelectorPackageNode( packageName );
152 packages.put( packageName, node );
153 root.add( node );
154 }
155
156 // put the classes into packages
157 Multimap<String,ClassEntry> packagedClassEntries = ArrayListMultimap.create();
158 for( ClassEntry classEntry : classEntries )
159 {
160 packagedClassEntries.put( classEntry.getPackageName(), classEntry );
161 }
162
163 // build the class nodes
164 for( String packageName : packagedClassEntries.keySet() )
165 {
166 // sort the class entries
167 List<ClassEntry> classEntriesInPackage = Lists.newArrayList( packagedClassEntries.get( packageName ) );
168 Collections.sort( classEntriesInPackage, m_comparator );
169
170 // create the nodes in order
171 for( ClassEntry classEntry : classEntriesInPackage )
172 {
173 ClassSelectorPackageNode node = packages.get( packageName );
174 node.add( new ClassSelectorClassNode( classEntry ) );
175 }
176 }
177
178 // finally, update the tree control
179 setModel( new DefaultTreeModel( root ) );
180 }
181}