[Fix] Regression bugs with scrolling and auto-scrolling
This commit is contained in:
		
							parent
							
								
									6a5515e276
								
							
						
					
					
						commit
						bb8591a803
					
				@ -20,7 +20,7 @@ Terminal::Terminal(GameState* game_state)
 | 
			
		||||
 | 
			
		||||
Terminal::~Terminal(void) {}
 | 
			
		||||
 | 
			
		||||
void Terminal::update(void) {
 | 
			
		||||
void Terminal::update(int content_width, int content_height) {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -92,7 +92,8 @@ void Terminal::_on_ret_press(void) {
 | 
			
		||||
  _game_state->send_network_command(_session_id, command);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Terminal::handle_input(SDL_Event* event, int window_x, int window_y, int window_gl_y) {
 | 
			
		||||
void Terminal::handle_input(SDL_Event* event, int window_x, int window_y, int window_gl_y,
 | 
			
		||||
                            int content_width, int content_height) {
 | 
			
		||||
  /* Pass input to TextView; if true, RET was pressed. */
 | 
			
		||||
  if(event->type == SDL_EVENT_KEY_DOWN) {
 | 
			
		||||
    switch(event->key.key) {
 | 
			
		||||
@ -114,10 +115,10 @@ void Terminal::handle_input(SDL_Event* event, int window_x, int window_y, int wi
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      default:
 | 
			
		||||
        if(_input_view->handle_event(event)) { _on_ret_press(); }
 | 
			
		||||
        if(_input_view->handle_event(event, content_height)) { _on_ret_press(); }
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    if(_input_view->handle_event(event)) { _on_ret_press(); }
 | 
			
		||||
    if(_input_view->handle_event(event, content_height)) { _on_ret_press(); }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -17,8 +17,9 @@ public:
 | 
			
		||||
  Terminal(GameState* game_state);
 | 
			
		||||
  ~Terminal(void);
 | 
			
		||||
 | 
			
		||||
  void update(void) override;
 | 
			
		||||
  void handle_input(SDL_Event* event, int window_x, int window_y, int window_gl_y) override;
 | 
			
		||||
  void update(int content_width, int content_height) override;
 | 
			
		||||
  void handle_input(SDL_Event* event, int window_x, int window_y, int window_gl_y,
 | 
			
		||||
                    int content_width, int content_height) override;
 | 
			
		||||
  void render(const RenderContext& context, int x, int y_screen, int y_gl,
 | 
			
		||||
              int width, int height) override;
 | 
			
		||||
  void scroll(int amount, int content_height) override;
 | 
			
		||||
 | 
			
		||||
@ -29,11 +29,12 @@ Editor::Editor(const std::string& filename)
 | 
			
		||||
 | 
			
		||||
Editor::~Editor(void) {}
 | 
			
		||||
 | 
			
		||||
void Editor::update(void) {
 | 
			
		||||
void Editor::update(int content_width, int content_height) {
 | 
			
		||||
  /* Nothing to do yet. */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Editor::handle_input(SDL_Event* event, int window_x, int window_y, int window_gl_y) {
 | 
			
		||||
void Editor::handle_input(SDL_Event* event, int window_x, int window_y, int window_gl_y,
 | 
			
		||||
                          int content_width, int content_height) {
 | 
			
		||||
  if(!event) return;
 | 
			
		||||
 | 
			
		||||
  _menu_bar->handle_event(event, window_x, window_y);
 | 
			
		||||
@ -44,7 +45,7 @@ void Editor::handle_input(SDL_Event* event, int window_x, int window_y, int wind
 | 
			
		||||
    /* C-S pressed, create a save action. */
 | 
			
		||||
    _pending_action = { ActionType::WRITE_FILE, _filename, _buffer.get_text() };
 | 
			
		||||
  } else {
 | 
			
		||||
    _view->handle_event(event);
 | 
			
		||||
    _view->handle_event(event, content_height);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -59,6 +60,8 @@ void Editor::render(const RenderContext& context, int x, int y_screen, int y_gl,
 | 
			
		||||
  _menu_bar->render_bar_bg(context.ui_renderer, x, y_screen, width);
 | 
			
		||||
  context.ui_renderer->flush_shapes();
 | 
			
		||||
 | 
			
		||||
  context.ui_renderer->enable_scissor(x, y_gl, width, content_height);
 | 
			
		||||
 | 
			
		||||
  /* Pass 2: Main text view. */
 | 
			
		||||
  context.ui_renderer->begin_text();
 | 
			
		||||
  _view->render_text_content(context.ui_renderer, _theme, x, content_y, width, content_height);
 | 
			
		||||
@ -71,6 +74,8 @@ void Editor::render(const RenderContext& context, int x, int y_screen, int y_gl,
 | 
			
		||||
    context.ui_renderer->flush_shapes();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  context.ui_renderer->disable_scissor();
 | 
			
		||||
 | 
			
		||||
  /* Pass 4: Menu bar text and dropdown. */
 | 
			
		||||
  context.ui_renderer->begin_text();
 | 
			
		||||
  _menu_bar->render_bar_text(context.ui_renderer, x, y_screen, width);
 | 
			
		||||
 | 
			
		||||
@ -25,8 +25,9 @@ public:
 | 
			
		||||
  Editor(const std::string& filename);
 | 
			
		||||
  ~Editor(void) override;
 | 
			
		||||
 | 
			
		||||
  void update(void) override;
 | 
			
		||||
  void handle_input(SDL_Event* event, int window_x, int window_y, int window_gl_y) override;
 | 
			
		||||
  void update(int content_width, int content_height) override;
 | 
			
		||||
  void handle_input(SDL_Event* event, int window_x, int window_y, int window_gl_y,
 | 
			
		||||
                    int content_widht, int content_heigth) override;
 | 
			
		||||
  void render(const RenderContext& context, int x, int y_screen, int y_gl,
 | 
			
		||||
              int width, int height) override;
 | 
			
		||||
  void scroll(int amount, int content_height) override;
 | 
			
		||||
 | 
			
		||||
@ -8,8 +8,9 @@
 | 
			
		||||
class IWindowContent {
 | 
			
		||||
public:
 | 
			
		||||
  virtual ~IWindowContent(void) = default;
 | 
			
		||||
  virtual void update(void) = 0;
 | 
			
		||||
  virtual void handle_input(SDL_Event* event, int window_x, int window_y, int window_gl_y) = 0;
 | 
			
		||||
  virtual void update(int content_width, int content_height) = 0;
 | 
			
		||||
  virtual void handle_input(SDL_Event* event, int window_x, int window_y, int window_gl_y,
 | 
			
		||||
                            int content_width, int content_height) = 0;
 | 
			
		||||
  virtual void render(const RenderContext& context, int x, int y_screen, int y_gl,
 | 
			
		||||
                      int width, int height) = 0;
 | 
			
		||||
  virtual void scroll(int amount, int content_height) = 0;
 | 
			
		||||
 | 
			
		||||
@ -22,17 +22,19 @@ TextView::TextView(TextBuffer* buffer, bool handle_ret, bool show_line_numbers,
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TextView::~TextView(void) {}
 | 
			
		||||
TextView::~TextView(void) = default;
 | 
			
		||||
 | 
			
		||||
bool TextView::handle_event(SDL_Event* event) {
 | 
			
		||||
bool TextView::handle_event(SDL_Event* event, int content_height) {
 | 
			
		||||
  if(!_buffer) return false;
 | 
			
		||||
 | 
			
		||||
  if(event->type == SDL_EVENT_TEXT_INPUT) {
 | 
			
		||||
    _buffer->insert_char(event->text.text[0]);
 | 
			
		||||
    _ensure_cursor_visible(content_height);
 | 
			
		||||
  } else if(event->type == SDL_EVENT_KEY_DOWN) {
 | 
			
		||||
    switch(event->key.key) {
 | 
			
		||||
      case SDLK_BACKSPACE:
 | 
			
		||||
        _buffer->backspace();
 | 
			
		||||
        _ensure_cursor_visible(content_height);
 | 
			
		||||
        break;
 | 
			
		||||
      case SDLK_RETURN:
 | 
			
		||||
        /*
 | 
			
		||||
@ -43,22 +45,28 @@ bool TextView::handle_event(SDL_Event* event) {
 | 
			
		||||
        if(_handle_ret) {
 | 
			
		||||
          _buffer->newline();
 | 
			
		||||
        }
 | 
			
		||||
        _ensure_cursor_visible(content_height);
 | 
			
		||||
        return true;
 | 
			
		||||
        break;
 | 
			
		||||
      case SDLK_LEFT:
 | 
			
		||||
        _buffer->move_cursor(-1,0);
 | 
			
		||||
        _ensure_cursor_visible(content_height);
 | 
			
		||||
        break;
 | 
			
		||||
      case SDLK_RIGHT:
 | 
			
		||||
        _buffer->move_cursor(1,0);
 | 
			
		||||
        _ensure_cursor_visible(content_height);
 | 
			
		||||
        break;
 | 
			
		||||
      case SDLK_UP:
 | 
			
		||||
        _buffer->move_cursor(0,-1);
 | 
			
		||||
        _ensure_cursor_visible(content_height);
 | 
			
		||||
        break;
 | 
			
		||||
      case SDLK_DOWN:
 | 
			
		||||
        _buffer->move_cursor(0,1);
 | 
			
		||||
        _ensure_cursor_visible(content_height);
 | 
			
		||||
        break;
 | 
			
		||||
      case SDLK_HOME:
 | 
			
		||||
        _buffer->move_cursor_home();
 | 
			
		||||
        _ensure_cursor_visible(content_height);
 | 
			
		||||
        break;
 | 
			
		||||
      case SDLK_END:
 | 
			
		||||
        _buffer->move_cursor_end();
 | 
			
		||||
@ -77,8 +85,13 @@ void TextView::scroll(int amount, int content_height) {
 | 
			
		||||
    _scroll_offset = 0;
 | 
			
		||||
  }
 | 
			
		||||
  float line_height = 20.0f;
 | 
			
		||||
  int visible_lines = content_height / line_height;
 | 
			
		||||
  int visible_lines = static_cast<int>(content_height / line_height)-1;
 | 
			
		||||
  int max_scroll = _buffer->get_line_count() - visible_lines;
 | 
			
		||||
  /* Allow one extra scroll step if content is larger than visible area. */
 | 
			
		||||
  if(_buffer->get_line_count() > visible_lines) max_scroll += 1;
 | 
			
		||||
  if(max_scroll < 0) {
 | 
			
		||||
    max_scroll = 0;
 | 
			
		||||
  }
 | 
			
		||||
  if(max_scroll < 0) max_scroll = 0;
 | 
			
		||||
  if(_scroll_offset > max_scroll) {
 | 
			
		||||
    _scroll_offset = max_scroll;
 | 
			
		||||
@ -168,7 +181,7 @@ void TextView::render_text_content(UIRenderer* ui_renderer, const SyntaxTheme& t
 | 
			
		||||
     * Culling: If the top of the current line is already below the bottom of the
 | 
			
		||||
     * view, we can stop rendering completely.
 | 
			
		||||
     */
 | 
			
		||||
    if(current_y > y + height) {
 | 
			
		||||
    if(current_y >= y + height) {
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -218,3 +231,20 @@ void TextView::render_cursor(UIRenderer* ui_renderer, const SyntaxTheme& theme,
 | 
			
		||||
    ui_renderer->draw_rect(cursor_x, cursor_y, 2, line_height, theme.normal);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TextView::_ensure_cursor_visible(int content_height) {
 | 
			
		||||
  Point cursor_pos = _buffer->get_cursor_pos();
 | 
			
		||||
  float line_height = 20.0f;
 | 
			
		||||
  int visible_lines = static_cast<int>(content_height / line_height)-1;
 | 
			
		||||
 | 
			
		||||
  /* If cursor above current scroll view, scroll up. */
 | 
			
		||||
  if(cursor_pos.row < _scroll_offset) {
 | 
			
		||||
    _scroll_offset = cursor_pos.row;
 | 
			
		||||
  } else if(cursor_pos.row >= _scroll_offset + visible_lines) {
 | 
			
		||||
    /* Below, scroll down. */
 | 
			
		||||
    _scroll_offset = cursor_pos.row - visible_lines+1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* Re-clamp scroll offset to ensure it's within valid bounds. */
 | 
			
		||||
  scroll(0, content_height);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -29,7 +29,7 @@ public:
 | 
			
		||||
  TextView(TextBuffer* buffer, bool handle_ret, bool show_line_numbers, bool syntax_highlighting);
 | 
			
		||||
  ~TextView(void);
 | 
			
		||||
 | 
			
		||||
  bool handle_event(SDL_Event* event);
 | 
			
		||||
  bool handle_event(SDL_Event* event, int content_height);
 | 
			
		||||
  void scroll(int amount, int content_height);
 | 
			
		||||
  void render_text_content(UIRenderer* ui_renderer, const SyntaxTheme& theme,
 | 
			
		||||
                           int x, int y, int width, int height);
 | 
			
		||||
@ -37,6 +37,7 @@ public:
 | 
			
		||||
                     int x, int y, int width, int height);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  void _ensure_cursor_visible(int content_height);
 | 
			
		||||
  std::vector<Token> _tokenize_line(const std::string& line);
 | 
			
		||||
 | 
			
		||||
  TextBuffer* _buffer;
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,5 @@
 | 
			
		||||
#include <GL/glew.h>
 | 
			
		||||
 | 
			
		||||
#include "ui_renderer.h"
 | 
			
		||||
#include "gfx/shape_renderer.h"
 | 
			
		||||
#include "gfx/txt_renderer.h"
 | 
			
		||||
@ -51,3 +53,12 @@ void UIRenderer::flush_shapes(void) {
 | 
			
		||||
TextRenderer* UIRenderer::get_text_renderer(void) {
 | 
			
		||||
  return _txt_renderer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UIRenderer::enable_scissor(int x, int y, int width, int height) {
 | 
			
		||||
  glEnable(GL_SCISSOR_TEST);
 | 
			
		||||
  glScissor(x, y, width, height);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UIRenderer::disable_scissor(void) {
 | 
			
		||||
  glDisable(GL_SCISSOR_TEST);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -26,6 +26,9 @@ public:
 | 
			
		||||
  /* Expose underlying text renderer for things like width calculation. */
 | 
			
		||||
  TextRenderer* get_text_renderer(void);
 | 
			
		||||
 | 
			
		||||
  void enable_scissor(int x, int y, int width, int height);
 | 
			
		||||
  void disable_scissor(void);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  ShapeRenderer*  _shape_renderer;
 | 
			
		||||
  TextRenderer*   _txt_renderer;
 | 
			
		||||
 | 
			
		||||
@ -129,9 +129,10 @@ void UIWindow::render(const RenderContext& context) {
 | 
			
		||||
  if(_content) {
 | 
			
		||||
    int content_screen_y = _y + title_bar_height;
 | 
			
		||||
    int content_height = _height - title_bar_height;
 | 
			
		||||
    int content_width = _width;
 | 
			
		||||
    /* Got to pass GL y-coord for scissor box to work correctly. */
 | 
			
		||||
    int content_gl_y = context.screen_height - content_screen_y - content_height;
 | 
			
		||||
    _content->render(context, _x, content_screen_y, content_gl_y, _width, content_height);
 | 
			
		||||
    _content->render(context, _x, content_screen_y, content_gl_y, content_width, content_height);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -215,7 +216,9 @@ void UIWindow::handle_event(SDL_Event* event, int screen_width,
 | 
			
		||||
  }
 | 
			
		||||
  if(_content) {
 | 
			
		||||
    int y_gl = screen_height - _y - _height;
 | 
			
		||||
    _content->handle_input(event, _x, _y, y_gl);
 | 
			
		||||
    int content_height = _height - title_bar_height;
 | 
			
		||||
    int content_width = _width;
 | 
			
		||||
    _content->handle_input(event, _x, _y, y_gl, content_width, content_height);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user