[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/i_window_content.h"
#include "ui/ui_window.h"
#include "ui/window_action.h"
#include <ui/main_menu.h>
#include <ui/boot_sequence.h>
@ -153,6 +154,18 @@ void GameState::update(void) {
}
}
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!!
* Pass GameState by reference ?

View File

@ -8,6 +8,7 @@
#include "client_network.h"
#include "gfx/txt_renderer.h"
#include "gfx/types.h"
#include "ui/window_action.h"
Terminal::Terminal(ClientNetwork* network)
: _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; }
WindowAction Terminal::get_pending_action(void) {
return { ActionType::NONE };
}
void Terminal::_on_ret_press(void) {
std::string command = _input_buffer.get_line(0);
_input_buffer.newline(); /* Add newline to buffer for histroy. */

View File

@ -22,6 +22,7 @@ public:
void add_history(const std::string& line);
void set_prompt(const std::string& prompt);
bool should_close(void) override;
WindowAction get_pending_action(void) override;
private:
void _on_ret_press(void);

View File

@ -16,6 +16,7 @@
#include <SDL3/SDL_video.h>
#include <ui/cursor_manager.h>
#include "ui/ui_window.h"
#include "ui/window_action.h"
static const std::string& get_random_snippet(const std::vector<std::string>& snippets) {
if(snippets.empty()) {
@ -171,6 +172,16 @@ void Desktop::update(int screen_width, int screen_height) {
_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) {
return _focused_window;
}

View File

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

View File

@ -1,8 +1,10 @@
#include "editor.h"
#include <memory>
#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);
}
@ -14,7 +16,13 @@ void Editor::update(void) {
void Editor::handle_input(SDL_Event* event) {
/* 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);
}
}
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) {
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 "ui/text_buffer.h"
#include "text_view.h"
#include "ui/window_action.h"
class Editor : public IWindowContent {
public:
@ -18,9 +19,11 @@ public:
bool show_cursor) override;
void scroll(int amount, int content_height) override;
bool should_close(void) override;
WindowAction get_pending_action(void) override;
private:
TextBuffer _buffer;
std::unique_ptr<TextView> _view;
bool _should_close;
WindowAction _pending_action;
};

View File

@ -2,6 +2,8 @@
#include <SDL3/SDL_events.h>
#include "window_action.h"
class TextRenderer;
class IWindowContent {
@ -13,4 +15,5 @@ public:
bool show_cursor = 0) = 0;
virtual void scroll(int amount, int content_height) = 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 "vfs.h"
#include "lua_api.h"
#include "lua_processor.h"
#include "machine_manager.h"
#include "machine.h"
@ -74,6 +75,10 @@ std::string CommandProcessor::process_command(const std::string& command) {
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. */
vfs_node* find_node_by_path(vfs_node* root, const std::string& path) {
if(path == "/") {

View File

@ -13,6 +13,7 @@ public:
~CommandProcessor(void);
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. */
vfs_node* get_current_dir(void);

View File

@ -107,13 +107,28 @@ void NetworkManager::on_message(std::shared_ptr<net::TcpConnection> connection,
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);
if(response == "__CLOSE_CONNECTION__") {
connection->send(response);
/* Just let me close the f.cking terminal? */
return;
}