Step 176: smooth UI transitions
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#include "../EditorState.h"
|
||||
#include "../EditorUtils.h"
|
||||
#include "../CompletionUtils.h"
|
||||
#include "../AnimationUtils.h"
|
||||
|
||||
static void renderEditorPanel(EditorState& state) {
|
||||
// ---------------------------------------------------------------
|
||||
@@ -69,6 +70,12 @@ static void renderEditorPanel(EditorState& state) {
|
||||
if (!state.active() || state.active()->path != path) {
|
||||
state.switchToBuffer(path);
|
||||
}
|
||||
const double nowSeconds = ImGui::GetTime();
|
||||
float tabAlpha = state.uiAnimations.tabFadeAlpha(path,
|
||||
nowSeconds,
|
||||
state.settings.getReduceMotion());
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_Alpha,
|
||||
ImGui::GetStyle().Alpha * tabAlpha);
|
||||
// Editable text area fills available space
|
||||
ImVec2 avail = ImGui::GetContentRegionAvail();
|
||||
avail.y -= 4; // small margin
|
||||
@@ -177,6 +184,9 @@ static void renderEditorPanel(EditorState& state) {
|
||||
opts.showLineNumbers = state.ui.showLineNumbers;
|
||||
opts.lineHeightScale = state.settings.getLineHeightScale();
|
||||
opts.letterSpacing = state.settings.getLetterSpacing();
|
||||
opts.cursorBlinkRate = state.settings.getCursorBlinkRate();
|
||||
opts.reduceMotion = state.settings.getReduceMotion();
|
||||
opts.nowSeconds = nowSeconds;
|
||||
if (state.ui.layoutPreset == LayoutPreset::Emacs) opts.annotationLayout = 1;
|
||||
else if (state.ui.layoutPreset == LayoutPreset::JetBrains) opts.annotationLayout = 2;
|
||||
else opts.annotationLayout = 0;
|
||||
@@ -186,6 +196,8 @@ static void renderEditorPanel(EditorState& state) {
|
||||
opts.annotations = &annoMarkers;
|
||||
opts.suggestions = &suggestionMarkers;
|
||||
opts.conflicts = &conflictMarkers;
|
||||
opts.searchPulseLine = state.search.pulseLine;
|
||||
opts.searchPulseStart = state.search.pulseStart;
|
||||
|
||||
if (buf->bufferMode == BufferManager::BufferMode::Structured) {
|
||||
opts.syncScrollX = &buf->splitScrollX;
|
||||
@@ -232,6 +244,9 @@ static void renderEditorPanel(EditorState& state) {
|
||||
genOpts.showCurrentLine = false;
|
||||
genOpts.lineHeightScale = state.settings.getLineHeightScale();
|
||||
genOpts.letterSpacing = state.settings.getLetterSpacing();
|
||||
genOpts.cursorBlinkRate = state.settings.getCursorBlinkRate();
|
||||
genOpts.reduceMotion = state.settings.getReduceMotion();
|
||||
genOpts.nowSeconds = nowSeconds;
|
||||
genOpts.highlightLine = buf->generatedHighlightLine;
|
||||
genOpts.syncScrollX = &buf->splitScrollX;
|
||||
genOpts.syncScrollY = &buf->splitScrollY;
|
||||
@@ -494,10 +509,20 @@ static void renderEditorPanel(EditorState& state) {
|
||||
state.hoverPending = false;
|
||||
}
|
||||
std::string hover = state.lsp->getHoverContents();
|
||||
if (!hover.empty()) {
|
||||
static std::string lastHoverText;
|
||||
bool hoverActive = !hover.empty();
|
||||
if (hoverActive) lastHoverText = hover;
|
||||
float alpha = AnimationUtils::tooltipAlpha("lsp_hover",
|
||||
hoverActive,
|
||||
nowSeconds,
|
||||
state.settings.getReduceMotion());
|
||||
if (alpha > 0.01f && !lastHoverText.empty()) {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_Alpha,
|
||||
ImGui::GetStyle().Alpha * alpha);
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::TextUnformatted(hover.c_str());
|
||||
ImGui::TextUnformatted(lastHoverText.c_str());
|
||||
ImGui::EndTooltip();
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -529,16 +554,34 @@ static void renderEditorPanel(EditorState& state) {
|
||||
if (res.hoverValid && (ImGui::GetIO().KeyCtrl || ImGui::GetIO().KeySuper)) {
|
||||
std::string preview;
|
||||
if (state.previewDefinitionAt(res.hoverLine, res.hoverCol, preview)) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::TextUnformatted(preview.c_str());
|
||||
ImGui::EndTooltip();
|
||||
float alpha = AnimationUtils::tooltipAlpha("definition_preview",
|
||||
true,
|
||||
nowSeconds,
|
||||
state.settings.getReduceMotion());
|
||||
if (alpha > 0.01f) {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_Alpha,
|
||||
ImGui::GetStyle().Alpha * alpha);
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::TextUnformatted(preview.c_str());
|
||||
ImGui::EndTooltip();
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
} else if (state.definitionPreviewValid) {
|
||||
std::string path = EditorState::fromFileUri(state.definitionPreview.uri);
|
||||
std::string label = path + ":" +
|
||||
std::to_string(state.definitionPreview.range.start.line + 1);
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::TextUnformatted(label.c_str());
|
||||
ImGui::EndTooltip();
|
||||
float alpha = AnimationUtils::tooltipAlpha("definition_preview_fallback",
|
||||
true,
|
||||
nowSeconds,
|
||||
state.settings.getReduceMotion());
|
||||
if (alpha > 0.01f) {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_Alpha,
|
||||
ImGui::GetStyle().Alpha * alpha);
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::TextUnformatted(label.c_str());
|
||||
ImGui::EndTooltip();
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -709,6 +752,7 @@ static void renderEditorPanel(EditorState& state) {
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (!open) {
|
||||
|
||||
@@ -1,11 +1,27 @@
|
||||
#pragma once
|
||||
#include "../EditorState.h"
|
||||
#include "../EditorUtils.h"
|
||||
#include "../AnimationUtils.h"
|
||||
|
||||
static void renderFindReplaceBar(EditorState& state) {
|
||||
if (!state.search.showFind) return;
|
||||
ImGui::Begin("Find & Replace", &state.search.showFind, ImGuiWindowFlags_AlwaysAutoResize);
|
||||
const double now = ImGui::GetTime();
|
||||
float alpha = 1.0f;
|
||||
float offset = 0.0f;
|
||||
bool render = AnimationUtils::panelTransition("FindReplacePanel",
|
||||
state.search.showFind,
|
||||
now,
|
||||
state.settings.getReduceMotion(),
|
||||
0.14f,
|
||||
12.0f,
|
||||
alpha,
|
||||
offset);
|
||||
if (!render) return;
|
||||
bool open = state.search.showFind;
|
||||
ImGui::SetNextWindowBgAlpha(alpha);
|
||||
ImGui::Begin("Find & Replace", &open, ImGuiWindowFlags_AlwaysAutoResize);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * alpha);
|
||||
ImGui::PushFont(state.uiFont);
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offset);
|
||||
ImGui::SetNextItemWidth(300);
|
||||
if (ImGui::InputText("Find", state.search.findBuf, sizeof(state.search.findBuf),
|
||||
ImGuiInputTextFlags_EnterReturnsTrue)) {
|
||||
@@ -19,13 +35,32 @@ static void renderFindReplaceBar(EditorState& state) {
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Replace All")) state.doReplaceAll();
|
||||
ImGui::PopFont();
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::End();
|
||||
if (!open) {
|
||||
state.search.showFind = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void renderProjectSearchPanel(EditorState& state) {
|
||||
if (!state.search.showProjectSearch) return;
|
||||
ImGui::Begin("Search", &state.search.showProjectSearch);
|
||||
const double now = ImGui::GetTime();
|
||||
float alpha = 1.0f;
|
||||
float offset = 0.0f;
|
||||
bool render = AnimationUtils::panelTransition("ProjectSearchPanel",
|
||||
state.search.showProjectSearch,
|
||||
now,
|
||||
state.settings.getReduceMotion(),
|
||||
0.16f,
|
||||
16.0f,
|
||||
alpha,
|
||||
offset);
|
||||
if (!render) return;
|
||||
bool open = state.search.showProjectSearch;
|
||||
ImGui::SetNextWindowBgAlpha(alpha);
|
||||
ImGui::Begin("Search", &open);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * alpha);
|
||||
ImGui::PushFont(state.uiFont);
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offset);
|
||||
bool doSearch = false;
|
||||
ImGui::SetNextItemWidth(420);
|
||||
if (ImGui::InputText("Query", state.search.searchQuery, sizeof(state.search.searchQuery),
|
||||
@@ -76,5 +111,9 @@ static void renderProjectSearchPanel(EditorState& state) {
|
||||
}
|
||||
ImGui::EndChild();
|
||||
ImGui::PopFont();
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::End();
|
||||
if (!open) {
|
||||
state.search.showProjectSearch = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "../EditorState.h"
|
||||
#include "../EditorUtils.h"
|
||||
#include "../ThemeEngine.h"
|
||||
#include "../AnimationUtils.h"
|
||||
#include <cstdlib>
|
||||
#include <filesystem>
|
||||
#include <vector>
|
||||
@@ -67,9 +68,26 @@ static int findFontIndex(const std::vector<FontOption>& options, const std::stri
|
||||
}
|
||||
|
||||
static void renderSettingsPanel(EditorState& state) {
|
||||
if (!state.ui.showSettingsPanel) return;
|
||||
ImGui::Begin("Settings", &state.ui.showSettingsPanel);
|
||||
const double now = ImGui::GetTime();
|
||||
const bool reduceMotion = state.settings.getReduceMotion();
|
||||
float alpha = 1.0f;
|
||||
float offset = 0.0f;
|
||||
const bool render = AnimationUtils::panelTransition("SettingsPanel",
|
||||
state.ui.showSettingsPanel,
|
||||
now,
|
||||
reduceMotion,
|
||||
0.18f,
|
||||
18.0f,
|
||||
alpha,
|
||||
offset);
|
||||
if (!render) return;
|
||||
bool open = state.ui.showSettingsPanel;
|
||||
ImGui::SetNextWindowBgAlpha(alpha);
|
||||
ImGui::Begin("Settings", &open);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * alpha);
|
||||
ImGui::PushFont(state.uiFont);
|
||||
float startX = ImGui::GetCursorPosX();
|
||||
ImGui::SetCursorPosX(startX + offset);
|
||||
bool settingsChanged = false;
|
||||
bool emacsConfigChanged = false;
|
||||
bool themeChanged = false;
|
||||
@@ -132,6 +150,11 @@ static void renderSettingsPanel(EditorState& state) {
|
||||
state.settings.setLetterSpacing(letterSpacing);
|
||||
settingsChanged = true;
|
||||
}
|
||||
float blinkRate = state.settings.getCursorBlinkRate();
|
||||
if (ImGui::SliderFloat("Cursor Blink Rate (Hz)", &blinkRate, 0.0f, 4.0f, "%.1f")) {
|
||||
state.settings.setCursorBlinkRate(blinkRate);
|
||||
settingsChanged = true;
|
||||
}
|
||||
|
||||
int tabSize = state.settings.getTabSize();
|
||||
const int tabSizes[] = {2, 4, 8};
|
||||
@@ -321,6 +344,11 @@ static void renderSettingsPanel(EditorState& state) {
|
||||
state.ui.showLineNumbers = showLineNumbers;
|
||||
settingsChanged = true;
|
||||
}
|
||||
bool reduceMotionSetting = state.settings.getReduceMotion();
|
||||
if (ImGui::Checkbox("Reduce Motion", &reduceMotionSetting)) {
|
||||
state.settings.setReduceMotion(reduceMotionSetting);
|
||||
settingsChanged = true;
|
||||
}
|
||||
|
||||
LayoutPreset preset = state.ui.layoutPreset;
|
||||
int presetIndex = 0;
|
||||
@@ -386,5 +414,9 @@ static void renderSettingsPanel(EditorState& state) {
|
||||
state.events.publish(UIEventType::ThemeChanged, {}, {}, ImGui::GetTime());
|
||||
}
|
||||
ImGui::PopFont();
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::End();
|
||||
if (!open) {
|
||||
state.ui.showSettingsPanel = false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user