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