Implement the timer class

Support calling ShowNetStartPane multiple times
This commit is contained in:
Magnus Norddahl 2023-12-31 06:36:26 +01:00 committed by Christoph Oelckers
parent efde75877d
commit 426837e7d4
8 changed files with 93 additions and 8 deletions

View file

@ -20,5 +20,7 @@ private:
Timer* PrevTimerObj = nullptr;
Timer* NextTimerObj = nullptr;
void* TimerId = nullptr;
friend class Widget;
};

View file

@ -2,6 +2,7 @@
#include <memory>
#include <string>
#include <functional>
#include "../core/rect.h"
class Engine;
@ -141,6 +142,9 @@ public:
static void RunLoop();
static void ExitLoop();
static void* StartTimer(int timeoutMilliseconds, std::function<void()> onTimer);
static void StopTimer(void* timerID);
static Size GetScreenSize();
virtual ~DisplayWindow() = default;

View file

@ -1,6 +1,7 @@
#include "core/timer.h"
#include "core/widget.h"
#include "window/window.h"
Timer::Timer(Widget* owner) : OwnerObj(owner)
{
@ -22,8 +23,21 @@ Timer::~Timer()
void Timer::Start(int timeoutMilliseconds, bool repeat)
{
Stop();
TimerId = DisplayWindow::StartTimer(timeoutMilliseconds, [=]() {
if (!repeat)
Stop();
if (FuncExpired)
FuncExpired();
});
}
void Timer::Stop()
{
if (TimerId != 0)
{
DisplayWindow::StopTimer(TimerId);
TimerId = 0;
}
}

View file

@ -568,5 +568,35 @@ Size Win32Window::GetScreenSize()
return Size(screenWidth / dpiScale, screenHeight / dpiScale);
}
static void CALLBACK Win32TimerCallback(HWND handle, UINT message, UINT_PTR timerID, DWORD timestamp)
{
auto it = Win32Window::Timers.find(timerID);
if (it != Win32Window::Timers.end())
{
it->second();
}
}
void* Win32Window::StartTimer(int timeoutMilliseconds, std::function<void()> onTimer)
{
UINT_PTR result = SetTimer(0, 0, timeoutMilliseconds, Win32TimerCallback);
if (result == 0)
throw std::runtime_error("Could not create timer");
Timers[result] = std::move(onTimer);
return (void*)result;
}
void Win32Window::StopTimer(void* timerID)
{
auto it = Timers.find((UINT_PTR)timerID);
if (it != Timers.end())
{
Timers.erase(it);
KillTimer(0, (UINT_PTR)timerID);
}
}
std::list<Win32Window*> Win32Window::Windows;
bool Win32Window::ExitRunLoop;
std::unordered_map<UINT_PTR, std::function<void()>> Win32Window::Timers;

View file

@ -8,6 +8,7 @@
#include <Windows.h>
#include <list>
#include <unordered_map>
#include <zwidget/window/window.h>
class Win32Window : public DisplayWindow
@ -54,10 +55,15 @@ public:
static void ExitLoop();
static Size GetScreenSize();
static void* StartTimer(int timeoutMilliseconds, std::function<void()> onTimer);
static void StopTimer(void* timerID);
static bool ExitRunLoop;
static std::list<Win32Window*> Windows;
std::list<Win32Window*>::iterator WindowsIterator;
static std::unordered_map<UINT_PTR, std::function<void()>> Timers;
LRESULT OnWindowMessage(UINT msg, WPARAM wparam, LPARAM lparam);
static LRESULT CALLBACK WndProc(HWND windowhandle, UINT msg, WPARAM wparam, LPARAM lparam);

View file

@ -30,6 +30,16 @@ Size DisplayWindow::GetScreenSize()
return Win32Window::GetScreenSize();
}
void* DisplayWindow::StartTimer(int timeoutMilliseconds, std::function<void()> onTimer)
{
return Win32Window::StartTimer(timeoutMilliseconds, std::move(onTimer));
}
void DisplayWindow::StopTimer(void* timerID)
{
Win32Window::StopTimer(timerID);
}
#else
std::unique_ptr<DisplayWindow> DisplayWindow::Create(DisplayWindowHost* windowHost)
@ -57,4 +67,14 @@ Size DisplayWindow::GetScreenSize()
throw std::runtime_error("DisplayWindow::GetScreenSize not implemented");
}
int DisplayWindow::StartTimer(int timeoutMilliseconds, std::function<void()> onTimer)
{
throw std::runtime_error("DisplayWindow::StartTimer not implemented");
}
void DisplayWindow::StopTimer(int timerID)
{
throw std::runtime_error("DisplayWindow::StopTimer not implemented");
}
#endif

View file

@ -10,15 +10,18 @@ NetStartWindow* NetStartWindow::Instance = nullptr;
void NetStartWindow::ShowNetStartPane(const char* message, int maxpos)
{
HideNetStartPane();
Size screenSize = GetScreenSize();
double windowWidth = 300.0;
double windowHeight = 150.0;
Instance = new NetStartWindow(message, maxpos);
Instance->SetFrameGeometry((screenSize.width - windowWidth) * 0.5, (screenSize.height - windowHeight) * 0.5, windowWidth, windowHeight);
Instance->Show();
if (!Instance)
{
Instance = new NetStartWindow();
Instance->SetFrameGeometry((screenSize.width - windowWidth) * 0.5, (screenSize.height - windowHeight) * 0.5, windowWidth, windowHeight);
Instance->Show();
}
Instance->SetMessage(message, maxpos);
}
void NetStartWindow::HideNetStartPane()
@ -60,7 +63,7 @@ bool NetStartWindow::RunMessageLoop(bool (*newtimer_callback)(void*), void* newu
return Instance->exitreason;
}
NetStartWindow::NetStartWindow(const std::string& message, int maxpos) : Widget(nullptr, WidgetType::Window)
NetStartWindow::NetStartWindow() : Widget(nullptr, WidgetType::Window)
{
SetWindowBackground(Colorf::fromRgba8(51, 51, 51));
SetWindowBorderColor(Colorf::fromRgba8(51, 51, 51));
@ -78,13 +81,18 @@ NetStartWindow::NetStartWindow(const std::string& message, int maxpos) : Widget(
AbortButton->OnClick = [=]() { OnClose(); };
AbortButton->SetText("Abort Network Game");
MessageLabel->SetText(message);
CallbackTimer = new Timer(this);
CallbackTimer->FuncExpired = [=]() { OnCallbackTimerExpired(); };
CallbackTimer->Start(500);
}
void NetStartWindow::SetMessage(const std::string& message, int newmaxpos)
{
MessageLabel->SetText(message);
maxpos = newmaxpos;
}
void NetStartWindow::SetProgress(int newpos)
{
if (pos != newpos && maxpos > 1)

View file

@ -16,8 +16,9 @@ public:
static bool RunMessageLoop(bool (*timer_callback)(void*), void* userdata);
private:
NetStartWindow(const std::string& message, int maxpos);
NetStartWindow();
void SetMessage(const std::string& message, int maxpos);
void SetProgress(int pos);
protected: