Skip to content

Commit

Permalink
support text colorization
Browse files Browse the repository at this point in the history
  • Loading branch information
scheffle committed Mar 4, 2024
1 parent 72c2129 commit c55805c
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 3 deletions.
60 changes: 58 additions & 2 deletions vstgui/lib/ctexteditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,12 @@ using CommandKeyArray = std::array<Key, static_cast<size_t> (ITextEditor::Comman
//------------------------------------------------------------------------
struct TextEditorView : public CView,
public ITextEditor,
public TextEditorColorization::IEditorExt,
public IFocusDrawing,
public ViewEventListenerAdapter
{
using Position = TextEditorColorization::Position;

TextEditorView (ITextEditorController* controller);
void beforeDelete () override;

Expand Down Expand Up @@ -256,6 +259,9 @@ struct TextEditorView : public CView,
void setFindOptions (FindOptions opt) const override;
void setFindString (std::string_view utf8Text) const override;

// TextEditorHighlighting::IEditorExt
std::u16string_view readText (size_t startOffset, size_t length) const override;

// commandos
bool doShifting (bool right) const;
void selectAll () const;
Expand Down Expand Up @@ -853,6 +859,16 @@ bool TextEditorView::setCommandKeyBinding (Command cmd, char16_t character, Virt
return true;
}

//------------------------------------------------------------------------
std::u16string_view TextEditorView::readText (size_t startOffset, size_t length) const
{
if (startOffset >= md.model.text.length () || md.model.lines.empty ())
return {};
if (startOffset + length >= md.model.text.length ())
length = md.model.text.length () - startOffset;
return {md.model.text.data () + startOffset, length};
}

//------------------------------------------------------------------------
inline Range toLineSelection (const Range& line, size_t selStart, size_t selEnd)
{
Expand Down Expand Up @@ -882,6 +898,9 @@ void TextEditorView::drawRect (CDrawContext* context, const CRect& dirtyRect)
context->setDrawMode (kAntiAliasing);
context->drawRect (dirtyRect, kDrawFilled);

auto styleProvider = dynamic_cast<TextEditorColorization::IStyleProvider*> (md.controller);
if (styleProvider)
styleProvider->beginDraw (*this);
CCoord x = getViewSize ().left + md.style->leftMargin;
CCoord y = getViewSize ().top - md.style->lineSpacing;
for (auto index = 0u; index < md.model.lines.size (); ++index)
Expand All @@ -894,7 +913,6 @@ void TextEditorView::drawRect (CDrawContext* context, const CRect& dirtyRect)
continue;
context->setFontColor (md.style->textColor);
context->setFont (md.style->font);
auto lt = line.text;
auto selRange =
toLineSelection (line.range, md.editState.select_start, md.editState.select_end);
if (selRange)
Expand Down Expand Up @@ -922,8 +940,46 @@ void TextEditorView::drawRect (CDrawContext* context, const CRect& dirtyRect)
context->setFillColor (md.style->selectionBackColor);
context->drawRect (r, kDrawFilled);
}
context->drawString (lt.getPlatformString (), {x, y});
if (styleProvider)
{
auto lineX = x;
auto styles = styleProvider->getStyles (*this, line.range.start, line.range.length);
size_t start = line.range.start;
size_t end = 0u;
std::string tmpStr;
for (const auto& style : styles)
{
if (style.start != start)
{
tmpStr = convert (md.model.text.substr (start, style.start - start));
replaceTabs (tmpStr, md.style->tabWidth);
context->setFontColor (md.style->textColor);
context->drawString (tmpStr.data (), {lineX, y});
lineX += context->getStringWidth (tmpStr.data ());
}
start = style.start < line.range.start ? line.range.start : style.start;
end = start + style.length;
if (start == end)
continue;
if (end > line.range.start + line.range.length)
end = line.range.start + line.range.length;
tmpStr = convert (md.model.text.substr (start, end - start));
replaceTabs (tmpStr, md.style->tabWidth);
context->setFontColor (style.color);
context->drawString (tmpStr.data (), {lineX, y});
lineX += context->getStringWidth (tmpStr.data ());
start += style.length;
}
}
else
{
context->drawString (line.text.getPlatformString (), {x, y});
}
}

if (styleProvider)
styleProvider->endDraw (*this);

// cursor
if ((md.cursorIsVisible || md.cursorAlpha != 0.f) &&
md.editState.select_start == md.editState.select_end)
Expand Down
39 changes: 38 additions & 1 deletion vstgui/lib/ctexteditor.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
//------------------------------------------------------------------------
namespace VSTGUI {

struct ITextEditorController;
struct ITextEditor;
struct ITextEditorController;

//------------------------------------------------------------------------
/** Create a new texteditor
Expand Down Expand Up @@ -109,4 +109,41 @@ struct TextEditorControllerAdapter : ITextEditorController
};

//------------------------------------------------------------------------
namespace TextEditorColorization {

//------------------------------------------------------------------------
struct Position
{
uint32_t row;
uint32_t column;
};

//------------------------------------------------------------------------
/** extension to ITextEditor, use a dynamic_cast to get it from an ITextEditor */
struct IEditorExt
{
virtual std::u16string_view readText (size_t startOffset, size_t length) const = 0;
};

//------------------------------------------------------------------------
/** extension to ITextEditorController */
struct IStyleProvider
{
using IEditorExt = TextEditorColorization::IEditorExt;

struct Style
{
size_t start;
size_t length;
CColor color;
};
using Styles = std::vector<Style>;

virtual void beginDraw (const IEditorExt& editor) = 0;
virtual Styles getStyles (const IEditorExt& editor, size_t beginOffset, size_t length) = 0;
virtual void endDraw (const IEditorExt& editor) = 0;
};

//------------------------------------------------------------------------
} // TextEditorHighlighting
} // VSTGUI

0 comments on commit c55805c

Please sign in to comment.