Skip to content

Commit

Permalink
Merge pull request #1601 from falbrechtskirchinger/improve-window-pos…
Browse files Browse the repository at this point in the history
…itioning

Improve in-game window positioning
  • Loading branch information
Flamefire authored Jul 25, 2023
2 parents 5907058 + fccbc9e commit 48bc284
Show file tree
Hide file tree
Showing 7 changed files with 237 additions and 34 deletions.
3 changes: 3 additions & 0 deletions libs/common/include/Point.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ struct Point //-V690
using ElementType = T;
static_assert(std::is_arithmetic<ElementType>::value, "Requires an arithmetic type");

static constexpr auto MinElementValue = std::numeric_limits<T>::min();
static constexpr auto MaxElementValue = std::numeric_limits<T>::max();

struct Truncate_t
{
constexpr explicit Truncate_t() = default;
Expand Down
26 changes: 18 additions & 8 deletions libs/s25main/Settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -347,10 +347,13 @@ void Settings::LoadIngame()
const auto* iniWindow = static_cast<const libsiedler2::ArchivItem_Ini*>(settingsIngame.find(window.second));
if(!iniWindow)
continue;
windows.persistentSettings[window.first].lastPos.x = iniWindow->getIntValue("pos_x");
windows.persistentSettings[window.first].lastPos.y = iniWindow->getIntValue("pos_y");
windows.persistentSettings[window.first].isOpen = iniWindow->getIntValue("is_open");
windows.persistentSettings[window.first].isMinimized = iniWindow->getValue("is_minimized", false);
auto& settings = windows.persistentSettings[window.first];
const auto lastPos = settings.lastPos =
DrawPoint(iniWindow->getIntValue("pos_x"), iniWindow->getIntValue("pos_y"));
settings.restorePos = DrawPoint(iniWindow->getValue("restore_pos_x", lastPos.x),
iniWindow->getValue("restore_pos_y", lastPos.y));
settings.isOpen = iniWindow->getIntValue("is_open");
settings.isMinimized = iniWindow->getValue("is_minimized", false);
}
} catch(std::runtime_error& e)
{
Expand Down Expand Up @@ -500,10 +503,17 @@ void Settings::SaveIngame()
auto* iniWindow = static_cast<libsiedler2::ArchivItem_Ini*>(settingsIngame.find(window.second));
if(!iniWindow)
continue;
iniWindow->setValue("pos_x", windows.persistentSettings[window.first].lastPos.x);
iniWindow->setValue("pos_y", windows.persistentSettings[window.first].lastPos.y);
iniWindow->setValue("is_open", windows.persistentSettings[window.first].isOpen);
iniWindow->setValue("is_minimized", windows.persistentSettings[window.first].isMinimized);
const auto& settings = windows.persistentSettings[window.first];
iniWindow->setValue("pos_x", settings.lastPos.x);
iniWindow->setValue("pos_y", settings.lastPos.y);
if(settings.restorePos != settings.lastPos)
{
// only save if different; defaults to lastPos on load
iniWindow->setValue("restore_pos_x", settings.restorePos.x);
iniWindow->setValue("restore_pos_y", settings.restorePos.y);
}
iniWindow->setValue("is_open", settings.isOpen);
iniWindow->setValue("is_minimized", settings.isMinimized);
}

bfs::path settingsPathIngame = RTTRCONFIG.ExpandPath(s25::resources::ingameOptions);
Expand Down
1 change: 1 addition & 0 deletions libs/s25main/Settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ bool checkPort(int port);
struct PersistentWindowSettings
{
DrawPoint lastPos = DrawPoint::Invalid();
DrawPoint restorePos = DrawPoint::Invalid();
bool isOpen = false;
bool isMinimized = false;
};
Expand Down
66 changes: 46 additions & 20 deletions libs/s25main/ingameWindows/IngameWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,9 @@ namespace {
constexpr Extent ButtonSize(16, 16);
}

const DrawPoint IngameWindow::posLastOrCenter(std::numeric_limits<DrawPoint::ElementType>::max(),
std::numeric_limits<DrawPoint::ElementType>::max());
const DrawPoint IngameWindow::posCenter(std::numeric_limits<DrawPoint::ElementType>::max() - 1,
std::numeric_limits<DrawPoint::ElementType>::max());
const DrawPoint IngameWindow::posAtMouse(std::numeric_limits<DrawPoint::ElementType>::max() - 1,
std::numeric_limits<DrawPoint::ElementType>::max() - 1);
const DrawPoint IngameWindow::posLastOrCenter(DrawPoint::MaxElementValue, DrawPoint::MaxElementValue);
const DrawPoint IngameWindow::posCenter(DrawPoint::MaxElementValue - 1, DrawPoint::MaxElementValue);
const DrawPoint IngameWindow::posAtMouse(DrawPoint::MaxElementValue - 1, DrawPoint::MaxElementValue - 1);

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

// Restore minimized state
if(windowSettings_ && windowSettings_->isMinimized)
if(windowSettings_)
{
isMinimized_ = true;
Extent minimizedSize(GetSize().x, contentOffset.y + contentOffsetEnd.y);
Window::Resize(minimizedSize);
// Restore minimized state
if(windowSettings_ && windowSettings_->isMinimized)
{
isMinimized_ = true;
Extent minimizedSize(GetSize().x, contentOffset.y + contentOffsetEnd.y);
Window::Resize(minimizedSize);
}
// Load restorePos
restorePos_ = windowSettings_->restorePos;
}

// Load last position or center the window
if(pos == posLastOrCenter)
{
if(windowSettings_ && windowSettings_->lastPos.isValid())
SetPos(windowSettings_->lastPos);
SetPos(windowSettings_->lastPos, !restorePos_.isValid());
else
MoveToCenter();
} else if(pos == posCenter)
MoveToCenter();
else if(pos == posAtMouse)
MoveNextToMouse();
else
SetPos(pos); // always call SetPos() to update restorePos
}

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

void IngameWindow::SetIwSize(const Extent& newSize)
{
// Is the window connecting with the bottom screen edge?
const auto atBottom = (GetPos().y + GetSize().y) >= VIDEODRIVER.GetRenderSize().y;

iwHeight = newSize.y;
Extent wndSize = newSize;
if(isMinimized_)
wndSize.y = 0;
wndSize += contentOffset + contentOffsetEnd;
Window::Resize(wndSize);

// Reset the position to check if parts of the window are out of the visible area
SetPos(GetPos());
// Adjust restorePos if the window was connecting with the bottom screen edge before being minimized
const auto pos = (atBottom && isMinimized_) ? DrawPoint(restorePos_.x, DrawPoint::MaxElementValue) : restorePos_;

// Reset the position
// 1) to check if parts of the window are out of the visible area
// 2) to re-connect the window with the bottom screen edge, if needed
SetPos(pos, false);
}

Extent IngameWindow::GetIwSize() const
Expand All @@ -105,24 +117,38 @@ DrawPoint IngameWindow::GetRightBottomBoundary()
return DrawPoint(GetSize() - contentOffsetEnd);
}

void IngameWindow::SetPos(DrawPoint newPos)
void IngameWindow::SetPos(DrawPoint newPos, bool saveRestorePos)
{
const Extent screenSize = VIDEODRIVER.GetRenderSize();
DrawPoint newRestorePos = newPos;
// Too far left or right?
if(newPos.x < 0)
newPos.x = 0;
else if(newPos.x + GetSize().x > screenSize.x)
newRestorePos.x = newPos.x = 0;
else if(newPos.x + GetSize().x >= screenSize.x)
{
newPos.x = screenSize.x - GetSize().x;
newRestorePos.x = DrawPoint::MaxElementValue; // make window stick to the right
}

// Too high or low?
if(newPos.y < 0)
newPos.y = 0;
else if(newPos.y + GetSize().y > screenSize.y)
newRestorePos.y = newPos.y = 0;
else if(newPos.y + GetSize().y >= screenSize.y)
{
newPos.y = screenSize.y - GetSize().y;
newRestorePos.y = DrawPoint::MaxElementValue; // make window stick to the bottom
}

// if possible save the position to settings
if(saveRestorePos)
restorePos_ = newRestorePos;

// if possible save the positions to settings
if(windowSettings_)
{
windowSettings_->lastPos = newPos;
if(saveRestorePos)
windowSettings_->restorePos = newRestorePos;
}

Window::SetPos(newPos);
}
Expand Down
4 changes: 3 additions & 1 deletion libs/s25main/ingameWindows/IngameWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#pragma once

#include "DrawPoint.h"
#include "Window.h"
#include "helpers/EnumArray.h"
#include "gameData/const_gui_ids.h"
Expand Down Expand Up @@ -71,7 +72,7 @@ class IngameWindow : public Window
DrawPoint GetRightBottomBoundary();

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

/// merkt das Fenster zum Schließen vor.
virtual void Close();
Expand Down Expand Up @@ -128,4 +129,5 @@ class IngameWindow : public Window
CloseBehavior closeBehavior_;
helpers::EnumArray<ButtonState, IwButton> buttonStates_;
PersistentWindowSettings* windowSettings_;
DrawPoint restorePos_;
};
5 changes: 0 additions & 5 deletions libs/s25main/ingameWindows/iwObservate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,6 @@ void iwObservate::Msg_ButtonClick(const unsigned ctrl_id)
for(unsigned i = 1; i <= 4; ++i)
GetCtrl<ctrlImageButton>(i)->SetPos(
DrawPoint(GetCtrl<ctrlImageButton>(i)->GetPos().x - diff, GetSize().y - 50));

DrawPoint maxPos(VIDEODRIVER.GetRenderSize() - GetSize() - Extent::all(1));
DrawPoint newPos = elMin(maxPos, GetPos());
if(newPos != GetPos())
SetPos(newPos);
}
}

Expand Down
Loading

0 comments on commit 48bc284

Please sign in to comment.