1 // Copyright (c) 2010, Amar Takhar
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright notice,
8 // this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above copyright notice,
10 // this list of conditions and the following disclaimer in the documentation
11 // and/or other materials provided with the distribution.
12 // * Neither the name of the Aegisub Group nor the names of its contributors
13 // may be used to endorse or promote products derived from this software
14 // without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 // POSSIBILITY OF SUCH DAMAGE.
27 //
28 // Aegisub Project http://www.aegisub.org/
29
30 #include "compat.h"
31 #include "dialog_manager.h"
32 #include "format.h"
33 #include "include/aegisub/context.h"
34
35 #include <libaegisub/dispatch.h>
36 #include <libaegisub/log.h>
37
38 #include <ctime>
39 #include <wx/button.h>
40 #include <wx/dialog.h>
41 #include <wx/sizer.h>
42 #include <wx/stattext.h>
43 #include <wx/textctrl.h>
44
45 namespace {
46 class EmitLog final : public agi::log::Emitter {
47 wxTextCtrl *text_ctrl;
48 public:
EmitLog(wxTextCtrl * t)49 EmitLog(wxTextCtrl *t)
50 : text_ctrl(t)
51 {
52 for (auto const& sm : agi::log::log->GetMessages())
53 log(sm);
54 }
55
log(agi::log::SinkMessage const & sm)56 void log(agi::log::SinkMessage const& sm) override {
57 time_t time = sm.time / 1000000000;
58 #ifndef _WIN32
59 tm tmtime;
60 localtime_r(&time, &tmtime);
61 auto log = fmt_wx("%c %02d:%02d:%02d %-6d <%-25s> [%s:%s:%d] %s\n",
62 agi::log::Severity_ID[sm.severity],
63 tmtime.tm_hour,
64 tmtime.tm_min,
65 tmtime.tm_sec,
66 (sm.time % 1000000000),
67 sm.section,
68 sm.file,
69 sm.func,
70 sm.line,
71 sm.message);
72 #else
73 auto log = fmt_wx("%c %-6ld <%-25s> [%s:%s:%d] %s\n",
74 agi::log::Severity_ID[sm.severity],
75 (sm.time % 1000000000),
76 sm.section,
77 sm.file,
78 sm.func,
79 sm.line,
80 sm.message);
81 #endif
82
83 if (wxIsMainThread())
84 text_ctrl->AppendText(log);
85 else
86 agi::dispatch::Main().Async([=]{ text_ctrl->AppendText(log); });
87 }
88 };
89
90 class LogWindow : public wxDialog {
91 agi::log::Emitter *emit_log;
92
93 public:
94 LogWindow(agi::Context *c);
95 ~LogWindow();
96 };
97
LogWindow(agi::Context * c)98 LogWindow::LogWindow(agi::Context *c)
99 : wxDialog(c->parent, -1, _("Log window"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX | wxRESIZE_BORDER)
100 {
101 wxTextCtrl *text_ctrl = new wxTextCtrl(this, -1, "", wxDefaultPosition, wxSize(700,300), wxTE_MULTILINE|wxTE_READONLY);
102 text_ctrl->SetDefaultStyle(wxTextAttr(wxNullColour, wxNullColour, wxFont(8, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL)));
103
104 wxSizer *sizer = new wxBoxSizer(wxVERTICAL);
105 sizer->Add(text_ctrl, wxSizerFlags(1).Expand().Border());
106 sizer->Add(new wxButton(this, wxID_OK), wxSizerFlags(0).Border().Right());
107 SetSizerAndFit(sizer);
108
109 agi::log::log->Subscribe(std::unique_ptr<agi::log::Emitter>(emit_log = new EmitLog(text_ctrl)));
110 }
111
~LogWindow()112 LogWindow::~LogWindow() {
113 agi::log::log->Unsubscribe(emit_log);
114 }
115 }
116
ShowLogWindow(agi::Context * c)117 void ShowLogWindow(agi::Context *c) {
118 c->dialog->Show<LogWindow>(c);
119 }
120