X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fgraphics%2FMenu.h;h=7aa2e9448794754d57024e36e16252bbba6f0389;hb=e35b71bedb8c2424346d60c737020f1599438b74;hp=f35a2bed2ce370cc8d19d8717a1e4de17eb1b6d7;hpb=e462583cabc752b8f03b423e98e93bca5f5045d8;p=l2e.git diff --git a/src/graphics/Menu.h b/src/graphics/Menu.h index f35a2be..7aa2e94 100644 --- a/src/graphics/Menu.h +++ b/src/graphics/Menu.h @@ -10,11 +10,8 @@ #include "Font.h" #include "Sprite.h" -#include "../geometry/operators.h" -#include "../geometry/Point.h" #include "../geometry/Vector.h" -#include #include #include @@ -22,24 +19,54 @@ namespace graphics { class Sprite; -// TODO: animation when top row changes +struct MenuProperties { + const Font *font; + const Font *disabledFont; + const Sprite *cursor; + int charsPerEntry; + int rows; + int rowGap; + int iconSpace; + int cols; + int colGap; + int charsPerNumber; + int charsPerAdditionalText; + int additionalTextGap; + char delimiter; + + MenuProperties() + : font(0), disabledFont(0), cursor(0) + , charsPerEntry(0), rows(0), rowGap(0) + , iconSpace(0), cols(0), colGap(0) + , charsPerNumber(0), charsPerAdditionalText(0) + , additionalTextGap(0), delimiter(':') { } + + MenuProperties(const Font *font, const Font *disabledFont, const Sprite *cursor, int charsPerEntry, int rows, int rowGap, int iconSpace, int cols, int colGap, int charsPerNumber, char delimiter, int charsPerAdditionalText, int additionalTextGap) + : font(font), disabledFont(disabledFont), cursor(cursor), charsPerEntry(charsPerEntry), rows(rows), rowGap(rowGap), iconSpace(iconSpace), cols(cols), colGap(colGap), charsPerNumber(charsPerNumber), charsPerAdditionalText(charsPerAdditionalText), additionalTextGap(additionalTextGap), delimiter(delimiter) { } + + static void CreateTypeDescription(); +}; + template -class Menu { +class Menu +: private MenuProperties { public: Menu(); - Menu(const Font *font, const Font *disabledFont, const Sprite *cursor, int charsPerEntry, int rows, int rowGap = 0, int cols = 1, int colGap = 0); - Menu(const Menu &); + Menu(const MenuProperties &); + Menu(const Font *font, const Font *disabledFont, const Sprite *cursor, int charsPerEntry, int rows, int rowGap = 0, int iconSpace = 0, int cols = 1, int colGap = 0, int charsPerNumber = 0, char delimiter = ':', int charsPerAdditionalText = 0, int additionalTextGap = 0); public: int Width() const; int Height() const; - int ColWidth() const { return font->CharWidth() * charsPerEntry; } + int ColWidth() const; int RowHeight() const { return font->CharHeight() + rowGap; } + int CharsPerEntry() const { return charsPerEntry; } T &Selected() { return entries[selected].value; } const T &Selected() const { return entries[selected].value; } const char *SelectedTitle() const { return entries[selected].title; } + int SelectedNumber() const { return entries[selected].number; } bool SelectedIsEnabled() const { return entries[selected].enabled; } void NextItem(); @@ -54,12 +81,14 @@ public: T &ValueAt(int index) { return entries[index].value; } const T &ValueAt(int index) const { return entries[index].value; } - void Add(const char *title, const T &value, bool enabled = true, const Sprite *icon = 0) { entries.push_back(Entry(title, value, enabled, icon)); } + void Add(const char *title, const T &value, bool enabled = true, const Sprite *icon = 0, int number = 0, const char *additionalText = 0) { entries.push_back(Entry(title, value, enabled, icon, number, additionalText)); } + void AddEmptyEntry() { entries.push_back(Entry(0, T(), false)); } void Disable(int index) { entries[index].enabled = false; } void Enable(int index) { entries[index].enabled = true; } void Reserve(int n) { entries.reserve(n); } + void Clear() { entries.clear(); } - void Draw(SDL_Surface *dest, geometry::Point position) const; + void Draw(SDL_Surface *dest, const geometry::Vector &position) const; private: int GetRow(int index) const { return index / cols; } @@ -67,22 +96,16 @@ private: private: struct Entry { - Entry(const char *title, const T &value, bool enabled = true, const Sprite *icon = 0) - : title(title), icon(icon), value(value), enabled(enabled) { } + Entry(const char *title, const T &value, bool enabled = true, const Sprite *icon = 0, int number = 0, const char *additionalText = 0) + : title(title), additionalText(additionalText), icon(icon), number(number), value(value), enabled(enabled) { } const char *title; + const char *additionalText; const Sprite *icon; + int number; T value; bool enabled; }; - const Font *font; - const Font *disabledFont; - const Sprite *cursor; std::vector entries; - int charsPerEntry; - int rows; - int rowGap; - int cols; - int colGap; int selected; int topRow; @@ -91,51 +114,49 @@ private: template Menu::Menu() -: font(0) -, disabledFont(0) -, cursor(0) -, charsPerEntry(0) -, rows(0) -, rowGap(0) -, cols(0) -, colGap(0) +: MenuProperties() , selected(0) , topRow(0) { } template -Menu::Menu(const Font *font, const Font *disabledFont, const Sprite *cursor, int charsPerEntry, int rows, int rowGap, int cols, int colGap) -: font(font) -, disabledFont(disabledFont ? disabledFont : font) -, cursor(cursor) -, charsPerEntry(charsPerEntry) -, rows(rows) -, rowGap(rowGap) -, cols(cols) -, colGap(colGap) +Menu::Menu(const MenuProperties &p) +: MenuProperties(p) , selected(0) , topRow(0) { } template -Menu::Menu(const Menu &other) -: font(other.font) -, disabledFont(other.disabledFont) -, cursor(other.cursor) -, entries(other.entries) -, charsPerEntry(other.charsPerEntry) -, rows(other.rows) -, rowGap(other.rowGap) -, cols(other.cols) -, colGap(other.colGap) -, selected(other.selected) -, topRow(other.topRow) { - std::cout << "copied Menu" << std::endl; +Menu::Menu(const Font *font, const Font *disabledFont, const Sprite *cursor, int charsPerEntry, int rows, int rowGap, int iconSpace, int cols, int colGap, int charsPerNumber, char delimiter, int charsPerAdditionalText, int additionalTextGap) +: MenuProperties( + font, disabledFont ? disabledFont : font, + cursor, charsPerEntry, + rows, rowGap, iconSpace, + cols, colGap, charsPerNumber, + delimiter, + charsPerAdditionalText, + additionalTextGap) +, selected(0) +, topRow(0) { + } +template +int Menu::ColWidth() const { + int width(iconSpace); + width += font->CharWidth() * (charsPerEntry + charsPerNumber); + if (charsPerNumber) { + width += font->CharWidth(); + } + if (charsPerAdditionalText) { + width += additionalTextGap + charsPerAdditionalText * font->CharWidth(); + } + return width; +} + template int Menu::Width() const { return cols * ColWidth() + (cols - 1) * colGap; @@ -169,11 +190,10 @@ void Menu::PreviousRow() { template void Menu::SelectIndex(int index) { - if (index < 0 || int(entries.size()) < index) return; - std::cout << "selecting index " << index << std::endl; + if (index < 0 || int(entries.size()) <= index) return; selected = index; - if (GetRow(selected) - rows > topRow) { - topRow = GetRow(selected) - rows; + if (topRow <= GetRow(selected) - rows) { + topRow = GetRow(selected) - rows + 1; } else if (GetRow(selected) < topRow) { topRow = GetRow(selected); } @@ -181,24 +201,42 @@ void Menu::SelectIndex(int index) { template -void Menu::Draw(SDL_Surface *dest, geometry::Point position) const { +void Menu::Draw(SDL_Surface *dest, const geometry::Vector &position) const { int start(topRow * cols); - int slots((topRow + rows) * cols); + int slots(rows * cols); int items(entries.size() - start); - int end(items < slots ? items : slots); + int end(start + (items < slots ? items : slots)); for (int i(0), count(end - start); i < count; ++i) { - geometry::Vector offset( + if (!entries[start + i].title) continue; + geometry::Vector iconOffset( (i % cols) * (ColWidth() + colGap), (i / cols) * RowHeight()); - if (entries[start + i].enabled) { - font->DrawString(entries[start + i].title, dest, position + offset, charsPerEntry); - } else { - disabledFont->DrawString(entries[start + i].title, dest, position + offset, charsPerEntry); + if (entries[start + i].icon) { + entries[start + i].icon->Draw(dest, position + iconOffset); + } + geometry::Vector textOffset(iconOffset.X() + iconSpace, iconOffset.Y()); + const Font *usedFont(entries[start + i].enabled ? font : disabledFont); + usedFont->DrawString(entries[start + i].title, dest, position + textOffset, charsPerEntry); + + textOffset += geometry::Vector(charsPerEntry * usedFont->CharWidth(), 0); + + if (charsPerAdditionalText) { + textOffset += geometry::Vector(additionalTextGap, 0); + if (entries[start + i].additionalText) { + usedFont->DrawString(entries[start + i].additionalText, dest, position + textOffset, charsPerAdditionalText); + } + textOffset += geometry::Vector(charsPerAdditionalText * usedFont->CharWidth(), 0); + } + + if (charsPerNumber) { + usedFont->DrawChar(delimiter, dest, position + textOffset); + textOffset += geometry::Vector(usedFont->CharWidth(), 0); + usedFont->DrawNumber(entries[start + i].number, dest, position + textOffset); } } geometry::Vector cursorOffset( (selected % cols) * (ColWidth() + colGap) - cursor->Width(), - (selected / cols) * RowHeight()); + ((selected - start) / cols) * RowHeight()); cursor->Draw(dest, position + cursorOffset); }