summaryrefslogtreecommitdiffstats
path: root/src/listview_curses.hh
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/listview_curses.hh199
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