2009-11-08 Chris Toshok <toshok@ximian.com>
[moon.git] / tools / munxap / View.cs
blob6128f5f9578ac0dbd85e8811b9c1392c7658edcd
1 /*
2 * View.cs.
4 * Contact:
5 * Moonlight List (moonlight-list@lists.ximian.com)
7 * Copyright 2009 Novell, Inc. (http://www.novell.com)
9 * See the LICENSE file included with the distribution for details.
13 using GLib;
14 using Gtk;
15 using Mono.Cecil;
17 using System;
18 using System.Collections;
19 using System.Collections.Generic;
20 using System.Diagnostics;
21 using System.IO;
22 using System.Resources;
23 using System.Text;
26 abstract class View {
27 public ZipContent Content { get; private set; }
29 public View (ZipContent content)
31 Content = content;
33 public View ()
37 public abstract Widget GetView ();
40 class ViewText : View {
41 ScrolledWindow scrolled_window;
42 TextView view;
43 TextBuffer buffer;
44 string text;
46 public ViewText (ZipContent content) : base (content)
50 public ViewText (string text) : base (null)
52 if (text == null)
53 throw new ArgumentNullException ("text");
54 this.text = text;
57 public override Widget GetView ()
59 if (scrolled_window != null)
60 return scrolled_window;
62 buffer = new TextBuffer (new TextTagTable ());
63 buffer.Text = Text;
64 view = new TextView (buffer);
66 scrolled_window = new ScrolledWindow ();
67 scrolled_window.Add (view);
69 return scrolled_window;
72 public virtual string Text {
73 get {
74 if (text == null)
75 text = File.ReadAllText (Content.UnzippedFilename);
76 return text;
78 set {
79 text = value;
84 class ViewXaml : ViewText {
85 public ViewXaml (ZipContent content) : base (content) {}
88 class ViewImage : View {
89 ScrolledWindow scrolled_window;
90 Gdk.Pixbuf pixbuf;
91 Gtk.Image image;
93 public ViewImage (ZipContent content) : base (content)
97 public ViewImage (System.IO.Stream stream) : base (null)
99 pixbuf = new Gdk.Pixbuf (stream);
102 public override Widget GetView ()
104 if (scrolled_window != null)
105 return scrolled_window;
107 image = new Gtk.Image (pixbuf);
108 scrolled_window = new ScrolledWindow ();
109 scrolled_window.AddWithViewport (image);
111 return scrolled_window;
115 class ViewCode : View {
116 ListStore store;
117 TreeView tree;
118 ScrolledWindow scrolled_tree;
119 MethodDefinition method;
120 public ViewCode (MethodDefinition method)
122 this.method = method;
125 public override Widget GetView ()
127 if (scrolled_tree != null)
128 return scrolled_tree;
130 // Create ui
131 store = new ListStore (typeof (string), typeof (string), typeof (string));
132 tree = new TreeView ();
133 tree.Model = store;
134 tree.AppendColumn ("Offset", new CellRendererText (), "text", 0);
135 tree.AppendColumn ("Instruction", new CellRendererText (), "text", 1);
136 tree.AppendColumn ("Operand", new CellRendererText (), "text", 2);
137 tree.HeadersVisible = true;
138 scrolled_tree = new ScrolledWindow ();
139 scrolled_tree.Add (tree);
141 Mono.Cecil.Cil.MethodBody body = method.Body;
142 Mono.Cecil.Cil.Instruction instr;
143 if (body != null) {
144 for (int i = 0; i < body.Instructions.Count; i++) {
145 instr = body.Instructions [i];
147 store.AppendValues ("IL_" + instr.Offset.ToString ("0000"), instr.OpCode.ToString (), FormatOperand (instr.Operand));
150 return scrolled_tree;
153 string FormatOperand (object operand)
155 Mono.Cecil.Cil.Instruction instr;
157 if (operand == null)
158 return string.Empty;
160 instr = operand as Mono.Cecil.Cil.Instruction;
161 if (instr != null)
162 return "IL_" + instr.Offset.ToString ("0000");
164 return operand.ToString ();
170 class ViewResource : View {
171 VBox box;
172 ListStore store;
173 TreeView tree;
174 ScrolledWindow scrolled_tree;
176 Resource resource;
178 public ViewResource (Resource resource) : base ()
180 this.resource = resource;
183 public override Widget GetView ()
185 if (box != null)
186 return box;
188 // Create ui
189 box = new VBox (false, 10);
190 store = new ListStore (typeof (string), typeof (string), typeof (object));
191 tree = new TreeView ();
192 tree.Model = store;
193 tree.AppendColumn ("Name", new CellRendererText (), "text", 0);
194 tree.AppendColumn ("Type", new CellRendererText (), "text", 1);
195 tree.HeadersVisible = true;
196 tree.CursorChanged += HandleCursorChanged;
197 scrolled_tree = new ScrolledWindow ();
198 scrolled_tree.Add (tree);
199 box.PackStart (scrolled_tree, true, true, 0);
201 // Load resources
202 EmbeddedResource embed = resource as EmbeddedResource;
203 if (embed != null) {
204 using (MemoryStream stream = new MemoryStream (embed.Data)) {
205 using (ResourceReader reader = new ResourceReader (stream)) {
206 foreach (DictionaryEntry obj in reader) {
207 store.AppendValues (obj.Key.ToString (), obj.Value.GetType ().FullName, obj.Value);
211 } else {
212 Console.WriteLine ("Don't know how to handle a resource whose type is {0}", resource.GetType ().FullName);
215 return box;
218 void HandleCursorChanged (object sender, EventArgs e)
220 TreeSelection selection = tree.Selection;
221 TreeModel model;
222 TreeIter iter;
223 Value v;
224 string name, type;
225 object value;
226 View view = null;
228 if (!selection.GetSelected (out model, out iter))
229 return;
231 v = new Value ();
232 store.GetValue (iter, 0, ref v);
233 name = v.Val as string;
234 v = new Value ();
235 store.GetValue (iter, 1, ref v);
236 type = v.Val as string;
237 v = new Value ();
238 store.GetValue (iter, 2, ref v);
239 value = v.Val;
241 // Create a view based on what we got
243 switch (type) {
244 case "System.IO.MemoryStream":
245 MemoryStream stream = value as MemoryStream;
246 if (name.EndsWith (".xaml")) {
247 stream.Position = 0;
248 using (MemoryStream clone = new MemoryStream (stream.ToArray ())) {
249 using (StreamReader t = new StreamReader (clone)) {
250 view = new ViewText (t.ReadToEnd ());
253 } else if (name.EndsWith (".png") || name.EndsWith (".jpg")) {
254 using (MemoryStream clone = new MemoryStream (stream.ToArray ())) {
255 view = new ViewImage (clone);
257 } else {
258 Console.WriteLine ("Don't know what to do with a {0} in a {1}", name, type);
260 break;
261 case "System.String":
262 if (value != null)
263 view = new ViewText ((string) value);
264 break;
265 default:
266 Console.WriteLine ("Unhandled case: {0}", type);
267 break;
270 // Remove previous views and add the new one
272 while (box.Children.Length > 1)
273 box.Remove (box.Children [1]);
275 if (view != null) {
276 box.PackStart (view.GetView (), true, true, 0);
277 box.ShowAll ();
282 class ViewAssembly : View {
283 HBox box;
284 TreeStore store;
285 TreeView tree;
286 ScrolledWindow scrolled_tree;
287 AssemblyDefinition assembly;
289 static Gdk.Pixbuf classPixbuf, delegatePixbuf, enumPixbuf;
290 static Gdk.Pixbuf eventPixbuf, fieldPixbuf, interfacePixbuf;
291 static Gdk.Pixbuf methodPixbuf, namespacePixbuf, propertyPixbuf;
292 static Gdk.Pixbuf attributePixbuf, structPixbuf, assemblyPixbuf;
294 static ViewAssembly ()
296 System.Reflection.Assembly ta = typeof (ViewAssembly).Assembly;
297 classPixbuf = new Gdk.Pixbuf (ta, "c.gif");
298 delegatePixbuf = new Gdk.Pixbuf (ta, "d.gif");
299 enumPixbuf = new Gdk.Pixbuf (ta, "en.gif");
300 eventPixbuf = new Gdk.Pixbuf (ta, "e.gif");
301 fieldPixbuf = new Gdk.Pixbuf (ta, "f.gif");
302 interfacePixbuf = new Gdk.Pixbuf (ta, "i.gif");
303 methodPixbuf = new Gdk.Pixbuf (ta, "m.gif");
304 namespacePixbuf = new Gdk.Pixbuf (ta, "n.gif");
305 propertyPixbuf = new Gdk.Pixbuf (ta, "p.gif");
306 attributePixbuf = new Gdk.Pixbuf (ta, "r.gif");
307 structPixbuf = new Gdk.Pixbuf (ta, "s.gif");
308 assemblyPixbuf = new Gdk.Pixbuf (ta, "y.gif");
311 public ViewAssembly (ZipContent content) : base (content) {}
313 public override Widget GetView ()
315 Gtk.TreeIter iter;
316 string line;
318 if (box != null)
319 return box;
321 // Create ui
322 box = new HBox ();
323 store = new TreeStore (typeof (string), typeof (string), typeof (string), typeof (object), typeof (Gdk.Pixbuf));
324 tree = new TreeView ();
325 tree.Model = store;
326 tree.AppendColumn ("Icon", new CellRendererPixbuf (), "pixbuf", 4);
327 tree.AppendColumn ("Name", new CellRendererText (), "text", 0);
328 tree.AppendColumn ("Type", new CellRendererText (), "text", 1);
329 tree.AppendColumn ("Info", new CellRendererText (), "text", 2);
330 tree.HeadersVisible = true;
331 tree.CursorChanged += HandleCursorChanged;
332 scrolled_tree = new ScrolledWindow ();
333 scrolled_tree.Add (tree);
334 box.PackStart (scrolled_tree, true, true, 0);
336 if (assembly == null)
337 assembly = AssemblyFactory.GetAssembly (Content.UnzippedFilename);
339 // Load resources
340 // first get a list of resources in the assembly
341 iter = store.AppendValues ("Resources");
342 foreach (Mono.Cecil.Resource res in assembly.MainModule.Resources) {
343 store.AppendValues (iter, res.Name, "Resource", "", res);
346 // Load types
347 Gtk.TreeIter classes = store.AppendValues ("Classes");
348 foreach (TypeDefinition type in assembly.MainModule.Types) {
349 Gtk.TreeIter cl = store.AppendValues (classes, type.FullName, "Type", "", type, classPixbuf);
350 List<MethodDefinition> shown_methods = new List<MethodDefinition> ();
351 foreach (PropertyDefinition property in type.Properties) {
352 Gtk.TreeIter prop = store.AppendValues (cl, property.Name, "Property", "", property, propertyPixbuf);
353 if (property.GetMethod != null) {
354 store.AppendValues (prop, FormatMethod (property.GetMethod), "Getter", "", property.GetMethod, methodPixbuf);
355 shown_methods.Add (property.GetMethod);
357 if (property.SetMethod != null) {
358 store.AppendValues (prop, FormatMethod (property.SetMethod), "Setter", "", property.SetMethod, methodPixbuf);
359 shown_methods.Add (property.SetMethod);
362 foreach (EventDefinition ev in type.Events) {
363 Gtk.TreeIter evIter = store.AppendValues (cl, ev.Name, "Event", "", ev, eventPixbuf);
364 if (ev.AddMethod != null) {
365 store.AppendValues (evIter, FormatMethod (ev.AddMethod), "Adder", "", ev.AddMethod, methodPixbuf);
366 shown_methods.Add (ev.AddMethod);
368 if (ev.RemoveMethod != null) {
369 store.AppendValues (evIter, FormatMethod (ev.RemoveMethod), "Remover", "", ev.RemoveMethod, methodPixbuf);
370 shown_methods.Add (ev.RemoveMethod);
372 if (ev.InvokeMethod != null) {
373 store.AppendValues (evIter, FormatMethod (ev.InvokeMethod), "Invoker", "", ev.InvokeMethod, methodPixbuf);
374 shown_methods.Add (ev.InvokeMethod);
377 foreach (MethodDefinition method in type.Methods) {
378 if (shown_methods.Contains (method))
379 continue;
380 store.AppendValues (cl, FormatMethod (method), "Method", "", method, methodPixbuf);
382 foreach (MethodDefinition method in type.Constructors) {
383 store.AppendValues (cl, FormatMethod (method), "Constructor", "", method, methodPixbuf);
385 foreach (FieldDefinition field in type.Fields) {
386 store.AppendValues (cl, field.FieldType.Name + " " + field.Name, "Field", "", field, fieldPixbuf);
389 return box;
392 string FormatMethod (MethodDefinition method)
394 StringBuilder result = new StringBuilder ();
396 result.Append (method.ReturnType.ReturnType.Name);
397 result.Append (" ");
398 result.Append (method.Name);
399 result.Append ("(");
401 for (int i = 0; i < method.Parameters.Count - 1; i++) {
402 if (i > 0)
403 result.Append (", ");
404 result.Append (method.Parameters [i].ParameterType.Name);
405 result.Append (" ");
406 result.Append (method.Parameters [i].Name);
408 result.Append (")");
410 return result.ToString ();
413 void HandleCursorChanged (object sender, EventArgs e)
415 TreeSelection selection = tree.Selection;
416 TreeModel model;
417 TreeIter iter;
418 Value v;
419 string type, info;
420 View view = null;
422 if (!selection.GetSelected (out model, out iter))
423 return;
425 // Create a view based on what we got
427 v = new Value ();
428 store.GetValue (iter, 2, ref v);
429 info = v.Val as string;
430 v = new Value ();
431 store.GetValue (iter, 1, ref v);
432 type = v.Val as string;
434 switch (type) {
435 case "Class":
436 Console.WriteLine ("JB, We need your decompiler.");
437 break;
438 case "Resource":
439 Resource res;
440 v = new Value ();
441 store.GetValue (iter, 3, ref v);
442 res = v.Val as Resource;
443 if (res != null) {
444 view = new ViewResource (res);
445 } else {
446 Console.WriteLine ("{0} didn't have a Resource, it had a {1}.", type, v.Val == null ? "null" : v.Val.GetType ().ToString ());
448 break;
449 case "Method":
450 case "Getter":
451 case "Setter":
452 case "Remover":
453 case "Adder":
454 case "Invoker":
455 case "Constructor":
456 MethodDefinition def;
457 v = new Value ();
458 store.GetValue (iter, 3, ref v);
459 def = v.Val as MethodDefinition;
460 if (def != null) {
461 view = new ViewCode (def);
462 } else {
463 Console.WriteLine ("{0} didn't have a MethodDefinition.", type);
465 break;
466 default:
467 Console.WriteLine ("Unhandled case: {0}", type);
468 break;
471 // Remove old views and add the new one
473 while (box.Children.Length > 1)
474 box.Remove (box.Children [1]);
476 if (view != null) {
477 box.PackStart (view.GetView (), true, true, 0);
478 box.ShowAll ();