add syntax highlighting (WIP)
This commit is contained in:
parent
ce1e9f76cf
commit
ed3865964b
@ -32,10 +32,9 @@
|
|||||||
autoresize='true'
|
autoresize='true'
|
||||||
margin='0'
|
margin='0'
|
||||||
padding='5'
|
padding='5'
|
||||||
editable='false'
|
|
||||||
multiline='true'
|
multiline='true'
|
||||||
line-numbers='true'
|
line-numbers='true'
|
||||||
text-color="#FFFFFFA0"
|
syntax='lua'
|
||||||
size-func="gui.get_viewport()[1]-350,40"
|
size-func="gui.get_viewport()[1]-350,40"
|
||||||
gravity="top-left"
|
gravity="top-left"
|
||||||
text-wrap='false'
|
text-wrap='false'
|
||||||
|
|||||||
@ -214,10 +214,14 @@ std::string_view BasicParser::readUntil(char c) {
|
|||||||
return source.substr(start, pos - start);
|
return source.substr(start, pos - start);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string_view BasicParser::readUntil(std::string_view s) {
|
std::string_view BasicParser::readUntil(std::string_view s, bool nothrow) {
|
||||||
int start = pos;
|
int start = pos;
|
||||||
size_t found = source.find(s, pos);
|
size_t found = source.find(s, pos);
|
||||||
if (found == std::string::npos) {
|
if (found == std::string::npos) {
|
||||||
|
if (nothrow) {
|
||||||
|
pos = source.size();
|
||||||
|
return source.substr(start);
|
||||||
|
}
|
||||||
throw error(util::quote(std::string(s))+" expected");
|
throw error(util::quote(std::string(s))+" expected");
|
||||||
}
|
}
|
||||||
skip(found - pos);
|
skip(found - pos);
|
||||||
|
|||||||
@ -105,7 +105,7 @@ protected:
|
|||||||
parsing_error error(const std::string& message);
|
parsing_error error(const std::string& message);
|
||||||
public:
|
public:
|
||||||
std::string_view readUntil(char c);
|
std::string_view readUntil(char c);
|
||||||
std::string_view readUntil(std::string_view s);
|
std::string_view readUntil(std::string_view s, bool nothrow);
|
||||||
std::string_view readUntilWhitespace();
|
std::string_view readUntilWhitespace();
|
||||||
std::string_view readUntilEOL();
|
std::string_view readUntilEOL();
|
||||||
std::string parseName();
|
std::string parseName();
|
||||||
|
|||||||
@ -119,24 +119,28 @@ public:
|
|||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
} else if (is_digit(c)) {
|
} else if (is_digit(c)) {
|
||||||
auto value = parseNumber(1);
|
dv::value value;
|
||||||
|
auto tag = TokenTag::UNEXPECTED;
|
||||||
|
try {
|
||||||
|
value = parseNumber(1);
|
||||||
|
tag = value.isInteger() ? TokenTag::INTEGER
|
||||||
|
: TokenTag::NUMBER;
|
||||||
|
} catch (const parsing_error& err) {}
|
||||||
|
|
||||||
auto literal = source.substr(start.pos, pos - start.pos);
|
auto literal = source.substr(start.pos, pos - start.pos);
|
||||||
emitToken(
|
emitToken(tag, std::string(literal), start);
|
||||||
value.isInteger() ? TokenTag::INTEGER : TokenTag::NUMBER,
|
|
||||||
std::string(literal),
|
|
||||||
start
|
|
||||||
);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '(': case '[': case '{':
|
case '(': case '[': case '{':
|
||||||
if (isNext("[==[")) {
|
if (isNext("[==[")) {
|
||||||
readUntil("]==]");
|
auto string = readUntil("]==]", true);
|
||||||
skip(4);
|
skip(4);
|
||||||
|
emitToken(TokenTag::COMMENT, std::string(string)+"]==]", start);
|
||||||
continue;
|
continue;
|
||||||
} else if (isNext("[[")) {
|
} else if (isNext("[[")) {
|
||||||
skip(2);
|
skip(2);
|
||||||
auto string = readUntil("]]");
|
auto string = readUntil("]]", true);
|
||||||
skip(2);
|
skip(2);
|
||||||
emitToken(TokenTag::STRING, std::string(string), start);
|
emitToken(TokenTag::STRING, std::string(string), start);
|
||||||
continue;
|
continue;
|
||||||
@ -154,7 +158,7 @@ public:
|
|||||||
continue;
|
continue;
|
||||||
case '\'': case '"': {
|
case '\'': case '"': {
|
||||||
skip(1);
|
skip(1);
|
||||||
auto string = parseString(c);
|
auto string = parseString(c, false);
|
||||||
emitToken(TokenTag::STRING, std::move(string), start);
|
emitToken(TokenTag::STRING, std::move(string), start);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -163,6 +167,8 @@ public:
|
|||||||
if (is_lua_operator_start(c)) {
|
if (is_lua_operator_start(c)) {
|
||||||
auto text = parseOperator();
|
auto text = parseOperator();
|
||||||
if (text == "--") {
|
if (text == "--") {
|
||||||
|
auto string = readUntilEOL();
|
||||||
|
emitToken(TokenTag::COMMENT, std::string(string), start);
|
||||||
skipLine();
|
skipLine();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,7 @@ namespace lua {
|
|||||||
|
|
||||||
enum class TokenTag {
|
enum class TokenTag {
|
||||||
KEYWORD, NAME, INTEGER, NUMBER, OPEN_BRACKET, CLOSE_BRACKET, STRING,
|
KEYWORD, NAME, INTEGER, NUMBER, OPEN_BRACKET, CLOSE_BRACKET, STRING,
|
||||||
OPERATOR, COMMA, SEMICOLON, UNEXPECTED
|
OPERATOR, COMMA, SEMICOLON, UNEXPECTED, COMMENT
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Token {
|
struct Token {
|
||||||
|
|||||||
72
src/devtools/syntax_highlighting.cpp
Normal file
72
src/devtools/syntax_highlighting.cpp
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#include "syntax_highlighting.hpp"
|
||||||
|
|
||||||
|
#include "coders/commons.hpp"
|
||||||
|
#include "coders/lua_parsing.hpp"
|
||||||
|
#include "graphics/core/Font.hpp"
|
||||||
|
|
||||||
|
using namespace devtools;
|
||||||
|
|
||||||
|
static std::unique_ptr<FontStylesScheme> build_styles(
|
||||||
|
const std::vector<lua::Token>& tokens
|
||||||
|
) {
|
||||||
|
FontStylesScheme styles {
|
||||||
|
{
|
||||||
|
{false, false, glm::vec4(0.8f, 0.8f, 0.8f, 1)}, // default
|
||||||
|
{true, false, glm::vec4(0.9, 0.6f, 0.4f, 1)}, // keyword
|
||||||
|
{false, false, glm::vec4(0.4, 0.8f, 0.5f, 1)}, // string
|
||||||
|
{false, false, glm::vec4(0.3, 0.3f, 0.3f, 1)}, // comment
|
||||||
|
{false, false, glm::vec4(0.4, 0.45f, 0.5f, 1)}, // self
|
||||||
|
{true, false, glm::vec4(1.0f, 0.2f, 0.1f, 1)}, // unexpected
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
size_t offset = 0;
|
||||||
|
for (int i = 0; i < tokens.size(); i++) {
|
||||||
|
const auto& token = tokens.at(i);
|
||||||
|
if (token.tag != lua::TokenTag::KEYWORD &&
|
||||||
|
token.tag != lua::TokenTag::STRING &&
|
||||||
|
token.tag != lua::TokenTag::INTEGER &&
|
||||||
|
token.tag != lua::TokenTag::NUMBER &&
|
||||||
|
token.tag != lua::TokenTag::COMMENT &&
|
||||||
|
token.tag != lua::TokenTag::UNEXPECTED) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (token.start.pos > offset) {
|
||||||
|
int n = token.start.pos - offset;
|
||||||
|
styles.map.insert(styles.map.end(), token.start.pos - offset, 0);
|
||||||
|
}
|
||||||
|
offset = token.end.pos;
|
||||||
|
int styleIndex;
|
||||||
|
switch (token.tag) {
|
||||||
|
case lua::TokenTag::KEYWORD: styleIndex = 1; break;
|
||||||
|
case lua::TokenTag::STRING:
|
||||||
|
case lua::TokenTag::INTEGER:
|
||||||
|
case lua::TokenTag::NUMBER: styleIndex = 2; break;
|
||||||
|
case lua::TokenTag::COMMENT: styleIndex = 3; break;
|
||||||
|
case lua::TokenTag::UNEXPECTED: styleIndex = 5; break;
|
||||||
|
default:
|
||||||
|
styleIndex = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
styles.map.insert(
|
||||||
|
styles.map.end(), token.end.pos - token.start.pos, styleIndex
|
||||||
|
);
|
||||||
|
}
|
||||||
|
styles.map.push_back(0);
|
||||||
|
return std::make_unique<FontStylesScheme>(std::move(styles));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<FontStylesScheme> devtools::syntax_highlight(
|
||||||
|
const std::string& lang, std::string_view source
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
if (lang == "lua") {
|
||||||
|
auto tokens = lua::tokenize("<string>", source);
|
||||||
|
return build_styles(tokens);
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
} catch (const parsing_error& err) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
12
src/devtools/syntax_highlighting.hpp
Normal file
12
src/devtools/syntax_highlighting.hpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
struct FontStylesScheme;
|
||||||
|
|
||||||
|
namespace devtools {
|
||||||
|
std::unique_ptr<FontStylesScheme> syntax_highlight(
|
||||||
|
const std::string& lang, std::string_view source
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -62,7 +62,7 @@ static inline void draw_glyph(
|
|||||||
pos.y + offset.y * right.y,
|
pos.y + offset.y * right.y,
|
||||||
right.x / glyphInterval,
|
right.x / glyphInterval,
|
||||||
up.y,
|
up.y,
|
||||||
-0.2f * style.italic,
|
-0.15f * style.italic,
|
||||||
16,
|
16,
|
||||||
c,
|
c,
|
||||||
batch.getColor() * style.color
|
batch.getColor() * style.color
|
||||||
@ -102,11 +102,11 @@ static inline void draw_text(
|
|||||||
const glm::vec3& right,
|
const glm::vec3& right,
|
||||||
const glm::vec3& up,
|
const glm::vec3& up,
|
||||||
float glyphInterval,
|
float glyphInterval,
|
||||||
const FontStylesScheme* styles
|
const FontStylesScheme* styles,
|
||||||
|
size_t styleMapOffset
|
||||||
) {
|
) {
|
||||||
static FontStylesScheme defStyles {
|
static FontStylesScheme defStyles {{{}}, {0}};
|
||||||
{{std::numeric_limits<size_t>::max()}},
|
|
||||||
};
|
|
||||||
if (styles == nullptr) {
|
if (styles == nullptr) {
|
||||||
styles = &defStyles;
|
styles = &defStyles;
|
||||||
}
|
}
|
||||||
@ -117,17 +117,12 @@ static inline void draw_text(
|
|||||||
int y = 0;
|
int y = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
size_t entryIndex = 0;
|
for (size_t i = 0; i < text.length(); i++) {
|
||||||
int styleCharsCounter = -1;
|
uint c = text[i];
|
||||||
const FontStyle* style = &styles->palette.at(entryIndex);
|
size_t styleIndex = styles->map.at(
|
||||||
|
std::min(styles->map.size() - 1, i + styleMapOffset)
|
||||||
for (uint c : text) {
|
);
|
||||||
styleCharsCounter++;
|
const FontStyle& style = styles->palette.at(styleIndex);
|
||||||
if (styleCharsCounter > style->n &&
|
|
||||||
entryIndex + 1 < styles->palette.size()) {
|
|
||||||
style = &styles->palette.at(++entryIndex);
|
|
||||||
styleCharsCounter = -1;
|
|
||||||
}
|
|
||||||
if (!font.isPrintableChar(c)) {
|
if (!font.isPrintableChar(c)) {
|
||||||
x++;
|
x++;
|
||||||
continue;
|
continue;
|
||||||
@ -143,7 +138,7 @@ static inline void draw_text(
|
|||||||
right,
|
right,
|
||||||
up,
|
up,
|
||||||
glyphInterval,
|
glyphInterval,
|
||||||
*style
|
style
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else if (charpage > page && charpage < next){
|
else if (charpage > page && charpage < next){
|
||||||
@ -174,6 +169,7 @@ void Font::draw(
|
|||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
const FontStylesScheme* styles,
|
const FontStylesScheme* styles,
|
||||||
|
size_t styleMapOffset,
|
||||||
float scale
|
float scale
|
||||||
) const {
|
) const {
|
||||||
draw_text(
|
draw_text(
|
||||||
@ -182,7 +178,8 @@ void Font::draw(
|
|||||||
glm::vec3(glyphInterval*scale, 0, 0),
|
glm::vec3(glyphInterval*scale, 0, 0),
|
||||||
glm::vec3(0, lineHeight*scale, 0),
|
glm::vec3(0, lineHeight*scale, 0),
|
||||||
glyphInterval/static_cast<float>(lineHeight),
|
glyphInterval/static_cast<float>(lineHeight),
|
||||||
styles
|
styles,
|
||||||
|
styleMapOffset
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,6 +187,7 @@ void Font::draw(
|
|||||||
Batch3D& batch,
|
Batch3D& batch,
|
||||||
std::wstring_view text,
|
std::wstring_view text,
|
||||||
const FontStylesScheme* styles,
|
const FontStylesScheme* styles,
|
||||||
|
size_t styleMapOffset,
|
||||||
const glm::vec3& pos,
|
const glm::vec3& pos,
|
||||||
const glm::vec3& right,
|
const glm::vec3& right,
|
||||||
const glm::vec3& up
|
const glm::vec3& up
|
||||||
@ -199,6 +197,7 @@ void Font::draw(
|
|||||||
right * static_cast<float>(glyphInterval),
|
right * static_cast<float>(glyphInterval),
|
||||||
up * static_cast<float>(lineHeight),
|
up * static_cast<float>(lineHeight),
|
||||||
glyphInterval/static_cast<float>(lineHeight),
|
glyphInterval/static_cast<float>(lineHeight),
|
||||||
styles
|
styles,
|
||||||
|
styleMapOffset
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,6 @@ class Batch3D;
|
|||||||
class Camera;
|
class Camera;
|
||||||
|
|
||||||
struct FontStyle {
|
struct FontStyle {
|
||||||
size_t n = -1;
|
|
||||||
bool bold = false;
|
bool bold = false;
|
||||||
bool italic = false;
|
bool italic = false;
|
||||||
glm::vec4 color {1, 1, 1, 1};
|
glm::vec4 color {1, 1, 1, 1};
|
||||||
@ -20,6 +19,7 @@ struct FontStyle {
|
|||||||
|
|
||||||
struct FontStylesScheme {
|
struct FontStylesScheme {
|
||||||
std::vector<FontStyle> palette;
|
std::vector<FontStyle> palette;
|
||||||
|
std::vector<ubyte> map;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Font {
|
class Font {
|
||||||
@ -57,6 +57,7 @@ public:
|
|||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
const FontStylesScheme* styles,
|
const FontStylesScheme* styles,
|
||||||
|
size_t styleMapOffset,
|
||||||
float scale = 1
|
float scale = 1
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
@ -64,6 +65,7 @@ public:
|
|||||||
Batch3D& batch,
|
Batch3D& batch,
|
||||||
std::wstring_view text,
|
std::wstring_view text,
|
||||||
const FontStylesScheme* styles,
|
const FontStylesScheme* styles,
|
||||||
|
size_t styleMapOffset,
|
||||||
const glm::vec3& pos,
|
const glm::vec3& pos,
|
||||||
const glm::vec3& right={1, 0, 0},
|
const glm::vec3& right={1, 0, 0},
|
||||||
const glm::vec3& up={0, 1, 0}
|
const glm::vec3& up={0, 1, 0}
|
||||||
|
|||||||
@ -98,13 +98,13 @@ void TextsRenderer::renderNote(
|
|||||||
pos + xvec * (width * 0.5f * preset.scale))) {
|
pos + xvec * (width * 0.5f * preset.scale))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
static FontStylesScheme styles {};
|
|
||||||
auto color = preset.color;
|
auto color = preset.color;
|
||||||
batch.setColor(glm::vec4(color.r, color.g, color.b, color.a * opacity));
|
batch.setColor(glm::vec4(color.r, color.g, color.b, color.a * opacity));
|
||||||
font.draw(
|
font.draw(
|
||||||
batch,
|
batch,
|
||||||
text,
|
text,
|
||||||
&styles,
|
nullptr,
|
||||||
|
0,
|
||||||
pos - xvec * (width * 0.5f) * preset.scale,
|
pos - xvec * (width * 0.5f) * preset.scale,
|
||||||
xvec * preset.scale,
|
xvec * preset.scale,
|
||||||
yvec * preset.scale
|
yvec * preset.scale
|
||||||
|
|||||||
@ -194,9 +194,9 @@ void SlotView::draw(const DrawContext* pctx, Assets* assets) {
|
|||||||
int y = pos.y+slotSize-16;
|
int y = pos.y+slotSize-16;
|
||||||
|
|
||||||
batch->setColor({0, 0, 0, 1.0f});
|
batch->setColor({0, 0, 0, 1.0f});
|
||||||
font->draw(*batch, text, x+1, y+1, nullptr);
|
font->draw(*batch, text, x+1, y+1, nullptr, 0);
|
||||||
batch->setColor(glm::vec4(1.0f));
|
batch->setColor(glm::vec4(1.0f));
|
||||||
font->draw(*batch, text, x, y, nullptr);
|
font->draw(*batch, text, x, y, nullptr, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -203,10 +203,10 @@ void Label::draw(const DrawContext* pctx, Assets* assets) {
|
|||||||
if (i < cache.lines.size()-1) {
|
if (i < cache.lines.size()-1) {
|
||||||
view = std::wstring_view(text.c_str()+offset, cache.lines.at(i+1).offset-offset);
|
view = std::wstring_view(text.c_str()+offset, cache.lines.at(i+1).offset-offset);
|
||||||
}
|
}
|
||||||
font->draw(*batch, view, pos.x, pos.y + i * totalLineHeight, styles.get());
|
font->draw(*batch, view, pos.x, pos.y + i * totalLineHeight, styles.get(), offset);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
font->draw(*batch, text, pos.x, pos.y, styles.get());
|
font->draw(*batch, text, pos.x, pos.y, styles.get(), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -52,7 +52,8 @@ void Plotter::draw(const DrawContext* pctx, Assets* assets) {
|
|||||||
string,
|
string,
|
||||||
pos.x + dmwidth + 2,
|
pos.x + dmwidth + 2,
|
||||||
pos.y + dmheight - y - labelsInterval,
|
pos.y + dmheight - y - labelsInterval,
|
||||||
nullptr
|
nullptr,
|
||||||
|
0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "Label.hpp"
|
#include "Label.hpp"
|
||||||
|
#include "devtools/syntax_highlighting.hpp"
|
||||||
#include "graphics/core/DrawContext.hpp"
|
#include "graphics/core/DrawContext.hpp"
|
||||||
#include "graphics/core/Batch2D.hpp"
|
#include "graphics/core/Batch2D.hpp"
|
||||||
#include "graphics/core/Font.hpp"
|
#include "graphics/core/Font.hpp"
|
||||||
@ -65,11 +66,10 @@ void TextBox::draw(const DrawContext* pctx, Assets* assets) {
|
|||||||
lcoord.y -= 2;
|
lcoord.y -= 2;
|
||||||
auto batch = pctx->getBatch2D();
|
auto batch = pctx->getBatch2D();
|
||||||
batch->texture(nullptr);
|
batch->texture(nullptr);
|
||||||
|
batch->setColor(glm::vec4(1.0f));
|
||||||
if (editable && int((Window::time() - caretLastMove) * 2) % 2 == 0) {
|
if (editable && int((Window::time() - caretLastMove) * 2) % 2 == 0) {
|
||||||
uint line = label->getLineByTextIndex(caret);
|
uint line = label->getLineByTextIndex(caret);
|
||||||
uint lcaret = caret - label->getTextLineOffset(line);
|
uint lcaret = caret - label->getTextLineOffset(line);
|
||||||
batch->setColor(glm::vec4(1.0f));
|
|
||||||
|
|
||||||
int width = font->calcWidth(input, lcaret);
|
int width = font->calcWidth(input, lcaret);
|
||||||
batch->rect(lcoord.x + width, lcoord.y+label->getLineYOffset(line), 2, lineHeight);
|
batch->rect(lcoord.x + width, lcoord.y+label->getLineYOffset(line), 2, lineHeight);
|
||||||
}
|
}
|
||||||
@ -529,10 +529,21 @@ void TextBox::stepDefaultUp(bool shiftPressed, bool breakSelection) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextBox::refreshSyntax() {
|
||||||
|
if (!syntax.empty()) {
|
||||||
|
if (auto styles = devtools::syntax_highlight(
|
||||||
|
syntax, util::wstr2str_utf8(input)
|
||||||
|
)) {
|
||||||
|
label->setStyles(std::move(styles));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TextBox::onInput() {
|
void TextBox::onInput() {
|
||||||
if (subconsumer) {
|
if (subconsumer) {
|
||||||
subconsumer(input);
|
subconsumer(input);
|
||||||
}
|
}
|
||||||
|
refreshSyntax();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextBox::performEditingKeyboardEvents(keycode key) {
|
void TextBox::performEditingKeyboardEvents(keycode key) {
|
||||||
@ -710,6 +721,7 @@ const std::wstring& TextBox::getText() const {
|
|||||||
void TextBox::setText(const std::wstring& value) {
|
void TextBox::setText(const std::wstring& value) {
|
||||||
this->input = value;
|
this->input = value;
|
||||||
input.erase(std::remove(input.begin(), input.end(), '\r'), input.end());
|
input.erase(std::remove(input.begin(), input.end(), '\r'), input.end());
|
||||||
|
refreshSyntax();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::wstring& TextBox::getPlaceholder() const {
|
const std::wstring& TextBox::getPlaceholder() const {
|
||||||
@ -789,3 +801,12 @@ void TextBox::setShowLineNumbers(bool flag) {
|
|||||||
bool TextBox::isShowLineNumbers() const {
|
bool TextBox::isShowLineNumbers() const {
|
||||||
return showLineNumbers;
|
return showLineNumbers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextBox::setSyntax(const std::string& lang) {
|
||||||
|
syntax = lang;
|
||||||
|
if (syntax.empty()) {
|
||||||
|
label->setStyles(nullptr);
|
||||||
|
} else {
|
||||||
|
refreshSyntax();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -57,6 +57,8 @@ namespace gui {
|
|||||||
bool autoresize = false;
|
bool autoresize = false;
|
||||||
bool showLineNumbers = false;
|
bool showLineNumbers = false;
|
||||||
|
|
||||||
|
std::string syntax;
|
||||||
|
|
||||||
void stepLeft(bool shiftPressed, bool breakSelection);
|
void stepLeft(bool shiftPressed, bool breakSelection);
|
||||||
void stepRight(bool shiftPressed, bool breakSelection);
|
void stepRight(bool shiftPressed, bool breakSelection);
|
||||||
void stepDefaultDown(bool shiftPressed, bool breakSelection);
|
void stepDefaultDown(bool shiftPressed, bool breakSelection);
|
||||||
@ -84,6 +86,8 @@ namespace gui {
|
|||||||
void refreshLabel();
|
void refreshLabel();
|
||||||
|
|
||||||
void onInput();
|
void onInput();
|
||||||
|
|
||||||
|
void refreshSyntax();
|
||||||
public:
|
public:
|
||||||
TextBox(
|
TextBox(
|
||||||
std::wstring placeholder,
|
std::wstring placeholder,
|
||||||
@ -219,5 +223,7 @@ namespace gui {
|
|||||||
virtual std::shared_ptr<UINode> getAt(glm::vec2 pos, std::shared_ptr<UINode> self) override;
|
virtual std::shared_ptr<UINode> getAt(glm::vec2 pos, std::shared_ptr<UINode> self) override;
|
||||||
virtual void setOnUpPressed(const runnable &callback);
|
virtual void setOnUpPressed(const runnable &callback);
|
||||||
virtual void setOnDownPressed(const runnable &callback);
|
virtual void setOnDownPressed(const runnable &callback);
|
||||||
|
|
||||||
|
virtual void setSyntax(const std::string& lang);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -357,6 +357,9 @@ static std::shared_ptr<UINode> readTextBox(UiXmlReader& reader, const xml::xmlel
|
|||||||
}
|
}
|
||||||
textbox->setText(text);
|
textbox->setText(text);
|
||||||
|
|
||||||
|
if (element->has("syntax")) {
|
||||||
|
textbox->setSyntax(element->attr("syntax").getText());
|
||||||
|
}
|
||||||
if (element->has("multiline")) {
|
if (element->has("multiline")) {
|
||||||
textbox->setMultiline(element->attr("multiline").asBool());
|
textbox->setMultiline(element->attr("multiline").asBool());
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user