refactor(console): phase 4 — extract ConsoleSelectionController from the god-class
Pull the text-selection concern out of ConsoleTab into a focused, ImGui-free
ConsoleSelectionController (console_selection_controller.{h,cpp}). It owns the
anchor/caret state and all the fiddly logic around it: the mouse-drag lifecycle
(beginDrag/updateDrag/endDrag), select-all, range ordering, text extraction over
the visible model, and the index shift applied when the buffer cap evicts lines
from the top.
ConsoleTab now delegates: the four scattered selection fields (is_selecting_,
has_selection_, sel_anchor_, sel_end_) and five helper methods (selectionStart/
End, isPosBeforeOrEqual, getSelectedText, clearSelection) collapse to a single
selection_ member plus a thin selectedText() wrapper. screenToTextPos (still
view-side — it needs the frame's layout) now returns the shared ConsoleTextPos,
so ConsoleTab::TextPos is retired.
The byte-offset / eviction math was previously only reachable through the live
ImGui renderer; it now has direct unit coverage (testConsoleSelectionController:
ordering, drag lifecycle, upward drag, select-all, partial/full/no-op eviction
shift, and filtered extraction). Full-node + lite build clean; ctest green;
source hygiene clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "console_channel.h"
|
||||
#include "console_model.h"
|
||||
#include "console_selection_controller.h"
|
||||
#include "console_text_layout.h"
|
||||
#include "../layout.h"
|
||||
#include "../../daemon/embedded_daemon.h"
|
||||
@@ -103,20 +104,13 @@ private:
|
||||
void renderInput(ConsoleCommandExecutor& exec);
|
||||
void renderCommandsPopup();
|
||||
|
||||
// Selection helpers
|
||||
std::string getSelectedText() const;
|
||||
void clearSelection();
|
||||
|
||||
// Convert screen position to line/column
|
||||
struct TextPos {
|
||||
int line = -1;
|
||||
int col = 0;
|
||||
};
|
||||
TextPos screenToTextPos(ImVec2 screen_pos) const;
|
||||
bool isPosBeforeOrEqual(const TextPos& a, const TextPos& b) const;
|
||||
TextPos selectionStart() const; // Returns the earlier of sel_anchor_ and sel_end_
|
||||
TextPos selectionEnd() const; // Returns the later of sel_anchor_ and sel_end_
|
||||
|
||||
// Map a screen point to a raw {line, col} position via this frame's wrapped layout.
|
||||
// (View-side because it needs layout_ + output_origin_; feeds the selection controller.)
|
||||
ConsoleTextPos screenToTextPos(ImVec2 screen_pos) const;
|
||||
|
||||
// The current selection's text (via selection_ over the visible model). "" if inactive.
|
||||
std::string selectedText() const;
|
||||
|
||||
// Thread-safe line store: producers on any thread call model_.ingest(); the main
|
||||
// thread drains it once per frame in render(). The visible deque is main-thread-only.
|
||||
ConsoleModel model_;
|
||||
@@ -128,11 +122,8 @@ private:
|
||||
int new_lines_since_scroll_ = 0; // new lines while scrolled up (for indicator)
|
||||
// (log-ingestion cursors + result queue moved to the ConsoleCommandExecutor)
|
||||
|
||||
// Text selection state
|
||||
bool is_selecting_ = false;
|
||||
bool has_selection_ = false;
|
||||
TextPos sel_anchor_; // Where the mouse was first pressed
|
||||
TextPos sel_end_; // Where the mouse currently is / was released
|
||||
// Text-selection state + logic (anchor/caret, ordering, extraction, eviction shift).
|
||||
ConsoleSelectionController selection_;
|
||||
float output_scroll_y_ = 0.0f; // Track scroll position for selection
|
||||
ImVec2 output_origin_ = {0, 0}; // Top-left of output area
|
||||
float output_line_height_ = 0.0f; // Text line height (for scanline alignment)
|
||||
|
||||
Reference in New Issue
Block a user