diff --git a/components/BaseComponent.h b/components/BaseComponent.h index f88b56b..ede64d1 100644 --- a/components/BaseComponent.h +++ b/components/BaseComponent.h @@ -7,7 +7,7 @@ protected: bool focusStatus; public: - BaseComponent(int top, int left, int width, int height) : top(top), left(left), width(width), height(height) {}; + BaseComponent(int left, int top, int width, int height) : top(top), left(left), width(width), height(height) {}; virtual ~BaseComponent() {}; void setTop(int top) { diff --git a/components/Editor.h b/components/Editor.h index c08804d..ef15693 100644 --- a/components/Editor.h +++ b/components/Editor.h @@ -3,10 +3,188 @@ #include "BaseComponent.h" #include "TextArea.h" +#include "Cursor.h" +#include "../utils/SyntaxHighlighter.h" +#include "../utils/RichText.h" +#include class Editor : public BaseComponent { private: - TextArea* textArea; + TextArea textArea_ = TextArea(0, 0, 0, 0); + Cursor cursor_; + std::string content_; + RichText coloredContent_; + std::string ruleName_; + std::vector lineedContent_; + + std::vector split(std::string content) { + std::vector lineedContent; + std::string tempStr = content_ + "\n"; + size_t pos = tempStr.find("\n"); + lineedContent.clear(); + while(pos != std::string::npos) { + lineedContent.push_back(tempStr.substr(0, pos)); + tempStr = tempStr.substr(pos + 1); + pos = tempStr.find("\n"); + } + return lineedContent; + } + + std::string assemble(std::vector lineedContent) { + std::string content = ""; + for(auto line : lineedContent) { + content += line + "\n"; + } + return content.substr(0, content.size() - 1); + } + +public: + Editor(int left, int top, int width, int height) : BaseComponent(left, top, width, height) { + textArea_ = TextArea(left, top, width, height); + cursor_.setPosition(left + 1, top + 1); + cursor_.setBounds(left + width - 2, top + height - 2); + content_ = ""; + cursor_.setVisibility(false); + }; + + void setRuleName(std::string ruleName) { ruleName_ = ruleName; } + std::string getRuleName() { return ruleName_; } + + void setContent(std::string content) { + content_ = content; + coloredContent_ = SyntaxHighlighter(ruleName_).highlight(content_); + textArea_.setText(coloredContent_); + lineedContent_ = split(content_); + } + std::string getContent() { return content_; } + + void setTitle(std::string title) { + textArea_.setTitle(RichText(title)); + } + void setTitle(RichText title) { + textArea_.setTitle(title); + } + + void draw() override { + textArea_.draw(); + cursor_.draw(); + } + + void moveUp(int step = 1) { + for(int i = 0; i < step; i++) + if(cursor_.getTop() == top + 1) { + textArea_.moveUp(); + } else { + cursor_.moveUp(); + } + } + + void moveDown(int step = 1) { + for(int i = 0; i < step; i++) + if(cursor_.getTop() == top + height - 2) { + textArea_.moveDown(); + } else { + cursor_.moveDown(); + } + } + + void moveLeft(int step = 1) { + for(int i = 0; i < step; i++) + if(cursor_.getLeft() == left + 1) { + textArea_.moveLeft(); + } else { + cursor_.moveLeft(); + } + } + + void moveRight(int step = 1) { + for(int i = 0; i < step; i++) + if(cursor_.getLeft() == left + width - 2) { + textArea_.moveRight(); + } else { + cursor_.moveRight(); + } + } + + void setFocus(bool focusStatus) { + BaseComponent::setFocus(focusStatus); + cursor_.setVisibility(focusStatus); + } + + void onKeyPress(int key) override { + if(!focusStatus) return; + + int currentLine = cursor_.getTop() - top - 1 + textArea_.getViewTop(); + int currentChar = cursor_.getLeft() - left - 1 + textArea_.getViewLeft(); + int lineLength = lineedContent_[currentLine].size(); + + if(key == 72 + 256) { // up + moveUp(); + } else if(key == 80 + 256) { // down + moveDown(); + } else if(key == 75 + 256) { // left + moveLeft(); + } else if(key == 77 + 256) { // right + moveRight(); + } else { + if(key == 224) return; + if(currentChar > lineLength) { + for(int i = 0; i < currentChar - lineLength; i++) { + moveLeft(); + } + currentChar = lineLength; + } + + if(key == 8) { // backspace + // 如果是第一个字符,则把当前行内容加到上一行末尾 + if(currentChar == 0) { + if(currentLine > 0) { + //移动光标到上一行末尾 + moveUp(); + for(int i = 0; i < lineedContent_[currentLine - 1].size(); i++) { + moveRight(); + } + lineedContent_[currentLine - 1] += lineedContent_[currentLine]; + lineedContent_.erase(lineedContent_.begin() + currentLine); + setContent(assemble(lineedContent_)); + } + } else { + //否则把当前行内容减去一个字符 + moveLeft(); + lineedContent_[currentLine] = lineedContent_[currentLine].substr(0, currentChar - 1) + lineedContent_[currentLine].substr(currentChar); + setContent(assemble(lineedContent_)); + } + } else if(key == 127 || key == 83 + 256) { // delete + if(currentChar == lineLength) { + if(currentLine < lineedContent_.size() - 1) { + lineedContent_[currentLine] += lineedContent_[currentLine + 1]; + lineedContent_.erase(lineedContent_.begin() + currentLine + 1); + setContent(assemble(lineedContent_)); + } + } else { + //否则把当前行内容减去一个字符 + lineedContent_[currentLine] = lineedContent_[currentLine].substr(0, currentChar) + lineedContent_[currentLine].substr(currentChar + 1); + setContent(assemble(lineedContent_)); + } + } else if(key == 13) { // enter + lineedContent_[currentLine].insert(currentChar, "\n"); + setContent(assemble(lineedContent_)); + moveDown(); + for(int i = 0; i < currentChar; i++) { + moveLeft(); + } + } else { + if(key == 9) { // tab + lineedContent_[currentLine].insert(currentChar, " "); + moveRight(3); + } else { + lineedContent_[currentLine].insert(currentChar, 1, key); + } + setContent(assemble(lineedContent_)); + moveRight(); + } + } + } }; #endif \ No newline at end of file diff --git a/components/Editor_test.cpp b/components/Editor_test.cpp new file mode 100644 index 0000000..b4c9156 --- /dev/null +++ b/components/Editor_test.cpp @@ -0,0 +1,55 @@ +#include "BaseComponent.h" +#include "Editor.h" +#include "../utils/RichText.h" +#include +#include + +int main() { + Editor editor(2, 2, 80, 20); + editor.setTitle("Editor Demo"); + + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + CONSOLE_CURSOR_INFO cci; + cci.bVisible = false; + cci.dwSize = 1; + SetConsoleCursorInfo(hConsole, &cci); + + std::ifstream file("Editor_test.cpp"); + std::string content; + std::string line; + while (std::getline(file, line)) { + content += line + "\n"; + } + file.close(); + content = content.substr(0, content.size() - 1); // remove last newline + + editor.setRuleName("cpp"); + editor.setContent(content); + + editor.draw(); + + while(true) { + if (_kbhit()) { + int scan = _getch(), opt; + if(scan == 224) { + opt = _getch() + 256; + } else { + opt = scan; + } + if(editor.isFocused()) { + if(opt == 27) { + editor.setFocus(false); + } else { + editor.onKeyPress(opt); + } + } else { + if(opt == 'i') { + editor.setFocus(true); + } + } + editor.draw(); + } + } + + return 0; +} \ No newline at end of file diff --git a/components/Rect.h b/components/Rect.h index ff3ec65..1e8771e 100644 --- a/components/Rect.h +++ b/components/Rect.h @@ -13,10 +13,10 @@ private: MColor color_ = COLOR_WHITE; public: - Rect(int top, int left, int width, int height) : BaseComponent(top, left, width, height){ + Rect(int left, int top, int width, int height) : BaseComponent(top, left, width, height){ color_ = getColor(COLOR_WHITE, COLOR_BLACK); } - Rect(int top, int left, int width, int height, const MColor color) : BaseComponent(top, left, width, height){ + Rect(int left, int top, int width, int height, const MColor color) : BaseComponent(top, left, width, height){ color_ = color; } ~Rect() override {} diff --git a/components/Text.h b/components/Text.h index 4ad62ae..37091f9 100644 --- a/components/Text.h +++ b/components/Text.h @@ -16,10 +16,10 @@ private: int maxLineWidth_ = 0; public: - Text(int top, int left, int width, int height) : BaseComponent(top, left, width, height) { + Text(int left, int top, int width, int height) : BaseComponent(top, left, width, height) { text_ = RichText(); } - Text(int top, int left, int width, int height, const RichText& text) : BaseComponent(top, left, width, height) { + Text(int left, int top, int width, int height, const RichText& text) : BaseComponent(top, left, width, height) { text_ = text; } ~Text() override { diff --git a/components/TextArea.h b/components/TextArea.h index 8ae0a03..ed9dcf4 100644 --- a/components/TextArea.h +++ b/components/TextArea.h @@ -14,12 +14,12 @@ private: Rect border_ = Rect(0, 0, 0, 0); public: - TextArea(int top, int left, int width, int height) : BaseComponent(top, left, width, height){ + TextArea(int left, int top, int width, int height) : BaseComponent(top, left, width, height){ border_ = Rect(left, top, width, height); text_ = Text(left + 1, top + 1, width - 2, height - 2); text_.setText(RichText()); } - TextArea(int top, int left, int width, int height, const RichText& text) : BaseComponent(top, left, width, height){ + TextArea(int left, int top, int width, int height, const RichText& text) : BaseComponent(top, left, width, height){ border_ = Rect(left, top, width, height); text_ = Text(left + 1, top + 1, width - 2, height - 2); text_.setText(text); @@ -67,6 +67,14 @@ public: } } + int getViewLeft() { + return text_.getViewLeft(); + } + + int getViewTop() { + return text_.getViewTop(); + } + void onKeyPress(int key) override { //不处理按键 } diff --git a/components/TextEditor.h b/components/TextEditor.h deleted file mode 100644 index e69de29..0000000 diff --git a/components/TextLine.h b/components/TextLine.h index 4963f37..957bd58 100644 --- a/components/TextLine.h +++ b/components/TextLine.h @@ -13,11 +13,11 @@ private: Rect border_ = Rect(0, 0, 0, 0); public: - TextLine(int top, int left, int width, int height) : BaseComponent(top, left, width, height){ + TextLine(int left, int top, int width, int height) : BaseComponent(top, left, width, height){ text_ = Text(top + 1, left + 1, width - 2, 1); border_ = Rect(top, left, width, height); } - TextLine(int top, int left, int width, int height, const RichText& text) : BaseComponent(top, left, width, height){ + TextLine(int left, int top, int width, int height, const RichText& text) : BaseComponent(top, left, width, height){ text_ = Text(top + 1, left + 1, width - 2, 1, text); border_ = Rect(top, left, width, height); }