mirror of
https://github.com/wesnoth/wesnoth
synced 2025-05-04 21:08:48 +00:00

...trying to preserve the selected player the viewport of the list would always be reset to show the selected player
318 lines
8.5 KiB
C++
318 lines
8.5 KiB
C++
/* $Id$ */
|
|
/*
|
|
Copyright (C) 2003 - 2009 by David White <dave@whitevine.net>
|
|
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License version 2
|
|
or at your option any later version.
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY.
|
|
|
|
See the COPYING file for more details.
|
|
*/
|
|
|
|
#ifndef WIDGET_MENU_HPP_INCLUDED
|
|
#define WIDGET_MENU_HPP_INCLUDED
|
|
|
|
#include <map>
|
|
#include <set>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
|
|
#include "../image.hpp"
|
|
#include "../events.hpp"
|
|
#include "../sdl_utils.hpp"
|
|
|
|
#include "scrollarea.hpp"
|
|
|
|
#include "SDL.h"
|
|
|
|
namespace gui {
|
|
|
|
class menu;
|
|
extern menu *empty_menu;
|
|
|
|
class menu : public scrollarea
|
|
{
|
|
public:
|
|
|
|
enum ROW_TYPE { NORMAL_ROW, SELECTED_ROW, HEADING_ROW };
|
|
//basic menu style
|
|
class style
|
|
{
|
|
public:
|
|
style();
|
|
virtual ~style();
|
|
virtual void init() {}
|
|
|
|
virtual SDL_Rect item_size(const std::string& item) const;
|
|
virtual void draw_row_bg(menu& menu_ref, const size_t row_index, const SDL_Rect& rect, ROW_TYPE type);
|
|
virtual void draw_row(menu& menu_ref, const size_t row_index, const SDL_Rect& rect, ROW_TYPE type);
|
|
void scale_images(int max_width, int max_height);
|
|
|
|
surface get_item_image(const image::locator &i_locator) const;
|
|
size_t get_font_size() const;
|
|
size_t get_cell_padding() const;
|
|
size_t get_thickness() const;
|
|
|
|
protected:
|
|
size_t font_size_;
|
|
size_t cell_padding_;
|
|
size_t thickness_; //additional cell padding for style use only
|
|
|
|
int normal_rgb_, selected_rgb_, heading_rgb_;
|
|
double normal_alpha_, selected_alpha_, heading_alpha_;
|
|
int max_img_w_, max_img_h_;
|
|
};
|
|
|
|
//image-border selction style
|
|
class imgsel_style : public style
|
|
{
|
|
public:
|
|
imgsel_style(const std::string &img_base, bool has_bg,
|
|
int normal_rgb, int selected_rgb, int heading_rgb,
|
|
double normal_alpha, double selected_alpha, double heading_alpha);
|
|
virtual ~imgsel_style();
|
|
|
|
virtual SDL_Rect item_size(const std::string& item) const;
|
|
virtual void draw_row_bg(menu& menu_ref, const size_t row_index, const SDL_Rect& rect, ROW_TYPE type);
|
|
virtual void draw_row(menu& menu_ref, const size_t row_index, const SDL_Rect& rect, ROW_TYPE type);
|
|
|
|
virtual void init() { load_images(); }
|
|
bool load_images();
|
|
|
|
protected:
|
|
const std::string img_base_;
|
|
std::map<std::string,surface> img_map_;
|
|
|
|
private:
|
|
bool load_image(const std::string &img_sub);
|
|
bool has_background_;
|
|
bool initialized_;
|
|
bool load_failed_;
|
|
int normal_rgb2_, selected_rgb2_, heading_rgb2_;
|
|
double normal_alpha2_, selected_alpha2_, heading_alpha2_;
|
|
struct bg_cache
|
|
{
|
|
bg_cache() : surf(), width(-1), height(-1)
|
|
{}
|
|
|
|
surface surf;
|
|
int width, height;
|
|
};
|
|
bg_cache bg_cache_;
|
|
};
|
|
friend class style;
|
|
friend class imgsel_style;
|
|
static style &default_style;
|
|
static style simple_style;
|
|
static imgsel_style bluebg_style;
|
|
|
|
struct item
|
|
{
|
|
item() : fields(), help(), id(0)
|
|
{}
|
|
|
|
item(const std::vector<std::string>& fields, size_t id)
|
|
: fields(fields), help(), id(id)
|
|
{}
|
|
|
|
std::vector<std::string> fields;
|
|
std::vector<std::string> help;
|
|
size_t id;
|
|
};
|
|
|
|
class sorter
|
|
{
|
|
public:
|
|
virtual ~sorter() {}
|
|
virtual bool column_sortable(int column) const = 0;
|
|
virtual bool less(int column, const item& row1, const item& row2) const = 0;
|
|
};
|
|
|
|
class basic_sorter : public sorter
|
|
{
|
|
public:
|
|
basic_sorter();
|
|
virtual ~basic_sorter() {}
|
|
|
|
basic_sorter& set_alpha_sort(int column);
|
|
basic_sorter& set_numeric_sort(int column);
|
|
basic_sorter& set_id_sort(int column);
|
|
basic_sorter& set_redirect_sort(int column, int to);
|
|
basic_sorter& set_position_sort(int column, const std::vector<int>& pos);
|
|
protected:
|
|
virtual bool column_sortable(int column) const;
|
|
virtual bool less(int column, const item& row1, const item& row2) const;
|
|
|
|
private:
|
|
std::set<int> alpha_sort_, numeric_sort_, id_sort_;
|
|
std::map<int,int> redirect_sort_;
|
|
std::map<int,std::vector<int> > pos_sort_;
|
|
};
|
|
|
|
menu(CVideo& video, const std::vector<std::string>& items,
|
|
bool click_selects=false, int max_height=-1, int max_width=-1,
|
|
const sorter* sorter_obj=NULL, style *menu_style=NULL, const bool auto_join=true);
|
|
|
|
int selection() const;
|
|
|
|
void move_selection(size_t id);
|
|
void move_selection_keeping_viewport(size_t id);
|
|
void reset_selection();
|
|
|
|
// allows user to change_item while running (dangerous)
|
|
void change_item(int pos1,int pos2,const std::string& str);
|
|
|
|
void erase_item(size_t index);
|
|
|
|
void set_heading(const std::vector<std::string>& heading);
|
|
|
|
/// Set new items to show and redraw/recalculate everything. If
|
|
/// strip_spaces is false, spaces will remain at the item edges. If
|
|
/// keep_viewport is true, the menu tries to keep the selection at
|
|
/// the same position as it were before the items were set.
|
|
void set_items(const std::vector<std::string>& items, bool strip_spaces=true,
|
|
bool keep_viewport=false);
|
|
|
|
/// Set a new max height for this menu. Note that this does not take
|
|
/// effect immediately, only after certain operations that clear
|
|
/// everything, such as set_items().
|
|
void set_max_height(const int new_max_height);
|
|
void set_max_width(const int new_max_width);
|
|
|
|
size_t nitems() const { return items_.size(); }
|
|
|
|
int process();
|
|
|
|
bool double_clicked();
|
|
|
|
void set_click_selects(bool value);
|
|
void set_numeric_keypress_selection(bool value);
|
|
|
|
void scroll(unsigned int pos);
|
|
|
|
//currently, menus do not manage the memory of their sorter
|
|
//this should be changed to a more object-oriented approach
|
|
void set_sorter(sorter *s);
|
|
void sort_by(int column);
|
|
void wrap_words();
|
|
|
|
protected:
|
|
bool item_ends_with_image(const std::string& item) const;
|
|
virtual void handle_event(const SDL_Event& event);
|
|
void set_inner_location(const SDL_Rect& rect);
|
|
|
|
bool requires_event_focus(const SDL_Event *event=NULL) const;
|
|
const std::vector<int>& column_widths() const;
|
|
virtual void draw_row(const size_t row_index, const SDL_Rect& rect, ROW_TYPE type);
|
|
|
|
style *style_;
|
|
bool silent_;
|
|
private:
|
|
size_t max_items_onscreen() const;
|
|
|
|
size_t heading_height() const;
|
|
|
|
int max_height_, max_width_;
|
|
mutable int max_items_, item_height_;
|
|
|
|
void adjust_viewport_to_selection();
|
|
void key_press(SDLKey key);
|
|
|
|
std::vector<item> items_;
|
|
std::vector<size_t> item_pos_;
|
|
|
|
std::vector<std::string> heading_;
|
|
mutable int heading_height_;
|
|
|
|
void create_help_strings();
|
|
void process_help_string(int mousex, int mousey);
|
|
|
|
std::pair<int,int> cur_help_;
|
|
int help_string_;
|
|
|
|
mutable std::vector<int> column_widths_;
|
|
|
|
size_t selected_;
|
|
bool click_selects_;
|
|
bool out_;
|
|
bool previous_button_;
|
|
//std::set<size_t> undrawn_items_;
|
|
|
|
bool show_result_;
|
|
|
|
bool double_clicked_;
|
|
|
|
void column_widths_item(const std::vector<std::string>& row, std::vector<int>& widths) const;
|
|
|
|
void clear_item(int item);
|
|
void draw_contents();
|
|
void draw();
|
|
int hit(int x, int y) const;
|
|
|
|
std::pair<int,int> hit_cell(int x, int y) const;
|
|
int hit_column(int x) const;
|
|
|
|
int hit_heading(int x, int y) const;
|
|
|
|
mutable std::map<int,SDL_Rect> itemRects_;
|
|
|
|
SDL_Rect get_item_rect(int item) const;
|
|
SDL_Rect get_item_rect_internal(size_t pos) const;
|
|
size_t get_item_height_internal(const std::vector<std::string>& item) const;
|
|
size_t get_item_height(int item) const;
|
|
int items_start() const;
|
|
|
|
int items_end() const;
|
|
int items_height() const;
|
|
|
|
void update_scrollbar_grip_height();
|
|
|
|
///variable which determines whether a numeric keypress should
|
|
///select an item on the dialog
|
|
bool num_selects_;
|
|
// These two variables are used to get the correct double click
|
|
// behavior so that a click that causes one double click wont be
|
|
// counted as a first click in the "next" double click.
|
|
bool ignore_next_doubleclick_;
|
|
bool last_was_doubleclick_;
|
|
|
|
//ellipsis calculation is slightly off, so default to false
|
|
bool use_ellipsis_;
|
|
|
|
const sorter* sorter_;
|
|
int sortby_;
|
|
bool sortreversed_;
|
|
int highlight_heading_;
|
|
|
|
/// Set new items to show. If strip_spaces is false, spaces will
|
|
/// remain at the item edges.
|
|
void fill_items(const std::vector<std::string>& items, bool strip_spaces);
|
|
|
|
void do_sort();
|
|
void recalculate_pos();
|
|
void assert_pos();
|
|
|
|
void update_size();
|
|
enum SELECTION_MOVE_VIEWPORT { MOVE_VIEWPORT, NO_MOVE_VIEWPORT };
|
|
void set_selection_pos(size_t pos, bool silent=false, SELECTION_MOVE_VIEWPORT move_viewport=MOVE_VIEWPORT);
|
|
void move_selection_to(size_t id, bool silent=false, SELECTION_MOVE_VIEWPORT move_viewport=MOVE_VIEWPORT);
|
|
void move_selection_up(size_t dep);
|
|
void move_selection_down(size_t dep);
|
|
|
|
void invalidate_row(size_t id);
|
|
void invalidate_row_pos(size_t pos);
|
|
void invalidate_heading();
|
|
|
|
std::set<int> invalid_;
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
#endif
|