]> Shamusworld >> Repos - virtualjaguar/blob - src/gui/menu.cpp
f0339775a5cdfc3e4d13a13b197c81015d49a03a
[virtualjaguar] / src / gui / menu.cpp
1 //
2 // Menu class & supporting structs/classes
3 //
4 // by James L. Hammons
5 //
6
7 #include "menu.h"
8
9 // Local variables
10 static const char separator[] = "--------------------------------------------------------";
11
12 // Implementation
13
14 Menu::Menu(uint32 x/*= 0*/, uint32 y/*= 0*/, uint32 w/*= 0*/, uint32 h/*= FONT_HEIGHT*/,
15         uint32 fgc/*= 0xFF7F0000*/, uint32 bgc/*= 0xFFFF3F3F*/, uint32 fgch/*= 0xFFFF3F3F*/,
16         uint32 bgch/*= 0xFFFF8787*/):
17         Element(x, y, w, h), activated(false), clicked(false), inside(0), insidePopup(0),
18         fgColor(fgc), bgColor(bgc), fgColorHL(fgch), bgColorHL(bgch), menuChosen(-1),
19         menuItemChosen(-1)
20 {
21 }
22
23 void Menu::HandleKey(SDLKey key)
24 {
25         for(uint32 i=0; i<itemList.size(); i++)
26         {
27                 for(uint32 j=0; j<itemList[i].item.size(); j++)
28                 {
29                         if (itemList[i].item[j].hotKey == key)
30                         {
31                                 SDL_Event event;
32                                 event.type = SDL_USEREVENT;
33                                 event.user.code = MENU_ITEM_CHOSEN;
34                                 event.user.data1 = (void *)itemList[i].item[j].action;
35                         SDL_PushEvent(&event);
36
37                                 clicked = false, menuChosen = menuItemChosen = -1;
38                                 break;
39                         }
40                 }
41         }
42 }
43
44 void Menu::HandleMouseMove(uint32 x, uint32 y)
45 {
46         inside = insidePopup = 0;
47
48         if (Inside(x, y))
49         {
50                 // Find out *where* we are inside the menu bar
51                 uint32 xpos = extents.x;
52
53                 for(uint32 i=0; i<itemList.size(); i++)
54                 {
55                         uint32 width = (itemList[i].title.length() + 2) * FONT_WIDTH;
56
57                         if (x >= xpos && x < xpos + width)
58                         {
59                                 inside = i + 1;
60                                 menuChosen = i;
61                                 break;
62                         }
63
64                         xpos += width;
65                 }
66         }
67
68         if (!Inside(x, y) && !clicked)
69         {
70                 menuChosen = -1;
71         }
72
73         if (itemList[menuChosen].Inside(x, y) && clicked)
74         {
75                 insidePopup = ((y - itemList[menuChosen].extents.y) / FONT_HEIGHT) + 1;
76                 menuItemChosen = insidePopup - 1;
77         }
78 }
79
80 void Menu::HandleMouseButton(uint32 x, uint32 y, bool mouseDown)
81 {
82         if (!clicked)
83         {
84                 if (mouseDown)
85                 {
86                         if (inside)
87                                 clicked = true;
88                         else
89                                 menuChosen = -1;                                        // clicked is already false...!
90                 }
91         }
92         else                                                                                    // clicked == true
93         {
94                 if (insidePopup && !mouseDown)                          // I.e., mouse-button-up
95                 {
96                         activated = true;
97                         if (itemList[menuChosen].item[menuItemChosen].action != NULL)
98                         {
99 //                              itemList[menuChosen].item[menuItemChosen].action();
100                                 SDL_Event event;
101                                 event.type = SDL_USEREVENT;
102                                 event.user.code = MENU_ITEM_CHOSEN;
103                                 event.user.data1 = (void *)itemList[menuChosen].item[menuItemChosen].action;
104                             SDL_PushEvent(&event);
105
106                                 clicked = false, menuChosen = menuItemChosen = -1;
107
108 /*                              SDL_Event event;
109                                 while (SDL_PollEvent(&event));          // Flush the event queue...
110                                 event.type = SDL_MOUSEMOTION;
111                                 int mx, my;
112                                 SDL_GetMouseState(&mx, &my);
113                                 event.motion.x = mx, event.motion.y = my;
114                             SDL_PushEvent(&event);                              // & update mouse position...!
115 */                      }
116                 }
117
118                 if (!inside && !insidePopup && mouseDown)
119                         clicked = false, menuChosen = menuItemChosen = -1;
120         }
121 }
122
123 void Menu::Draw(uint32 offsetX/*= 0*/, uint32 offsetY/*= 0*/)
124 {
125         uint32 xpos = extents.x + offsetX;
126
127         for(uint32 i=0; i<itemList.size(); i++)
128         {
129 //              uint16 color1 = fgColor, color2 = bgColor;
130                 uint32 color1 = fgColor, color2 = bgColor;
131                 if (inside == (i + 1) || (menuChosen != -1 && (uint32)menuChosen == i))
132                         color1 = fgColorHL, color2 = bgColorHL;
133
134                 DrawStringOpaque(screenBuffer, xpos, extents.y + offsetY, color1, color2,
135                         " %s ", itemList[i].title.c_str());
136                 xpos += (itemList[i].title.length() + 2) * FONT_WIDTH;
137         }
138
139         // Draw sub menu (but only if active)
140         if (clicked)
141         {
142                 uint32 ypos = extents.y + FONT_HEIGHT + 1;
143
144                 for(uint32 i=0; i<itemList[menuChosen].item.size(); i++)
145                 {
146 //                      uint16 color1 = fgColor, color2 = bgColor;
147                         uint32 color1 = fgColor, color2 = bgColor;
148
149                         if (insidePopup == i + 1)
150                                 color1 = fgColorHL, color2 = bgColorHL, menuItemChosen = i;
151
152                         if (itemList[menuChosen].item[i].name.length() > 0)
153                                 DrawStringOpaque(screenBuffer, itemList[menuChosen].extents.x, ypos,
154                                         color1, color2, " %-*.*s ", itemList[menuChosen].charLength,
155                                         itemList[menuChosen].charLength, itemList[menuChosen].item[i].name.c_str());
156                         else
157                                 DrawStringOpaque(screenBuffer, itemList[menuChosen].extents.x, ypos,
158                                         fgColor, bgColor, "%.*s", itemList[menuChosen].charLength + 2, separator);
159
160                         ypos += FONT_HEIGHT;
161                 }
162         }
163 }
164
165 void Menu::Add(MenuItems mi)
166 {
167         for(uint32 i=0; i<mi.item.size(); i++)
168                 if (mi.item[i].name.length() > mi.charLength)
169                         mi.charLength = mi.item[i].name.length();
170
171         // Set extents here as well...
172         mi.extents.x = extents.x + extents.w, mi.extents.y = extents.y + FONT_HEIGHT + 1;
173         mi.extents.w = (mi.charLength + 2) * FONT_WIDTH, mi.extents.h = mi.item.size() * FONT_HEIGHT;
174
175         itemList.push_back(mi);
176         extents.w += (mi.title.length() + 2) * FONT_WIDTH;
177 }