diff --git a/bin/assets/colorschemes/colorschemes.conf b/bin/assets/colorschemes/colorschemes.conf index 7b6fafabe..60ff85f25 100644 --- a/bin/assets/colorschemes/colorschemes.conf +++ b/bin/assets/colorschemes/colorschemes.conf @@ -17,7 +17,9 @@ suggestion_selected = #ffffff,#2f3240 error = red warning = yellow notice = #8abdff -minimap_current_line = #93DDFA40 +minimap_background = #282a36AA +minimap_visible_area = #FFFFFF1A +minimap_current_line = #FFFFFF0A minimap_hover = #FFFFFF1A minimap_selection = #8abdff80 minimap_highlight = #FFFF0080 diff --git a/include/eepp/ui/uicodeeditor.hpp b/include/eepp/ui/uicodeeditor.hpp index 6eadd79a8..6efc7feda 100644 --- a/include/eepp/ui/uicodeeditor.hpp +++ b/include/eepp/ui/uicodeeditor.hpp @@ -97,8 +97,6 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { Float scale{ 1 }; int tabWidth{ 4 }; bool drawBackground{ true }; - Color selectionColor{ Color::Transparent }; - Color caretColor{ Color::Transparent }; Float gutterWidth{ 5 }; // dp width }; @@ -399,6 +397,8 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { virtual Float getLineWidth( const Int64& lineIndex ); + size_t characterWidth( const String& str ) const; + Float getTextWidth( const String& text ) const; Float getLineHeight() const; @@ -442,7 +442,7 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { void scrollToCursor( bool centered = true ); void scrollTo( const TextPosition& position, bool centered = false, - bool forceExactPosition = false ); + bool forceExactPosition = false, bool scrollX = true ); const MinimapConfig& getMinimapConfig() const; @@ -460,6 +460,8 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { void setBlinkTime( const Time& blinkTime ); + Int64 getCurrentColumnCount() const; + protected: struct LastXOffset { TextPosition position; @@ -512,6 +514,8 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { Color mSelectionMatchColor; Color mErrorColor; Color mWarningColor; + Color mMinimapBackgroundColor; + Color mMinimapVisibleAreaColor; Color mMinimapCurrentLineColor; Color mMinimapHoverColor; Color mMinimapSelectionColor; diff --git a/src/eepp/ui/doc/syntaxcolorscheme.cpp b/src/eepp/ui/doc/syntaxcolorscheme.cpp index 2016bb42a..50beec0b9 100644 --- a/src/eepp/ui/doc/syntaxcolorscheme.cpp +++ b/src/eepp/ui/doc/syntaxcolorscheme.cpp @@ -63,10 +63,13 @@ SyntaxColorScheme SyntaxColorScheme::getDefault() { { "error", { Color::Red } }, { "warning", { Color::Yellow } }, { "notice", Color( "#8abdff" ) }, + // minimap colors + { "minimap_background", Color( "#282a36AA" ) }, { "minimap_current_line", Color( "#93DDFA40" ) }, { "minimap_hover", Color( "#FFFFFF1A" ) }, { "minimap_selection", Color( "#8abdff80" ) }, - { "minimap_highlight", Color( "#FFFF0040" ) } } }; + { "minimap_highlight", Color( "#FFFF0040" ) }, + { "minimap_visible_area", Color( "#FFFFFF0A" ) } } }; } std::vector SyntaxColorScheme::loadFromStream( IOStream& stream ) { @@ -164,7 +167,7 @@ SyntaxColorScheme::SyntaxColorScheme( const std::string& name, const std::unordered_map& editorColors ) : mName( name ), mSyntaxColors( syntaxColors ), mEditorColors( editorColors ) {} -static const SyntaxColorScheme::Style StyleEmpty = { Color::White }; +static const SyntaxColorScheme::Style StyleEmpty = { Color::Transparent }; static const SyntaxColorScheme StyleDefault = SyntaxColorScheme::getDefault(); const SyntaxColorScheme::Style& SyntaxColorScheme::getSyntaxStyle( const std::string& type ) const { @@ -209,6 +212,8 @@ SyntaxColorScheme::getEditorSyntaxStyle( const std::string& type ) const { return StyleDefault.getEditorSyntaxStyle( "warning" ); else if ( type == "notice" ) return StyleDefault.getEditorSyntaxStyle( "notice" ); + else if ( type == "minimap_background" ) + return StyleDefault.getEditorSyntaxStyle( "minimap_background" ); else if ( type == "minimap_current_line" ) return StyleDefault.getEditorSyntaxStyle( "minimap_current_line" ); else if ( type == "minimap_hover" ) @@ -217,6 +222,8 @@ SyntaxColorScheme::getEditorSyntaxStyle( const std::string& type ) const { return StyleDefault.getEditorSyntaxStyle( "minimap_selection" ); else if ( type == "minimap_highlight" ) return StyleDefault.getEditorSyntaxStyle( "minimap_highlight" ); + else if ( type == "minimap_visible_area" ) + return StyleDefault.getEditorSyntaxStyle( "minimap_visible_area" ); return StyleEmpty; } diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp index a1731eab8..a8430d0ce 100644 --- a/src/eepp/ui/uicodeeditor.cpp +++ b/src/eepp/ui/uicodeeditor.cpp @@ -320,7 +320,7 @@ void UICodeEditor::scheduledUpdate( const Time& ) { } mMouseDown = false; getUISceneNode()->getWindow()->getInput()->captureMouse( false ); - } else if ( !isMouseOverMeOrChilds() ) { + } else if ( !isMouseOverMeOrChilds() || mMinimapDragging ) { onMouseMove( getUISceneNode()->getEventDispatcher()->getMousePos(), getUISceneNode()->getEventDispatcher()->getPressTrigger() ); } @@ -347,10 +347,10 @@ void UICodeEditor::updateLongestLineWidth() { if ( mHorizontalScrollBarEnabled ) { Float maxWidth = mLongestLineWidth; findLongestLine(); - if ( maxWidth != mLongestLineWidth ) - updateScrollBar(); mLongestLineWidthLastUpdate.restart(); mLongestLineWidthDirty = false; + if ( maxWidth != mLongestLineWidth ) + updateScrollBar(); } } @@ -589,9 +589,7 @@ const Uint32& UICodeEditor::getTabWidth() const { } UICodeEditor* UICodeEditor::setTabWidth( const Uint32& tabWidth ) { - if ( mTabWidth != tabWidth ) { - mTabWidth = tabWidth; - } + mTabWidth = tabWidth; return this; } @@ -709,9 +707,12 @@ void UICodeEditor::updateColorScheme() { mLineBreakColumnColor = mColorScheme.getEditorColor( "line_break_column" ); mMatchingBracketColor = mColorScheme.getEditorColor( "matching_bracket" ); mSelectionMatchColor = mColorScheme.getEditorColor( "matching_selection" ); + mMinimapBackgroundColor = mColorScheme.getEditorColor( "minimap_background" ); + if ( Color::Transparent == mMinimapBackgroundColor ) + mMinimapBackgroundColor = getBackgroundColor(); + mMinimapVisibleAreaColor = mColorScheme.getEditorColor( "minimap_visible_area" ); mMinimapCurrentLineColor = mColorScheme.getEditorColor( "minimap_current_line" ); mMinimapHoverColor = mColorScheme.getEditorColor( "minimap_hover" ); - mMinimapSelectionColor = mColorScheme.getEditorColor( "minimap_hover" ); mMinimapHighlightColor = mColorScheme.getEditorColor( "minimap_highlight" ); mMinimapSelectionColor = mColorScheme.getEditorColor( "minimap_selection" ); } @@ -972,7 +973,7 @@ Uint32 UICodeEditor::onMouseDown( const Vector2i& position, const Uint32& flags return 1; if ( !mMinimapHover && !mMouseDown ) { mMinimapScrollOffset = 0; - scrollTo( { calculateMinimapClickedLine( position ), 0 }, true, true ); + scrollTo( { calculateMinimapClickedLine( position ), 0 }, true, true, false ); return 1; } mMouseDown = true; @@ -987,7 +988,7 @@ Uint32 UICodeEditor::onMouseDown( const Vector2i& position, const Uint32& flags if ( ( flags & EE_BUTTON_LMASK ) && mMouseDown && rect.contains( position.asFloat() ) ) { scrollTo( { calculateMinimapClickedLine( position ) - mMinimapScrollOffset, 0 }, - false, true ); + false, true, false ); getUISceneNode()->setCursor( Cursor::Arrow ); } return 1; @@ -1051,7 +1052,7 @@ Uint32 UICodeEditor::onMouseMove( const Vector2i& position, const Uint32& flags updateMipmapHover( position.asFloat() ); if ( mMinimapDragging && ( flags & EE_BUTTON_LMASK ) ) { scrollTo( { calculateMinimapClickedLine( position ) - mMinimapScrollOffset, 0 }, false, - true ); + true, false ); getUISceneNode()->setCursor( Cursor::Arrow ); return 1; } @@ -1298,10 +1299,11 @@ void UICodeEditor::updateScrollBar() { if ( mHorizontalScrollBarEnabled ) { mHScrollBar->setPixelsPosition( 0, mSize.getHeight() - mHScrollBar->getPixelsSize().getHeight() ); - mHScrollBar->setPixelsSize( - mSize.getWidth() - - ( notVisibleLineCount > 0 ? mVScrollBar->getPixelsSize().getWidth() : 0 ), - mHScrollBar->getPixelsSize().getHeight() ); + mHScrollBar->setPixelsSize( mSize.getWidth() - + ( mVerticalScrollBarEnabled && notVisibleLineCount > 0 + ? mVScrollBar->getPixelsSize().getWidth() + : 0 ), + mHScrollBar->getPixelsSize().getHeight() ); Float viewPortWidth = getViewportWidth(); mHScrollBar->setPageStep( viewPortWidth / mLongestLineWidth ); mHScrollBar->setClickStep( 0.2f ); @@ -1459,8 +1461,8 @@ int UICodeEditor::getVisibleLinesCount() { return lines.second - lines.first; } -void UICodeEditor::scrollTo( const TextPosition& position, bool centered, - bool forceExactPosition ) { +void UICodeEditor::scrollTo( const TextPosition& position, bool centered, bool forceExactPosition, + bool scrollX ) { auto lineRange = getVisibleLineRange(); Int64 minDistance = mHScrollBar->isVisible() ? 3 : 2; @@ -1495,6 +1497,8 @@ void UICodeEditor::scrollTo( const TextPosition& position, bool centered, } // Horizontal Scroll + if ( !scrollX ) + return; Float offsetX = getXOffsetCol( position ); Float glyphSize = getGlyphWidth(); Float minVisibility = glyphSize; @@ -1556,6 +1560,14 @@ Float UICodeEditor::getXOffsetCol( const TextPosition& position ) { return x; } +size_t UICodeEditor::characterWidth( const String& str ) const { + Int64 cc = str.size(); + Int64 count = 0; + for ( Int64 i = 0; i < cc; i++ ) + count += str[i] == '\t' ? mTabWidth : 1; + return count; +} + Float UICodeEditor::getTextWidth( const String& line ) const { Float glyphWidth = getGlyphWidth(); size_t len = line.length(); @@ -1986,6 +1998,7 @@ Float UICodeEditor::getGlyphWidth() const { void UICodeEditor::udpateGlyphWidth() { mGlyphWidth = mFont->getGlyph( ' ', getCharacterSize(), false ).advance; + invalidateLongestLineWidth(); } Drawable* UICodeEditor::findIcon( const std::string& name ) { @@ -2084,19 +2097,34 @@ void UICodeEditor::paste() { } void UICodeEditor::fontSizeGrow() { + Float line = mScroll.y / getLineHeight(); + Float col = mScroll.x / getGlyphWidth(); mFontStyleConfig.CharacterSize = eemin( 96, mFontStyleConfig.CharacterSize + 1 ); onFontChanged(); + updateLongestLineWidth(); + setScrollY( getLineHeight() * line ); + setScrollX( getGlyphWidth() * col ); invalidateDraw(); } void UICodeEditor::fontSizeShrink() { + Float line = mScroll.y / getLineHeight(); + Float col = mScroll.x / getGlyphWidth(); mFontStyleConfig.CharacterSize = eemax( 4, mFontStyleConfig.CharacterSize - 1 ); onFontChanged(); + updateLongestLineWidth(); + setScrollY( getLineHeight() * line ); + setScrollX( getGlyphWidth() * col ); invalidateDraw(); } void UICodeEditor::fontSizeReset() { + Float line = mScroll.y / getLineHeight(); + Float col = mScroll.x / getGlyphWidth(); setFontSize( mFontSize ); + updateLongestLineWidth(); + setScrollY( getLineHeight() * line ); + setScrollX( getGlyphWidth() * col ); } const bool& UICodeEditor::getShowWhitespaces() const { @@ -2334,7 +2362,7 @@ void UICodeEditor::drawLineText( const Int64& index, Vector2f position, const Fl } position.x += textWidth; - curChar += text.size(); + curChar += characterWidth( text ); continue; } } @@ -2371,7 +2399,7 @@ void UICodeEditor::drawLineText( const Int64& index, Vector2f position, const Fl } position.x += textWidth; - curChar += text.size(); + curChar += characterWidth( text ); } } @@ -2460,8 +2488,8 @@ void UICodeEditor::drawWhitespaces( const std::pair& lineRange, Vector2f position( { startScroll.x, startScroll.y + lineHeight * index } ); const auto& text = mDoc->line( index ).getText(); for ( size_t i = 0; i < text.size(); i++ ) { - if ( position.x + glyphW >= mScreenPos.x && - position.x <= mScreenPos.x + mSize.getWidth() ) { + if ( position.x + mScroll.x + ( text[i] == '\t' ? tabWidth : glyphW ) >= mScreenPos.x && + position.x <= mScreenPos.x + mScroll.x + mSize.getWidth() ) { if ( ' ' == text[i] ) { cpoint->draw( Vector2f( position.x, position.y ) ); position.x += glyphW; @@ -2683,11 +2711,11 @@ void UICodeEditor::drawMinimap( const Vector2f& start, primitives.setForceDraw( false ); if ( mMinimapConfig.drawBackground ) { - primitives.setColor( getBackgroundColor().blendAlpha( mAlpha ) ); + primitives.setColor( Color( mMinimapBackgroundColor ).blendAlpha( mAlpha ) ); primitives.drawRectangle( rect ); } - primitives.setColor( Color( mCurrentLineBackgroundColor ).blendAlpha( mAlpha ) ); + primitives.setColor( Color( mMinimapVisibleAreaColor ).blendAlpha( mAlpha ) ); primitives.drawRectangle( { { rect.Left, visibleY }, Sizef( rect.getWidth(), scrollerHeight ) } ); if ( mMinimapHover || mMinimapDragging ) { @@ -2957,4 +2985,13 @@ bool UICodeEditor::checkAutoCloseXMLTag( const String& text ) { return false; } +Int64 UICodeEditor::getCurrentColumnCount() const { + Int64 curLine = mDoc->getSelection().start().line(); + Int64 sel = mDoc->getSelection().start().column(); + Int64 count = 0; + for ( Int64 i = 0; i < sel; i++ ) + count += mDoc->line( curLine ).getText()[i] == '\t' ? mTabWidth : 1; + return count; +} + }} // namespace EE::UI diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index 2e5bc0f6a..56ed772bd 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -1533,10 +1533,10 @@ void App::onDocumentCursorPosChange( UICodeEditor*, TextDocument& doc ) { } void App::updateDocInfo( TextDocument& doc ) { - if ( mConfig.editor.showDocInfo && mDocInfoText ) { + if ( mConfig.editor.showDocInfo && mDocInfoText && mEditorSplitter->getCurEditor() ) { mDocInfoText->setText( String::format( "line: %lld / %lu col: %lld %s", doc.getSelection().start().line() + 1, - doc.linesCount(), doc.getSelection().start().column(), + doc.linesCount(), mEditorSplitter->getCurEditor()->getCurrentColumnCount(), doc.getLineEnding() == TextDocument::LineEnding::LF ? "LF" : "CRLF" ) ); } }