1 module easyd.gtk.widgets;
2 
3 // (C) 2014-2019 by Matthias Rossmy
4 // This file is distributed under the "Fair Use License v2"
5 
6 import easyd.base;
7 import easyd.gtk.base;
8 
9 import core.vararg;
10 
11 import gtk.Button;
12 import gtk.Entry;
13 import gtk.EditableIF;
14 import gtk.SpinButton;
15 import gtk.CheckButton;
16 import gtk.ScrolledWindow;
17 import gtk.TreeView;
18 import gtk.TreeIter;
19 import gtk.TreeViewColumn;
20 import gtk.TreePath;
21 import gtk.Widget;
22 import gtk.CellRenderer;
23 import gtk.CellRendererText;
24 import gtk.TreeStore;
25 import gdk.Pixbuf;
26 
27 class Button : gtk.Button.Button
28 {
29     void delegate()[] onClick;
30 
31     this(string s, void delegate() onclick=null)
32     {
33         super(s);
34         addOnClicked(&onClickFunc);
35         if(onclick !is null)
36         {
37             onClick ~= onclick;
38         }
39     }
40 
41     this(StockID id, void delegate() onclick=null)
42     {
43         super(id);
44         addOnClicked(&onClickFunc);
45         if(onclick !is null)
46         {
47             onClick ~= onclick;
48         }
49     }
50 
51     protected void onClickFunc(gtk.Button.Button b)
52     {
53         onClick.trigger();
54     }
55 }
56 
57 class LineEdit : Entry, IBindable!string
58 {
59     void delegate(string)[] onChange;
60 	void delegate()[] onPressEnter;
61 
62     this()
63     {
64         super();
65         addOnChanged(&onChangeFunc);
66 		addOnActivate(&onPressEnterFunc);
67     }
68 
69     protected void onChangeFunc(EditableIF e)
70     {
71         onChange.trigger((cast(Entry)e).getText());
72     }
73 
74 	protected void onPressEnterFunc(Entry e)
75 	{
76 		onPressEnter.trigger;
77 	}
78 
79 	@property string value()
80 	{
81 		return getText;
82 	}
83 	alias value this;
84 
85 	@property void value(string val)
86 	{
87 		setText(val);
88 	}
89 }
90 
91 class SpinBox(T) : gtk.SpinButton.SpinButton, IBindable!T
92 {
93 	this(real min=0, real max=100, real step=1)
94 	{
95 		super(min,max,step);
96 	}
97 
98 	@property T value()
99 	{
100 		return getValue.to!T;
101 	}
102 	alias value this;
103 	
104 	@property void value(T val)
105 	{
106 		setValue(val);
107 	}
108 }
109 
110 class CheckBox : gtk.CheckButton.CheckButton, IBindable!bool
111 {
112 	this(string label="")
113 	{
114 		super(label);
115 	}
116 
117 	@property bool value()
118 	{
119 		return getActive;
120 	}
121 	alias value this;
122 	
123 	@property void value(bool val)
124 	{
125 		setActive(val);
126 	}
127 }
128 
129 class TreeView : ScrolledWindow
130 {
131     gtk.TreeView.TreeView treeView;
132     alias treeView this;
133 	bool expandOnClick=true;
134 	void delegate(TreeIter)[] onChangeCursor;
135 	void delegate(TreeIter)[] onActivateRow;
136 	protected int handleChangeCursor=1;
137 
138     this()
139     {
140         super();
141         treeView = new gtk.TreeView.TreeView();
142         add(treeView);
143 		treeView.addOnCursorChanged(&onCursorChangeFunc);
144 		treeView.addOnRowActivated(&onRowActivatedFunc);
145 		treeView.addOnButtonRelease(&onButtonReleaseFunc);
146     }
147 
148     TreeViewColumn addCol(string name)
149     {
150         auto col = new TreeViewColumn;
151         appendColumn(col);
152         col.setTitle(name);
153         setHeadersVisible(getNColumns>1);
154         return col;
155     }
156 
157     TreeViewColumn addTextCol(string name, int modelcol)
158     {
159         auto col = addCol(name);
160         col.add!CellRendererText("text",modelcol);
161         return col;
162     }
163 
164     TreeIter addRow(...)
165     {
166         //writeln("addRow...");
167         int x;
168         TreeIter it;
169         if(_arguments[0] == typeid(TreeIter))
170         {
171             it = (cast(TreeStore)getModel).createIter(va_arg!(TreeIter)(_argptr));
172             x = 1;
173         }
174         else
175         {
176             //writeln("Creating columns...");
177             if(getNColumns==0)
178             {
179                 for (int col=0; col < _arguments.length; col++)
180                 {
181                     if (_arguments[col] == typeid(string))
182                     {
183                         addTextCol("",col);
184                     }
185                     else
186                     {
187                         throw new Exception("Can't auto-create view columns for a model that contains other types than strings");
188                     }
189                 }
190             }
191             //writeln("Creating model...");
192             if(getModel() is null)
193             {
194                 GType[] types;
195                 for (int col=0; col < _arguments.length; col++)
196                 {
197                     if (_arguments[col] == typeid(int))
198                     {
199                         types ~= GType.INT;
200                     }
201                     if (_arguments[col] == typeid(string))
202                     {
203                         types ~= GType.STRING;
204                     }
205                     if (_arguments[col] == typeid(Pixbuf))
206                     {
207                         types ~= Pixbuf.getType;
208                     }
209                 }
210                 setModel(new TreeStore(types));
211             }
212             //writeln("Getting iterator...");
213             it = (cast(TreeStore)getModel).createIter();
214             x = 0;
215         }
216         //writeln("Setting values...");
217         for (int col=0; x < _arguments.length; x++,col++)
218         {
219             if (_arguments[x] == typeid(int))
220             {
221                 (cast(TreeStore)getModel).setValue(it,col,va_arg!(int)(_argptr));
222             }
223             if (_arguments[x] == typeid(string))
224             {
225                 (cast(TreeStore)getModel).setValue(it,col,va_arg!(string)(_argptr));
226             }
227             if (_arguments[x] == typeid(Pixbuf))
228             {
229                 (cast(TreeStore)getModel).setValue(it,col,va_arg!(Pixbuf)(_argptr)); 
230             }
231         }
232         //writeln("...finished addRow");
233         return it;
234     }
235     
236     void delRow(TreeIter it)
237     {
238 		(cast(TreeStore)getModel).remove(it);
239 	}
240 
241     void clear()
242     {
243         if(getModel() !is null)
244         {
245 			handleChangeCursor--;
246 			(cast(TreeStore)getModel).clear;
247 			handleChangeCursor++;
248 			//GC.collect;
249         }
250     }
251 
252     void setSelectedIter(TreeIter it, int col=0)
253     {
254         treeView.setCursor(it.getTreePath,getColumn(col),0);
255     }
256 
257 	/*Guid id(TreeIter it, int col=1)
258 	{
259 		if(it is null) return Guid.invalid;
260 		//writeln(getModel.getValueString(it,col));
261 		return Guid(BigInt("0x" ~ getModel.getValueString(it,col)));
262 	}*/
263 
264 	TreeIter currentIter()
265 	{
266 		TreePath p;
267 		TreeViewColumn c;
268 		getCursor(p,c);
269 		if(p)
270 		{
271 			return new TreeIter(getModel(),p);
272 		}else{
273 			return null;
274 		}
275 	}
276 
277 	/*Guid currentId(int col=1)
278 	{
279 		return id(currentIter,col);
280 	}*/
281 
282     protected void onCursorChangeFunc(gtk.TreeView.TreeView tv)
283     {
284 		if(handleChangeCursor<1) return;
285         TreePath p;
286         TreeViewColumn c;
287         getCursor(p,c);
288         //writeln(p);
289 		if(p)
290 		{
291 			onChangeCursor.trigger(new TreeIter(getModel(),p));
292 			handleChangeCursor--;
293 			treeView.setCursor(p,c,false);
294 			handleChangeCursor++;
295 		}
296     }
297 
298 	protected void onRowActivatedFunc(TreePath p, TreeViewColumn c, gtk.TreeView.TreeView tv)
299 	{
300 		onActivateRow.trigger(new TreeIter(getModel(),p));
301 		treeView.setCursor(p,c,false);
302 	}
303 	
304 	protected bool onButtonReleaseFunc(GdkEventButton* e, Widget w)
305 	{
306 		//writeln("Release ",e.button);
307 		if(e.button==1 && expandOnClick)
308 		{
309 			TreePath p;
310 			TreeViewColumn c;
311 			getCursor(p,c);
312 			expandRow(p,false);
313 		}
314 		return false;
315 	}
316 }
317 
318 CellRenderer add(TRend)(TreeViewColumn col, ...)
319 {
320     auto rend = new TRend;
321     col.packStart(rend,0);
322     for (int x=0; x < _arguments.length; x+=2)
323     {
324         col.addAttribute(rend,va_arg!(string)(_argptr),va_arg!(int)(_argptr));
325     }
326     return rend;
327 }
328