[Add] Bound-checked terminal scrolling.
This commit is contained in:
		
							parent
							
								
									846b8595f4
								
							
						
					
					
						commit
						70f096abc4
					
				@ -1,6 +1,7 @@
 | 
			
		||||
#include <cstdio>
 | 
			
		||||
#include <SDL3/SDL.h>
 | 
			
		||||
#include <GL/glew.h>
 | 
			
		||||
#include <SDL3/SDL_events.h>
 | 
			
		||||
 | 
			
		||||
#include "gfx/txt_renderer.h"
 | 
			
		||||
#include "terminal.h"
 | 
			
		||||
@ -8,6 +9,7 @@
 | 
			
		||||
Terminal::Terminal(void) {
 | 
			
		||||
  /* Placeholder welcome message to history. */
 | 
			
		||||
  _history.push_back("Welcome to Bettola");
 | 
			
		||||
  _scroll_offset = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Terminal::_on_ret_press(void) {
 | 
			
		||||
@ -26,6 +28,15 @@ void Terminal::_on_ret_press(void) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  _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) {
 | 
			
		||||
@ -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,
 | 
			
		||||
                      bool show_cursor) {
 | 
			
		||||
 | 
			
		||||
  float white[]     = { 1.0f, 1.0f, 1.0f };
 | 
			
		||||
  float green[]     = { 0.2f, 1.0f, 0.2f };
 | 
			
		||||
  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);
 | 
			
		||||
  glScissor(x, y, width, height);
 | 
			
		||||
 | 
			
		||||
  /* Draw history. */
 | 
			
		||||
  for(size_t i = 0; i < _history.size(); ++i) {
 | 
			
		||||
    float y_pos = (y+height) - padding - line_height - (i*line_height);
 | 
			
		||||
  /* Draw History. */
 | 
			
		||||
  for(size_t i = _scroll_offset; i < _history.size(); ++i) {
 | 
			
		||||
    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);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* Draw current input line. */
 | 
			
		||||
  std::string prompt = "> ";
 | 
			
		||||
  std::string line_to_render = prompt + _input_buffer;
 | 
			
		||||
  std::string line_to_render = "> " + _input_buffer;
 | 
			
		||||
  if(show_cursor) {
 | 
			
		||||
    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);
 | 
			
		||||
 | 
			
		||||
  /* Disable scissor test. */
 | 
			
		||||
 | 
			
		||||
@ -11,10 +11,12 @@ public:
 | 
			
		||||
 | 
			
		||||
  void handle_input(SDL_Event* event);
 | 
			
		||||
  void render(TextRenderer* renderer, int x, int y, int width, int height, bool show_cursor);
 | 
			
		||||
  void scroll(int amount, int content_height);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  void _on_ret_press(void);
 | 
			
		||||
 | 
			
		||||
  std::string _input_buffer;
 | 
			
		||||
  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;
 | 
			
		||||
  _content      = nullptr;
 | 
			
		||||
  _is_dragging  = false;
 | 
			
		||||
  _is_hovered   = false;
 | 
			
		||||
  _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;
 | 
			
		||||
      _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;
 | 
			
		||||
  Terminal* _content;
 | 
			
		||||
  bool _is_focused; /* Managed by desktop. */
 | 
			
		||||
  bool _is_hovered; /* Send scroll events even if not focused. */
 | 
			
		||||
 | 
			
		||||
  bool _is_dragging;
 | 
			
		||||
  int _drag_offset_x, _drag_offset_y;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user