diff --git a/Makefile b/Makefile index 4ed741bb561..d025a6daf31 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ SDL_CFLAGS=`sdl-config --cflags` `freetype-config --cflags` SDL_LIBS=`sdl-config --libs` `freetype-config --libs` -lSDL_mixer -lSDL_ttf -lSDL_image -lSDL_net LIBS=${SDL_LIBS} -lstdc++ INCLUDES=-I. -Isrc -Isrc/tools -Isrc/widgets -OBJS=src/actions.o src/ai.o src/ai_attack.o src/ai_move.o src/config.o src/dialogs.o src/display.o src/filesystem.o src/font.o src/game.o src/game_config.o src/game_events.o src/gamestatus.o src/hotkeys.o src/intro.o src/key.o src/language.o src/log.o src/map.o src/menu.o src/multiplayer.o src/network.o src/pathfind.o src/playlevel.o src/playturn.o src/preferences.o src/replay.o src/sdl_utils.o src/sound.o src/team.o src/terrain.o src/tooltips.o src/unit.o src/unit_types.o src/video.o src/widgets/button.o src/widgets/slider.o src/widgets/textbox.o +OBJS=src/actions.o src/ai.o src/ai_attack.o src/ai_move.o src/config.o src/dialogs.o src/display.o src/filesystem.o src/font.o src/game.o src/game_config.o src/game_events.o src/gamestatus.o src/hotkeys.o src/intro.o src/key.o src/language.o src/log.o src/map.o src/multiplayer.o src/network.o src/pathfind.o src/playlevel.o src/playturn.o src/preferences.o src/replay.o src/sdl_utils.o src/show_dialog.o src/sound.o src/team.o src/terrain.o src/tooltips.o src/unit.o src/unit_types.o src/video.o src/widgets/button.o src/widgets/menu.o src/widgets/slider.o src/widgets/textbox.o MAKE_TRANS_OBJS=src/tools/make_translation.o src/config.o src/filesystem.o src/log.o MERGE_TRANS_OBJS=src/tools/merge_translations.o src/config.o src/filesystem.o src/log.o diff --git a/images/terrain/flag-team1.png b/images/terrain/flag-team1.png index 19ed0e83d99..7ef6fe77188 100644 Binary files a/images/terrain/flag-team1.png and b/images/terrain/flag-team1.png differ diff --git a/images/terrain/flag-team5.png b/images/terrain/flag-team5.png index 19ed0e83d99..7077f34779e 100644 Binary files a/images/terrain/flag-team5.png and b/images/terrain/flag-team5.png differ diff --git a/images/terrain/flag-team6.png b/images/terrain/flag-team6.png index 19ed0e83d99..67f1db0040d 100644 Binary files a/images/terrain/flag-team6.png and b/images/terrain/flag-team6.png differ diff --git a/src/ai.cpp b/src/ai.cpp index e5a19dd2241..0adf0d31398 100644 --- a/src/ai.cpp +++ b/src/ai.cpp @@ -17,11 +17,11 @@ #include "dialogs.hpp" #include "game_config.hpp" #include "log.hpp" -#include "menu.hpp" #include "pathfind.hpp" #include "playlevel.hpp" #include "playturn.hpp" #include "replay.hpp" +#include "show_dialog.hpp" #include diff --git a/src/dialogs.hpp b/src/dialogs.hpp index e0cf3f8b9e3..e3ab79fce83 100644 --- a/src/dialogs.hpp +++ b/src/dialogs.hpp @@ -15,7 +15,7 @@ #include "actions.hpp" #include "display.hpp" -#include "menu.hpp" +#include "show_dialog.hpp" namespace dialogs { diff --git a/src/display.cpp b/src/display.cpp index 1d8f66aab64..5dbba59481b 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -19,9 +19,9 @@ #include "hotkeys.hpp" #include "language.hpp" #include "log.hpp" -#include "menu.hpp" #include "preferences.hpp" #include "sdl_utils.hpp" +#include "show_dialog.hpp" #include "sound.hpp" #include "tooltips.hpp" #include "util.hpp" diff --git a/src/game.cpp b/src/game.cpp index e3a4018a03a..6e8af040c70 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -25,13 +25,13 @@ #include "gamestatus.hpp" #include "key.hpp" #include "language.hpp" -#include "menu.hpp" #include "multiplayer.hpp" #include "network.hpp" #include "pathfind.hpp" #include "playlevel.hpp" #include "preferences.hpp" #include "replay.hpp" +#include "show_dialog.hpp" #include "sound.hpp" #include "team.hpp" #include "unit_types.hpp" @@ -153,8 +153,14 @@ int play_game(int argc, char** argv) for(int arg = 1; arg != argc; ++arg) { const std::string val(argv[arg]); + if(val.empty()) { + continue; + } + if(val == "--windowed" || val == "-w") { preferences::set_fullscreen(false); + } else if(val == "--fullscreen" || val == "-f") { + preferences::set_fullscreen(true); } else if(val == "--test" || val == "-t") { test_mode = true; } else if(val == "--debug" || val == "-d") { @@ -162,9 +168,14 @@ int play_game(int argc, char** argv) } else if(val == "--help" || val == "-h") { std::cout << "usage: " << argv[0] << " [options] [data-directory]\n"; + return 0; } else if(val == "--version" || val == "-v") { std::cout << "Battle for Wesnoth " << game_config::version << "\n"; + return 0; + } else if(val[0] == '-') { + std::cerr << "unknown option: " << val << "\n"; + return 0; } else { if(!is_directory(val)) { std::cerr << "Could not find directory '" << val << "'\n"; diff --git a/src/game_events.cpp b/src/game_events.cpp index d55739c40c5..04ddad56839 100644 --- a/src/game_events.cpp +++ b/src/game_events.cpp @@ -11,10 +11,10 @@ See the COPYING file for more details. */ #include "game_events.hpp" -#include "menu.hpp" #include "language.hpp" #include "playlevel.hpp" #include "replay.hpp" +#include "show_dialog.hpp" #include "sound.hpp" #include "util.hpp" diff --git a/src/hotkeys.cpp b/src/hotkeys.cpp index 4a5ce8c7fe4..2d85306497c 100644 --- a/src/hotkeys.cpp +++ b/src/hotkeys.cpp @@ -13,9 +13,9 @@ #include "config.hpp" #include "hotkeys.hpp" #include "language.hpp" -#include "menu.hpp" #include "playlevel.hpp" #include "preferences.hpp" +#include "show_dialog.hpp" #include "video.hpp" #include diff --git a/src/intro.cpp b/src/intro.cpp index bd3837000e0..e4a81e49d73 100644 --- a/src/intro.cpp +++ b/src/intro.cpp @@ -14,7 +14,7 @@ #include "intro.hpp" #include "key.hpp" #include "language.hpp" -#include "menu.hpp" +#include "show_dialog.hpp" #include "widgets/button.hpp" #include diff --git a/src/multiplayer.cpp b/src/multiplayer.cpp index c40f590c610..a76e33bb88d 100644 --- a/src/multiplayer.cpp +++ b/src/multiplayer.cpp @@ -13,11 +13,11 @@ #include "language.hpp" #include "log.hpp" -#include "menu.hpp" #include "multiplayer.hpp" #include "network.hpp" #include "playlevel.hpp" #include "replay.hpp" +#include "show_dialog.hpp" #include #include diff --git a/src/playlevel.hpp b/src/playlevel.hpp index df1fd7f0a2d..973b1dc15fe 100644 --- a/src/playlevel.hpp +++ b/src/playlevel.hpp @@ -21,8 +21,8 @@ #include "game_config.hpp" #include "gamestatus.hpp" #include "key.hpp" -#include "menu.hpp" #include "pathfind.hpp" +#include "show_dialog.hpp" #include "team.hpp" #include "unit_types.hpp" #include "unit.hpp" diff --git a/src/playturn.hpp b/src/playturn.hpp index 0f74600d6a7..ece0501230c 100644 --- a/src/playturn.hpp +++ b/src/playturn.hpp @@ -22,8 +22,8 @@ #include "game_events.hpp" #include "gamestatus.hpp" #include "key.hpp" -#include "menu.hpp" #include "pathfind.hpp" +#include "show_dialog.hpp" #include "team.hpp" #include "unit_types.hpp" #include "unit.hpp" diff --git a/src/preferences.cpp b/src/preferences.cpp index 337ebd58e6f..c9e24b8e4e7 100644 --- a/src/preferences.cpp +++ b/src/preferences.cpp @@ -14,8 +14,8 @@ #include "font.hpp" #include "hotkeys.hpp" #include "language.hpp" -#include "menu.hpp" #include "preferences.hpp" +#include "show_dialog.hpp" #include "sound.hpp" #include "util.hpp" #include "widgets/button.hpp" diff --git a/src/replay.cpp b/src/replay.cpp index fe3d19c9f49..21ff108cf69 100644 --- a/src/replay.cpp +++ b/src/replay.cpp @@ -17,11 +17,11 @@ #include "dialogs.hpp" #include "game_config.hpp" #include "log.hpp" -#include "menu.hpp" #include "pathfind.hpp" #include "playlevel.hpp" #include "playturn.hpp" #include "replay.hpp" +#include "show_dialog.hpp" #include #include diff --git a/src/menu.cpp b/src/show_dialog.cpp similarity index 71% rename from src/menu.cpp rename to src/show_dialog.cpp index fb9f946cc4c..8a1fa9dbf60 100644 --- a/src/menu.cpp +++ b/src/show_dialog.cpp @@ -10,16 +10,18 @@ See the COPYING file for more details. */ + #include "config.hpp" #include "font.hpp" #include "language.hpp" -#include "menu.hpp" #include "playlevel.hpp" +#include "show_dialog.hpp" #include "language.hpp" #include "sdl_utils.hpp" #include "tooltips.hpp" #include "util.hpp" #include "widgets/button.hpp" +#include "widgets/menu.hpp" #include "widgets/textbox.hpp" #include @@ -171,336 +173,6 @@ void draw_solid_tinted_rectangle(int x, int y, int w, int h, } //end namespace gui -namespace { -const size_t max_menu_items = 18; -const size_t menu_font_size = 16; -const size_t menu_cell_padding = 10; - -class menu -{ - display* display_; - int x_, y_; - std::vector > items_; - mutable std::vector column_widths_; - - scoped_sdl_surface buffer_; - int selected_; - bool click_selects_; - bool previous_button_; - bool drawn_; - - mutable int height_; - mutable int width_; - - mutable int first_item_on_screen_; - gui::button uparrow_, downarrow_; - - const std::vector& column_widths() const - { - if(column_widths_.empty()) { - for(size_t row = 0; row != items_.size(); ++row) { - for(size_t col = 0; col != items_[row].size(); ++col) { - static const SDL_Rect area = - {0,0,display_->x(),display_->y()}; - - const SDL_Rect res = - font::draw_text(NULL,area,menu_font_size, - font::NORMAL_COLOUR,items_[row][col],x_,y_); - - if(col == column_widths_.size()) { - column_widths_.push_back(res.w + menu_cell_padding); - } else if(res.w > column_widths_[col] - menu_cell_padding) { - column_widths_[col] = res.w + menu_cell_padding; - } - } - } - } - - return column_widths_; - } - - void draw_item(int item) { - SDL_Rect rect = get_item_rect(item); - if(rect.w == 0) - return; - - if(buffer_.get() != NULL) { - const int ypos = items_start()+(item-first_item_on_screen_)*rect.h; - SDL_Rect srcrect = {0,ypos,rect.w,rect.h}; - SDL_BlitSurface(buffer_,&srcrect, - display_->video().getSurface(),&rect); - } - - gui::draw_solid_tinted_rectangle(x_,rect.y,width(),rect.h, - item == selected_ ? 150:0,0,0, - item == selected_ ? 0.6 : 0.2, - display_->video().getSurface()); - - SDL_Rect area = {0,0,display_->x(),display_->y()}; - - const std::vector& widths = column_widths(); - - int xpos = rect.x; - for(size_t i = 0; i != items_[item].size(); ++i) { - font::draw_text(display_,area,menu_font_size,font::NORMAL_COLOUR, - items_[item][i],xpos,rect.y); - xpos += widths[i]; - } - } - - void draw() { - drawn_ = true; - - for(size_t i = 0; i != items_.size(); ++i) - draw_item(i); - - display_->video().flip(); - } - - int hit(int x, int y) const { - if(x > x_ && x < x_ + width() && y > y_ && y < y_ + height()){ - for(size_t i = 0; i != items_.size(); ++i) { - const SDL_Rect& rect = get_item_rect(i); - if(y > rect.y && y < rect.y + rect.h) - return i; - } - } - - return -1; - } - - mutable std::map itemRects_; - - SDL_Rect get_item_rect(int item) const - { - const SDL_Rect empty_rect = {0,0,0,0}; - if(item < first_item_on_screen_ || - size_t(item) >= first_item_on_screen_ + max_menu_items) { - return empty_rect; - } - - const std::map::const_iterator i = itemRects_.find(item); - if(i != itemRects_.end()) - return i->second; - - int y = y_ + items_start(); - if(item != first_item_on_screen_) { - const SDL_Rect& prev = get_item_rect(item-1); - y = prev.y + prev.h; - } - - static const SDL_Rect area = {0,0,display_->x(),display_->y()}; - - SDL_Rect res = font::draw_text(NULL,area,menu_font_size, - font::NORMAL_COLOUR,items_[item][0],x_,y); - - res.w = width(); - - //only insert into the cache if the menu's co-ordinates have - //been initialized - if(x_ > 0 && y_ > 0) - itemRects_.insert(std::pair(item,res)); - - return res; - } - - int items_start() const - { - if(items_.size() > max_menu_items) - return uparrow_.height(); - else - return 0; - } - - int items_end() const - { - if(items_.size() > max_menu_items) - return height() - downarrow_.height(); - else - return height(); - } - - int items_height() const - { - return items_end() - items_start(); - } - -public: - menu(display& disp, const std::vector& items, - bool click_selects=false) - : display_(&disp), x_(0), y_(0), buffer_(NULL), - selected_(-1), click_selects_(click_selects), - previous_button_(true), drawn_(false), height_(-1), width_(-1), - first_item_on_screen_(0), - uparrow_(disp,"",gui::button::TYPE_PRESS,"uparrow"), - downarrow_(disp,"",gui::button::TYPE_PRESS,"downarrow") - { - for(std::vector::const_iterator item = items.begin(); - item != items.end(); ++item) { - items_.push_back(config::split(*item)); - - //make sure there is always at least one item - if(items_.back().empty()) - items_.back().push_back(" "); - } - } - - int height() const { - if(height_ == -1) { - height_ = 0; - for(size_t i = 0; i != items_.size() && i != max_menu_items; ++i) { - height_ += get_item_rect(i).h; - } - - if(items_.size() > max_menu_items) { - height_ += uparrow_.height() + downarrow_.height(); - } - } - - return height_; - } - - int width() const { - if(width_ == -1) { - const std::vector& widths = column_widths(); - width_ = std::accumulate(widths.begin(),widths.end(),0); - } - - return width_; - } - - int selection() const { return selected_; } - - void set_loc(int x, int y) { - x_ = x; - y_ = y; - - const int w = width(); - - SDL_Rect portion = {x_,y_,w,height()}; - SDL_Surface* const screen = display_->video().getSurface(); - buffer_.assign(get_surface_portion(screen, portion)); - - if(items_.size() > max_menu_items) { - uparrow_.set_x(x_); - uparrow_.set_y(y_); - downarrow_.set_x(x_); - downarrow_.set_y(y_+items_end()); - } - } - - int process(int x, int y, bool button,bool up_arrow,bool down_arrow, - bool page_up, bool page_down, int select_item) { - if(items_.size() > size_t(max_menu_items)) { - const bool up = uparrow_.process(x,y,button); - if(up && first_item_on_screen_ > 0) { - itemRects_.clear(); - --first_item_on_screen_; - - draw(); - } - - const bool down = downarrow_.process(x,y,button); - if(down && - size_t(first_item_on_screen_+max_menu_items) < items_.size()) { - itemRects_.clear(); - ++first_item_on_screen_; - draw(); - } - } - - if(select_item >= 0 && size_t(select_item) < items_.size()) { - selected_ = select_item; - if(selected_ < first_item_on_screen_) { - itemRects_.clear(); - first_item_on_screen_ = selected_; - } - - if(size_t(selected_ - first_item_on_screen_) >= max_menu_items) { - itemRects_.clear(); - first_item_on_screen_ = selected_ - max_menu_items - 1; - } - - draw(); - } - - if(up_arrow && !click_selects_ && selected_ > 0) { - --selected_; - if(selected_ < first_item_on_screen_) { - itemRects_.clear(); - first_item_on_screen_ = selected_; - } - - draw(); - } - - if(down_arrow && !click_selects_ && selected_ < int(items_.size()-1)) { - ++selected_; - if(size_t(selected_ - first_item_on_screen_) == max_menu_items) { - itemRects_.clear(); - ++first_item_on_screen_; - } - - draw(); - } - - if(page_up && !click_selects_) { - selected_ -= max_menu_items; - if(selected_ < 0) - selected_ = 0; - - itemRects_.clear(); - first_item_on_screen_ = selected_; - - draw(); - } - - if(page_down && !click_selects_) { - selected_ += max_menu_items; - if(size_t(selected_) >= items_.size()) - selected_ = items_.size()-1; - - first_item_on_screen_ = selected_ - (max_menu_items-1); - if(first_item_on_screen_ < 0) - first_item_on_screen_ = 0; - - itemRects_.clear(); - - draw(); - } - - const int starting_selected = selected_; - - const int hit_item = hit(x,y); - - if(click_selects_) { - selected_ = hit_item; - if(button && !previous_button_) - return selected_; - else { - if(!drawn_ || selected_ != starting_selected) - draw(); - previous_button_ = button; - return -1; - } - } - - if(button && hit_item != -1){ - selected_ = hit_item; - } - - if(selected_ == -1) - selected_ = 0; - - if(selected_ != starting_selected) - draw(); - - return -1; - } -}; - -} - namespace gui { diff --git a/src/menu.hpp b/src/show_dialog.hpp similarity index 96% rename from src/menu.hpp rename to src/show_dialog.hpp index e6527ff03bd..655ad6b8a95 100644 --- a/src/menu.hpp +++ b/src/show_dialog.hpp @@ -10,8 +10,9 @@ See the COPYING file for more details. */ -#ifndef MENU_HPP_INCLUDED -#define MENU_HPP_INCLUDED + +#ifndef SHOW_DIALOG_HPP_INCLUDED +#define SHOW_DIALOG_HPP_INCLUDED #include "display.hpp" #include "SDL.h" diff --git a/src/tooltips.cpp b/src/tooltips.cpp index 562774b8728..e39d920f072 100644 --- a/src/tooltips.cpp +++ b/src/tooltips.cpp @@ -1,5 +1,5 @@ #include "font.hpp" -#include "menu.hpp" +#include "show_dialog.hpp" #include "tooltips.hpp" #include "sdl_utils.hpp" diff --git a/src/widgets/menu.cpp b/src/widgets/menu.cpp new file mode 100644 index 00000000000..7fe9964ab7d --- /dev/null +++ b/src/widgets/menu.cpp @@ -0,0 +1,323 @@ +#include "menu.hpp" + +#include "../font.hpp" +#include "../show_dialog.hpp" + +#include + +namespace { +const size_t max_menu_items = 18; +const size_t menu_font_size = 16; +const size_t menu_cell_padding = 10; +} + +namespace gui { + +menu::menu(display& disp, const std::vector& items, + bool click_selects) + : display_(&disp), x_(0), y_(0), buffer_(NULL), + selected_(-1), click_selects_(click_selects), + previous_button_(true), drawn_(false), height_(-1), width_(-1), + first_item_on_screen_(0), + uparrow_(disp,"",gui::button::TYPE_PRESS,"uparrow"), + downarrow_(disp,"",gui::button::TYPE_PRESS,"downarrow") +{ + for(std::vector::const_iterator item = items.begin(); + item != items.end(); ++item) { + items_.push_back(config::split(*item)); + + //make sure there is always at least one item + if(items_.back().empty()) + items_.back().push_back(" "); + } +} + +int menu::height() const +{ + if(height_ == -1) { + height_ = 0; + for(size_t i = 0; i != items_.size() && i != max_menu_items; ++i) { + height_ += get_item_rect(i).h; + } + + if(items_.size() > max_menu_items) { + height_ += uparrow_.height() + downarrow_.height(); + } + } + + return height_; +} + +int menu::width() const +{ + if(width_ == -1) { + const std::vector& widths = column_widths(); + width_ = std::accumulate(widths.begin(),widths.end(),0); + } + + return width_; +} + +int menu::selection() const { return selected_; } + +void menu::set_loc(int x, int y) +{ + x_ = x; + y_ = y; + + const int w = width(); + + SDL_Rect portion = {x_,y_,w,height()}; + SDL_Surface* const screen = display_->video().getSurface(); + buffer_.assign(get_surface_portion(screen, portion)); + + if(items_.size() > max_menu_items) { + uparrow_.set_x(x_); + uparrow_.set_y(y_); + downarrow_.set_x(x_); + downarrow_.set_y(y_+items_end()); + } +} + +int menu::process(int x, int y, bool button,bool up_arrow,bool down_arrow, + bool page_up, bool page_down, int select_item) +{ + if(items_.size() > size_t(max_menu_items)) { + const bool up = uparrow_.process(x,y,button); + if(up && first_item_on_screen_ > 0) { + itemRects_.clear(); + --first_item_on_screen_; + + draw(); + } + + const bool down = downarrow_.process(x,y,button); + if(down && + size_t(first_item_on_screen_+max_menu_items) < items_.size()) { + itemRects_.clear(); + ++first_item_on_screen_; + draw(); + } + } + + if(select_item >= 0 && size_t(select_item) < items_.size()) { + selected_ = select_item; + if(selected_ < first_item_on_screen_) { + itemRects_.clear(); + first_item_on_screen_ = selected_; + } + + if(size_t(selected_ - first_item_on_screen_) >= max_menu_items) { + itemRects_.clear(); + first_item_on_screen_ = selected_ - max_menu_items - 1; + } + + draw(); + } + + if(up_arrow && !click_selects_ && selected_ > 0) { + --selected_; + if(selected_ < first_item_on_screen_) { + itemRects_.clear(); + first_item_on_screen_ = selected_; + } + + draw(); + } + + if(down_arrow && !click_selects_ && selected_ < int(items_.size()-1)) { + ++selected_; + if(size_t(selected_ - first_item_on_screen_) == max_menu_items) { + itemRects_.clear(); + ++first_item_on_screen_; + } + + draw(); + } + + if(page_up && !click_selects_) { + selected_ -= max_menu_items; + if(selected_ < 0) + selected_ = 0; + + itemRects_.clear(); + first_item_on_screen_ = selected_; + + draw(); + } + + if(page_down && !click_selects_) { + selected_ += max_menu_items; + if(size_t(selected_) >= items_.size()) + selected_ = items_.size()-1; + + first_item_on_screen_ = selected_ - (max_menu_items-1); + if(first_item_on_screen_ < 0) + first_item_on_screen_ = 0; + + itemRects_.clear(); + + draw(); + } + + const int starting_selected = selected_; + + const int hit_item = hit(x,y); + + if(click_selects_) { + selected_ = hit_item; + if(button && !previous_button_) + return selected_; + else { + if(!drawn_ || selected_ != starting_selected) + draw(); + previous_button_ = button; + return -1; + } + } + + if(button && hit_item != -1){ + selected_ = hit_item; + } + + if(selected_ == -1) + selected_ = 0; + + if(selected_ != starting_selected) + draw(); + + return -1; +} + +const std::vector& menu::column_widths() const +{ + if(column_widths_.empty()) { + for(size_t row = 0; row != items_.size(); ++row) { + for(size_t col = 0; col != items_[row].size(); ++col) { + static const SDL_Rect area = + {0,0,display_->x(),display_->y()}; + + const SDL_Rect res = + font::draw_text(NULL,area,menu_font_size, + font::NORMAL_COLOUR,items_[row][col],x_,y_); + + if(col == column_widths_.size()) { + column_widths_.push_back(res.w + menu_cell_padding); + } else if(res.w > column_widths_[col] - menu_cell_padding) { + column_widths_[col] = res.w + menu_cell_padding; + } + } + } + } + + return column_widths_; +} + +void menu::draw_item(int item) +{ + SDL_Rect rect = get_item_rect(item); + if(rect.w == 0) + return; + + if(buffer_.get() != NULL) { + const int ypos = items_start()+(item-first_item_on_screen_)*rect.h; + SDL_Rect srcrect = {0,ypos,rect.w,rect.h}; + SDL_BlitSurface(buffer_,&srcrect, + display_->video().getSurface(),&rect); + } + + gui::draw_solid_tinted_rectangle(x_,rect.y,width(),rect.h, + item == selected_ ? 150:0,0,0, + item == selected_ ? 0.6 : 0.2, + display_->video().getSurface()); + + SDL_Rect area = {0,0,display_->x(),display_->y()}; + + const std::vector& widths = column_widths(); + + int xpos = rect.x; + for(size_t i = 0; i != items_[item].size(); ++i) { + font::draw_text(display_,area,menu_font_size,font::NORMAL_COLOUR, + items_[item][i],xpos,rect.y); + xpos += widths[i]; + } +} + +void menu::draw() +{ + drawn_ = true; + + for(size_t i = 0; i != items_.size(); ++i) + draw_item(i); + + display_->video().flip(); +} + +int menu::hit(int x, int y) const +{ + if(x > x_ && x < x_ + width() && y > y_ && y < y_ + height()){ + for(size_t i = 0; i != items_.size(); ++i) { + const SDL_Rect& rect = get_item_rect(i); + if(y > rect.y && y < rect.y + rect.h) + return i; + } + } + + return -1; +} + +SDL_Rect menu::get_item_rect(int item) const +{ + const SDL_Rect empty_rect = {0,0,0,0}; + if(item < first_item_on_screen_ || + size_t(item) >= first_item_on_screen_ + max_menu_items) { + return empty_rect; + } + + const std::map::const_iterator i = itemRects_.find(item); + if(i != itemRects_.end()) + return i->second; + + int y = y_ + items_start(); + if(item != first_item_on_screen_) { + const SDL_Rect& prev = get_item_rect(item-1); + y = prev.y + prev.h; + } + + static const SDL_Rect area = {0,0,display_->x(),display_->y()}; + + SDL_Rect res = font::draw_text(NULL,area,menu_font_size, + font::NORMAL_COLOUR,items_[item][0],x_,y); + + res.w = width(); + + //only insert into the cache if the menu's co-ordinates have + //been initialized + if(x_ > 0 && y_ > 0) + itemRects_.insert(std::pair(item,res)); + + return res; +} + +int menu::items_start() const +{ + if(items_.size() > max_menu_items) + return uparrow_.height(); + else + return 0; +} + +int menu::items_end() const +{ + if(items_.size() > max_menu_items) + return height() - downarrow_.height(); + else + return height(); +} + +int menu::items_height() const +{ + return items_end() - items_start(); +} + +} diff --git a/src/widgets/menu.hpp b/src/widgets/menu.hpp new file mode 100644 index 00000000000..950b1d20cf9 --- /dev/null +++ b/src/widgets/menu.hpp @@ -0,0 +1,66 @@ +#ifndef WIDGET_MENU_HPP_INCLUDED +#define WIDGET_MENU_HPP_INCLUDED + +#include +#include + +#include "../display.hpp" +#include "../sdl_utils.hpp" + +#include "button.hpp" + +#include "SDL.h" + +namespace gui { + +class menu +{ +public: + menu(display& disp, const std::vector& items, + bool click_selects=false); + + int height() const; + int width() const; + + int selection() const; + + void set_loc(int x, int y); + + int process(int x, int y, bool button,bool up_arrow,bool down_arrow, + bool page_up, bool page_down, int select_item); + +private: + display* display_; + int x_, y_; + std::vector > items_; + mutable std::vector column_widths_; + + scoped_sdl_surface buffer_; + int selected_; + bool click_selects_; + bool previous_button_; + bool drawn_; + + mutable int height_; + mutable int width_; + + mutable int first_item_on_screen_; + gui::button uparrow_, downarrow_; + + const std::vector& column_widths() const; + void draw_item(int item); + void draw(); + int hit(int x, int y) const; + + mutable std::map itemRects_; + + SDL_Rect get_item_rect(int item) const; + int items_start() const; + + int items_end() const; + int items_height() const; +}; + +} + +#endif