From 1d0f57cbceb778139ca215cc4fcfd1584951f6dd Mon Sep 17 00:00:00 2001 From: dshaligram Date: Wed, 22 Nov 2006 08:41:20 +0000 Subject: Merged stone_soup r15:451 into trunk. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@452 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/menu.h | 251 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 222 insertions(+), 29 deletions(-) (limited to 'crawl-ref/source/menu.h') diff --git a/crawl-ref/source/menu.h b/crawl-ref/source/menu.h index 05e4796383..441685e11a 100644 --- a/crawl-ref/source/menu.h +++ b/crawl-ref/source/menu.h @@ -5,6 +5,7 @@ #include #include #include "AppHdr.h" +#include "externs.h" #include "defines.h" #include "libutil.h" @@ -33,7 +34,8 @@ struct menu_letter return *this; } - menu_letter operator ++ (int postfix) + // dummy postfix argument unnamed to stop gcc from complaining + menu_letter operator ++ (int) { menu_letter copy = *this; this->operator++(); @@ -41,6 +43,77 @@ struct menu_letter } }; +class formatted_string +{ +public: + formatted_string() : ops() { } + formatted_string(const std::string &s, bool init_style = false); + + operator std::string() const; + void display(int start = 0, int end = -1) const; + std::string tostring(int start = 0, int end = -1) const; + + void cprintf(const char *s, ...); + void cprintf(const std::string &s); + void gotoxy(int x, int y); + void movexy(int delta_x, int delta_y); + void textcolor(int color); + + void clear(); + + std::string::size_type length() const; + + const formatted_string &operator += (const formatted_string &other); + +public: + static formatted_string parse_string( + const std::string &s, + bool eol_ends_format = true, + bool (*process_tag)(const std::string &tag) = NULL ); + +private: + enum fs_op_type + { + FSOP_COLOUR, + FSOP_CURSOR, + FSOP_TEXT + }; + + static int get_colour(const std::string &tag); + +private: + struct fs_op + { + fs_op_type type; + int x, y; + bool relative; + std::string text; + + fs_op(int color) + : type(FSOP_COLOUR), x(color), y(-1), relative(false), text() + { + } + + fs_op(int cx, int cy, bool rel = false) + : type(FSOP_CURSOR), x(cx), y(cy), relative(rel), text() + { + } + + fs_op(const std::string &s) + : type(FSOP_TEXT), x(-1), y(-1), relative(false), text(s) + { + } + + operator fs_op_type () const + { + return type; + } + void display() const; + }; + + std::vector ops; +}; + struct item_def; struct MenuEntry { @@ -51,7 +124,7 @@ struct MenuEntry MenuEntryLevel level; void *data; - MenuEntry( const std::string &txt = std::string(""), + MenuEntry( const std::string &txt = std::string(), MenuEntryLevel lev = MEL_ITEM, int qty = 0, int hotk = 0 ) : @@ -66,6 +139,10 @@ struct MenuEntry } virtual ~MenuEntry() { } + bool operator<( const MenuEntry& rhs ) const { + return text < rhs.text; + } + void add_hotkey( int key ) { if (key && !is_hotkey(key)) @@ -91,8 +168,7 @@ struct MenuEntry "%c - %s", hotkeys[0], text.c_str()); return std::string(buf); } - return std::string(level == MEL_SUBTITLE? " " : - level == MEL_ITEM? "" : " ") + text; + return text; } virtual bool selected() const @@ -118,15 +194,19 @@ public: enum MenuFlag { - MF_NOSELECT = 0, // No selection is permitted - MF_SINGLESELECT = 1, // Select just one item - MF_MULTISELECT = 2, // Select multiple items - MF_NO_SELECT_QTY = 4, // Disallow partial selections - MF_ANYPRINTABLE = 8, // Any printable character is valid, and - // closes the menu. - MF_SELECT_ANY_PAGE = 16, // Allow selections to occur on any page. - - MF_EASY_EXIT = 64 + MF_NOSELECT = 0x0000, // No selection is permitted + MF_SINGLESELECT = 0x0001, // Select just one item + MF_MULTISELECT = 0x0002, // Select multiple items + MF_NO_SELECT_QTY = 0x0004, // Disallow partial selections + MF_ANYPRINTABLE = 0x0008, // Any printable character is valid, and + // closes the menu. + MF_SELECT_BY_PAGE = 0x0010, // Allow selections to occur only on + // currently visible page. + + MF_ALWAYS_SHOW_MORE = 0x0020, // Always show the -more- footer + MF_NOWRAP = 0x0040, // Paging past the end will not wrap back. + + MF_EASY_EXIT = 0x1000 }; /////////////////////////////////////////////////////////////////////// @@ -142,18 +222,28 @@ public: Menu( int flags = MF_MULTISELECT ); virtual ~Menu(); - void set_flags( int new_flags ) { this->flags = new_flags; } + // Remove all items from the Menu, leave title intact. + void clear(); + + // Sets menu flags to new_flags. If use_options is true, game options may + // override options. + void set_flags(int new_flags, bool use_options = true); int get_flags() const { return flags; } - bool is_set( int flag ) const; + virtual bool is_set( int flag ) const; bool draw_title_suffix( const std::string &s, bool titlefirst = true ); void update_title(); + + // Sets a replacement for the --more-- string. + void set_more(const formatted_string &more); void set_highlighter( MenuHighlighter *h ); void set_title( MenuEntry *e ); void add_entry( MenuEntry *entry ); void get_selected( std::vector *sel ) const; + void set_maxpagesize(int max); + void set_select_filter( std::vector filter ) { select_filter = filter; @@ -162,22 +252,31 @@ public: unsigned char getkey() const { return lastch; } void reset(); - std::vector show(); + std::vector show(bool reuse_selections = false); + std::vector selected_entries() const; + + size_t item_count() const { return items.size(); } public: typedef std::string (*selitem_tfn)( const std::vector *sel ); + typedef void (*drawitem_tfn)(int index, const MenuEntry *me); + typedef int (*keyfilter_tfn)(int keyin); - selitem_tfn selitem_text; + selitem_tfn f_selitem; + drawitem_tfn f_drawitem; + keyfilter_tfn f_keyfilter; protected: MenuEntry *title; int flags; int first_entry, y_offset; - int pagesize; + int pagesize, max_pagesize; + + formatted_string more; std::vector items; - std::vector *sel; + std::vector sel; std::vector select_filter; // Class that is queried to colour menu entries. @@ -189,28 +288,122 @@ protected: bool alive; - void do_menu( std::vector *selected ); - virtual void draw_select_count( int count ); - void draw_item( int index ) const; +protected: + void do_menu(); + virtual void draw_select_count(int count, bool force = false); + virtual void draw_item( int index ) const; + virtual void draw_item(int index, const MenuEntry *me) const; + virtual void draw_stock_item(int index, const MenuEntry *me) const; + virtual void draw_title(); - void draw_menu( std::vector *selected ); - bool page_down(); - bool line_down(); - bool page_up(); - bool line_up(); + virtual void write_title(); + virtual void draw_menu(); + virtual bool page_down(); + virtual bool line_down(); + virtual bool page_up(); + virtual bool line_up(); + + virtual int pre_process(int key); + virtual int post_process(int key); + + bool in_page(int index) const; void deselect_all(bool update_view = true); - void select_items( int key, int qty = -1 ); + virtual void select_items( int key, int qty = -1 ); void select_index( int index, int qty = -1 ); bool is_hotkey(int index, int key ); bool is_selectable(int index) const; - int item_colour(const MenuEntry *me) const; + virtual int item_colour(int index, const MenuEntry *me) const; virtual bool process_key( int keyin ); }; +// Uses a sliding selector rather than hotkeyed selection. +class slider_menu : public Menu +{ +public: + // Multiselect would be awkward to implement. + slider_menu(int flags = MF_SINGLESELECT); + void display(); + std::vector show(); + + void set_search(const std::string &search); + void set_limits(int starty, int endy); + const MenuEntry *selected_entry() const; + +protected: + int item_colour(int index, const MenuEntry *me) const; + void draw_stock_item(int index, const MenuEntry *me) const; + void draw_menu(); + + void new_selection(int nsel); + bool move_selection(int nsel); + + bool page_down(); + bool line_down(); + bool page_up(); + bool line_up(); + + bool is_set(int flag) const; + void select_items( int key, int qty ); + bool fix_entry(); + bool process_key( int keyin ); + + int post_process(int key); + + void select_search(const std::string &search); + +protected: + formatted_string less; + int starty, endy; + int selected; + std::string search; +}; + +// This is only tangentially related to menus, but what the heck. +// Note, column margins start on 1, not 0. +class column_composer +{ +public: + // Number of columns and left margins for 2nd, 3rd, ... nth column. + column_composer(int ncols, ...); + + void clear(); + void add_formatted(int ncol, + const std::string &tagged_text, + bool add_separator = true, + bool eol_ends_format = true, + bool (*text_filter)(const std::string &tag) = NULL, + int margin = -1); + + std::vector formatted_lines() const; + + void set_pagesize(int pagesize); + +private: + struct column; + void compose_formatted_column( + const std::vector &lines, + int start_col, + int margin); + void strip_blank_lines(std::vector &) const; + +private: + struct column + { + int margin; + int lines; + + column(int marg = 1) : margin(marg), lines(0) { } + }; + + int ncols, pagesize; + std::vector columns; + std::vector flines; +}; + int menu_colour(const std::string &itemtext); #endif -- cgit v1.2.3-54-g00ecf