1 /*
2     GUILIB:  An example GUI framework library for use with SDL
3 */
4 
5 #include <string.h>
6 
7 #include "SDL.h"
8 #include "GUI_button.h"
9 #include "GUI_loadimage.h"
10 
11 
12 /* the check marks bitmap */
13 #include "the_checker.h"
14 SDL_Surface *checkmarks=NULL;
15 
16 
17 
18 /* The default callback quits the GUI */
Default_ActiveProc(void * unused)19 static GUI_status Default_ActiveProc(void *unused)
20 {
21 	return(GUI_QUIT);
22 }
23 
24 
GUI_Button(void * data,int x,int y,SDL_Surface * image,SDL_Surface * image2,GUI_ActiveProc activeproc)25 GUI_Button:: GUI_Button(void *data, int x, int y, SDL_Surface *image,
26 			SDL_Surface *image2,GUI_ActiveProc activeproc)
27  : GUI_Widget(data, x, y, image->w, image->h)
28 {
29 	if ( activeproc == NULL ) {
30 		ActiveProc = Default_ActiveProc;
31 	} else {
32 		ActiveProc = activeproc;
33 	}
34 	button = image;
35 	button2 = image2;
36 	freebutton = 0;
37 	for (int i=0;i<3; ++i ) {
38   		pressed[i]=0;
39 	}
40 	enabled=1;
41 	buttonFont=NULL;
42 	freefont=0;
43 	flatbutton=0;
44 	is_checkable=0;
45 	checked=0;
46 }
47 
GUI_Button(void * data,int x,int y,int w,int h,GUI_ActiveProc activeproc)48 GUI_Button:: GUI_Button(void *data, int x, int y, int w, int h,
49 			GUI_ActiveProc activeproc)
50  : GUI_Widget(data, x, y, w, h)
51 {
52 	if ( activeproc == NULL ) {
53 		ActiveProc = Default_ActiveProc;
54 	} else {
55 		ActiveProc = activeproc;
56 	}
57 	button = NULL;
58 	button2 = NULL;
59 	freebutton = 0;
60 	for (int i=0;i<3; ++i ) {
61   		pressed[i]=0;
62 	}
63 	enabled=1;
64 	buttonFont=NULL;
65 	freefont=0;
66 	flatbutton=0;
67 	is_checkable=0;
68 	checked=0;
69 }
70 
GUI_Button(void * data,int x,int y,int w,int h,char * text,GUI_Font * font,int alignment,int is_checkbutton,GUI_ActiveProc activeproc,int flat)71 GUI_Button::GUI_Button(void *data, int x, int y, int w, int h, char *text,
72 		       GUI_Font *font, int alignment, int is_checkbutton,
73 		       GUI_ActiveProc activeproc, int flat)
74  : GUI_Widget(data,x,y,w,h)
75 {
76   if ( activeproc == NULL )
77     ActiveProc = Default_ActiveProc;
78   else
79     ActiveProc = activeproc;
80 
81   if (font!=NULL)
82   {
83     buttonFont=font;
84     freefont=0;
85   }
86   else
87   {
88    buttonFont=new GUI_Font();
89    freefont=1;
90   }
91   flatbutton=flat;
92   freebutton=1;
93   button=NULL;
94   button2=NULL;
95 
96   is_checkable=is_checkbutton;
97   checked=0;
98   if (is_checkable &&(checkmarks==NULL))
99   {
100     checkmarks=GUI_LoadImage(checker_w,checker_h,checker_pal,checker_data);
101     SDL_SetColorKey(checkmarks,SDL_SRCCOLORKEY,0);
102   }
103   ChangeTextButton(-1,-1,-1,-1,text,alignment);
104 
105   for (int i=0;i<3; ++i ) {
106   	pressed[i]=0;
107   }
108   enabled=1;
109 }
110 
~GUI_Button()111 GUI_Button::~GUI_Button()
112 {
113   if (freebutton)
114   {
115     if (button)
116       SDL_FreeSurface(button);
117     if (button2)
118       SDL_FreeSurface(button2);
119   }
120   if (freefont)
121     delete buttonFont;
122 }
123 
124 /* Resize/reposition/change text */
ChangeTextButton(int x,int y,int w,int h,char * text,int alignment)125 void GUI_Button::ChangeTextButton(int x, int y, int w, int h, char* text, int alignment)
126 {
127   if (x>=0)
128     area.x=x;
129   if (y>=0)
130     area.y=y;
131   if (w>=0)
132     area.w=w;
133   if (h>=0)
134     area.h=h;
135 
136   if (freebutton)
137   {
138     if (button)
139       SDL_FreeSurface(button);
140     if (button2)
141       SDL_FreeSurface(button2);
142     if (flatbutton)
143     {
144       button=CreateTextButtonImage(BUTTON2D_UP,text,alignment);
145       button2=CreateTextButtonImage(BUTTON2D_DOWN,text,alignment);
146     }
147     else
148     {
149       button=CreateTextButtonImage(BUTTON3D_UP,text,alignment);
150       button2=CreateTextButtonImage(BUTTON3D_DOWN,text,alignment);
151     }
152   }
153 }
154 
155 /* Show the widget  */
Display(void)156 void GUI_Button:: Display(void)
157 {
158 	if (button)
159 	{
160 	  if ((button2!=NULL) && (pressed[0])==1)
161 	    SDL_BlitSurface(button2,NULL,screen,&area);
162 	  else
163 	    SDL_BlitSurface(button,NULL,screen,&area);
164 	}
165 	if (is_checkable)
166 	{
167 /*
168 **** OLD VERSION WITH TEXT CHECKMARK ****
169 	  if (checked)
170 	  {
171 	    buttonFont->SetTransparency(1);
172 	    buttonFont->SetColoring(255,0,0);
173 	    buttonFont->TextOut(screen,area.x+4,area.y+4,textmark);
174 	  }
175 */
176 	  SDL_Rect src,dest=area;
177 	  src.x=8-(checked*8); src.y=0;
178 	  src.w=8; src.h=10;
179 	  dest.x+=4; dest.y+=4;
180 	  dest.w=8; dest.h=10;
181 	  SDL_BlitSurface(checkmarks,&src,screen,&dest);
182 	}
183 	if (!enabled)
184 	{
185 	  Uint8 *pointer;
186 	  int pixel=SDL_MapRGB(screen->format,0,0,0);;
187 	  Uint8 bytepp=screen->format->BytesPerPixel;
188 
189 	  if (!SDL_LockSurface(screen))
190 	  {
191 	    for (int y=0;y<area.h;y+=2)
192 	    {
193 	      pointer=(Uint8*)screen->pixels+screen->pitch*(area.y+y)+(area.x*bytepp);
194 	      for (int x=0;x<area.w>>1;x++)
195 	      {
196 	        switch (bytepp)
197 	        {
198 	        case 1:
199 		  *((Uint8 *)(pointer)) = (Uint8)pixel;
200 		  pointer+=2;
201 		  break;
202 	        case 2:
203 		  *((Uint16 *)(pointer)) = (Uint16)pixel;
204 		  pointer+=4;
205 		  break;
206 	        case 3:  /* Format/endian independent */
207 		  Uint8 r, g, b;
208 
209 		  r = (pixel>>screen->format->Rshift)&0xFF;
210 		  g = (pixel>>screen->format->Gshift)&0xFF;
211 		  b = (pixel>>screen->format->Bshift)&0xFF;
212 		  *((pointer)+screen->format->Rshift/8) = r;
213 		  *((pointer)+screen->format->Gshift/8) = g;
214 		  *((pointer)+screen->format->Bshift/8) = b;
215 		  pointer+=6;
216 		  break;
217 	        case 4:
218 		  *((Uint32 *)(pointer)) = (Uint32)pixel;
219 		  pointer+=8;
220 		  break;
221 	        }
222 	      }
223 	    }
224 	    SDL_UnlockSurface(screen);
225 	  }
226 	}
227 }
228 
229 /* Mouse hits activate us */
MouseDown(int x,int y,int button)230 GUI_status GUI_Button:: MouseDown(int x, int y, int button)
231 {
232 	if (enabled &&(button==1))
233 	{
234 	  pressed[0]=1;
235 	  Redraw();
236 	}
237 	return GUI_PASS;
238 }
239 
MouseUp(int x,int y,int button)240 GUI_status GUI_Button::MouseUp(int x,int y,int button)
241 {
242 	if ((button==1) && (pressed[0]))
243 	{
244 	  pressed[0]=0;
245 	  if ((x>=0) && (y>=0))
246 	    if (ActiveProc(widget_data)==GUI_QUIT)
247 	      return GUI_QUIT;
248 	  Redraw();
249 	}
250 	return GUI_PASS;
251 }
252 
MouseMotion(int x,int y,Uint8 state)253 GUI_status GUI_Button::MouseMotion(int x,int y,Uint8 state)
254 {
255 	if ((pressed[0]==1) && ((x<0) || (y<0)))
256 	{
257 	  pressed[0]=2;
258 	  Redraw();
259 	}
260 	if ((pressed[0]==2) && (x>=0) && (y>=0))
261 	{
262 	  pressed[0]=1;
263 	  Redraw();
264 	}
265 	return GUI_PASS;
266 }
267 
Disable()268 void GUI_Button::Disable()
269 {
270 	enabled=0;
271 	Redraw();
272 }
273 
Enable(int flag)274 void GUI_Button::Enable(int flag)
275 {
276 	enabled=flag;
277 	Redraw();
278 }
279 
CreateTextButtonImage(int style,char * text,int alignment)280 SDL_Surface* GUI_Button::CreateTextButtonImage(int style, char *text, int alignment)
281 {
282   SDL_Rect fillrect;
283   int th,tw,tx,ty;
284   SDL_Surface *img=SDL_AllocSurface(SDL_SWSURFACE,area.w,area.h,
285 				    16,31 << 11,63 << 5,31,0);
286   Uint32 color1=SDL_MapRGB(img->format,BL_R,BL_G,BL_B);
287   Uint32 color2=SDL_MapRGB(img->format,BS_R,BS_G,BS_B);
288   Uint32 color3=SDL_MapRGB(img->format,BF_R,BF_G,BF_B);
289   Uint32 color4=SDL_MapRGB(img->format,BI2_R,BI2_G,BI2_B);
290 
291   if (img==NULL) return NULL;
292 
293   buttonFont->SetColoring(0,0,0);
294   buttonFont->SetTransparency(1);
295   buttonFont->TextExtent(text,&tw,&th);
296   if (tw>(area.w-(4+is_checkable*16)))
297   {
298     text[(area.w-(4+is_checkable*16))/buttonFont->CharWidth()]=0;
299     buttonFont->TextExtent(text,&tw,&th);
300   }
301   if (th>(area.h-4))
302   {
303     text[0]=0;
304   }
305   switch (alignment)
306   {
307   case BUTTON_TEXTALIGN_LEFT:
308     tx=4+(is_checkable*16);
309     break;
310   case BUTTON_TEXTALIGN_CENTER:
311     tx=(area.w-tw) >> 1;
312     break;
313   case BUTTON_TEXTALIGN_RIGHT:
314     tx=area.w-5-tw;
315     break;
316   }
317   ty=(area.h-th) >> 1;
318 
319   switch (style)
320   {
321   case BUTTON3D_UP:
322     fillrect.x=0; fillrect.y=0;
323     fillrect.w=area.w; fillrect.h=2;
324     SDL_FillRect(img,&fillrect,color1);
325     fillrect.y=area.h-2;
326     SDL_FillRect(img,&fillrect,color2);
327     fillrect.x=0; fillrect.y=0;
328     fillrect.w=2; fillrect.h=area.h;
329     SDL_FillRect(img,&fillrect,color1);
330     fillrect.x=area.w-2;
331     SDL_FillRect(img,&fillrect,color2);
332     fillrect.h=1; fillrect.w=1;
333     SDL_FillRect(img,&fillrect,color1);
334     fillrect.x=1;
335     fillrect.y=area.h-1;
336     SDL_FillRect(img,&fillrect,color2);
337     fillrect.x=2; fillrect.y=2;
338     fillrect.w=area.w-4; fillrect.h=area.h-4;
339     SDL_FillRect(img,&fillrect,color3);
340     buttonFont->TextOut(img,tx,ty,text);
341     break;
342   case BUTTON3D_DOWN:
343     fillrect.x=0; fillrect.y=0;
344     fillrect.w=area.w; fillrect.h=area.h;
345     SDL_FillRect(img,&fillrect,color3);
346     buttonFont->TextOut(img,tx+1,ty+1,text);
347     break;
348   case BUTTON2D_UP:
349     fillrect.x=0; fillrect.y=0;
350     fillrect.w=area.w; fillrect.h=area.h;
351     SDL_FillRect(img,&fillrect,color3);
352     buttonFont->TextOut(img,tx,ty,text);
353     break;
354   case BUTTON2D_DOWN:
355     fillrect.x=0; fillrect.y=0;
356     fillrect.w=area.w; fillrect.h=area.h;
357     SDL_FillRect(img,&fillrect,color4);
358     buttonFont->SetTransparency(0);
359     buttonFont->SetColoring(BI1_R,BI1_G,BI1_B,BI2_R,BI2_G,BI2_B);
360     buttonFont->TextOut(img,tx,ty,text);
361     break;
362   }
363   return img;
364 }
365