[Add] Bound-checked terminal scrolling.
This commit is contained in:
parent
846b8595f4
commit
70f096abc4
@ -1,6 +1,7 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
|
#include <SDL3/SDL_events.h>
|
||||||
|
|
||||||
#include "gfx/txt_renderer.h"
|
#include "gfx/txt_renderer.h"
|
||||||
#include "terminal.h"
|
#include "terminal.h"
|
||||||
@ -8,6 +9,7 @@
|
|||||||
Terminal::Terminal(void) {
|
Terminal::Terminal(void) {
|
||||||
/* Placeholder welcome message to history. */
|
/* Placeholder welcome message to history. */
|
||||||
_history.push_back("Welcome to Bettola");
|
_history.push_back("Welcome to Bettola");
|
||||||
|
_scroll_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Terminal::_on_ret_press(void) {
|
void Terminal::_on_ret_press(void) {
|
||||||
@ -26,6 +28,15 @@ void Terminal::_on_ret_press(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_input_buffer.clear();
|
_input_buffer.clear();
|
||||||
|
/* TODO: Ugly hack. Refactor to pass window height
|
||||||
|
* We need the window height to know if we should
|
||||||
|
* auto-scroll, but we don't have it here.
|
||||||
|
* Assume the height of 500 for now.
|
||||||
|
*/
|
||||||
|
int visible_lines = (500-5.0f)/20.0f; /* Subtract padding. */
|
||||||
|
if((int)_history.size()+1 > visible_lines) {
|
||||||
|
_scroll_offset = (_history.size()+1) - visible_lines+1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Terminal::handle_input(SDL_Event* event) {
|
void Terminal::handle_input(SDL_Event* event) {
|
||||||
@ -42,8 +53,27 @@ void Terminal::handle_input(SDL_Event* event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Terminal::scroll(int amount, int win_content_height) {
|
||||||
|
/* amount > 0 = scroll up. amount < 0 = scroll down. */
|
||||||
|
_scroll_offset += amount;
|
||||||
|
|
||||||
|
/* Lower bound: Don't scroll below the top of the history. */
|
||||||
|
if(_scroll_offset < 0) {
|
||||||
|
_scroll_offset = 0;
|
||||||
|
}
|
||||||
|
/* Upper bound: Don't scroll past the last command. */
|
||||||
|
float line_height = 20.0f;
|
||||||
|
int visible_lines = win_content_height / line_height;
|
||||||
|
int max_scroll = (_history.size()+1) - visible_lines;
|
||||||
|
if(max_scroll < 0) max_scroll = 0;
|
||||||
|
if(_scroll_offset > max_scroll) {
|
||||||
|
_scroll_offset = max_scroll;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Terminal::render(TextRenderer* renderer, int x, int y, int width, int height,
|
void Terminal::render(TextRenderer* renderer, int x, int y, int width, int height,
|
||||||
bool show_cursor) {
|
bool show_cursor) {
|
||||||
|
|
||||||
float white[] = { 1.0f, 1.0f, 1.0f };
|
float white[] = { 1.0f, 1.0f, 1.0f };
|
||||||
float green[] = { 0.2f, 1.0f, 0.2f };
|
float green[] = { 0.2f, 1.0f, 0.2f };
|
||||||
float line_height = 20.0f;
|
float line_height = 20.0f;
|
||||||
@ -53,19 +83,19 @@ void Terminal::render(TextRenderer* renderer, int x, int y, int width, int heigh
|
|||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
glScissor(x, y, width, height);
|
glScissor(x, y, width, height);
|
||||||
|
|
||||||
/* Draw history. */
|
/* Draw History. */
|
||||||
for(size_t i = 0; i < _history.size(); ++i) {
|
for(size_t i = _scroll_offset; i < _history.size(); ++i) {
|
||||||
float y_pos = (y+height) - padding - line_height - (i*line_height);
|
float y_pos = (y+height) - padding - line_height - ((i - _scroll_offset) * line_height);
|
||||||
renderer->render_text(_history[i].c_str(), x+padding, y_pos, 1.0f, white);
|
renderer->render_text(_history[i].c_str(), x+padding, y_pos, 1.0f, white);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Draw current input line. */
|
/* Draw current input line. */
|
||||||
std::string prompt = "> ";
|
std::string line_to_render = "> " + _input_buffer;
|
||||||
std::string line_to_render = prompt + _input_buffer;
|
|
||||||
if(show_cursor) {
|
if(show_cursor) {
|
||||||
line_to_render += "_";
|
line_to_render += "_";
|
||||||
}
|
}
|
||||||
float prompt_y_pos = (y+height) - padding - line_height - (_history.size()*line_height);
|
float prompt_y_pos = (y+height) - padding - line_height
|
||||||
|
- ((_history.size()-_scroll_offset)*line_height);
|
||||||
renderer->render_text(line_to_render.c_str(), x+padding, prompt_y_pos, 1.0f, green);
|
renderer->render_text(line_to_render.c_str(), x+padding, prompt_y_pos, 1.0f, green);
|
||||||
|
|
||||||
/* Disable scissor test. */
|
/* Disable scissor test. */
|
||||||
|
|||||||
@ -11,10 +11,12 @@ public:
|
|||||||
|
|
||||||
void handle_input(SDL_Event* event);
|
void handle_input(SDL_Event* event);
|
||||||
void render(TextRenderer* renderer, int x, int y, int width, int height, bool show_cursor);
|
void render(TextRenderer* renderer, int x, int y, int width, int height, bool show_cursor);
|
||||||
|
void scroll(int amount, int content_height);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _on_ret_press(void);
|
void _on_ret_press(void);
|
||||||
|
|
||||||
std::string _input_buffer;
|
std::string _input_buffer;
|
||||||
std::vector<std::string> _history;
|
std::vector<std::string> _history;
|
||||||
|
int _scroll_offset;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -11,6 +11,7 @@ UIWindow::UIWindow(const char* title, int x, int y, int width, int height) {
|
|||||||
_height = height;
|
_height = height;
|
||||||
_content = nullptr;
|
_content = nullptr;
|
||||||
_is_dragging = false;
|
_is_dragging = false;
|
||||||
|
_is_hovered = false;
|
||||||
_is_focused = false; /* Not focused by default? */
|
_is_focused = false; /* Not focused by default? */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,6 +89,16 @@ void UIWindow::handle_event(SDL_Event* event) {
|
|||||||
_x = event->motion.x - _drag_offset_x;
|
_x = event->motion.x - _drag_offset_x;
|
||||||
_y = event->motion.y - _drag_offset_y;
|
_y = event->motion.y - _drag_offset_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check if mouse hovered over window. */
|
||||||
|
_is_hovered = is_point_inside(event->motion.x, event->motion.y);
|
||||||
|
} else if(event->type == SDL_EVENT_MOUSE_WHEEL) {
|
||||||
|
/* Only scroll window if mouse is hovering. */
|
||||||
|
if(_is_hovered && _content) {
|
||||||
|
/* SDL's wheel motion is negative scroll up on the y. */
|
||||||
|
int content_height_gl = _height - title_bar_height;
|
||||||
|
_content->scroll(-event->wheel.y, content_height_gl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -23,6 +23,7 @@ private:
|
|||||||
std::string _title;
|
std::string _title;
|
||||||
Terminal* _content;
|
Terminal* _content;
|
||||||
bool _is_focused; /* Managed by desktop. */
|
bool _is_focused; /* Managed by desktop. */
|
||||||
|
bool _is_hovered; /* Send scroll events even if not focused. */
|
||||||
|
|
||||||
bool _is_dragging;
|
bool _is_dragging;
|
||||||
int _drag_offset_x, _drag_offset_y;
|
int _drag_offset_x, _drag_offset_y;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user