1 /**
2  * @file
3  * @brief Menu button used in non-game menus
4 **/
5 
6 #pragma once
7 
8 #include <vector>
9 
10 #include "ui.h"
11 #include "tilefont.h"
12 
13 using std::vector;
14 
15 class MenuButton : public ui::Bin
16 {
17     friend class OuterMenu;
18 public:
19     MenuButton();
20 
21     virtual void _render() override;
22     virtual ui::SizeReq _get_preferred_size(ui::Widget::Direction, int) override;
23     virtual void _allocate_region() override;
24     virtual bool on_event(const ui::Event& event) override;
25 
26     int id = 0;
27     int hotkey = 0;
28     colour_t highlight_colour = LIGHTGREY;
29 #ifndef USE_TILE_LOCAL
30     colour_t fg_highlight = BLACK;
31 #endif
32     string description;
33 
34     bool activate();
35 
36 #ifdef USE_TILE_WEB
37     void serialize();
38 #endif
39 
40 protected:
can_take_focus()41     bool can_take_focus() override { return true; };
42 
43     bool focused = false;
44     bool hovered = false;
45     bool active = false;
46 #ifdef USE_TILE_LOCAL
47     ShapeBuffer m_buf;
48     LineBuffer m_line_buf;
49 #endif
50 
51 #ifndef USE_TILE_LOCAL
52     void recolour_descendants(const shared_ptr<Widget>& node);
53     colour_t fg_normal = LIGHTGREY;
54 #endif
55 };
56 
57 class OuterMenu : public ui::Widget
58 {
59 public:
60     OuterMenu(bool can_shrink, int width, int height);
61 
62 #ifdef USE_TILE_WEB
63     ~OuterMenu();
64     void serialize(string name);
65     static void recv_outer_menu_focus(const char *menu_id, int hotkey);
66 #endif
67 
68     virtual void _render() override;
69     virtual ui::SizeReq _get_preferred_size(ui::Widget::Direction, int) override;
70     virtual void _allocate_region() override;
71     virtual bool on_event(const ui::Event& event) override;
72 
get_child_at_offset(int,int)73     virtual shared_ptr<Widget> get_child_at_offset(int, int) override {
74         return m_root;
75     }
76 
77     void add_button(shared_ptr<MenuButton> btn, int x, int y);
78     void add_label(shared_ptr<ui::Text> label, int x, int y);
79     MenuButton* get_button(int x, int y);
80     MenuButton* get_button_by_id(int id);
get_buttons()81     const vector<MenuButton*>& get_buttons() { return m_buttons; };
set_initial_focus(MenuButton * btn)82     void set_initial_focus(MenuButton *btn) {
83         ASSERT(!have_allocated);
84         m_initial_focus = btn;
85     };
86 
87     void scroll_button_into_view(MenuButton *btn);
88 
89     weak_ptr<OuterMenu> linked_menus[4];
90     shared_ptr<ui::Switcher> descriptions;
91     const char *menu_id {nullptr};
92 
93 protected:
94     bool scroller_event_hook(const ui::Event& ev);
95     bool move_button_focus(int fx, int fy, int dx, int dy, int limit);
96 
97     shared_ptr<ui::Grid> m_grid;
98     shared_ptr<ui::Widget> m_root;
99     vector<MenuButton*> m_buttons;
100     vector<pair<formatted_string, coord_def>> m_labels;
101     vector<int> m_description_indexes;
102     int m_width;
103     int m_height;
104     MenuButton* m_initial_focus {nullptr};
105 
106     bool have_allocated {false};
107 
108     static bool focus_button_on_mouseenter;
109 };
110