1 import gtk
= gtk2
.gtk2
;
3 int main(string argv
[]) {
6 auto window
= new AppWin();
18 window
= gtk
.Window
.new_(gtk
.WindowType
.TOPLEVEL
);
20 set_title(cast(char*)"Hello World!");
21 set_default_size(200, 128);
23 this.signal_connect
!"delete-event"(&delete_cb
);
25 auto vbox
= gtk
.VBox
.new_(0, 0);
26 auto disp
= gtk
.Entry
.new_();
27 vbox
.add(&disp
.widget
);
28 vbox
.set_child_packing(&disp
.widget
, 0, 1, 0, gtk
.PackType
.START
);
30 auto calc
= new Calculator(disp
);
32 auto keypad
= new Keypad(calc
);
33 vbox
.add(&keypad
.widget
);
38 static extern (C
) int delete_cb(gtk
.Widget
* this_
, gtk
.Event
* event
, void* user_data
) {
45 // A custom widget, composited out of many std buttons:
51 // D lets us "magically" inherit the GTK object, but the "parent"
52 // widget has no idea about our pseudo-derived class. We keep a
53 // mapping from gtk-widgets to instances of this object;
54 // This also allows us to "cheat" and eg. redirect child widget
55 // callbacks directly to this "class".
56 static Keypad
*[gtk
.Widget
*] widget2this
;
60 enum colnum
=5, rownum
=4;
61 static immutable string
[colnum
][rownum
] labels
= [
62 ["7", "8", "9", "/", "C"],
63 ["4", "5", "6", "*", ""],
64 ["1", "2", "3", "-", ""],
65 ["0", ".", "=", "+", ""]
68 this(Calculator
* calc
) {
71 table
= gtk
.Table
.new_(colnum
, rownum
, 0);
77 foreach (y
, labelrow
; labels
)
78 foreach (x
, label
; labelrow
) {
79 auto but
= gtk
.Button
.new_with_label(cast(char*)label
);
80 but
.signal_connect
!"button-press-event"(&bpress_cb
, cast(void*)label
);
81 widget2this
[&but
.widget
] = &this;
82 attach_defaults(&but
.widget
, x
, x
+1, y
, y
+1);
86 static extern (C
) int bpress_cb(gtk
.Widget
* this_
, gtk
.Gdk2
.EventButton
* event
, void* user_data
) {
88 if (event
.type
==gtk
.EventType
.BUTTON_PRESS
&& event
.button
==1)
89 widget2this
[this_
].calc
.key(cast(immutable char*)user_data
);
94 // The code sitting between the keypad and the display:
96 // NOTE: The "diplay" could be another custom widget, just like the
97 // keypad, but to keep this example simple we'll use a gtk.Entry
101 double v
= 0, pv
= 0;
102 string display_string
;
104 bool entering
, haveprev
;
113 str0
= cast(char*)toStringz(display_string
);
117 this(typeof(disp
) disp
) {
119 disp
.set_alignment(1);
126 if (!entering
&& op
==pop)
131 display_string
= null;
138 case '+': v
= pv
+ v
; break;
139 case '-': v
= pv
- v
; break;
140 case '*': v
= pv
* v
; break;
141 case '/': v
= pv
/ v
; break;
145 display_string
= to
!string(v
);
150 void clear() { v
= 0; pv
= 0; display_string
= null; haveprev
= 0; entering
= 0; pop = 0; }
152 void key(immutable char* key
) {
156 case '0': .. case '9': case '.':
160 v
= to
!double(display_string
);
163 display_string
= display_string
[0..$-1];
164 v
= to
!double(display_string
);
168 display_string
= (k
=='.') ?
"0." : key
[0..1];
169 v
= to
!double(display_string
);
173 case '+', '-', '*', '/', '=': oper(k
); break;