Skip to content

Commit 48bc284

Browse files
authored
Merge pull request #1601 from falbrechtskirchinger/improve-window-positioning
Improve in-game window positioning
2 parents 5907058 + fccbc9e commit 48bc284

7 files changed

Lines changed: 237 additions & 34 deletions

File tree

libs/common/include/Point.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ struct Point //-V690
2222
using ElementType = T;
2323
static_assert(std::is_arithmetic<ElementType>::value, "Requires an arithmetic type");
2424

25+
static constexpr auto MinElementValue = std::numeric_limits<T>::min();
26+
static constexpr auto MaxElementValue = std::numeric_limits<T>::max();
27+
2528
struct Truncate_t
2629
{
2730
constexpr explicit Truncate_t() = default;

libs/s25main/Settings.cpp

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -347,10 +347,13 @@ void Settings::LoadIngame()
347347
const auto* iniWindow = static_cast<const libsiedler2::ArchivItem_Ini*>(settingsIngame.find(window.second));
348348
if(!iniWindow)
349349
continue;
350-
windows.persistentSettings[window.first].lastPos.x = iniWindow->getIntValue("pos_x");
351-
windows.persistentSettings[window.first].lastPos.y = iniWindow->getIntValue("pos_y");
352-
windows.persistentSettings[window.first].isOpen = iniWindow->getIntValue("is_open");
353-
windows.persistentSettings[window.first].isMinimized = iniWindow->getValue("is_minimized", false);
350+
auto& settings = windows.persistentSettings[window.first];
351+
const auto lastPos = settings.lastPos =
352+
DrawPoint(iniWindow->getIntValue("pos_x"), iniWindow->getIntValue("pos_y"));
353+
settings.restorePos = DrawPoint(iniWindow->getValue("restore_pos_x", lastPos.x),
354+
iniWindow->getValue("restore_pos_y", lastPos.y));
355+
settings.isOpen = iniWindow->getIntValue("is_open");
356+
settings.isMinimized = iniWindow->getValue("is_minimized", false);
354357
}
355358
} catch(std::runtime_error& e)
356359
{
@@ -500,10 +503,17 @@ void Settings::SaveIngame()
500503
auto* iniWindow = static_cast<libsiedler2::ArchivItem_Ini*>(settingsIngame.find(window.second));
501504
if(!iniWindow)
502505
continue;
503-
iniWindow->setValue("pos_x", windows.persistentSettings[window.first].lastPos.x);
504-
iniWindow->setValue("pos_y", windows.persistentSettings[window.first].lastPos.y);
505-
iniWindow->setValue("is_open", windows.persistentSettings[window.first].isOpen);
506-
iniWindow->setValue("is_minimized", windows.persistentSettings[window.first].isMinimized);
506+
const auto& settings = windows.persistentSettings[window.first];
507+
iniWindow->setValue("pos_x", settings.lastPos.x);
508+
iniWindow->setValue("pos_y", settings.lastPos.y);
509+
if(settings.restorePos != settings.lastPos)
510+
{
511+
// only save if different; defaults to lastPos on load
512+
iniWindow->setValue("restore_pos_x", settings.restorePos.x);
513+
iniWindow->setValue("restore_pos_y", settings.restorePos.y);
514+
}
515+
iniWindow->setValue("is_open", settings.isOpen);
516+
iniWindow->setValue("is_minimized", settings.isMinimized);
507517
}
508518

509519
bfs::path settingsPathIngame = RTTRCONFIG.ExpandPath(s25::resources::ingameOptions);

libs/s25main/Settings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ bool checkPort(int port);
2525
struct PersistentWindowSettings
2626
{
2727
DrawPoint lastPos = DrawPoint::Invalid();
28+
DrawPoint restorePos = DrawPoint::Invalid();
2829
bool isOpen = false;
2930
bool isMinimized = false;
3031
};

libs/s25main/ingameWindows/IngameWindow.cpp

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,9 @@ namespace {
2424
constexpr Extent ButtonSize(16, 16);
2525
}
2626

27-
const DrawPoint IngameWindow::posLastOrCenter(std::numeric_limits<DrawPoint::ElementType>::max(),
28-
std::numeric_limits<DrawPoint::ElementType>::max());
29-
const DrawPoint IngameWindow::posCenter(std::numeric_limits<DrawPoint::ElementType>::max() - 1,
30-
std::numeric_limits<DrawPoint::ElementType>::max());
31-
const DrawPoint IngameWindow::posAtMouse(std::numeric_limits<DrawPoint::ElementType>::max() - 1,
32-
std::numeric_limits<DrawPoint::ElementType>::max() - 1);
27+
const DrawPoint IngameWindow::posLastOrCenter(DrawPoint::MaxElementValue, DrawPoint::MaxElementValue);
28+
const DrawPoint IngameWindow::posCenter(DrawPoint::MaxElementValue - 1, DrawPoint::MaxElementValue);
29+
const DrawPoint IngameWindow::posAtMouse(DrawPoint::MaxElementValue - 1, DrawPoint::MaxElementValue - 1);
3330

3431
const Extent IngameWindow::borderSize(1, 1);
3532
IngameWindow::IngameWindow(unsigned id, const DrawPoint& pos, const Extent& size, std::string title,
@@ -54,25 +51,32 @@ IngameWindow::IngameWindow(unsigned id, const DrawPoint& pos, const Extent& size
5451
// Save to settings that window is open
5552
SaveOpenStatus(true);
5653

57-
// Restore minimized state
58-
if(windowSettings_ && windowSettings_->isMinimized)
54+
if(windowSettings_)
5955
{
60-
isMinimized_ = true;
61-
Extent minimizedSize(GetSize().x, contentOffset.y + contentOffsetEnd.y);
62-
Window::Resize(minimizedSize);
56+
// Restore minimized state
57+
if(windowSettings_ && windowSettings_->isMinimized)
58+
{
59+
isMinimized_ = true;
60+
Extent minimizedSize(GetSize().x, contentOffset.y + contentOffsetEnd.y);
61+
Window::Resize(minimizedSize);
62+
}
63+
// Load restorePos
64+
restorePos_ = windowSettings_->restorePos;
6365
}
6466

6567
// Load last position or center the window
6668
if(pos == posLastOrCenter)
6769
{
6870
if(windowSettings_ && windowSettings_->lastPos.isValid())
69-
SetPos(windowSettings_->lastPos);
71+
SetPos(windowSettings_->lastPos, !restorePos_.isValid());
7072
else
7173
MoveToCenter();
7274
} else if(pos == posCenter)
7375
MoveToCenter();
7476
else if(pos == posAtMouse)
7577
MoveNextToMouse();
78+
else
79+
SetPos(pos); // always call SetPos() to update restorePos
7680
}
7781

7882
void IngameWindow::Resize(const Extent& newSize)
@@ -84,15 +88,23 @@ void IngameWindow::Resize(const Extent& newSize)
8488

8589
void IngameWindow::SetIwSize(const Extent& newSize)
8690
{
91+
// Is the window connecting with the bottom screen edge?
92+
const auto atBottom = (GetPos().y + GetSize().y) >= VIDEODRIVER.GetRenderSize().y;
93+
8794
iwHeight = newSize.y;
8895
Extent wndSize = newSize;
8996
if(isMinimized_)
9097
wndSize.y = 0;
9198
wndSize += contentOffset + contentOffsetEnd;
9299
Window::Resize(wndSize);
93100

94-
// Reset the position to check if parts of the window are out of the visible area
95-
SetPos(GetPos());
101+
// Adjust restorePos if the window was connecting with the bottom screen edge before being minimized
102+
const auto pos = (atBottom && isMinimized_) ? DrawPoint(restorePos_.x, DrawPoint::MaxElementValue) : restorePos_;
103+
104+
// Reset the position
105+
// 1) to check if parts of the window are out of the visible area
106+
// 2) to re-connect the window with the bottom screen edge, if needed
107+
SetPos(pos, false);
96108
}
97109

98110
Extent IngameWindow::GetIwSize() const
@@ -105,24 +117,38 @@ DrawPoint IngameWindow::GetRightBottomBoundary()
105117
return DrawPoint(GetSize() - contentOffsetEnd);
106118
}
107119

108-
void IngameWindow::SetPos(DrawPoint newPos)
120+
void IngameWindow::SetPos(DrawPoint newPos, bool saveRestorePos)
109121
{
110122
const Extent screenSize = VIDEODRIVER.GetRenderSize();
123+
DrawPoint newRestorePos = newPos;
111124
// Too far left or right?
112125
if(newPos.x < 0)
113-
newPos.x = 0;
114-
else if(newPos.x + GetSize().x > screenSize.x)
126+
newRestorePos.x = newPos.x = 0;
127+
else if(newPos.x + GetSize().x >= screenSize.x)
128+
{
115129
newPos.x = screenSize.x - GetSize().x;
130+
newRestorePos.x = DrawPoint::MaxElementValue; // make window stick to the right
131+
}
116132

117133
// Too high or low?
118134
if(newPos.y < 0)
119-
newPos.y = 0;
120-
else if(newPos.y + GetSize().y > screenSize.y)
135+
newRestorePos.y = newPos.y = 0;
136+
else if(newPos.y + GetSize().y >= screenSize.y)
137+
{
121138
newPos.y = screenSize.y - GetSize().y;
139+
newRestorePos.y = DrawPoint::MaxElementValue; // make window stick to the bottom
140+
}
122141

123-
// if possible save the position to settings
142+
if(saveRestorePos)
143+
restorePos_ = newRestorePos;
144+
145+
// if possible save the positions to settings
124146
if(windowSettings_)
147+
{
125148
windowSettings_->lastPos = newPos;
149+
if(saveRestorePos)
150+
windowSettings_->restorePos = newRestorePos;
151+
}
126152

127153
Window::SetPos(newPos);
128154
}

libs/s25main/ingameWindows/IngameWindow.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#pragma once
66

7+
#include "DrawPoint.h"
78
#include "Window.h"
89
#include "helpers/EnumArray.h"
910
#include "gameData/const_gui_ids.h"
@@ -71,7 +72,7 @@ class IngameWindow : public Window
7172
DrawPoint GetRightBottomBoundary();
7273

7374
/// Set the position for the window after adjusting newPos so the window is in the visible area
74-
void SetPos(DrawPoint newPos);
75+
void SetPos(DrawPoint newPos, bool saveRestorePos = true);
7576

7677
/// merkt das Fenster zum Schließen vor.
7778
virtual void Close();
@@ -128,4 +129,5 @@ class IngameWindow : public Window
128129
CloseBehavior closeBehavior_;
129130
helpers::EnumArray<ButtonState, IwButton> buttonStates_;
130131
PersistentWindowSettings* windowSettings_;
132+
DrawPoint restorePos_;
131133
};

libs/s25main/ingameWindows/iwObservate.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,11 +143,6 @@ void iwObservate::Msg_ButtonClick(const unsigned ctrl_id)
143143
for(unsigned i = 1; i <= 4; ++i)
144144
GetCtrl<ctrlImageButton>(i)->SetPos(
145145
DrawPoint(GetCtrl<ctrlImageButton>(i)->GetPos().x - diff, GetSize().y - 50));
146-
147-
DrawPoint maxPos(VIDEODRIVER.GetRenderSize() - GetSize() - Extent::all(1));
148-
DrawPoint newPos = elMin(maxPos, GetPos());
149-
if(newPos != GetPos())
150-
SetPos(newPos);
151146
}
152147
}
153148

0 commit comments

Comments
 (0)