Files
wx_wherigo/main/src/ui/wherigo_dialog.cpp
2026-02-13 02:55:04 +01:00

162 lines
5.4 KiB
C++

#include "ui/wherigo_dialog.h"
#include "lua/media_manager.h"
#include "lua/game_engine.h"
#include <wx/sizer.h>
#include <wx/stattext.h>
#include <wx/statbmp.h>
#include <wx/button.h>
#include <wx/log.h>
#include <wx/mstream.h>
#include <wx/image.h>
namespace wherigo {
WherigoMessageDialog::WherigoMessageDialog(wxWindow *parent, const wxString &text,
const wxString &title,
const std::vector<wxString> &buttons,
const wxString &mediaName)
: wxDialog(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize,
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) {
auto *sizer = new wxBoxSizer(wxVERTICAL);
// Media/Image (if provided)
if (!mediaName.IsEmpty()) {
auto mediaData = MediaManager::getInstance().getMediaByName(mediaName.ToStdString());
if (!mediaData.empty()) {
wxMemoryInputStream stream(mediaData.data(), mediaData.size());
wxImage image(stream);
if (image.IsOk()) {
// Get screen DPI for scaling
wxWindow* topWindow = wxTheApp->GetTopWindow();
double contentScaleFactor = 1.0;
if (topWindow) {
contentScaleFactor = topWindow->GetContentScaleFactor();
}
// Scale image - doubled size from original (800x600 instead of 400x300)
// Adjust for DPI/Retina displays
int maxWidth = static_cast<int>(800 * contentScaleFactor);
int maxHeight = static_cast<int>(600 * contentScaleFactor);
if (image.GetWidth() > maxWidth || image.GetHeight() > maxHeight) {
double scaleX = (double)maxWidth / image.GetWidth();
double scaleY = (double)maxHeight / image.GetHeight();
double scale = std::min(scaleX, scaleY);
image.Rescale(image.GetWidth() * scale, image.GetHeight() * scale, wxIMAGE_QUALITY_HIGH);
}
wxBitmap bitmap(image);
auto *imageCtrl = new wxStaticBitmap(this, wxID_ANY, bitmap);
sizer->Add(imageCtrl, 0, wxALL | wxALIGN_CENTER, 10);
} else {
wxLogDebug("Failed to load image: %s", mediaName);
auto *mediaLabel = new wxStaticText(this, wxID_ANY,
wxString::Format("[Media: %s]", mediaName));
mediaLabel->SetForegroundColour(*wxLIGHT_GREY);
sizer->Add(mediaLabel, 0, wxALL | wxALIGN_CENTER, 10);
}
} else {
wxLogDebug("No media data for: %s", mediaName);
auto *mediaLabel = new wxStaticText(this, wxID_ANY,
wxString::Format("[Media: %s]", mediaName));
mediaLabel->SetForegroundColour(*wxLIGHT_GREY);
sizer->Add(mediaLabel, 0, wxALL | wxALIGN_CENTER, 10);
}
}
// Text (only show if not just a placeholder like ".")
if (!text.IsEmpty() && text != ".") {
auto *textCtrl = new wxStaticText(this, wxID_ANY, text);
textCtrl->Wrap(800); // Also doubled wrap width
sizer->Add(textCtrl, 1, wxALL | wxEXPAND, 15);
} else if (mediaName.IsEmpty()) {
// No media and empty/placeholder text - show something
auto *textCtrl = new wxStaticText(this, wxID_ANY, text);
textCtrl->Wrap(800); // Also doubled wrap width
sizer->Add(textCtrl, 1, wxALL | wxEXPAND, 15);
}
// Buttons
auto *buttonSizer = new wxBoxSizer(wxHORIZONTAL);
if (buttons.empty()) {
auto *okButton = new wxButton(this, wxID_OK, "OK");
buttonSizer->Add(okButton, 0, wxALL, 5);
okButton->Bind(wxEVT_BUTTON, &WherigoMessageDialog::onButton, this);
} else {
for (size_t i = 0; i < buttons.size(); i++) {
auto *btn = new wxButton(this, 1000 + i, buttons[i]);
buttonSizer->Add(btn, 0, wxALL, 5);
btn->Bind(wxEVT_BUTTON, &WherigoMessageDialog::onButton, this);
}
}
sizer->Add(buttonSizer, 0, wxALIGN_CENTER | wxBOTTOM, 10);
SetSizerAndFit(sizer);
SetMinSize(wxSize(600, 300)); // Doubled from 300x150
CenterOnParent();
}
void WherigoMessageDialog::onButton(wxCommandEvent &event) {
int id = event.GetId();
if (id == wxID_OK) {
m_selectedButton = 0;
} else {
m_selectedButton = id - 1000;
}
EndModal(wxID_OK);
}
WherigoDialogRunner& WherigoDialogRunner::getInstance() {
static WherigoDialogRunner instance;
return instance;
}
void WherigoDialogRunner::showMessageBox(const wxString &text, const wxString &title,
std::function<void(int)> callback) {
WherigoMessageDialog dlg(nullptr, text, title);
dlg.ShowModal();
if (callback) {
callback(dlg.getSelectedButton());
}
}
void WherigoDialogRunner::showDialog(const std::vector<DialogEntry> &entries,
std::function<void(int)> callback) {
for (size_t i = 0; i < entries.size(); i++) {
const auto &entry = entries[i];
std::vector<wxString> buttons;
for (const auto &btn : entry.buttons) {
buttons.push_back(wxString::FromUTF8(btn));
}
if (buttons.empty() && i < entries.size() - 1) {
buttons.push_back("Weiter");
} else if (buttons.empty()) {
buttons.push_back("OK");
}
WherigoMessageDialog dlg(nullptr, wxString::FromUTF8(entry.text), "Wherigo",
buttons, wxString::FromUTF8(entry.mediaName));
dlg.ShowModal();
// For the last entry, call the callback with the selected button
if (i == entries.size() - 1 && callback) {
callback(dlg.getSelectedButton());
}
}
// Notify game state change after dialog sequence completes
GameEngine::getInstance().notifyStateChanged();
}
} // namespace wherigo