diff --git a/client/src/game_state.cpp b/client/src/game_state.cpp index 9092219..4959f29 100644 --- a/client/src/game_state.cpp +++ b/client/src/game_state.cpp @@ -10,6 +10,7 @@ #include "gfx/txt_renderer.h" #include "terminal.h" #include "ui/desktop.h" +#include "ui/i_window_content.h" #include "ui/ui_window.h" #include #include @@ -126,11 +127,9 @@ void GameState::update(void) { case Screen::DESKTOP: { std::string server_msg; while(_network->poll_message(server_msg)) { - UIWindow* focused_window = _desktop->get_focused_window(); - if(!focused_window) - continue; - - Terminal* terminal = focused_window->get_content(); + IWindowContent* content = _desktop->get_focused_window() ? + _desktop->get_focused_window()->get_content() : nullptr; + Terminal* terminal = dynamic_cast(content); if(!terminal) continue; diff --git a/client/src/terminal.cpp b/client/src/terminal.cpp index b9f2a84..f65afa3 100644 --- a/client/src/terminal.cpp +++ b/client/src/terminal.cpp @@ -12,7 +12,7 @@ Terminal::Terminal(ClientNetwork* network) : _network(network), _should_close(false), _scroll_offset(0), _prompt("") { - _input_view = std::make_unique(&_input_buffer); + _input_view = std::make_unique(&_input_buffer, false); } Terminal::~Terminal(void) {} @@ -42,7 +42,7 @@ void Terminal::set_prompt(const std::string& prompt) { _prompt = prompt; } -bool Terminal::close(void) { return _should_close; } +bool Terminal::should_close(void) { return _should_close; } void Terminal::_on_ret_press(void) { 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. */ 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. */ glDisable(GL_SCISSOR_TEST); } diff --git a/client/src/terminal.h b/client/src/terminal.h index bf289ce..e3bbcbd 100644 --- a/client/src/terminal.h +++ b/client/src/terminal.h @@ -8,19 +8,20 @@ #include "client_network.h" #include "ui/text_buffer.h" #include "ui/text_view.h" +#include "ui/i_window_content.h" -class Terminal { +class Terminal : public IWindowContent { public: Terminal(ClientNetwork* network); ~Terminal(void); - void update(void); - 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); + 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; void add_history(const std::string& line); void set_prompt(const std::string& prompt); - bool close(void); + bool should_close(void) override; private: void _on_ret_press(void); diff --git a/client/src/ui/desktop.cpp b/client/src/ui/desktop.cpp index 2ae6f7d..1801be2 100644 --- a/client/src/ui/desktop.cpp +++ b/client/src/ui/desktop.cpp @@ -1,16 +1,17 @@ #include -#include #include #include #include #include +#include "ui/editor.h" #include "desktop.h" #include #include "client_network.h" #include "gfx/shape_renderer.h" #include "gfx/txt_renderer.h" #include "terminal.h" +#include "ui/i_window_content.h" #include "ui/taskbar.h" #include #include @@ -107,6 +108,12 @@ void Desktop::handle_event(SDL_Event* event, int screen_width, int screen_height term_window->set_content(std::move(term)); add_window(std::move(term_window)); _launcher_is_open = false; + } else if(app_to_launch == "Editor") { + auto editor = std::make_unique(); + auto editor_window = std::make_unique("Editor", 200, 200, 600, 400); + editor_window->set_content(std::move(editor)); + add_window(std::move(editor_window)); + _launcher_is_open = false; } } else { 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) { _focused_window->handle_event(event, screen_width, screen_height, _taskbar->get_height()); - Terminal* content = _focused_window->get_content(); - if(content && (event->type == SDL_EVENT_TEXT_INPUT || event->type == SDL_EVENT_KEY_DOWN)) { + IWindowContent* content = _focused_window->get_content(); + if(content) { + /* + * Only terminal should receive direct text input this way. + * Editor gets it through the generic handle_event call. + */ content->handle_input(event); } } diff --git a/client/src/ui/editor.cpp b/client/src/ui/editor.cpp new file mode 100644 index 0000000..e66caa9 --- /dev/null +++ b/client/src/ui/editor.cpp @@ -0,0 +1,31 @@ +#include "editor.h" +#include +#include "gfx/txt_renderer.h" + +Editor::Editor(void) : _should_close(false) { + _view = std::make_unique(&_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; +} diff --git a/client/src/ui/editor.h b/client/src/ui/editor.h new file mode 100644 index 0000000..3d16a10 --- /dev/null +++ b/client/src/ui/editor.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +#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 _view; + bool _should_close; +}; diff --git a/client/src/ui/i_window_content.h b/client/src/ui/i_window_content.h new file mode 100644 index 0000000..fb7b35a --- /dev/null +++ b/client/src/ui/i_window_content.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +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; +}; diff --git a/client/src/ui/launcher.cpp b/client/src/ui/launcher.cpp index 4c2cc66..907dd4f 100644 --- a/client/src/ui/launcher.cpp +++ b/client/src/ui/launcher.cpp @@ -7,6 +7,7 @@ Launcher::Launcher(int x, int y, int width) : _x(x), _y(y), _width(width) { /* TODO: Hardcode the launcher apps for now. */ _apps.push_back("Terminal"); + _apps.push_back("Editor"); int item_height = 30; _height = _apps.size() * item_height; diff --git a/client/src/ui/text_view.cpp b/client/src/ui/text_view.cpp index a7aa2ba..f786347 100644 --- a/client/src/ui/text_view.cpp +++ b/client/src/ui/text_view.cpp @@ -4,7 +4,8 @@ #include "gfx/types.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) {} @@ -24,6 +25,9 @@ bool TextView::handle_event(SDL_Event* event) { * For terminal, we just want to submit. No newline. * We'll return true and let the parent component do the do'ing. */ + if(_handle_ret) { + _buffer->newline(); + } return true; break; 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; 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; 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) { std::string line = _buffer->get_line(i); diff --git a/client/src/ui/text_view.h b/client/src/ui/text_view.h index ad94613..b2f2856 100644 --- a/client/src/ui/text_view.h +++ b/client/src/ui/text_view.h @@ -8,14 +8,16 @@ class TextRenderer; class TextView { public: - TextView(TextBuffer* buffer); + TextView(TextBuffer* buffer, bool handle_ret); ~TextView(void); 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); private: TextBuffer* _buffer; int _scroll_offset; + bool _handle_ret; }; diff --git a/client/src/ui/ui_window.cpp b/client/src/ui/ui_window.cpp index b6bf0e6..d1ce9b3 100644 --- a/client/src/ui/ui_window.cpp +++ b/client/src/ui/ui_window.cpp @@ -4,6 +4,7 @@ #include "gfx/shape_renderer.h" #include "gfx/txt_renderer.h" #include "gfx/types.h" +#include "ui/i_window_content.h" UIWindow::UIWindow(const char* title, int x, int y, int width, int height) : _title(title), @@ -53,15 +54,15 @@ bool UIWindow::should_close(void) const { return _should_close; } -void UIWindow::set_content(std::unique_ptr term) { - _content = std::move(term); +void UIWindow::set_content(std::unique_ptr content) { + _content = std::move(content); } void UIWindow::set_focused(bool focused) { _is_focused = focused; } -Terminal* UIWindow::get_content(void) { +IWindowContent* UIWindow::get_content(void) { return _content.get(); } diff --git a/client/src/ui/ui_window.h b/client/src/ui/ui_window.h index 666080f..f70b362 100644 --- a/client/src/ui/ui_window.h +++ b/client/src/ui/ui_window.h @@ -2,10 +2,11 @@ #include #include +#include #include "gfx/shape_renderer.h" #include "gfx/txt_renderer.h" -#include "terminal.h" +#include "i_window_content.h" enum class WindowState { NORMAL, @@ -39,8 +40,8 @@ public: bool should_close(void) const; void set_focused(bool focused); bool is_point_inside(int x, int y); - void set_content(std::unique_ptr term); - Terminal* get_content(void); + void set_content(std::unique_ptr content); + IWindowContent* get_content(void); bool is_mouse_over_resize_handle(int mouse_x, int mouse_y) const; const std::string& get_title(void) const; @@ -49,7 +50,7 @@ private: int _x, _y, _width, _height; Rect _pre_maximize_rect; std::string _title; - std::unique_ptr _content; + std::unique_ptr _content; bool _is_focused; /* Managed by desktop. */ bool _is_hovered; /* Send scroll events even if not focused. */ bool _should_close;