mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-08-18 06:55:48 +03:00
Implemented tab-stops support (SpartanJ/ecode#55). Not enabled by default until I'm sure I did not break anything.
This commit is contained in:
@@ -156,6 +156,18 @@ shapeAndRun( const String& string, const FontStyleConfig& config,
|
||||
|
||||
} // namespace
|
||||
|
||||
Float Text::tabAdvance( Float hspace, Uint32 tabWidth, std::optional<Float> tabOffset ) {
|
||||
Float advance = hspace * tabWidth;
|
||||
if ( tabOffset ) {
|
||||
Float offset = fmodf( *tabOffset, advance );
|
||||
advance = advance - offset;
|
||||
// If there is not enough space until the next stop, skip it
|
||||
if ( advance < hspace )
|
||||
advance += hspace * tabWidth;
|
||||
}
|
||||
return advance;
|
||||
}
|
||||
|
||||
bool Text::TextShaperEnabled = false;
|
||||
|
||||
std::string Text::styleFlagToString( const Uint32& flags ) {
|
||||
@@ -216,28 +228,33 @@ Uint32 Text::stringToStyleFlag( const std::string& str ) {
|
||||
|
||||
Float Text::getTextWidth( Font* font, const Uint32& fontSize, const String& string,
|
||||
const Uint32& style, const Uint32& tabWidth,
|
||||
const Float& outlineThickness, Uint32 textDrawHints ) {
|
||||
const Float& outlineThickness, Uint32 textDrawHints,
|
||||
std::optional<Float> tabOffset ) {
|
||||
return getTextWidth<String>( font, fontSize, string, style, tabWidth, outlineThickness,
|
||||
textDrawHints );
|
||||
textDrawHints, tabOffset );
|
||||
}
|
||||
|
||||
Float Text::getTextWidth( Font* font, const Uint32& fontSize, const String::View& string,
|
||||
const Uint32& style, const Uint32& tabWidth,
|
||||
const Float& outlineThickness, Uint32 textDrawHints ) {
|
||||
const Float& outlineThickness, Uint32 textDrawHints,
|
||||
std::optional<Float> tabOffset ) {
|
||||
return getTextWidth<String::View>( font, fontSize, string, style, tabWidth, outlineThickness,
|
||||
textDrawHints );
|
||||
textDrawHints, tabOffset );
|
||||
}
|
||||
|
||||
Float Text::getTextWidth( const String& string, const FontStyleConfig& config,
|
||||
const Uint32& tabWidth, Uint32 textDrawHints ) {
|
||||
const Uint32& tabWidth, Uint32 textDrawHints,
|
||||
std::optional<Float> tabOffset ) {
|
||||
return getTextWidth<String>( config.Font, config.CharacterSize, string, config.Style, tabWidth,
|
||||
config.OutlineThickness, textDrawHints );
|
||||
config.OutlineThickness, textDrawHints, tabOffset );
|
||||
}
|
||||
|
||||
Float Text::getTextWidth( const String::View& string, const FontStyleConfig& config,
|
||||
const Uint32& tabWidth, Uint32 textDrawHints ) {
|
||||
const Uint32& tabWidth, Uint32 textDrawHints,
|
||||
std::optional<Float> tabOffset ) {
|
||||
return getTextWidth<String::View>( config.Font, config.CharacterSize, string, config.Style,
|
||||
tabWidth, config.OutlineThickness, textDrawHints );
|
||||
tabWidth, config.OutlineThickness, textDrawHints,
|
||||
tabOffset );
|
||||
}
|
||||
|
||||
Sizef Text::draw( const String& string, const Vector2f& pos, Font* font, Float fontSize,
|
||||
@@ -412,19 +429,9 @@ Sizef Text::draw( const StringType& string, const Vector2f& pos, Font* font, Flo
|
||||
GlyphDrawable* spaceGlyph = nullptr;
|
||||
GlyphDrawable* tabGlyph = nullptr;
|
||||
Float hspace = font->getGlyph( ' ', fontSize, isBold, isItalic ).advance;
|
||||
if ( whitespaceDisplayConfig.tabDisplayCharacter ) {
|
||||
std::optional<Float> tabOffset{ whitespaceDisplayConfig.tabOffset };
|
||||
if ( whitespaceDisplayConfig.tabDisplayCharacter )
|
||||
tabGlyph = font->getGlyphDrawable( whitespaceDisplayConfig.tabDisplayCharacter, fontSize );
|
||||
switch ( whitespaceDisplayConfig.tabAlign ) {
|
||||
case CharacterAlignment::Center:
|
||||
tabAlign = ( ( tabWidth * hspace ) - tabGlyph->getPixelsSize().getWidth() ) * 0.5f;
|
||||
break;
|
||||
case CharacterAlignment::Right:
|
||||
tabAlign = ( tabWidth * hspace ) - tabGlyph->getPixelsSize().getWidth();
|
||||
break;
|
||||
case CharacterAlignment::Left:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BR->setBlendMode( BlendMode::Alpha() );
|
||||
BR->quadsBegin();
|
||||
@@ -445,12 +452,30 @@ Sizef Text::draw( const StringType& string, const Vector2f& pos, Font* font, Flo
|
||||
cluster = curGlyph.cluster;
|
||||
ch = string[cluster];
|
||||
if ( ch == '\t' ) {
|
||||
Float advance = tabAdvance( hspace, tabWidth,
|
||||
tabOffset ? cpos.x - pos.x + *tabOffset
|
||||
: std::optional<Float>{} );
|
||||
|
||||
if ( whitespaceDisplayConfig.tabDisplayCharacter ) {
|
||||
switch ( whitespaceDisplayConfig.tabAlign ) {
|
||||
case CharacterAlignment::Center:
|
||||
tabAlign =
|
||||
( advance - tabGlyph->getPixelsSize().getWidth() ) * 0.5f;
|
||||
break;
|
||||
case CharacterAlignment::Right:
|
||||
tabAlign = advance - tabGlyph->getPixelsSize().getWidth();
|
||||
break;
|
||||
case CharacterAlignment::Left:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( tabGlyph ) {
|
||||
drawGlyph( BR, tabGlyph, { cpos.x + tabAlign, cpos.y },
|
||||
whitespaceDisplayConfig.color, isItalic );
|
||||
}
|
||||
width += hspace * tabWidth;
|
||||
cpos.x += hspace * tabWidth;
|
||||
width += advance;
|
||||
cpos.x += advance;
|
||||
} else {
|
||||
if ( style & Text::Shadow ) {
|
||||
auto* gds = font->getGlyphDrawableFromGlyphIndex(
|
||||
@@ -552,7 +577,23 @@ Sizef Text::draw( const StringType& string, const Vector2f& pos, Font* font, Flo
|
||||
case '\r':
|
||||
continue;
|
||||
case '\t': {
|
||||
Float advance = hspace * tabWidth;
|
||||
Float advance =
|
||||
tabAdvance( hspace, tabWidth,
|
||||
tabOffset ? cpos.x - pos.x + *tabOffset : std::optional<Float>{} );
|
||||
|
||||
if ( whitespaceDisplayConfig.tabDisplayCharacter ) {
|
||||
switch ( whitespaceDisplayConfig.tabAlign ) {
|
||||
case CharacterAlignment::Center:
|
||||
tabAlign = ( advance - tabGlyph->getPixelsSize().getWidth() ) * 0.5f;
|
||||
break;
|
||||
case CharacterAlignment::Right:
|
||||
tabAlign = advance - tabGlyph->getPixelsSize().getWidth();
|
||||
break;
|
||||
case CharacterAlignment::Left:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( tabGlyph ) {
|
||||
drawGlyph( BR, tabGlyph, { cpos.x + tabAlign, cpos.y },
|
||||
whitespaceDisplayConfig.color, isItalic );
|
||||
@@ -657,10 +698,12 @@ Sizef Text::draw( const StringType& string, const Vector2f& pos, const FontStyle
|
||||
|
||||
template <typename StringType>
|
||||
bool Text::wrapText( Font* font, const Uint32& fontSize, StringType& string, const Float& maxWidth,
|
||||
const Uint32& style, const Uint32& tabWidth, const Float& outlineThickness ) {
|
||||
const Uint32& style, const Uint32& tabWidth, const Float& outlineThickness,
|
||||
std::optional<Float> tabOffset ) {
|
||||
if ( string.empty() || NULL == font )
|
||||
return false;
|
||||
|
||||
Float x = 0.f;
|
||||
Float tCurWidth = 0.f;
|
||||
Float tWordWidth = 0.f;
|
||||
auto tChar = &string[0];
|
||||
@@ -680,12 +723,13 @@ bool Text::wrapText( Font* font, const Uint32& fontSize, StringType& string, con
|
||||
Float fCharWidth = (Float)pChar.advance;
|
||||
|
||||
if ( ( *tChar ) == '\t' )
|
||||
fCharWidth = hspace * tabWidth;
|
||||
fCharWidth = tabAdvance( hspace, tabWidth, tabOffset ? ( *tabOffset + x ) : tabOffset );
|
||||
else if ( ( *tChar ) == '\r' )
|
||||
fCharWidth = 0;
|
||||
|
||||
// Add the new char width to the current word width
|
||||
tWordWidth += fCharWidth;
|
||||
x += fCharWidth;
|
||||
|
||||
if ( *tChar != '\r' ) {
|
||||
tWordWidth +=
|
||||
@@ -707,9 +751,11 @@ bool Text::wrapText( Font* font, const Uint32& fontSize, StringType& string, con
|
||||
*tLastSpace = '\n';
|
||||
tChar = tLastSpace + 1;
|
||||
wrapped = true;
|
||||
x = 0.f;
|
||||
} else { // The word is larger than the current possible width
|
||||
*tChar = '\n';
|
||||
wrapped = true;
|
||||
x = 0.f;
|
||||
}
|
||||
|
||||
if ( tChar == tLastChar )
|
||||
@@ -727,6 +773,7 @@ bool Text::wrapText( Font* font, const Uint32& fontSize, StringType& string, con
|
||||
} else if ( '\n' == *tChar ) {
|
||||
tWordWidth = 0.f;
|
||||
tCurWidth = 0.f;
|
||||
x = 0.f;
|
||||
tLastSpace = NULL;
|
||||
tChar++;
|
||||
} else {
|
||||
@@ -739,19 +786,21 @@ bool Text::wrapText( Font* font, const Uint32& fontSize, StringType& string, con
|
||||
|
||||
template <typename StringType>
|
||||
bool Text::wrapText( StringType& string, const Float& maxWidth, const FontStyleConfig& config,
|
||||
const Uint32& tabWidth ) {
|
||||
const Uint32& tabWidth, std::optional<Float> tabOffset ) {
|
||||
return wrapText<StringType>( config.Font, config.CharacterSize, string, maxWidth, config.Style,
|
||||
tabWidth, config.OutlineThickness );
|
||||
tabWidth, config.OutlineThickness, tabOffset );
|
||||
}
|
||||
|
||||
bool Text::wrapText( Font* font, const Uint32& fontSize, String& string, const Float& maxWidth,
|
||||
const Uint32& style, const Uint32& tabWidth, const Float& outlineThickness ) {
|
||||
return wrapText<String>( font, fontSize, string, maxWidth, style, tabWidth, outlineThickness );
|
||||
const Uint32& style, const Uint32& tabWidth, const Float& outlineThickness,
|
||||
std::optional<Float> tabOffset ) {
|
||||
return wrapText<String>( font, fontSize, string, maxWidth, style, tabWidth, outlineThickness,
|
||||
tabOffset );
|
||||
}
|
||||
|
||||
bool Text::wrapText( String& string, const Float& maxWidth, const FontStyleConfig& config,
|
||||
const Uint32& tabWidth ) {
|
||||
return wrapText<String>( string, maxWidth, config, tabWidth );
|
||||
const Uint32& tabWidth, std::optional<Float> tabOffset ) {
|
||||
return wrapText<String>( string, maxWidth, config, tabWidth, tabOffset );
|
||||
}
|
||||
|
||||
Text::Text() {}
|
||||
@@ -1004,7 +1053,8 @@ void Text::findWordFromCharacterIndex( Int32 characterIndex, Int32& initCur, Int
|
||||
template <typename StringType>
|
||||
Float Text::getTextWidth( Font* font, const Uint32& fontSize, const StringType& string,
|
||||
const Uint32& style, const Uint32& tabWidth,
|
||||
const Float& outlineThickness, Uint32 textDrawHints ) {
|
||||
const Float& outlineThickness, Uint32 textDrawHints,
|
||||
std::optional<Float> tabOffset ) {
|
||||
if ( NULL == font || string.empty() )
|
||||
return 0;
|
||||
Float width = 0;
|
||||
@@ -1028,7 +1078,10 @@ Float Text::getTextWidth( Font* font, const Uint32& fontSize, const StringType&
|
||||
if ( string[i] == '\n' ) {
|
||||
width = 0;
|
||||
} else {
|
||||
width += ( string[i] == '\t' ) ? hspace * tabWidth : hspace;
|
||||
width +=
|
||||
( string[i] == '\t' )
|
||||
? tabAdvance( hspace, tabWidth, tabOffset ? *tabOffset + width : tabOffset )
|
||||
: hspace;
|
||||
}
|
||||
maxWidth = eemax( width, maxWidth );
|
||||
}
|
||||
@@ -1047,7 +1100,8 @@ Float Text::getTextWidth( Font* font, const Uint32& fontSize, const StringType&
|
||||
hb_glyph_info_t curGlyph = glyphInfo[i];
|
||||
auto curChar = string[curGlyph.cluster];
|
||||
if ( curChar == '\t' ) {
|
||||
width += hspace * tabWidth;
|
||||
width += tabAdvance( hspace, tabWidth,
|
||||
tabOffset ? *tabOffset + width : tabOffset );
|
||||
} else {
|
||||
const Glyph& glyph = font->getGlyphByIndex(
|
||||
curGlyph.codepoint, fontSize, bold, italic, outlineThickness,
|
||||
@@ -1081,7 +1135,7 @@ Float Text::getTextWidth( Font* font, const Uint32& fontSize, const StringType&
|
||||
codepoint = string.at( i );
|
||||
Glyph glyph = font->getGlyph( codepoint, fontSize, bold, italic, outlineThickness );
|
||||
if ( codepoint == '\t' ) {
|
||||
width += hspace * tabWidth;
|
||||
width += tabAdvance( hspace, tabWidth, tabOffset ? *tabOffset + width : tabOffset );
|
||||
} else if ( codepoint == '\n' ) {
|
||||
width = 0;
|
||||
} else if ( codepoint != '\r' ) {
|
||||
@@ -1096,10 +1150,10 @@ Float Text::getTextWidth( Font* font, const Uint32& fontSize, const StringType&
|
||||
}
|
||||
|
||||
template <typename StringType>
|
||||
std::size_t Text::findLastCharPosWithinLength( Font* font, const Uint32& fontSize,
|
||||
const StringType& string, Float maxWidth,
|
||||
const Uint32& style, const Uint32& tabWidth,
|
||||
const Float& outlineThickness ) {
|
||||
std::size_t
|
||||
Text::findLastCharPosWithinLength( Font* font, const Uint32& fontSize, const StringType& string,
|
||||
Float maxWidth, const Uint32& style, const Uint32& tabWidth,
|
||||
const Float& outlineThickness, std::optional<Float> tabOffset ) {
|
||||
if ( NULL == font || string.empty() )
|
||||
return 0;
|
||||
String::StringBaseType codepoint;
|
||||
@@ -1127,7 +1181,8 @@ std::size_t Text::findLastCharPosWithinLength( Font* font, const Uint32& fontSiz
|
||||
auto curChar = string[curGlyph.cluster];
|
||||
|
||||
if ( curChar == '\t' ) {
|
||||
width += hspace * tabWidth;
|
||||
width += tabAdvance( hspace, tabWidth,
|
||||
tabOffset ? *tabOffset + width : tabOffset );
|
||||
} else {
|
||||
const Glyph& glyph = font->getGlyphByIndex(
|
||||
curGlyph.codepoint, fontSize, bold, italic, outlineThickness,
|
||||
@@ -1170,7 +1225,7 @@ std::size_t Text::findLastCharPosWithinLength( Font* font, const Uint32& fontSiz
|
||||
font->getKerning( prevChar, codepoint, fontSize, bold, italic, outlineThickness );
|
||||
width += glyph.advance;
|
||||
} else if ( codepoint == '\t' )
|
||||
width += hspace * tabWidth;
|
||||
width += tabAdvance( hspace, tabWidth, tabOffset ? *tabOffset + width : tabOffset );
|
||||
|
||||
if ( width > maxWidth )
|
||||
return i > 0 ? i - 1 : 0;
|
||||
@@ -1183,7 +1238,8 @@ std::size_t Text::findLastCharPosWithinLength( Font* font, const Uint32& fontSiz
|
||||
|
||||
Vector2f Text::findCharacterPos( std::size_t index, Font* font, const Uint32& fontSize,
|
||||
const String& string, const Uint32& style, const Uint32& tabWidth,
|
||||
const Float& outlineThickness, bool allowNewLine ) {
|
||||
const Float& outlineThickness, std::optional<Float> tabOffset,
|
||||
bool allowNewLine ) {
|
||||
// Make sure that we have a valid font
|
||||
if ( !font )
|
||||
return Vector2f();
|
||||
@@ -1227,7 +1283,9 @@ Vector2f Text::findCharacterPos( std::size_t index, Font* font, const Uint32& fo
|
||||
auto curChar = string[curGlyph.cluster];
|
||||
|
||||
if ( curChar == '\t' ) {
|
||||
position.x += hspace * tabWidth;
|
||||
position.x +=
|
||||
tabAdvance( hspace, tabWidth,
|
||||
tabOffset ? *tabOffset + position.x : tabOffset );
|
||||
} else {
|
||||
const Glyph& glyph = font->getGlyphByIndex(
|
||||
curGlyph.codepoint, fontSize, bold, italic, outlineThickness,
|
||||
@@ -1281,7 +1339,8 @@ Vector2f Text::findCharacterPos( std::size_t index, Font* font, const Uint32& fo
|
||||
position.x += hspace;
|
||||
continue;
|
||||
case '\t':
|
||||
position.x += hspace * tabWidth;
|
||||
position.x +=
|
||||
tabAdvance( hspace, tabWidth, tabOffset ? *tabOffset + position.x : tabOffset );
|
||||
continue;
|
||||
case '\n':
|
||||
if ( allowNewLine ) {
|
||||
@@ -1306,7 +1365,8 @@ Vector2f Text::findCharacterPos( std::size_t index, Font* font, const Uint32& fo
|
||||
|
||||
Int32 Text::findCharacterFromPos( const Vector2i& pos, bool returnNearest, Font* font,
|
||||
const Uint32& fontSize, const String& string, const Uint32& style,
|
||||
const Uint32& tabWidth, const Float& outlineThickness ) {
|
||||
const Uint32& tabWidth, const Float& outlineThickness,
|
||||
std::optional<Float> tabOffset ) {
|
||||
if ( NULL == font )
|
||||
return 0;
|
||||
|
||||
@@ -1341,7 +1401,8 @@ Int32 Text::findCharacterFromPos( const Vector2i& pos, bool returnNearest, Font*
|
||||
lWidth = width;
|
||||
|
||||
if ( curChar == '\t' ) {
|
||||
width += hspace * tabWidth;
|
||||
width += tabAdvance( hspace, tabWidth,
|
||||
tabOffset ? *tabOffset + width : tabOffset );
|
||||
} else {
|
||||
const Glyph& glyph = font->getGlyphByIndex(
|
||||
curGlyph.codepoint, fontSize, bold, italic, outlineThickness,
|
||||
@@ -1419,7 +1480,7 @@ Int32 Text::findCharacterFromPos( const Vector2i& pos, bool returnNearest, Font*
|
||||
prevChar = codepoint;
|
||||
width += glyph.advance;
|
||||
} else if ( codepoint == '\t' ) {
|
||||
width += hspace * tabWidth;
|
||||
width += tabAdvance( hspace, tabWidth, tabOffset ? *tabOffset + width : tabOffset );
|
||||
}
|
||||
if ( codepoint == '\n' ) {
|
||||
lWidth = 0;
|
||||
@@ -1462,32 +1523,37 @@ Int32 Text::findCharacterFromPos( const Vector2i& pos, bool returnNearest, Font*
|
||||
std::size_t Text::findLastCharPosWithinLength( Font* font, const Uint32& fontSize,
|
||||
const String& string, Float maxWidth,
|
||||
const Uint32& style, const Uint32& tabWidth,
|
||||
const Float& outlineThickness ) {
|
||||
const Float& outlineThickness,
|
||||
std::optional<Float> tabOffset ) {
|
||||
return findLastCharPosWithinLength<String>( font, fontSize, string, maxWidth, style, tabWidth,
|
||||
outlineThickness );
|
||||
outlineThickness, tabOffset );
|
||||
}
|
||||
|
||||
std::size_t Text::findLastCharPosWithinLength( Font* font, const Uint32& fontSize,
|
||||
const String::View& string, Float maxWidth,
|
||||
const Uint32& style, const Uint32& tabWidth,
|
||||
const Float& outlineThickness ) {
|
||||
const Float& outlineThickness,
|
||||
std::optional<Float> tabOffset ) {
|
||||
return findLastCharPosWithinLength<String::View>( font, fontSize, string, maxWidth, style,
|
||||
tabWidth, outlineThickness );
|
||||
tabWidth, outlineThickness, tabOffset );
|
||||
}
|
||||
|
||||
std::size_t Text::findLastCharPosWithinLength( const String& string, Float maxWidth,
|
||||
const FontStyleConfig& config,
|
||||
const Uint32& tabWidth ) {
|
||||
const Uint32& tabWidth,
|
||||
std::optional<Float> tabOffset ) {
|
||||
return findLastCharPosWithinLength<String>( config.Font, config.CharacterSize, string, maxWidth,
|
||||
config.Style, tabWidth, config.OutlineThickness );
|
||||
config.Style, tabWidth, config.OutlineThickness,
|
||||
tabOffset );
|
||||
}
|
||||
|
||||
std::size_t Text::findLastCharPosWithinLength( const String::View& string, Float maxWidth,
|
||||
const FontStyleConfig& config,
|
||||
const Uint32& tabWidth ) {
|
||||
const Uint32& tabWidth,
|
||||
std::optional<Float> tabOffset ) {
|
||||
return findLastCharPosWithinLength<String::View>( config.Font, config.CharacterSize, string,
|
||||
maxWidth, config.Style, tabWidth,
|
||||
config.OutlineThickness );
|
||||
config.OutlineThickness, tabOffset );
|
||||
}
|
||||
|
||||
void Text::updateWidthCache() {
|
||||
|
||||
@@ -50,13 +50,12 @@ std::string DocumentView::fromLineWrapType( LineWrapType type ) {
|
||||
}
|
||||
|
||||
Float DocumentView::computeOffsets( const String::View& string, const FontStyleConfig& fontStyle,
|
||||
Uint32 tabWidth, Float maxWidth ) {
|
||||
|
||||
Uint32 tabWidth, Float maxWidth, bool tabStops ) {
|
||||
static const String sepSpaces = " \t\n\v\f\r";
|
||||
auto nonIndentPos = string.find_first_not_of( sepSpaces.data() );
|
||||
if ( nonIndentPos != String::View::npos ) {
|
||||
Float w = Text::getTextWidth( string.substr( 0, nonIndentPos ), fontStyle, tabWidth,
|
||||
TextHints::AllAscii );
|
||||
TextHints::AllAscii, tabStops ? 0 : std::optional<Float>{} );
|
||||
return maxWidth != 0.f ? ( w > maxWidth ? 0.f : w ) : w;
|
||||
}
|
||||
return 0.f;
|
||||
@@ -67,7 +66,7 @@ DocumentView::LineWrapInfo DocumentView::computeLineBreaks( const String::View&
|
||||
Float maxWidth, LineWrapMode mode,
|
||||
bool keepIndentation, Uint32 tabWidth,
|
||||
Float whiteSpaceWidth, Uint32 textHints,
|
||||
Float initialXOffset ) {
|
||||
bool tabStops, Float initialXOffset ) {
|
||||
LineWrapInfo info;
|
||||
info.wraps.push_back( 0 );
|
||||
if ( string.empty() || nullptr == fontStyle.Font || mode == LineWrapMode::NoWrap )
|
||||
@@ -83,8 +82,8 @@ DocumentView::LineWrapInfo DocumentView::computeLineBreaks( const String::View&
|
||||
: whiteSpaceWidth;
|
||||
|
||||
if ( keepIndentation ) {
|
||||
info.paddingStart =
|
||||
computeOffsets( string, fontStyle, tabWidth, eemax( maxWidth - hspace, hspace ) );
|
||||
info.paddingStart = computeOffsets( string, fontStyle, tabWidth,
|
||||
eemax( maxWidth - hspace, hspace ), tabStops );
|
||||
}
|
||||
|
||||
Float xoffset = initialXOffset;
|
||||
@@ -108,7 +107,7 @@ DocumentView::LineWrapInfo DocumentView::computeLineBreaks( const String::View&
|
||||
: hspace;
|
||||
|
||||
if ( curChar == '\t' )
|
||||
w = hspace * tabWidth;
|
||||
w = Text::tabAdvance( hspace, tabWidth, tabStops ? w : std::optional<Float>{} );
|
||||
|
||||
if ( !isMonospace && curChar != '\r' ) {
|
||||
w += fontStyle.Font->getKerning( prevChar, curChar, fontStyle.CharacterSize, bold,
|
||||
@@ -143,22 +142,22 @@ DocumentView::LineWrapInfo DocumentView::computeLineBreaks( const String& string
|
||||
Float maxWidth, LineWrapMode mode,
|
||||
bool keepIndentation, Uint32 tabWidth,
|
||||
Float whiteSpaceWidth, Uint32 textHints,
|
||||
Float initialXOffset ) {
|
||||
bool tabStops, Float initialXOffset ) {
|
||||
return computeLineBreaks( string.view(), fontStyle, maxWidth, mode, keepIndentation, tabWidth,
|
||||
whiteSpaceWidth, textHints, initialXOffset );
|
||||
whiteSpaceWidth, textHints, tabStops, initialXOffset );
|
||||
}
|
||||
|
||||
DocumentView::LineWrapInfo DocumentView::computeLineBreaks( const TextDocument& doc, size_t line,
|
||||
const FontStyleConfig& fontStyle,
|
||||
Float maxWidth, LineWrapMode mode,
|
||||
bool keepIndentation, Uint32 tabWidth,
|
||||
Float whiteSpaceWidth,
|
||||
Float whiteSpaceWidth, bool tabStops,
|
||||
Float initialXOffset ) {
|
||||
const auto& docLine = doc.line( line );
|
||||
const auto& text = docLine.getText();
|
||||
return computeLineBreaks( text.view().substr( 0, text.size() - 1 ), fontStyle, maxWidth, mode,
|
||||
keepIndentation, tabWidth, whiteSpaceWidth, docLine.getTextHints(),
|
||||
initialXOffset );
|
||||
tabStops, initialXOffset );
|
||||
}
|
||||
|
||||
DocumentView::DocumentView( std::shared_ptr<TextDocument> doc, FontStyleConfig fontStyle,
|
||||
@@ -260,7 +259,7 @@ void DocumentView::invalidateCache() {
|
||||
} else {
|
||||
auto lb = wrap ? computeLineBreaks( *mDoc, i, mFontStyle, mMaxWidth, mConfig.mode,
|
||||
mConfig.keepIndentation, mConfig.tabWidth,
|
||||
mWhiteSpaceWidth )
|
||||
mWhiteSpaceWidth, mConfig.tabStops )
|
||||
: LineWrapInfo{ { 0 }, 0.f };
|
||||
mVisibleLinesOffset.emplace_back( lb.paddingStart );
|
||||
bool first = true;
|
||||
@@ -526,9 +525,9 @@ void DocumentView::updateCache( Int64 fromLine, Int64 toLine, Int64 numLines ) {
|
||||
eemax( mMaxWidth - mWhiteSpaceWidth, mWhiteSpaceWidth ) ) );
|
||||
mDocLineToVisibleIndex[i] = static_cast<Int64>( VisibleIndex::invalid );
|
||||
} else {
|
||||
auto lb =
|
||||
computeLineBreaks( *mDoc, i, mFontStyle, mMaxWidth, mConfig.mode,
|
||||
mConfig.keepIndentation, mConfig.tabWidth, mWhiteSpaceWidth );
|
||||
auto lb = computeLineBreaks( *mDoc, i, mFontStyle, mMaxWidth, mConfig.mode,
|
||||
mConfig.keepIndentation, mConfig.tabWidth,
|
||||
mWhiteSpaceWidth, mConfig.tabStops );
|
||||
|
||||
mVisibleLinesOffset.insert( mVisibleLinesOffset.begin() + i, lb.paddingStart );
|
||||
|
||||
@@ -680,10 +679,11 @@ void DocumentView::changeVisibility( Int64 fromDocIdx, Int64 toDocIdx, bool visi
|
||||
}
|
||||
continue;
|
||||
}
|
||||
auto lb = isWrapEnabled() ? computeLineBreaks( *mDoc, i, mFontStyle, mMaxWidth,
|
||||
mConfig.mode, mConfig.keepIndentation,
|
||||
mConfig.tabWidth, mWhiteSpaceWidth )
|
||||
: LineWrapInfo{ { 0 }, 0 };
|
||||
auto lb = isWrapEnabled()
|
||||
? computeLineBreaks( *mDoc, i, mFontStyle, mMaxWidth, mConfig.mode,
|
||||
mConfig.keepIndentation, mConfig.tabWidth,
|
||||
mWhiteSpaceWidth, mConfig.tabStops )
|
||||
: LineWrapInfo{ { 0 }, 0 };
|
||||
if ( recomputeOffset )
|
||||
mVisibleLinesOffset[i] = lb.paddingStart;
|
||||
for ( const auto& col : lb.wraps ) {
|
||||
@@ -824,4 +824,11 @@ void DocumentView::setOnFoldUnfoldCb(
|
||||
mOnFoldUnfoldCb = std::move( onFoldUnfoldCb );
|
||||
}
|
||||
|
||||
void DocumentView::setTabStops( bool enabled ) {
|
||||
if ( enabled != mConfig.tabStops ) {
|
||||
mConfig.tabStops = enabled;
|
||||
invalidateCache();
|
||||
}
|
||||
}
|
||||
|
||||
}}} // namespace EE::UI::Doc
|
||||
|
||||
@@ -122,7 +122,7 @@ UICodeEditor::UICodeEditor( const std::string& elementTag, const bool& autoRegis
|
||||
UIWidget( elementTag ),
|
||||
mFont( FontManager::instance()->getByName( "monospace" ) ),
|
||||
mDoc( std::make_shared<TextDocument>() ),
|
||||
mDocView( mDoc, mFontStyleConfig, {} ),
|
||||
mDocView( mDoc, mFontStyleConfig, { .tabStops = mTabStops } ),
|
||||
mBlinkTime( Seconds( 0.5f ) ),
|
||||
mFoldsRefreshTime( Seconds( 2.f ) ),
|
||||
mTabWidth( 4 ),
|
||||
@@ -2019,12 +2019,13 @@ Float UICodeEditor::getLineWidth( const Int64& docLine ) {
|
||||
auto found = mLinesWidthCache.find( docLine );
|
||||
if ( found != mLinesWidthCache.end() && line.getHash() == found->second.first )
|
||||
return found->second.second;
|
||||
Float width = getTextWidth( line.getText() );
|
||||
Float width = getTextWidth( line.getText(), {}, mTabStops ? 0 : std::optional<Float>{} );
|
||||
mLinesWidthCache[docLine] = { line.getHash(), width };
|
||||
return width;
|
||||
}
|
||||
|
||||
return getTextWidth( mDoc->line( docLine ).getText(), isMonospaceLine );
|
||||
return getTextWidth( mDoc->line( docLine ).getText(), isMonospaceLine,
|
||||
mTabStops ? 0 : std::optional<Float>{} );
|
||||
}
|
||||
|
||||
void UICodeEditor::updateScrollBar() {
|
||||
@@ -2455,7 +2456,8 @@ Vector2d UICodeEditor::getTextPositionOffset( const TextPosition& position,
|
||||
Float x =
|
||||
Text::findCharacterPos( position.column() - info.range.start().column(), mFont,
|
||||
getCharacterSize(), partialLine, mFontStyleConfig.Style,
|
||||
mTabWidth, mFontStyleConfig.OutlineThickness, false )
|
||||
mTabWidth, mFontStyleConfig.OutlineThickness,
|
||||
mTabStops ? 0 : std::optional<Float>(), false )
|
||||
.x;
|
||||
if ( visualizeNewLine && allowVisualLineEnd &&
|
||||
position.column() == (Int64)mDoc->line( position.line() ).getText().size() - 1 )
|
||||
@@ -2468,7 +2470,8 @@ Vector2d UICodeEditor::getTextPositionOffset( const TextPosition& position,
|
||||
Int64 maxCol = eemin( position.column(), info.range.end().column() );
|
||||
for ( auto i = info.range.start().column(); i < maxCol; i++ ) {
|
||||
if ( line[i] == '\t' ) {
|
||||
x += glyphWidth * mTabWidth;
|
||||
x += Text::tabAdvance( glyphWidth, mTabWidth,
|
||||
mTabStops ? x : std::optional<Float>{} );
|
||||
} else if ( visualizeNewLine || ( line[i] != '\n' && line[i] != '\r' ) ) {
|
||||
x += glyphWidth;
|
||||
}
|
||||
@@ -2483,11 +2486,12 @@ Vector2d UICodeEditor::getTextPositionOffset( const TextPosition& position,
|
||||
if ( !isMonospaceLine( position.line() ) ) {
|
||||
bool isLastChar =
|
||||
position.column() == (Int64)mDoc->line( position.line() ).getText().size();
|
||||
Float x = Text::findCharacterPos(
|
||||
isLastChar ? position.column() - 1 : position.column(), mFont,
|
||||
getCharacterSize(), mDoc->line( position.line() ).getText(),
|
||||
mFontStyleConfig.Style, mTabWidth, mFontStyleConfig.OutlineThickness, false )
|
||||
.x;
|
||||
Float x =
|
||||
Text::findCharacterPos(
|
||||
isLastChar ? position.column() - 1 : position.column(), mFont, getCharacterSize(),
|
||||
mDoc->line( position.line() ).getText(), mFontStyleConfig.Style, mTabWidth,
|
||||
mFontStyleConfig.OutlineThickness, mTabStops ? 0 : std::optional<Float>(), false )
|
||||
.x;
|
||||
if ( visualizeNewLine && isLastChar )
|
||||
x += getGlyphWidth();
|
||||
return { x, offsetY };
|
||||
@@ -2499,7 +2503,7 @@ Vector2d UICodeEditor::getTextPositionOffset( const TextPosition& position,
|
||||
Int64 maxCol = eemin( (Int64)line.size(), position.column() );
|
||||
for ( auto i = 0; i < maxCol; i++ ) {
|
||||
if ( line[i] == '\t' ) {
|
||||
x += glyphWidth * mTabWidth;
|
||||
x += Text::tabAdvance( glyphWidth, mTabWidth, mTabStops ? x : std::optional<Float>{} );
|
||||
} else if ( visualizeNewLine || ( line[i] != '\n' && line[i] != '\r' ) ) {
|
||||
x += glyphWidth;
|
||||
}
|
||||
@@ -2519,31 +2523,34 @@ size_t UICodeEditor::characterWidth( const String& str ) const {
|
||||
return characterWidth<String>( str );
|
||||
}
|
||||
|
||||
Float UICodeEditor::getTextWidth( const String& text ) const {
|
||||
return getTextWidth<String>( text, false );
|
||||
Float UICodeEditor::getTextWidth( const String& text, std::optional<Float> tabOffset ) const {
|
||||
return getTextWidth<String>( text, false, tabOffset );
|
||||
}
|
||||
|
||||
size_t UICodeEditor::characterWidth( const String::View& str ) const {
|
||||
return characterWidth<String::View>( str );
|
||||
}
|
||||
|
||||
Float UICodeEditor::getTextWidth( const String::View& text ) const {
|
||||
return getTextWidth<String::View>( text, false );
|
||||
Float UICodeEditor::getTextWidth( const String::View& text, std::optional<Float> tabOffset ) const {
|
||||
return getTextWidth<String::View>( text, false, tabOffset );
|
||||
}
|
||||
|
||||
Float UICodeEditor::getTextWidth( const String& text, bool fromMonospaceLine ) const {
|
||||
return getTextWidth<String>( text, fromMonospaceLine );
|
||||
Float UICodeEditor::getTextWidth( const String& text, bool fromMonospaceLine,
|
||||
std::optional<Float> tabOffset ) const {
|
||||
return getTextWidth<String>( text, fromMonospaceLine, tabOffset );
|
||||
}
|
||||
|
||||
Float UICodeEditor::getTextWidth( const String::View& text, bool fromMonospaceLine ) const {
|
||||
return getTextWidth<String::View>( text, fromMonospaceLine );
|
||||
Float UICodeEditor::getTextWidth( const String::View& text, bool fromMonospaceLine,
|
||||
std::optional<Float> tabOffset ) const {
|
||||
return getTextWidth<String::View>( text, fromMonospaceLine, tabOffset );
|
||||
}
|
||||
|
||||
template <typename StringType>
|
||||
Float UICodeEditor::getTextWidth( const StringType& line, bool fromMonospaceLine ) const {
|
||||
Float UICodeEditor::getTextWidth( const StringType& line, bool fromMonospaceLine,
|
||||
std::optional<Float> tabOffset ) const {
|
||||
if ( !fromMonospaceLine && isNotMonospace() ) {
|
||||
return Text::getTextWidth( mFont, getCharacterSize(), line, mFontStyleConfig.Style,
|
||||
mTabWidth );
|
||||
mTabWidth, 0.f, 0, tabOffset );
|
||||
}
|
||||
|
||||
Float glyphWidth = getGlyphWidth();
|
||||
@@ -2551,7 +2558,11 @@ Float UICodeEditor::getTextWidth( const StringType& line, bool fromMonospaceLine
|
||||
line.length() ? ( line[line.length() - 1] == '\n' ? line.length() - 1 : line.length() ) : 0;
|
||||
Float x = 0;
|
||||
for ( size_t i = 0; i < len; i++ )
|
||||
x += ( line[i] == '\t' ) ? glyphWidth * mTabWidth : glyphWidth;
|
||||
x +=
|
||||
( line[i] == '\t' )
|
||||
? Text::tabAdvance( glyphWidth, mTabWidth,
|
||||
mTabStops ? ( x + ( tabOffset ? *tabOffset : 0 ) ) : tabOffset )
|
||||
: glyphWidth;
|
||||
return x;
|
||||
}
|
||||
|
||||
@@ -3110,50 +3121,51 @@ Int64 UICodeEditor::getColFromXOffset( VisibleIndex visibleIndex, const Float& x
|
||||
return visibleIndexRange.start().column() +
|
||||
Text::findCharacterFromPos( Vector2i( eemax( -xOffset + x, 0.f ), 0 ), true,
|
||||
mFont, getCharacterSize(), line,
|
||||
mFontStyleConfig.Style, mTabWidth );
|
||||
mFontStyleConfig.Style, mTabWidth, 0.f,
|
||||
mTabStops ? 0 : std::optional<Float>() );
|
||||
}
|
||||
|
||||
Int64 len = line.length();
|
||||
Float glyphWidth = getGlyphWidth();
|
||||
Float tabWidth = glyphWidth * mTabWidth;
|
||||
Float hTab = tabWidth * 0.5f;
|
||||
for ( int i = 0; i < len; i++ ) {
|
||||
bool isTab = ( line[i] == '\t' );
|
||||
Float advance = isTab ? Text::tabAdvance( glyphWidth, mTabWidth,
|
||||
mTabStops ? xOffset : std::optional<Float>{} )
|
||||
: glyphWidth;
|
||||
if ( xOffset >= x ) {
|
||||
auto col = xOffset - x > ( isTab ? hTab : glyphWidth * 0.5f )
|
||||
? eemax<Int64>( 0, i - 1 )
|
||||
: i;
|
||||
auto col = xOffset - x > advance * 0.5f ? eemax<Int64>( 0, i - 1 ) : i;
|
||||
return visibleIndexRange.start().column() + col;
|
||||
} else if ( isTab && ( xOffset + tabWidth > x ) ) {
|
||||
auto col = x - xOffset > hTab ? eemin<Int64>( i + 1, line.size() - 1 ) : i;
|
||||
} else if ( isTab && ( xOffset + advance > x ) ) {
|
||||
auto col =
|
||||
x - xOffset > ( advance * 0.5f ) ? eemin<Int64>( i + 1, line.size() - 1 ) : i;
|
||||
return visibleIndexRange.start().column() + col;
|
||||
}
|
||||
xOffset += isTab ? tabWidth : glyphWidth;
|
||||
xOffset += advance;
|
||||
}
|
||||
return visibleIndexRange.start().column() + static_cast<Int64>( line.size() ) - 1;
|
||||
}
|
||||
|
||||
if ( !isMonospaceLine( pos.line() ) ) {
|
||||
return Text::findCharacterFromPos( Vector2i( x, 0 ), true, mFont, getCharacterSize(),
|
||||
mDoc->line( pos.line() ).getText(),
|
||||
mFontStyleConfig.Style, mTabWidth );
|
||||
return Text::findCharacterFromPos(
|
||||
Vector2i( x, 0 ), true, mFont, getCharacterSize(), mDoc->line( pos.line() ).getText(),
|
||||
mFontStyleConfig.Style, mTabWidth, 0.f, mTabStops ? 0 : std::optional<Float>() );
|
||||
}
|
||||
|
||||
const String& line = mDoc->line( pos.line() ).getText();
|
||||
Int64 len = line.length();
|
||||
Float glyphWidth = getGlyphWidth();
|
||||
Float xOffset = 0;
|
||||
Float tabWidth = glyphWidth * mTabWidth;
|
||||
Float hTab = tabWidth * 0.5f;
|
||||
for ( int i = 0; i < len; i++ ) {
|
||||
bool isTab = ( line[i] == '\t' );
|
||||
Float advance = isTab ? Text::tabAdvance( glyphWidth, mTabWidth,
|
||||
mTabStops ? xOffset : std::optional<Float>{} )
|
||||
: glyphWidth;
|
||||
if ( xOffset >= x ) {
|
||||
return xOffset - x > ( isTab ? hTab : glyphWidth * 0.5f ) ? eemax<Int64>( 0, i - 1 )
|
||||
: i;
|
||||
} else if ( isTab && ( xOffset + tabWidth > x ) ) {
|
||||
return x - xOffset > hTab ? eemin<Int64>( i + 1, line.size() - 1 ) : i;
|
||||
return xOffset - x > ( advance * 0.5f ) ? eemax<Int64>( 0, i - 1 ) : i;
|
||||
} else if ( isTab && ( xOffset + advance > x ) ) {
|
||||
return x - xOffset > ( advance * 0.5f ) ? eemin<Int64>( i + 1, line.size() - 1 ) : i;
|
||||
}
|
||||
xOffset += isTab ? tabWidth : glyphWidth;
|
||||
xOffset += advance;
|
||||
}
|
||||
return static_cast<Int64>( line.size() ) - 1;
|
||||
}
|
||||
@@ -3822,6 +3834,7 @@ void UICodeEditor::drawLineText( const Int64& line, Vector2f position, const Flo
|
||||
bool ended = false;
|
||||
Float lineOffset = getLineOffset();
|
||||
size_t pos = 0;
|
||||
Float initX = position.x;
|
||||
Uint32 drawHints = docLine.getTextHints();
|
||||
if ( mDoc->mightBeBinary() && mFont->getType() == FontType::TTF ) {
|
||||
FontTrueType* ttf = static_cast<FontTrueType*>( mFont );
|
||||
@@ -3832,7 +3845,8 @@ void UICodeEditor::drawLineText( const Int64& line, Vector2f position, const Flo
|
||||
}
|
||||
WhitespaceDisplayConfig whitespaceDisplayConfig =
|
||||
mShowWhitespaces ? WhitespaceDisplayConfig{ L'·', mTabIndentCharacter, mTabIndentAlignment,
|
||||
Color( mWhitespaceColor ).blendAlpha( mAlpha ) }
|
||||
Color( mWhitespaceColor ).blendAlpha( mAlpha ),
|
||||
std::optional<Float>{} }
|
||||
: WhitespaceDisplayConfig{};
|
||||
|
||||
String::View buff;
|
||||
@@ -3869,12 +3883,17 @@ void UICodeEditor::drawLineText( const Int64& line, Vector2f position, const Flo
|
||||
|
||||
if ( style.background != Color::Transparent ) {
|
||||
primitives.setColor( Color( style.background ).blendAlpha( mAlpha ) );
|
||||
primitives.drawRectangle(
|
||||
Rectf( position,
|
||||
Sizef( getTextWidth( text, isMonospace ), lineHeight ) ) );
|
||||
primitives.drawRectangle( Rectf(
|
||||
position, Sizef( getTextWidth( text, isMonospace,
|
||||
mTabStops ? position.x - initX
|
||||
: std::optional<Float>{} ),
|
||||
lineHeight ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( mTabStops )
|
||||
whitespaceDisplayConfig.tabOffset = position.x - initX;
|
||||
|
||||
position.x +=
|
||||
Text::draw( text, { position.x, position.y + lineOffset }, fontStyle,
|
||||
mTabWidth, drawHints, whitespaceDisplayConfig )
|
||||
@@ -3913,7 +3932,12 @@ void UICodeEditor::drawLineText( const Int64& line, Vector2f position, const Flo
|
||||
}
|
||||
pos += token.len;
|
||||
|
||||
Float textWidth = isMonospace ? getTextWidth( text, isMonospace ) : 0;
|
||||
if ( mTabStops )
|
||||
whitespaceDisplayConfig.tabOffset = position.x - initX;
|
||||
|
||||
Float textWidth =
|
||||
isMonospace ? getTextWidth( text, isMonospace, whitespaceDisplayConfig.tabOffset )
|
||||
: 0;
|
||||
if ( !isMonospace || ( position.x + textWidth >= mScreenPos.x &&
|
||||
position.x <= mScreenPos.x + mSize.getWidth() ) ) {
|
||||
Int64 curCharsWidth = text.size();
|
||||
@@ -4399,7 +4423,7 @@ void UICodeEditor::drawIndentationGuides( const DocumentLineRange& lineRange,
|
||||
p.setForceDraw( false );
|
||||
Float w = eefloor( PixelDensity::dpToPx( 1 ) );
|
||||
String idt( mDoc->getIndentString() );
|
||||
auto spaceW = getTextWidth( String( " " ) );
|
||||
auto spaceW = getTextWidth( String( " " ), {} );
|
||||
p.setColor( Color( mWhitespaceColor ).blendAlpha( mAlpha ) );
|
||||
auto indentSize = mDoc->getIndentType() == TextDocument::IndentType::IndentTabs
|
||||
? getTabWidth()
|
||||
@@ -5352,4 +5376,11 @@ bool UICodeEditor::allowSelectingTextFromGutter() const {
|
||||
return mAllowSelectingTextFromGutter;
|
||||
}
|
||||
|
||||
void UICodeEditor::setTabStops( bool enabled ) {
|
||||
if ( mTabStops != enabled ) {
|
||||
mTabStops = enabled;
|
||||
mDocView.setTabStops( enabled );
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace EE::UI
|
||||
|
||||
@@ -141,6 +141,7 @@ void AppConfig::load( const std::string& confPath, std::string& keybindingsPath,
|
||||
doc.writeUnicodeBOM = ini.getValueB( "document", "write_bom", false );
|
||||
doc.indentWidth = ini.getValueI( "document", "indent_width", 4 );
|
||||
doc.indentSpaces = ini.getValueB( "document", "indent_spaces", false );
|
||||
doc.tabStops = ini.getValueB( "document", "tab_stops", false );
|
||||
doc.lineEndings =
|
||||
TextFormat::stringToLineEnding( ini.getValue( "document", "line_endings", "LF" ) );
|
||||
// Migrate old data
|
||||
@@ -303,6 +304,7 @@ void AppConfig::save( const std::vector<std::string>& recentFiles,
|
||||
ini.setValueB( "document", "auto_detect_indent_type", doc.autoDetectIndentType );
|
||||
ini.setValueB( "document", "write_bom", doc.writeUnicodeBOM );
|
||||
ini.setValueI( "document", "indent_width", doc.indentWidth );
|
||||
ini.setValueB( "document", "tab_stops", doc.tabStops );
|
||||
ini.setValueB( "document", "indent_spaces", doc.indentSpaces );
|
||||
ini.setValue( "document", "line_endings", TextFormat::lineEndingToString( doc.lineEndings ) );
|
||||
ini.setValueI( "document", "tab_width", doc.tabWidth );
|
||||
|
||||
@@ -98,6 +98,7 @@ struct DocumentConfig {
|
||||
bool autoDetectIndentType{ true };
|
||||
bool writeUnicodeBOM{ false };
|
||||
bool indentSpaces{ false };
|
||||
bool tabStops{ false };
|
||||
TextFormat::LineEnding lineEndings{ TextFormat::LineEnding::LF };
|
||||
int indentWidth{ 4 };
|
||||
int tabWidth{ 4 };
|
||||
|
||||
@@ -2368,6 +2368,7 @@ void App::onCodeEditorCreated( UICodeEditor* editor, TextDocument& doc ) {
|
||||
editor->setFoldDrawable( findIcon( "chevron-down", PixelDensity::dpToPxI( 12 ) ) );
|
||||
editor->setFoldedDrawable( findIcon( "chevron-right", PixelDensity::dpToPxI( 12 ) ) );
|
||||
editor->setEnableFlashCursor( config.flashCursor );
|
||||
editor->setTabStops( mConfig.doc.tabStops );
|
||||
|
||||
doc.setAutoCloseBrackets( !mConfig.editor.autoCloseBrackets.empty() );
|
||||
doc.setAutoCloseBracketsPairs( makeAutoClosePairs( mConfig.editor.autoCloseBrackets ) );
|
||||
|
||||
@@ -634,6 +634,9 @@ UIMenu* SettingsMenu::createDocumentMenu() {
|
||||
mApp->getConfig().doc.trimTrailingWhitespaces )
|
||||
->setId( "trim_whitespaces" );
|
||||
|
||||
mGlobalMenu->addCheckBox( i18n( "tab_stops", "Tab Stops" ), mApp->getConfig().doc.tabStops )
|
||||
->setId( "tab_stops" );
|
||||
|
||||
mGlobalMenu
|
||||
->addCheckBox( i18n( "force_new_line_at_end_of_file", "Force New Line at End of File" ),
|
||||
mApp->getConfig().doc.forceNewLineAtEndOfFile )
|
||||
@@ -730,6 +733,11 @@ UIMenu* SettingsMenu::createDocumentMenu() {
|
||||
mApp->getConfig().workspace.sessionSnapshot = item->isActive();
|
||||
} else if ( "allow_flash_cursor" == id ) {
|
||||
mApp->getConfig().editor.flashCursor = item->isActive();
|
||||
} else if ( "tab_stops" == id ) {
|
||||
mApp->getConfig().doc.tabStops = item->isActive();
|
||||
mSplitter->forEachEditor( [this]( UICodeEditor* editor ) {
|
||||
editor->setTabStops( mApp->getConfig().doc.tabStops );
|
||||
} );
|
||||
}
|
||||
} else if ( "line_breaking_column" == id ) {
|
||||
mApp->getSettingsActions()->setLineBreakingColumn();
|
||||
|
||||
Reference in New Issue
Block a user