SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
LogWindow.cpp
Go to the documentation of this file.
1 #include "LogWindow.h"
2 #include <imgui_internal.h>
3 
4 LogWindow::LogWindow(int screenWidth, int screenHeight, ImFont* fontHeading, ImFont* fontText)
5  : _screenW(screenWidth),
6  _screenH(screenHeight),
7  _fontHeading(fontHeading),
8  _fontText(fontText)
9 {
10  _autoScroll = true;
11  clear();
12 }
13 
15 {
16  _buf.clear();
17  _lineOffsets.clear();
18  _lineOffsets.push_back(0);
19 }
20 
21 void LogWindow::post(const std::string& message)
22 {
23  addLog(message.c_str());
24 }
25 
26 void LogWindow::draw(const char* title, bool* p_open)
27 {
28 
29  float framePadding = 0.02f * _screenH;
30  ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(framePadding, framePadding));
31  ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.f);
32  ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(framePadding, framePadding));
33  ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(framePadding, framePadding));
34  ImGui::PushStyleVar(ImGuiStyleVar_ScrollbarSize, 2.f * framePadding + _fontHeading->FontSize);
35 
36  ImGui::PushFont(_fontHeading);
37  if (!ImGui::Begin(title, p_open))
38  {
39  ImGui::End();
40  ImGui::PopStyleVar(5);
41  ImGui::PopFont();
42  return;
43  }
44  // pop heading font
45  ImGui::PopFont();
46  ImGui::PushFont(_fontText);
47 
48  // Options menu
49  if (ImGui::BeginPopup("Options"))
50  {
51  ImGui::Checkbox("Auto-scroll", &_autoScroll);
52  ImGui::EndPopup();
53  }
54 
55  // Main window
56  if (ImGui::Button("Options"))
57  ImGui::OpenPopup("Options");
58  ImGui::SameLine();
59  bool clearIt = ImGui::Button("Clear");
60  ImGui::SameLine();
61  bool copy = ImGui::Button("Copy");
62  ImGui::SameLine();
63  _filter.Draw("Filter", -100.0f);
64 
65  ImGui::Separator();
66  ImGui::BeginChild("scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);
67 
68  if (clearIt)
69  clear();
70  if (copy)
71  ImGui::LogToClipboard();
72 
73  ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
74  const char* buf = _buf.begin();
75  const char* buf_end = _buf.end();
76  if (_filter.IsActive())
77  {
78  // In this example we don't use the clipper when _filter is enabled.
79  // This is because we don't have a random access on the result on our filter.
80  // A real application processing logs with ten of thousands of entries may want to store the result of search/filter.
81  // especially if the filtering function is not trivial (e.g. reg-exp).
82  for (int line_no = 0; line_no < _lineOffsets.Size; line_no++)
83  {
84  const char* line_start = buf + _lineOffsets[line_no];
85  const char* line_end = (line_no + 1 < _lineOffsets.Size) ? (buf + _lineOffsets[line_no + 1] - 1) : buf_end;
86  if (_filter.PassFilter(line_start, line_end))
87  ImGui::TextUnformatted(line_start, line_end);
88  }
89  }
90  else
91  {
92  // The simplest and easy way to display the entire buffer:
93  // ImGui::TextUnformatted(buf_begin, buf_end);
94  // And it'll just work. TextUnformatted() has specialization for large blob of text and will fast-forward to skip non-visible lines.
95  // Here we instead demonstrate using the clipper to only process lines that are within the visible area.
96  // If you have tens of thousands of items and their processing cost is non-negligible, coarse clipping them on your side is recommended.
97  // Using ImGuiListClipper requires A) random access into your data, and B) items all being the same height,
98  // both of which we can handle since we an array pointing to the beginning of each line of text.
99  // When using the filter (in the block of code above) we don't have random access into the data to display anymore, which is why we don't use the clipper.
100  // Storing or skimming through the search result would make it possible (and would be recommended if you want to search through tens of thousands of entries)
101  ImGuiListClipper clipper;
102  clipper.Begin(_lineOffsets.Size);
103  while (clipper.Step())
104  {
105  for (int line_no = clipper.DisplayStart; line_no < clipper.DisplayEnd; line_no++)
106  {
107  const char* line_start = buf + _lineOffsets[line_no];
108  const char* line_end = (line_no + 1 < _lineOffsets.Size) ? (buf + _lineOffsets[line_no + 1] - 1) : buf_end;
109  ImGui::TextUnformatted(line_start, line_end);
110  }
111  }
112  clipper.End();
113  }
114  ImGui::PopStyleVar();
115 
116  if (_autoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY())
117  ImGui::SetScrollHereY(1.0f);
118 
119  ImGui::EndChild();
120  ImGui::End();
121 
122  ImGui::PopStyleVar(5);
123  ImGui::PopFont();
124 }
125 
126 void LogWindow::addLog(const char* fmt, ...) IM_FMTARGS(2)
127 {
128  int old_size = _buf.size();
129  va_list args;
130  va_start(args, fmt);
131  _buf.appendfv(fmt, args);
132  va_end(args);
133  for (int new_size = _buf.size(); old_size < new_size; old_size++)
134  if (_buf[old_size] == '\n')
135  _lineOffsets.push_back(old_size + 1);
136 }
ImVector< int > _lineOffsets
Definition: LogWindow.h:23
void clear()
Definition: LogWindow.cpp:14
ImFont * _fontHeading
Definition: LogWindow.h:30
ImGuiTextBuffer _buf
Definition: LogWindow.h:21
ImFont * _fontText
Definition: LogWindow.h:29
void addLog(const char *fmt,...) IM_FMTARGS(2)
Definition: LogWindow.cpp:126
LogWindow(int screenWidth, int screenHeight, ImFont *fontHeading, ImFont *fontText)
Definition: LogWindow.cpp:4
int _screenH
Definition: LogWindow.h:27
void draw(const char *title, bool *p_open=NULL)
Definition: LogWindow.cpp:26
void post(const std::string &message) override
Definition: LogWindow.cpp:21
bool _autoScroll
Definition: LogWindow.h:24
ImGuiTextFilter _filter
Definition: LogWindow.h:22