| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- #pragma once
- #include "lumacs/buffer.hpp"
- #include "lumacs/window.hpp"
- #include <memory>
- #include <functional>
- #include <vector>
- #include <list>
- namespace lumacs {
- /// Editor state change events
- enum class EditorEvent {
- BufferModified,
- CursorMoved,
- ViewportChanged,
- WindowLayoutChanged, // New event
- WindowFocused, // New event: a different window gained focus
- Message, // New event
- CommandMode, // Trigger command mode (minibuffer)
- Quit
- };
- struct LayoutNode;
- /// Core editor logic, independent of UI framework
- class EditorCore {
- public:
- EditorCore();
- ~EditorCore() = default;
- // Disable copy, allow move
- EditorCore(const EditorCore&) = delete;
- EditorCore& operator=(const EditorCore&) = delete;
- EditorCore(EditorCore&&) noexcept = default;
- EditorCore& operator=(EditorCore&&) noexcept = default;
- // === Message System ===
- void set_message(std::string msg) {
- last_message_ = std::move(msg);
- emit_event(EditorEvent::Message);
- }
-
- const std::string& last_message() const { return last_message_; }
- // === Actions ===
- void enter_command_mode() {
- emit_event(EditorEvent::CommandMode);
- }
- // === Buffer Management ===
-
- /// Get the current buffer (of the active window)
- [[nodiscard]] const Buffer& buffer() const noexcept;
- [[nodiscard]] Buffer& buffer() noexcept;
- /// Load a file into the current window
- bool load_file(const std::filesystem::path& path);
- /// Create a new empty buffer in current window
- void new_buffer(std::string name = "*scratch*");
- // === Window Management ===
- /// Split the current window horizontally (active window becomes top, new one bottom)
- void split_horizontally();
- /// Split the current window vertically (active window becomes left, new one right)
- void split_vertically();
- /// Close the current window
- void close_active_window();
- /// Move focus to the next window
- void next_window();
- /// Get the active window
- std::shared_ptr<Window> active_window() const { return active_window_; }
- /// Get the root of the layout tree (for rendering)
- std::shared_ptr<LayoutNode> root_layout() const { return root_node_; }
- // === Cursor Management (Proxies to active window) ===
- [[nodiscard]] Position cursor() const noexcept;
- void set_cursor(Position pos);
- // === Cursor Movement (Proxies to active window) ===
- void move_up();
- void move_down();
- void move_left();
- void move_right();
- void move_to_line_start();
- void move_to_line_end();
- // === Viewport Management (Proxies to active window) ===
-
- const Viewport& viewport() const noexcept;
- void set_viewport_size(int width, int height);
- void adjust_scroll();
- std::pair<size_t, size_t> visible_line_range() const;
- // === Event Callbacks ===
- using EventCallback = std::function<void(EditorEvent)>;
- void on_event(EventCallback callback) {
- event_callbacks_.push_back(std::move(callback));
- }
- // === Actions ===
- void request_quit() {
- emit_event(EditorEvent::Quit);
- }
- // === Undo/Redo ===
- bool undo();
- bool redo();
- bool can_undo() const;
- bool can_redo() const;
- private:
- // All open buffers
- std::list<std::shared_ptr<Buffer>> buffers_;
-
- // Window layout
- std::shared_ptr<LayoutNode> root_node_;
- std::shared_ptr<Window> active_window_;
-
- std::string last_message_;
- std::vector<EventCallback> event_callbacks_;
- void emit_event(EditorEvent event);
-
- // Helper to find a node containing the active window
- LayoutNode* find_parent_node(LayoutNode* root, std::shared_ptr<Window> target);
-
- // Helper to collect all windows in traversal order
- void collect_windows(LayoutNode* node, std::vector<std::shared_ptr<Window>>& windows);
- };
- struct LayoutNode {
- enum class Type { Leaf, HorizontalSplit, VerticalSplit };
- Type type;
-
- // If Leaf
- std::shared_ptr<Window> window;
-
- // If Split
- std::shared_ptr<LayoutNode> child1;
- std::shared_ptr<LayoutNode> child2;
- float ratio = 0.5f; // For future resizing
-
- LayoutNode(std::shared_ptr<Window> w) : type(Type::Leaf), window(w) {}
- LayoutNode(Type t, std::shared_ptr<LayoutNode> c1, std::shared_ptr<LayoutNode> c2)
- : type(t), child1(c1), child2(c2) {}
- };
- } // namespace lumacs
|