menu.hpp

Go to the documentation of this file.
00001 /* $Id: menu.hpp 23842 2008-02-16 08:47:16Z mordante $ */
00002 /*
00003    Copyright (C) 2003 - 2008 by David White <dave@whitevine.net>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License version 2
00008    or at your option any later version.
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY.
00011 
00012    See the COPYING file for more details.
00013 */
00014 
00015 #ifndef WIDGET_MENU_HPP_INCLUDED
00016 #define WIDGET_MENU_HPP_INCLUDED
00017 
00018 #include <map>
00019 #include <set>
00020 #include <string>
00021 #include <vector>
00022 
00023 
00024 #include "../image.hpp"
00025 #include "../events.hpp"
00026 #include "../sdl_utils.hpp"
00027 
00028 #include "scrollarea.hpp"
00029 
00030 #include "SDL.h"
00031 
00032 namespace gui {
00033 
00034 class menu;
00035 extern menu *empty_menu;
00036 
00037 class menu : public scrollarea
00038 {
00039 public:
00040 
00041     enum ROW_TYPE { NORMAL_ROW, SELECTED_ROW, HEADING_ROW };
00042     //basic menu style
00043     class style
00044     {
00045     public:
00046         style();
00047         virtual ~style();
00048         virtual void init() {}
00049 
00050         virtual SDL_Rect item_size(const std::string& item) const;
00051         virtual void draw_row_bg(menu& menu_ref, const size_t row_index, const SDL_Rect& rect, ROW_TYPE type);
00052         virtual void draw_row(menu& menu_ref, const size_t row_index, const SDL_Rect& rect, ROW_TYPE type);
00053         void scale_images(int max_width, int max_height);
00054 
00055         surface get_item_image(const image::locator &i_locator) const;
00056         size_t get_font_size() const;
00057         size_t get_cell_padding() const;
00058         size_t get_thickness() const;
00059 
00060     protected:
00061         size_t font_size_;
00062         size_t cell_padding_;
00063         size_t thickness_;  //additional cell padding for style use only
00064 
00065         int normal_rgb_, selected_rgb_, heading_rgb_;
00066         double normal_alpha_, selected_alpha_, heading_alpha_;
00067         int max_img_w_, max_img_h_;
00068     };
00069 
00070     //image-border selction style
00071     class imgsel_style : public style
00072     {
00073     public:
00074         imgsel_style(const std::string &img_base, bool has_bg,
00075                                  int normal_rgb, int selected_rgb, int heading_rgb,
00076                                  double normal_alpha, double selected_alpha, double heading_alpha);
00077         virtual ~imgsel_style();
00078 
00079         virtual SDL_Rect item_size(const std::string& item) const;
00080         virtual void draw_row_bg(menu& menu_ref, const size_t row_index, const SDL_Rect& rect, ROW_TYPE type);
00081         virtual void draw_row(menu& menu_ref, const size_t row_index, const SDL_Rect& rect, ROW_TYPE type);
00082 
00083         virtual void init() { load_images(); }
00084         bool load_images();
00085 
00086     protected:
00087         const std::string img_base_;
00088         std::map<std::string,surface> img_map_;
00089 
00090     private:
00091         bool load_image(const std::string &img_sub);
00092         bool has_background_;
00093         bool initialized_;
00094         bool load_failed_;
00095         int normal_rgb2_, selected_rgb2_, heading_rgb2_;
00096         double normal_alpha2_, selected_alpha2_, heading_alpha2_;
00097         struct bg_cache
00098         {
00099             bg_cache() : surf(), width(-1), height(-1)
00100             {}
00101 
00102             surface surf;
00103             int width, height;
00104         };
00105         bg_cache bg_cache_;
00106     };
00107     friend class style;
00108     friend class imgsel_style;
00109     static style &default_style;
00110     static style simple_style;
00111     static imgsel_style bluebg_style;
00112 
00113     struct item
00114     {
00115         item() : fields(), help(), id(0)
00116         {}
00117 
00118         item(const std::vector<std::string>& fields, size_t id)
00119             : fields(fields), help(), id(id)
00120         {}
00121 
00122         std::vector<std::string> fields;
00123         std::vector<std::string> help;
00124         size_t id;
00125     };
00126 
00127     class sorter
00128     {
00129     public:
00130         virtual ~sorter() {}
00131         virtual bool column_sortable(int column) const = 0;
00132         virtual bool less(int column, const item& row1, const item& row2) const = 0;
00133     };
00134 
00135     class basic_sorter : public sorter
00136     {
00137     public:
00138         basic_sorter();
00139         virtual ~basic_sorter() {}
00140 
00141         basic_sorter& set_alpha_sort(int column);
00142         basic_sorter& set_numeric_sort(int column);
00143         basic_sorter& set_id_sort(int column);
00144         basic_sorter& set_redirect_sort(int column, int to);
00145         basic_sorter& set_position_sort(int column, const std::vector<int>& pos);
00146     protected:
00147         virtual bool column_sortable(int column) const;
00148         virtual bool less(int column, const item& row1, const item& row2) const;
00149 
00150     private:
00151         std::set<int> alpha_sort_, numeric_sort_, id_sort_;
00152         std::map<int,int> redirect_sort_;
00153         std::map<int,std::vector<int> > pos_sort_;
00154     };
00155 
00156     menu(CVideo& video, const std::vector<std::string>& items,
00157          bool click_selects=false, int max_height=-1, int max_width=-1,
00158          const sorter* sorter_obj=NULL, style *menu_style=NULL, const bool auto_join=true);
00159 
00160     int selection() const;
00161 
00162     void move_selection(size_t id);
00163     void reset_selection();
00164 
00165     // allows user to change_item while running (dangerous)
00166     void change_item(int pos1,int pos2,const std::string& str);
00167 
00168     void erase_item(size_t index);
00169 
00170     void set_heading(const std::vector<std::string>& heading);
00171 
00172     /// Set new items to show and redraw/recalculate everything. If
00173     /// strip_spaces is false, spaces will remain at the item edges. If
00174     /// keep_viewport is true, the menu tries to keep the selection at
00175     /// the same position as it were before the items were set.
00176     void set_items(const std::vector<std::string>& items, bool strip_spaces=true,
00177                    bool keep_viewport=false);
00178 
00179     /// Set a new max height for this menu. Note that this does not take
00180     /// effect immediately, only after certain operations that clear
00181     /// everything, such as set_items().
00182     void set_max_height(const int new_max_height);
00183     void set_max_width(const int new_max_width);
00184 
00185     size_t nitems() const { return items_.size(); }
00186 
00187     int process();
00188 
00189     bool double_clicked();
00190 
00191     void set_click_selects(bool value);
00192     void set_numeric_keypress_selection(bool value);
00193 
00194     void scroll(unsigned int pos);
00195 
00196     //currently, menus do not manage the memory of their sorter
00197     //this should be changed to a more object-oriented approach
00198     void set_sorter(sorter *s);
00199     void sort_by(int column);
00200     void wrap_words();
00201 
00202 protected:
00203     bool item_ends_with_image(const std::string& item) const;
00204     virtual void handle_event(const SDL_Event& event);
00205     void set_inner_location(const SDL_Rect& rect);
00206 
00207     bool requires_event_focus(const SDL_Event *event=NULL) const;
00208     const std::vector<int>& column_widths() const;
00209     virtual void draw_row(const size_t row_index, const SDL_Rect& rect, ROW_TYPE type);
00210 
00211     style *style_;
00212     bool silent_;
00213 private:
00214     size_t max_items_onscreen() const;
00215 
00216     size_t heading_height() const;
00217 
00218     int max_height_, max_width_;
00219     mutable int max_items_, item_height_;
00220 
00221     void adjust_viewport_to_selection();
00222     void key_press(SDLKey key);
00223 
00224     std::vector<item> items_;
00225     std::vector<size_t> item_pos_;
00226 
00227     std::vector<std::string> heading_;
00228     mutable int heading_height_;
00229 
00230     void create_help_strings();
00231     void process_help_string(int mousex, int mousey);
00232 
00233     std::pair<int,int> cur_help_;
00234     int help_string_;
00235 
00236     mutable std::vector<int> column_widths_;
00237 
00238     size_t selected_;
00239     bool click_selects_;
00240     bool out_;
00241     bool previous_button_;
00242     //std::set<size_t> undrawn_items_;
00243 
00244     bool show_result_;
00245 
00246     bool double_clicked_;
00247 
00248     void column_widths_item(const std::vector<std::string>& row, std::vector<int>& widths) const;
00249 
00250     void clear_item(int item);
00251     void draw_contents();
00252     void draw();
00253     int hit(int x, int y) const;
00254 
00255     std::pair<int,int> hit_cell(int x, int y) const;
00256     int hit_column(int x) const;
00257 
00258     int hit_heading(int x, int y) const;
00259 
00260     mutable std::map<int,SDL_Rect> itemRects_;
00261 
00262     SDL_Rect get_item_rect(int item) const;
00263     SDL_Rect get_item_rect_internal(size_t pos) const;
00264     size_t get_item_height_internal(const std::vector<std::string>& item) const;
00265     size_t get_item_height(int item) const;
00266     int items_start() const;
00267 
00268     int items_end() const;
00269     int items_height() const;
00270 
00271     void update_scrollbar_grip_height();
00272 
00273     ///variable which determines whether a numeric keypress should
00274     ///select an item on the dialog
00275     bool num_selects_;
00276     // These two variables are used to get the correct double click
00277     // behavior so that a click that causes one double click wont be
00278     // counted as a first click in the "next" double click.
00279     bool ignore_next_doubleclick_;
00280     bool last_was_doubleclick_;
00281 
00282     //ellipsis calculation is slightly off, so default to false
00283     bool use_ellipsis_;
00284 
00285     const sorter* sorter_;
00286     int sortby_;
00287     bool sortreversed_;
00288     int highlight_heading_;
00289 
00290     /// Set new items to show. If strip_spaces is false, spaces will
00291     /// remain at the item edges.
00292     void fill_items(const std::vector<std::string>& items, bool strip_spaces);
00293 
00294     void do_sort();
00295     void recalculate_pos();
00296     void assert_pos();
00297 
00298     void update_size();
00299     enum SELECTION_MOVE_VIEWPORT { MOVE_VIEWPORT, NO_MOVE_VIEWPORT };
00300     void set_selection_pos(size_t pos, bool silent=false, SELECTION_MOVE_VIEWPORT move_viewport=MOVE_VIEWPORT);
00301     void move_selection_to(size_t id, bool silent=false, SELECTION_MOVE_VIEWPORT move_viewport=MOVE_VIEWPORT);
00302     void move_selection_up(size_t dep);
00303     void move_selection_down(size_t dep);
00304 
00305     void invalidate_row(size_t id);
00306     void invalidate_row_pos(size_t pos);
00307     void invalidate_heading();
00308 
00309     std::set<int> invalid_;
00310 };
00311 
00312 
00313 
00314 }
00315 
00316 #endif

Generated by doxygen 1.5.5 on 23 May 2008 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs