BufferPane: add ability to draw line number gutter

This commit is contained in:
Josh Holtrop 2017-09-26 20:47:48 -04:00
parent 6d310f0f14
commit 1c673817d2
2 changed files with 82 additions and 10 deletions

View File

@ -1,4 +1,5 @@
#include "BufferPane.h" #include "BufferPane.h"
#include <cmath>
int BufferPane::Cwd::operator()(uint32_t character) int BufferPane::Cwd::operator()(uint32_t character)
{ {
@ -24,26 +25,53 @@ BufferPane::BufferPane(Window * window, std::shared_ptr<Buffer> buffer)
m_buffer_view->set_scroll_offset(5); m_buffer_view->set_scroll_offset(5);
m_buffer_view->update(); m_buffer_view->update();
m_show_status_bar = true; m_show_status_bar = true;
m_show_line_number_gutter = true;
m_command_mode = false; m_command_mode = false;
m_focused = false; m_focused = false;
m_rows = 0;
m_columns = 0;
} }
void BufferPane::resize(int width, int height) void BufferPane::resize(int width, int height)
{ {
Pane::resize(width, height); Pane::resize(width, height);
m_columns = std::max(1, m_width / m_window->font()->get_advance()); resize_buffer_view();
}
void BufferPane::resize_buffer_view()
{
if (m_show_line_number_gutter)
{
int max_line_possible = 1;
if (m_iterator->valid())
{
max_line_possible = std::min(m_iterator->line() + m_rows - m_buffer_view->cursor_screen_row(), m_buffer->end().line());
}
m_line_number_gutter_width = log10(max_line_possible) + 1;
}
else
{
m_line_number_gutter_width = 0;
}
int columns = std::max(1, (m_width - col_x(0)) / m_window->font()->get_advance());
int height_subtract = 0; int height_subtract = 0;
if (m_show_status_bar) if (m_show_status_bar)
{ {
height_subtract = m_window->font()->get_line_height() + 1; height_subtract = m_window->font()->get_line_height() + 1;
} }
m_rows = std::max(1, (m_height - height_subtract) / m_window->font()->get_line_height()); int rows = std::max(1, (m_height - height_subtract) / m_window->font()->get_line_height());
m_buffer_view->resize(m_columns, m_rows); if ((rows != m_rows) || (columns != m_columns))
m_buffer_view->update(); {
m_rows = rows;
m_columns = columns;
m_buffer_view->resize(m_columns, m_rows);
m_buffer_view->update();
}
} }
void BufferPane::draw() void BufferPane::draw()
{ {
resize_buffer_view();
if (m_iterator->valid()) if (m_iterator->valid())
{ {
for (auto line_iterator = m_buffer_view->vert_iter(); for (auto line_iterator = m_buffer_view->vert_iter();
@ -57,6 +85,10 @@ void BufferPane::draw()
{ {
draw_cursor(col_x(0), row_y(0), 0, 1); draw_cursor(col_x(0), row_y(0), 0, 1);
} }
if (m_show_line_number_gutter)
{
m_window->gl()->draw_rect(win_x(m_line_number_gutter_width * m_window->font()->get_advance() + 1), win_y(0), 1, m_height, 0.5, 0.5, 0.5, 1.0);
}
if (m_show_status_bar) if (m_show_status_bar)
{ {
draw_status_bar(); draw_status_bar();
@ -82,6 +114,10 @@ void BufferPane::scroll_window_down(Window::ScrollMode scroll_mode)
void BufferPane::draw_buffer_line(int screen_row, std::shared_ptr<Buffer::Iterator> start_of_line) void BufferPane::draw_buffer_line(int screen_row, std::shared_ptr<Buffer::Iterator> start_of_line)
{ {
if (m_show_line_number_gutter)
{
draw_line_number(screen_row, start_of_line->line());
}
int last_drawn_crosshair_row = -1; int last_drawn_crosshair_row = -1;
for (auto it = m_buffer_view->horiz_iter(start_of_line); for (auto it = m_buffer_view->horiz_iter(start_of_line);
it.is_valid(); it.is_valid();
@ -96,7 +132,7 @@ void BufferPane::draw_buffer_line(int screen_row, std::shared_ptr<Buffer::Iterat
if ((draw_row > last_drawn_crosshair_row) && if ((draw_row > last_drawn_crosshair_row) &&
((!it.is_eol()) || (it.row_offset() == 0))) ((!it.is_eol()) || (it.row_offset() == 0)))
{ {
draw_crosshair(0, row_y(draw_row), col_x(m_columns)); draw_crosshair(col_x(0), row_y(draw_row), col_x(m_columns));
last_drawn_crosshair_row = draw_row; last_drawn_crosshair_row = draw_row;
} }
} }
@ -130,7 +166,7 @@ void BufferPane::draw_buffer_line(int screen_row, std::shared_ptr<Buffer::Iterat
* did not do this then the draw_crosshair for the next * did not do this then the draw_crosshair for the next
* character on the new row would overwrite the wrapped * character on the new row would overwrite the wrapped
* part of the cursor. */ * part of the cursor. */
draw_crosshair(0, row_y(row), col_x(m_columns)); draw_crosshair(col_x(0), row_y(row), col_x(m_columns));
last_drawn_crosshair_row = row; last_drawn_crosshair_row = row;
} }
} }
@ -146,12 +182,12 @@ void BufferPane::draw_buffer_line(int screen_row, std::shared_ptr<Buffer::Iterat
} }
else else
{ {
draw_character(it.code_point(), draw_row, it.screen_column()); draw_buffer_character(it.code_point(), draw_row, it.screen_column());
} }
} }
} }
void BufferPane::draw_character(uint32_t character, int screen_row, int screen_column) void BufferPane::draw_buffer_character(uint32_t character, int screen_row, int screen_column)
{ {
if ((character != ' ') && if ((character != ' ') &&
(character != '\t') && (character != '\t') &&
@ -221,6 +257,33 @@ void BufferPane::draw_crosshair(int x, int y, int width, int height)
} }
} }
void BufferPane::draw_line_number(int screen_row, size_t line_number)
{
if (screen_row >= 0)
{
char line_number_string[20];
int length = snprintf(line_number_string, sizeof(line_number_string), "%lu", line_number + 1u);
int x = (m_line_number_gutter_width - length) * m_window->font()->get_advance();
int y = row_y(screen_row);
float r, g;
if (line_number == m_iterator->line())
{
r = 1.0;
g = 1.0;
}
else
{
r = 0.6;
g = 0.6;
}
for (int i = 0; i < length; i++)
{
m_window->gl()->draw_character(win_x(x), win_y(y), line_number_string[i], *m_window->font(), r, g, 0.0, 1.0);
x += m_window->font()->get_advance();
}
}
}
void BufferPane::exit_insert_mode() void BufferPane::exit_insert_mode()
{ {
if (insert_mode()) if (insert_mode())
@ -408,6 +471,7 @@ void BufferPane::set_command_mode()
{ {
m_command_mode = true; m_command_mode = true;
set_show_status_bar(false); set_show_status_bar(false);
set_show_line_number_gutter(false);
enter_insert_mode(Window::EnterInsertModeMode::START_OF_CHAR); enter_insert_mode(Window::EnterInsertModeMode::START_OF_CHAR);
} }

View File

@ -45,6 +45,10 @@ public:
{ {
m_show_status_bar = show_status_bar; m_show_status_bar = show_status_bar;
} }
void set_show_line_number_gutter(bool show_line_number_gutter)
{
m_show_line_number_gutter = show_line_number_gutter;
}
void set_command_mode(); void set_command_mode();
void set_focused(bool focused) void set_focused(bool focused)
{ {
@ -55,12 +59,13 @@ public:
protected: protected:
void draw_buffer_line(int screen_row, std::shared_ptr<Buffer::Iterator> start_of_line); void draw_buffer_line(int screen_row, std::shared_ptr<Buffer::Iterator> start_of_line);
void draw_character(uint32_t character, int screen_row, int screen_column); void draw_buffer_character(uint32_t character, int screen_row, int screen_column);
void draw_cursor(int x, int y, int i, int columns); void draw_cursor(int x, int y, int i, int columns);
void draw_crosshair(int x, int y, int width = -1, int height = -1); void draw_crosshair(int x, int y, int width = -1, int height = -1);
void draw_line_number(int screen_row, size_t line_number);
int col_x(int col) int col_x(int col)
{ {
return col * m_window->font()->get_advance(); return (m_line_number_gutter_width + col) * m_window->font()->get_advance() + (m_show_line_number_gutter ? 3 : 0);
} }
int row_y(int row) int row_y(int row)
{ {
@ -70,6 +75,7 @@ protected:
size_t display_column() const; size_t display_column() const;
void draw_status_bar(); void draw_status_bar();
int calculate_lines_to_scroll(Window::ScrollMode scroll_mode); int calculate_lines_to_scroll(Window::ScrollMode scroll_mode);
void resize_buffer_view();
Window * m_window; Window * m_window;
std::shared_ptr<Buffer> m_buffer; std::shared_ptr<Buffer> m_buffer;
@ -77,9 +83,11 @@ protected:
std::shared_ptr<BufferView> m_buffer_view; std::shared_ptr<BufferView> m_buffer_view;
int m_rows; int m_rows;
int m_columns; int m_columns;
int m_line_number_gutter_width;
std::shared_ptr<Buffer::Iterator> m_iterator; std::shared_ptr<Buffer::Iterator> m_iterator;
std::list<std::pair<int, Buffer::Iterator>> m_screen_lines; std::list<std::pair<int, Buffer::Iterator>> m_screen_lines;
bool m_show_status_bar; bool m_show_status_bar;
bool m_show_line_number_gutter;
bool m_command_mode; bool m_command_mode;
bool m_focused; bool m_focused;
}; };