2021-06-27 21:25:29 +00:00
|
|
|
/***
|
|
|
|
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
|
|
|
|
|
|
|
File: ConsoleWxWidgets.cpp
|
|
|
|
Date: 2021-6-8
|
|
|
|
Author: Reece
|
|
|
|
***/
|
|
|
|
#include <RuntimeInternal.hpp>
|
|
|
|
#include "ConsoleWxWidgets.hpp"
|
|
|
|
|
|
|
|
#if defined(_AUHAS_WXWIDGETS)
|
|
|
|
#include <asio.hpp>
|
|
|
|
#include <wx/wxprec.h>
|
|
|
|
#include <wx/wx.h>
|
|
|
|
|
|
|
|
#include <wx/wxprec.h>
|
|
|
|
#include <wx/wx.h>
|
|
|
|
#include <wx/richtext/richtextctrl.h>
|
|
|
|
|
|
|
|
static bool DarkModeEnabled();
|
|
|
|
|
|
|
|
class ConsoleFrame;
|
|
|
|
|
|
|
|
static AuList<Aurora::Console::ConsoleMessage> gPendingLines;
|
|
|
|
static Aurora::Threading::Primitives::MutexUnique_t gMutex;
|
|
|
|
static bool gWxConsoleReady;
|
|
|
|
static ConsoleFrame *gWxFrame;
|
|
|
|
|
|
|
|
|
|
|
|
class WxSplitterLine : public wxWindow
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
WxSplitterLine() {}
|
|
|
|
WxSplitterLine(wxSize splitter, wxColor color, wxWindow *parent, wxWindowID winid) : wxWindow(parent, winid), _color(color)
|
|
|
|
{
|
|
|
|
SetMinSize(splitter);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OnPaint(wxPaintEvent &paint)
|
|
|
|
{
|
|
|
|
wxPaintDC re(this);
|
|
|
|
re.SetBrush(_color);
|
|
|
|
re.SetBackground(_color);
|
|
|
|
re.Clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
DECLARE_EVENT_TABLE()
|
|
|
|
|
|
|
|
wxColor _color;
|
|
|
|
};
|
|
|
|
wxBEGIN_EVENT_TABLE(WxSplitterLine, wxPanel)
|
|
|
|
EVT_PAINT(WxSplitterLine::OnPaint)
|
|
|
|
wxEND_EVENT_TABLE()
|
|
|
|
|
|
|
|
class ConsoleApp : public wxApp
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
~ConsoleApp();
|
|
|
|
virtual bool OnInit();
|
|
|
|
};
|
|
|
|
IMPLEMENT_APP_NO_MAIN(ConsoleApp);
|
|
|
|
|
|
|
|
ConsoleApp::~ConsoleApp()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class ConsoleFrame : public wxFrame
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ConsoleFrame(const wxString &title, const wxPoint &pos, const wxSize &size);
|
|
|
|
|
|
|
|
~ConsoleFrame()
|
|
|
|
{
|
|
|
|
Aurora::Threading::Primitives::MutexUnique_t re(gMutex.get());
|
|
|
|
gWxConsoleReady = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void WriteLine(const Aurora::Console::ConsoleMessage &msg);
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
void OnHello(wxCommandEvent &event);
|
|
|
|
void OnExit(wxCommandEvent &event);
|
|
|
|
void OnAbout(wxCommandEvent &event);
|
|
|
|
void OnBugWrite(wxCommandEvent &event);
|
|
|
|
void OnInit(wxWindowCreateEvent &event);
|
2021-07-01 10:42:48 +00:00
|
|
|
void OnShow(wxWindowCreateEvent &event);
|
2021-06-27 21:25:29 +00:00
|
|
|
void OnCmd(wxCommandEvent &event);
|
2021-07-01 10:42:48 +00:00
|
|
|
void OnPump(wxTimerEvent& event);
|
2021-06-27 21:25:29 +00:00
|
|
|
|
|
|
|
WxSplitterLine *NewSplitter(wxSize splitter, wxColor color);
|
|
|
|
|
|
|
|
wxDECLARE_EVENT_TABLE();
|
|
|
|
wxRichTextCtrl *richtextbox_;
|
|
|
|
wxTextCtrl *commandbox_;
|
|
|
|
wxMenuBar *menuBar_;
|
|
|
|
wxBoxSizer *sizer_;
|
|
|
|
AuList<WxSplitterLine *> _splitters;
|
2021-07-01 10:42:48 +00:00
|
|
|
wxTimer timer_;
|
2021-06-27 21:25:29 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
ID_Hello = 1,
|
|
|
|
ID_BLACKBOX,
|
|
|
|
ID_WRITE_REPORT,
|
|
|
|
ID_OPENTXT,
|
|
|
|
ID_OPENBIN
|
|
|
|
};
|
|
|
|
wxBEGIN_EVENT_TABLE(ConsoleFrame, wxFrame)
|
|
|
|
EVT_MENU(ID_Hello, ConsoleFrame::OnHello)
|
|
|
|
EVT_MENU(wxID_EXIT, ConsoleFrame::OnExit)
|
|
|
|
EVT_MENU(wxID_ABOUT, ConsoleFrame::OnAbout)
|
|
|
|
EVT_MENU(ID_WRITE_REPORT, ConsoleFrame::OnBugWrite)
|
|
|
|
EVT_WINDOW_CREATE(ConsoleFrame::OnInit)
|
|
|
|
wxEND_EVENT_TABLE()
|
|
|
|
|
|
|
|
|
|
|
|
bool ConsoleApp::OnInit()
|
|
|
|
{
|
|
|
|
ConsoleFrame *frame = _new ConsoleFrame("Aurora Engine Console", wxPoint(50, 50), wxSize(1080, 550));
|
|
|
|
frame->Show(true);
|
|
|
|
gWxFrame = frame;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConsoleFrame::OnCmd(wxCommandEvent &event)
|
|
|
|
{
|
|
|
|
// im lazy, i know, bite me
|
|
|
|
auto textbox = reinterpret_cast<wxTextCtrl *>(this);
|
|
|
|
|
|
|
|
AuString line = textbox->GetLineText(0);
|
|
|
|
if (line.empty())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
textbox->Clear();
|
|
|
|
|
|
|
|
Aurora::Console::Commands::DispatchCommand(line);
|
|
|
|
}
|
|
|
|
|
|
|
|
WxSplitterLine *ConsoleFrame::NewSplitter(wxSize splitter, wxColor color)
|
|
|
|
{
|
|
|
|
auto re = new WxSplitterLine(splitter, color, this, -1);
|
|
|
|
_splitters.push_back(re);
|
|
|
|
return re;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConsoleFrame::WriteLine(const Aurora::Console::ConsoleMessage &string)
|
|
|
|
{
|
|
|
|
static std::array<const wxColour, static_cast<size_t>(Aurora::Console::EAnsiColor::eCount)> ColorMap
|
|
|
|
{
|
|
|
|
*wxRED, // kRed,
|
|
|
|
*wxRED, // kBoldRed,
|
|
|
|
*wxGREEN, // kGreen,
|
|
|
|
*wxGREEN, // kBoldGreen,
|
|
|
|
*wxYELLOW, // kYellow,
|
|
|
|
*wxYELLOW, // kBoldYellow,
|
|
|
|
*wxBLUE, // kBlue,
|
|
|
|
*wxBLUE, // kBoldBlue,
|
|
|
|
*wxRED, // kMagenta,
|
|
|
|
*wxRED, // kBoldMagenta,
|
|
|
|
*wxBLUE, // kCyan,
|
|
|
|
*wxBLUE, // kBoldCyan,
|
|
|
|
*wxWHITE, // kReset
|
|
|
|
};
|
|
|
|
|
|
|
|
static std::array<bool, static_cast<size_t>(Aurora::Console::EAnsiColor::eCount)> HahaBald
|
|
|
|
{
|
|
|
|
false, // kRed,
|
|
|
|
true, // kBoldRed,
|
|
|
|
false, // kGreen,
|
|
|
|
true, // kBoldGreen,
|
|
|
|
false, // kYellow,
|
|
|
|
true, // kBoldYellow,
|
|
|
|
false, // kBlue,
|
|
|
|
true, // kBoldBlue,
|
|
|
|
false, // kMagenta,
|
|
|
|
true, // kBoldMagenta,
|
|
|
|
false, // kCyan,
|
|
|
|
true, // kBoldCyan,
|
|
|
|
false, // kReset
|
|
|
|
};
|
|
|
|
|
|
|
|
auto writeLine = string.ToSimplified();
|
|
|
|
|
|
|
|
bool useColor = DarkModeEnabled();
|
|
|
|
|
|
|
|
auto color = useColor ? ColorMap[static_cast<int>(string.color)] : wxColor(0, 0, 0);
|
|
|
|
auto bold = useColor ? HahaBald[static_cast<int>(string.color)] : false;
|
|
|
|
|
|
|
|
|
|
|
|
if (richtextbox_->GetNumberOfLines() > 1000)
|
|
|
|
richtextbox_->Clear();
|
|
|
|
|
|
|
|
//richtextbox_->BeginParagraphSpacing(0, 20);
|
|
|
|
|
|
|
|
auto pos = richtextbox_->GetCaretPosition();
|
|
|
|
auto selPos = richtextbox_->GetLastPosition() - 1;
|
|
|
|
|
|
|
|
richtextbox_->SetCaretPosition(selPos);
|
|
|
|
|
|
|
|
richtextbox_->BeginTextColour(color);
|
|
|
|
|
|
|
|
if (bold)
|
|
|
|
richtextbox_->BeginBold();
|
|
|
|
|
|
|
|
richtextbox_->WriteText(writeLine);
|
|
|
|
richtextbox_->Newline();
|
|
|
|
|
|
|
|
if (bold)
|
|
|
|
richtextbox_->EndBold();
|
|
|
|
|
|
|
|
richtextbox_->EndTextColour();
|
|
|
|
|
|
|
|
|
|
|
|
if ((pos == -1) || // true once
|
|
|
|
(pos == selPos) || // most likely
|
|
|
|
(abs(pos - selPos) < 5)) // ux
|
|
|
|
{
|
|
|
|
auto newPos = richtextbox_->GetLastPosition() - 1;
|
|
|
|
richtextbox_->ScrollIntoView(newPos, WXK_DOWN);
|
|
|
|
richtextbox_->SetCaretPosition(newPos);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
richtextbox_->SetCaretPosition(pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
//richtextbox_->Disable
|
|
|
|
//richtextbox_->EndParagraphSpacing();
|
|
|
|
}
|
|
|
|
|
|
|
|
ConsoleFrame::ConsoleFrame(const wxString &title, const wxPoint &pos, const wxSize &size)
|
|
|
|
: wxFrame(NULL, wxID_ANY, title, pos, size)
|
|
|
|
{
|
|
|
|
#if defined(AURORA_PLATFORM_WIN32)
|
|
|
|
bool useWin32DarkHack = DarkModeEnabled();
|
|
|
|
#else
|
|
|
|
bool useWin32DarkHack = false;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// 1080, 550
|
|
|
|
this->SetClientSize(this->FromDIP(wxSize(903, 434)));
|
|
|
|
|
|
|
|
menuBar_ = _new wxMenuBar;
|
|
|
|
if (!menuBar_) return;
|
|
|
|
|
|
|
|
{
|
|
|
|
wxMenu *menuFile = _new wxMenu;
|
|
|
|
if (!menuFile) return;
|
|
|
|
|
|
|
|
menuFile->Append(wxID_SAVE, "Export text log");
|
|
|
|
menuFile->AppendSeparator();
|
|
|
|
menuFile->Append(ID_OPENTXT, "Open text log");
|
|
|
|
menuFile->Append(ID_OPENBIN, "Open binary log");
|
|
|
|
|
|
|
|
menuBar_->Append(menuFile, "&Logs");
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
wxMenu *menuHelp = _new wxMenu;
|
|
|
|
if (!menuHelp) return;
|
|
|
|
|
|
|
|
menuHelp->Append(ID_BLACKBOX, "&Report application state to the black box");
|
|
|
|
menuHelp->Append(ID_WRITE_REPORT, "&[Internal] Write a bug report");
|
|
|
|
menuHelp->Append(ID_WRITE_REPORT, "&[Public] Write a bug report");
|
|
|
|
menuBar_->Append(menuHelp, "&Bugs");
|
|
|
|
}
|
|
|
|
|
|
|
|
richtextbox_ = _new wxRichTextCtrl(this, -1, wxEmptyString,
|
|
|
|
wxDefaultPosition, wxDefaultSize,
|
|
|
|
(useWin32DarkHack ? wxBORDER_NONE : 0) | wxTE_MULTILINE | wxRE_READONLY | wxRE_CENTER_CARET);
|
|
|
|
if (!richtextbox_) return;
|
|
|
|
|
|
|
|
commandbox_ = _new wxTextCtrl(this, -1, wxEmptyString,
|
|
|
|
wxDefaultPosition, wxDefaultSize,
|
|
|
|
(useWin32DarkHack ? wxBORDER_NONE : 0) | wxTE_PROCESS_ENTER);
|
|
|
|
if (!commandbox_) return;
|
|
|
|
|
|
|
|
if (useWin32DarkHack)
|
|
|
|
{
|
|
|
|
this->SetBackgroundColour(wxColour(0, 0, 0));
|
|
|
|
|
|
|
|
richtextbox_->SetBackgroundColour(wxColour(0, 0, 0));
|
|
|
|
richtextbox_->SetForegroundColour(wxColour(255, 255, 255));
|
|
|
|
|
|
|
|
commandbox_->SetBackgroundColour(wxColour(0, 0, 0));
|
|
|
|
commandbox_->SetForegroundColour(wxColour(255, 255, 255));
|
|
|
|
|
2021-07-01 10:42:48 +00:00
|
|
|
//this->Connect(wxEVT_SHOW, wxWindowCreateEventHandler(ConsoleFrame::OnShow));
|
2021-06-27 21:25:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
commandbox_->SetHint("Type a command here");
|
|
|
|
commandbox_->Connect(wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(ConsoleFrame::OnCmd));
|
2021-07-01 10:42:48 +00:00
|
|
|
//commandbox_->Bind(wxEVT_COMMAND_TEXT_ENTER, &ConsoleFrame::OnCmd, commandbox_);
|
2021-06-27 21:25:29 +00:00
|
|
|
|
|
|
|
sizer_ = _new wxBoxSizer(wxVERTICAL);
|
|
|
|
if (!sizer_) return;
|
|
|
|
|
|
|
|
sizer_->Add(richtextbox_, 3, wxEXPAND);
|
|
|
|
if (useWin32DarkHack)
|
|
|
|
{
|
|
|
|
sizer_->Add(NewSplitter(wxSize(4, 2), wxColour(0x38, 0x38, 0x38)), 0, wxEXPAND);
|
|
|
|
sizer_->Add(NewSplitter(wxSize(4, 1), wxColour(0, 0, 0)), 0, wxEXPAND);
|
|
|
|
}
|
|
|
|
sizer_->Add(commandbox_, 0, wxEXPAND | wxBOTTOM);
|
|
|
|
if (useWin32DarkHack)
|
|
|
|
{
|
|
|
|
sizer_->Add(NewSplitter(wxSize(4, 1), wxColour(0, 0, 0)), 0, wxEXPAND);
|
|
|
|
sizer_->Add(NewSplitter(wxSize(4, 2), wxColour(0x38, 0x38, 0x38)), 0, wxEXPAND);
|
|
|
|
}
|
|
|
|
|
|
|
|
SetSizer(sizer_);
|
|
|
|
SetMenuBar(menuBar_);
|
|
|
|
|
2021-07-01 10:42:48 +00:00
|
|
|
timer_.Bind(wxEVT_TIMER, &ConsoleFrame::OnPump, this);
|
|
|
|
timer_.Start(100);
|
2021-06-27 21:25:29 +00:00
|
|
|
gWxConsoleReady = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(AURORA_PLATFORM_WIN32)
|
|
|
|
#include <Uxtheme.h>
|
|
|
|
#include <Extensions/Win32/DarkTheme.hpp>
|
|
|
|
|
|
|
|
static bool DarkModeEnabled()
|
|
|
|
{
|
|
|
|
return Aurora::Extensions::Win32::g_darkModeSupported;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConsoleFrame::OnInit(wxWindowCreateEvent &event)
|
2021-07-01 10:42:48 +00:00
|
|
|
{
|
|
|
|
OnShow(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConsoleFrame::OnShow(wxWindowCreateEvent &event)
|
2021-06-27 21:25:29 +00:00
|
|
|
{
|
|
|
|
if (!DarkModeEnabled()) return;
|
|
|
|
|
|
|
|
auto handle = event.GetWindow()->GetHWND();
|
|
|
|
Aurora::Extensions::Win32::AllowDarkModeForWindow(handle, true);
|
|
|
|
|
|
|
|
if (Aurora::Extensions::Win32::_FlushMenuThemes)
|
|
|
|
Aurora::Extensions::Win32::_FlushMenuThemes();
|
|
|
|
|
|
|
|
SetWindowTheme(handle, L"DarkMode_Explorer", NULL);
|
|
|
|
SendMessageW(handle, WM_THEMECHANGED, 0, 0);
|
|
|
|
|
|
|
|
Aurora::Extensions::Win32::RefreshTitleBarThemeColor(handle);
|
|
|
|
UpdateWindow(handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
2021-07-01 10:42:48 +00:00
|
|
|
void ConsoleFrame::OnInit(wxWindowCreateEvent &event)
|
|
|
|
{}
|
|
|
|
|
|
|
|
void ConsoleFrame::OnShow(wxWindowCreateEvent &event)
|
|
|
|
{}
|
|
|
|
|
2021-06-27 21:25:29 +00:00
|
|
|
static bool DarkModeEnabled()
|
|
|
|
{
|
|
|
|
return Aurora::Build::EPlatform == Aurora::Build::EPlatform::kPlatformLinux;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void ConsoleFrame::OnExit(wxCommandEvent &event)
|
|
|
|
{
|
|
|
|
Close(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConsoleFrame::OnAbout(wxCommandEvent &event)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConsoleFrame::OnHello(wxCommandEvent &event)
|
|
|
|
{
|
|
|
|
LogGame("nani?!");
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConsoleFrame::OnBugWrite(wxCommandEvent &event)
|
|
|
|
{
|
|
|
|
Aurora::Processes::OpenUri(gRuntimeConfig.console.supportInternal);
|
|
|
|
}
|
|
|
|
|
2021-07-01 10:42:48 +00:00
|
|
|
namespace Aurora::Console::ConsoleWxWidgets
|
|
|
|
{
|
|
|
|
static void WxWidgetsPump();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConsoleFrame::OnPump(wxTimerEvent &event)
|
|
|
|
{
|
|
|
|
Aurora::Console::ConsoleWxWidgets::WxWidgetsPump();
|
|
|
|
}
|
2021-06-27 21:25:29 +00:00
|
|
|
|
|
|
|
namespace Aurora::Console::ConsoleWxWidgets
|
|
|
|
{
|
|
|
|
static wxInitializer *gInitializer;
|
|
|
|
|
|
|
|
static bool UseWxConsole()
|
|
|
|
{
|
|
|
|
if (gRuntimeConfig.console.disableAll)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GetConsoleWindow())
|
|
|
|
{
|
|
|
|
if (!gRuntimeConfig.console.forceToolKitWindow)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool WxWidgetsInit()
|
|
|
|
{
|
|
|
|
wxApp::SetInstance(_new ConsoleApp());
|
|
|
|
|
|
|
|
#if defined(AURORA_PLATFORM_WIN32) || true
|
|
|
|
std::wstring auroraw(L"Aurora");
|
|
|
|
static wxChar *s = auroraw.data();
|
|
|
|
static int count = 1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
gInitializer = new wxInitializer(count, &s);
|
|
|
|
|
|
|
|
if (!gInitializer->IsOk())
|
|
|
|
{
|
|
|
|
#if wxUSE_LOG
|
|
|
|
delete wxLog::SetActiveTarget(NULL);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
if (!wxTheApp->CallOnInit())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
wxTheApp->OnUnhandledException();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void WxWidgetsRequestExit()
|
|
|
|
{
|
|
|
|
if (!gMutex)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Threading::LockGuardPtr re(gMutex.get()); // pupose two of the mutex: locking deconstruction/gWxConsoleReady
|
|
|
|
// its a horible hack, but -
|
|
|
|
// 1) our dtor comes before the final apps class, and
|
|
|
|
// 2) the app will deregister the top window before the dtor
|
|
|
|
// which means
|
|
|
|
// `if (!gWxConsoleReady) return;` under lock
|
|
|
|
// -> gWxConsoleReady must be true, and `wxTheApp->GetTopWindow`'s dtor is locked,
|
|
|
|
// even as a remote thread, we should be able to do ipc given a dtor pinned object safely
|
|
|
|
// the shitty wiki doesn't describe how we're supposed to dispatch cmds to the os loop (w/o a window)
|
|
|
|
|
|
|
|
if (!gWxConsoleReady) return;
|
|
|
|
|
|
|
|
auto window = wxTheApp->GetTopWindow();
|
|
|
|
if (!window) return;
|
|
|
|
|
|
|
|
window->GetEventHandler()->CallAfter([]()
|
|
|
|
{
|
|
|
|
wxTheApp->Exit();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
static Aurora::Threading::Threads::ThreadUnique_t gWxWidgetsThread;
|
|
|
|
|
|
|
|
static void WxWidgetsThreadMain()
|
|
|
|
{
|
|
|
|
if (!WxWidgetsInit())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
wxTheApp->OnRun();
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
wxTheApp->OnUnhandledException();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Init()
|
|
|
|
{
|
|
|
|
if (!UseWxConsole())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
gMutex = Aurora::Threading::Primitives::MutexUnique();
|
|
|
|
|
|
|
|
Aurora::Console::Hooks::AddHook([&](const Aurora::Console::ConsoleMessage &string) -> void
|
|
|
|
{
|
|
|
|
gMutex->Lock();
|
|
|
|
gPendingLines.push_back(string);
|
|
|
|
gMutex->Unlock();
|
|
|
|
});
|
|
|
|
|
|
|
|
Aurora::Threading::Threads::AbstractThreadVectors handler;
|
|
|
|
handler.DoRun = [](Aurora::Threading::Threads::IAuroraThread *)
|
|
|
|
{
|
|
|
|
WxWidgetsThreadMain();
|
|
|
|
};
|
|
|
|
|
|
|
|
gWxWidgetsThread = Aurora::Threading::Threads::ThreadUnique(handler);
|
|
|
|
if (!gWxWidgetsThread)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
gWxWidgetsThread->SetName("WxWidgets");
|
|
|
|
gWxWidgetsThread->Run();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void WxWidgetsPump()
|
|
|
|
{
|
|
|
|
// called from within WxWidget main loop, do not worry about locking is ready
|
|
|
|
// we _know_ the wxwidget app is referenceable
|
|
|
|
|
|
|
|
if (!wxTheApp) return;
|
|
|
|
if (!gWxConsoleReady) return;
|
|
|
|
|
|
|
|
AuList<Console::ConsoleMessage> lines;
|
|
|
|
{
|
|
|
|
Aurora::Threading::LockGuardPtr re(gMutex.get());
|
|
|
|
lines = std::exchange(gPendingLines, {});
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const auto& line : lines)
|
|
|
|
{
|
|
|
|
gWxFrame->WriteLine(line);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Pump()
|
|
|
|
{
|
2021-07-01 10:42:48 +00:00
|
|
|
#if 0
|
2021-06-27 21:25:29 +00:00
|
|
|
Aurora::Threading::LockGuardPtr re(gMutex.get());
|
|
|
|
|
|
|
|
if (!gWxConsoleReady) return;
|
|
|
|
|
|
|
|
wxTheApp->GetTopWindow()->GetEventHandler()->CallAfter([]()
|
|
|
|
{
|
|
|
|
WxWidgetsPump();
|
|
|
|
});
|
2021-07-01 10:42:48 +00:00
|
|
|
#endif
|
2021-06-27 21:25:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Exit()
|
|
|
|
{
|
|
|
|
WxWidgetsRequestExit();
|
|
|
|
|
|
|
|
gWxWidgetsThread.reset();
|
|
|
|
|
|
|
|
auto wxHandle = wxTheApp;
|
|
|
|
if (wxHandle)
|
|
|
|
{
|
|
|
|
delete wxHandle;
|
|
|
|
}
|
|
|
|
|
|
|
|
gMutex.reset();
|
|
|
|
gPendingLines.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
namespace Aurora::Console::ConsoleWxWidgets
|
|
|
|
{
|
|
|
|
void Init()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
void Pump()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
void Exit()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|