1 /// Use gtk.Builder for loading interface
2 module gtkui.builder;
3 
4 import std.experimental.logger;
5 import std.exception : enforce;
6 
7 import gtk.Builder;
8 import gtk.Widget;
9 import gtk.Window;
10 import gobject.ObjectG;
11 
12 import gtkui.base;
13 import gtkui.exception;
14 
15 ///
16 abstract class BuilderUI : GtkUI
17 {
18     mixin GtkUIHelper;
19 
20     /// parse xml ui and create elements
21     protected Builder builder;
22 
23     ///
24     this(string xml)
25     {
26         builder = new Builder;
27         enforce(builder.addFromString(xml), new GUIException("cannot create ui"));
28         setUpGtkWidgetFields();
29     }
30 
31     /// Use builder for getting objects
32     override ObjectG getObject(string name) { return builder.getObject(name); }
33 }
34 
35 /// Class for main UI controller
36 class MainBuilderUI : BuilderUI
37 {
38     mixin GtkUIHelper;
39 
40     import glib.Idle;
41     static import gtk.Main;
42     alias GtkMain = gtk.Main.Main;
43 
44 protected:
45     static bool __gtk_inited = false;
46 
47     /// run Main.init with empty args by default
48     static void initializeGtk(string[] args=[])
49     {
50         if (__gtk_inited) return;
51         __gtk_inited = true;
52         GtkMain.init(args);
53     }
54 
55     ///
56     void delegate()[] onQuitList;
57 
58     ///
59     void quit() { foreach(dlg; onQuitList) dlg(); }
60 
61 public:
62 
63     ///
64     Idle[] idles;
65 
66     ///
67     void addOnIdle(void delegate() fnc)
68     { idles ~= new Idle({ fnc(); return true; }); }
69 
70     ///
71     void runLoop() { GtkMain.run(); }
72 
73     ///
74     void exitLoop() { GtkMain.quit(); }
75 
76     ///
77     void addOnQuit(void delegate() dlg) { onQuitList ~= dlg; }
78 
79     ///
80     protected static string lastUsedCss;
81 
82     ///
83     static void updateStyle(string css, bool throwOnError=false)
84     {
85         import gtk.CssProvider;
86         import gdk.Screen;
87         import gtk.StyleContext;
88         import std.typecons : scoped;
89 
90         if (css != lastUsedCss)
91         {
92             lastUsedCss = css;
93             try
94             {
95                 auto prov = scoped!CssProvider;
96                 prov.loadFromData(css);
97 
98                 StyleContext.addProviderForScreen(Screen.getDefault(),
99                         prov, GTK_STYLE_PROVIDER_PRIORITY_USER);
100             }
101             catch (Throwable e)
102             {
103                 .error("error while loading style: ", e.msg);
104                 if (throwOnError) throw e;
105             }
106         }
107     }
108 
109     ///
110     this(string xml, string css="")
111     {
112         initializeGtk();
113         super(xml);
114         if (css.length)
115             updateStyle(css);
116     }
117 
118     /++
119         add on hide calling quit method
120      +/
121     void setupMainWindow(Window w)
122     {
123         w.addOnHide((Widget){ quit(); });
124         w.showAll();
125     }
126 }
127 
128 /// For child UI controllers
129 class ChildBuilderUI : BuilderUI
130 {
131     mixin GtkUIHelper;
132 
133     ///
134     this(string xml) { super(xml); }
135 
136     /// For adding by parent controller
137     abstract Widget mainWidget() @property;
138 }