mirror of https://github.com/tstack/lnav.git
155 lines
3.3 KiB
C++
155 lines
3.3 KiB
C++
/**
|
|
* @file listview_curses.cc
|
|
*/
|
|
|
|
#include "listview_curses.hh"
|
|
|
|
using namespace std;
|
|
|
|
listview_curses::listview_curses()
|
|
: lv_source(NULL),
|
|
lv_window(NULL),
|
|
lv_y(0),
|
|
lv_top(0),
|
|
lv_left(0),
|
|
lv_height(0),
|
|
lv_needs_update(true),
|
|
lv_show_scrollbar(true)
|
|
{ }
|
|
|
|
listview_curses::~listview_curses()
|
|
{ }
|
|
|
|
void listview_curses::reload_data(void)
|
|
{
|
|
if (this->lv_source == NULL) {
|
|
this->lv_top = vis_line_t(0);
|
|
}
|
|
else if (this->lv_top >= this->get_inner_height()) {
|
|
this->lv_top = max(vis_line_t(0),
|
|
vis_line_t(this->get_inner_height() - 1));
|
|
}
|
|
this->lv_needs_update = true;
|
|
}
|
|
|
|
bool listview_curses::handle_key(int ch)
|
|
{
|
|
vis_line_t height(0);
|
|
|
|
unsigned long width;
|
|
bool retval = true;
|
|
|
|
this->get_dimensions(height, width);
|
|
switch (ch) {
|
|
case 'l':
|
|
case KEY_RIGHT:
|
|
this->shift_left(width / 2);
|
|
break;
|
|
|
|
case 'h':
|
|
case KEY_LEFT:
|
|
this->shift_left(-(width / 2));
|
|
break;
|
|
|
|
case '\r':
|
|
case 'j':
|
|
case KEY_DOWN:
|
|
this->shift_top(vis_line_t(1));
|
|
break;
|
|
|
|
case 'k':
|
|
case KEY_UP:
|
|
this->shift_top(vis_line_t(-1));
|
|
break;
|
|
|
|
case 'b':
|
|
case KEY_BACKSPACE:
|
|
case KEY_PPAGE:
|
|
this->shift_top(-height);
|
|
break;
|
|
|
|
case ' ':
|
|
case KEY_NPAGE:
|
|
this->shift_top(height);
|
|
break;
|
|
|
|
case KEY_HOME:
|
|
this->set_top(vis_line_t(0));
|
|
break;
|
|
|
|
case KEY_END:
|
|
case 'B':
|
|
this->set_top(max(vis_line_t(0),
|
|
max(this->lv_top,
|
|
vis_line_t(this->get_inner_height() - height + 1))));
|
|
break;
|
|
|
|
default:
|
|
retval = false;
|
|
break;
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
void listview_curses::do_update(void)
|
|
{
|
|
if (this->lv_window != NULL && this->lv_needs_update) {
|
|
vis_line_t y(this->lv_y), height, bottom, lines;
|
|
struct line_range lr;
|
|
unsigned long width;
|
|
size_t row_count;
|
|
|
|
this->get_dimensions(height, width);
|
|
lr.lr_start = this->lv_left;
|
|
lr.lr_end = this->lv_left + width;
|
|
|
|
row_count = this->get_inner_height();
|
|
if (this->lv_top >= (int)row_count) {
|
|
this->lv_top = max(vis_line_t(0), vis_line_t(row_count) - height);
|
|
}
|
|
|
|
lines = y + min(height, vis_line_t(row_count) - this->lv_top);
|
|
bottom = y + height;
|
|
for (; y < lines; ++y) {
|
|
vis_line_t row = this->lv_top + y - vis_line_t(this->lv_y);
|
|
attr_line_t al;
|
|
string line;
|
|
|
|
this->lv_source->listview_value_for_row(*this, row, al);
|
|
this->mvwattrline(this->lv_window, y, 0, al, lr);
|
|
}
|
|
|
|
/* Clear out any remaining lines on the display. */
|
|
for (; y < bottom; ++y) {
|
|
wmove(this->lv_window, y, 0);
|
|
wclrtoeol(this->lv_window);
|
|
}
|
|
|
|
if (this->lv_show_scrollbar) {
|
|
double progress = 1.0;
|
|
double coverage = 1.0;
|
|
|
|
if (this->get_inner_height() > 0) {
|
|
progress = (double)this->lv_top / (double)this->get_inner_height();
|
|
coverage = (double)height / (double)this->get_inner_height();
|
|
}
|
|
|
|
y = vis_line_t(this->lv_y) +
|
|
vis_line_t((int)(progress * (double)height));
|
|
lines = y + min(height, vis_line_t((int)(coverage * (double)height)));
|
|
for (; y <= lines; ++y) {
|
|
char buffer;
|
|
|
|
mvwinnstr(this->lv_window, y, width - 1, &buffer, 1);
|
|
wattron(this->lv_window, A_REVERSE);
|
|
mvwaddnstr(this->lv_window, y, width - 1, &buffer, 1);
|
|
wattroff(this->lv_window, A_REVERSE);
|
|
}
|
|
wmove(this->lv_window, this->lv_y + height - 1, 0);
|
|
}
|
|
|
|
this->lv_needs_update = false;
|
|
}
|
|
}
|