Line data Source code
1 : #include "gui/views/gui_snapshots.h"
2 :
3 : #include <imgui.h>
4 :
5 : #include <algorithm>
6 : #include <cstdio>
7 :
8 : #include "gui/theme/theme.h"
9 :
10 : namespace Amplitron {
11 :
12 12 : void GuiSnapshots::render() {
13 12 : const SnapshotsProps& p = props_;
14 :
15 16 : float bar_height = ImGui::GetFrameHeight() + ImGui::GetStyle().WindowPadding.y * 2.0f +
16 12 : ImGui::GetStyle().WindowBorderSize * 2.0f;
17 :
18 12 : ImGui::BeginChild("SnapshotBar", ImVec2(0, bar_height), true,
19 : ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
20 :
21 : // Vertically center the button row
22 4 : {
23 12 : float avail_y = ImGui::GetContentRegionAvail().y;
24 12 : float row_h = ImGui::GetFrameHeight();
25 12 : float pad_y = std::max(0.0f, (avail_y - row_h) * 0.5f);
26 12 : ImGui::SetCursorPosY(ImGui::GetCursorPosY() + pad_y);
27 : }
28 :
29 12 : ImGui::TextColored(Theme::TextSecondary(), "SNAPSHOTS");
30 :
31 60 : for (int i = 0; i < SnapshotManager::NUM_SLOTS; ++i) {
32 48 : ImGui::SameLine();
33 :
34 48 : const auto& slot = p.slots[i];
35 48 : const bool is_active = slot.is_active;
36 48 : const bool is_filled = slot.is_filled;
37 48 : const char* lbl = slot.label;
38 :
39 48 : if (is_active) {
40 12 : ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.50f, 0.42f, 0.20f, 1.0f));
41 12 : ImGui::PushStyleColor(ImGuiCol_ButtonHovered, Theme::GoldHot());
42 12 : ImGui::PushStyleColor(ImGuiCol_ButtonActive, Theme::Gold());
43 40 : } else if (is_filled) {
44 12 : ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.22f, 0.20f, 0.16f, 1.0f));
45 12 : ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.35f, 0.30f, 0.18f, 1.0f));
46 12 : ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.45f, 0.38f, 0.18f, 1.0f));
47 4 : } else {
48 24 : ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.14f, 0.13f, 0.12f, 1.0f));
49 24 : ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.20f, 0.19f, 0.16f, 1.0f));
50 24 : ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.25f, 0.23f, 0.19f, 1.0f));
51 : }
52 :
53 16 : char btn_id[16];
54 48 : std::snprintf(btn_id, sizeof(btn_id), "%s##snap_%d", lbl, i);
55 :
56 48 : if (ImGui::Button(btn_id)) {
57 0 : if (is_filled) {
58 0 : if (p.on_recall_slot) p.on_recall_slot(i);
59 0 : std::snprintf(status_msg_, sizeof(status_msg_), "Recalled %s", lbl);
60 0 : status_timer_ = STATUS_DISPLAY_SECONDS;
61 0 : }
62 0 : }
63 :
64 48 : ImGui::PopStyleColor(3);
65 :
66 : // Tooltip
67 48 : if (ImGui::IsItemHovered()) {
68 0 : if (is_filled)
69 0 : ImGui::SetTooltip(
70 : "Left-click to recall snapshot %s (or Ctrl+%d)\nRight-click to overwrite or "
71 : "clear",
72 0 : lbl, i + 1);
73 : else
74 0 : ImGui::SetTooltip("Slot %s is empty\nRight-click to save current board here", lbl);
75 0 : }
76 :
77 : // Right-click context menu
78 16 : char popup_id[24];
79 48 : std::snprintf(popup_id, sizeof(popup_id), "SnapCtx_%d", i);
80 48 : if (ImGui::BeginPopupContextItem(popup_id)) {
81 0 : char save_label[40];
82 0 : std::snprintf(save_label, sizeof(save_label), "Save current board to %s", lbl);
83 0 : if (ImGui::MenuItem(save_label)) {
84 0 : if (p.on_save_slot) p.on_save_slot(i);
85 0 : std::snprintf(status_msg_, sizeof(status_msg_), "Saved to %s", lbl);
86 0 : status_timer_ = STATUS_DISPLAY_SECONDS;
87 0 : }
88 0 : if (is_filled) {
89 0 : char clear_label[24];
90 0 : std::snprintf(clear_label, sizeof(clear_label), "Clear %s", lbl);
91 0 : ImGui::Separator();
92 0 : if (ImGui::MenuItem(clear_label)) {
93 0 : if (p.on_clear_slot) p.on_clear_slot(i);
94 0 : }
95 0 : }
96 0 : ImGui::EndPopup();
97 0 : }
98 16 : }
99 :
100 12 : ImGui::SameLine();
101 :
102 12 : if (status_timer_ > 0.0f) {
103 9 : float alpha = std::min(status_timer_, 1.0f);
104 9 : ImGui::TextColored(ImVec4(0.90f, 0.78f, 0.39f, alpha), " %s", status_msg_);
105 9 : status_timer_ -= ImGui::GetIO().DeltaTime;
106 3 : } else {
107 3 : ImGui::TextColored(
108 4 : Theme::TextDim(),
109 : " Left-click to recall | Right-click to save / clear | Ctrl+1-4 to recall");
110 : }
111 :
112 12 : ImGui::EndChild();
113 12 : }
114 :
115 : } // namespace Amplitron
|