Mercurial > otakunoraifu
comparison window/menuitem.cc @ 0:223b71206888
Initial import
author | thib |
---|---|
date | Fri, 01 Aug 2008 16:32:45 +0000 |
parents | |
children | 15a18fbe6f21 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:223b71206888 |
---|---|
1 /* | |
2 * Copyright (c) 2004-2006 Kazunori "jagarl" Ueno | |
3 * All rights reserved. | |
4 * | |
5 * Redistribution and use in source and binary forms, with or without | |
6 * modification, are permitted provided that the following conditions | |
7 * are met: | |
8 * 1. Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * 2. Redistributions in binary form must reproduce the above copyright | |
11 * notice, this list of conditions and the following disclaimer in the | |
12 * documentation and/or other materials provided with the distribution. | |
13 * 3. The name of the author may not be used to endorse or promote products | |
14 * derived from this software without specific prior written permission. | |
15 * | |
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
26 */ | |
27 | |
28 | |
29 #include"menuitem.h" | |
30 | |
31 #define Button WidButton | |
32 #define Scale WidScale | |
33 #define Label WidLabel | |
34 #define TextButton WidTextButton | |
35 #define Text WidText | |
36 | |
37 #define MenuItem WidMenuItem | |
38 #define RadioGroup WidRadioGroup | |
39 #define ScaleMenu WidScaleMenu | |
40 void fill(Surface* src, const Rect& rect, int r, int g, int b, int a = 0xff); | |
41 | |
42 MenuItem::MenuItem(PicContainer* parent, const Rect& r_orig, int _x_size, int _y_size, int* _value_ptr) : | |
43 x_size(_x_size), y_size(_y_size), value_ptr(_value_ptr), set_func(0), set_pointer(0) { | |
44 SetPic(parent->create_node(r_orig, 0)); | |
45 menu_width = r_orig.width(); | |
46 menu_height = r_orig.height(); | |
47 label = 0; | |
48 lb_width = 0; lb_right = 0; | |
49 lb_left = -1; lb_bottom = -1; | |
50 int i; | |
51 for (i=0; i<x_size*y_size; i++) item.push_back(0); | |
52 }; | |
53 void MenuItem::SetLabelLeft(PicWidget* lb, const Rect& min_rect, const Rect& min_margin) { | |
54 lb_width = min_rect.width(); | |
55 lb_right = min_margin.width(); | |
56 lb_left = -1; | |
57 lb_bottom = -1; | |
58 label = lb; | |
59 } | |
60 void MenuItem::SetLabelTop(PicWidget* lb, const Rect& left_margin, const Rect& bottom_margin) { | |
61 lb_left = left_margin.width(); | |
62 lb_bottom = bottom_margin.height(); | |
63 lb_width = -1; | |
64 lb_right = -1; | |
65 label = lb; | |
66 } | |
67 void MenuItem::SetValue(int new_value) { | |
68 SetValueImpl(new_value); | |
69 if (value_ptr) *value_ptr = new_value; | |
70 if (set_func) (*set_func)(set_pointer, this); | |
71 } | |
72 void MenuItem::activate(void) { | |
73 iterator it; | |
74 for (it=item.begin(); it!=item.end(); it++) { | |
75 if (*it == 0) continue; | |
76 (*it)->activate(); | |
77 } | |
78 } | |
79 void MenuItem::deactivate(void) { | |
80 iterator it; | |
81 for (it=item.begin(); it!=item.end(); it++) { | |
82 if (*it == 0) continue; | |
83 (*it)->deactivate(); | |
84 } | |
85 } | |
86 void MenuItem::pack(void) { | |
87 int x_min = 0, y_min = 0; | |
88 if (lb_width == -1) { // 上にラベルを貼る | |
89 if (lb_left < 0) lb_left = 0; | |
90 if (lb_bottom < 0) lb_bottom = 0; | |
91 if (label && label->Pic()) { | |
92 label->Pic()->Move(lb_left, 0); | |
93 y_min = lb_bottom + label->Pic()->Height(); | |
94 } else { | |
95 y_min = lb_bottom; | |
96 } | |
97 } else { // 左にラベルを貼る | |
98 if (lb_right < 0) lb_right = 0; | |
99 if (label && label->Pic()) { | |
100 int label_width = label->Pic()->Width(); | |
101 int label_height = label->Pic()->Height(); | |
102 if (label_width > lb_width - lb_right) { | |
103 x_min = label_width + lb_right; | |
104 } else { | |
105 x_min = lb_width; | |
106 } | |
107 } else { | |
108 x_min = lb_width; | |
109 } | |
110 } | |
111 int* item_width = new int[x_size]; | |
112 int* item_height = new int[y_size]; | |
113 int* item_x = new int[x_size]; | |
114 int* item_y = new int[y_size]; | |
115 int i,j; | |
116 for (i=0; i<x_size; i++) item_width[i]=0; | |
117 for (i=0; i<y_size; i++) item_height[i]=0; | |
118 | |
119 iterator it = item.begin(); | |
120 for (i=0; i<y_size; i++) { | |
121 for (j=0; j<x_size; j++) { | |
122 if (*it != 0 && (*it)->Pic() != 0) { | |
123 PicBase* pic = (*it)->Pic(); | |
124 if (item_width[j] < pic->Width()) item_width[j] = pic->Width(); | |
125 if (item_height[i] < pic->Height()) item_height[i] = pic->Height(); | |
126 } | |
127 it++; | |
128 } | |
129 } | |
130 int width=0, height=0; | |
131 for (i=0; i<x_size; i++) { | |
132 width += item_width[i]; | |
133 } | |
134 for (i=0; i<y_size; i++) { | |
135 height += item_height[i]; | |
136 } | |
137 | |
138 int x=x_min, y=y_min; | |
139 // width / height の再割り当て | |
140 if (menu_width > width + x_min) { | |
141 int dif = menu_width - width - x_min; | |
142 int n = x_size + 1; | |
143 x += dif/n; | |
144 for (i=0; i<x_size; i++) { | |
145 item_x[i] = x + item_width[i] / 2; | |
146 x += item_width[i] + dif*(i+2)/n - dif*(i+1)/n; | |
147 } | |
148 } else { | |
149 if (menu_width == 0) { | |
150 Pic()->SetSurfaceRect(Rect(0, 0, width+x_min, Pic()->Height())); | |
151 } | |
152 for (i=0; i<x_size; i++) { | |
153 item_x[i] = x + item_width[i] / 2; | |
154 x += item_width[i]; | |
155 } | |
156 } | |
157 if (menu_height > height+y_min) { | |
158 int dif = menu_height - height - y_min; | |
159 int n = y_size + 1; | |
160 y += dif/n; | |
161 for (i=0; i<y_size; i++) { | |
162 item_y[i] = y + item_height[i] / 2; | |
163 y += item_height[i] + dif*(i+2)/n - dif*(i+1)/n; | |
164 } | |
165 } else { | |
166 if (menu_height == 0) { | |
167 Pic()->SetSurfaceRect(Rect(0, 0, Pic()->Width(), height+y_min)); | |
168 } | |
169 for (i=0; i<y_size; i++) { | |
170 item_y[i] = y + item_height[i] / 2; | |
171 y += item_height[i]; | |
172 } | |
173 } | |
174 // 位置の再割り当て | |
175 it = item.begin(); | |
176 for (i=0; i<y_size; i++) { | |
177 for (j=0; j<x_size; j++) { | |
178 if (*it != 0 && (*it)->Pic() != 0) { | |
179 PicBase* pic = (*it)->Pic(); | |
180 int x0 = item_x[j]-pic->Width()/2; | |
181 int y0 = item_y[i]-pic->Height()/2; | |
182 pic->Move(x0, y0); | |
183 } | |
184 it++; | |
185 } | |
186 } | |
187 // 左にラベルがある場合、ラベルの高さ方向のセンタリング | |
188 if (label && label->Pic() && lb_width != -1) { | |
189 int label_width = label->Pic()->Width(); | |
190 int label_height = label->Pic()->Height(); | |
191 label->Pic()->Move(x_min-label_width-lb_right, (Pic()->Height() - label_height) / 2); | |
192 } | |
193 | |
194 delete[] item_width; | |
195 delete[] item_height; | |
196 delete[] item_x; | |
197 delete[] item_y; | |
198 }; | |
199 | |
200 RadioButton::RadioButton(Event::Container& _container, PicContainer* _parent, const Rect& r_orig, int _x_size, int _y_size, int* _value_ptr, const Rect& _button_r, int _text_size, const Color& _fore, const Color& _pressed, const Color& _back) : | |
201 MenuItem(_parent, r_orig, _x_size, _y_size,_value_ptr), | |
202 container(_container), parent(_parent), text_size(_text_size), button_rect(_button_r), buttons(0), | |
203 fore_color(_fore), pressed_color(_pressed), back_color(_back) { | |
204 } | |
205 void RadioButton::Add(const char* s, bool is_center) { | |
206 Add(s, fore_color, pressed_color, back_color, is_center); | |
207 } | |
208 void RadioButton::Add(const char* s, const Color& fore, const Color& pressed, const Color& back, bool is_center) { | |
209 if (buttons >= x_size*y_size) { | |
210 fprintf(stderr,"too many buttons (%d/%d) in RadioButton::Add ; text = %s\n",x_size,y_size,s); | |
211 return; | |
212 } | |
213 TextButton* wid = new TextButton(container, PicNode(), s, text_size, TextButton::Attribute(is_center ? TextButton::CENTER : 0), button_rect, 1, fore, pressed, back); | |
214 | |
215 wid->press_func = &PressCallback; | |
216 wid->press_pointer = (void*)this; | |
217 | |
218 if (value_ptr && buttons == *value_ptr) wid->Toggle(true); | |
219 int x_pos, y_pos; | |
220 if (y_size == 0) x_pos=buttons; | |
221 else x_pos = buttons / y_size, y_pos = buttons % y_size; | |
222 item[x_pos + y_pos*x_size] = wid; | |
223 buttons++; | |
224 }; | |
225 void RadioButton::PressCallback(void* pointer, Button* from) { | |
226 RadioButton* wid = (RadioButton*)pointer; | |
227 int i; | |
228 for (i=0; i<wid->x_size*wid->y_size; i++) { | |
229 if (from == wid->item[i]) { | |
230 wid->SetValue(i); | |
231 return; | |
232 } | |
233 } | |
234 return; | |
235 } | |
236 void RadioButton::SetValueImpl(int new_value) { | |
237 int i; | |
238 for (i=0; i<x_size*y_size; i++) { | |
239 Button* wid = dynamic_cast<Button*>(item[i]); | |
240 if (wid) { | |
241 if (i == new_value) wid->Toggle(true); | |
242 else wid->Toggle(false); | |
243 } | |
244 } | |
245 } |