This commit is contained in:
2026-04-20 20:16:16 -06:00
parent fa519d937f
commit b90f1181ce
6 changed files with 116 additions and 12 deletions

View File

@@ -0,0 +1,21 @@
#pragma once
#include <desktoplib/terminal/Terminal.hpp>
namespace ckitty::terminal {
class Content {
public:
virtual ~Content() = default;
// Content must report how tall it wants to be
virtual int getTotalHeight() const = 0;
// Render only the rows between startRow and endRow
// relativeY is where the Content starts drawing in terminal space
virtual void render(Terminal& t, pos screenPos, pos viewport, std::pair<int, int> rows) const = 0;
};
}

View File

@@ -0,0 +1,59 @@
#include "InnerScroll.hpp"
namespace ckitty::terminal {
InnerScroll::InnerScroll(pos p, int w, int h, Content& c)
: position(p), width(w), height(h), _content(c) {
}
void InnerScroll::scroll(int delta) {
int maxScroll = std::max(0, _content.getTotalHeight() - height);
scrollY = std::clamp(scrollY + delta, 0, maxScroll);
}
void InnerScroll::render(Terminal& t) const {
int totalH = _content.getTotalHeight();
int viewH = height;
int contentWidth = width - 1; // Last column reserved for scrollbar
// 1. Render the Content Viewport
// We only ask content to draw what fits in our height
int start = scrollY;
int end = std::min(totalH, scrollY + viewH);
_content.render(t, position, pos(contentWidth, height), { start, end });
// 2. Clear empty space if content is shorter than viewport
if (end - start < viewH) {
for (int y = (end - start); y < viewH; ++y) {
t << pos{ position.x, position.y + y }
<< std::string(contentWidth, ' ');
}
}
// 3. Render Scrollbar Track
int scrollX = position.x + width - 1;
t << trackColor;
for (int y = 0; y < viewH; ++y) {
t << pos{ scrollX, position.y + y } << "";
}
// 4. Render Scrollbar Thumb
if (totalH > viewH) {
// Calculate thumb height (proportional to visibility)
int thumbH = std::max(1, (viewH * viewH) / totalH);
// Calculate thumb position
float scrollPercent = (float)scrollY / (totalH - viewH);
int thumbPos = (int)(scrollPercent * (viewH - thumbH));
t << thumbColor;
for (int y = 0; y < thumbH; ++y) {
t << pos{ scrollX, position.y + thumbPos + y } << "";
}
}
t << style::RESET;
}
}

View File

@@ -1,2 +1,38 @@
#pragma once
#include <desktoplib/terminal/Terminal.hpp>
#include <desktoplib/terminal/ui/Content.hpp>
#include <memory>
namespace ckitty::terminal {
class InnerScroll : public UI {
public:
pos position;
int width, height;
int scrollY = 0; // The top-most visible row of the content
// Styling
color trackColor = color::B_BLACK;
color thumbColor = color::WHITE;
private:
Content& _content;
public:
InnerScroll(pos p, int w, int h, Content& c);
public:
void render(Terminal& t) const override;
// Helper to scroll
void scroll(int delta);
void scrollTo(int row);
};
}

View File

@@ -1,9 +0,0 @@
#pragma once
namespace ckitty {
namespace terminal {
}
}

View File

@@ -1,3 +0,0 @@
#pragma once