1 /*
2     GUILIB:  An example GUI framework library for use with SDL
3 */
4 
5 #include "GUI_widget.h"
6 
7 
8 /* Widget constructors */
GUI_Widget(void * data)9 GUI_Widget:: GUI_Widget(void *data)
10 {
11 	Init(data, 0, 0, 0, 0);
12 }
GUI_Widget(void * data,int x,int y,int w,int h)13 GUI_Widget:: GUI_Widget(void *data, int x, int y, int w, int h)
14 {
15 	Init(data, x, y, w, h);
16 }
17 void
Init(void * data,int x,int y,int w,int h)18 GUI_Widget:: Init(void *data, int x, int y, int w, int h)
19 {
20 	widget_data = data;
21 	screen = NULL;
22 	SetRect(x, y, w, h);
23 	Show();
24 	error = NULL;
25 	for (int n=0;n<3; ++n ) {
26 		pressed[n]=0;
27 	}
28 }
29 
30 /* Mark the widget as visible -- this is the default state */
31 void
Show(void)32 GUI_Widget:: Show(void)
33 {
34 	status = WIDGET_VISIBLE;
35 }
36 
37 /* Mark the widget as hidden;  no display, no events */
38 void
Hide(void)39 GUI_Widget:: Hide(void)
40 {
41 	status = WIDGET_HIDDEN;
42 }
43 
44 /* Mark the widget as free, so it will be deleted by the GUI */
45 void
Delete(void)46 GUI_Widget:: Delete(void)
47 {
48 	status = WIDGET_DELETED;
49 }
50 
51 /* Report status to GUI */
52 int
Status(void)53 GUI_Widget:: Status(void)
54 {
55 	return(status);
56 }
57 
58 /* Set the bounds of the widget.
59    If 'w' or 'h' is -1, that parameter will not be changed.
60  */
61 void
SetRect(int x,int y,int w,int h)62 GUI_Widget:: SetRect(int x, int y, int w, int h)
63 {
64 	area.x = x;
65 	area.y = y;
66 	if ( w >= 0 ) {
67 		area.w = w;
68 	}
69 	if ( h >= 0 ) {
70 		area.h = h;
71 	}
72 }
73 void
SetRect(SDL_Rect ** bounds)74 GUI_Widget:: SetRect(SDL_Rect **bounds)
75 {
76 	int minx, maxx;
77 	int miny, maxy;
78 	int i, v;
79 
80 	maxx = 0;
81 	maxy = 0;
82 	for ( i=0; bounds[i]; ++i ) {
83 		v = (bounds[i]->x+bounds[i]->w-1);
84 		if ( maxx < v ) {
85 			maxx = v;
86 		}
87 		v = (bounds[i]->y+bounds[i]->h-1);
88 		if ( maxy < v ) {
89 			maxy = v;
90 		}
91 	}
92 	minx = maxx;
93 	miny = maxy;
94 	for ( i=0; bounds[i]; ++i ) {
95 		v = bounds[i]->x;
96 		if ( minx > v ) {
97 			minx = v;
98 		}
99 		v = bounds[i]->y;
100 		if ( miny > v ) {
101 			miny = v;
102 		}
103 	}
104 	SetRect(minx, miny, (maxx-minx+1), (maxy-miny+1));
105 }
106 
107 /* Check to see if a point intersects the bounds of the widget.
108  */
109 int
HitRect(int x,int y)110 GUI_Widget:: HitRect(int x, int y)
111 {
112 	return(HitRect(x, y, area));
113 }
114 int
HitRect(int x,int y,SDL_Rect & rect)115 GUI_Widget:: HitRect(int x, int y, SDL_Rect &rect)
116 {
117 	int hit;
118 
119 	hit = 1;
120 	if ( (x < rect.x) || (x >= (rect.x+rect.w)) ||
121 	     (y < rect.y) || (y >= (rect.y+rect.h)) ) {
122 		hit = 0;
123 	}
124 	return(hit);
125 }
126 
127 /* Set the display surface for this widget */
128 void
SetDisplay(SDL_Surface * display)129 GUI_Widget:: SetDisplay(SDL_Surface *display)
130 {
131 	screen = display;
132 }
133 
134 /* Show the widget.
135    If the surface needs to be locked, it will be locked
136    before this call, and unlocked after it returns.
137 
138 ****************NO, NOT AT ALL IF I'M NOT TOO DUMB TO LOOK******
139 ******OTHERWISE YOU COULDN'T FILLRECT in Display(), ETC!!!! ***********
140  */
141 void
Display(void)142 GUI_Widget:: Display(void)
143 {
144 }
145 
146 /* Redraw the widget and only the widget */
Redraw(void)147 void GUI_Widget::Redraw(void)
148 {
149   if (status==WIDGET_VISIBLE)
150   {
151     Display();
152     SDL_UpdateRects(screen,1,&area);
153   }
154 }
155 
156 /* GUI idle function -- run when no events pending */
157 GUI_status
Idle(void)158 GUI_Widget:: Idle(void)
159 {
160 	return(GUI_PASS);
161 }
162 
163 /* Widget event handlers.
164    These functions should return a status telling the GUI whether
165    or not the event should be passed on to other widgets.
166    These are called by the default HandleEvent function.
167 */
168 GUI_status
KeyDown(SDL_keysym key)169 GUI_Widget:: KeyDown(SDL_keysym key)
170 {
171 	return(GUI_PASS);
172 }
173 GUI_status
KeyUp(SDL_keysym key)174 GUI_Widget:: KeyUp(SDL_keysym key)
175 {
176 	return(GUI_PASS);
177 }
178 GUI_status
MouseDown(int x,int y,int button)179 GUI_Widget:: MouseDown(int x, int y, int button)
180 {
181 	return(GUI_PASS);
182 }
183 GUI_status
MouseUp(int x,int y,int button)184 GUI_Widget:: MouseUp(int x, int y, int button)
185 {
186 	return(GUI_PASS);
187 }
188 GUI_status
MouseMotion(int x,int y,Uint8 state)189 GUI_Widget:: MouseMotion(int x, int y, Uint8 state)
190 {
191 	return(GUI_PASS);
192 }
193 
194 /* Main event handler function.
195    This function gets raw SDL events from the GUI.
196  */
197 GUI_status
HandleEvent(const SDL_Event * event)198 GUI_Widget:: HandleEvent(const SDL_Event *event)
199 {
200 	switch (event->type) {
201 		case SDL_KEYDOWN: {
202 			return(KeyDown(event->key.keysym));
203 		}
204 		break;
205 		case SDL_KEYUP: {
206 			return(KeyUp(event->key.keysym));
207 		}
208 		break;
209 		case SDL_MOUSEBUTTONDOWN: {
210 			int x, y, button;
211 			x = event->button.x;
212 			y = event->button.y;
213 			if ( HitRect(x, y) ) {
214 				button = event->button.button;
215 				return(MouseDown(x, y, button));
216 			}
217 		}
218 		break;
219 		case SDL_MOUSEBUTTONUP: {
220 			int x, y, button;
221 			x = event->button.x;
222 			y = event->button.y;
223 			button = event->button.button;
224 			if ( HitRect(x, y) )
225 			{
226 				button = event->button.button;
227 				return(MouseUp(x, y, button));
228 			}
229 			/* if widget was clicked before we must let it deactivate itself*/
230 			else if (ClickState(1)) return(MouseUp(-1,-1,button));
231 		}
232 		break;
233 		case SDL_MOUSEMOTION: {
234 			int x, y;
235 			Uint8 state;
236 			x = event->motion.x;
237 			y = event->motion.y;
238 			state = event->motion.state;
239 			if ( HitRect(x, y) )
240 			{
241   			  return(MouseMotion(x, y, state));
242 			}
243 			/* if widget was clicked before we must let it react*/
244 			else if (ClickState(1)) return(MouseMotion(-1,-1,state));
245 		}
246 		break;
247 		default: {
248 			/* Pass it along.. */;
249 		}
250 		break;
251 	}
252 	return(GUI_PASS);
253 }
254