OXYGENHUB
◆ main openmsx / src / imgui / ImGuiAdjust.cc
3.3 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#include "ImGuiAdjust.hh"
2
3
#include <imgui.h>
4
5
#include <optional>
6
7
namespace 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
46
void AdjustWindowInMainViewPort::pre()
47
{
48
	if (setMainViewPort) {
49
		setMainViewPort = false;
50
		const auto* mainViewPort = ImGui::GetMainViewport();
51
		ImGui::SetNextWindowViewport(mainViewPort->ID);
52
	}
53
}
54
55
bool AdjustWindowInMainViewPort::post()
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
93
void AdjustWindowInMainViewPort::save(ImGuiTextBuffer& buf)
94
{
95
	savePersistent(buf, *this, persistentElements);
96
}
97
98
bool AdjustWindowInMainViewPort::loadLine(std::string_view name, zstring_view value)
99
{
100
	return loadOnePersistent(name, value, *this, persistentElements);
101
}
102
103
} // namespace openmsx