Add 'CenterOnCursor' command and improve cursor scrolling logic
- Introduced `CommandId::CenterOnCursor` to center viewport on the cursor line. - Improved scrolling behavior in `ImGuiRenderer` to avoid aggressive centering and keep visible lines stable. - Updated `make-app-release` to rename the output app to `kge-qt.app`. - Adjusted padding in `ImGuiFrontend` to align with `ImGuiRenderer` settings for consistent scrolling. - Bumped version to 1.4.1.
This commit is contained in:
@@ -4,7 +4,7 @@ project(kte)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(KTE_VERSION "1.4.0")
|
||||
set(KTE_VERSION "1.4.1")
|
||||
|
||||
# Default to terminal-only build to avoid SDL/OpenGL dependency by default.
|
||||
# Enable with -DBUILD_GUI=ON when SDL2/OpenGL/Freetype are available.
|
||||
|
||||
32
Command.cc
32
Command.cc
@@ -109,6 +109,33 @@ ensure_cursor_visible(const Editor &ed, Buffer &buf)
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
cmd_center_on_cursor(CommandContext &ctx)
|
||||
{
|
||||
Buffer *buf = ctx.editor.CurrentBuffer();
|
||||
if (!buf)
|
||||
return false;
|
||||
const auto &rows = buf->Rows();
|
||||
std::size_t total = rows.size();
|
||||
std::size_t content = ctx.editor.ContentRows();
|
||||
if (content == 0)
|
||||
content = 1;
|
||||
std::size_t cy = buf->Cury();
|
||||
std::size_t half = content / 2;
|
||||
std::size_t new_rowoffs = (cy > half) ? (cy - half) : 0;
|
||||
// Clamp to valid range
|
||||
if (total > content) {
|
||||
std::size_t max_rowoffs = total - content;
|
||||
if (new_rowoffs > max_rowoffs)
|
||||
new_rowoffs = max_rowoffs;
|
||||
} else {
|
||||
new_rowoffs = 0;
|
||||
}
|
||||
buf->SetOffsets(new_rowoffs, buf->Coloffs());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ensure_at_least_one_line(Buffer &buf)
|
||||
{
|
||||
@@ -4445,6 +4472,11 @@ InstallDefaultCommands()
|
||||
// Syntax highlighting (public commands)
|
||||
CommandRegistry::Register({CommandId::Syntax, "syntax", "Syntax: on|off|reload", cmd_syntax, true});
|
||||
CommandRegistry::Register({CommandId::SetOption, "set", "Set option: key=value", cmd_set_option, true});
|
||||
// Viewport control
|
||||
CommandRegistry::Register({
|
||||
CommandId::CenterOnCursor, "center-on-cursor", "Center viewport on current line", cmd_center_on_cursor,
|
||||
false, false
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -106,6 +106,8 @@ enum class CommandId {
|
||||
// Syntax highlighting
|
||||
Syntax, // ":syntax on|off|reload"
|
||||
SetOption, // generic ":set key=value" (v1: filetype=<lang>)
|
||||
// Viewport control
|
||||
CenterOnCursor, // center the viewport on the current cursor line (C-k k)
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -272,10 +272,11 @@ GUIFrontend::Step(Editor &ed, bool &running)
|
||||
float disp_w = io.DisplaySize.x > 0 ? io.DisplaySize.x : static_cast<float>(width_);
|
||||
float disp_h = io.DisplaySize.y > 0 ? io.DisplaySize.y : static_cast<float>(height_);
|
||||
|
||||
// Account for the GUI window padding and the status bar height used in GUIRenderer
|
||||
const ImGuiStyle &style = ImGui::GetStyle();
|
||||
float pad_x = style.WindowPadding.x;
|
||||
float pad_y = style.WindowPadding.y;
|
||||
// Account for the GUI window padding and the status bar height used in ImGuiRenderer.
|
||||
// ImGuiRenderer pushes WindowPadding = (6,6) every frame, so use the same constants here
|
||||
// to avoid mismatches that would cause premature scrolling.
|
||||
const float pad_x = 6.0f;
|
||||
const float pad_y = 6.0f;
|
||||
// Status bar reserves one frame height (with spacing) inside the window
|
||||
float status_h = ImGui::GetFrameHeightWithSpacing();
|
||||
|
||||
|
||||
@@ -140,7 +140,8 @@ ImGuiRenderer::Draw(Editor &ed)
|
||||
prev_buf_coloffs = buf_coloffs;
|
||||
|
||||
// Synchronize cursor and scrolling.
|
||||
// Ensure the cursor is visible even on the first frame or when it didn't move.
|
||||
// Ensure the cursor is visible, but avoid aggressive centering so that
|
||||
// the same lines remain visible until the cursor actually goes off-screen.
|
||||
{
|
||||
// Compute visible row range using the child window height
|
||||
float child_h = ImGui::GetWindowHeight();
|
||||
@@ -151,15 +152,30 @@ ImGuiRenderer::Draw(Editor &ed)
|
||||
long last_row = first_row + vis_rows - 1;
|
||||
|
||||
long cyr = static_cast<long>(cy);
|
||||
if (cyr < first_row || cyr > last_row) {
|
||||
float target = (static_cast<float>(cyr) - std::max(0L, vis_rows / 2)) * row_h;
|
||||
if (cyr < first_row) {
|
||||
// Scroll just enough to bring the cursor line to the top
|
||||
float target = static_cast<float>(cyr) * row_h;
|
||||
if (target < 0.f)
|
||||
target = 0.f;
|
||||
float max_y = ImGui::GetScrollMaxY();
|
||||
if (max_y >= 0.f && target > max_y)
|
||||
target = max_y;
|
||||
ImGui::SetScrollY(target);
|
||||
scroll_y = ImGui::GetScrollY();
|
||||
first_row = static_cast<long>(scroll_y / row_h);
|
||||
last_row = first_row + vis_rows - 1;
|
||||
} else if (cyr > last_row) {
|
||||
// Scroll just enough to bring the cursor line to the bottom
|
||||
long new_first = cyr - vis_rows + 1;
|
||||
if (new_first < 0)
|
||||
new_first = 0;
|
||||
float target = static_cast<float>(new_first) * row_h;
|
||||
float max_y = ImGui::GetScrollMaxY();
|
||||
if (target < 0.f)
|
||||
target = 0.f;
|
||||
if (max_y >= 0.f && target > max_y)
|
||||
target = max_y;
|
||||
ImGui::SetScrollY(target);
|
||||
// refresh local variables
|
||||
scroll_y = ImGui::GetScrollY();
|
||||
first_row = static_cast<long>(scroll_y / row_h);
|
||||
last_row = first_row + vis_rows - 1;
|
||||
|
||||
@@ -42,6 +42,9 @@ KLookupKCommand(const int ascii_key, const bool ctrl, CommandId &out) -> bool
|
||||
case 'a':
|
||||
out = CommandId::MarkAllAndJumpEnd;
|
||||
return true;
|
||||
case 'k':
|
||||
out = CommandId::CenterOnCursor; // C-k k center current line
|
||||
return true;
|
||||
case 'b':
|
||||
out = CommandId::BufferSwitchStart;
|
||||
return true;
|
||||
@@ -215,4 +218,4 @@ KLookupEscCommand(const int ascii_key, CommandId &out) -> bool
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -20,9 +20,10 @@ cmake -S . -B cmake-build-release -DBUILD_GUI=ON -DCMAKE_BUILD_TYPE=Release -DEN
|
||||
|
||||
cd cmake-build-release-qt
|
||||
make clean
|
||||
rm -fr kge.app*
|
||||
rm -fr kge.app* kge-qt.app*
|
||||
make
|
||||
zip -r kge.app.zip kge.app
|
||||
sha256sum kge.app.zip
|
||||
mv kge.app kge-qt.app
|
||||
zip -r kge-qt.app.zip kge-qt.app
|
||||
sha256sum kge-qt.app.zip
|
||||
open .
|
||||
cd ..
|
||||
|
||||
Reference in New Issue
Block a user