Commit 8b57e7d6 authored by Gauthier Quesnel's avatar Gauthier Quesnel
Browse files

gui: add a window logging system

parent 3bde1162
Pipeline #11033 passed with stage
in 47 seconds
......@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(irritator-gui VERSION 0.1.0 LANGUAGES CXX)
set(gui_sources
imnodes.cpp imnodes.hpp node-editor.cpp
imnodes.cpp imnodes.hpp window-logger.cpp node-editor.cpp
${PROJECT_SOURCE_DIR}/../../external/imgui/imgui.cpp
${PROJECT_SOURCE_DIR}/../../external/imgui/imgui.h
${PROJECT_SOURCE_DIR}/../../external/imgui/imgui_demo.cpp
......
......@@ -5,6 +5,8 @@
#ifndef ORG_VLEPROJECT_IRRITATOR_APP_GUI_2020
#define ORG_VLEPROJECT_IRRITATOR_APP_GUI_2020
#include <imgui.h>
namespace irt {
void
......@@ -16,6 +18,22 @@ node_editor_show();
void
node_editor_shutdown();
struct window_logger
{
ImGuiTextBuffer buffer;
ImGuiTextFilter filter;
ImVector<int> line_offsets;
bool auto_scroll = true;
bool scroll_to_bottom = false;
void clear() noexcept;
void log(const int level, const char* fmt, ...) IM_FMTARGS(3);
void log(const int level, const char* fmt, va_list args) IM_FMTLIST(3);
void show(bool* is_show);
};
} // namespace irt
#endif
......@@ -17,6 +17,8 @@
namespace irt {
window_logger log_w;
enum class simulation_status
{
success,
......@@ -87,12 +89,14 @@ run_simulation(simulation& sim,
{
current = begin;
if (irt::is_bad(sim.initialize(current))) {
log_w.log(3, "Simulation initialization failure");
st = simulation_status::internal_error;
return;
}
do {
if (!is_success(sim.run(current))) {
log_w.log(3, "Simulation run failure");
st = simulation_status::internal_error;
return;
}
......@@ -130,7 +134,7 @@ struct editor
model_id get_model(int index) const noexcept
{
auto *mdl = sim.models.try_to_get(static_cast<u32>(index));
auto* mdl = sim.models.try_to_get(static_cast<u32>(index));
return sim.models.get_id(mdl);
}
......@@ -708,13 +712,12 @@ show_editor(const char* editor_name, editor& ed)
if (ImGui::BeginMenu("Examples")) {
if (ImGui::MenuItem("Insert Lotka Volterra model")) {
if (is_bad(ed.initialize_lotka_volterra()))
fmt::print("Error: fail to initialize a lotka volterra");
log_w.log(3, "Fail to initialize a Lotka Volterra");
}
if (ImGui::MenuItem("Insert Izzhikevitch model")) {
if (ImGui::MenuItem("Insert Izhikevitch model")) {
if (is_bad(ed.initialize_izhikevitch()))
fmt::print(stderr,
"fail to initialize an Izzhikevitch model\n");
log_w.log(3, "Fail to initialize an Izhikevitch model");
}
ImGui::EndMenu();
......@@ -724,7 +727,7 @@ show_editor(const char* editor_name, editor& ed)
}
ImGui::Text("X -- delete selected nodes and/or connections /"
" D -- duplicate selected nodes and/or connections ");
" D -- duplicate selected nodes");
imnodes::BeginNodeEditor();
......@@ -758,8 +761,7 @@ show_editor(const char* editor_name, editor& ed)
if (ed.sim.none_models.can_alloc(1u) &&
ed.sim.models.can_alloc(1u)) {
auto& mdl = ed.sim.none_models.alloc();
ed.sim.alloc(
mdl, ed.sim.none_models.get_id(mdl), "none");
ed.sim.alloc(mdl, ed.sim.none_models.get_id(mdl), "none");
}
}
......@@ -767,9 +769,8 @@ show_editor(const char* editor_name, editor& ed)
if (ed.sim.integrator_models.can_alloc(1u) &&
ed.sim.models.can_alloc(1u)) {
auto& mdl = ed.sim.integrator_models.alloc();
ed.sim.alloc(mdl,
ed.sim.integrator_models.get_id(mdl),
"integrator");
ed.sim.alloc(
mdl, ed.sim.integrator_models.get_id(mdl), "integrator");
}
}
......@@ -777,9 +778,8 @@ show_editor(const char* editor_name, editor& ed)
if (ed.sim.quantifier_models.can_alloc(1u) &&
ed.sim.models.can_alloc(1u)) {
auto& mdl = ed.sim.quantifier_models.alloc();
ed.sim.alloc(mdl,
ed.sim.quantifier_models.get_id(mdl),
"quantifier");
ed.sim.alloc(
mdl, ed.sim.quantifier_models.get_id(mdl), "quantifier");
}
}
......@@ -787,8 +787,7 @@ show_editor(const char* editor_name, editor& ed)
if (ed.sim.adder_2_models.can_alloc(1u) &&
ed.sim.models.can_alloc(1u)) {
auto& mdl = ed.sim.adder_2_models.alloc();
ed.sim.alloc(
mdl, ed.sim.adder_2_models.get_id(mdl), "adder");
ed.sim.alloc(mdl, ed.sim.adder_2_models.get_id(mdl), "adder");
}
}
......@@ -796,8 +795,7 @@ show_editor(const char* editor_name, editor& ed)
if (ed.sim.adder_3_models.can_alloc(1u) &&
ed.sim.models.can_alloc(1u)) {
auto& mdl = ed.sim.adder_3_models.alloc();
ed.sim.alloc(
mdl, ed.sim.adder_3_models.get_id(mdl), "adder");
ed.sim.alloc(mdl, ed.sim.adder_3_models.get_id(mdl), "adder");
}
}
......@@ -805,8 +803,7 @@ show_editor(const char* editor_name, editor& ed)
if (ed.sim.adder_4_models.can_alloc(1u) &&
ed.sim.models.can_alloc(1u)) {
auto& mdl = ed.sim.adder_4_models.alloc();
ed.sim.alloc(
mdl, ed.sim.adder_4_models.get_id(mdl), "adder");
ed.sim.alloc(mdl, ed.sim.adder_4_models.get_id(mdl), "adder");
}
}
......@@ -814,8 +811,7 @@ show_editor(const char* editor_name, editor& ed)
if (ed.sim.mult_2_models.can_alloc(1u) &&
ed.sim.models.can_alloc(1u)) {
auto& mdl = ed.sim.mult_2_models.alloc();
ed.sim.alloc(
mdl, ed.sim.mult_2_models.get_id(mdl), "mult");
ed.sim.alloc(mdl, ed.sim.mult_2_models.get_id(mdl), "mult");
}
}
......@@ -823,8 +819,7 @@ show_editor(const char* editor_name, editor& ed)
if (ed.sim.mult_3_models.can_alloc(1u) &&
ed.sim.models.can_alloc(1u)) {
auto& mdl = ed.sim.mult_3_models.alloc();
ed.sim.alloc(
mdl, ed.sim.mult_3_models.get_id(mdl), "mult");
ed.sim.alloc(mdl, ed.sim.mult_3_models.get_id(mdl), "mult");
}
}
......@@ -832,8 +827,7 @@ show_editor(const char* editor_name, editor& ed)
if (ed.sim.mult_4_models.can_alloc(1u) &&
ed.sim.models.can_alloc(1u)) {
auto& mdl = ed.sim.mult_4_models.alloc();
ed.sim.alloc(
mdl, ed.sim.mult_4_models.get_id(mdl), "mult");
ed.sim.alloc(mdl, ed.sim.mult_4_models.get_id(mdl), "mult");
}
}
......@@ -841,8 +835,7 @@ show_editor(const char* editor_name, editor& ed)
if (ed.sim.counter_models.can_alloc(1u) &&
ed.sim.models.can_alloc(1u)) {
auto& mdl = ed.sim.counter_models.alloc();
ed.sim.alloc(
mdl, ed.sim.counter_models.get_id(mdl), "counter");
ed.sim.alloc(mdl, ed.sim.counter_models.get_id(mdl), "counter");
}
}
......@@ -850,9 +843,8 @@ show_editor(const char* editor_name, editor& ed)
if (ed.sim.generator_models.can_alloc(1u) &&
ed.sim.models.can_alloc(1u)) {
auto& mdl = ed.sim.generator_models.alloc();
ed.sim.alloc(mdl,
ed.sim.generator_models.get_id(mdl),
"generator");
ed.sim.alloc(
mdl, ed.sim.generator_models.get_id(mdl), "generator");
}
}
......@@ -860,9 +852,8 @@ show_editor(const char* editor_name, editor& ed)
if (ed.sim.constant_models.can_alloc(1u) &&
ed.sim.models.can_alloc(1u)) {
auto& mdl = ed.sim.constant_models.alloc();
ed.sim.alloc(mdl,
ed.sim.constant_models.get_id(mdl),
"constant");
ed.sim.alloc(
mdl, ed.sim.constant_models.get_id(mdl), "constant");
}
}
......@@ -870,8 +861,7 @@ show_editor(const char* editor_name, editor& ed)
if (ed.sim.cross_models.can_alloc(1u) &&
ed.sim.models.can_alloc(1u)) {
auto& mdl = ed.sim.cross_models.alloc();
ed.sim.alloc(
mdl, ed.sim.cross_models.get_id(mdl), "cross");
ed.sim.alloc(mdl, ed.sim.cross_models.get_id(mdl), "cross");
}
}
......@@ -879,14 +869,13 @@ show_editor(const char* editor_name, editor& ed)
if (ed.sim.time_func_models.can_alloc(1u) &&
ed.sim.models.can_alloc(1u)) {
auto& mdl = ed.sim.time_func_models.alloc();
ed.sim.alloc(mdl,
ed.sim.time_func_models.get_id(mdl),
"time-func");
ed.sim.alloc(
mdl, ed.sim.time_func_models.get_id(mdl), "time-func");
}
}
ImGui::EndPopup();
//imnodes::SetNodeScreenSpacePos(new_node, click_pos);
// imnodes::SetNodeScreenSpacePos(new_node, click_pos);
}
ImGui::PopStyleVar();
......@@ -914,9 +903,8 @@ show_editor(const char* editor_name, editor& ed)
std::fill_n(selected_links.data(), selected_links.size(), -1);
imnodes::GetSelectedLinks(selected_links.data());
std::sort(selected_links.begin(),
selected_links.end(),
std::less<int>());
std::sort(
selected_links.begin(), selected_links.end(), std::less<int>());
for (size_t i = 0; i != selected_links.size(); ++i)
assert(selected_links[i] != -1);
......@@ -926,11 +914,14 @@ show_editor(const char* editor_name, editor& ed)
int current_link_id = 0;
output_port* o_port = nullptr;
while (ed.sim.output_ports.next(o_port) && link_id_to_delete != -1) {
while (ed.sim.output_ports.next(o_port) &&
link_id_to_delete != -1) {
for (const auto dst : o_port->connections) {
if (auto* i_port = ed.sim.input_ports.try_to_get(dst); i_port) {
if (auto* i_port = ed.sim.input_ports.try_to_get(dst);
i_port) {
if (current_link_id == link_id_to_delete) {
ed.sim.disconnect(ed.sim.output_ports.get_id(o_port), dst);
ed.sim.disconnect(
ed.sim.output_ports.get_id(o_port), dst);
++i;
......@@ -1065,7 +1056,7 @@ void
node_editor_initialize()
{
if (!ed.initialize()) {
fmt::print(stderr, "node_editor_initialize failed\n");
log_w.log(3, "Fail to initialize node editor\n");
return;
}
......@@ -1076,7 +1067,10 @@ void
node_editor_show()
{
if (ed.initialized)
show_editor("editor1", ed);
show_editor("Editor 1", ed);
static bool show_log = true;
log_w.show(&show_log);
}
void
......
// Copyright (c) 2020 INRA Distributed under the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include "gui.hpp"
namespace irt {
void
window_logger::clear() noexcept
{
buffer.clear();
line_offsets.clear();
line_offsets.push_back(0);
}
static const char* log_prefix[] = { "[emergency]", "[alert]", "[critical]",
"[error]", "[warning]", "[notice]",
"[info]", "[debug]" };
void
window_logger::log(const int level, const char* fmt, ...)
{
auto old_size = buffer.size();
va_list args;
va_start(args, fmt);
buffer.append(log_prefix[level]);
buffer.appendfv(fmt, args);
va_end(args);
for (auto new_size = buffer.size(); old_size < new_size; ++old_size)
if (buffer[old_size] == '\n')
line_offsets.push_back(old_size + 1);
if (auto_scroll)
scroll_to_bottom = true;
}
void
window_logger::log(const int level, const char* fmt, va_list args)
{
auto old_size = buffer.size();
buffer.append(log_prefix[level]);
buffer.appendfv(fmt, args);
for (auto new_size = buffer.size(); old_size < new_size; ++old_size)
if (buffer[old_size] == '\n')
line_offsets.push_back(old_size + 1);
if (auto_scroll)
scroll_to_bottom = true;
}
void
window_logger::show(bool* is_show)
{
ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Log", is_show)) {
ImGui::End();
return;
}
if (ImGui::BeginPopup("Options")) {
if (ImGui::Checkbox("Auto-scroll", &auto_scroll))
if (auto_scroll)
scroll_to_bottom = true;
ImGui::EndPopup();
}
if (ImGui::Button("Options"))
ImGui::OpenPopup("Options");
ImGui::SameLine();
bool need_clear = ImGui::Button("Clear");
ImGui::SameLine();
bool need_copy = ImGui::Button("Copy");
ImGui::SameLine();
filter.Draw("Filter", -100.0f);
ImGui::Separator();
ImGui::BeginChild(
"scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);
if (need_clear)
clear();
if (need_copy)
ImGui::LogToClipboard();
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
const char* buf = buffer.begin();
const char* buf_end = buffer.end();
if (filter.IsActive()) {
for (auto line_no = 0; line_no < line_offsets.Size; line_no++) {
const char* line_start = buf + line_offsets[line_no];
const char* line_end = (line_no + 1 < line_offsets.Size)
? (buf + line_offsets[line_no + 1] - 1)
: buf_end;
if (filter.PassFilter(line_start, line_end))
ImGui::TextUnformatted(line_start, line_end);
}
} else {
ImGuiListClipper clipper;
clipper.Begin(line_offsets.Size);
while (clipper.Step()) {
for (int line_no = clipper.DisplayStart;
line_no < clipper.DisplayEnd;
line_no++) {
const char* line_start = buf + line_offsets[line_no];
const char* line_end = (line_no + 1 < line_offsets.Size)
? (buf + line_offsets[line_no + 1] - 1)
: buf_end;
ImGui::TextUnformatted(line_start, line_end);
}
}
clipper.End();
}
ImGui::PopStyleVar();
if (scroll_to_bottom)
ImGui::SetScrollHereY(1.0f);
scroll_to_bottom = false;
ImGui::EndChild();
ImGui::End();
}
} // irt
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment