完善Menu类

This commit is contained in:
梦凌汐 2024-12-19 20:48:30 +08:00
parent 4f55beda64
commit ac4e01daf6
2 changed files with 151 additions and 0 deletions

107
components/Menu.h Normal file
View File

@ -0,0 +1,107 @@
#ifndef MENU_H
#define MENU_H
#include "BaseComponent.h"
#include "TextLine.h"
#include "../mystl/my_vector.h"
#include "../utils/RichText.h"
#include "../utils/Color.h"
#include <string>
struct MenuOption {
std::string id, title;
MenuOption(const std::string& id, const std::string& title) : id(id), title(title) {}
MenuOption() : id(), title() {}
};
class Menu : public BaseComponent {
private:
struct Option {
MenuOption option;
Text* text;
Option(MenuOption option, Text* text) : option(option), text(text) {}
Option() : option(), text(nullptr) {}
};
MyVector<Option> options_;
int currentIndex_ = 0;
Rect border_ = {0, 0, 0, 0};
public:
Menu(int left, int top, RichText title, MyVector<MenuOption> options) : BaseComponent(left, top, 0, 0) { // set left/top to -1 to center the menu
int maxLength = 0;
for (int i = 0; i < options.size(); i++) {
if (options[i].title.size() > maxLength) {
maxLength = options[i].title.size();
}
}
int width = std::max(maxLength + 2, static_cast<int>(title.plainText().length()) + 4);
int height = options.size() + 2;
border_.setTitle(title);
border_.setWidth(width); border_.setHeight(height);
// get the size of the console
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(hConsole, &csbi);
int consoleWidth = csbi.srWindow.Right - csbi.srWindow.Left + 1;
int consoleHeight = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
if (left == -1) {
left = (consoleWidth - width) / 2;
}
if (top == -1) {
top = (consoleHeight - height) / 2;
}
border_.setLeft(left); border_.setTop(top);
BaseComponent::setPosition(left, top);
BaseComponent::setWidth(width); BaseComponent::setHeight(height);
for (int i = 0; i < options.size(); i++) {
std::cout << options[i].title << " at (" << static_cast<int>(left + width / 2 - options[i].title.size() / 2) << "," << top + 1 + i << ")" << std::endl;
options_.push_back({options[i], new Text(static_cast<int>(left + width / 2 - options[i].title.size() / 2), top + 1 + i, options[i].title.size(), 2, RichText(options[i].title, COLOR_GRAY))});
}
if(options_.size() > 0) {
options_[0].text->setText(RichText(options_[0].option.title, COLOR_WHITE));
}
}
void draw() override {
border_.draw();
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
//获得缓冲区信息
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(hConsole, &csbi);
for (int i = 0; i < options_.size(); i++) {
options_[i].text->draw();
}
SetConsoleTextAttribute(hConsole, BackgroundColorToWinColor(COLOR_BLACK) | FrontColorToWinColor(COLOR_WHITE));
}
void onKeyPress(int key) override {
if(!focusStatus) return;
if(key == 72 + 256) {
if(currentIndex_ == 0) return;
currentIndex_--;
} else if(key == 80 + 256) {
if(currentIndex_ == options_.size() - 1) return;
currentIndex_++;
}
for (int i = 0; i < options_.size(); i++) {
options_[i].text->setText(RichText(options_[i].text->getText().plainText(), COLOR_GRAY));
}
options_[currentIndex_].text->setText(RichText(options_[currentIndex_].text->getText().plainText(), COLOR_WHITE));
}
};
#endif

44
components/Menu_test.cpp Normal file
View File

@ -0,0 +1,44 @@
#include "Menu.h"
#include "../mystl/my_vector.h"
int main() {
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO cci;
cci.bVisible = false;
cci.dwSize = 1;
SetConsoleCursorInfo(hConsole, &cci);
MyVector<MenuOption> ops;
ops.push_back(MenuOption("1", "Option 1"));
ops.push_back(MenuOption("2", "Opt 2"));
ops.push_back(MenuOption("3", "This is Option 3"));
Menu menu(-1, -1, RichText("Menu Title"), ops);
menu.draw();
while(true) {
if (_kbhit()) {
int scan = _getch(), opt;
if(scan == 224) {
opt = _getch() + 256;
} else {
opt = scan;
}
if(menu.isFocused()) {
if(opt == 27) {
menu.setFocus(false);
} else {
menu.onKeyPress(opt);
}
} else {
if(opt == 'i') {
menu.setFocus(true);
}
}
}
menu.draw();
}
return 0;
}