openMSX
ImGuiAdjust.cc
Go to the documentation of this file.
1#include "ImGuiAdjust.hh"
2
3#include <imgui.h>
4
5#include <optional>
6
7namespace openmsx {
8
9// Adjust one dimension. So call it once for X, once for Y.
10[[nodiscard]] static std::optional<float> adjustWindowPositionForResizedViewPort(
11 float oldViewPortSize, float newViewPortSize, float relWindowPos, float windowSize)
12{
13 // Window can no longer fit in new viewPort.
14 if (newViewPortSize < windowSize) return {};
15
16 // Closer to left or right border (or top/bottom)?
17 float windowEndPos = relWindowPos + windowSize;
18 float distanceToLeft = relWindowPos;
19 float distanceToRight = oldViewPortSize - windowEndPos;
20
21 if (distanceToLeft < distanceToRight) {
22 // Maintain the distance to the closest border.
23 float newDistanceToLeft = distanceToLeft;
24 float newWindowPos = newDistanceToLeft;
25 float newWindowEndPos = newWindowPos + windowSize;
26 float newDistanceToRight = newViewPortSize - newWindowEndPos;
27
28 // Check if the other border becomes the closer one.
29 if (newDistanceToLeft > newDistanceToRight) {
30 // If so, place in the middle instead.
31 newWindowPos = (newViewPortSize - windowSize) * 0.5f;
32 }
33 return newWindowPos;
34 } else {
35 float newDistanceToRight = distanceToRight;
36 float newWidowEndPos = newViewPortSize - newDistanceToRight;
37 float newWindowPos = newWidowEndPos - windowSize;
38 float newDistanceToLeft = newWindowPos;
39 if (newDistanceToRight > newDistanceToLeft) {
40 newWindowPos = (newViewPortSize - windowSize) * 0.5f;
41 }
42 return newWindowPos;
43 }
44}
45
47{
48 if (setMainViewPort) {
49 setMainViewPort = false;
50 const auto* mainViewPort = ImGui::GetMainViewport();
51 ImGui::SetNextWindowViewport(mainViewPort->ID);
52 }
53}
54
56{
57 const auto* mainViewPort = ImGui::GetMainViewport();
58 const auto* windowViewPort = ImGui::GetWindowViewport();
59 bool isOnMainViewPort = windowViewPort == mainViewPort;
60 gl::vec2 newViewPortSize = mainViewPort->Size;
61 gl::vec2 mainViewPortPos = mainViewPort->Pos;
62 gl::vec2 relWindowPos = gl::vec2(ImGui::GetWindowPos()) - mainViewPortPos;
63
64 if (oldIsOnMainViewPort && (oldViewPortSize != newViewPortSize)) {
65 gl::vec2 windowSize = ImGui::GetWindowSize();
66 if (!isOnMainViewPort) {
67 // previous frame we were in the main view port,
68 // but now, after main view port has resized,
69 // we're not. Try to pull us back into the main
70 // view port.
71 setMainViewPort = true;
72 isOnMainViewPort = true;
73 relWindowPos = oldRelWindowPos;
74 }
75 auto newPosX = adjustWindowPositionForResizedViewPort(
76 oldViewPortSize.x, newViewPortSize.x, relWindowPos.x, windowSize.x);
77 auto newPosY = adjustWindowPositionForResizedViewPort(
78 oldViewPortSize.y, newViewPortSize.y, relWindowPos.y, windowSize.y);
79 if (newPosX && newPosY) {
80 relWindowPos = gl::vec2{*newPosX, *newPosY};
81 ImGui::SetWindowPos(mainViewPortPos + relWindowPos);
82 }
83 }
84
85 // data for next frame
86 oldViewPortSize = newViewPortSize;
87 oldRelWindowPos = relWindowPos;
88 oldIsOnMainViewPort = isOnMainViewPort;
89
90 return isOnMainViewPort;
91}
92
93void AdjustWindowInMainViewPort::save(ImGuiTextBuffer& buf)
94{
95 savePersistent(buf, *this, persistentElements);
96}
97
98bool AdjustWindowInMainViewPort::loadLine(std::string_view name, zstring_view value)
99{
100 return loadOnePersistent(name, value, *this, persistentElements);
101}
102
103} // namespace openmsx
bool loadLine(std::string_view name, zstring_view value)
void save(ImGuiTextBuffer &buf)
Like std::string_view, but with the extra guarantee that it refers to a zero-terminated string.
vecN< 2, float > vec2
Definition gl_vec.hh:382
This file implemented 3 utility functions:
Definition Autofire.cc:11
bool loadOnePersistent(std::string_view name, zstring_view value, C &c, const std::tuple< Elements... > &tup)
void savePersistent(ImGuiTextBuffer &buf, C &c, const std::tuple< Elements... > &tup)