1 import gtk
= gtk2
.gtk2
;
3 int main(string argv
[]) {
6 auto win
= 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);
72 table
.set_border_width(2);
73 table
.set_row_spacings(4);
74 table
.set_col_spacings(4);
76 foreach (y
, labelrow
; labels
)
77 foreach (x
, label
; labelrow
) {
78 auto but
= gtk
.Button
.new_with_label(cast(char*)label
);
79 but
.signal_connect
!"button-press-event"(&bpress_cb
, cast(void*)label
);
80 widget2this
[&but
.widget
] = &this;
81 attach_defaults(&but
.widget
, x
, x
+1, y
, y
+1);
85 static extern (C
) int bpress_cb(gtk
.Widget
* this_
, gtk
.Gdk2
.EventButton
* event
, void* user_data
) {
87 if (event
.type
==gtk
.EventType
.BUTTON_PRESS
&& event
.button
==1)
88 widget2this
[this_
].calc
.key(cast(immutable char*)user_data
);
93 // The code sitting between the keypad and the display:
95 // NOTE: The "diplay" could be another custom widget, just like the
96 // keypad, but to keep this example simple we'll use a gtk.Entry
100 double v
= 0, pv
= 0;
101 string display_string
;
103 bool entering
, haveprev
;
112 str0
= cast(char*)toStringz(display_string
);
116 this(typeof(disp
) disp
) {
118 disp
.set_alignment(1);
125 if (!entering
&& op
==pop)
130 display_string
= null;
137 case '+': v
= pv
+ v
; break;
138 case '-': v
= pv
- v
; break;
139 case '*': v
= pv
* v
; break;
140 case '/': v
= pv
/ v
; break;
144 display_string
= to
!string(v
);
149 void clear() { v
= 0; pv
= 0; display_string
= null; haveprev
= 0; entering
= 0; pop = 0; }
151 void key(immutable char* key
) {
155 case '0': .. case '9': case '.':
159 v
= to
!double(display_string
);
162 display_string
= display_string
[0..$-1];
163 v
= to
!double(display_string
);
167 display_string
= (k
=='.') ?
"0." : key
[0..1];
168 v
= to
!double(display_string
);
172 case '+', '-', '*', '/', '=': oper(k
); break;