Mercurial > projects > dynamin
annotate dynamin/gui/button.d @ 103:73060bc3f004
Change license to Boost 1.0 and MPL 2.0.
author | Jordan Miner <jminer7@gmail.com> |
---|---|
date | Tue, 15 May 2012 22:06:02 -0500 |
parents | 651082a9b364 |
children |
rev | line source |
---|---|
0 | 1 |
2 /* | |
103
73060bc3f004
Change license to Boost 1.0 and MPL 2.0.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
3 * Copyright Jordan Miner |
0 | 4 * |
103
73060bc3f004
Change license to Boost 1.0 and MPL 2.0.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
5 * This Source Code Form is subject to the terms of the Mozilla Public |
73060bc3f004
Change license to Boost 1.0 and MPL 2.0.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
6 * License, v. 2.0. If a copy of the MPL was not distributed with this |
73060bc3f004
Change license to Boost 1.0 and MPL 2.0.
Jordan Miner <jminer7@gmail.com>
parents:
78
diff
changeset
|
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
0 | 8 * |
9 */ | |
10 | |
11 module dynamin.gui.button; | |
12 | |
13 import dynamin.all_core; | |
14 import dynamin.all_gui; | |
15 import dynamin.all_painting; | |
62 | 16 import dynamin.gui.control; |
17 import dynamin.gui.events; | |
0 | 18 import tango.io.Stdout; |
19 import dynamin.c.cairo; // TODO: remove | |
20 | |
21 // TODO: maybe change to ControlState and add Disabled ? | |
22 enum ButtonState { | |
23 Normal, Hot, Pressed | |
24 } | |
25 // TODO: move to another file | |
26 enum TextImageRelation { | |
27 Overlay, TextBeforeImage, ImageBeforeText, TextAboveImage, ImageAboveText | |
28 } | |
29 | |
30 /** | |
31 * A button is a control that can be clicked to perform an action. | |
32 * | |
33 * The appearance of a button with Windows Classic: | |
34 * | |
35 * $(IMAGE ../web/example_button.png) | |
36 */ | |
37 class Button : Control { | |
38 protected: | |
62 | 39 package bool _isDefault; |
0 | 40 ButtonState _state; |
62 | 41 override void whenFocusGained(EventArgs e) { |
42 super.whenFocusGained(e); | |
43 auto anc = findAncestor((Container c) { | |
44 return c.defaultButton !is null; | |
45 }); | |
46 if(anc) { | |
47 foreach(d; &anc.descendants) { | |
48 if(auto b = cast(Button)d) | |
49 b._isDefault = false; | |
50 } | |
51 } | |
52 _isDefault = true; | |
53 } | |
54 override void whenFocusLost(EventArgs e) { | |
55 super.whenFocusLost(e); | |
56 _isDefault = false; | |
57 auto anc = findAncestor((Container c) { | |
58 return c.defaultButton !is null; | |
59 }); | |
60 if(anc) | |
61 anc.defaultButton._isDefault = true; | |
62 } | |
0 | 63 override void whenMouseDragged(MouseEventArgs e) { |
64 if(contains(e.x, e.y)) | |
65 state = ButtonState.Pressed; | |
66 else | |
67 state = ButtonState.Normal; | |
68 } | |
69 override void whenMouseEntered(EventArgs e) { | |
70 state = ButtonState.Hot; | |
71 } | |
72 override void whenMouseLeft(EventArgs e) { | |
73 state = ButtonState.Normal; | |
74 } | |
75 override void whenMouseDown(MouseEventArgs e) { | |
76 if(e.button == MouseButton.Left) { | |
77 state = ButtonState.Pressed; | |
78 focus(); | |
79 } | |
80 } | |
81 override void whenMouseUp(MouseEventArgs e) { | |
82 if(state != ButtonState.Pressed) return; | |
83 state = ButtonState.Hot; | |
84 clicked(new EventArgs); | |
85 } | |
86 override void whenKeyDown(KeyEventArgs e) { | |
62 | 87 if(e.key == Key.Space) { |
0 | 88 state = ButtonState.Pressed; |
62 | 89 e.stopped = true; |
90 } else if(e.key == Key.Enter) { // being default is implied in keyDown | |
91 scope e2 = new EventArgs; | |
92 clicked(e2); | |
93 e.stopped = true; | |
94 } | |
0 | 95 } |
96 override void whenKeyUp(KeyEventArgs e) { | |
97 if(e.key == Key.Space) { | |
98 if(state != ButtonState.Pressed) return; | |
99 state = ButtonState.Normal; | |
62 | 100 scope e2 = new EventArgs; |
101 clicked(e2); | |
102 e.stopped = true; | |
0 | 103 } |
104 } | |
105 override void whenPainting(PaintingEventArgs e) { | |
106 Theme.current.Button_paint(this, e.graphics); | |
107 return; | |
108 // TODO: move to a theme or delete | |
109 with(e.graphics) { | |
110 if(_state == ButtonState.Hot) | |
111 source = Color(200, 0, 0); | |
112 else if(_state == ButtonState.Pressed) | |
113 source = Color(110, 0, 0); | |
114 else | |
115 source = Color(220, 80, 80); | |
116 moveTo(3, 0); | |
117 lineTo(width-3, 0); | |
118 lineTo(width, 3); | |
119 lineTo(width, height-3); | |
120 lineTo(width-3, height); | |
121 lineTo(3, height); | |
122 lineTo(0, height-3); | |
123 lineTo(0, 3); | |
124 closePath(); | |
125 fill(); | |
126 auto grad = cairo_pattern_create_linear(0, 0, 0, height/2+3); | |
127 cairo_pattern_add_color_stop_rgba(grad, 0, 1, 1, 1, .4); | |
128 cairo_pattern_add_color_stop_rgba(grad, 1, 1, 1, 1, .05); | |
129 cairo_set_source(handle, grad); | |
130 cairo_pattern_destroy(grad); | |
131 moveTo(3, 0); | |
132 lineTo(width-3, 0); | |
133 lineTo(width, 3); | |
134 lineTo(width, cast(int)height/2-3); | |
135 lineTo(width-3, cast(int)height/2); | |
136 lineTo(3, cast(int)height/2); | |
137 lineTo(0, cast(int)height/2+3); | |
138 lineTo(0, 3); | |
139 closePath(); | |
140 fill(); | |
141 | |
142 source = _state == ButtonState.Pressed ? Color.White : Color.Black; | |
143 fontSize = 13; | |
144 drawText(text, 5, height/2); | |
145 } | |
146 return; | |
147 | |
148 } | |
149 public void paintFore(Graphics g) { | |
150 auto extents = g.getTextExtents(text); | |
151 g.drawText(text, (width-extents.width)/2, (height-extents.height)/2); | |
152 } | |
153 | |
154 public: | |
10
ccc108b25a0a
Convert to using a struct for events. Fix some comments too.
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
155 /// Override this method in a subclass to handle the clicked event. |
0 | 156 protected void whenClicked(EventArgs e) { } |
157 /// This event occurs after the button has been clicked. | |
10
ccc108b25a0a
Convert to using a struct for events. Fix some comments too.
Jordan Miner <jminer7@gmail.com>
parents:
0
diff
changeset
|
158 Event!(whenClicked) clicked; |
0 | 159 |
63 | 160 /// |
0 | 161 this() { |
78
651082a9b364
Add Event.setUp() and use in place of mainHandler and dispatcher.
Jordan Miner <jminer7@gmail.com>
parents:
63
diff
changeset
|
162 clicked.setUp(&whenClicked); |
0 | 163 _focusable = true; |
164 } | |
63 | 165 /// |
0 | 166 this(string text) { |
167 this(); | |
168 this.text = text; | |
169 } | |
170 override Size bestSize() { return Theme.current.Button_bestSize(this); } | |
63 | 171 /// |
0 | 172 ButtonState state() { return _state; } |
63 | 173 /// |
0 | 174 void state(ButtonState s) { _state = s; repaint(); } |
62 | 175 /** |
176 * Returns true if this button should be painted as being default. | |
177 * Mainly for themes. | |
178 */ | |
179 bool isDefault() { return _isDefault; } | |
0 | 180 } |