miggrating the logger to a new system

This commit is contained in:
Joud Kandeel
2026-04-11 22:09:23 +02:00
parent 852d1cbf93
commit e75d6ce06c
4 changed files with 218 additions and 6 deletions

View File

@@ -0,0 +1,160 @@
#include "CLogger.hpp"
#include "IEvent.hpp"
namespace mce::tui {
CLogger::CLogger(core::QEventBus& qBus) : Panel(qBus) {}
CLogger::CLogger(core::QEventBus& qBus, const std::string& title,
const uint16_t width, const uint16_t height,
core::FunctionContainer fc)
: Panel(qBus, title, width, height, fc) {
//outputBuffer.reserve(MAX_BUFFER_SIZE);
qBus.subscribe<event::LoggerOutput>([this](const event::LoggerOutput& e) {
if (e.channel == Panel::getProperties().title) {
e.severity;
log(char(e.severity) + e.msg);
}
});
}
eastl::shared_ptr<CLogger> CLogger::createInstance(core::QEventBus& qBus,
const std::string& title, const uint16_t width, const uint16_t height,
core::FunctionContainer fc) {
auto component = eastl::make_shared<CLogger>(qBus, title, width, height, fc);
component->setPosition(1, 1);
return component;
}
void CLogger::log(const std::string& message) {
std::lock_guard<std::mutex> lock(bufferMutex);
if (outputBuffer.size() >= MAX_BUFFER_SIZE) {
outputBuffer.pop_front(); // Remove oldest message
}
outputBuffer.push_back(message); // Add new message at the end
// Auto scroll to bottom when new message arrives (only if not dragging)
if (!isDraggingScrollbar)
scrollToBottom();
}
void CLogger::onRender(RenderTarget* out) {
Panel::onRender(out);
Panel::clear(0x2588, 0x11);
std::lock_guard<std::mutex> lock(bufferMutex);
const uint16_t w = getSize().x;
const uint16_t h = getSize().y;
if (w <= 2 || h <= 2) return;
const size_t totalLines = outputBuffer.size();
const int maxScroll = std::max(0, (int)totalLines - (int)h);
verticalScroll = std::clamp(verticalScroll, 0, maxScroll);
if (Panel::isFocused()) {
// Draw the actual log lines
for (uint16_t y = 0; y < h; ++y) {
size_t lineIdx = verticalScroll + y;
if (lineIdx >= totalLines)
break;
const std::string& text = outputBuffer[lineIdx];
if (!text.empty() && horizontalScroll < (int)text.size()) {
std::string visiblePart = text.substr(horizontalScroll,
std::min((size_t)w - 1, text.size() - horizontalScroll));
char color = visiblePart[0];
Panel::renderText(0, y, visiblePart.data() + 1, 0x10 | color); // This is correct
}
}
// Vertical Scrollbar (using renderLine or loop with renderText)
if (maxScroll > 0) {
int thumbHeight = std::max(2, (h * h) / std::max(1, (int)totalLines));
int thumbPos = (verticalScroll * (h - thumbHeight)) / std::max(1, maxScroll);
// You can use renderLine for the background of scrollbar
Panel::renderLine(w - 1, 0, w - 1, h - 1, 0x2502, 0x07);
// Draw thumb
Panel::renderLine(w - 1, thumbPos, w - 1, thumbPos + thumbHeight - 1, 0x2593, 0x06);
}
else {
Panel::renderLine(w - 1, 0, w - 1, h - 1, 0x2502, 0x07);
}
out->setPixel(w - 1 + Panel::getPosition().x, Panel::getPosition().y - 1, 0x25B2, 0x03);
out->setPixel(w - 1 + Panel::getPosition().x, h + Panel::getPosition().y, 0x25BC, 0x03);
}
}
void CLogger::onUpdate(EventProcessor* ep) {
Panel::onUpdate(ep);
if (!ep) return;
auto mousePos = ep->getMousePos();
auto mouse = ep->Mouse(sf::Mouse::Left);
const uint16_t panelX = getPosition().x; // assuming Panel has getPosition()
const uint16_t panelY = getPosition().y;
const uint16_t panelW = getSize().x;
const uint16_t panelH = getSize().y;
// Convert global mouse pos to local panel coordinates
int localX = mousePos.x - panelX;
int localY = mousePos.y - panelY;
if(Panel::isFocused())
{
// === Vertical Scrollbar Interaction ===
const bool onScrollbar = (localX == panelW - 1) && (localY >= 0 && localY < panelH);
if (mouse.bStrokePressed && onScrollbar) {
isDraggingScrollbar = true;
dragStartY = localY;
dragStartScroll = verticalScroll;
}
else if (mouse.bStrokeReleased) {
isDraggingScrollbar = false;
}
if (isDraggingScrollbar && mouse.bStrokeIsHeld) {
std::lock_guard<std::mutex> lock(bufferMutex);
int totalLines = (int)outputBuffer.size();
int maxScroll = std::max(0, totalLines - (int)panelH);
if (maxScroll > 0) {
float scrollRatio = (float)localY / (panelH - 1);
verticalScroll = (int)(scrollRatio * maxScroll);
verticalScroll = std::clamp(verticalScroll, 0, maxScroll);
}
}
// Optional: Click above/below scrollbar thumb to page up/down
if (mouse.bStrokePressed && localX == panelW - 1) {
std::lock_guard<std::mutex> lock(bufferMutex);
int totalLines = (int)outputBuffer.size();
int maxScroll = std::max(0, totalLines - (int)panelH);
if (localY < (panelH / 2))
verticalScroll = std::max(0, verticalScroll - (panelH / 2)); // Page Up
else
verticalScroll = std::min(maxScroll, verticalScroll + (panelH / 2)); // Page Down
}
}
}
void CLogger::scrollToBottom() {
//std::lock_guard<std::mutex> lock(bufferMutex);
verticalScroll = std::max(0, (int)outputBuffer.size() - (int)getSize().y);
}
} // namespace mce::tui

View File

@@ -0,0 +1,43 @@
#pragma once
#include "Panel.hpp"
#include <vector>
#include <queue>
namespace mce::tui {
class CLogger : public Panel {
public:
CLogger(core::QEventBus& qBus);
CLogger(core::QEventBus& qBus, const std::string& title,
const uint16_t width, const uint16_t height,
core::FunctionContainer fc = {});
static eastl::shared_ptr<CLogger> createInstance(core::QEventBus& qBus,
const std::string& title, const uint16_t width, const uint16_t height,
core::FunctionContainer fc = {});
virtual void onRender(RenderTarget* out) override;
virtual void onUpdate(EventProcessor* ep) override;
void scrollUp(int lines = 1);
void scrollDown(int lines = 1);
void scrollToBottom();
private:
// Optional: Add log manually
void log(const std::string& message);
int verticalScroll = 0;
int horizontalScroll = 0;
// Mouse dragging state
bool isDraggingScrollbar = false;
int dragStartY = 0;
int dragStartScroll = 0;
std::deque<std::string> outputBuffer;
std::mutex bufferMutex;
static constexpr size_t MAX_BUFFER_SIZE = 5000; // prevent unlimited growth
};
} // namespace mce::tui

View File

@@ -13,7 +13,8 @@ namespace mce::tui {
Panel::~Panel() {
}
eastl::shared_ptr<Panel> Panel::createInstance(core::QEventBus& qBus, const std::string& title, const uint16_t width, const uint16_t height, core::FunctionContainer fc) {
eastl::shared_ptr<Panel> Panel::createInstance(core::QEventBus& qBus, const std::string& title, const uint16_t width, const uint16_t height, core::FunctionContainer fc) {
auto component = eastl::make_shared<Panel>(qBus, title, width, height, fc);
if (component->re.buffer.empty()) {
return nullptr;
@@ -288,15 +289,18 @@ namespace mce::tui {
}
void Panel::onRender(RenderTarget* out) {
if (this->fc.findFunction("OnLastRender"))
this->fc.callFunction<void>("OnLastRender");
if (this->fc.findFunction("onLastRender"))
this->fc.callFunction<void, Panel&>("onLastRender", *this);
for (int i = 0; i < this->components.size(); i++) {
auto& component = this->components[i];
component->onRender(this);
}
//int a = this->GetTitle().length() * (this->GetTitle().length() / this->GetSize().X);
Panel::setUpFrame(out, this->getRect(), Panel::props.borderColor);
if (Panel::targeted)
Panel::setUpFrame(out, this->getRect(), Panel::props.borderColor);
else
Panel::setUpFrame(out, this->getRect(), 0x08);
switch (Panel::props.titleAlignment) {
default:
break;
@@ -317,8 +321,8 @@ namespace mce::tui {
}
RenderTarget::flushTo(out, this->getRect());
if (this->fc.findFunction("OnRender"))
this->fc.callFunction<void, Panel&>("OnRender", *this);
if (this->fc.findFunction("onRender"))
this->fc.callFunction<void, Panel&>("onRender", *this);
}
void Panel::onInit() {
@@ -335,6 +339,9 @@ namespace mce::tui {
// TODO: insert return statement here
return Panel::props;
}
bool Panel::isFocused() {
return targeted;
}
void Panel::setUpFrame(RenderTarget* out, sf::Rect<short> rect, uint8_t color) {
uint16_t x = rect.left;
uint16_t y = rect.top;

View File

@@ -54,6 +54,8 @@ namespace mce::tui {
sf::Rect<short> getRect() const;
Properties& getProperties();
bool isFocused();
protected:
void setUpFrame(RenderTarget* out, sf::Rect<short> rect, uint8_t color);
private: