Skip to content

Commit

Permalink
Merge pull request #12 from hnsk0808/new-layout
Browse files Browse the repository at this point in the history
重写的排版
  • Loading branch information
jimmy-sketch authored Oct 7, 2024
2 parents 6fd7d9b + 4999555 commit addaf7a
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 106 deletions.
162 changes: 77 additions & 85 deletions chen_cppcguilib/cgui.cpp
Original file line number Diff line number Diff line change
@@ -1,39 +1,74 @@
#include"cgui.h"
#include <iostream>

static void addNewLinesTo(std::vector<std::vector<cgui::string>>& target, int n) {
if (n > target.size()) {
for (int i = 0; i < n - target.size(); ++i) {
target.emplace_back();
}
static std::vector<cgui::string> outlineComponent(std::shared_ptr<component> c) {
std::vector<cgui::string> ret;
ret.push_back("+" + cgui::string(c->getWidth(), '-') + "+");
for (auto& line : c->getData()) {
ret.push_back("|" + line + "|");
}
ret.push_back("+" + cgui::string(c->getWidth(), '-') + "+");
return ret;
}

page::page(bool enableSelect)
: enableSelect(enableSelect)
{}

std::string page::toString()
{
std::vector<std::vector<cgui::string>> lines;
for (auto& c : components) {
int row = getAboveComponentHeight(c.first);
// 如果上方无组件,且不是这行的第一个组件,则与左边组件对齐
if (row == 0 && c.first.row != 0 && c.first.col != 0) {
auto left = findNearestComponent(c.first, 0, -1);
if (!isBadLogicPos(left)) {
row = getAboveComponentHeight(left);

if (enableSelect) {
lineHeightList[selectedPos.row] = std::max(lineHeightList[selectedPos.row], components[selectedPos]->getHeight() + 2);
lineWidthList[selectedPos.col] = std::max(lineWidthList[selectedPos.col], components[selectedPos]->getWidth() + 2);
}

for (auto [pos, c] : components) {
if (enableSelect && pos == selectedPos) {
c = std::make_shared<basicImage>(outlineComponent(c));
}

int height = c->getHeight();
int width = c->getWidth();
auto data = c->getData();

int lineHeight = lineHeightList[pos.row];
int lineWidth = lineWidthList[pos.col];

int yOffset = 0;
for (int i = pos.row; i > 0; --i) {
yOffset += lineHeightList[i-1];
}

if (yOffset + lineHeight + 1 > lines.size()) {
lines.resize(yOffset + lineHeight + 1);
}

for (int i = 0; i < lineHeight; ++i) {
if (i < height) {
data[i] += cgui::string(lineWidth - data[i].length(), ' ');
lines[yOffset + i].push_back(data[i]);
}
else {
lines[yOffset + i].push_back(cgui::string(lineWidth, ' '));
}
}
}

addNewLinesTo(lines, row + 1);
for (int l = 0; l < c.second->getHeight(); ++l) {
addNewLinesTo(lines, row + l + 1);
cgui::string str = c.second->getData()[l];
int h = getLeftComponentHeight(c.first);
if (h != 0 && h < c.second->getHeight() && l >= h) {
str.insert(0, getAllLeftComponentWidth(c.first, l), ' ');
if (enableSelect) {
lineHeightList[selectedPos.row] = 0;
lineWidthList[selectedPos.col] = 0;
for (auto& [p, c] : components) {
if (p.col == selectedPos.col) {
lineWidthList[selectedPos.col] = std::max(lineWidthList[selectedPos.col], c->getWidth());
}
if (p.row == selectedPos.row) {
lineHeightList[selectedPos.row] = std::max(lineHeightList[selectedPos.row], c->getHeight());
}
lines[row + l].push_back(str);
}
// 以后加入组件间距
}

std::string ret = "";
for (auto& line : lines) {
for (auto& str : line) {
Expand All @@ -53,81 +88,38 @@ void page::update()
void page::setTo(logicPos pos, std::shared_ptr<component> src)
{
components[pos] = src;
lineWidthList[pos.col] = std::max(lineWidthList[pos.col], src->getWidth());
lineHeightList[pos.row] = std::max(lineHeightList[pos.row], src->getHeight());
}

void page::clear()
void page::erase(logicPos pos)
{
components.clear();
}

int page::getUpperComponentHeight(logicPos current) {
logicPos upper = { current.row - 1, current.col };
auto it = components.find(upper);
if (it != components.end()) {
return it->second->getHeight();
}
return 0;
}

int page::getAboveComponentHeight(logicPos current) {
logicPos upper = current;
int h = getUpperComponentHeight(upper);
int ret = h;
while (h != 0) {
upper = { upper.row - 1, upper.col };
h = getUpperComponentHeight(upper);
ret += h;
}
return ret;
}

int page::getLeftComponentWidth(logicPos current) {
logicPos left = { current.row, current.col - 1 };
auto it = components.find(left);
if (it != components.end()) {
return it->second->getWidth();
}
return 0;
}

int page::getAllLeftComponentWidth(logicPos current, int row)
{
logicPos left = current;
int ret = 0;
while (true) {
int h = getLeftComponentHeight(left);
if (h == 0 || row < h) {
break;
components.erase(pos);
lineWidthList[pos.col] = 0;
lineHeightList[pos.row] = 0;
for (auto& [p, c] : components) {
if (p.col == pos.col) {
lineWidthList[pos.col] = std::max(lineWidthList[pos.col], c->getWidth());
}
if (p.row == pos.row) {
lineHeightList[pos.row] = std::max(lineHeightList[pos.row], c->getHeight());
}
left.col -= 1;
ret += components[left]->getWidth();
}
return ret;
}

int page::getLeftComponentHeight(logicPos current) {
logicPos left = { current.row, current.col - 1 };
auto it = components.find(left);
if (it != components.end()) {
return it->second->getHeight();
}
return 0;
void page::clear()
{
components.clear();
lineHeightList.clear();
lineWidthList.clear();
}

logicPos page::findNearestComponent(logicPos current, int y, int x)
void page::setEnableSelect(bool v)
{
logicPos iter = { current.row + y, current.col + x };
while (!isBadLogicPos(iter)) {
auto it = components.find(iter);
if (it != components.end()) {
return it->first;
}
iter = { iter.col + y, iter.row + x };
}
return { -1, -1 };
enableSelect = v;
}

bool page::isBadLogicPos(logicPos pos)
void page::select(logicPos pos)
{
return !(pos.col >= 0 && pos.row >= 0 && pos.col < 99 && pos.row < 99);
selectedPos = pos;
}
39 changes: 22 additions & 17 deletions chen_cppcguilib/cgui.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,34 +14,39 @@ struct logicPos {
static bool operator<(logicPos lhs, logicPos rhs) {
return (lhs.row < rhs.row) || (lhs.row == rhs.row && lhs.col < rhs.col);
}
static bool operator==(logicPos lhs, logicPos rhs) {
return (lhs.row == rhs.row) && (lhs.col == rhs.col);
}

class page
{
public:
//重要函数:刷新、呈现控件内容
page(bool enableSelect);

//重要函数:刷新、呈现控件内容
std::string toString();
void update();

//把某个控件放到...
//把某个控件放到...
void setTo(logicPos pos, std::shared_ptr<component> src);

//清空控件
//删除某个控件
void erase(logicPos pos);

//清空控件
void clear();

//启用控件选择
void setEnableSelect(bool v);

//选择控件
void select(logicPos pos);

private:
std::map<logicPos, std::shared_ptr<component>> components;
// 获得组件上方一个组件的高
int getUpperComponentHeight(logicPos current);
// 获得组件上方所有组件的高的总和
int getAboveComponentHeight(logicPos current);
// 获得左边组件的宽
int getLeftComponentWidth(logicPos current);
// 获得左边所有低于自身组件的宽,碰到同行的也停止
int getAllLeftComponentWidth(logicPos current, int row);
// 获得左边组件的高
int getLeftComponentHeight(logicPos current);
// 找最近的存在的组件,y表示每次向下走格数,x表示每次向右走格数,可以为负,有则返回位置,无则返回-1,-1
logicPos findNearestComponent(logicPos current, int y, int x);
// 判断位置是不是不合理的
bool isBadLogicPos(logicPos pos);
std::map<int, int> lineWidthList;
std::map<int, int> lineHeightList;

logicPos selectedPos = { 0, 0 };
bool enableSelect;
};
27 changes: 25 additions & 2 deletions chen_cppcguilib/utils/string.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ using namespace cgui;

static const std::string defaultColor = "\033[0m";

string::string() {}
string::string(const char* in) : str(in) { calculateVisibleLength(); }
string::string(std::string_view in) : str(in) { calculateVisibleLength(); }
string::string(int count, char c) : str(count, c) {}
string::string(int count, char c) : str(count, c) { calculateVisibleLength(); }

size_t string::size() const { return str.size(); }
int string::length() const { return visibleLength; }
Expand Down Expand Up @@ -71,6 +72,18 @@ void cgui::string::operator+=(char other)
visibleLength += 1;
}

void cgui::string::operator=(const string& other)
{
str = other.str;
visibleLength = other.visibleLength;
}

void cgui::string::operator=(std::string_view other)
{
str = other;
calculateVisibleLength();
}

const char* cgui::string::data() const
{
return str.data();
Expand Down Expand Up @@ -98,4 +111,14 @@ void string::calculateVisibleLength() {
// 处理unicode字符
// todo
visibleLength = cleanLine.size();
}
}

string cgui::operator+(std::string_view lhs, string& rhs)
{
return string(lhs) + rhs;
}

string cgui::operator+(std::string_view lhs, string&& rhs)
{
return string(lhs) + rhs;
}
5 changes: 5 additions & 0 deletions chen_cppcguilib/utils/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ namespace cgui {
//
class string {
public:
string();
string(const char* in);
string(std::string_view in);
string(int count, char c);
Expand All @@ -41,6 +42,8 @@ class string {
string& operator+(char other);
void operator+=(const string& other);
void operator+=(char other);
void operator=(const string& other);
void operator=(std::string_view other);

const char* data() const;

Expand All @@ -52,5 +55,7 @@ class string {
int pushBackPos() const; // 如果有颜色,pos会在最后一个恢复默认颜色之前
void calculateVisibleLength();
};
string operator+(std::string_view lhs, string& rhs);
string operator+(std::string_view lhs, string&& rhs);

}
31 changes: 29 additions & 2 deletions sandbox/main.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include <cgui.h>
#include <conio.h>
#include <string>
#include <thread>
#include <iostream>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#define STB_TRUETYPE_IMPLEMENTATION
Expand Down Expand Up @@ -56,7 +58,7 @@ void initFont() {

int main() {
initFont();
page p;
page p(false);

auto image = std::make_shared<basicImage>(getImageByLines("apple.png"));
auto progressBar = std::make_shared<basicProgressBar>(10, 0);
Expand All @@ -75,7 +77,7 @@ int main() {
p.update();

while (!progressBar->isDone()) {
std::this_thread::sleep_for(200ms);
std::this_thread::sleep_for(500ms);
progressBar->updateProgress(progressBar->getProgress() + 10);
p.update();
}
Expand All @@ -98,5 +100,30 @@ int main() {
p.setTo({ 0, 10 }, image);
p.update();

page p1(true);
p1.setTo({ 0, 0 }, std::make_shared<basicText>("\x1b[38;2;255;0;0mOption1\033[0m"));
p1.setTo({ 0, 1 }, std::make_shared<basicText>("\x1b[38;2;0;255;0mOption2\033[0m"));
p1.setTo({ 0, 2 }, std::make_shared<basicText>("\x1b[38;2;255;0;255mOption3\033[0m"));
p1.setTo({ 0, 3 }, std::make_shared<basicText>("\x1b[38;2;0;255;0mOption4\033[0m"));
p1.setTo({ 0, 4 }, std::make_shared<basicText>("\x1b[38;2;255;0;0mOption5\033[0m"));

int i = 0;
while (true) {
p1.select({ 0, i });
system("cls");
std::cout << p.toString();
std::cout << std::endl << std::endl << std::endl;
std::cout << p1.toString();

char c = _getch();
if (c == 75) {
i -= 1;
if (i < 0) { i = 4; }
}
else if (c == 77) {
i += 1;
if (i > 4) { i = 0; }
}
}
return 0;
}

0 comments on commit addaf7a

Please sign in to comment.