1 /*
2  * This file is part of gtkD.
3  *
4  * gtkD is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * gtkD is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with gtkD; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
17  */
18 
19 module TestWindow;
20 
21 //debug = 1;
22 
23 //version=cairo;
24 
25 version(cairo)private import cairo.clock;
26 
27 private import gtk.Version;
28 private import gtk.Table;
29 
30 private import stdlib = core.stdc.stdlib : exit;
31 private import core.thread;
32 private import std.random;
33 private import std.string;
34 
35 import gdk.Threads;
36 
37 private import gtk.Main;
38 private import gtk.MainWindow;
39 private import gtk.Adjustment;
40 private import gtk.AccelGroup;
41 
42 private import TestEntries;
43 
44 //private import gtkDTree;
45 private import TestStock;
46 private import TestDrawingArea;
47 private import TestScales;
48 private import TestText;
49 //private import TestTree;
50 private import TestTreeView;
51 private import TestTreeView1;
52 private import TestImage;
53 private import TestThemes;
54 private import TestAspectFrame;
55 private import TestIdle;
56 private import TTextView;
57 //private import TEditableCells;
58 
59 private import gtk.MenuItem;
60 private import gtk.Widget;
61 private import gtk.MenuBar;
62 private import gtk.Notebook;
63 private import gtk.ComboBoxText;
64 private import gtk.FileChooserDialog;
65 private import gtk.FontSelectionDialog;
66 private import gtk.ColorSelectionDialog;
67 private import gtk.Button;
68 private import gtk.VBox;
69 private import gtk.MessageDialog;
70 private import gtk.Frame;
71 private import gtk.HButtonBox;
72 private import gtk.Statusbar;
73 private import gtk.Menu;
74 private import gtk.HandleBox;
75 private import gtk.Toolbar;
76 private import gtk.SeparatorToolItem;
77 private import gtk.ToolButton;
78 private import gtk.RadioButton;
79 private import gtk.CheckButton;
80 private import gtk.ToggleButton;
81 //private import gtk.ListItem;
82 private import gtk.HBox;
83 private import gtk.Arrow;
84 //private import gtk.ListG;
85 //private import gtk.OptionMenu;
86 private import gtk.ButtonBox;
87 private import gtk.Calendar;
88 private import gtk.VButtonBox;
89 private import gtk.SpinButton;
90 private import gtk.ListStore;
91 private import gtk.TreeIter;
92 private import gtk.TreeView;
93 private import gtk.TreeViewColumn;
94 private import gtk.CellRendererText;
95 //private import gtk.SListG;
96 //private import ddi.Drawable;
97 private import gtk.Window;
98 
99 private import gtk.ScrolledWindow;
100 private import gtk.MessageDialog;
101 
102 private import core.memory;
103 
104 private import glib.ListSG;
105 
106 private import glib.Str;
107 private import gtk.Label;
108 private import glib.ListG;
109 private import gtk.Paned;
110 private import gtk.HPaned;
111 private import gtk.VPaned;
112 
113 private import gtk.Calendar;
114 private import std.stdio;
115 private import gtk.VButtonBox;
116 private import gtk.FileChooserButton;
117 
118 private import gtk.AboutDialog;
119 private import gtk.Dialog;
120 
121 private import gtk.TreeStore;
122 private import gdk.Pixbuf;
123 private import gtk.ComboBox;
124 
125 private import gtk.TreePath;
126 private import gtk.CellRenderer;
127 private import gtk.CellRendererPixbuf;
128 
129 /**
130  * This tests the GtkD widgets
131  */
132 
133 
134 class TestWindow : MainWindow
135 {
136 	/**
137 	 * Executed when the user tries to close the window
138 	 * @return true to refuse to close the window
139 	 */
140 	int windowDelete(GdkEvent* event, Widget widget)
141 	{
142 
143 		debug(events) writeln("TestWindow.widgetDelete : this and widget to delete %X %X",this,window);
144 		MessageDialog d = new MessageDialog(
145 										this,
146 										GtkDialogFlags.MODAL,
147 										MessageType.QUESTION,
148 										ButtonsType.YES_NO,
149 										"Are you sure you want' to exit these GtkDTests?");
150 		int responce = d.run();
151 		if ( responce == ResponseType.YES )
152 		{
153 			stdlib.exit(0);
154 		}
155 		d.destroy();
156 		return true;
157 	}
158 
159 	void anyButtonExits(Button button)
160 	{
161 			stdlib.exit(0);
162 	}
163 
164 	this()
165 	{
166 		super("GtkD tests");
167 		setup();
168 		showAll();
169 
170 		string versionCompare = Version.checkVersion(3,0,0);
171 
172 		if ( versionCompare.length > 0 )
173 		{
174 			MessageDialog d = new MessageDialog(this,
175 										GtkDialogFlags.MODAL,
176 										MessageType.WARNING,
177 										ButtonsType.OK,
178 										"GtkD : Gtk+ version missmatch\n" ~ versionCompare ~
179 										"\nYou might run into problems!"~
180 										"\n\nPress OK to continue");
181 			d.run();
182 			d.destroy();
183 		}
184 	}
185 
186 	void setup()
187 	{
188 		//Frame.defaultBorder = 7;
189 
190 		VBox mainBox = new VBox(false,0);
191 		mainBox.packStart(getMenuBar(),false,false,0);
192 		mainBox.packStart(getToolbar(),false,false,0);
193 
194 		Notebook notebook = setNotebook();
195 		notebook.setBorderWidth(10);
196 		mainBox.packStart(notebook,true,true,0);
197 
198 		Button cancelButton = new Button(StockID.CANCEL, &anyButtonExits);
199 		Button exitButton = new Button(StockID.QUIT, &anyButtonExits);
200 		Button quitButton = new Button(StockID.OK, &anyButtonExits);
201 
202 		ButtonBox bBox = HButtonBox.createActionBox();
203 
204 		bBox.packEnd(exitButton,0,0,10);
205 		bBox.packEnd(cancelButton,0,0,10);
206 		bBox.packEnd(quitButton,0,0,10);
207 		mainBox.packStart(bBox,false,false,0);
208 
209 		Statusbar statusbar = new Statusbar();
210 
211 		mainBox.packStart(statusbar,false,true,0);
212 		add(mainBox);
213 
214 		notebook.appendPage(new TestEntries,"Entry");
215 		testEventBox(notebook);
216 
217 		testButtons(notebook);
218 
219 		notebook.appendPage(new TestStock,"Stock");
220 		testLists(notebook);
221 		testNotebook(notebook);
222 		testPaned(notebook);
223 		testDialogs(notebook);
224 		testViewport(notebook);
225 
226 		version(Windows)
227 		{
228 			// todo - threads are still broken on windows
229 		}
230 		else
231 		{
232 			testThreads(notebook);
233 		}
234 
235 		notebook.appendPage(new TestScales,"Scales");
236 			testSpinButton(notebook);
237 
238 		notebook.appendPage(new TestTreeView,"TreeView");
239 		notebook.appendPage(new TestTreeView1,"TreeView 1");
240 			testList(notebook);
241 
242 		version(linux) {
243 			// this block crashes gtk+ on win32 for some reason
244 			notebook.appendPage(new Frame(new TestDrawingArea,"Drawing Area"),"Drawing");
245 			notebook.appendPage(new TestText,"Text");
246 			notebook.appendPage(new TestImage(this),"Image");
247 			//TestThemes seems to be unfinished.
248 			//notebook.appendPage(new TestThemes(this),"Themes");
249 			notebook.appendPage(new TestAspectFrame(),"Aspect Frame");
250 			notebook.appendPage(new TestIdle(),"Idle");
251 			version(cairo)notebook.appendPage(new Clock(), "Cairo");
252 			gtkDemo(notebook);
253 		}
254 	}
255 
256 	MenuBar getMenuBar()
257 	{
258 
259 		AccelGroup accelGroup = new AccelGroup();
260 
261 		addAccelGroup(accelGroup);
262 
263 
264 		MenuBar menuBar = new MenuBar();
265 
266 		Menu menu = menuBar.append("_File");
267 
268 		MenuItem item = new MenuItem(&onMenuActivate, "_New","file.new", true, accelGroup, 'n');
269 		//item.addAccelerator("activate",accelGroup,'n',GdkModifierType.CONTROL_MASK,GtkAccelFlags.VISIBLE);
270 
271 		menu.append(item);
272 		menu.append(new MenuItem(&onMenuActivate, "_Open","file.open", true, accelGroup, 'o'));
273 		menu.append(new MenuItem(&onMenuActivate, "_Close","file.close", true, accelGroup, 'c'));
274 		menu.append(new MenuItem(&onMenuActivate, "E_xit","file.exit", true, accelGroup, 'x'));
275 
276 
277 		menu = menuBar.append("_Edit");
278 
279 		menu.append(new MenuItem(&onMenuActivate,"_Find","edit.find", true, accelGroup, 'f'));
280 		menu.append(new MenuItem(&onMenuActivate,"_Search","edit.search", true, accelGroup, 's'));
281 
282 		menu = menuBar.append("_Help");
283 		menu.append(new MenuItem(&onMenuActivate,"_About","help.about", true, accelGroup, 'a',GdkModifierType.CONTROL_MASK|GdkModifierType.SHIFT_MASK));
284 
285 
286 
287 
288 		return menuBar;
289 	}
290 
291 	class GtkDAbout : AboutDialog
292 	{
293 		this()
294 		{
295 			string[] names;
296 			names ~= "Antonio Monteiro (binding/wrapping/proxying/decorating for D)";
297 			names ~= "www.gtk.org (base C library)";
298 
299 			setAuthors( names );
300 			setDocumenters( names );
301 			setArtists( names );
302 			setLicense("License is LGPL");
303 			setWebsite("http://lisdev.com");
304 		}
305 	}
306 
307 	void onMenuActivate(MenuItem menuItem)
308 	{
309 		string action = menuItem.getActionName();
310 		switch( action )
311 		{
312 			case "help.about":
313 				GtkDAbout dlg = new GtkDAbout();
314 				dlg.addOnResponse(&onDialogResponse);
315 				dlg.showAll();
316 				break;
317 			default:
318 				MessageDialog d = new MessageDialog(
319 					this,
320 					GtkDialogFlags.MODAL,
321 					MessageType.INFO,
322 					ButtonsType.OK,
323 					"You pressed menu item "~action);
324 				d.run();
325 				d.destroy();
326 			break;
327 		}
328 
329 	}
330 
331 	void onDialogResponse(int response, Dialog dlg)
332 	{
333 		if(response == GtkResponseType.CANCEL)
334 			dlg.destroy();
335 	}
336 
337 	Widget getToolbar()
338 	{
339 		HandleBox handleBox = new HandleBox();
340 		Toolbar toolbar = new Toolbar();
341 		toolbar.insert(new ToolButton(StockID.OPEN));
342 		toolbar.insert(new ToolButton(StockID.CLOSE));
343 		toolbar.insert(new SeparatorToolItem());
344 		toolbar.insert(new ToolButton(StockID.SAVE));
345 		toolbar.insert(new ToolButton(StockID.SAVE_AS));
346 
347 		handleBox.add(toolbar);
348 
349 		return handleBox;
350 
351 	}
352 
353 	Notebook setNotebook()
354 	{
355 		Notebook notebook = new Notebook();
356 		notebook.addOnSwitchPage(&onNotebookSwitchPage);
357 		notebook.setTabPos(PositionType.LEFT);
358 		return notebook;
359 	}
360 
361 	void onNotebookSwitchPage(Widget notePage, uint pageNumber, Notebook notebook)
362 	{
363 		//writefln("Notebook switch to page %s", pageNumber);
364 		// fullCollect helps finding objects that shouldn't have been collected
365 		GC.collect();
366 		//writefln("exiting Notebook switch to page %s", pageNumber);
367 	}
368 
369 	//private import EventBox;
370 
371 	void testEventBox(Notebook notebook)
372 	{
373 
374 //		EventBox eventBox = new EventBox();
375 //		eventBox.add(new Label("label on event box"));
376 //		notebook.appendPage(eventBox,"Buttons");
377 
378 		//EventBox eventBox = new EventBox();
379 		//eventBox.add(new Label("label on event box"));
380 		notebook.appendPage(new Label("just a simple label"),new Label("label"));
381 
382 	}
383 
384 	void testButtons(Notebook notebook)
385 	{
386 
387 		Table table = new Table(2,12,0);
388 
389 		//ListSG listSG = new ListSG();
390 
391 		RadioButton radio1Button = new RadioButton(cast(ListSG)null,"Option 1");
392 		RadioButton radio2Button = new RadioButton(radio1Button,"Option 2");
393 		RadioButton radio3Button = new RadioButton(radio2Button,"Option 3");
394 		RadioButton radio4Button = new RadioButton(radio3Button,"Option 4");
395 		RadioButton radio5Button = new RadioButton(radio4Button,"Option 5");
396 		RadioButton radio6Button = new RadioButton(radio5Button,"Option 6");
397 		RadioButton radio7Button = new RadioButton(radio6Button,"Option 7");
398 		RadioButton radio8Button = new RadioButton(radio7Button,"Option 8");
399 		RadioButton radio9Button = new RadioButton(radio8Button,"Option 9");
400 		table.attach(radio1Button,0,1,0,1,AttachOptions.FILL,AttachOptions.FILL,4,4);
401 		table.attach(radio2Button,0,1,1,2,AttachOptions.FILL,AttachOptions.FILL,4,4);
402 		table.attach(radio3Button,0,1,2,3,AttachOptions.FILL,AttachOptions.FILL,4,4);
403 		table.attach(radio4Button,0,1,3,4,AttachOptions.FILL,AttachOptions.FILL,4,4);
404 		table.attach(radio5Button,0,1,4,5,AttachOptions.FILL,AttachOptions.FILL,4,4);
405 		table.attach(radio6Button,0,1,5,6,AttachOptions.FILL,AttachOptions.FILL,4,4);
406 		table.attach(radio7Button,0,1,6,7,AttachOptions.FILL,AttachOptions.FILL,4,4);
407 		table.attach(radio8Button,0,1,7,8,AttachOptions.FILL,AttachOptions.FILL,4,4);
408 		table.attach(radio9Button,0,1,8,9,AttachOptions.FILL,AttachOptions.FILL,4,4);
409 
410 		CheckButton editableButton = new CheckButton("editable");
411 		CheckButton visibleButton = new CheckButton("visible");
412 		table.attach(editableButton,0,1,9,10,AttachOptions.FILL,AttachOptions.FILL,4,4);
413 		table.attach(visibleButton,0,1,10,11,AttachOptions.FILL,AttachOptions.FILL,4,4);
414 
415 		ToggleButton toggleButton = new ToggleButton("Toggle this");
416 		table.attach(toggleButton,0,1,11,12,AttachOptions.FILL,AttachOptions.FILL,4,4);
417 
418 		Button button = new Button("test events");
419 		table.attach(button,0,1,12,13,AttachOptions.FILL,AttachOptions.FILL,4,4);
420 
421 		void bActivate(Button button)
422 		{
423 			writeln("button Activate");
424 		}
425 		void bClicked(Button button)
426 		{
427 			writeln("button Clicked");
428 		}
429 		void bEnter(Button button)
430 		{
431 			writeln("button Enter");
432 		}
433 		void bLeave(Button button)
434 		{
435 			writeln("button Leave");
436 		}
437 		void bPressed(Button button)
438 		{
439 			writeln("button Pressed");
440 		}
441 		void bReleased(Button button)
442 		{
443 			writeln("button Released");
444 		}
445 		button.addOnActivate(&bActivate);
446 		button.addOnClicked(&bClicked);
447 		button.addOnEnter(&bEnter);
448 		button.addOnLeave(&bLeave);
449 		button.addOnPressed(&bPressed);
450 		button.addOnReleased(&bReleased);
451 
452 //		for ( ShadowType shadow = 0; shadow<=ShadowType.max ; shadow ++)
453 //		{
454 //			for ( DirectionType direction = 0 ; direction<=DirectionType.max ; direction++)
455 //			{
456 //				table.attach(new Arrow(direction,shadow),direction+1,direction+2,shadow,shadow+1,AttachOptions.FILL,AttachOptions.FILL,4,4);
457 //				table.attach(new Arrow(direction,shadow),direction+1,direction+2,shadow,shadow+1,AttachOptions.FILL,AttachOptions.FILL,4,4);
458 //				table.attach(new Arrow(direction,shadow),direction+1,direction+2,shadow,shadow+1,AttachOptions.FILL,AttachOptions.FILL,4,4);
459 //				table.attach(new Arrow(direction,shadow),direction+1,direction+2,shadow,shadow+1,AttachOptions.FILL,AttachOptions.FILL,4,4);
460 //			}
461 //		}
462 
463 
464 		notebook.appendPage(new Frame(table,"Buttons"),"Buttons");
465 
466 	}
467 
468 	class ComboStore : TreeStore
469 	{
470 		this()
471 		{
472 			//int* i = cast(int*)pixbufGetType();
473 
474 			GType[] columns;
475 			columns ~= GType.STRING;
476 			columns ~= GType.STRING;
477 			super(columns);
478 		}
479 
480 	}
481 
482 
483 	void testLists(Notebook notebook)
484 	{
485 		VBox mainBox = new VBox(false,3);
486 
487 		// comboBoxTextEntry from a list of strings
488 		mainBox.packStart(new Label("String combo"),false,true,0);
489 		static string[] cbList = ["item 1","item 2","item 3","item 4","item 5","item 6","item 7","item 8","item 9"];
490 		comboText = new ComboBoxText();
491 		string entry3 = "Combo box text entry 3";
492 		comboText.appendText("Combo box text entry 1");
493 		comboText.appendText("Combo box text entry 2");
494 		comboText.appendText(entry3);
495 		comboText.appendText("Combo box text entry 4");
496 		comboText.appendText("Combo box text entry 5");
497 		comboText.setActive(2);
498 
499 		ButtonBox actionBox1 = HButtonBox.createActionBox();
500 		actionBox1.packStart(comboText,false,false,0);
501 
502 		Button showCombo1 = new Button("ShowCombo", &showTextCombo);
503 		actionBox1.packStart(showCombo1,false,false,0);
504 
505 		mainBox.packStart(new Frame(actionBox1, "Text entry ComboBox"),false,false,0);
506 
507 
508 
509 		// TODO combo with widgets
510 
511 
512 		// new ComboBox + TreeModel
513 
514 		ComboStore comboStore = new ComboStore();
515 
516 		TreeIter iterFirst;	// to set the first active iter
517 		TreeIter iterChild;
518 		TreeIter iterTop = comboStore.append(null);
519 		comboStore.setValue(iterTop, 0, "Paganini" );
520 		iterFirst = comboStore.append(iterTop);
521 		comboStore.setValue(iterFirst, 0, "Nicolo" );
522 
523 		iterTop = comboStore.append(null);
524 		comboStore.setValue(iterTop, 0, "List" );
525 		iterChild = comboStore.append(iterTop);
526 		comboStore.setValue(iterChild, 0, "Franz" );
527 
528 		iterTop = comboStore.append(null);
529 		comboStore.setValue(iterTop, 0, "Beethoven" );
530 		iterChild = comboStore.append(iterTop);
531 		comboStore.setValue(iterChild, 0, "Ludwic" );
532 		iterChild = comboStore.append(iterTop);
533 		comboStore.setValue(iterChild, 0, "Maria" );
534 		iterChild = comboStore.append(iterTop);
535 		comboStore.setValue(iterChild, 0, "Van" );
536 
537 		iterTop = comboStore.append(null);
538 		comboStore.setValue(iterTop, 0, "Bach" );
539 		iterChild = comboStore.append(iterTop);
540 		comboStore.setValue(iterChild, 0, "Johann" );
541 		iterChild = comboStore.append(iterTop);
542 		comboStore.setValue(iterChild, 0, "Sebastian" );
543 
544 		ComboBox treeCombo = new ComboBox(comboStore);
545 		treeCombo.setWrapWidth(1);
546 		treeCombo.setProperty("entry-text-column", 0);
547 
548 		// TODO something is wrong gettign the ier from the path
549 		//TreePath path = new TreePath("0,0");
550 		//comboStore.getIter(iterChild, path);
551 		//treeCombo.setActiveIter(iterChild);
552 		// use a previously set iter
553 		treeCombo.setActiveIter(iterFirst);
554 
555 		mainBox.packStart(new Frame(treeCombo,"Tree Combo box"),false,true,0);
556 
557 		simpleCombo = new ComboBoxText();
558 		simpleCombo.appendText("Top");
559 		simpleCombo.appendText("Bottom");
560 		simpleCombo.appendText("Left");
561 		simpleCombo.appendText("Right");
562 		simpleCombo.setActive(0);
563 
564 		// actions
565 
566 		ButtonBox actionBox = HButtonBox.createActionBox();
567 		actionBox.packStart(simpleCombo,false,false,0);
568 
569 		Button showCombo = new Button("ShowCombo", &showSimpleCombo);
570 		actionBox.packStart(showCombo,false,false,0);
571 
572 		mainBox.packStart(new Frame(actionBox, "Simple text list"),false,false,0);
573 
574 		notebook.appendPage(new Frame(mainBox,"Lists"),"Lists");
575 
576 	}
577 	ComboBoxText simpleCombo;
578 	ComboBoxText comboText;
579 
580 	void showTextCombo(Button button)
581 	{
582 		writeln("Combo selected text = %s",comboText.getActiveText());
583 	}
584 
585 	void showSimpleCombo(Button button)
586 	{
587 		writeln("Combo selected text = %s",simpleCombo.getActiveText());
588 	}
589 
590 	class NB : Notebook
591 	{
592 		void itemActivated(MenuItem menu_item)
593 		{
594 			writeln("NB.activateCallback");
595 		}
596 		void buttonClicked(Button button)
597 		{
598 			setCurrentPage(2);
599 		}
600 
601 		void switchPage(Notebook notebook, /*NotebookPage page,*/ uint pageNumber)
602 		{
603 			writeln("new page = %d",pageNumber);
604 		}
605 	}
606 
607 
608 	NB nb;
609 
610 	void posLeft(Button button)
611 	{
612 		nb.setTabPos(PositionType.LEFT);
613 	}
614 	void posRight(Button button)
615 	{
616 		nb.setTabPos(PositionType.RIGHT);
617 	}
618 	void posTop(Button button)
619 	{
620 		nb.setTabPos(PositionType.TOP);
621 	}
622 	void posBottom(Button button)
623 	{
624 		nb.setTabPos(PositionType.BOTTOM);
625 	}
626 
627 	/**
628 	 * tests notebook
629 	 * @param nodebook
630 	 */
631 	void testNotebook(Notebook notebook)
632 	{
633 
634       	nb = new NB();
635       	nb.setTabPos(PositionType.min);
636       	nb.popupEnable();
637 		nb.setShowBorder(false);
638 		nb.setBorderWidth(0);
639 
640       	class PageMove
641       	{
642       		Notebook notebook;
643       		PositionType toPos;
644       		this(Notebook notebook,PositionType toPos)
645       		{
646       			this.notebook = notebook;
647       			this.toPos = toPos;
648       		}
649       		void buttonClickedCallback()
650       		{
651       			notebook.setTabPos(toPos);
652       		}
653       	}
654 
655 		PageMove toLeft = new PageMove(nb,PositionType.LEFT);
656 		PageMove toRight = new PageMove(nb,PositionType.RIGHT);
657 		PageMove toTop = new PageMove(nb,PositionType.TOP);
658 		PageMove toBottom = new PageMove(nb,PositionType.BOTTOM);
659 
660 
661 		notebook.appendPage(nb,new Label("Notebook"));
662 
663       	for( char i = '1' ; i<'5' ; i++ )
664       	{
665       		Table table = new Table(2,2,true);
666 			Button left = new Button("Left "~ i);
667 			left.addOnClicked(&posLeft);
668 			Button right = new Button("Right "~ i);
669 			right.addOnClicked(&posRight);
670 			Button top = new Button("top "~ i);
671 			top.addOnClicked(&posTop);
672 			Button bottom = new Button("bottom "~ i);
673 			bottom.addOnClicked(&posBottom);
674 
675 			table.attach(top,0,1,0,1,AttachOptions.SHRINK,AttachOptions.SHRINK,4,4);
676 			table.attach(right,1,2,0,1,AttachOptions.SHRINK,AttachOptions.SHRINK,4,4);
677 			table.attach(left,0,1,1,2,AttachOptions.SHRINK,AttachOptions.SHRINK,4,4);
678 			table.attach(bottom,1,2,1,2,AttachOptions.SHRINK,AttachOptions.SHRINK,4,4);
679       		if ( i == 3 )
680 			{
681 
682 //				MenuItem menuItem = new MenuItem("menu page 3",&nb.itemActivated);
683 //
684 //				Menu menu = new Menu();
685 //				menu.append(new MenuItem("page 3.1",&nb.itemActivated));
686 //				menu.append(new MenuItem("page 3.2",&nb.itemActivated));
687 //				menu.append(new MenuItem("page 3.3",&nb.itemActivated));
688 //				menu.append(new MenuItem("page 3.4",&nb.itemActivated));
689 //
690 //				menuItem.setSubmenu(menu);
691 
692 				HBox box = new HBox(false,0);
693 				box.setBorderWidth(0);
694 				Button button = new Button("Page " ~ i ~ "\0");
695 				button.addOnClicked(&nb.buttonClicked);
696 				button.setBorderWidth(0);
697 				button.setRelief(ReliefStyle.NONE);
698 				CheckButton checkButton = new CheckButton();
699 				checkButton.setBorderWidth(0);
700 				box.packStart(checkButton,false,false,0);
701 				box.packStart(button,false,false,0);
702 				//nb.appendPageMenu(table,box,menuItem);
703 				//nb.appendPage(table,box);
704 			}
705 			else
706 			{
707 				nb.appendPage(table,new Label("Page " ~ i ~ "\0"));
708 			}
709       	}
710 		//nb.addOnSwitchPage(&nb.switchPage);
711 	}
712 
713 	void testPaned(Notebook notebook)
714 	{
715 
716 		Paned mainPaned = new VPaned();
717 		Paned p0 = mainPaned;
718 		Button p1;
719 		Paned p2;
720 
721 		bool h = true;
722 		for ( char c='1' ; c<='5' ; c++ )
723 		{
724 			p1 = new Button("Pane "~c);
725 			if ( h ) p2 = new HPaned();
726 			else p2 = new VPaned();
727 
728 			p0.add1(p1);
729 			p0.add2(p2);
730 			p0 = p2;
731 			h = !h;
732 		}
733 
734 		notebook.appendPage(mainPaned,new Label("Paned"));
735 
736 	}
737 
738 	FileChooserDialog fcd;
739 	FontSelectionDialog f;
740 	ColorSelectionDialog d;
741 
742 	void showFileChooser(Button button)
743 	{
744 		string[] a;
745 		ResponseType[] r;
746 		a ~= "Lets go!";
747 		a ~= "Please don't";
748 		r ~= ResponseType.OK;
749 		r ~= ResponseType.CANCEL;
750 		if ( fcd  is  null )
751 		{
752 			fcd = new FileChooserDialog("File Chooser", this, FileChooserAction.OPEN, a, r);
753 		}
754 
755 		fcd.setSelectMultiple(true);
756 		fcd.run();
757 //		writefln("file selected = %s",fcd.getFileName());
758 //
759 //		foreach ( int i, string selection ; fs.getSelections())
760 //		{
761 //			writeln("File(s) selected [%d] %s",i,selection);
762 //		}
763 		fcd.hide();
764 	}
765 
766 	void showColor(Button button)
767 	{
768 		if ( d  is  null )
769 		{
770 			d = new ColorSelectionDialog("Select the color");
771 		}
772 		d.run();
773 		d.hide();
774 	}
775 
776 	void showCalendar(Button button)
777 	{
778 		Window calWin = new Window("Calendar");
779 		Calendar calendar = new Calendar();
780 		//calendar.setTitle("No Title");
781 		calWin.add(calendar);
782 		calWin.showAll();
783 	}
784 
785 	void showFont(Button button)
786 	{
787 		if ( f  is  null )
788 		{
789 			f = new FontSelectionDialog("Select the font");
790 		}
791 		f.run();
792 		string fontName = f.getFontName();
793 		f.hide();
794 	}
795 
796 	Button fontButton;
797 
798 	void testDialogs(Notebook notebook)
799 	{
800 
801 		ButtonBox bBox = VButtonBox.createActionBox();
802 
803 		if ( fcd  is  null )
804 		{
805 			fcd = new FileChooserDialog("File Chooser", this, FileChooserAction.OPEN);
806 		}
807 
808 
809 		Button fileChooser = new Button("File Chooser", &showFileChooser);
810 		FileChooserButton fcb = new FileChooserButton(fcd);
811 
812 		Button color = new Button("Color Dialog", &showColor);
813 		Button calendar = new Button("Calendar Dialog", &showCalendar);
814 		fontButton = new Button("Font Dialog", &showFont);
815 		//fontButton.modifyFont("[Newspaper][16]");
816 
817 		bBox.packStart(fileChooser,0,0,10);
818 		bBox.packStart(fcb,0,0,10);
819 		bBox.packStart(color,0,0,10);
820 		bBox.packStart(calendar,0,0,10);
821 		bBox.packStart(fontButton,0,0,10);
822 
823 		notebook.appendPage(new Frame(bBox,"Dialogs"),new Label("Dialogs"));
824 
825 	}
826 
827 	__gshared Button[] threadTestButtons;
828 	static T1[] t1s;
829 
830 	class T1 : Thread
831 	{
832 		int num;
833 
834 		this(int num)
835 		{
836 			super(&run);
837 			this.num = num;
838 		}
839 
840 		void run()
841 		{
842 			runCommon();
843 		}
844 		
845 		int runCommon()
846 		{
847 			while(1)
848 			{
849 				size_t buttonNum = uniform(0, threadTestButtons.length);
850 				Button button = threadTestButtons[buttonNum];
851 
852 				threadsEnter();
853 				button.removeAll();
854 				button.setLabel(format("%s", num));
855 				threadsLeave();
856 				yield();
857 			}
858 			assert(0);
859 		}
860 	}
861 
862 	void testThreads(Notebook notebook)
863 	{
864 
865 		Table grid = new Table(8,8,0);
866 		for ( int i = 0 ; i<8 ; i++)
867 		{
868 			for ( int j = 0 ; j<8; j++)
869 			{
870 				Button button = new Button(format("%s",(j+8*i)));
871 				threadTestButtons ~= button;
872 				grid.attach( button,
873 							i,i+1,
874 							j,j+1,
875 							AttachOptions.SHRINK,AttachOptions.SHRINK,4,4);
876 
877 				t1s ~= new T1(j+8*i);
878 			}
879 		}
880 
881 		void stop(Button button)
882 		{
883 			foreach ( T1 t ; t1s )
884 			{
885 				if ( t.isRunning() )
886 				{
887 					t.sleep(dur!("hnsecs")(100));
888 				}
889 			}
890 		}
891 
892 		void go(Button button)
893 		{
894 			foreach ( T1 t ; t1s )
895 			{
896 				if ( !t.isRunning() )
897 				{
898 					t.start();
899 				}
900 			}
901 		}
902 
903 		VBox vbox = new VBox(false, 2);
904 		vbox.packStart(grid, true, true,2);
905 		ButtonBox actions = HButtonBox.createActionBox();
906 
907 		Button button = new Button(StockID.STOP, &stop);
908 		actions.packStart(button, false, false, 7);
909 		button = new Button(StockID.OK, &go);
910 		actions.packStart(button, false, false, 7);
911 
912 		vbox.packStart(actions, false, false, 2);
913 
914 		notebook.appendPage(vbox,new Label("Threads"));
915 	}
916 
917 	void testViewport(Notebook notebook)
918 	{
919 
920 		Table grid = new Table(21,21,0);
921 		for ( int i = 0 ; i<21 ; i++)
922 		{
923 			for ( int j = 0 ; j<21; j++)
924 			{
925 				if ( (i == j) || (i+j==20) || (i==10) || (j==10))
926 				{
927 					grid.attach(
928 						new Button("Button"),
929 							i,i+1,
930 							j,j+1,
931 							AttachOptions.SHRINK,AttachOptions.SHRINK,4,4);
932 				}
933 			}
934 		}
935 
936 		ScrolledWindow sw = new ScrolledWindow(null,null);
937 		sw.addWithViewport(grid);
938 		notebook.appendPage(sw,new Label("Viewport"));
939 	}
940 
941 	void testSpinButton(Notebook notebook)
942 	{
943 		Table table = new Table(2,1,false);
944 
945 		SpinButton spin = new SpinButton(new Adjustment(1.0, 0.0, 100.0, 1.0, 10.0, 0),1,0);
946 		table.attach(new Label("Spin this:"),0,1,0,1,AttachOptions.FILL,AttachOptions.FILL,4,4);
947 		table.attach(spin,1,2,0,1,AttachOptions.FILL,AttachOptions.FILL,4,4);
948 
949 		notebook.appendPage(table,"Spin Buttons");
950 
951 	}
952 
953 	void testList(Notebook notebook)
954 	{
955 		class TestListStore : ListStore
956 		{
957 			this()
958 			{
959 				static GType [3] columns = [
960 								GType.STRING,
961 								GType.STRING,
962 								GType.STRING
963 								];
964 				super(columns);
965 			}
966 		}
967 
968 		TestListStore testListStore = new TestListStore();
969 
970 		TreeIter iterTop = testListStore.createIter();
971 
972 		static int [3] cols = [0,1,2];
973 		string[] vals;
974 		vals ~= "Antonio";
975 		vals ~= "Canada";
976 		vals ~= "Ontario";
977 		testListStore.set(iterTop,cols,vals);
978 
979 		testListStore.append(iterTop);
980 		string[] vals1;
981 		vals1 ~= "John Reimer";
982 		vals1 ~= "Canada";
983 		vals1 ~= "BC";
984 		testListStore.set(iterTop,cols,vals1);
985 
986 		testListStore.append(iterTop);
987 		string[] vals2;
988 		vals2 ~= "Friend of GtkD 2";
989 		vals2 ~= "Poland";
990 		vals2 ~= "Torun";
991 		testListStore.set(iterTop,cols,vals2);
992 
993 		testListStore.append(iterTop);
994 		string[] vals3;
995 		vals3 ~= "Friend of GtkD 3";
996 		vals3 ~= "Norway";
997 		vals3 ~= "Norway";
998 		testListStore.set(iterTop,cols,vals3);
999 
1000 		TreeView treeView = new TreeView(testListStore);
1001 		treeView.setHeadersClickable(true);
1002 		treeView.setRulesHint(true);
1003 
1004 		//CellRendererText cellText = new CellRendererText();
1005 		TreeViewColumn column = new TreeViewColumn("Author",new CellRendererText(),"text", 0);
1006 		treeView.appendColumn(column);
1007 		column.setResizable(true);
1008 		column.setReorderable(true);
1009 		column.setSortColumnId(0);
1010 		column.setSortIndicator(true);
1011 
1012 		column = new TreeViewColumn("Country",new CellRendererText(),"text", 1);
1013 		treeView.appendColumn(column);
1014 		column.setResizable(true);
1015 		column.setReorderable(true);
1016 		column.setSortColumnId(1);
1017 		column.setSortIndicator(true);
1018 
1019 		column = new TreeViewColumn("Province",new CellRendererText(),"text", 2);
1020 		treeView.appendColumn(column);
1021 		column.setResizable(true);
1022 		column.setReorderable(true);
1023 		column.setSortColumnId(2);
1024 		column.setSortIndicator(true);
1025 
1026 		//notebook.appendPage(treeView,"ListView");
1027 		ScrolledWindow sw = new ScrolledWindow(null,null);
1028 		sw.addWithViewport(treeView);
1029 		notebook.appendPage(sw,"ListView");
1030 	}
1031 
1032 	void testDelete(Notebook notebook)
1033 	{
1034 //		ulong l = 0;
1035 //		while(true)
1036 //		{
1037 //			int i =0;
1038 //			while(i<1 )
1039 //			{
1040 //				//Button b = new Button("Button");
1041 //				Drawable d = getDrawable();
1042 //				delete d;
1043 //				++i;
1044 //			}
1045 //			++l;
1046 //			write("testDelete count = %d\n\0",l*i);
1047 //		}
1048 
1049 	}
1050 
1051 	void gtkDemo(Notebook notebook)
1052 	{
1053 		void showTTextView(Button button)
1054 		{
1055 			new TTextView();
1056 		}
1057 
1058 		void showTEditableCells(Button button)
1059 		{
1060 		//	new TEditableCells();
1061 		}
1062 
1063 		ButtonBox vBBox = VButtonBox.createActionBox();
1064 
1065 		Button button = new Button("Text View");
1066 		button.addOnClicked(&showTTextView);
1067 		vBBox.packStart(button,false,false,4);
1068 
1069 		button = new Button("Editable Cells");
1070 		button.addOnClicked(&showTEditableCells);
1071 		vBBox.packStart(button,false,false,4);
1072 
1073 		notebook.appendPage(vBBox,"gtk-demo");
1074 	}
1075 }
1076 
1077 private import gtkc.Loader;
1078 
1079 void main(string[] args)
1080 {
1081 	Linker.dumpLoadLibraries();
1082 	Linker.dumpFailedLoads();
1083 
1084 	version(Windows)
1085 	{
1086 		// todo threads are still broken on windows...
1087 		Main.init(args);
1088 	}
1089 	else
1090 	{
1091 		Main.initMultiThread(args);
1092 	}
1093 
1094 	TestWindow window = new TestWindow();
1095 
1096 	debug(1)writefln("before Main.run");
1097 	Main.run();
1098 	debug(1)writefln("after Main.run");
1099 }