mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-01-18 23:52:02 +00:00
Finish the error window implementation
This commit is contained in:
parent
2d6203a0fe
commit
da83b546ad
7 changed files with 292 additions and 16 deletions
|
@ -172,4 +172,7 @@ public:
|
|||
virtual void SetCaptionTextColor(uint32_t bgra8) = 0;
|
||||
|
||||
virtual void PresentBitmap(int width, int height, const uint32_t* pixels) = 0;
|
||||
|
||||
virtual std::string GetClipboardText() = 0;
|
||||
virtual void SetClipboardText(const std::string& text) = 0;
|
||||
};
|
||||
|
|
|
@ -379,11 +379,18 @@ void Widget::ReleaseMouseCapture()
|
|||
|
||||
std::string Widget::GetClipboardText()
|
||||
{
|
||||
return {};
|
||||
Widget* w = Window();
|
||||
if (w)
|
||||
return w->DispWindow->GetClipboardText();
|
||||
else
|
||||
return {};
|
||||
}
|
||||
|
||||
void Widget::SetClipboardText(const std::string& text)
|
||||
{
|
||||
Widget* w = Window();
|
||||
if (w)
|
||||
w->DispWindow->SetClipboardText(text);
|
||||
}
|
||||
|
||||
Widget* Widget::Window()
|
||||
|
|
|
@ -254,6 +254,77 @@ double Win32Window::GetDpiScale() const
|
|||
return GetDpiForWindow(WindowHandle) / 96.0;
|
||||
}
|
||||
|
||||
std::string Win32Window::GetClipboardText()
|
||||
{
|
||||
BOOL result = OpenClipboard(WindowHandle);
|
||||
if (result == FALSE)
|
||||
throw std::runtime_error("Unable to open clipboard");
|
||||
|
||||
HANDLE handle = GetClipboardData(CF_UNICODETEXT);
|
||||
if (handle == 0)
|
||||
{
|
||||
CloseClipboard();
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::wstring::value_type* data = (std::wstring::value_type*)GlobalLock(handle);
|
||||
if (data == 0)
|
||||
{
|
||||
CloseClipboard();
|
||||
return std::string();
|
||||
}
|
||||
std::string str = from_utf16(data);
|
||||
GlobalUnlock(handle);
|
||||
|
||||
CloseClipboard();
|
||||
return str;
|
||||
}
|
||||
|
||||
void Win32Window::SetClipboardText(const std::string& text)
|
||||
{
|
||||
std::wstring text16 = to_utf16(text);
|
||||
|
||||
BOOL result = OpenClipboard(WindowHandle);
|
||||
if (result == FALSE)
|
||||
throw std::runtime_error("Unable to open clipboard");
|
||||
|
||||
result = EmptyClipboard();
|
||||
if (result == FALSE)
|
||||
{
|
||||
CloseClipboard();
|
||||
throw std::runtime_error("Unable to empty clipboard");
|
||||
}
|
||||
|
||||
unsigned int length = (text16.length() + 1) * sizeof(std::wstring::value_type);
|
||||
HANDLE handle = GlobalAlloc(GMEM_MOVEABLE, length);
|
||||
if (handle == 0)
|
||||
{
|
||||
CloseClipboard();
|
||||
throw std::runtime_error("Unable to allocate clipboard memory");
|
||||
}
|
||||
|
||||
void* data = GlobalLock(handle);
|
||||
if (data == 0)
|
||||
{
|
||||
GlobalFree(handle);
|
||||
CloseClipboard();
|
||||
throw std::runtime_error("Unable to lock clipboard memory");
|
||||
}
|
||||
memcpy(data, text16.c_str(), length);
|
||||
GlobalUnlock(handle);
|
||||
|
||||
HANDLE data_result = SetClipboardData(CF_UNICODETEXT, handle);
|
||||
|
||||
if (data_result == 0)
|
||||
{
|
||||
GlobalFree(handle);
|
||||
CloseClipboard();
|
||||
throw std::runtime_error("Unable to set clipboard data");
|
||||
}
|
||||
|
||||
CloseClipboard();
|
||||
}
|
||||
|
||||
void Win32Window::PresentBitmap(int width, int height, const uint32_t* pixels)
|
||||
{
|
||||
BITMAPV5HEADER header = {};
|
||||
|
|
|
@ -44,6 +44,9 @@ public:
|
|||
void SetCaptionColor(uint32_t bgra8) override;
|
||||
void SetCaptionTextColor(uint32_t bgra8) override;
|
||||
|
||||
std::string GetClipboardText() override;
|
||||
void SetClipboardText(const std::string& text) override;
|
||||
|
||||
Point GetLParamPos(LPARAM lparam) const;
|
||||
|
||||
static void ProcessEvents();
|
||||
|
|
|
@ -104,7 +104,7 @@ void MainWindow::ShowErrorPane(const char* text)
|
|||
I_NetDone();
|
||||
}
|
||||
|
||||
PrintStr(text);
|
||||
// PrintStr(text);
|
||||
|
||||
size_t totalsize = 0;
|
||||
for (const FString& line : bufferedConsoleStuff)
|
||||
|
@ -115,7 +115,7 @@ void MainWindow::ShowErrorPane(const char* text)
|
|||
for (const FString& line : bufferedConsoleStuff)
|
||||
alltext.append(line.GetChars(), line.Len());
|
||||
|
||||
ErrorWindow::ExecModal(alltext);
|
||||
restartrequest = ErrorWindow::ExecModal(text, alltext);
|
||||
}
|
||||
|
||||
void MainWindow::ShowNetStartPane(const char* message, int maxpos)
|
||||
|
|
|
@ -1,20 +1,25 @@
|
|||
|
||||
#include "errorwindow.h"
|
||||
#include "version.h"
|
||||
#include <zwidget/widgets/textedit/textedit.h>
|
||||
#include "v_font.h"
|
||||
#include "printf.h"
|
||||
#include <zwidget/core/image.h>
|
||||
#include <zwidget/widgets/pushbutton/pushbutton.h>
|
||||
|
||||
void ErrorWindow::ExecModal(const std::string& text)
|
||||
bool ErrorWindow::ExecModal(const std::string& text, const std::string& log)
|
||||
{
|
||||
Size screenSize = GetScreenSize();
|
||||
double windowWidth = 1200.0;
|
||||
double windowHeight = 700.0;
|
||||
|
||||
auto window = new ErrorWindow();
|
||||
window->SetText(text);
|
||||
auto window = std::make_unique<ErrorWindow>();
|
||||
window->SetText(text, log);
|
||||
window->SetFrameGeometry((screenSize.width - windowWidth) * 0.5, (screenSize.height - windowHeight) * 0.5, windowWidth, windowHeight);
|
||||
window->Show();
|
||||
|
||||
DisplayWindow::RunLoop();
|
||||
|
||||
return window->Restart;
|
||||
}
|
||||
|
||||
ErrorWindow::ErrorWindow() : Widget(nullptr, WidgetType::Window)
|
||||
|
@ -26,19 +31,175 @@ ErrorWindow::ErrorWindow() : Widget(nullptr, WidgetType::Window)
|
|||
SetWindowCaptionColor(Colorf::fromRgba8(33, 33, 33));
|
||||
SetWindowCaptionTextColor(Colorf::fromRgba8(226, 223, 219));
|
||||
|
||||
LogView = new TextEdit(this);
|
||||
LogView = new LogViewer(this);
|
||||
ClipboardButton = new PushButton(this);
|
||||
RestartButton = new PushButton(this);
|
||||
|
||||
ClipboardButton->OnClick = [=]() { OnClipboardButtonClicked(); };
|
||||
RestartButton->OnClick = [=]() { OnRestartButtonClicked(); };
|
||||
|
||||
ClipboardButton->SetText("Copy to clipboard");
|
||||
RestartButton->SetText("Restart");
|
||||
|
||||
LogView->SetFocus();
|
||||
}
|
||||
|
||||
void ErrorWindow::SetText(const std::string& text)
|
||||
void ErrorWindow::SetText(const std::string& text, const std::string& log)
|
||||
{
|
||||
LogView->SetText(text);
|
||||
LogView->SetText(text, log);
|
||||
|
||||
clipboardtext.clear();
|
||||
clipboardtext.reserve(log.size() + text.size() + 100);
|
||||
|
||||
// Strip the color escapes from the log
|
||||
const uint8_t* cptr = (const uint8_t*)log.data();
|
||||
while (int chr = GetCharFromString(cptr))
|
||||
{
|
||||
if (chr != TEXTCOLOR_ESCAPE)
|
||||
{
|
||||
// The bar characters, most commonly used to indicate map changes
|
||||
if (chr >= 0x1D && chr <= 0x1F)
|
||||
{
|
||||
chr = 0x2550; // Box Drawings Double Horizontal
|
||||
}
|
||||
clipboardtext += MakeUTF8(chr);
|
||||
}
|
||||
}
|
||||
|
||||
clipboardtext += "\nExecution could not continue.\n";
|
||||
clipboardtext += text;
|
||||
clipboardtext += "\n";
|
||||
}
|
||||
|
||||
void ErrorWindow::OnClipboardButtonClicked()
|
||||
{
|
||||
SetClipboardText(clipboardtext);
|
||||
}
|
||||
|
||||
void ErrorWindow::OnRestartButtonClicked()
|
||||
{
|
||||
Restart = true;
|
||||
DisplayWindow::ExitLoop();
|
||||
}
|
||||
|
||||
void ErrorWindow::OnClose()
|
||||
{
|
||||
Restart = false;
|
||||
DisplayWindow::ExitLoop();
|
||||
}
|
||||
|
||||
void ErrorWindow::OnGeometryChanged()
|
||||
{
|
||||
double w = GetWidth();
|
||||
double h = GetHeight();
|
||||
LogView->SetFrameGeometry(Rect::xywh(20.0, 20.0, w - 40.0, h - 40.0));
|
||||
|
||||
double y = GetHeight() - 15.0 - ClipboardButton->GetPreferredHeight();
|
||||
ClipboardButton->SetFrameGeometry(20.0, y, 170.0, ClipboardButton->GetPreferredHeight());
|
||||
RestartButton->SetFrameGeometry(GetWidth() - 20.0 - 100.0, y, 100.0, RestartButton->GetPreferredHeight());
|
||||
y -= 20.0;
|
||||
|
||||
LogView->SetFrameGeometry(Rect::xywh(0.0, 0.0, w, y));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LogViewer::LogViewer(Widget* parent) : Widget(parent)
|
||||
{
|
||||
SetNoncontentSizes(8.0, 8.0, 8.0, 8.0);
|
||||
}
|
||||
|
||||
void LogViewer::SetText(const std::string& text, const std::string& log)
|
||||
{
|
||||
lines.clear();
|
||||
|
||||
std::string::size_type start = 0;
|
||||
std::string::size_type end = log.find('\n');
|
||||
while (end != std::string::npos)
|
||||
{
|
||||
lines.push_back(CreateLineLayout(log.substr(start, end - start)));
|
||||
start = end + 1;
|
||||
end = log.find('\n', start);
|
||||
}
|
||||
|
||||
lines.push_back(CreateLineLayout(log.substr(start)));
|
||||
|
||||
// Add an empty line as a bit of spacing
|
||||
lines.push_back(CreateLineLayout({}));
|
||||
|
||||
SpanLayout layout;
|
||||
//layout.AddImage(Image::LoadResource("widgets/erroricon.svg"), -8.0);
|
||||
layout.AddText("Execution could not continue.", largefont, Colorf::fromRgba8(255, 170, 170));
|
||||
lines.push_back(layout);
|
||||
|
||||
layout.Clear();
|
||||
layout.AddText(text, largefont, Colorf::fromRgba8(255, 255, 170));
|
||||
lines.push_back(layout);
|
||||
|
||||
Update();
|
||||
}
|
||||
|
||||
SpanLayout LogViewer::CreateLineLayout(const std::string& text)
|
||||
{
|
||||
SpanLayout layout;
|
||||
|
||||
Colorf curcolor = Colorf::fromRgba8(255, 255, 255);
|
||||
std::string curtext;
|
||||
|
||||
const uint8_t* cptr = (const uint8_t*)text.data();
|
||||
while (int chr = GetCharFromString(cptr))
|
||||
{
|
||||
if (chr != TEXTCOLOR_ESCAPE)
|
||||
{
|
||||
// The bar characters, most commonly used to indicate map changes
|
||||
if (chr >= 0x1D && chr <= 0x1F)
|
||||
{
|
||||
chr = 0x2550; // Box Drawings Double Horizontal
|
||||
}
|
||||
curtext += MakeUTF8(chr);
|
||||
}
|
||||
else
|
||||
{
|
||||
EColorRange range = V_ParseFontColor(cptr, CR_UNTRANSLATED, CR_YELLOW);
|
||||
if (range != CR_UNDEFINED)
|
||||
{
|
||||
if (!curtext.empty())
|
||||
layout.AddText(curtext, font, curcolor);
|
||||
curtext.clear();
|
||||
|
||||
PalEntry color = V_LogColorFromColorRange(range);
|
||||
curcolor = Colorf::fromRgba8(color.r, color.g, color.b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
curtext.push_back(' ');
|
||||
layout.AddText(curtext, font, curcolor);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
void LogViewer::OnPaintFrame(Canvas* canvas)
|
||||
{
|
||||
double w = GetFrameGeometry().width;
|
||||
double h = GetFrameGeometry().height;
|
||||
Colorf bordercolor = Colorf::fromRgba8(100, 100, 100);
|
||||
canvas->fillRect(Rect::xywh(0.0, 0.0, w, h), Colorf::fromRgba8(38, 38, 38));
|
||||
//canvas->fillRect(Rect::xywh(0.0, 0.0, w, 1.0), bordercolor);
|
||||
//canvas->fillRect(Rect::xywh(0.0, h - 1.0, w, 1.0), bordercolor);
|
||||
//canvas->fillRect(Rect::xywh(0.0, 0.0, 1.0, h - 0.0), bordercolor);
|
||||
//canvas->fillRect(Rect::xywh(w - 1.0, 0.0, 1.0, h - 0.0), bordercolor);
|
||||
}
|
||||
|
||||
void LogViewer::OnPaint(Canvas* canvas)
|
||||
{
|
||||
double width = GetWidth();
|
||||
double y = GetHeight();
|
||||
for (size_t i = lines.size(); i > 0 && y > 0.0; i--)
|
||||
{
|
||||
SpanLayout& layout = lines[i - 1];
|
||||
layout.Layout(canvas, width);
|
||||
layout.SetPosition(Point(0.0, y - layout.GetSize().height));
|
||||
layout.DrawLayout(canvas);
|
||||
y -= layout.GetSize().height;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,21 +1,52 @@
|
|||
#pragma once
|
||||
|
||||
#include <zwidget/core/widget.h>
|
||||
#include <zwidget/core/span_layout.h>
|
||||
|
||||
class TextEdit;
|
||||
class LogViewer;
|
||||
class PushButton;
|
||||
|
||||
class ErrorWindow : public Widget
|
||||
{
|
||||
public:
|
||||
static void ExecModal(const std::string& text);
|
||||
static bool ExecModal(const std::string& text, const std::string& log);
|
||||
|
||||
ErrorWindow();
|
||||
|
||||
bool Restart = false;
|
||||
|
||||
protected:
|
||||
void OnClose() override;
|
||||
void OnGeometryChanged() override;
|
||||
|
||||
private:
|
||||
ErrorWindow();
|
||||
void SetText(const std::string& text, const std::string& log);
|
||||
|
||||
void SetText(const std::string& text);
|
||||
void OnClipboardButtonClicked();
|
||||
void OnRestartButtonClicked();
|
||||
|
||||
TextEdit* LogView = nullptr;
|
||||
LogViewer* LogView = nullptr;
|
||||
PushButton* ClipboardButton = nullptr;
|
||||
PushButton* RestartButton = nullptr;
|
||||
|
||||
std::string clipboardtext;
|
||||
};
|
||||
|
||||
class LogViewer : public Widget
|
||||
{
|
||||
public:
|
||||
LogViewer(Widget* parent);
|
||||
|
||||
void SetText(const std::string& text, const std::string& log);
|
||||
|
||||
protected:
|
||||
void OnPaintFrame(Canvas* canvas) override;
|
||||
void OnPaint(Canvas* canvas) override;
|
||||
|
||||
private:
|
||||
SpanLayout CreateLineLayout(const std::string& text);
|
||||
|
||||
std::shared_ptr<Font> largefont = Font::Create("Poppins", 16.0);
|
||||
std::shared_ptr<Font> font = Font::Create("Poppins", 12.0);
|
||||
std::vector<SpanLayout> lines;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue