1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "ultima/nuvie/core/nuvie_defs.h"
24 #include "ultima/nuvie/gui/gui_button.h"
25 #include "ultima/nuvie/gui/gui_load_image.h"
26 
27 namespace Ultima {
28 namespace Nuvie {
29 
30 /* the check marks bitmap */
31 Graphics::ManagedSurface *checkmarks = NULL;
32 
33 
GUI_Button(void * data,int x,int y,Graphics::ManagedSurface * image,Graphics::ManagedSurface * image2,GUI_CallBack * callback,bool free_surfaces)34 GUI_Button:: GUI_Button(void *data, int x, int y, Graphics::ManagedSurface *image,
35 						Graphics::ManagedSurface *image2, GUI_CallBack *callback, bool free_surfaces)
36 	: GUI_Widget(data, x, y, image->w, image->h) {
37 	callback_object = callback;
38 
39 	button = image;
40 	button2 = image2;
41 	freebutton = free_surfaces;
42 	for (int i = 0; i < 3; ++i) {
43 		pressed[i] = 0;
44 	}
45 	enabled = 1;
46 	buttonFont = NULL;
47 	freefont = 0;
48 	flatbutton = 0;
49 	is_checkable = 0;
50 	checked = 0;
51 	is_highlighted = false;
52 }
53 
GUI_Button(void * data,int x,int y,int w,int h,GUI_CallBack * callback)54 GUI_Button:: GUI_Button(void *data, int x, int y, int w, int h,
55 						GUI_CallBack *callback)
56 	: GUI_Widget(data, x, y, w, h) {
57 	callback_object = callback;
58 
59 	button = NULL;
60 	button2 = NULL;
61 	freebutton = 0;
62 	for (int i = 0; i < 3; ++i) {
63 		pressed[i] = 0;
64 	}
65 	enabled = 1;
66 	buttonFont = NULL;
67 	freefont = 0;
68 	flatbutton = 0;
69 	is_checkable = 0;
70 	checked = 0;
71 	is_highlighted = false;
72 }
73 
GUI_Button(void * data,int x,int y,int w,int h,const char * text,GUI_Font * font,int alignment,int is_checkbutton,GUI_CallBack * callback,int flat)74 GUI_Button::GUI_Button(void *data, int x, int y, int w, int h, const char *text,
75 					   GUI_Font *font, int alignment, int is_checkbutton,
76 					   GUI_CallBack *callback, int flat)
77 	: GUI_Widget(data, x, y, w, h) {
78 	callback_object = callback;
79 
80 	if (font != NULL) {
81 		buttonFont = font;
82 		freefont = 0;
83 	} else {
84 		buttonFont = new GUI_Font();
85 		freefont = 1;
86 	}
87 	flatbutton = flat;
88 	freebutton = 1;
89 	button = NULL;
90 	button2 = NULL;
91 
92 	is_checkable = is_checkbutton;
93 	checked = 0;
94 	is_highlighted = false;
95 	/*
96 	  if (is_checkable &&(checkmarks==NULL))
97 	  {
98 	    checkmarks=GUI_LoadImage(checker_w,checker_h,checker_pal,checker_data);
99 	    SDL_SetColorKey(checkmarks,SDL_SRCCOLORKEY,0);
100 	  }
101 	*/
102 	ChangeTextButton(-1, -1, -1, -1, text, alignment);
103 
104 	for (int i = 0; i < 3; ++i) {
105 		pressed[i] = 0;
106 	}
107 	enabled = 1;
108 }
109 
~GUI_Button()110 GUI_Button::~GUI_Button() {
111 	if (freebutton) {
112 		if (button)
113 			SDL_FreeSurface(button);
114 		if (button2)
115 			SDL_FreeSurface(button2);
116 	}
117 	if (freefont)
118 		delete buttonFont;
119 }
120 
121 /* Resize/reposition/change text */
ChangeTextButton(int x,int y,int w,int h,const char * text,int alignment)122 void GUI_Button::ChangeTextButton(int x, int y, int w, int h, const char *text, int alignment) {
123 	if (x != -1 || y != -1) {
124 		assert(x >= 0 && y >= 0);
125 		area.moveTo(x, y);
126 	}
127 
128 	if (w != -1 || h != -1) {
129 		assert(w >= 0 && h >= 0);
130 		area.setWidth(w);
131 		area.setHeight(h);
132 	}
133 
134 	if (freebutton) {
135 		if (button)
136 			SDL_FreeSurface(button);
137 		if (button2)
138 			SDL_FreeSurface(button2);
139 		if (flatbutton) {
140 			button = CreateTextButtonImage(BUTTON2D_UP, text, alignment);
141 			button2 = CreateTextButtonImage(BUTTON2D_DOWN, text, alignment);
142 		} else {
143 			button = CreateTextButtonImage(BUTTON3D_UP, text, alignment);
144 			button2 = CreateTextButtonImage(BUTTON3D_DOWN, text, alignment);
145 		}
146 	}
147 }
148 
149 /* Show the widget  */
Display(bool full_redraw)150 void GUI_Button:: Display(bool full_redraw) {
151 	Common::Rect src, dest = area;
152 
153 	if (button) {
154 		if ((button2 != NULL) && ((pressed[0]) == 1 || is_highlighted))
155 			SDL_BlitSurface(button2, NULL, surface, &dest);
156 		else
157 			SDL_BlitSurface(button, NULL, surface, &dest);
158 	}
159 	if (is_checkable) {
160 		src.left = 8 - (checked * 8);
161 		src.top = 0;
162 		src.setWidth(8);
163 		src.setHeight(10);
164 		dest.left += 4;
165 		dest.top += 4;
166 		dest.setWidth(8);
167 		dest.setHeight(10);
168 		SDL_BlitSurface(checkmarks, &src, surface, &dest);
169 	}
170 	if (!enabled) {
171 		uint8 *pointer;
172 		int pixel = SDL_MapRGB(surface->format, 0, 0, 0);
173 		uint8 bytepp = surface->format.bytesPerPixel;
174 
175 		if (!SDL_LockSurface(surface)) {
176 			for (int y = 0; y < area.height(); y += 2) {
177 				pointer = (uint8 *)surface->getPixels() + surface->pitch * (area.top + y) + (area.left * bytepp);
178 				for (int x = 0; x<area.width() >> 1; x++) {
179 					switch (bytepp) {
180 					case 1:
181 						*((uint8 *)(pointer)) = (uint8)pixel;
182 						pointer += 2;
183 						break;
184 					case 2:
185 						*((uint16 *)(pointer)) = (uint16)pixel;
186 						pointer += 4;
187 						break;
188 					case 3:  /* Format/endian independent */
189 						uint8 r, g, b;
190 
191 						r = (pixel >> surface->format.rShift) & 0xFF;
192 						g = (pixel >> surface->format.gShift) & 0xFF;
193 						b = (pixel >> surface->format.bShift) & 0xFF;
194 						*((pointer) + surface->format.rShift / 8) = r;
195 						*((pointer) + surface->format.gShift / 8) = g;
196 						*((pointer) + surface->format.bShift / 8) = b;
197 						pointer += 6;
198 						break;
199 					case 4:
200 						*((uint32 *)(pointer)) = (uint32)pixel;
201 						pointer += 8;
202 						break;
203 					}
204 				}
205 			}
206 			SDL_UnlockSurface(surface);
207 		}
208 	}
209 
210 	DisplayChildren();
211 }
212 
213 /* Mouse hits activate us */
MouseDown(int x,int y,Shared::MouseButton btn)214 GUI_status GUI_Button:: MouseDown(int x, int y, Shared::MouseButton btn) {
215 //	if(btn == SDL_BUTTON_WHEELUP || btn == SDL_BUTTON_WHEELDOWN)
216 //	  return GUI_PASS;
217 	if (enabled && (btn == Shared::BUTTON_LEFT || btn == Shared::BUTTON_RIGHT)) {
218 		pressed[0] = 1;
219 		Redraw();
220 	}
221 	return GUI_YUM;
222 }
223 
MouseUp(int x,int y,Shared::MouseButton btn)224 GUI_status GUI_Button::MouseUp(int x, int y, Shared::MouseButton btn) {
225 //	if (btn==SDL_BUTTON_WHEELUP || btn==SDL_BUTTON_WHEELDOWN)
226 //		return GUI_PASS;
227 	if ((btn == Shared::BUTTON_LEFT || btn == Shared::BUTTON_RIGHT) && (pressed[0])) {
228 		pressed[0] = 0;
229 		return Activate_button(x, y, btn);
230 	}
231 	return GUI_YUM;
232 }
233 
Activate_button(int x,int y,Shared::MouseButton btn)234 GUI_status GUI_Button::Activate_button(int x, int y, Shared::MouseButton btn) {
235 	if (x >= 0 && y >= 0) {
236 		if (callback_object && callback_object->callback(BUTTON_CB, this, widget_data) == GUI_QUIT)
237 			return GUI_QUIT;
238 	}
239 	Redraw();
240 	return GUI_YUM;
241 }
242 
MouseMotion(int x,int y,uint8 state)243 GUI_status GUI_Button::MouseMotion(int x, int y, uint8 state) {
244 	if ((pressed[0] == 1) && ((x < 0) || (y < 0))) {
245 		pressed[0] = 2;
246 		Redraw();
247 	}
248 	if ((pressed[0] == 2) && (x >= 0) && (y >= 0)) {
249 		pressed[0] = 1;
250 		Redraw();
251 	}
252 	return GUI_YUM;
253 }
254 
Disable()255 void GUI_Button::Disable() {
256 	enabled = 0;
257 	Redraw();
258 }
259 
Enable(int flag)260 void GUI_Button::Enable(int flag) {
261 	enabled = flag;
262 	Redraw();
263 }
264 
CreateTextButtonImage(int style,const char * text,int alignment)265 Graphics::ManagedSurface *GUI_Button::CreateTextButtonImage(int style, const char *text, int alignment) {
266 	Common::Rect fillrect;
267 	int th, tw;
268 	int tx = 0, ty = 0;
269 	char *duptext = 0;
270 
271 	Graphics::ManagedSurface *img = new Graphics::ManagedSurface(area.width(), area.height(),
272 		Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
273 
274 	if (img == NULL)
275 		return NULL;
276 
277 	uint32 color1 = SDL_MapRGB(img->format, BL_R, BL_G, BL_B);
278 	uint32 color2 = SDL_MapRGB(img->format, BS_R, BS_G, BS_B);
279 	uint32 color3 = SDL_MapRGB(img->format, BF_R, BF_G, BF_B);
280 	uint32 color4 = SDL_MapRGB(img->format, BI2_R, BI2_G, BI2_B);
281 
282 
283 	buttonFont->setColoring(0, 0, 0);
284 	buttonFont->setTransparency(true);
285 	buttonFont->textExtent(text, &tw, &th);
286 	if (tw > (area.width() - (4 + is_checkable * 16))) {
287 		int n = (area.width() - (4 + is_checkable * 16)) / buttonFont->charWidth();
288 		duptext = new char[n + 1];
289 		strncpy(duptext, text, n);
290 		duptext[n] = 0;
291 		text = duptext;
292 		buttonFont->textExtent(text, &tw, &th);
293 	}
294 	if (th > (area.height() - 4)) {
295 		text = "";
296 	}
297 	switch (alignment) {
298 	case BUTTON_TEXTALIGN_LEFT:
299 		tx = 4 + (is_checkable * 16);
300 		break;
301 	case BUTTON_TEXTALIGN_CENTER:
302 		tx = (area.width() - tw) >> 1;
303 		break;
304 	case BUTTON_TEXTALIGN_RIGHT:
305 		tx = area.width() - 5 - tw;
306 		break;
307 	}
308 	ty = (area.height() - th) >> 1;
309 
310 	if (!area.isEmpty()) {
311 		switch (style) {
312 		case BUTTON3D_UP:
313 			fillrect = Common::Rect(area.width(), 2);
314 			SDL_FillRect(img, &fillrect, color1);
315 			fillrect.moveTo(0, area.height() - 2);
316 			SDL_FillRect(img, &fillrect, color2);
317 
318 			fillrect = Common::Rect(2, area.height());
319 			SDL_FillRect(img, &fillrect, color1);
320 			fillrect.moveTo(area.width() - 2, 0);
321 			SDL_FillRect(img, &fillrect, color2);
322 
323 			fillrect.setHeight(1);
324 			fillrect.setWidth(1);
325 			SDL_FillRect(img, &fillrect, color1);
326 			fillrect.moveTo(1, area.height() - 1);
327 			SDL_FillRect(img, &fillrect, color2);
328 
329 			fillrect = Common::Rect(2, 2, area.width() - 2, area.height() - 2);
330 			SDL_FillRect(img, &fillrect, color3);
331 
332 			buttonFont->textOut(img, tx, ty, text);
333 			break;
334 		case BUTTON3D_DOWN:
335 			fillrect = Common::Rect(area.width(), area.height());
336 			SDL_FillRect(img, &fillrect, color3);
337 			buttonFont->textOut(img, tx + 1, ty + 1, text);
338 			break;
339 		case BUTTON2D_UP:
340 			fillrect = Common::Rect(area.width(), area.height());
341 			SDL_FillRect(img, &fillrect, color3);
342 			buttonFont->textOut(img, tx, ty, text);
343 			break;
344 		case BUTTON2D_DOWN:
345 			fillrect = Common::Rect(area.width(), area.height());
346 			SDL_FillRect(img, &fillrect, color4);
347 			buttonFont->setTransparency(false);
348 			buttonFont->setColoring(BI1_R, BI1_G, BI1_B, BI2_R, BI2_G, BI2_B);
349 			buttonFont->textOut(img, tx, ty, text);
350 			break;
351 		}
352 	}
353 
354 	delete[] duptext;
355 
356 	return img;
357 }
358 
359 } // End of namespace Nuvie
360 } // End of namespace Ultima
361