/
ConsoleView.cpp
97 lines (77 loc) · 2.26 KB
/
ConsoleView.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include "ConsoleView.h"
#include "imodule.h"
#include <boost/algorithm/string/replace.hpp>
namespace wxutil
{
ConsoleView::ConsoleView(wxWindow* parent) :
wxTextCtrl(parent, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_RICH2|wxTE_READONLY),
_errorAttr(*wxRED),
_warningAttr(wxColour(128, 128, 0)),
_standardAttr(*wxBLACK)
{
_lineBuffer.reserve(512);
}
void ConsoleView::appendText(const std::string& text, TextMode mode)
{
// The text usually arrives in single characters at a time
// Directly writing to the wxTextCtrl is awfully slow, so let's do some buffering
// In case the textmode changes, we need to flush the line
if (_bufferMode != mode)
{
flushLine();
}
// Write to the buffer first
_bufferMode = mode;
_buffer.append(text);
// Once we hit a single newline, flush the line
if (text == "\n")
{
flushLine();
}
// Request an idle callback on the GUI thread
requestIdleCallback();
}
void ConsoleView::flushLine()
{
if (!_buffer.empty())
{
std::lock_guard<std::mutex> lock(_lineBufferMutex);
_lineBuffer.push_back(std::make_pair(_bufferMode, std::string()));
_lineBuffer.back().second.swap(_buffer);
}
}
void ConsoleView::onIdle()
{
// Idle events occur in the main thread - prevent interrupting
// threads in the middle of a line
std::lock_guard<std::mutex> idleLock(
module::GlobalModuleRegistry().getApplicationContext().getStreamLock());
flushLine();
std::lock_guard<std::mutex> lock(_lineBufferMutex);
if (_lineBuffer.empty()) return;
for (LineBuffer::value_type& pair : _lineBuffer)
{
switch (pair.first)
{
case ModeStandard:
SetDefaultStyle(_standardAttr);
break;
case ModeWarning:
SetDefaultStyle(_warningAttr);
break;
case ModeError:
SetDefaultStyle(_errorAttr);
break;
default:
SetDefaultStyle(_standardAttr);
};
// Replace NULL characters
boost::algorithm::replace_all(pair.second, "\0", "NULL");
// Insert at the end of the text buffer
AppendText(pair.second);
}
_lineBuffer.clear();
// Scroll to bottom
ShowPosition(GetLastPosition());
}
} // namespace