diff options
Diffstat (limited to '')
-rw-r--r-- | src/listview_curses.hh | 199 |
1 files changed, 111 insertions, 88 deletions
diff --git a/src/listview_curses.hh b/src/listview_curses.hh index bf375bc..6e003e4 100644 --- a/src/listview_curses.hh +++ b/src/listview_curses.hh @@ -39,7 +39,6 @@ #include <sys/types.h> -#include "base/func_util.hh" #include "view_curses.hh" #include "vis_line.hh" @@ -105,12 +104,37 @@ class list_overlay_source { public: virtual ~list_overlay_source() = default; - virtual bool list_value_for_overlay(const listview_curses& lv, - int y, - int bottom, + virtual void reset() {} + + virtual bool list_static_overlay(const listview_curses& lv, + int y, + int bottom, + attr_line_t& value_out) + { + return false; + } + + virtual std::vector<attr_line_t> list_overlay_menu( + const listview_curses& lv, vis_line_t line) + { + return {}; + } + + virtual nonstd::optional<attr_line_t> list_header_for_overlay( + const listview_curses& lv, vis_line_t line) + { + return nonstd::nullopt; + } + + virtual void list_value_for_overlay(const listview_curses& lv, vis_line_t line, - attr_line_t& value_out) - = 0; + std::vector<attr_line_t>& value_out) + { + } + + virtual void set_show_details_in_overlay(bool val) {} + + virtual bool get_show_details_in_overlay() const { return false; } }; class list_input_delegate { @@ -166,7 +190,7 @@ public: } /** @return The overlay source delegate. */ - list_overlay_source* get_overlay_source() + list_overlay_source* get_overlay_source() const { return this->lv_overlay_source; } @@ -207,21 +231,41 @@ public: void set_selection(vis_line_t sel); - void shift_selection(int offset); + void set_selection_without_context(vis_line_t sel); + + enum class shift_amount_t { + up_line, + up_page, + down_line, + down_page, + }; + + void shift_selection(shift_amount_t sa); vis_line_t get_selection() const { - if (this->lv_selectable) { + if (this->lv_selectable && this->lv_selection != -1_vl) { return this->lv_selection; } return this->lv_top; } + nonstd::optional<vis_line_t> get_overlay_selection() const + { + if (this->lv_overlay_focused) { + return this->lv_focused_overlay_selection; + } + + return nonstd::nullopt; + } + + void set_overlay_selection(nonstd::optional<vis_line_t> sel); + void set_sync_selection_and_top(bool value) { - this->lv_sync_selection_and_top = value; - if (value) { - this->set_top(this->get_selection()); + if (this->lv_sync_selection_and_top != value) { + this->lv_sync_selection_and_top = value; + this->set_needs_update(); } } @@ -251,7 +295,7 @@ public: vis_line_t rows_available(vis_line_t line, row_direction_t dir) const; template<typename F> - auto map_top_row(F func) -> + auto map_top_row(F func) const -> typename std::result_of<F(const attr_line_t&)>::type { if (this->lv_top >= this->get_inner_height()) { @@ -260,7 +304,8 @@ public: std::vector<attr_line_t> top_line{1}; - this->lv_source->listview_value_for_rows(*this, this->lv_top, top_line); + this->lv_source->listview_value_for_rows( + *this, this->get_selection(), top_line); return func(top_line[0]); } @@ -270,26 +315,6 @@ public: /** @return The curses window this view is attached to. */ WINDOW* get_window() const { return this->lv_window; } - void set_y(unsigned int y) - { - if (y != this->lv_y) { - this->lv_y = y; - this->set_needs_update(); - } - } - - unsigned int get_y() const { return this->lv_y; } - - void set_x(unsigned int x) - { - if (x != this->lv_x) { - this->lv_x = x; - this->set_needs_update(); - } - } - - unsigned int get_x() const { return this->lv_x; } - /** * Set the line number to be displayed at the top of the view. If the * value is invalid, flash() will be called. If the value is valid, the @@ -330,20 +355,7 @@ public: * @param suppress_flash Don't call flash() if the offset is out-of-bounds. * @return The final value of top. */ - vis_line_t shift_top(vis_line_t offset, bool suppress_flash = false) - { - if (offset < 0 && this->lv_top == 0) { - if (suppress_flash == false) { - alerter::singleton().chime( - "the top of the view has been reached"); - } - } else { - this->set_top(std::max(0_vl, this->lv_top + offset), - suppress_flash); - } - - return this->lv_top; - } + vis_line_t shift_top(vis_line_t offset, bool suppress_flash = false); /** * Set the column number to be displayed at the left of the view. If the @@ -352,31 +364,10 @@ public: * * @param left The new value for left. */ - void set_left(unsigned int left) - { - if (this->lv_left == left) { - return; - } - - if (left > this->lv_left) { - unsigned long width; - vis_line_t height; - - this->get_dimensions(height, width); - if ((this->get_inner_width() - this->lv_left) <= width) { - alerter::singleton().chime( - "the maximum width of the view has been reached"); - return; - } - } - - this->lv_left = left; - this->invoke_scroll(); - this->set_needs_update(); - } + void set_left(int left); /** @return The column number that is displayed at the left. */ - unsigned int get_left() const { return this->lv_left; } + int get_left() const { return this->lv_left; } /** * Shift the value of left by the given value. @@ -384,7 +375,7 @@ public: * @param offset The amount to change top by. * @return The final value of top. */ - unsigned int shift_left(int offset) + int shift_left(int offset) { if (this->lv_word_wrap) { alerter::singleton().chime( @@ -454,7 +445,7 @@ public: getmaxyx(this->lv_window, height, width_out); if (this->lv_height < 0) { height_out = vis_line_t(height) + this->lv_height - - vis_line_t(this->lv_y); + - vis_line_t(this->vc_y); if (height_out < 0_vl) { height_out = 0_vl; } @@ -462,8 +453,8 @@ public: height_out = this->lv_height; } } - if (this->lv_x < width_out) { - width_out -= this->lv_x; + if (this->vc_x < width_out) { + width_out -= this->vc_x; } else { width_out = 0; } @@ -490,9 +481,11 @@ public: /** * Query the data source and draw the visible lines on the display. */ - void do_update(); + bool do_update() override; + + bool handle_mouse(mouse_event& me) override; - bool handle_mouse(mouse_event& me); + bool contains(int x, int y) const override; listview_curses& set_tail_space(vis_line_t space) { @@ -503,20 +496,42 @@ public: vis_line_t get_tail_space() const { return this->lv_tail_space; } - void log_state() + void log_state() override { log_debug("listview_curses=%p", this); - log_debug(" lv_title=%s", this->lv_title.c_str()); - log_debug(" lv_y=%u", this->lv_y); - log_debug(" lv_top=%d", (int) this->lv_top); - log_debug(" lv_left=%d", (int) this->lv_left); - log_debug(" lv_height=%d", this->lv_height); - log_debug(" lv_selection=%d", (int) this->lv_selection); - log_debug(" inner_height=%d", (int) this->get_inner_height()); + log_debug( + " lv_title=%s; vc_y=%u; lv_top=%d; lv_left=%d; lv_height=%d; " + "lv_selection=%d; inner_height=%d", + this->lv_title.c_str(), + this->vc_y, + (int) this->lv_top, + this->lv_left, + this->lv_height, + (int) this->lv_selection, + (int) this->get_inner_height()); } virtual void invoke_scroll() { this->lv_scroll(this); } + struct main_content { + vis_line_t mc_line; + }; + struct static_overlay_content {}; + struct overlay_menu { + vis_line_t om_line; + }; + struct overlay_content { + vis_line_t oc_main_line; + vis_line_t oc_line; + }; + struct empty_space {}; + + using display_line_content_t = mapbox::util::variant<main_content, + overlay_menu, + static_overlay_content, + overlay_content, + empty_space>; + protected: void delegate_scroll_out() { @@ -527,6 +542,9 @@ protected: void update_top_from_selection(); + vis_line_t get_overlay_top(vis_line_t row, size_t count, size_t total); + size_t get_overlay_height(size_t total, vis_line_t view_height); + enum class lv_mode_t { NONE, DOWN, @@ -542,11 +560,12 @@ protected: list_overlay_source* lv_overlay_source{nullptr}; action lv_scroll; /*< The scroll action. */ WINDOW* lv_window{nullptr}; /*< The window that contains this view. */ - unsigned int lv_x{0}; - unsigned int lv_y{0}; /*< The y offset of this view. */ vis_line_t lv_top{0}; /*< The line at the top of the view. */ - unsigned int lv_left{0}; /*< The column at the left of the view. */ + int lv_left{0}; /*< The column at the left of the view. */ vis_line_t lv_height{0}; /*< The abs/rel height of the view. */ + bool lv_overlay_focused{false}; + vis_line_t lv_focused_overlay_top{0_vl}; + vis_line_t lv_focused_overlay_selection{0_vl}; int lv_history_position{0}; bool lv_overlay_needs_update{true}; bool lv_show_scrollbar{true}; /*< Draw the scrollbar in the view. */ @@ -565,6 +584,10 @@ protected: int lv_mouse_y{-1}; lv_mode_t lv_mouse_mode{lv_mode_t::NONE}; vis_line_t lv_tail_space{1}; + + std::vector<display_line_content_t> lv_display_lines; + unsigned int lv_scroll_top{0}; + unsigned int lv_scroll_bottom{0}; }; #endif |