1 /*
2  *  JLib - Jacob's Library.
3  *  Copyright (C) 2003, 2004  Juan Carlos Seijo P�rez
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Library General Public
7  *  License as published by the Free Software Foundation; either
8  *  version 2 of the License, or (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  Library General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Library General Public
16  *  License along with this library; if not, write to the Free
17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  *  Juan Carlos Seijo P�rez
20  *  jacob@mainreactor.net
21  */
22 
23 /** Menu en pantalla compuesto de imag�nes.
24  * @file    JImageMenu.cpp
25  * @author  Juan Carlos Seijo P�rez
26  * @date    28/04/2004
27  * @version 0.0.1 - 28/04/2004 - Primera versi�n.
28  * @version 0.0.2 - 25/09/2004 - Modificaci�n del m�todo 2D de Pos() para aceptar floats (quita libertad sino).
29  */
30 
31 #include <JLib/Graphics/JImageMenu.h>
32 
Select()33 bool JImageMenuEntry::Select()
34 {
35 	if (Action)
36 	{
37 		Action(data);
38 		return true;
39 	}
40 
41 	return false;
42 }
43 
JImageMenu()44 JImageMenu::JImageMenu()
45 {
46 	curOption = options.NewIterator();
47 }
48 
ApplyLayout(JTree<JImageMenuEntry * >::Iterator * it)49 void JImageMenu::ApplyLayout(JTree<JImageMenuEntry *>::Iterator *it)
50 {
51 	// Si es distribuci�n libre, lo especificar�n desde fuera
52 	if (config.layout == JIMAGEMENU_FREE)
53 	{
54 		return;
55 	}
56 
57 	s32 maxX = 0;
58 	s32 xOff = 0, yOff = 0;
59 
60 	// Determina la anchura m�xima entre todas las opciones de esta rama
61 	do
62 	{
63 		maxX = maxX < it->Data()->Image()->Width() ? it->Data()->Image()->Width() : maxX;
64 
65 		// Renderiza los hijos
66 		if (it->Child())
67 		{
68 			ApplyLayout(it);
69 		}
70 	} while (it->Next());
71 
72 	it->FirstInBranch();
73 
74 	// Aplica la distribuci�n de men�
75 	do
76 	{
77 		switch (config.layout)
78 		{
79 		case JIMAGEMENU_LEFT:
80 			it->Data()->Image()->Pos(0, yOff);
81 			it->Data()->HiImage()->Pos(0, yOff);
82 			yOff += it->Data()->Image()->Height();
83 			break;
84 
85 		case JIMAGEMENU_RIGHT:
86 			xOff = -it->Data()->Image()->Width();
87 			it->Data()->Image()->Pos(xOff, yOff);
88 			it->Data()->HiImage()->Pos(xOff, yOff);
89 			yOff += it->Data()->Image()->Height();
90 			break;
91 
92 		case JIMAGEMENU_CENTER:
93 			xOff = -(it->Data()->Image()->Width()/2);
94 			it->Data()->Image()->Pos(xOff, yOff);
95 			it->Data()->HiImage()->Pos(xOff, yOff);
96 			yOff += it->Data()->Image()->Height();
97 			break;
98 
99 		case JIMAGEMENU_SAMELINE:
100 			it->Data()->Image()->Pos(xOff, 0);
101 			it->Data()->HiImage()->Pos(xOff, 0);
102 			xOff += it->Data()->Image()->Width();
103 			break;
104 
105 		default:
106 			break;
107 		}
108 	} while (it->Next());
109 
110 	it->Parent();
111 }
112 
Init(JImageMenuConfig & cfg)113 bool JImageMenu::Init(JImageMenuConfig &cfg)
114 {
115 	if (curOption == 0)
116 	{
117 		// No es una aplicaci�n v�lida o no se a�adieron opciones
118 		return false;
119 	}
120 
121 	memcpy(&config, &cfg, sizeof(config));
122 
123 	// Renderiza las opciones de men�
124 	curOption->Root();
125 	ApplyLayout(curOption);
126 
127 	return true;
128 }
129 
Pos(float x,float y)130 void JImageMenu::Pos(float x, float y)
131 {
132 	pos.x = x;
133 	pos.y = y;
134 	if (curOption)
135 	{
136 		// Renderiza las opciones de men�
137 		curOption->Root();
138 		ApplyLayout(curOption);
139 	}
140 }
141 
Draw()142 void JImageMenu::Draw()
143 {
144 	JTree<JImageMenuEntry *>::Iterator *it = new JTree<JImageMenuEntry *>::Iterator(*curOption);
145 	JImage * img;
146 
147 	it->FirstInBranch();
148 
149 	do
150 	{
151 		// Si es la opci�n seleccionada muestra su imagen resaltada
152 		if (it->Data() == curOption->Data())
153 		{
154 			img = it->Data()->HiImage();
155 		}
156 		else
157 		{
158 			img = it->Data()->Image();
159 		}
160 
161 		img->Draw((s32)(X() + img->X()), (s32)(Y() + img->Y()));
162 
163 	} while (it->Next());
164 
165 	delete it;
166 }
167 
TrackKeyboard(SDL_keysym key)168 void JImageMenu::TrackKeyboard(SDL_keysym key)
169 {
170 	// Actualiza el estado seg�n el teclado
171 	if (config.trackKeyboard)
172 	{
173 		switch (key.sym)
174 		{
175 		case SDLK_TAB:
176 			// SHIFT + TAB
177 			if (JApp::App()->KeyMods() & KMOD_SHIFT)
178 			{
179 				// Opci�n anterior
180 				curOption->Prev();
181 			}
182 			// TAB
183 			else
184 			{
185 				// Opci�n siguiente
186 				curOption->Next();
187 			}
188 			break;
189 
190 		case SDLK_UP:
191 		case SDLK_LEFT:
192 			// Opci�n anterior
193 			curOption->Prev();
194 			break;
195 
196 		case SDLK_DOWN:
197 		case SDLK_RIGHT:
198 			// Opci�n siguiente
199 			curOption->Next();
200 			break;
201 
202 		case SDLK_KP_ENTER:
203 		case SDLK_RETURN:
204 			// Ejecuta la acci�n asociada
205 			if (!curOption->Data()->Select() && config.autoEnter)
206 			{
207 				// Si no hay acci�n asociada y se especific� autoEnter, intenta descender
208 				// a la opci�n hija.
209 				curOption->Child();
210 			}
211 			break;
212 
213 		case SDLK_ESCAPE:
214 			// Va a la opci�n padre.
215 			curOption->Parent();
216 			break;
217 
218 		default:
219 			break;
220 		} // switch (key)
221 	} // Track keyboard
222 }
223 
TrackMouse(s32 bt,s32 x,s32 y)224 void JImageMenu::TrackMouse(s32 bt, s32 x, s32 y)
225 {
226 	// Actualiza el estado seg�n el rat�n
227 	if (config.trackMouse)
228 	{
229 		JTree<JImageMenuEntry *>::Iterator *it = new JTree<JImageMenuEntry *>::Iterator(*curOption);
230 		s32 mx, my;
231 		bool found = false;
232 		mx = JApp::App()->MouseX();
233 		my = JApp::App()->MouseY();
234 
235 		it->FirstInBranch();
236 
237 		// Comprueba si est� sobre alguna opci�n
238 		do
239 		{
240 			if (mx > it->Data()->Image()->X() + X() &&
241 					mx < it->Data()->Image()->X() + X() + it->Data()->Image()->Width() &&
242 					my > it->Data()->Image()->Y() + Y() &&
243 					my < it->Data()->Image()->Y() + Y() + it->Data()->Image()->Height())
244 			{
245 				// Est� dentro, hace que sea la opci�n resaltada
246 				found = true;
247 
248 				// Borra el iterador actual
249 				delete(curOption);
250 
251 				curOption = it;
252 			}
253 		} while (!found && it->Next());
254 
255 
256 		if (found)
257 		{
258 			// Si ahora est� pulsado, activa el flag de pulsaci�n
259 			if (bt & SDL_BUTTON_LEFT)
260 			{
261 				// Ejecuta la acci�n asociada
262 				if (!curOption->Data()->Select() && config.autoEnter)
263 				{
264 					// Si no hay acci�n asociada y se especific� autoEnter, intenta descender
265 					// a la opci�n hija.
266 					curOption->Child();
267 				}
268 			}
269 		}
270 
271 		// Si encontr� una opci�n bajo el cursor el iterador sobre esa opci�n
272 		// pasa a ser el iterador de opci�n actual, no lo borra
273 		if (!found)
274 			delete it;
275 	} // Track mouse
276 }
277 
278