[Add] File saving for the fancy new text editor.

This commit is contained in:
Ritchie Cunningham 2025-09-30 21:37:24 +01:00
parent b4d985db29
commit ebd1e222d7
12 changed files with 91 additions and 4 deletions

View File

@ -12,6 +12,7 @@
#include "ui/desktop.h" #include "ui/desktop.h"
#include "ui/i_window_content.h" #include "ui/i_window_content.h"
#include "ui/ui_window.h" #include "ui/ui_window.h"
#include "ui/window_action.h"
#include <ui/main_menu.h> #include <ui/main_menu.h>
#include <ui/boot_sequence.h> #include <ui/boot_sequence.h>
@ -153,6 +154,18 @@ void GameState::update(void) {
} }
} }
if(_desktop) { if(_desktop) {
WindowAction action = _desktop->get_pending_action();
switch(action.type) {
case ActionType::WRITE_FILE: {
std::string message = "WRITEF::" + action.payload1 + "::" + action.payload2;
_network->send(message);
break;
}
case ActionType::NONE:
default:
/* Do nothing. */
break;
}
/* /*
* TODO: These fuck'in window dimensions just need to be global at this point!! * TODO: These fuck'in window dimensions just need to be global at this point!!
* Pass GameState by reference ? * Pass GameState by reference ?

View File

@ -8,6 +8,7 @@
#include "client_network.h" #include "client_network.h"
#include "gfx/txt_renderer.h" #include "gfx/txt_renderer.h"
#include "gfx/types.h" #include "gfx/types.h"
#include "ui/window_action.h"
Terminal::Terminal(ClientNetwork* network) Terminal::Terminal(ClientNetwork* network)
: _network(network), _should_close(false), _scroll_offset(0), : _network(network), _should_close(false), _scroll_offset(0),
@ -44,6 +45,10 @@ void Terminal::set_prompt(const std::string& prompt) {
bool Terminal::should_close(void) { return _should_close; } bool Terminal::should_close(void) { return _should_close; }
WindowAction Terminal::get_pending_action(void) {
return { ActionType::NONE };
}
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);
_input_buffer.newline(); /* Add newline to buffer for histroy. */ _input_buffer.newline(); /* Add newline to buffer for histroy. */

View File

@ -22,6 +22,7 @@ public:
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 should_close(void) override; bool should_close(void) override;
WindowAction get_pending_action(void) override;
private: private:
void _on_ret_press(void); void _on_ret_press(void);

View File

@ -16,6 +16,7 @@
#include <SDL3/SDL_video.h> #include <SDL3/SDL_video.h>
#include <ui/cursor_manager.h> #include <ui/cursor_manager.h>
#include "ui/ui_window.h" #include "ui/ui_window.h"
#include "ui/window_action.h"
static const std::string& get_random_snippet(const std::vector<std::string>& snippets) { static const std::string& get_random_snippet(const std::vector<std::string>& snippets) {
if(snippets.empty()) { if(snippets.empty()) {
@ -171,6 +172,16 @@ void Desktop::update(int screen_width, int screen_height) {
_windows.end()); _windows.end());
} }
WindowAction Desktop::get_pending_action(void) {
if(_focused_window) {
IWindowContent* content = _focused_window->get_content();
if(content) {
return content->get_pending_action();
}
}
return { ActionType::NONE };
}
UIWindow* Desktop::get_focused_window(void) { UIWindow* Desktop::get_focused_window(void) {
return _focused_window; return _focused_window;
} }

View File

@ -10,6 +10,7 @@
#include "ui/ui_window.h" #include "ui/ui_window.h"
#include "ui/taskbar.h" #include "ui/taskbar.h"
#include "ui/launcher.h" #include "ui/launcher.h"
#include "ui/window_action.h"
/* Animated background stuff. */ /* Animated background stuff. */
struct ScrollingText { struct ScrollingText {
@ -31,6 +32,7 @@ public:
void render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer, int screen_height, void render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer, int screen_height,
bool show_cursor); bool show_cursor);
WindowAction get_pending_action(void);
UIWindow* get_focused_window(void); UIWindow* get_focused_window(void);
private: private:

View File

@ -1,8 +1,10 @@
#include "editor.h" #include "editor.h"
#include <memory> #include <memory>
#include "gfx/txt_renderer.h" #include "gfx/txt_renderer.h"
#include "ui/window_action.h"
Editor::Editor(void) : _should_close(false) { Editor::Editor(void)
: _should_close(false), _pending_action({ActionType::NONE}) {
_view = std::make_unique<TextView>(&_buffer, true); _view = std::make_unique<TextView>(&_buffer, true);
} }
@ -14,7 +16,13 @@ void Editor::update(void) {
void Editor::handle_input(SDL_Event* event) { void Editor::handle_input(SDL_Event* event) {
/* We don't care about the return val here. RET is just newline. */ /* We don't care about the return val here. RET is just newline. */
if(event->type == SDL_EVENT_KEY_DOWN && event->key.key == SDLK_S &&
(event->key.mod & SDL_KMOD_CTRL)) {
/* C-S pressed, create a save action. */
_pending_action = { ActionType::WRITE_FILE, "test.txt", _buffer.get_text() };
} else {
_view->handle_event(event); _view->handle_event(event);
}
} }
void Editor::render(TextRenderer* renderer, int x, int y, int width, int height, void Editor::render(TextRenderer* renderer, int x, int y, int width, int height,
@ -29,3 +37,9 @@ void Editor::scroll(int amount, int content_height) {
bool Editor::should_close(void) { bool Editor::should_close(void) {
return _should_close; return _should_close;
} }
WindowAction Editor::get_pending_action(void) {
WindowAction action = _pending_action;
_pending_action.type = ActionType::NONE; /* Clear action. */
return action;
}

View File

@ -6,6 +6,7 @@
#include "i_window_content.h" #include "i_window_content.h"
#include "ui/text_buffer.h" #include "ui/text_buffer.h"
#include "text_view.h" #include "text_view.h"
#include "ui/window_action.h"
class Editor : public IWindowContent { class Editor : public IWindowContent {
public: public:
@ -18,9 +19,11 @@ public:
bool show_cursor) override; bool show_cursor) override;
void scroll(int amount, int content_height) override; void scroll(int amount, int content_height) override;
bool should_close(void) override; bool should_close(void) override;
WindowAction get_pending_action(void) override;
private: private:
TextBuffer _buffer; TextBuffer _buffer;
std::unique_ptr<TextView> _view; std::unique_ptr<TextView> _view;
bool _should_close; bool _should_close;
WindowAction _pending_action;
}; };

View File

@ -2,6 +2,8 @@
#include <SDL3/SDL_events.h> #include <SDL3/SDL_events.h>
#include "window_action.h"
class TextRenderer; class TextRenderer;
class IWindowContent { class IWindowContent {
@ -13,4 +15,5 @@ public:
bool show_cursor = 0) = 0; bool show_cursor = 0) = 0;
virtual void scroll(int amount, int content_height) = 0; virtual void scroll(int amount, int content_height) = 0;
virtual bool should_close(void) = 0; virtual bool should_close(void) = 0;
virtual WindowAction get_pending_action() = 0;
}; };

View File

@ -0,0 +1,14 @@
#pragma once
#include <string>
enum class ActionType {
NONE,
WRITE_FILE
};
struct WindowAction {
ActionType type = ActionType::NONE;
std::string payload1; /* i.e., filename. */
std::string payload2; /* i.e., content. */
};

View File

@ -3,6 +3,7 @@
#include "command_processor.h" #include "command_processor.h"
#include "vfs.h" #include "vfs.h"
#include "lua_api.h"
#include "lua_processor.h" #include "lua_processor.h"
#include "machine_manager.h" #include "machine_manager.h"
#include "machine.h" #include "machine.h"
@ -74,6 +75,10 @@ std::string CommandProcessor::process_command(const std::string& command) {
return "Unknown command: " + command_name + "\n"; return "Unknown command: " + command_name + "\n";
} }
std::string CommandProcessor::write_file(const std::string& path, const std::string& content) {
return api::write_file(*this, path, content);
}
/* Find a VFS node by it's absolute path. */ /* Find a VFS node by it's absolute path. */
vfs_node* find_node_by_path(vfs_node* root, const std::string& path) { vfs_node* find_node_by_path(vfs_node* root, const std::string& path) {
if(path == "/") { if(path == "/") {

View File

@ -13,6 +13,7 @@ public:
~CommandProcessor(void); ~CommandProcessor(void);
std::string process_command(const std::string& command); std::string process_command(const std::string& command);
std::string write_file(const std::string& path, const std::string& content);
/* Public interface for API functions. */ /* Public interface for API functions. */
vfs_node* get_current_dir(void); vfs_node* get_current_dir(void);

View File

@ -107,13 +107,28 @@ void NetworkManager::on_message(std::shared_ptr<net::TcpConnection> connection,
return; return;
} }
fprintf(stderr, "[Player %u] Command: '%s'\n", player->id, message.c_str()); /* Check for "special" message prefixes. */
if(message.rfind("WRITEF::", 0) == 0) {
/* Message format: WRITEF::/path/to/file::content. */
std::string payload = message.substr(8);
size_t separator_pos = payload.find("::");
if(separator_pos != std::string::npos) {
std::string filepath = payload.substr(0, separator_pos);
std::string content = payload.substr(separator_pos+2);
fprintf(stderr, "[Player %u] Write file: \'%s\'\n", player->id, filepath.c_str());
player->cmd_processor->write_file(filepath, content);
/* Response not required for a file write. */
}
return;
}
/* If no prefix, treat as normal terminal command. */
fprintf(stderr, "[Player %u] Command: '%s'\n", player->id, message.c_str());
std::string response = player->cmd_processor->process_command(message); std::string response = player->cmd_processor->process_command(message);
if(response == "__CLOSE_CONNECTION__") { if(response == "__CLOSE_CONNECTION__") {
connection->send(response); connection->send(response);
/* Just let me close the f.cking terminal? */
return; return;
} }