Skip to content

Commit

Permalink
More WIP, getting closer.
Browse files Browse the repository at this point in the history
  • Loading branch information
SpartanJ committed May 15, 2024
1 parent 8c404f0 commit bb7df84
Show file tree
Hide file tree
Showing 12 changed files with 292 additions and 81 deletions.
7 changes: 1 addition & 6 deletions include/eepp/math/math.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,7 @@ template <typename T> inline T roundDown( T x ) {

/** @return The number of digits in a number. */
template <typename T> static T countDigits( T num ) {
T count = 0;
while ( num != 0 ) {
count++;
num /= 10;
}
return count;
return num == 0 ? 1 : (T)log10( std::abs( num ) ) + 1;
}

}} // namespace EE::Math
Expand Down
15 changes: 14 additions & 1 deletion include/eepp/ui/linewrapping.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,18 @@ namespace EE { namespace UI {

enum class LineWrapMode { NoWrap, Letter, Word };

enum class LineWrapType { Viewport, LineBreakingColumn };

class EE_API LineWrapping {
public:
static LineWrapMode toLineWrapMode( std::string mode );

static std::string fromLineWrapMode( LineWrapMode mode );

static LineWrapType toLineWrapType( std::string type );

static std::string fromLineWrapType( LineWrapType type );

struct Config {
LineWrapMode mode{ LineWrapMode::NoWrap };
bool keepIndentation{ true };
Expand Down Expand Up @@ -68,7 +78,7 @@ class EE_API LineWrapping {

void setConfig( Config config );

void setMaxWidth( Float maxWidth );
void setMaxWidth( Float maxWidth, bool forceReconstructBreaks = false );

void setFontStyle( FontStyleConfig fontStyle );

Expand All @@ -88,6 +98,9 @@ class EE_API LineWrapping {

TextRange getVisualLineRange( Int64 visualLine ) const;

std::shared_ptr<TextDocument> getDocument() const;
void setDocument( const std::shared_ptr<TextDocument>& doc );

protected:
std::shared_ptr<TextDocument> mDoc;
FontStyleConfig mFontStyle;
Expand Down
16 changes: 16 additions & 0 deletions include/eepp/ui/uicodeeditor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,20 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client {

void invalidateLongestLineWidth();

const LineWrapping& lineWrapping() const { return mLineWrapping; }

LineWrapMode getLineWrapMode() const { return mLineWrapping.getConfig().mode; }

void setLineWrapMode( LineWrapMode mode );

LineWrapType getLineWrapType() const;

void setLineWrapType( LineWrapType lineWrapType );

bool getLineWrapKeepIndentation() const { return mLineWrapping.getConfig().keepIndentation; }

void setLineWrapKeepIndentation( bool keep );

protected:
struct LastXOffset {
TextPosition position{ 0, 0 };
Expand Down Expand Up @@ -692,6 +706,7 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client {
bool mShowIndentationGuides{ false };
bool mShowLinesRelativePosition{ false };
bool mDisplayLockedIcon{ false };
bool mInvalidateOnLoaded{ false };
std::atomic<size_t> mHighlightWordProcessing{ false };
TextRange mLinkPosition;
String mLink;
Expand Down Expand Up @@ -767,6 +782,7 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client {
size_t mJumpLinesLength{ 5 };
UIIcon* mFileLockIcon{ nullptr };
std::string mFileLockIconName{ "file-lock-fill" };
LineWrapType mLineWrapType{ LineWrapType::Viewport };

UICodeEditor( const std::string& elementTag, const bool& autoRegisterBaseCommands = true,
const bool& autoRegisterBaseKeybindings = true );
Expand Down
4 changes: 2 additions & 2 deletions src/eepp/ui/doc/textdocument.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1299,8 +1299,8 @@ size_t TextDocument::remove( const size_t& cursorIdx, TextRange range,
}

if ( linesRemoved > 0 ) {
mHighlighter->moveHighlight( range.start().line(), -linesRemoved );
notifiyDocumenLineMove( range.start().line(), -linesRemoved );
mHighlighter->moveHighlight( range.end().line(), -linesRemoved );
notifiyDocumenLineMove( range.end().line(), -linesRemoved );
}

notifyTextChanged( { originalRange, "" } );
Expand Down
136 changes: 91 additions & 45 deletions src/eepp/ui/linewrapping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,44 @@

namespace EE { namespace UI {

LineWrapMode LineWrapping::toLineWrapMode( std::string mode ) {
String::toLowerInPlace( mode );
if ( mode == "word" )
return LineWrapMode::Word;
if ( mode == "letter" )
return LineWrapMode::Letter;
return LineWrapMode::NoWrap;
}

std::string LineWrapping::fromLineWrapMode( LineWrapMode mode ) {
switch ( mode ) {
case LineWrapMode::Letter:
return "letter";
case LineWrapMode::Word:
return "word";
case LineWrapMode::NoWrap:
default:
return "nowrap";
}
}

LineWrapType LineWrapping::toLineWrapType( std::string type ) {
String::toLowerInPlace( type );
if ( "line_breaking_column" == type )
return LineWrapType::LineBreakingColumn;
return LineWrapType::Viewport;
}

std::string LineWrapping::fromLineWrapType( LineWrapType type ) {
switch ( type ) {
case LineWrapType::LineBreakingColumn:
return "line_breaking_column";
case LineWrapType::Viewport:
default:
return "viewport";
}
}

LineWrapping::LineWrapInfo LineWrapping::computeLineBreaks( const String& string,
const FontStyleConfig& fontStyle,
Float maxWidth, LineWrapMode mode,
Expand Down Expand Up @@ -68,7 +106,7 @@ LineWrapping::LineWrapInfo LineWrapping::computeLineBreaks( const String& string
xoffset = w + info.paddingStart;
}
lastSpace = 0;
} else if ( curChar == ' ' ) {
} else if ( curChar == ' ' || curChar == '.' ) {
lastSpace = idx;
lastWidth = xoffset;
}
Expand Down Expand Up @@ -101,6 +139,7 @@ LineWrapping::LineWrapInfo LineWrapping::computeLineBreaks( const TextDocument&
bool bold = ( fontStyle.Style & Text::Style::Bold ) != 0;
bool italic = ( fontStyle.Style & Text::Style::Italic ) != 0;
Float outlineThickness = fontStyle.OutlineThickness;
bool isMonospace = fontStyle.Font->isMonospace();

size_t lastSpace = 0;
Uint32 prevChar = 0;
Expand All @@ -120,47 +159,41 @@ LineWrapping::LineWrapInfo LineWrapping::computeLineBreaks( const TextDocument&
fontStyle, tabWidth );
}

Float w = Text::getTextWidth( text, fontStyle, tabWidth );

if ( xoffset + w > maxWidth ) {
for ( const auto& curChar : text ) {
Float w = fontStyle.Font
->getGlyph( curChar, fontStyle.CharacterSize, bold, italic,
outlineThickness )
.advance;

if ( curChar == '\t' )
w += hspace * tabWidth;
else if ( ( curChar ) == '\r' )
w = 0;
for ( const auto& curChar : text ) {
Float w = !isMonospace ? fontStyle.Font
->getGlyph( curChar, fontStyle.CharacterSize, bold, italic,
outlineThickness )
.advance
: hspace;

if ( curChar == '\t' )
w += hspace * tabWidth;
else if ( ( curChar ) == '\r' )
w = 0;

if ( !isMonospace && curChar != '\r' ) {
w += fontStyle.Font->getKerning( prevChar, curChar, fontStyle.CharacterSize, bold,
italic, outlineThickness );
prevChar = curChar;
}

if ( curChar != '\r' ) {
w += fontStyle.Font->getKerning( prevChar, curChar, fontStyle.CharacterSize,
bold, italic, outlineThickness );
prevChar = curChar;
}
xoffset += w;

xoffset += w;

if ( xoffset > maxWidth ) {
if ( mode == LineWrapMode::Word && lastSpace ) {
info.wraps.push_back( lastSpace + 1 );
xoffset = w + info.paddingStart + ( xoffset - lastWidth );
} else {
info.wraps.push_back( idx );
xoffset = w + info.paddingStart;
}
lastSpace = 0;
} else if ( curChar == ' ' ) {
lastSpace = idx;
lastWidth = xoffset;
if ( xoffset > maxWidth ) {
if ( mode == LineWrapMode::Word && lastSpace ) {
info.wraps.push_back( lastSpace + 1 );
xoffset = w + info.paddingStart + ( xoffset - lastWidth );
} else {
info.wraps.push_back( idx );
xoffset = w + info.paddingStart;
}

idx++;
lastSpace = 0;
} else if ( curChar == ' ' || curChar == '.' ) {
lastSpace = idx;
lastWidth = xoffset;
}
} else {
xoffset += w;
idx += text.size();

idx++;
}
}

Expand All @@ -177,10 +210,12 @@ bool LineWrapping::isWrapEnabled() const {
return mConfig.mode != LineWrapMode::NoWrap;
}

void LineWrapping::setMaxWidth( Float maxWidth ) {
void LineWrapping::setMaxWidth( Float maxWidth, bool forceReconstructBreaks ) {
if ( maxWidth != mMaxWidth ) {
mMaxWidth = maxWidth;
reconstructBreaks();
} else if ( forceReconstructBreaks ) {
reconstructBreaks();
}
}

Expand All @@ -199,17 +234,17 @@ void LineWrapping::setLineWrapMode( LineWrapMode mode ) {
}

TextPosition LineWrapping::getDocumentLine( Int64 visibleIndex ) const {
if ( mConfig.mode == LineWrapMode::NoWrap )
if ( mConfig.mode == LineWrapMode::NoWrap || mWrappedLines.empty() )
return { visibleIndex, 0 };
return mWrappedLines[eeclamp( visibleIndex, 0ll,
static_cast<Int64>( mWrappedLines.size() - 1 ) )];
eemax( static_cast<Int64>( mWrappedLines.size() ) - 1, 0ll ) )];
}

Float LineWrapping::getLineOffset( Int64 docIdx ) const {
if ( mConfig.mode == LineWrapMode::NoWrap )
if ( mConfig.mode == LineWrapMode::NoWrap || mWrappedLinesOffset.empty() )
return 0;
return mWrappedLinesOffset[eeclamp( docIdx, 0ll,
static_cast<Int64>( mWrappedLinesOffset.size() - 1 ) )];
return mWrappedLinesOffset[eeclamp(
docIdx, 0ll, eemax( static_cast<Int64>( mWrappedLinesOffset.size() ) - 1, 0ll ) )];
}

void LineWrapping::setConfig( Config config ) {
Expand All @@ -220,7 +255,7 @@ void LineWrapping::setConfig( Config config ) {
}

void LineWrapping::reconstructBreaks() {
if ( 0 == mMaxWidth || mDoc->isLoading() )
if ( 0 == mMaxWidth || !mDoc || mDoc->isLoading() )
return;

mWrappedLines.clear();
Expand Down Expand Up @@ -335,6 +370,17 @@ TextRange LineWrapping::getVisualLineRange( Int64 visualLine ) const {
return { start, end };
}

std::shared_ptr<TextDocument> LineWrapping::getDocument() const {
return mDoc;
}

void LineWrapping::setDocument( const std::shared_ptr<TextDocument>& doc ) {
if ( mDoc != doc ) {
mDoc = doc;
reconstructBreaks();
}
}

void LineWrapping::updateBreaks( Int64 fromLine, Int64 toLine, Int64 numLines ) {
if ( mConfig.mode == LineWrapMode::NoWrap )
return;
Expand Down

0 comments on commit bb7df84

Please sign in to comment.