mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-08-13 04:42:12 +03:00
Line wrap WIP.
This commit is contained in:
@@ -32,6 +32,12 @@ class EE_API LineWrapping {
|
||||
bool operator!=( const Config& other ) { return !( *this == other ); }
|
||||
};
|
||||
|
||||
struct VisualLine {
|
||||
Int64 visualLineIndex;
|
||||
std::vector<TextPosition> visualLines;
|
||||
Float offset{ 0 };
|
||||
};
|
||||
|
||||
static LineWrapInfo computeLineBreaks( const String& string, const FontStyleConfig& fontStyle,
|
||||
Float maxWidth, LineWrapMode mode, bool keepIndentation,
|
||||
Uint32 tabWidth = 4 );
|
||||
@@ -43,6 +49,8 @@ class EE_API LineWrapping {
|
||||
|
||||
LineWrapping( std::shared_ptr<TextDocument> doc, FontStyleConfig fontStyle, Config config );
|
||||
|
||||
bool isWrapEnabled() const;
|
||||
|
||||
size_t getTotalLines() const;
|
||||
|
||||
const Config& config() const { return mConfig; }
|
||||
@@ -51,12 +59,26 @@ class EE_API LineWrapping {
|
||||
|
||||
void updateBreaks( Int64 fromLine, Int64 toLine, Int64 numLines );
|
||||
|
||||
Config getConfig() const { return mConfig; }
|
||||
|
||||
void setConfig( Config config );
|
||||
|
||||
void setMaxWidth( Float maxWidth );
|
||||
|
||||
void setFontStyle( FontStyleConfig fontStyle );
|
||||
|
||||
void setLineWrapMode( LineWrapMode mode );
|
||||
|
||||
TextPosition getDocumentLine( Int64 visibleIndex ) const;
|
||||
|
||||
Float getLineOffset( Int64 docIdx ) const;
|
||||
|
||||
Int64 toWrappedIndex( Int64 docIdx, bool retLast = false ) const;
|
||||
|
||||
bool isWrappedLine( Int64 docIdx ) const;
|
||||
|
||||
VisualLine getVisualLine( Int64 docIdx ) const;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<TextDocument> mDoc;
|
||||
FontStyleConfig mFontStyle;
|
||||
@@ -65,8 +87,6 @@ class EE_API LineWrapping {
|
||||
std::vector<TextPosition> mWrappedLines;
|
||||
std::vector<Float> mWrappedLinesOffset;
|
||||
std::vector<Int64> mWrappedLineToIndex;
|
||||
|
||||
Int64 toWrappedIndex( Int64 docIdx, bool retLast );
|
||||
};
|
||||
|
||||
}} // namespace EE::UI
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <eepp/ui/doc/syntaxhighlighter.hpp>
|
||||
#include <eepp/ui/doc/textdocument.hpp>
|
||||
#include <eepp/ui/keyboardshortcut.hpp>
|
||||
#include <eepp/ui/linewrapping.hpp>
|
||||
#include <eepp/ui/uifontstyleconfig.hpp>
|
||||
#include <eepp/ui/uiwidget.hpp>
|
||||
#include <unordered_map>
|
||||
@@ -72,23 +73,23 @@ class UICodeEditorPlugin {
|
||||
return false;
|
||||
}
|
||||
virtual void drawBeforeLineText( UICodeEditor*, const Int64&, Vector2f, const Float&,
|
||||
const Float& ){};
|
||||
const Float& ) {};
|
||||
virtual void drawAfterLineText( UICodeEditor* /*editor*/, const Int64& /*index*/,
|
||||
Vector2f /*position*/, const Float& /*fontSize*/,
|
||||
const Float& /*lineHeight*/ ){};
|
||||
const Float& /*lineHeight*/ ) {};
|
||||
virtual void minimapDrawBeforeLineText( UICodeEditor* /*editor*/, const Int64& /*index*/,
|
||||
const Vector2f& /*position*/, const Vector2f& /*size*/,
|
||||
const Float& /*charWidth*/,
|
||||
const Float& /*gutterWidth*/ ){};
|
||||
const Float& /*gutterWidth*/ ) {};
|
||||
virtual void minimapDrawAfterLineText( UICodeEditor*, const Int64&, const Vector2f&,
|
||||
const Vector2f&, const Float&, const Float& ){};
|
||||
const Vector2f&, const Float&, const Float& ) {};
|
||||
|
||||
virtual void drawGutter( UICodeEditor* /*editor*/, const Int64& /*index*/,
|
||||
const Vector2f& /*screenStart*/, const Float& /*lineHeight*/,
|
||||
const Float& /*gutterWidth*/, const Float& /*fontSize*/ ){};
|
||||
const Float& /*gutterWidth*/, const Float& /*fontSize*/ ) {};
|
||||
|
||||
virtual void drawTop( UICodeEditor* /*editor*/, const Vector2f& /*screenStart*/,
|
||||
const Sizef& /*size*/, const Float& /*fontSize*/ ){};
|
||||
const Sizef& /*size*/, const Float& /*fontSize*/ ) {};
|
||||
|
||||
Uint32 addOnReadyCallback( const OnReadyCb& cb ) {
|
||||
mOnReadyCallbacks[mReadyCbNum++] = cb;
|
||||
@@ -647,6 +648,7 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client {
|
||||
Font* mFont;
|
||||
UIFontStyleConfig mFontStyleConfig;
|
||||
std::shared_ptr<Doc::TextDocument> mDoc;
|
||||
LineWrapping mLineWrapping;
|
||||
Clock mBlinkTimer;
|
||||
Time mBlinkTime;
|
||||
bool mDirtyEditor{ false };
|
||||
@@ -939,6 +941,8 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client {
|
||||
void updateIMELocation();
|
||||
|
||||
void drawLockedIcon( const Vector2f start );
|
||||
|
||||
size_t getTotalVisibleLines() const;
|
||||
};
|
||||
|
||||
}} // namespace EE::UI
|
||||
|
||||
@@ -302,6 +302,7 @@
|
||||
../../include/eepp/thirdparty/chipmunk/cpSpace.h
|
||||
../../include/eepp/thirdparty/chipmunk/cpSpatialIndex.h
|
||||
../../include/eepp/thirdparty/chipmunk/cpVect.h
|
||||
../../include/eepp/ui/linewrapping.hpp
|
||||
../../include/eepp/ui/models/model.hpp
|
||||
../../include/eepp/ui/abstract/uiabstracttableview.hpp
|
||||
../../include/eepp/ui/abstract/uiabstractview.hpp
|
||||
@@ -1117,6 +1118,7 @@
|
||||
../../src/eepp/ui/doc/textformat.cpp
|
||||
../../src/eepp/ui/doc/textundostack.cpp
|
||||
../../src/eepp/ui/keyboardshortcut.cpp
|
||||
../../src/eepp/ui/linewrapping.cpp
|
||||
../../src/eepp/ui/models/filesystemmodel.cpp
|
||||
../../src/eepp/ui/models/model.cpp
|
||||
../../src/eepp/ui/models/modelindex.cpp
|
||||
|
||||
@@ -176,6 +176,10 @@ LineWrapping::LineWrapping( std::shared_ptr<TextDocument> doc, FontStyleConfig f
|
||||
mFontStyle( std::move( fontStyle ) ),
|
||||
mConfig( std::move( config ) ) {}
|
||||
|
||||
bool LineWrapping::isWrapEnabled() const {
|
||||
return mConfig.mode != LineWrapMode::NoWrap;
|
||||
}
|
||||
|
||||
void LineWrapping::setMaxWidth( Float maxWidth ) {
|
||||
if ( maxWidth != mMaxWidth ) {
|
||||
mMaxWidth = maxWidth;
|
||||
@@ -190,6 +194,25 @@ void LineWrapping::setFontStyle( FontStyleConfig fontStyle ) {
|
||||
}
|
||||
}
|
||||
|
||||
void LineWrapping::setLineWrapMode( LineWrapMode mode ) {
|
||||
if ( mode != mConfig.mode ) {
|
||||
mConfig.mode = mode;
|
||||
reconstructBreaks();
|
||||
}
|
||||
}
|
||||
|
||||
TextPosition LineWrapping::getDocumentLine( Int64 visibleIndex ) const {
|
||||
if ( mConfig.mode == LineWrapMode::NoWrap )
|
||||
return { visibleIndex, 0 };
|
||||
return mWrappedLines[eeclamp( visibleIndex, 0ll,
|
||||
static_cast<Int64>( mWrappedLines.size() - 1 ) )];
|
||||
}
|
||||
|
||||
Float LineWrapping::getLineOffset( Int64 docIdx ) const {
|
||||
return mWrappedLinesOffset[eeclamp( docIdx, 0ll,
|
||||
static_cast<Int64>( mWrappedLinesOffset.size() - 1 ) )];
|
||||
}
|
||||
|
||||
void LineWrapping::setConfig( Config config ) {
|
||||
if ( config != mConfig ) {
|
||||
mConfig = std::move( config );
|
||||
@@ -205,8 +228,11 @@ void LineWrapping::reconstructBreaks() {
|
||||
mWrappedLineToIndex.clear();
|
||||
mWrappedLinesOffset.clear();
|
||||
|
||||
if ( mConfig.mode == LineWrapMode::NoWrap )
|
||||
return;
|
||||
|
||||
Int64 linesCount = mDoc->linesCount();
|
||||
mWrappedLines.reserve( linesCount * 2 );
|
||||
mWrappedLines.reserve( linesCount );
|
||||
mWrappedLinesOffset.reserve( linesCount );
|
||||
|
||||
for ( auto i = 0; i < linesCount; i++ ) {
|
||||
@@ -230,13 +256,11 @@ void LineWrapping::reconstructBreaks() {
|
||||
}
|
||||
}
|
||||
|
||||
Int64 LineWrapping::toWrappedIndex( Int64 docIdx, bool retLast ) {
|
||||
auto idx =
|
||||
mWrappedLineToIndex[docIdx < 0
|
||||
? 0
|
||||
: ( docIdx >= static_cast<Int64>( mWrappedLineToIndex.size() )
|
||||
? mWrappedLineToIndex.size() - 1
|
||||
: docIdx )];
|
||||
Int64 LineWrapping::toWrappedIndex( Int64 docIdx, bool retLast ) const {
|
||||
if ( mConfig.mode == LineWrapMode::NoWrap )
|
||||
return docIdx;
|
||||
auto idx = mWrappedLineToIndex[eeclamp( docIdx, 0ll,
|
||||
static_cast<Int64>( mWrappedLineToIndex.size() - 1 ) )];
|
||||
if ( retLast ) {
|
||||
Int64 lastOfLine = mWrappedLines[idx].line();
|
||||
Int64 wrappedCount = mWrappedLines.size();
|
||||
@@ -250,7 +274,25 @@ Int64 LineWrapping::toWrappedIndex( Int64 docIdx, bool retLast ) {
|
||||
return idx;
|
||||
}
|
||||
|
||||
bool LineWrapping::isWrappedLine( Int64 docIdx ) const {
|
||||
return isWrapEnabled() && toWrappedIndex( docIdx ) != toWrappedIndex( docIdx, true );
|
||||
}
|
||||
|
||||
LineWrapping::VisualLine LineWrapping::getVisualLine( Int64 docIdx ) const {
|
||||
VisualLine line;
|
||||
Int64 fromIdx = toWrappedIndex( docIdx );
|
||||
Int64 toIdx = toWrappedIndex( docIdx, true );
|
||||
line.visualLineIndex = fromIdx;
|
||||
line.visualLines.reserve( toIdx - fromIdx + 1 );
|
||||
for ( Int64 i = fromIdx; i <= toIdx; i++ )
|
||||
line.visualLines.emplace_back( mWrappedLines[i] );
|
||||
line.offset = mWrappedLinesOffset[docIdx];
|
||||
return line;
|
||||
}
|
||||
|
||||
void LineWrapping::updateBreaks( Int64 fromLine, Int64 toLine, Int64 numLines ) {
|
||||
if ( mConfig.mode == LineWrapMode::NoWrap )
|
||||
return;
|
||||
// Get affected wrapped range
|
||||
Int64 oldIdxFrom = toWrappedIndex( fromLine, false );
|
||||
Int64 oldIdxTo = toWrappedIndex( toLine, true );
|
||||
|
||||
@@ -119,6 +119,7 @@ UICodeEditor::UICodeEditor( const std::string& elementTag, const bool& autoRegis
|
||||
UIWidget( elementTag ),
|
||||
mFont( FontManager::instance()->getByName( "monospace" ) ),
|
||||
mDoc( std::make_shared<TextDocument>() ),
|
||||
mLineWrapping( mDoc, mFontStyleConfig, {} ),
|
||||
mBlinkTime( Seconds( 0.5f ) ),
|
||||
mTabWidth( 4 ),
|
||||
mMouseWheelScroll( 50 ),
|
||||
@@ -160,6 +161,8 @@ UICodeEditor::UICodeEditor( const std::string& elementTag, const bool& autoRegis
|
||||
mDoc->registerClient( this );
|
||||
subscribeScheduledUpdate();
|
||||
|
||||
mLineWrapping.setLineWrapMode( LineWrapMode::Word );
|
||||
|
||||
if ( autoRegisterBaseCommands )
|
||||
registerCommands();
|
||||
if ( autoRegisterBaseKeybindings )
|
||||
@@ -267,10 +270,11 @@ void UICodeEditor::draw() {
|
||||
if ( !mLocked && mHighlightCurrentLine ) {
|
||||
for ( const auto& sel : mDoc->getSelections() ) {
|
||||
primitives.setColor( Color( mCurrentLineBackgroundColor ).blendAlpha( mAlpha ) );
|
||||
primitives.drawRectangle(
|
||||
Rectf( Vector2f( startScroll.x + mScroll.x,
|
||||
startScroll.y + sel.start().line() * lineHeight ),
|
||||
Sizef( mSize.getWidth(), lineHeight ) ) );
|
||||
primitives.drawRectangle( Rectf(
|
||||
Vector2f( startScroll.x + mScroll.x,
|
||||
startScroll.y +
|
||||
mLineWrapping.toWrappedIndex( sel.start().line() ) * lineHeight ),
|
||||
Sizef( mSize.getWidth(), lineHeight ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,7 +328,9 @@ void UICodeEditor::draw() {
|
||||
|
||||
for ( unsigned long i = lineRange.first; i <= lineRange.second; i++ ) {
|
||||
Vector2f curScroll(
|
||||
{ startScroll.x, static_cast<float>( startScroll.y + lineHeight * (double)i ) } );
|
||||
{ startScroll.x,
|
||||
static_cast<float>( startScroll.y +
|
||||
lineHeight * (double)mLineWrapping.toWrappedIndex( i ) ) } );
|
||||
|
||||
for ( auto& plugin : mPlugins )
|
||||
plugin->drawBeforeLineText( this, i, curScroll, charSize, lineHeight );
|
||||
@@ -349,7 +355,9 @@ void UICodeEditor::draw() {
|
||||
|
||||
if ( hasFocus() && getUISceneNode()->getWindow()->getIME().isEditing() ) {
|
||||
Vector2f cursorPos( startScroll.x + getXOffsetCol( cursor ),
|
||||
startScroll.y + cursor.line() * lineHeight + getLineOffset() );
|
||||
startScroll.y +
|
||||
mLineWrapping.toWrappedIndex( cursor.line() ) * lineHeight +
|
||||
getLineOffset() );
|
||||
FontStyleConfig config( mFontStyleConfig );
|
||||
config.FontColor = mFontStyleConfig.getFontSelectedColor();
|
||||
getUISceneNode()->getWindow()->getIME().draw( cursorPos, getFontHeight(), config,
|
||||
@@ -572,11 +580,15 @@ UICodeEditor* UICodeEditor::setFont( Font* font ) {
|
||||
void UICodeEditor::onFontChanged() {
|
||||
invalidateLinesCache();
|
||||
udpateGlyphWidth();
|
||||
mLineWrapping.setFontStyle( mFontStyleConfig );
|
||||
invalidateDraw();
|
||||
}
|
||||
|
||||
void UICodeEditor::onFontStyleChanged() {
|
||||
invalidateLinesCache();
|
||||
udpateGlyphWidth();
|
||||
mLineWrapping.setFontStyle( mFontStyleConfig );
|
||||
invalidateDraw();
|
||||
}
|
||||
|
||||
void UICodeEditor::onDocumentLoaded( TextDocument* ) {}
|
||||
@@ -586,6 +598,7 @@ void UICodeEditor::onDocumentReloaded( TextDocument* ) {
|
||||
sendEvent( &event );
|
||||
invalidateDraw();
|
||||
invalidateLongestLineWidth();
|
||||
mLineWrapping.reconstructBreaks();
|
||||
}
|
||||
|
||||
void UICodeEditor::onDocumentLoaded() {
|
||||
@@ -593,6 +606,7 @@ void UICodeEditor::onDocumentLoaded() {
|
||||
sendEvent( &event );
|
||||
invalidateDraw();
|
||||
invalidateLongestLineWidth();
|
||||
mLineWrapping.reconstructBreaks();
|
||||
}
|
||||
|
||||
void UICodeEditor::onDocumentChanged() {
|
||||
@@ -647,8 +661,6 @@ UICodeEditor* UICodeEditor::setFontSize( const Float& size ) {
|
||||
mFontStyleConfig.CharacterSize =
|
||||
eeabs( size - (int)size ) == 0.5f || (int)size == size ? size : eefloor( size );
|
||||
mFontSize = mFontStyleConfig.CharacterSize;
|
||||
udpateGlyphWidth();
|
||||
invalidateDraw();
|
||||
onFontChanged();
|
||||
}
|
||||
return this;
|
||||
@@ -702,7 +714,12 @@ const Uint32& UICodeEditor::getTabWidth() const {
|
||||
}
|
||||
|
||||
UICodeEditor* UICodeEditor::setTabWidth( const Uint32& tabWidth ) {
|
||||
mTabWidth = tabWidth;
|
||||
if ( mTabWidth != tabWidth ) {
|
||||
mTabWidth = tabWidth;
|
||||
auto config = mLineWrapping.getConfig();
|
||||
config.tabWidth = tabWidth;
|
||||
mLineWrapping.setConfig( config );
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -882,7 +899,7 @@ void UICodeEditor::invalidateLongestLineWidth() {
|
||||
mLongestLineWidthLastUpdate.restart();
|
||||
}
|
||||
|
||||
Uint32 UICodeEditor::onFocus( NodeFocusReason reason ) {
|
||||
Uint32 UICodeEditor::onFocus( NodeFocusReason reason ) {
|
||||
if ( !mLocked ) {
|
||||
mLastExecuteEventId = getUISceneNode()->getWindow()->getInput()->getEventsSentId();
|
||||
resetCursor();
|
||||
@@ -970,6 +987,10 @@ void UICodeEditor::drawLockedIcon( const Vector2f start ) {
|
||||
fileLockIcon->setColor( col );
|
||||
}
|
||||
|
||||
size_t UICodeEditor::getTotalVisibleLines() const {
|
||||
return mLineWrapping.getTotalLines();
|
||||
}
|
||||
|
||||
Uint32 UICodeEditor::onTextEditing( const TextEditingEvent& event ) {
|
||||
UIWidget::onTextEditing( event );
|
||||
mLastActivity.restart();
|
||||
@@ -1051,9 +1072,9 @@ Vector2f UICodeEditor::getViewPortLineCount() const {
|
||||
Sizef UICodeEditor::getMaxScroll() const {
|
||||
Vector2f vplc( getViewPortLineCount() );
|
||||
return Sizef( eemax( 0.f, mLongestLineWidth - getViewportWidth() ),
|
||||
vplc.y > mDoc->linesCount() - 1
|
||||
vplc.y > getTotalVisibleLines() - 1
|
||||
? 0.f
|
||||
: eefloor( mDoc->linesCount() - getViewPortLineCount().y ) *
|
||||
: eefloor( getTotalVisibleLines() - getViewPortLineCount().y ) *
|
||||
getLineHeight() );
|
||||
}
|
||||
|
||||
@@ -1524,7 +1545,8 @@ Vector2f UICodeEditor::getRelativeScreenPosition( const TextPosition& pos ) {
|
||||
Vector2f startScroll( start - mScroll );
|
||||
auto lineHeight = getLineHeight();
|
||||
return { startScroll.x + getXOffsetCol( pos ),
|
||||
startScroll.y + pos.line() * lineHeight + getLineOffset() };
|
||||
startScroll.y + mLineWrapping.toWrappedIndex( pos.line() ) * lineHeight +
|
||||
getLineOffset() };
|
||||
}
|
||||
|
||||
bool UICodeEditor::getShowLinesRelativePosition() const {
|
||||
@@ -1547,7 +1569,9 @@ void UICodeEditor::drawCursor( const Vector2f& startScroll, const Float& lineHei
|
||||
const TextPosition& cursor ) {
|
||||
if ( mCursorVisible && !mLocked && isTextSelectionEnabled() ) {
|
||||
Vector2f cursorPos( startScroll.x + getXOffsetCol( cursor ),
|
||||
startScroll.y + cursor.line() * lineHeight + getLineOffset() );
|
||||
startScroll.y +
|
||||
mLineWrapping.toWrappedIndex( cursor.line() ) * lineHeight +
|
||||
getLineOffset() );
|
||||
Primitives primitives;
|
||||
primitives.setColor( Color( mCaretColor ).blendAlpha( mAlpha ) );
|
||||
primitives.drawRectangle(
|
||||
@@ -1558,11 +1582,13 @@ void UICodeEditor::drawCursor( const Vector2f& startScroll, const Float& lineHei
|
||||
void UICodeEditor::onSizeChange() {
|
||||
UIWidget::onSizeChange();
|
||||
invalidateEditor( false );
|
||||
mLineWrapping.setMaxWidth( getViewportWidth() );
|
||||
}
|
||||
|
||||
void UICodeEditor::onPaddingChange() {
|
||||
UIWidget::onPaddingChange();
|
||||
invalidateEditor( false );
|
||||
mLineWrapping.setMaxWidth( getViewportWidth() );
|
||||
}
|
||||
|
||||
std::pair<size_t, Float> UICodeEditor::findLongestLineInRange( const TextRange& range ) {
|
||||
@@ -1728,6 +1754,8 @@ void UICodeEditor::onDocumentTextChanged( const DocumentContentChange& change )
|
||||
invalidateDraw();
|
||||
checkMatchingBrackets();
|
||||
sendCommonEvent( Event::OnTextChanged );
|
||||
mLineWrapping.updateBreaks( change.range.start().line(), change.range.end().line(),
|
||||
change.range.length() );
|
||||
|
||||
if ( !change.text.empty() ) {
|
||||
auto range = findLongestLineInRange( change.range );
|
||||
@@ -1808,6 +1836,8 @@ void UICodeEditor::onDocumentLineMove( const Int64& fromLine, const Int64& numLi
|
||||
}
|
||||
}
|
||||
}
|
||||
mLineWrapping.updateBreaks( fromLine, std::min( fromLine + numLines, linesCount - 1 ),
|
||||
numLines );
|
||||
} else if ( numLines < 0 ) {
|
||||
for ( Int64 i = fromLine; i < linesCount; i++ ) {
|
||||
auto lineIt = mLinesWidthCache.find( i - numLines );
|
||||
@@ -1818,6 +1848,7 @@ void UICodeEditor::onDocumentLineMove( const Int64& fromLine, const Int64& numLi
|
||||
mLinesWidthCache[i] = std::move( nl.mapped() );
|
||||
}
|
||||
}
|
||||
mLineWrapping.updateBreaks( std::max( 0ll, fromLine + numLines ), fromLine, numLines );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1829,8 +1860,13 @@ void UICodeEditor::onDocumentDirtyOnFileSystem( TextDocument* doc ) {
|
||||
std::pair<Uint64, Uint64> UICodeEditor::getVisibleLineRange() const {
|
||||
Float lineHeight = getLineHeight();
|
||||
Float minLine = eemax( 0.f, eefloor( mScroll.y / lineHeight ) );
|
||||
Float maxLine = eemin( mDoc->linesCount() - 1.f,
|
||||
Float maxLine = eemin( getTotalVisibleLines() - 1.f,
|
||||
eefloor( ( mSize.getHeight() + mScroll.y ) / lineHeight ) + 1 );
|
||||
if ( mLineWrapping.isWrapEnabled() ) {
|
||||
return std::make_pair<Uint64, Uint64>(
|
||||
(Uint64)mLineWrapping.getDocumentLine( minLine ).line(),
|
||||
(Uint64)mLineWrapping.getDocumentLine( maxLine ).line() );
|
||||
}
|
||||
return std::make_pair<Uint64, Uint64>( (Uint64)minLine, (Uint64)maxLine );
|
||||
}
|
||||
|
||||
@@ -3002,7 +3038,8 @@ void UICodeEditor::drawWordRanges( const TextRanges& ranges, const std::pair<int
|
||||
Rectf selRect;
|
||||
Int64 startCol = range.start().column();
|
||||
Int64 endCol = range.end().column();
|
||||
selRect.Top = startScroll.y + range.start().line() * lineHeight;
|
||||
selRect.Top =
|
||||
startScroll.y + mLineWrapping.toWrappedIndex( range.start().line() ) * lineHeight;
|
||||
selRect.Bottom = selRect.Top + lineHeight;
|
||||
selRect.Left = startScroll.x + getXOffsetCol( { range.start().line(), startCol } );
|
||||
selRect.Right = startScroll.x + getXOffsetCol( { range.start().line(), endCol } );
|
||||
@@ -3043,7 +3080,7 @@ void UICodeEditor::drawWordMatch( const String& text, const std::pair<int, int>&
|
||||
Rectf selRect;
|
||||
Int64 startCol = pos;
|
||||
Int64 endCol = pos + text.size();
|
||||
selRect.Top = startScroll.y + ln * lineHeight;
|
||||
selRect.Top = startScroll.y + mLineWrapping.toWrappedIndex( ln ) * lineHeight;
|
||||
selRect.Bottom = selRect.Top + lineHeight;
|
||||
selRect.Left = startScroll.x + getXOffsetCol( { ln, startCol } );
|
||||
selRect.Right = startScroll.x + getXOffsetCol( { ln, endCol } );
|
||||
@@ -3082,6 +3119,60 @@ void UICodeEditor::drawLineText( const Int64& line, Vector2f position, const Flo
|
||||
Sizef size;
|
||||
FontStyleConfig fontStyle( mFontStyleConfig );
|
||||
fontStyle.CharacterSize = fontSize;
|
||||
bool isWrappedLine = mLineWrapping.isWrappedLine( line );
|
||||
|
||||
if ( isWrappedLine ) {
|
||||
auto vline = mLineWrapping.getVisualLine( line );
|
||||
size_t curvline = 1;
|
||||
size_t nextLineCol = vline.visualLines[curvline].column();
|
||||
for ( const auto& token : tokens ) {
|
||||
const SyntaxColorScheme::Style& style = mColorScheme.getSyntaxStyle( token.type );
|
||||
fontStyle.Style = style.style;
|
||||
fontStyle.FontColor = Color( style.color ).blendAlpha( mAlpha );
|
||||
fontStyle.OutlineThickness = style.outlineThickness;
|
||||
if ( fontStyle.OutlineThickness )
|
||||
fontStyle.OutlineColor = style.outlineColor;
|
||||
|
||||
while ( pos <= strLine.size() ) {
|
||||
auto maxLength = nextLineCol - pos;
|
||||
String::View text = strLine.view().substr(
|
||||
pos, std::min( static_cast<size_t>( token.len ), maxLength ) );
|
||||
|
||||
if ( style.background != Color::Transparent ) {
|
||||
primitives.setColor( Color( style.background ).blendAlpha( mAlpha ) );
|
||||
primitives.drawRectangle(
|
||||
Rectf( position, Sizef( getTextWidth( text ), lineHeight ) ) );
|
||||
}
|
||||
|
||||
position.x += Text::draw( text, { position.x, position.y + lineOffset }, fontStyle,
|
||||
mTabWidth )
|
||||
.getWidth();
|
||||
pos += text.size();
|
||||
|
||||
if ( pos < nextLineCol || maxLength == 0 )
|
||||
break;
|
||||
|
||||
position.y += lineHeight;
|
||||
position.x = originalPosition.x + vline.offset;
|
||||
curvline++;
|
||||
// bool nbreak = pos == nextLineCol && nextLineCol - pos == 0;
|
||||
if ( curvline < vline.visualLines.size() ) {
|
||||
nextLineCol = vline.visualLines[curvline].column();
|
||||
} else {
|
||||
nextLineCol = strLine.size();
|
||||
}
|
||||
/*if ( nbreak )
|
||||
break;*/
|
||||
}
|
||||
}
|
||||
|
||||
if ( mDoc->mightBeBinary() && mFont->getType() == FontType::TTF ) {
|
||||
FontTrueType* ttf = static_cast<FontTrueType*>( mFont );
|
||||
ttf->setEnableFallbackFont( isFallbackFont );
|
||||
ttf->setEnableEmojiFallback( isEmojiFallbackFont );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for ( const auto& token : tokens ) {
|
||||
String::View text = strLine.view();
|
||||
@@ -3243,7 +3334,7 @@ void UICodeEditor::drawTextRange( const TextRange& range, const std::pair<int, i
|
||||
for ( auto ln = startLine; ln <= endLine; ln++ ) {
|
||||
const String& line = mDoc->line( ln ).getText();
|
||||
Rectf selRect;
|
||||
selRect.Top = startScroll.y + ln * lineHeight;
|
||||
selRect.Top = startScroll.y + mLineWrapping.toWrappedIndex( ln ) * lineHeight;
|
||||
selRect.Bottom = selRect.Top + lineHeight;
|
||||
if ( range.start().line() == ln ) {
|
||||
selRect.Left = startScroll.x + getXOffsetCol( { ln, range.start().column() } );
|
||||
@@ -3287,7 +3378,9 @@ void UICodeEditor::drawLineNumbers( const std::pair<int, int>& lineRange,
|
||||
}
|
||||
Text::draw( pos,
|
||||
Vector2f( screenStart.x + mLineNumberPaddingLeft,
|
||||
startScroll.y + lineHeight * (double)i + lineOffset ),
|
||||
startScroll.y +
|
||||
lineHeight * (double)mLineWrapping.toWrappedIndex( i ) +
|
||||
lineOffset ),
|
||||
mFontStyleConfig.Font, fontSize,
|
||||
( i >= selection.start().line() && i <= selection.end().line() )
|
||||
? mLineNumberActiveFontColor
|
||||
@@ -3303,10 +3396,13 @@ void UICodeEditor::drawColorPreview( const Vector2f& startScroll, const Float& l
|
||||
primitives.setColor( mPreviewColor );
|
||||
Float startX = getXOffsetCol( mPreviewColorRange.start() );
|
||||
Float endX = getXOffsetCol( mPreviewColorRange.end() );
|
||||
primitives.drawRectangle( Rectf(
|
||||
Vector2f( startScroll.x + mScroll.x + startX,
|
||||
startScroll.y + mPreviewColorRange.start().line() * lineHeight + lineHeight ),
|
||||
Sizef( endX - startX, lineHeight * 2 ) ) );
|
||||
primitives.drawRectangle(
|
||||
Rectf( Vector2f( startScroll.x + mScroll.x + startX,
|
||||
startScroll.y +
|
||||
mLineWrapping.toWrappedIndex( mPreviewColorRange.start().line() ) *
|
||||
lineHeight +
|
||||
lineHeight ),
|
||||
Sizef( endX - startX, lineHeight * 2 ) ) );
|
||||
}
|
||||
|
||||
void UICodeEditor::drawWhitespaces( const std::pair<int, int>& lineRange,
|
||||
@@ -3324,7 +3420,8 @@ void UICodeEditor::drawWhitespaces( const std::pair<int, int>& lineRange,
|
||||
adv->setColor( color );
|
||||
cpoint->setColor( color );
|
||||
for ( int index = lineRange.first; index <= lineRange.second; index++ ) {
|
||||
Vector2f position( { startScroll.x, startScroll.y + lineHeight * index } );
|
||||
Vector2f position(
|
||||
{ startScroll.x, startScroll.y + lineHeight * mLineWrapping.toWrappedIndex( index ) } );
|
||||
const auto& text = mDoc->line( index ).getText();
|
||||
for ( size_t i = 0; i < text.size(); i++ ) {
|
||||
if ( position.x + mScroll.x + ( text[i] == '\t' ? tabWidth : glyphW ) >= mScreenPos.x &&
|
||||
@@ -3381,7 +3478,8 @@ void UICodeEditor::drawIndentationGuides( const std::pair<int, int>& lineRange,
|
||||
? getTabWidth()
|
||||
: mDoc->getIndentWidth();
|
||||
for ( int index = lineRange.first; index <= lineRange.second; index++ ) {
|
||||
Vector2f position( { startScroll.x, startScroll.y + lineHeight * index } );
|
||||
Vector2f position(
|
||||
{ startScroll.x, startScroll.y + lineHeight * mLineWrapping.toWrappedIndex( index ) } );
|
||||
int spaces = getLineIndentGuideSpaces( *mDoc.get(), index, indentSize );
|
||||
for ( int i = 0; i < spaces; i += indentSize )
|
||||
p.drawRectangle( Rectf( { position.x + spaceW * i, position.y }, { w, lineHeight } ) );
|
||||
@@ -3400,7 +3498,7 @@ void UICodeEditor::drawLineEndings( const std::pair<int, int>& lineRange,
|
||||
nl->setColor( color );
|
||||
for ( int index = lineRange.first; index <= lineRange.second; index++ ) {
|
||||
Vector2f position( { startScroll.x + getLineWidth( index ) - getGlyphWidth(),
|
||||
startScroll.y + lineHeight * index } );
|
||||
startScroll.y + lineHeight * mLineWrapping.toWrappedIndex( index ) } );
|
||||
nl->draw( Vector2f( position.x, position.y ) );
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user