]> git.localhorst.tv Git - l2e.git/blob - src/graphics/Menu.h
interpret user input in spell selection
[l2e.git] / src / graphics / Menu.h
1 /*
2  * Menu.h
3  *
4  *  Created on: Aug 8, 2012
5  *      Author: holy
6  */
7
8 #ifndef GRAPHICS_MENU_H_
9 #define GRAPHICS_MENU_H_
10
11 #include "Font.h"
12 #include "Sprite.h"
13 #include "../geometry/operators.h"
14 #include "../geometry/Point.h"
15 #include "../geometry/Vector.h"
16
17 #include <iostream>
18 #include <vector>
19 #include <SDL.h>
20
21 namespace graphics {
22
23 class Sprite;
24
25 // TODO: animation when top row changes
26 template<class T>
27 class Menu {
28
29 public:
30         Menu();
31         Menu(const Font *font, const Font *disabledFont, const Sprite *cursor, int charsPerEntry, int rows, int rowGap = 0, int cols = 1, int colGap = 0);
32         Menu(const Menu &);
33
34 public:
35         int Width() const;
36         int Height() const;
37         int ColWidth() const { return font->CharWidth() * charsPerEntry; }
38         int RowHeight() const { return font->CharHeight() + rowGap; }
39
40         T &Selected() { return entries[selected].value; }
41         const T &Selected() const { return entries[selected].value; }
42         const char *SelectedTitle() const { return entries[selected].title; }
43         bool SelectedIsEnabled() const { return entries[selected].enabled; }
44
45         void NextItem();
46         void PreviousItem();
47         void NextRow();
48         void PreviousRow();
49         void SelectIndex(int index);
50         int SelectedIndex() const { return selected; }
51         bool IsSelected(int index) const { return index == selected; }
52
53         int EntryCount() const { return entries.size(); }
54         T &ValueAt(int index) { return entries[index].value; }
55         const T &ValueAt(int index) const { return entries[index].value; }
56
57         void Add(const char *title, const T &value, bool enabled = true, const Sprite *icon = 0) { entries.push_back(Entry(title, value, enabled, icon)); }
58         void Disable(int index) { entries[index].enabled = false; }
59         void Enable(int index) { entries[index].enabled = true; }
60         void Reserve(int n) { entries.reserve(n); }
61
62         void Draw(SDL_Surface *dest, geometry::Point<int> position) const;
63
64 private:
65         int GetRow(int index) const { return index / cols; }
66         int GetCol(int index) const { return index % cols; }
67
68 private:
69         struct Entry {
70                 Entry(const char *title, const T &value, bool enabled = true, const Sprite *icon = 0)
71                 : title(title), icon(icon), value(value), enabled(enabled) { }
72                 const char *title;
73                 const Sprite *icon;
74                 T value;
75                 bool enabled;
76         };
77         const Font *font;
78         const Font *disabledFont;
79         const Sprite *cursor;
80         std::vector<Entry> entries;
81         int charsPerEntry;
82         int rows;
83         int rowGap;
84         int cols;
85         int colGap;
86         int selected;
87         int topRow;
88
89 };
90
91
92 template<class T>
93 Menu<T>::Menu()
94 : font(0)
95 , disabledFont(0)
96 , cursor(0)
97 , charsPerEntry(0)
98 , rows(0)
99 , rowGap(0)
100 , cols(0)
101 , colGap(0)
102 , selected(0)
103 , topRow(0) {
104
105 }
106
107 template<class T>
108 Menu<T>::Menu(const Font *font, const Font *disabledFont, const Sprite *cursor, int charsPerEntry, int rows, int rowGap, int cols, int colGap)
109 : font(font)
110 , disabledFont(disabledFont ? disabledFont : font)
111 , cursor(cursor)
112 , charsPerEntry(charsPerEntry)
113 , rows(rows)
114 , rowGap(rowGap)
115 , cols(cols)
116 , colGap(colGap)
117 , selected(0)
118 , topRow(0) {
119
120 }
121
122 template<class T>
123 Menu<T>::Menu(const Menu &other)
124 : font(other.font)
125 , disabledFont(other.disabledFont)
126 , cursor(other.cursor)
127 , entries(other.entries)
128 , charsPerEntry(other.charsPerEntry)
129 , rows(other.rows)
130 , rowGap(other.rowGap)
131 , cols(other.cols)
132 , colGap(other.colGap)
133 , selected(other.selected)
134 , topRow(other.topRow) {
135         std::cout << "copied Menu" << std::endl;
136 }
137
138
139 template<class T>
140 int Menu<T>::Width() const {
141         return cols * ColWidth() + (cols - 1) * colGap;
142 }
143
144 template<class T>
145 int Menu<T>::Height() const {
146         return rows * font->CharHeight() + (rows - 1) * rowGap;
147 }
148
149
150 template<class T>
151 void Menu<T>::NextItem() {
152         SelectIndex(selected + 1);
153 }
154
155 template<class T>
156 void Menu<T>::PreviousItem() {
157         SelectIndex(selected - 1);
158 }
159
160 template<class T>
161 void Menu<T>::NextRow() {
162         SelectIndex(selected + cols);
163 }
164
165 template<class T>
166 void Menu<T>::PreviousRow() {
167         SelectIndex(selected - cols);
168 }
169
170 template<class T>
171 void Menu<T>::SelectIndex(int index) {
172         if (index < 0 || int(entries.size()) < index) return;
173         std::cout << "selecting index " << index << std::endl;
174         selected = index;
175         if (GetRow(selected) - rows > topRow) {
176                 topRow = GetRow(selected) - rows;
177         } else if (GetRow(selected) < topRow) {
178                 topRow = GetRow(selected);
179         }
180 }
181
182
183 template<class T>
184 void Menu<T>::Draw(SDL_Surface *dest, geometry::Point<int> position) const {
185         int start(topRow * cols);
186         int slots((topRow + rows) * cols);
187         int items(entries.size() - start);
188         int end(items < slots ? items : slots);
189         for (int i(0), count(end - start); i < count; ++i) {
190                 geometry::Vector<int> offset(
191                                 (i % cols) * (ColWidth() + colGap),
192                                 (i / cols) * RowHeight());
193                 if (entries[start + i].enabled) {
194                         font->DrawString(entries[start + i].title, dest, position + offset, charsPerEntry);
195                 } else {
196                         disabledFont->DrawString(entries[start + i].title, dest, position + offset, charsPerEntry);
197                 }
198         }
199         geometry::Vector<int> cursorOffset(
200                         (selected % cols) * (ColWidth() + colGap) - cursor->Width(),
201                         (selected / cols) * RowHeight());
202         cursor->Draw(dest, position + cursorOffset);
203 }
204
205 }
206
207 #endif /* GRAPHICS_MENU_H_ */