BufferView: add scroll_view_{up,down}()

This commit is contained in:
Josh Holtrop 2017-09-13 20:08:09 -04:00
parent 84759d0a36
commit 70aba6e2d4
3 changed files with 189 additions and 0 deletions

View File

@ -192,6 +192,46 @@ bool BufferView::cursor_move(CursorMovement which, bool allow_eol)
return moved; return moved;
} }
void BufferView::scroll_view_up(int n_lines, bool allow_eol)
{
int so = effective_scroll_offset();
int rows_to_move_cursor = (so + n_lines) - (m_height - m_cursor_screen_row - 1);
rows_to_move_cursor = std::min(calculate_rows_above_screen(rows_to_move_cursor), rows_to_move_cursor);
int actual_lines_moved = 0;
while (rows_to_move_cursor-- > 0)
{
if (move_cursor_screen_row_up(allow_eol))
{
actual_lines_moved++;
}
else
{
break;
}
}
m_cursor_screen_row += (n_lines - actual_lines_moved);
}
void BufferView::scroll_view_down(int n_lines, bool allow_eol)
{
int so = effective_scroll_offset();
int rows_to_move_cursor = (so + n_lines) - m_cursor_screen_row;
rows_to_move_cursor = std::min(calculate_rows_below_screen(rows_to_move_cursor), rows_to_move_cursor);
int actual_lines_moved = 0;
while (rows_to_move_cursor-- > 0)
{
if (move_cursor_screen_row_down(allow_eol))
{
actual_lines_moved++;
}
else
{
break;
}
}
m_cursor_screen_row -= (n_lines - actual_lines_moved);
}
/************************************************************************** /**************************************************************************
* Internal functions * Internal functions
*************************************************************************/ *************************************************************************/
@ -374,3 +414,35 @@ void BufferView::move_forward_to_screen_position(
} }
} }
} }
int BufferView::calculate_rows_above_screen(int stop_at)
{
if (m_lines.empty())
return 0;
const LineDescriptor & first_line = *m_lines.begin();
auto iterator = std::make_shared<Buffer::Iterator>(*first_line.line);
int lines = std::max(0, -first_line.row_offset);
while (lines < stop_at)
{
if (!iterator->go_previous_line())
break;
lines += calculate_rows_in_line(iterator);
}
return lines;
}
int BufferView::calculate_rows_below_screen(int stop_at)
{
if (m_lines.empty())
return 0;
const LineDescriptor & last_line = *m_lines.rbegin();
auto iterator = std::make_shared<Buffer::Iterator>(*last_line.line);
int lines = std::max(0, last_line.row_offset + last_line.n_rows - m_height);
while (lines < stop_at)
{
if (!iterator->go_next_line())
break;
lines += calculate_rows_in_line(iterator);
}
return lines;
}

View File

@ -84,6 +84,8 @@ public:
{ {
m_cursor_screen_row = cursor_screen_row; m_cursor_screen_row = cursor_screen_row;
} }
void scroll_view_up(int n_lines, bool allow_eol);
void scroll_view_down(int n_lines, bool allow_eol);
protected: protected:
struct LineDescriptor struct LineDescriptor
@ -126,6 +128,8 @@ protected:
void move_forward_to_screen_position( void move_forward_to_screen_position(
std::shared_ptr<Buffer::Iterator> line, int target_row_offset, std::shared_ptr<Buffer::Iterator> line, int target_row_offset,
bool allow_eol); bool allow_eol);
int calculate_rows_above_screen(int stop_at);
int calculate_rows_below_screen(int stop_at);
}; };
#endif #endif

View File

@ -520,3 +520,116 @@ TEST(BufferViewTest, cursor_move_screen_row_up_and_down_returns_false_at_top_and
} }
EXPECT_FALSE(bv.cursor_move(BufferView::CursorMovement::SCREEN_ROW_DOWN, false)); EXPECT_FALSE(bv.cursor_move(BufferView::CursorMovement::SCREEN_ROW_DOWN, false));
} }
TEST(BufferViewTest, scrolls_the_view_up_and_down)
{
auto b = buffer1();
auto iterator = b->add_iterator();
BufferView bv(b, iterator, Cwd);
bv.resize(40, 6);
bv.update();
EXPECT_EQ(0, LineNumber(iterator));
EXPECT_EQ(0, bv.cursor_screen_row());
bv.scroll_view_down(1, false);
bv.update();
EXPECT_EQ(1, LineNumber(iterator));
EXPECT_EQ(0, bv.cursor_screen_row());
bv.scroll_view_down(5, false);
bv.update();
EXPECT_EQ(6, LineNumber(iterator));
EXPECT_EQ(0, bv.cursor_screen_row());
bv.scroll_view_down(1, false);
bv.update();
EXPECT_EQ(7, LineNumber(iterator));
EXPECT_EQ(0, bv.cursor_screen_row());
bv.scroll_view_down(1, false);
bv.update();
EXPECT_EQ(7, LineNumber(iterator));
EXPECT_EQ(0, bv.cursor_screen_row());
bv.scroll_view_down(3, false);
bv.update();
EXPECT_EQ(7, LineNumber(iterator));
EXPECT_EQ(0, bv.cursor_screen_row());
bv.scroll_view_up(1, false);
bv.update();
EXPECT_EQ(7, LineNumber(iterator));
EXPECT_EQ(1, bv.cursor_screen_row());
bv.scroll_view_up(4, false);
bv.update();
EXPECT_EQ(7, LineNumber(iterator));
EXPECT_EQ(5, bv.cursor_screen_row());
bv.scroll_view_up(1, false);
bv.update();
EXPECT_EQ(6, LineNumber(iterator));
EXPECT_EQ(5, bv.cursor_screen_row());
bv.scroll_view_up(1, false);
bv.update();
EXPECT_EQ(5, LineNumber(iterator));
EXPECT_EQ(5, bv.cursor_screen_row());
bv.scroll_view_up(1, false);
bv.update();
EXPECT_EQ(5, LineNumber(iterator));
EXPECT_EQ(5, bv.cursor_screen_row());
bv.scroll_view_up(3, false);
bv.update();
EXPECT_EQ(5, LineNumber(iterator));
EXPECT_EQ(5, bv.cursor_screen_row());
}
TEST(BufferViewTest, scrolls_the_view_up_and_down_with_nonzero_scroll_offset)
{
auto b = buffer1();
auto iterator = b->add_iterator();
BufferView bv(b, iterator, Cwd);
bv.resize(40, 6);
bv.set_scroll_offset(2);
bv.update();
EXPECT_EQ(0, LineNumber(iterator));
EXPECT_EQ(0, bv.cursor_screen_row());
bv.scroll_view_down(1, false);
bv.update();
EXPECT_EQ(3, LineNumber(iterator));
EXPECT_EQ(2, bv.cursor_screen_row());
bv.scroll_view_down(5, false);
bv.update();
EXPECT_EQ(8, LineNumber(iterator));
EXPECT_EQ(2, bv.cursor_screen_row());
bv.scroll_view_down(1, false);
bv.update();
EXPECT_EQ(9, LineNumber(iterator));
EXPECT_EQ(2, bv.cursor_screen_row());
bv.scroll_view_down(1, false);
bv.update();
EXPECT_EQ(9, LineNumber(iterator));
EXPECT_EQ(2, bv.cursor_screen_row());
bv.scroll_view_down(3, false);
bv.update();
EXPECT_EQ(9, LineNumber(iterator));
EXPECT_EQ(2, bv.cursor_screen_row());
bv.scroll_view_up(1, false);
bv.update();
EXPECT_EQ(9, LineNumber(iterator));
EXPECT_EQ(3, bv.cursor_screen_row());
bv.scroll_view_up(4, false);
bv.update();
EXPECT_EQ(5, LineNumber(iterator));
EXPECT_EQ(3, bv.cursor_screen_row());
bv.scroll_view_up(1, false);
bv.update();
EXPECT_EQ(4, LineNumber(iterator));
EXPECT_EQ(3, bv.cursor_screen_row());
bv.scroll_view_up(1, false);
bv.update();
EXPECT_EQ(3, LineNumber(iterator));
EXPECT_EQ(3, bv.cursor_screen_row());
bv.scroll_view_up(1, false);
bv.update();
EXPECT_EQ(3, LineNumber(iterator));
EXPECT_EQ(3, bv.cursor_screen_row());
bv.scroll_view_up(3, false);
bv.update();
EXPECT_EQ(3, LineNumber(iterator));
EXPECT_EQ(3, bv.cursor_screen_row());
}