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