context: using System;
  using System.Collections.Generic;
  using System.IO;
  using System.Reflection;
  
  using Gdk;
  using Gtk;
  using Pango;
  
  namespace GtkDemo
  {
  	public class DemoMain
  	{
  		private Gtk.Window window;
  		private TextBuffer infoBuffer = new TextBuffer (null);
  		private TextBuffer sourceBuffer = new TextBuffer (null);
  		private TreeView treeView;
  		private TreeStore store;
  		private TreeIter oldSelection = TreeIter.Zero;
  
  		public static void Main (string[] args)
  		{
  			Application.Init ();
  			new DemoMain ();
  			Application.Run ();
  		}
  
  		public DemoMain ()
  		{
  			SetupDefaultIcon ();
  		   	window = new Gtk.Window ("Gtk# Code Demos");
  		   	window.SetDefaultSize (600, 400);
  			window.DeleteEvent += new DeleteEventHandler (WindowDelete);
  
  			HBox hbox = new HBox (false, 0);
  			window.Add (hbox);
  
  			treeView = CreateTree ();
  			hbox.PackStart (treeView, false, false, 0);
  
  			Notebook notebook = new Notebook ();
  			hbox.PackStart (notebook, true, true, 0);
  
  			notebook.AppendPage (CreateText (infoBuffer, false), new Label ("_Info"));
  			TextTag heading = new TextTag ("heading");
  			heading.Font = "Sans 18";
  			infoBuffer.TagTable.Add (heading);
  
  			notebook.AppendPage (CreateText (sourceBuffer, true), new Label ("_Source"));
  
  			window.ShowAll ();
  		}
  
  		private void LoadFile (string filename)
  		{
  			Stream file = Assembly.GetExecutingAssembly ().GetManifestResourceStream (filename);
  			if (file != null) {
  				LoadStream (file);
  			} else if (File.Exists (filename)) {
  				file = File.OpenRead (filename);
  				LoadStream (file);
  			} else {
  				infoBuffer.Text = String.Format ("{0} was not found.", filename);
  				sourceBuffer.Text = String.Empty;
  			}
  
  			Fontify ();
  		}
  
  		private enum LoadState {
  			Title,
  			Info,
  			SkipWhitespace,
  			Body
  		};
  
  		private void LoadStream (Stream file)
  		{
  			StreamReader sr = new StreamReader (file);
  			LoadState state = LoadState.Title;
  			bool inPara = false;
  
  			infoBuffer.Text = "";
  			sourceBuffer.Text = "";
  
  			TextIter infoIter = infoBuffer.EndIter;
  			TextIter sourceIter = sourceBuffer.EndIter;
  
  			// mostly broken comment parsing for splitting
  			// out the special comments to display in the infobuffer
  
  			string line, trimmed;
  			while (sr.Peek () != -1) {
  				line = sr.ReadLine ();
  				trimmed = line.Trim ();
  
  				switch (state) {
  				case LoadState.Title:
  					if (trimmed.StartsWith ("/* ")) {
  						infoBuffer.InsertWithTagsByName (ref infoIter, trimmed.Substring (3), "heading");
  						state = LoadState.Info;
  					}
  					break;
  
  				case LoadState.Info:
  					if (trimmed == "*") {
  						infoBuffer.Insert (ref infoIter, "\n");
  						inPara = false;
  					} else if (trimmed.StartsWith ("* ")) {
  						if (inPara)
  							infoBuffer.Insert (ref infoIter, " ");
  						infoBuffer.Insert (ref infoIter, trimmed.Substring (2));
  						inPara = true;
  					} else if (trimmed.StartsWith ("*/"))
  						state = LoadState.SkipWhitespace;
  					break;
  
  				case LoadState.SkipWhitespace:
  					if (trimmed != "") {
  						state = LoadState.Body;
  						goto case LoadState.Body;
  					}
  					break;
  
  				case LoadState.Body:
  					sourceBuffer.Insert (ref sourceIter, line + "\n");
  					break;
  				}
  			}
  			sr.Close ();
  			file.Close ();
  		}
  
  		// this is to highlight the sourceBuffer
  		private void Fontify ()
  		{
  		}
  
  		private void SetupDefaultIcon ()
  		{
  			Gdk.Pixbuf pixbuf = Gdk.Pixbuf.LoadFromResource ("gtk-logo-rgb.gif");
  
  			if (pixbuf != null) {
  				// The gtk-logo-rgb icon has a white background
  				// make it transparent instead
  				Pixbuf transparent  = pixbuf.AddAlpha (true, 0xff, 0xff, 0xff);
  
  				Gtk.Window.DefaultIconList = new Gdk.Pixbuf [] { transparent };
  			}
  		}
  
  		private TreeView CreateTree ()
  		{
  			TreeView view = new TreeView ();
  			view.Model = FillTree ();
  
  			CellRendererText cr = new CellRendererText ();
  			TreeViewColumn column = new TreeViewColumn ("Widget (double click for demo)", cr, "text", 0);
  			column.AddAttribute (cr, "style" , 2);
  			view.AppendColumn (column);
  
  			view.Selection.Changed += new EventHandler (TreeChanged);
  			view.RowActivated += new RowActivatedHandler (RowActivated);
  			view.ExpandAll ();
  			view.SetSizeRequest (200, -1);
  			view.Selection.Mode = Gtk.SelectionMode.Browse;
  			return view;
  		}
  
  		private ScrolledWindow CreateText (TextBuffer buffer, bool IsSource)
  		{
  			ScrolledWindow scrolledWindow = new ScrolledWindow ();
  			scrolledWindow.SetPolicy (PolicyType.Automatic, PolicyType.Automatic);
  			scrolledWindow.ShadowType = ShadowType.In;
  
  			TextView textView = new TextView (buffer);
  			textView.Editable = false;
  			textView.CursorVisible = false;
  
  			scrolledWindow.Add (textView);
  
  			if (IsSource) {
  				FontDescription fontDescription = FontDescription.FromString ("monospace");
  				textView.OverrideFont (fontDescription);
  				textView.WrapMode = Gtk.WrapMode.None;
  			} else {
  				// Make it a bit nicer for text
  				textView.WrapMode = Gtk.WrapMode.Word;
  				textView.PixelsAboveLines = 2;
  				textView.PixelsBelowLines = 2;
  			}
  
  			return scrolledWindow;
  		}
  
  		private TreeStore FillTree ()
  		{
  			// title, filename, italic
  			store = new TreeStore (typeof (string), typeof (System.Type), typeof (bool));
  			Dictionary<string, TreeIter> parents = new Dictionary<string, TreeIter> ();
  			TreeIter parent;
  
  			Type[] types = Assembly.GetExecutingAssembly ().GetTypes ();
  			foreach (Type t in types) {
  				object[] att = t.GetCustomAttributes (typeof (DemoAttribute), false);
  
gt: 				foreach (DemoAttribute demo in att) {