[Add] Text editor and generic window content.
This commit is contained in:
parent
324cc795f0
commit
b4d985db29
@ -10,6 +10,7 @@
|
|||||||
#include "gfx/txt_renderer.h"
|
#include "gfx/txt_renderer.h"
|
||||||
#include "terminal.h"
|
#include "terminal.h"
|
||||||
#include "ui/desktop.h"
|
#include "ui/desktop.h"
|
||||||
|
#include "ui/i_window_content.h"
|
||||||
#include "ui/ui_window.h"
|
#include "ui/ui_window.h"
|
||||||
#include <ui/main_menu.h>
|
#include <ui/main_menu.h>
|
||||||
#include <ui/boot_sequence.h>
|
#include <ui/boot_sequence.h>
|
||||||
@ -126,11 +127,9 @@ void GameState::update(void) {
|
|||||||
case Screen::DESKTOP: {
|
case Screen::DESKTOP: {
|
||||||
std::string server_msg;
|
std::string server_msg;
|
||||||
while(_network->poll_message(server_msg)) {
|
while(_network->poll_message(server_msg)) {
|
||||||
UIWindow* focused_window = _desktop->get_focused_window();
|
IWindowContent* content = _desktop->get_focused_window() ?
|
||||||
if(!focused_window)
|
_desktop->get_focused_window()->get_content() : nullptr;
|
||||||
continue;
|
Terminal* terminal = dynamic_cast<Terminal*>(content);
|
||||||
|
|
||||||
Terminal* terminal = focused_window->get_content();
|
|
||||||
if(!terminal)
|
if(!terminal)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
Terminal::Terminal(ClientNetwork* network)
|
Terminal::Terminal(ClientNetwork* network)
|
||||||
: _network(network), _should_close(false), _scroll_offset(0),
|
: _network(network), _should_close(false), _scroll_offset(0),
|
||||||
_prompt("") {
|
_prompt("") {
|
||||||
_input_view = std::make_unique<TextView>(&_input_buffer);
|
_input_view = std::make_unique<TextView>(&_input_buffer, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Terminal::~Terminal(void) {}
|
Terminal::~Terminal(void) {}
|
||||||
@ -42,7 +42,7 @@ void Terminal::set_prompt(const std::string& prompt) {
|
|||||||
_prompt = prompt;
|
_prompt = prompt;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Terminal::close(void) { return _should_close; }
|
bool Terminal::should_close(void) { return _should_close; }
|
||||||
|
|
||||||
void Terminal::_on_ret_press(void) {
|
void Terminal::_on_ret_press(void) {
|
||||||
std::string command = _input_buffer.get_line(0);
|
std::string command = _input_buffer.get_line(0);
|
||||||
@ -123,7 +123,8 @@ void Terminal::render(TextRenderer* renderer, int x, int y, int width, int heigh
|
|||||||
|
|
||||||
/* Render text view for the input right after prompt. */
|
/* Render text view for the input right after prompt. */
|
||||||
float input_x_pos = x + padding + (prompt_str.length() * 8.5f); /* Estimate width */
|
float input_x_pos = x + padding + (prompt_str.length() * 8.5f); /* Estimate width */
|
||||||
_input_view->render(renderer, input_x_pos, prompt_y_pos, show_cursor);
|
float input_width = width - (input_x_pos-x);
|
||||||
|
_input_view->render(renderer, input_x_pos, prompt_y_pos, input_width, line_height, show_cursor);
|
||||||
/* Disable scissor test. */
|
/* Disable scissor test. */
|
||||||
glDisable(GL_SCISSOR_TEST);
|
glDisable(GL_SCISSOR_TEST);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,19 +8,20 @@
|
|||||||
#include "client_network.h"
|
#include "client_network.h"
|
||||||
#include "ui/text_buffer.h"
|
#include "ui/text_buffer.h"
|
||||||
#include "ui/text_view.h"
|
#include "ui/text_view.h"
|
||||||
|
#include "ui/i_window_content.h"
|
||||||
|
|
||||||
class Terminal {
|
class Terminal : public IWindowContent {
|
||||||
public:
|
public:
|
||||||
Terminal(ClientNetwork* network);
|
Terminal(ClientNetwork* network);
|
||||||
~Terminal(void);
|
~Terminal(void);
|
||||||
|
|
||||||
void update(void);
|
void update(void) override;
|
||||||
void handle_input(SDL_Event* event);
|
void handle_input(SDL_Event* event) override;
|
||||||
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) override;
|
||||||
void scroll(int amount, int content_height);
|
void scroll(int amount, int content_height) override;
|
||||||
void add_history(const std::string& line);
|
void add_history(const std::string& line);
|
||||||
void set_prompt(const std::string& prompt);
|
void set_prompt(const std::string& prompt);
|
||||||
bool close(void);
|
bool should_close(void) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _on_ret_press(void);
|
void _on_ret_press(void);
|
||||||
|
|||||||
@ -1,16 +1,17 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <chrono>
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#include "ui/editor.h"
|
||||||
#include "desktop.h"
|
#include "desktop.h"
|
||||||
#include <SDL3/SDL_events.h>
|
#include <SDL3/SDL_events.h>
|
||||||
#include "client_network.h"
|
#include "client_network.h"
|
||||||
#include "gfx/shape_renderer.h"
|
#include "gfx/shape_renderer.h"
|
||||||
#include "gfx/txt_renderer.h"
|
#include "gfx/txt_renderer.h"
|
||||||
#include "terminal.h"
|
#include "terminal.h"
|
||||||
|
#include "ui/i_window_content.h"
|
||||||
#include "ui/taskbar.h"
|
#include "ui/taskbar.h"
|
||||||
#include <SDL3/SDL_video.h>
|
#include <SDL3/SDL_video.h>
|
||||||
#include <ui/cursor_manager.h>
|
#include <ui/cursor_manager.h>
|
||||||
@ -107,6 +108,12 @@ void Desktop::handle_event(SDL_Event* event, int screen_width, int screen_height
|
|||||||
term_window->set_content(std::move(term));
|
term_window->set_content(std::move(term));
|
||||||
add_window(std::move(term_window));
|
add_window(std::move(term_window));
|
||||||
_launcher_is_open = false;
|
_launcher_is_open = false;
|
||||||
|
} else if(app_to_launch == "Editor") {
|
||||||
|
auto editor = std::make_unique<Editor>();
|
||||||
|
auto editor_window = std::make_unique<UIWindow>("Editor", 200, 200, 600, 400);
|
||||||
|
editor_window->set_content(std::move(editor));
|
||||||
|
add_window(std::move(editor_window));
|
||||||
|
_launcher_is_open = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
UIWindow* clicked_window = _taskbar->handle_event(event, screen_height, _windows);
|
UIWindow* clicked_window = _taskbar->handle_event(event, screen_height, _windows);
|
||||||
@ -137,8 +144,12 @@ void Desktop::handle_event(SDL_Event* event, int screen_width, int screen_height
|
|||||||
if(_focused_window) {
|
if(_focused_window) {
|
||||||
_focused_window->handle_event(event, screen_width, screen_height,
|
_focused_window->handle_event(event, screen_width, screen_height,
|
||||||
_taskbar->get_height());
|
_taskbar->get_height());
|
||||||
Terminal* content = _focused_window->get_content();
|
IWindowContent* content = _focused_window->get_content();
|
||||||
if(content && (event->type == SDL_EVENT_TEXT_INPUT || event->type == SDL_EVENT_KEY_DOWN)) {
|
if(content) {
|
||||||
|
/*
|
||||||
|
* Only terminal should receive direct text input this way.
|
||||||
|
* Editor gets it through the generic handle_event call.
|
||||||
|
*/
|
||||||
content->handle_input(event);
|
content->handle_input(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
31
client/src/ui/editor.cpp
Normal file
31
client/src/ui/editor.cpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#include "editor.h"
|
||||||
|
#include <memory>
|
||||||
|
#include "gfx/txt_renderer.h"
|
||||||
|
|
||||||
|
Editor::Editor(void) : _should_close(false) {
|
||||||
|
_view = std::make_unique<TextView>(&_buffer, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Editor::~Editor(void) {}
|
||||||
|
|
||||||
|
void Editor::update(void) {
|
||||||
|
/* Nothing to do yet. */
|
||||||
|
}
|
||||||
|
|
||||||
|
void Editor::handle_input(SDL_Event* event) {
|
||||||
|
/* We don't care about the return val here. RET is just newline. */
|
||||||
|
_view->handle_event(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Editor::render(TextRenderer* renderer, int x, int y, int width, int height,
|
||||||
|
bool show_cursor) {
|
||||||
|
_view->render(renderer, x, y, width, height, show_cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Editor::scroll(int amount, int content_height) {
|
||||||
|
_view->scroll(amount, content_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Editor::should_close(void) {
|
||||||
|
return _should_close;
|
||||||
|
}
|
||||||
26
client/src/ui/editor.h
Normal file
26
client/src/ui/editor.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "gfx/txt_renderer.h"
|
||||||
|
#include "i_window_content.h"
|
||||||
|
#include "ui/text_buffer.h"
|
||||||
|
#include "text_view.h"
|
||||||
|
|
||||||
|
class Editor : public IWindowContent {
|
||||||
|
public:
|
||||||
|
Editor(void);
|
||||||
|
~Editor(void) override;
|
||||||
|
|
||||||
|
void update(void) override;
|
||||||
|
void handle_input(SDL_Event* event) override;
|
||||||
|
void render(TextRenderer* renderer, int x, int y, int width, int height,
|
||||||
|
bool show_cursor) override;
|
||||||
|
void scroll(int amount, int content_height) override;
|
||||||
|
bool should_close(void) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
TextBuffer _buffer;
|
||||||
|
std::unique_ptr<TextView> _view;
|
||||||
|
bool _should_close;
|
||||||
|
};
|
||||||
16
client/src/ui/i_window_content.h
Normal file
16
client/src/ui/i_window_content.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SDL3/SDL_events.h>
|
||||||
|
|
||||||
|
class TextRenderer;
|
||||||
|
|
||||||
|
class IWindowContent {
|
||||||
|
public:
|
||||||
|
virtual ~IWindowContent(void) = default;
|
||||||
|
virtual void update(void) = 0;
|
||||||
|
virtual void handle_input(SDL_Event* event) = 0;
|
||||||
|
virtual void render(TextRenderer* renderer, int x, int y, int width, int height,
|
||||||
|
bool show_cursor = 0) = 0;
|
||||||
|
virtual void scroll(int amount, int content_height) = 0;
|
||||||
|
virtual bool should_close(void) = 0;
|
||||||
|
};
|
||||||
@ -7,6 +7,7 @@
|
|||||||
Launcher::Launcher(int x, int y, int width) : _x(x), _y(y), _width(width) {
|
Launcher::Launcher(int x, int y, int width) : _x(x), _y(y), _width(width) {
|
||||||
/* TODO: Hardcode the launcher apps for now. */
|
/* TODO: Hardcode the launcher apps for now. */
|
||||||
_apps.push_back("Terminal");
|
_apps.push_back("Terminal");
|
||||||
|
_apps.push_back("Editor");
|
||||||
|
|
||||||
int item_height = 30;
|
int item_height = 30;
|
||||||
_height = _apps.size() * item_height;
|
_height = _apps.size() * item_height;
|
||||||
|
|||||||
@ -4,7 +4,8 @@
|
|||||||
#include "gfx/types.h"
|
#include "gfx/types.h"
|
||||||
#include "ui/text_buffer.h"
|
#include "ui/text_buffer.h"
|
||||||
|
|
||||||
TextView::TextView(TextBuffer* buffer) : _buffer(buffer), _scroll_offset(0) {}
|
TextView::TextView(TextBuffer* buffer, bool handle_ret) : _buffer(buffer),
|
||||||
|
_scroll_offset(0), _handle_ret(handle_ret) {}
|
||||||
|
|
||||||
TextView::~TextView(void) {}
|
TextView::~TextView(void) {}
|
||||||
|
|
||||||
@ -24,6 +25,9 @@ bool TextView::handle_event(SDL_Event* event) {
|
|||||||
* For terminal, we just want to submit. No newline.
|
* For terminal, we just want to submit. No newline.
|
||||||
* We'll return true and let the parent component do the do'ing.
|
* We'll return true and let the parent component do the do'ing.
|
||||||
*/
|
*/
|
||||||
|
if(_handle_ret) {
|
||||||
|
_buffer->newline();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
case SDLK_LEFT:
|
case SDLK_LEFT:
|
||||||
@ -66,7 +70,8 @@ void TextView::scroll(int amount, int content_height) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextView::render(TextRenderer* renderer, int x, int y, bool show_cursor) {
|
void TextView::render(TextRenderer* renderer, int x, int y, int width, int height,
|
||||||
|
bool show_cursor) {
|
||||||
if(!_buffer) return;
|
if(!_buffer) return;
|
||||||
|
|
||||||
const Color text_color = { 1.0f, 1.0f, 1.0f };
|
const Color text_color = { 1.0f, 1.0f, 1.0f };
|
||||||
@ -74,7 +79,7 @@ void TextView::render(TextRenderer* renderer, int x, int y, bool show_cursor) {
|
|||||||
float padding = 5.0f;
|
float padding = 5.0f;
|
||||||
|
|
||||||
Point cursor_pos = _buffer->get_cursor_pos();
|
Point cursor_pos = _buffer->get_cursor_pos();
|
||||||
float current_y = y;
|
float current_y = y + height - line_height; /* Start at top. */
|
||||||
|
|
||||||
for(size_t i = _scroll_offset; i < _buffer->get_line_count(); ++i) {
|
for(size_t i = _scroll_offset; i < _buffer->get_line_count(); ++i) {
|
||||||
std::string line = _buffer->get_line(i);
|
std::string line = _buffer->get_line(i);
|
||||||
|
|||||||
@ -8,14 +8,16 @@ class TextRenderer;
|
|||||||
|
|
||||||
class TextView {
|
class TextView {
|
||||||
public:
|
public:
|
||||||
TextView(TextBuffer* buffer);
|
TextView(TextBuffer* buffer, bool handle_ret);
|
||||||
~TextView(void);
|
~TextView(void);
|
||||||
|
|
||||||
bool handle_event(SDL_Event* event);
|
bool handle_event(SDL_Event* event);
|
||||||
void render(TextRenderer* renderer, int x, int y, 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);
|
void scroll(int amount, int content_height);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TextBuffer* _buffer;
|
TextBuffer* _buffer;
|
||||||
int _scroll_offset;
|
int _scroll_offset;
|
||||||
|
bool _handle_ret;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
#include "gfx/shape_renderer.h"
|
#include "gfx/shape_renderer.h"
|
||||||
#include "gfx/txt_renderer.h"
|
#include "gfx/txt_renderer.h"
|
||||||
#include "gfx/types.h"
|
#include "gfx/types.h"
|
||||||
|
#include "ui/i_window_content.h"
|
||||||
|
|
||||||
UIWindow::UIWindow(const char* title, int x, int y, int width, int height) :
|
UIWindow::UIWindow(const char* title, int x, int y, int width, int height) :
|
||||||
_title(title),
|
_title(title),
|
||||||
@ -53,15 +54,15 @@ bool UIWindow::should_close(void) const {
|
|||||||
return _should_close;
|
return _should_close;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UIWindow::set_content(std::unique_ptr<Terminal> term) {
|
void UIWindow::set_content(std::unique_ptr<IWindowContent> content) {
|
||||||
_content = std::move(term);
|
_content = std::move(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UIWindow::set_focused(bool focused) {
|
void UIWindow::set_focused(bool focused) {
|
||||||
_is_focused = focused;
|
_is_focused = focused;
|
||||||
}
|
}
|
||||||
|
|
||||||
Terminal* UIWindow::get_content(void) {
|
IWindowContent* UIWindow::get_content(void) {
|
||||||
return _content.get();
|
return _content.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,10 +2,11 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "gfx/shape_renderer.h"
|
#include "gfx/shape_renderer.h"
|
||||||
#include "gfx/txt_renderer.h"
|
#include "gfx/txt_renderer.h"
|
||||||
#include "terminal.h"
|
#include "i_window_content.h"
|
||||||
|
|
||||||
enum class WindowState {
|
enum class WindowState {
|
||||||
NORMAL,
|
NORMAL,
|
||||||
@ -39,8 +40,8 @@ public:
|
|||||||
bool should_close(void) const;
|
bool should_close(void) const;
|
||||||
void set_focused(bool focused);
|
void set_focused(bool focused);
|
||||||
bool is_point_inside(int x, int y);
|
bool is_point_inside(int x, int y);
|
||||||
void set_content(std::unique_ptr<Terminal> term);
|
void set_content(std::unique_ptr<IWindowContent> content);
|
||||||
Terminal* get_content(void);
|
IWindowContent* get_content(void);
|
||||||
bool is_mouse_over_resize_handle(int mouse_x, int mouse_y) const;
|
bool is_mouse_over_resize_handle(int mouse_x, int mouse_y) const;
|
||||||
const std::string& get_title(void) const;
|
const std::string& get_title(void) const;
|
||||||
|
|
||||||
@ -49,7 +50,7 @@ private:
|
|||||||
int _x, _y, _width, _height;
|
int _x, _y, _width, _height;
|
||||||
Rect _pre_maximize_rect;
|
Rect _pre_maximize_rect;
|
||||||
std::string _title;
|
std::string _title;
|
||||||
std::unique_ptr<Terminal> _content;
|
std::unique_ptr<IWindowContent> _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_hovered; /* Send scroll events even if not focused. */
|
||||||
bool _should_close;
|
bool _should_close;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user