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 2.1 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18  
19 module ui.Main;
20 
21 //version = leds;
22 version = gtkDdev;
23 version = gtkDtest;
24 //version = difiles
25 //version = compiler;
26 version(linux)
27 {
28 	version = gtkDgl;
29 	version = gtkDgltest;
30 }
31 version = dmd;
32 //version = gdc;
33 
34 private import ui.Installer;
35 
36 private import ui.gtkDLogo;
37 
38 private import gtk.GtkD;
39 private import gtk.Alignment;
40 private import gtk.MainWindow;
41 private import gtk.VBox;
42 private import gtk.HBox;
43 private import gtk.Button;
44 private import gtk.Label;
45 private import gtk.Frame;
46 private import gtk.ButtonBox;
47 private import gtk.HButtonBox;
48 private import gtk.Entry;
49 private import gtk.CheckButton;
50 private import gtk.Notebook;
51 private import gtk.Widget;
52 private import gtk.Image;
53 private import gtkc.gtktypes;
54 private import gtk.SizeGroup;
55 private import gtk.HSeparator;
56 private import gtk.PopupBox;
57 	
58 private import gtkc.gtktypes;
59 	
60 private import gdk.Event;
61 private import std.stdio;
62 private import std.process;
63 private import std.string;
64 
65 private import std.c.stdlib;
66 
67 interface InstallerUI
68 {
69 	void setUserPanel(UserPanel panel);
70 	void addSelection(char[] id, CheckButton check);
71 	CheckButton getSelectionButton(char[] id);
72 	bool getSelection(char[] id);
73 	void setSelection(char[] id, bool state);
74 	void setSensitive(char[] id, bool state);
75 
76 	void addDirectory(char[] id, Entry entry);
77 	char[] getDirectory(char[] id);
78 	void setDirectory(char[] id, char[] value);
79 	
80 	//void nextPanel();
81 	//void prevPanel();
82 }
83 
84 public class MainInstaller : MainWindow , InstallerUI
85 {
86 	
87 	HBox topBox;
88 	VBox leftBox;
89 	VBox tasksBox;
90 	VBox mainBox;
91 	Notebook notebook;
92 	ButtonBox buttonBox;
93 
94 	Button backButton;
95 	Button nextButton;
96 	Button exitButton;
97 	Button installButton;
98 
99 	UserPanel[] userPanels;
100 	UserPanel currentUserPanel;
101 	CheckButton[char[]] selections;
102 	Entry[char[]] directories;
103 
104 	int movingDirection;	// going back or next, 0=don't know
105 	
106 	this()
107 	{
108 		version(leds)
109 		{
110 			super("GtkD and Leds installer");
111 		}
112 		else
113 		{
114 			super("GtkD installer");
115 		}
116 		setup();
117 		addPanels();
118 		setUserPanel(0);
119 		showAll();
120 	}
121 	
122 	public void addSelection(char[] id, CheckButton check)
123 	{
124 		selections[id] = check;
125 	}
126 	
127 	public CheckButton getSelectionButton(char[] id)
128 	{
129 		CheckButton check;
130 		if ( id in selections )
131 		{
132 			check = selections[id];
133 		}
134 		return check;
135 	}
136 	
137 	public bool getSelection(char[] id)
138 	{
139 		if ( id in selections )
140 		{
141 			return cast(bool)selections[id].getActive();
142 		}
143 		return false;
144 	}
145 	public void setSelection(char[] id, bool active)
146 	{
147 		if ( id in selections )
148 		{
149 			selections[id].setActive(active);
150 		}
151 	}
152 	public void setSensitive(char[] id, bool active)
153 	{
154 		if ( id in selections )
155 		{
156 			selections[id].setSensitive(active);
157 		}
158 	}
159 
160 	public void addDirectory(char[] id, Entry entry)
161 	{
162 		directories[id] = entry;
163 	}
164 	public char[] getDirectory(char[] id)
165 	{
166 		if ( id in directories )
167 		{
168 			return directories[id].getText();
169 		}
170 		return null;
171 	}
172 	public void setDirectory(char[] id, char[] value)
173 	{
174 		if ( id in directories )
175 		{
176 			return directories[id].setText(value);
177 		}
178 	}
179 
180 	public void nextPanel()
181 	{
182 		movingDirection = 1;
183 		notebook.nextPage();
184 		setUserPanel(notebook.getCurrentPage());
185 	}
186 	
187 	public void prevPanel()
188 	{
189 		movingDirection = -1;
190 		notebook.prevPage();
191 		setUserPanel(notebook.getCurrentPage());
192 	}
193 	
194 	private void setup()
195 	{
196 		topBox = new HBox(false, 2);
197 		leftBox = new VBox(false, 7);
198 		tasksBox = new VBox(false, 7);
199 		mainBox = new VBox(false, 2);
200 		notebook = new Notebook;
201 		notebook.setShowTabs(false);
202 		notebook.setSizeRequest(400,300);
203 		buttonBox = HButtonBox.createActionBox();
204 		
205 		exitButton = makeButton(null, StockID.QUIT, "Exit", "exit");
206 		buttonBox.packStart(Alignment.west(exitButton), true, true, 7);
207 
208 		version(Win32)
209 		{
210 			backButton = makeButton(buttonBox, StockID.GO_BACK, "<< Back", "back");
211 			nextButton = makeButton(buttonBox, StockID.GO_FORWARD, "Next >>", "next");
212 			installButton = makeButton(buttonBox, StockID.OK, "Install", "install");
213 		}
214 		else
215 		{
216 			backButton = makeButton(buttonBox, StockID.GO_BACK, "Back", "back");
217 			nextButton = makeButton(buttonBox, StockID.GO_FORWARD, "Next", "next");
218 			installButton = makeButton(buttonBox, StockID.OK, "Install", "install");
219 		}
220 		
221 //		Button logo = new Button();
222 //		logo.setImage(getGtkDLogo());
223 //		logo.addOnButtonPress(&logoClicked);
224 //		logo.setRelief(ReliefStyle.NONE);
225 //		logo.setFocusOnClick(false);
226 
227 		mainBox.packStart(Alignment.west(getGtkDLogo()), false, false, 2);
228 		mainBox.packStart(notebook, true, true, 2);
229 		mainBox.packStart(buttonBox, false, false, 2);
230 
231 		topBox.packStart(new Frame(tasksBox,""), false, false, 2);
232 		topBox.packStart(mainBox, true, true, 2);
233 		
234 		add(topBox);
235 	}
236 
237 	private int logoClicked(GdkEventButton* event, Widget widget)
238 	{
239 		
240 		PopupBox.information(this, "Help with the graphics design is apreciated", "GtkDLogo");
241 		return false;
242 	}
243 	
244 	private Button makeButton(ButtonBox box,StockID id, char[] label, char[] action)
245 	{
246 		Button button = new Button();
247 		button.setActionName(action);
248 		button.removeAll();
249 		button.setImage(new Image(id, IconSize.BUTTON));
250 		button.setLabel(label);
251 		if ( box !is null )
252 		{
253 			box.packStart(button, false, false, 7);
254 		}
255 		button.addOnClicked(&userActions);
256 		return button;
257 	}
258 	
259 	private void addPanels()
260 	{
261 		addPanel(new SelectionsPanel(this));
262 		version(gtkDdev)addPanel(new DevPanel(this));
263 		version(leds)	addPanel(new LedsPanel(this));
264 		version(compiler)	addPanel(new MainCompilerPanel(this));
265 		addPanel(new LocalPanel(this));
266 		addPanel(new InstallPanel(this));
267 		addPanel(new TestPanel(this));
268 	}
269 	
270 	CheckButton[char[]] tasksList;
271 	
272 	private void addPanel(UserPanel userPanel)
273 	{
274 		notebook.appendPage(userPanel.getWidget(), userPanel.getName());
275 		
276 		if ( userPanel.getName().length > 0 )
277 		{
278 			HBox hbox = new HBox(false, 1);
279 			CheckButton check = new CheckButton();
280 			hbox.packStart(check, false, false, 4);
281 			hbox.packStart(Alignment.west(new Label(userPanel.getName())), false, false, 4);
282 			tasksBox.packStart(hbox, false, false, 4);
283 			tasksList[userPanel.getName()] = check;
284 			check.setSensitive(false);
285 		}
286 		userPanels ~= userPanel;
287 	}
288 	
289 	private void userActions(Button button)
290 	{
291 		char[] action = button.getActionName();
292 		switch ( action )
293 		{
294 			case "exit":
295 				GtkD.exit(0);
296 				break;
297 			
298 			case "back":
299 				prevPanel();
300 				break;
301 				
302 			case "next":
303 				nextPanel();
304 				break;
305 		
306 			case "install":
307 				hide();
308 				new Installer(this);
309 				nextPanel();
310 				break;
311 		
312 			default:
313 				writefln("userAction = %s", action);
314 				break;
315 			
316 		}
317 	}
318 	
319 	private void setUserPanel(uint number)
320 	{
321 		if ( number < userPanels.length )
322 		{
323 			UserPanel panel = userPanels[number];
324 			setUserPanel(panel);
325 		}
326 	}
327 	
328 	public void setUserPanel(UserPanel panel)
329 	{
330 		if ( currentUserPanel !is null )
331 		{
332 			currentUserPanel.exited();
333 		}
334 		while ( !panel.selected() 
335 				&& movingDirection != 0
336 				)
337 		{
338 			if ( movingDirection > 0 )
339 			{
340 				nextPanel();
341 			}
342 			else
343 			{
344 				prevPanel();
345 			}
346 			return;
347 		}
348 		backButton.setSensitive(panel.allowBack());
349 		nextButton.setSensitive(panel.allowNext());
350 		bool allowInstall = true;
351 		foreach ( UserPanel userPanel ; userPanels )
352 		{
353 			if ( !userPanel.complete() )
354 			{
355 				allowInstall = false;
356 			}
357 			if ( userPanel.getName in tasksList )
358 			{
359 				tasksList[userPanel.getName()].setActive(userPanel.complete());
360 			}
361 		}
362 		installButton.setSensitive(allowInstall);
363 		currentUserPanel = panel;
364 	}
365 }
366 
367 class UserPanel
368 {
369 	InstallerUI installerUI;
370 	
371 	bool completed = false;
372 
373 	
374 	
375 	abstract Widget getWidget();
376 	abstract char[] getName();
377 	public this(InstallerUI installerUI)
378 	{
379 		this.installerUI = installerUI;
380 
381 	}
382 	public bool allowNext()
383 	{
384 		return true;
385 	}
386 	public bool allowBack()
387 	{
388 		return true;
389 	}
390 	public bool selected()
391 	{
392 		return true;
393 	}
394 	public bool exited()
395 	{
396 		return selected();
397 	}
398 	public bool complete()
399 	{
400 		return completed;
401 	}
402 	
403 	protected HBox newSelection(char[] selection, char[] id)
404 	{
405 		HBox box = new HBox(false, 2);
406 		
407 		Button button = new Button(StockID.HELP, &userHelp, true);
408 		button.setActionName(id);
409 		button.setImage(new Image(StockID.HELP, IconSize.MENU));
410 		CheckButton check = new CheckButton(selection, &userSelection);
411 		check.setActionName(id);
412 		
413 		box.packStart(button, false, false, 2);
414 		box.packStart(check, false, false, 2);
415 		installerUI.addSelection(id, check);
416 		return box;
417 	}
418 
419 	protected HBox newDirectory(char[] label, char[] id, SizeGroup sizeGroup)
420 	{
421 		HBox box = new HBox(false, 2);
422 		Button button = new Button(StockID.HELP, &userHelp, true);
423 		button.setActionName(id);
424 		button.setImage(new Image(StockID.HELP, IconSize.MENU));
425 		Entry entry = new Entry();
426 
427 		box.packStart(button, false, false, 2);
428 		Label l = new Label(label);
429 		Alignment alig = Alignment.west(l);
430 		sizeGroup.addWidget(alig);
431 		box.packStart(alig, false, false, 2);
432 		box.packStart(entry, true, true, 2);
433 		button = new Button(StockID.INDEX, &userDirectory);
434 		button.setActionName(id);
435 		button.setLabel("Browse");
436 		button.setImage(new Image(StockID.INDEX, IconSize.MENU));
437 		box.packStart(button, false, false, 2);
438 		installerUI.addDirectory(id, entry);
439 		return box;
440 	}
441 	
442 	protected HBox newButton(Button actionButton, char[] id)
443 	{
444 		HBox box = new HBox(false, 2);
445 		
446 		Button button = new Button(StockID.HELP, &userHelp, true);
447 		button.setActionName(id);
448 		button.setImage(new Image(StockID.HELP, IconSize.MENU));
449 		
450 		box.packStart(button, false, false, 2);
451 		box.packStart(actionButton, false, false, 2);
452 		return box;
453 	}
454 	
455 	void userSelection(CheckButton check)
456 	{
457 		switch ( check.getActionName() )
458 		{
459 			
460 			case "leds":
461 				bool active = cast(bool)check.getActive();
462 				installerUI.setSensitive("ledsGtkD", active);
463 				installerUI.setSensitive("ledsLeds", active);
464 				installerUI.setSensitive("ledsDool", active);
465 				installerUI.setSensitive("ledsDante", active);
466 				installerUI.setSensitive("ledsPhobos", active);
467 				break;
468 			
469 			default:
470 				// nothing
471 				break;
472 		}
473 	}
474 	
475 	void userHelp(Button button)
476 	{
477 		
478 	}
479 private import gtk.FileChooserDialog;
480 private import gtk.FileChooser;
481 	void userDirectory(Button button)
482 	{
483 		char[] id = button.getActionName();
484 		char[] dir = installerUI.getDirectory(id);
485 		if ( dir != null )
486 		{
487 			FileChooserDialog chooserDialog = new FileChooserDialog(
488 						"Select directory",
489 						mainInstaller,
490 						FileChooserAction.SELECT_FOLDER
491 						);
492 			FileChooser chooser = chooserDialog.getFileChooser();
493 			chooser.setCurrentFolder(dir);
494 			ResponseType response = cast(ResponseType)chooserDialog.run();
495 			if ( response == ResponseType.GTK_RESPONSE_OK )
496 			{
497 				installerUI.setDirectory(id, chooser.getCurrentFolder());
498 			}
499 			chooserDialog.hide(); // is it released ?
500 		}
501 	}
502 }
503 
504 class SelectionsPanel : UserPanel
505 {
506 	VBox vbox;
507 	
508 	public this(InstallerUI installerUI)
509 	{
510 		super(installerUI);
511 	}
512 	public char[] getName()
513 	{
514 		return "Selections";
515 	}
516 	public Widget getWidget()
517 	{
518 		if ( vbox is null )
519 		{
520 			vbox = new VBox(false, 2);
521 			setup();
522 		}
523 		return vbox;
524 	}
525 	
526 	public bool allowBack()
527 	{
528 		return false;
529 	}
530 	
531 	public bool selected()
532 	{
533 		completed = true;
534 		return true;
535 	}
536 	
537 	private void setup()
538 	{
539 		vbox.packStart(new Label("Select the components to install"), false, false, 14);
540 		vbox.packStart(newSelection("Install GtkD", "gtkD"), false, false, 2);
541 		version(gtkDdev) vbox.packStart(newSelection("Install GtkD for development", "gtkDDev"), false, false, 2);
542 		version(gtkDgl) vbox.packStart(newSelection("Install GtkDgl", "gtkDgl"), false, false, 2);
543 		version(gtkDdev) version(gtkDgl) vbox.packStart(newSelection("Install GtkDgl for development", "duiglDev"), false, false, 2);
544 		version(leds) vbox.packStart(newSelection("Install Leds", "leds"), false, false, 2);
545 
546 		installerUI.setSelection("gtkD", true);
547 		version(gtkDdev) installerUI.setSelection("gtkDDev", true);
548 		version(gtkDgl) installerUI.setSelection("gtkDgl", true);
549 		version(gtkDdev) version(gtkDgl) installerUI.setSelection("duiglDev", true);
550 		version(leds) installerUI.setSelection("leds", true);
551 
552 	}
553 	
554 }
555 
556 class DevPanel : UserPanel
557 {
558 	VBox vbox;
559 	
560 	public this(InstallerUI installerUI)
561 	{
562 		super(installerUI);
563 	}
564 	public char[] getName()
565 	{
566 		return "GtkD Development";
567 	}
568 	public Widget getWidget()
569 	{
570 		if ( vbox is null )
571 		{
572 			vbox = new VBox(false, 2);
573 			setup();
574 		}
575 		return vbox;
576 	}
577 	
578 	public bool selected()
579 	{
580 		completed = true;
581 		return installerUI.getSelection("gtkDDev")
582 				|| installerUI.getSelection("gtkDglDev");
583 	}
584 	
585 	private void setup()
586 	{
587 		vbox.packStart(new Label("Select GtkD modules"), false, false, 14);
588 		version(difiles) vbox.packStart(newSelection("GtkD .di files", "gtkDdi"), false, false, 2);
589 		vbox.packStart(newSelection("GtkD source files", "gtkDSource"), false, false, 2);
590 		vbox.packStart(newSelection("GtkDTests - general UI tests", "gtkDTests"), false, false, 2);
591 		version(gtkDgl) vbox.packStart(newSelection("SimpleGL - simplest GL test", "gtkDglSimple"), false, false, 2);
592 		version(gtkDgl) vbox.packStart(newSelection("ShapesGL - showing more of openGL integration", "gtkDglShapes"), false, false, 2);
593 
594 		version(difiles) installerUI.setSelection("gtkDdi", true);
595 		installerUI.setSelection("gtkDSource", true);
596 		installerUI.setSelection("gtkDTests", true);
597 		version(gtkDgl) installerUI.setSelection("gtkDglSimple", true);
598 		version(gtkDgl) installerUI.setSelection("gtkDglShapes", true);
599 
600 	}
601 	
602 }
603 
604 
605 class LedsPanel : UserPanel
606 {
607 	VBox vbox;
608 	
609 	public this(InstallerUI installerUI)
610 	{
611 		super(installerUI);
612 	}
613 	public char[] getName()
614 	{
615 		return "Leds projects";
616 	}
617 	public Widget getWidget()
618 	{
619 		if ( vbox is null )
620 		{
621 			vbox = new VBox(false, 2);
622 			setup();
623 		}
624 		return vbox;
625 	}
626 	
627 	public bool selected()
628 	{
629 		completed = true;
630 		return installerUI.getSelection("leds");
631 	}
632 	
633 	private void setup()
634 	{
635 		vbox.packStart(new Label("Select the leds projects to create"), false, false, 14);
636 		vbox.packStart(newSelection("Create a leds project for GtkD", "ledsGtkD"), false, false, 2);
637 		vbox.packStart(newSelection("Create a leds project for Leds", "ledsLeds"), false, false, 2);
638 		vbox.packStart(newSelection("Create a leds project for Dool", "ledsDool"), false, false, 2);
639 		vbox.packStart(newSelection("Create a leds project for Dante", "ledsDante"), false, false, 2);
640 		vbox.packStart(newSelection("Create a leds project for phobos", "ledsPhobos"), false, false, 2);
641 
642 		installerUI.setSelection("ledsGtkD", true);
643 		installerUI.setSelection("ledsLeds", true);
644 		installerUI.setSelection("ledsDool", true);
645 		installerUI.setSelection("ledsDante", true);
646 		installerUI.setSelection("ledsPhobos", true);
647 
648 	}
649 	
650 }
651 
652 
653 class MainCompilerPanel : UserPanel
654 {
655 	VBox vbox;
656 	
657 	public this(InstallerUI installerUI)
658 	{
659 		super(installerUI);
660 	}
661 	public char[] getName()
662 	{
663 		return "D Compiler";
664 	}
665 	public Widget getWidget()
666 	{
667 		if ( vbox is null )
668 		{
669 			vbox = new VBox(false, 2);
670 			setup();
671 		}
672 		return vbox;
673 	}
674 	
675 	public bool selected()
676 	{
677 		completed = true;
678 		return true;
679 	}
680 	
681 	private void setup()
682 	{
683 		vbox.packStart(new Label("Select your D compiler"), false, false, 14);
684 		
685 		vbox.packStart(new Label("For the installation"), false, false, 7);
686 		vbox.packStart(newSelection("Digital Mars DMD", "instalCompilerDMD"), false, false, 2);
687 		vbox.packStart(newSelection("gnu D GDC", "installCompilerGDC"), false, false, 2);
688 
689 		vbox.packStart(new Label("For your leds projects"), false, false, 7);
690 		vbox.packStart(newSelection("Digital Mars DMD", "ledsCompilerDMD"), false, false, 2);
691 		vbox.packStart(newSelection("gnu D GDC", "ledsCompilerGDC"), false, false, 2);
692 
693 		installerUI.setSelection("instalCompilerDMD", true);
694 		installerUI.setSelection("installCompilerGDC", false);
695 		version(leds) installerUI.setSelection("ledsCompilerDMD", true);
696 		version(leds) installerUI.setSelection("ledsCompilerGDC", false);
697 		
698 		installerUI.setSensitive("instalCompilerDMD", false);
699 		installerUI.setSensitive("installCompilerGDC", false);
700 		version(leds) installerUI.setSensitive("ledsCompilerDMD", false);
701 		version(leds) installerUI.setSensitive("ledsCompilerGDC", false);
702 	}
703 	
704 }
705 
706 
707 
708 class LocalPanel : UserPanel
709 {
710 	VBox vbox;
711 	SizeGroup sizeGroup;
712 	
713 	char[] home;
714 	
715 	public this(InstallerUI installerUI)
716 	{
717 		super(installerUI);
718 		sizeGroup = new SizeGroup(SizeGroupMode.HORIZONTAL);
719 		version(Win32)
720 		{
721 			home = std..string.toString(getenv("HOMEPATH"));
722 		}
723 		else
724 		{
725 			home = std..string.toString(getenv("HOME"));
726 		}
727 			
728 	}
729 	public char[] getName()
730 	{
731 		return "Local";
732 	}
733 	
734 	private import std.path;
735 	private import std.file;
736 	
737 	private bool validDir(char[] dir)
738 	{
739 		bool valid = dir.length > 0;
740 		return valid;
741 	}
742 	
743 	public bool validDMDHome()
744 	{
745 		bool valid = false;
746 		char[] dir = installerUI.getDirectory("dmdHome");
747 		valid = validDir(dir);
748 		if ( valid )
749 		{
750 			try
751 			{
752 				version(Win32) char[] dmd = std.path.join(std.path.join(dir ,"bin"), "dmd.exe");
753 				else  char[] dmd = std.path.join(std.path.join(dir ,"bin"), "dmd");
754 				std.file.isfile(dmd);
755 				version(Win32)
756 				{
757 					char[] dm = std.path.join(std.path.join(dir,"..\\dm"),"bin");
758 					char[] link = std.path.join(dm, "link.exe");
759 					std.file.isfile(link);
760 					char[] lib = std.path.join(dm, "lib.exe");
761 					std.file.isfile(lib);
762 				}
763 				else  char[] link = std.path.join(std.path.join(dir ,"bin"), "dmd");
764 				valid = true;
765 			}
766 			catch ( FileException pe )
767 			{
768 				valid = false;
769 			}
770 		}
771 		
772 		return valid;
773 	}
774 	
775 //	class GuessFile
776 //	{
777 //		char[] guess;
778 //		char[] fetch;
779 //		char[] userChoice;
780 //		bool create;
781 //		bool confirmed;
782 //		
783 //		bool isDir(char[] dir)
784 //		{
785 //			bool ok = false;
786 //			try
787 //			{
788 //				ok = cast(bool)std.file.isfile(dir);
789 //			}
790 //			catch ( FileException fe )
791 //			{
792 //				ok = false;
793 //			}
794 //			return ok;
795 //		}
796 //		
797 //		bool exists(char[] fileName)
798 //		{
799 //			bool ok = false;
800 //			try
801 //			{
802 //				ok = cast(bool)std.file.exists(fileName);
803 //			}
804 //			catch ( FileException fe )
805 //			{
806 //				ok = false;
807 //			}
808 //			return ok;
809 //		}
810 //	}
811 
812 	public char[] guessDMDHome()
813 	{
814 		char[] guess;
815 		version(Win32)
816 		{
817 			guess = "\\dmd";
818 		}
819 		else
820 		{
821 			guess = std.path.join(home, "dmd");
822 		}
823 		return guess;
824 	}
825 	
826 	public char[] guessGtkHome()
827 	{
828 		char[] guess;
829 		version(Win32)
830 		{
831 			guess = "\\Program Files\\Common Files\\GTK\\2.0\\bin";
832 		}
833 		else
834 		{
835 			guess = "/usr/lib";
836 		}
837 		return guess;
838 	}
839 	
840 	public char[] guessGtkDLibHome()
841 	{
842 		char[] guess;
843 		version(Win32)
844 		{
845 			guess = "\\Program Files\\Common Files\\GTK\\2.0\\bin";
846 		}
847 		else
848 		{
849 			guess = "/home/ruimt/usr/lib";
850 		}
851 		return guess;
852 	}
853 
854 	public char[] guessGtkDDevHome()
855 	{
856 		char[] guess;
857 		version(Win32)
858 		{
859 			guess = "\\testRelease";
860 		}
861 		else
862 		{
863 			guess = std.path.join(home, "devel/D/testInstall/GtkD1");
864 		}
865 		return guess;
866 	}
867 
868 	public char[] guessLedsHome()
869 	{
870 		char[] guess;
871 		version(Win32)
872 		{
873 			guess = "\\Program Files\\Common Files\\org\\dsource\\leds";
874 		}
875 		else
876 		{
877 			guess = std.path.join(home, "devel/D/Leds1");
878 		}
879 		return guess;
880 	}
881 
882 	
883 	public bool selected()
884 	{
885 		completed = true;
886 		version(dmd)
887 		{
888 			if ( completed )
889 			{
890 				completed = validDMDHome();
891 			}
892 		}
893 		version(gtkDdev)
894 		{
895 			if ( completed )
896 			{
897 				completed = installerUI.getDirectory("gtkDDevHome").length > 0;
898 			}
899 		}
900 		version(leds)
901 		{
902 			if ( completed )
903 			{
904 				completed = installerUI.getDirectory("ledsHome").length > 0;
905 			}
906 		}
907 		
908 		if ( completed )
909 		{
910 			completed = installerUI.getDirectory("gtkHome").length > 0;
911 		}
912 		if ( completed )
913 		{
914 			completed = installerUI.getDirectory("gtkDLibHome").length > 0;
915 		}
916 		
917 		return true;
918 	}
919 	public Widget getWidget()
920 	{
921 		if ( vbox is null )
922 		{
923 			vbox = new VBox(false, 2);
924 			setup();
925 		}
926 		return vbox;
927 	}
928 	private void setup()
929 	{
930 		vbox.packStart(new Label("Select the paths for installation"), false, false, 14);
931 		vbox.packStart(newDirectory("DMD home", "dmdHome", sizeGroup), false, false, 2);
932 		vbox.packStart(newDirectory("Gtk lib home", "gtkHome", sizeGroup), false, false, 2);
933 		vbox.packStart(newDirectory("GtkD lib home", "gtkDLibHome", sizeGroup), false, false, 2);
934 		version(gtkDdev) vbox.packStart(newDirectory("GtkD dev home", "gtkDDevHome", sizeGroup), false, false, 2);
935 		version(leds) vbox.packStart(newDirectory("leds home", "ledsHome", sizeGroup), false, false, 2);
936 		
937 		installerUI.setDirectory("dmdHome", guessDMDHome());
938 		installerUI.setDirectory("gtkHome", guessGtkHome());
939 		installerUI.setDirectory("gtkDLibHome", guessGtkDLibHome());
940 		version(gtkDdev) installerUI.setDirectory("gtkDDevHome", guessGtkDDevHome());
941 		version(leds) installerUI.setDirectory("ledsHome", guessLedsHome());
942 	}
943 }
944 
945 class InstallPanel : UserPanel
946 {
947 	VBox vbox;
948 	//bool installed = false;
949 	public this(InstallerUI installerUI)
950 	{
951 		super(installerUI);
952 	}
953 	public bool selected()
954 	{
955 		completed = true;
956 		return true;
957 	}
958 	public char[] getName()
959 	{
960 		return "Install";
961 	}
962 	public Widget getWidget()
963 	{
964 		if ( vbox is null )
965 		{
966 			vbox = new VBox(false, 2);
967 			setup();
968 		}
969 		return vbox;
970 	}
971 	
972 	bool allowNext()
973 	{
974 		return false;
975 	}
976 	
977 	private void setup()
978 	{
979 		Label label = new Label(
980 			"Thank you for installing GtkD\n"
981 			~"press Install to continue"
982 		);
983 		vbox.packStart(label, true, true, 2);
984 		
985 		version(gtkDtest) vbox.packStart(newSelection("Create desktop icon for gtkD tests", "gtkDTestsIcon"), false, false, 2);
986 		version(leds) vbox.packStart(newSelection("Create desktop icon for leds", "ledsIcon"), false, false, 2);
987 		version(leds) vbox.packStart(newSelection("set leds as your D editor", "ledsDEditor"), false, false, 2);
988 		
989 		version(gtkDtest) installerUI.setSelection("gtkDTestsIcon", false);
990 		version(leds) installerUI.setSelection("ledsIcon", false);
991 		version(leds) installerUI.setSelection("ledsDEditor", false);
992 
993 		version(gtkDtest) installerUI.setSensitive("gtkDTestsIcon", false);
994 		version(leds) installerUI.setSensitive("ledsIcon", false);
995 		version(leds) installerUI.setSensitive("ledsDEditor", false);
996 	}
997 }
998 
999 class TestPanel : UserPanel
1000 {
1001 	VBox vbox;
1002 	bool active;
1003 	//bool installed = false;
1004 	public this(InstallerUI installerUI)
1005 	{
1006 		super(installerUI);
1007 	}
1008 	public bool complete()
1009 	{
1010 		return !active;
1011 	}
1012 	public bool selected()
1013 	{
1014 		active = true;
1015 		completed = true;
1016 		return true;
1017 	}
1018 	public char[] getName()
1019 	{
1020 		return "";
1021 	}
1022 	public Widget getWidget()
1023 	{
1024 		if ( vbox is null )
1025 		{
1026 			vbox = new VBox(false, 2);
1027 			setup();
1028 		}
1029 		return vbox;
1030 	}
1031 	
1032 	bool allowNext()
1033 	{
1034 		return false;
1035 	}
1036 	
1037 	bool allowBack()
1038 	{
1039 		return false;
1040 	}
1041 
1042 	private void testButtonAction(Button button)
1043 	{
1044 		switch ( button.getActionName() )
1045 		{
1046 
1047 			default:
1048 				writefln("testButtonAction going for %s", button.getActionName());
1049 				std.process.system(button.getActionName());
1050 				break;
1051 		}
1052 
1053 	}
1054 	
1055 	private void setup()
1056 	{
1057 		Label label = new Label(
1058 			"Installation is complete\n"
1059 			~"press Exit to quit the installer\n"
1060 			~"or execute the test programs"
1061 		);
1062 		vbox.packStart(label, false, false, 2);
1063 		
1064 		Button button;
1065 		
1066 		version(gtkDtest)
1067 		{
1068 			if ( installerUI.getSelection("gtkDTests") )
1069 			{
1070 				button = new Button("gtkD Tests");
1071 				vbox.packStart(newButton(button, "helpGtkDTests"), false, false, 2);
1072 				button.setActionName(installerUI.getDirectory("gtkDDevHome")~"/gtkDTests");
1073 				button.addOnClicked(&testButtonAction);
1074 			}
1075 		}
1076 		version(gtkDgltest)
1077 		{
1078 			if ( installerUI.getSelection("gtkDglSimple") )
1079 			{
1080 				button = new Button("SimpleGL test");
1081 				button.setActionName(installerUI.getDirectory("gtkDDevHome")~"/SimpleGL");
1082 				button.addOnClicked(&testButtonAction);
1083 				vbox.packStart(newButton(button, "helpSimpleGLTest"), false, false, 2);
1084 			}
1085 			if ( installerUI.getSelection("gtkDglShapes") )
1086 			{
1087 				button = new Button("ShapesGL test");
1088 				button.setActionName(installerUI.getDirectory("gtkDDevHome")~"/ShapesGL");
1089 				button.addOnClicked(&testButtonAction);
1090 				vbox.packStart(newButton(button, "helpShapesGLTest"), false, false, 2);
1091 			}
1092 		}
1093 		version(leds)
1094 		{
1095 			if ( installerUI.getSelection("leds") )
1096 			{
1097 				button = new Button("Leds");
1098 				button.setActionName(installerUI.getDirectory("ledsHome")~"/leds");
1099 				button.addOnClicked(&testButtonAction);
1100 				vbox.packStart(newButton(button, "helpLedsTest"), false, false, 2);
1101 			}
1102 		}
1103 		
1104 	}
1105 }
1106 
1107 MainInstaller mainInstaller;
1108 
1109 int main(char[][] args)
1110 {
1111 	version(Win32)
1112 	{
1113 		GtkD.init(args);
1114 	}
1115 	else
1116 	{
1117 		GtkD.initMultiThread(args);
1118 	}
1119 	mainInstaller = new MainInstaller();
1120 	GtkD.main();
1121 	return 0;
1122 }