Skip to content

Commit 0d764bb

Browse files
authored
Feature show changelog (#82)
* show changelog on update * cosmetic changes * remove unsafe pointer member * tidy * add version to window title * add missing include vector
1 parent f2bd9d6 commit 0d764bb

File tree

11 files changed

+165
-46
lines changed

11 files changed

+165
-46
lines changed

xpano/constants.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ constexpr float kMaxMatchConf = 0.4f;
7272

7373
const std::string kAppConfigFilename = "app_config.alpaca";
7474
const std::string kUserConfigFilename = "user_config.alpaca";
75+
const std::string kChangelogFilename = "CHANGELOG.md";
7576

7677
constexpr int kCropEdgeTolerance = 10;
7778
constexpr int kAutoCropSamplingDistance = 512;

xpano/gui/layout.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
#include <imgui_internal.h>
55

66
#include "xpano/constants.h"
7+
#include "xpano/utils/imgui_.h"
78

89
namespace xpano::gui::layout {
910

1011
namespace {
1112
void InitDockSpaceFirstTime(ImGuiID dockspace_id, ImVec2 viewport_size) {
12-
const auto text_base_width = ImGui::CalcTextSize("A").x;
13-
const auto sidebar_width = kSidebarWidth * text_base_width;
13+
const auto sidebar_width = utils::imgui::DpiAwareSize(kSidebarWidth, 0).x;
1414

1515
ImGuiID dock_main_id = dockspace_id;
1616
ImGuiID dock_id_thumbnails = ImGui::DockBuilderSplitNode(

xpano/gui/panels/about.cc

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <algorithm>
44
#include <iterator>
5+
#include <optional>
56
#include <sstream>
67
#include <string>
78
#include <utility>
@@ -11,6 +12,7 @@
1112

1213
#include "xpano/constants.h"
1314
#include "xpano/utils/future.h"
15+
#include "xpano/utils/imgui_.h"
1416
#include "xpano/utils/text.h"
1517

1618
namespace xpano::gui {
@@ -59,30 +61,45 @@ AboutPane::AboutPane(std::future<utils::Texts> licenses)
5961

6062
void AboutPane::Show() { show_ = true; }
6163

64+
std::optional<utils::Text> AboutPane::GetText(const std::string& name) {
65+
if (licenses_future_.valid()) {
66+
WaitForLicenseLoading();
67+
}
68+
auto result = std::find_if(
69+
licenses_.begin(), licenses_.end(),
70+
[&name](const utils::Text& text) { return text.name == name; });
71+
if (result == licenses_.end()) {
72+
return {};
73+
}
74+
return *result;
75+
}
76+
77+
void AboutPane::WaitForLicenseLoading() {
78+
auto temp_licenses = licenses_future_.get();
79+
std::copy(temp_licenses.begin(), temp_licenses.end(),
80+
std::back_inserter(licenses_));
81+
}
82+
6283
void AboutPane::Draw() {
6384
if (!show_) {
6485
return;
6586
}
6687

88+
if (licenses_.size() == 1 &&
89+
xpano::utils::future::IsReady(licenses_future_)) {
90+
WaitForLicenseLoading();
91+
}
92+
6793
ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDocking |
6894
ImGuiWindowFlags_NoCollapse |
6995
ImGuiWindowFlags_NoSavedSettings;
7096

71-
const auto text_base_width = ImGui::CalcTextSize("A").x;
72-
ImGui::SetNextWindowSize(ImVec2(kAboutBoxWidth * text_base_width,
73-
kAboutBoxHeight * ImGui::GetTextLineHeight()),
74-
ImGuiCond_Once);
97+
ImGui::SetNextWindowSize(
98+
utils::imgui::DpiAwareSize(kAboutBoxWidth, kAboutBoxHeight),
99+
ImGuiCond_Once);
75100
ImGui::Begin("About", &show_, window_flags);
76101

77102
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
78-
79-
if (licenses_.size() == 1 &&
80-
xpano::utils::future::IsReady(licenses_future_)) {
81-
auto temp_licenses = licenses_future_.get();
82-
std::copy(temp_licenses.begin(), temp_licenses.end(),
83-
std::back_inserter(licenses_));
84-
}
85-
86103
if (ImGui::BeginCombo("##license_combo",
87104
licenses_[current_license_].name.c_str())) {
88105
for (int i = 0; i < licenses_.size(); ++i) {
@@ -93,20 +110,8 @@ void AboutPane::Draw() {
93110
ImGui::EndCombo();
94111
}
95112

96-
ImGui::BeginChild("License", ImVec2(0, 0));
97-
const auto& license = licenses_[current_license_];
98-
99-
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
100-
ImGuiListClipper clipper;
101-
int num_lines = static_cast<int>(license.lines.size());
102-
clipper.Begin(num_lines);
103-
while (clipper.Step()) {
104-
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
105-
ImGui::TextUnformatted(license.lines[i].c_str());
106-
}
107-
}
108-
ImGui::PopStyleVar();
109-
ImGui::EndChild();
113+
utils::imgui::DrawScrollableText("License",
114+
licenses_[current_license_].lines);
110115

111116
ImGui::End();
112117
}

xpano/gui/panels/about.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include <future>
4+
#include <optional>
45

56
#include "xpano/utils/text.h"
67

@@ -12,7 +13,11 @@ class AboutPane {
1213
void Draw();
1314
void Show();
1415

16+
std::optional<utils::Text> GetText(const std::string& name);
17+
1518
private:
19+
void WaitForLicenseLoading();
20+
1621
bool show_ = false;
1722
int current_license_ = 0;
1823
std::future<utils::Texts> licenses_future_;

xpano/gui/panels/warning_pane.cc

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
#include "xpano/gui/panels/warning_pane.h"
22

33
#include <imgui.h>
4+
#include <spdlog/fmt/fmt.h>
45
#include <spdlog/spdlog.h>
56

67
#include "xpano/constants.h"
7-
#include "xpano/gui/action.h"
8+
#include "xpano/utils/imgui_.h"
9+
#include "xpano/version_fmt.h"
810

911
namespace xpano::gui {
1012

@@ -15,18 +17,17 @@ const char* WarningMessage(WarningType warning) {
1517
return "Only 8-bit stitching pipeline is implemented!\nHigher bit depth "
1618
"images are converted to 8-bit.";
1719
case WarningType::kFirstTimeLaunch:
18-
return "Your friendly panorama stitching app:\n"
19-
" - default settings are designed to work out of the box with "
20-
"most images\n"
21-
" - hover over the little question marks for detailed "
22-
"instructions";
20+
return "Your friendly panorama stitching app";
2321
case WarningType::kUserPrefBreakingChange:
24-
return "The user settings format has changed, reverting to defaults.";
22+
return "The user settings format has "
23+
"changed, reverting to defaults.";
2524
case WarningType::kUserPrefCouldntLoad:
2625
return "Couldn't load user settings, reverting to defaults.";
2726
case WarningType::kUserPrefResetOnRequest:
2827
return "User settings were reset to default values,\nyou can keep "
2928
"experimenting!";
29+
case WarningType::kNewVersion:
30+
return "Xpano was updated!";
3031
default:
3132
return "";
3233
}
@@ -36,6 +37,8 @@ const char* Title(WarningType warning) {
3637
switch (warning) {
3738
case WarningType::kFirstTimeLaunch:
3839
return "Welcome to Xpano!";
40+
case WarningType::kNewVersion:
41+
return "Version update";
3942
case WarningType::kUserPrefResetOnRequest:
4043
return "Info";
4144
default:
@@ -51,10 +54,14 @@ bool EnableSnooze(WarningType warning) {
5154
return false;
5255
}
5356
}
57+
5458
} // namespace
5559

5660
void WarningPane::Draw() {
57-
if (current_warning_ == WarningType::kNone && !pending_warnings_.empty()) {
61+
if (current_warning_ == WarningType::kNone) {
62+
if (pending_warnings_.empty()) {
63+
return;
64+
}
5865
Show(pending_warnings_.front());
5966
pending_warnings_.pop();
6067
}
@@ -65,12 +72,12 @@ void WarningPane::Draw() {
6572
if (ImGui::BeginPopupModal(Title(current_warning_), nullptr,
6673
ImGuiWindowFlags_AlwaysAutoResize)) {
6774
ImGui::TextUnformatted(WarningMessage(current_warning_));
75+
DrawExtra(current_warning_);
6876
ImGui::Spacing();
6977
ImGui::Separator();
7078
ImGui::Spacing();
7179

72-
const auto text_base_width = ImGui::CalcTextSize("A").x;
73-
if (ImGui::Button("OK", ImVec2(text_base_width * kWideButtonWidth, 0))) {
80+
if (ImGui::Button("OK", utils::imgui::DpiAwareSize(kWideButtonWidth, 0))) {
7481
ImGui::CloseCurrentPopup();
7582
current_warning_ = WarningType::kNone;
7683
}
@@ -89,10 +96,48 @@ void WarningPane::Draw() {
8996
}
9097
}
9198

99+
void WarningPane::DrawExtra(WarningType warning) {
100+
switch (warning) {
101+
case WarningType::kFirstTimeLaunch: {
102+
ImGui::Text(
103+
" - default settings are designed to work out of the box with most "
104+
"images");
105+
ImGui::Text(
106+
" - hover over the little question marks for detailed instructions:");
107+
ImGui::SameLine();
108+
utils::imgui::InfoMarker(
109+
"(?)", "You can try importing a whole directory at once");
110+
break;
111+
}
112+
case WarningType::kNewVersion: {
113+
ImGui::TextUnformatted(new_version_message_.c_str());
114+
if (changelog_) {
115+
ImGui::Spacing();
116+
ImGui::Separator();
117+
ImGui::Spacing();
118+
utils::imgui::DrawScrollableText(
119+
"Changelog", changelog_->lines,
120+
utils::imgui::DpiAwareSize(kAboutBoxWidth, kAboutBoxHeight / 2));
121+
}
122+
break;
123+
}
124+
default:
125+
break;
126+
}
127+
}
128+
92129
void WarningPane::Queue(WarningType warning) {
93130
pending_warnings_.push(warning);
94131
}
95132

133+
void WarningPane::QueueNewVersion(version::Triplet previous_version,
134+
std::optional<utils::Text> changelog) {
135+
pending_warnings_.push(WarningType::kNewVersion);
136+
new_version_message_ = fmt::format(" - from version {} to version {}",
137+
previous_version, version::Current());
138+
changelog_ = std::move(changelog);
139+
}
140+
96141
void WarningPane::Show(WarningType warning) {
97142
if (!dont_show_again_.contains(warning)) {
98143
ImGui::OpenPopup(Title(warning));

xpano/gui/panels/warning_pane.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
#pragma once
22

3+
#include <optional>
34
#include <queue>
5+
#include <string>
46
#include <unordered_set>
57

6-
#include "xpano/gui/action.h"
8+
#include "xpano/utils/text.h"
9+
#include "xpano/version.h"
710

811
namespace xpano::gui {
912

@@ -13,13 +16,17 @@ enum class WarningType {
1316
kFirstTimeLaunch,
1417
kUserPrefBreakingChange,
1518
kUserPrefCouldntLoad,
16-
kUserPrefResetOnRequest
19+
kUserPrefResetOnRequest,
20+
kNewVersion
1721
};
1822

1923
class WarningPane {
2024
public:
2125
void Draw();
26+
void DrawExtra(WarningType warning);
2227
void Queue(WarningType warning);
28+
void QueueNewVersion(version::Triplet previous_version,
29+
std::optional<utils::Text> changelog);
2330

2431
private:
2532
void Show(WarningType warning);
@@ -28,6 +35,9 @@ class WarningPane {
2835

2936
std::queue<WarningType> pending_warnings_;
3037
std::unordered_set<WarningType> dont_show_again_;
38+
39+
std::string new_version_message_;
40+
std::optional<utils::Text> changelog_;
3141
};
3242

3343
} // namespace xpano::gui

xpano/gui/pano_gui.cc

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "xpano/utils/config.h"
2828
#include "xpano/utils/future.h"
2929
#include "xpano/utils/imgui_.h"
30+
#include "xpano/version.h"
3031

3132
template <>
3233
struct fmt::formatter<xpano::gui::StatusMessage> : formatter<std::string> {
@@ -252,12 +253,16 @@ WarningType GetWarningType(utils::config::LoadingStatus loading_status) {
252253
PanoGui::PanoGui(backends::Base* backend, logger::Logger* logger,
253254
const utils::config::Config& config,
254255
std::future<utils::Texts> licenses)
255-
: plot_pane_(backend),
256-
thumbnail_pane_(backend),
256+
: options_(config.user_options),
257257
log_pane_(logger),
258+
about_pane_(std::move(licenses)),
258259
bugreport_pane_(logger),
259-
options_(config.user_options),
260-
about_pane_(std::move(licenses)) {
260+
plot_pane_(backend),
261+
thumbnail_pane_(backend) {
262+
if (config.app_state.xpano_version != version::Current()) {
263+
warning_pane_.QueueNewVersion(config.app_state.xpano_version,
264+
about_pane_.GetText(kChangelogFilename));
265+
}
261266
if (config.user_options_status != utils::config::LoadingStatus::kSuccess) {
262267
warning_pane_.Queue(GetWarningType(config.user_options_status));
263268
}

xpano/main.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "xpano/utils/resource.h"
3939
#include "xpano/utils/sdl_.h"
4040
#include "xpano/utils/text.h"
41+
#include "xpano/version_fmt.h"
4142

4243
#if !SDL_VERSION_ATLEAST(2, 0, 17)
4344
#error This backend requires SDL 2.0.17+ because of SDL_RenderGeometry() function
@@ -96,9 +97,10 @@ int main(int /*unused*/, char** /*unused*/) {
9697

9798
// Setup SDL Window + Renderer
9899
auto window_flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI;
100+
auto window_title = fmt::format("Xpano {}", xpano::version::Current());
99101
SDL_Window* window =
100-
SDL_CreateWindow("Xpano", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
101-
config.app_state.window_width,
102+
SDL_CreateWindow(window_title.c_str(), SDL_WINDOWPOS_CENTERED,
103+
SDL_WINDOWPOS_CENTERED, config.app_state.window_width,
102104
config.app_state.window_height, window_flags);
103105

104106
SDL_Renderer* renderer = SDL_CreateRenderer(

xpano/utils/imgui_.cc

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <filesystem>
55
#include <optional>
66
#include <utility>
7+
#include <vector>
78

89
#include <imgui.h>
910
#include <imgui_impl_sdlrenderer.h>
@@ -82,4 +83,25 @@ std::string InitIniFilePath(
8283
: ini_file_name;
8384
}
8485

86+
void DrawScrollableText(const char* label,
87+
const std::vector<std::string>& lines, ImVec2 size) {
88+
ImGui::BeginChild(label, size);
89+
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
90+
ImGuiListClipper clipper;
91+
int num_lines = static_cast<int>(lines.size());
92+
clipper.Begin(num_lines);
93+
while (clipper.Step()) {
94+
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
95+
ImGui::TextUnformatted(lines[i].c_str());
96+
}
97+
}
98+
ImGui::PopStyleVar();
99+
ImGui::EndChild();
100+
}
101+
102+
ImVec2 DpiAwareSize(int width, int height) {
103+
return {static_cast<float>(width) * ImGui::CalcTextSize("A").x,
104+
static_cast<float>(height) * ImGui::GetTextLineHeight()};
105+
}
106+
85107
} // namespace xpano::utils::imgui

0 commit comments

Comments
 (0)