1 module declui.backend;
2 
3 import declui.components;
4 
5 /**
6 The backend for a given UI toolkit.
7 It is used to create compoonents and to enter the main event loop.
8 */
9 interface ToolkitBackend
10 {
11 	/// Enters the main event loop for the backend.
12 	void run(string[] args, IWindow window);
13 
14 	/// Creates a window.
15 	IWindow window();
16 
17 	/// Creates a label.
18 	ILabel label();
19 
20 	/// Creates a button.
21 	IButton button();
22 
23 	/// Creates a menubar.
24 	IMenuBar menubar();
25 
26 	/// Creates a menu.
27 	IMenu menu();
28 
29 	/// Creates a menu button.
30 	IMenuButton menubutton();
31 }
32 
33 private static ToolkitBackend _backend = null;
34 
35 /// Gets the backend used to create compoonents.
36 ToolkitBackend dui()
37 {
38 	if (_backend is null)
39 	{
40 		_backend = createBackend();
41 	}
42 	return _backend;
43 }
44 
45 version(unittest) private ToolkitBackend createBackend()
46 {
47 	import declui.testing : TestingBackend;
48 	return new TestingBackend;
49 }
50 else private ToolkitBackend createBackend()
51 {
52 	import std.process : environment;
53 	import std.stdio : stderr;
54 	import core.stdc.stdlib : exit;
55 
56 	auto toolkit = environment.get("DECLUI_TOOLKIT", "gtk");
57 	if (toolkit !in _toolkits)
58 	{
59 		stderr.writefln!"Error: there is no toolkit registered under the name '%s'."(toolkit);
60 		stderr.writeln("The following toolkits are available:");
61 		foreach (name, _; _toolkits)
62 			stderr.writefln!"  - %s"(name);
63 		exit(1);
64 	}
65 
66 	return _toolkits[toolkit]();
67 }
68 
69 alias ToolkitFactory = ToolkitBackend function();
70 private ToolkitFactory[string] _toolkits;
71 
72 /**
73 Registers a new toolkit backend that can be used to run the app.
74 Params:
75   factory = The factory that can create a toolkit backend.
76   name = The name of the backend.
77 */
78 void registerToolkit(string name, ToolkitFactory factory)
79 {
80 	_toolkits[name] = factory;
81 }