diff --git a/bin/assets/colorschemes/colorschemes.conf b/bin/assets/colorschemes/colorschemes.conf index 736081c68..108852066 100644 --- a/bin/assets/colorschemes/colorschemes.conf +++ b/bin/assets/colorschemes/colorschemes.conf @@ -14,6 +14,8 @@ matching_selection = #3e596e matching_search = #181b1e suggestion = #e1e1e6,#1d1f27 suggestion_selected = #ffffff,#2f3240 +error = red +warning = yellow normal = #e1e1e6 symbol = #e1e1e6 diff --git a/include/eepp/ui/uicodeeditor.hpp b/include/eepp/ui/uicodeeditor.hpp index 830225ef1..1f34e30ed 100644 --- a/include/eepp/ui/uicodeeditor.hpp +++ b/include/eepp/ui/uicodeeditor.hpp @@ -456,6 +456,10 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { void setAutoCloseXMLTags( bool autoCloseXMLTags ); + const Time& getBlinkTime() const; + + void setBlinkTime( const Time& blinkTime ); + protected: struct LastXOffset { TextPosition position; @@ -466,6 +470,7 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { std::shared_ptr mDoc; Vector2f mScrollPos; Clock mBlinkTimer; + Time mBlinkTime; bool mDirtyEditor{ false }; bool mCursorVisible{ false }; bool mMouseDown{ false }; @@ -505,6 +510,8 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { Color mLineBreakColumnColor; Color mMatchingBracketColor; Color mSelectionMatchColor; + Color mErrorColor; + Color mWarningColor; SyntaxColorScheme mColorScheme; SyntaxHighlighter mHighlighter; UIScrollBar* mVScrollBar; diff --git a/src/eepp/scene/eventdispatcher.cpp b/src/eepp/scene/eventdispatcher.cpp index 2d03f6957..66f298e06 100644 --- a/src/eepp/scene/eventdispatcher.cpp +++ b/src/eepp/scene/eventdispatcher.cpp @@ -117,7 +117,7 @@ void EventDispatcher::update( const Time& time ) { Node* lastFocusNode = mFocusNode; if ( NULL != mOverNode ) { - getMouseOverNode()->onMouseUp( mMousePosi, mInput->getReleaseTrigger() ); + mOverNode->onMouseUp( mMousePosi, mInput->getReleaseTrigger() ); if ( NULL != mOverNode ) sendMsg( mOverNode, NodeMessage::MouseUp, mInput->getReleaseTrigger() ); } @@ -136,6 +136,12 @@ void EventDispatcher::update( const Time& time ) { mClickPos = mMousePosi; } + } else { + if ( NULL != mOverNode ) { + mOverNode->onMouseUp( mMousePosi, mInput->getReleaseTrigger() ); + if ( NULL != mOverNode ) + sendMsg( mOverNode, NodeMessage::MouseUp, mInput->getReleaseTrigger() ); + } } } diff --git a/src/eepp/scene/scenenode.cpp b/src/eepp/scene/scenenode.cpp index bbb44504b..22a1d6ef9 100644 --- a/src/eepp/scene/scenenode.cpp +++ b/src/eepp/scene/scenenode.cpp @@ -456,6 +456,9 @@ void SceneNode::onDrawDebugDataChange() {} void SceneNode::subscribeScheduledUpdate( Node* node ) { mScheduledUpdate.insert( node ); + auto it = mScheduledUpdateRemove.find( node ); + if ( it != mScheduledUpdateRemove.end() ) + mScheduledUpdateRemove.erase( it ); } void SceneNode::unsubscribeScheduledUpdate( Node* node ) { diff --git a/src/eepp/ui/doc/syntaxcolorscheme.cpp b/src/eepp/ui/doc/syntaxcolorscheme.cpp index 0daf3c18a..c54d55004 100644 --- a/src/eepp/ui/doc/syntaxcolorscheme.cpp +++ b/src/eepp/ui/doc/syntaxcolorscheme.cpp @@ -28,37 +28,37 @@ namespace EE { namespace UI { namespace Doc { // "warning" (warning underline color) SyntaxColorScheme SyntaxColorScheme::getDefault() { - return { "lite", + return { "eepp", { { "normal", Color( "#e1e1e6" ) }, { "symbol", Color( "#e1e1e6" ) }, - { "comment", Color( "#676b6f" ) }, - { "keyword", Color( "#E58AC9" ) }, - { "keyword2", Color( "#F77483" ) }, - { "number", Color( "#FFA94D" ) }, - { "literal", Color( "#FFA94D" ) }, - { "string", Color( "#f7c95c" ) }, - { "operator", Color( "#93DDFA" ) }, - { "function", Color( "#93DDFA" ) }, - { "link", { Color( "#93DDFA" ) } }, - { "link_hover", { Color( "#93DDFA" ), Color::Transparent, Text::Underlined } }, + { "comment", Color( "#cd8b00" ) }, + { "keyword", { Color( "#ff79c6" ), Color::Transparent, Text::Shadow } }, + { "keyword2", { Color( "#8be9fd" ), Color::Transparent, Text::Shadow } }, + { "number", Color( "#ffd24a" ) }, + { "literal", { Color( "#f1fa8c" ), Color::Transparent, Text::Shadow } }, + { "string", Color( "#ffcd8b" ) }, + { "operator", Color( "#51f0e7" ) }, + { "function", { Color( "#00dc7f" ), Color::Transparent, Text::Shadow } }, + { "link", { Color( "#6ae0f9" ), Color::Transparent, Text::Shadow } }, + { "link_hover", { Color::Transparent, Color::Transparent, Text::Underlined } }, }, - { { "background", Color( "#2e2e32" ) }, - { "text", Color( "#97979c" ) }, + { { "background", Color( "#282a36" ) }, + { "text", Color( "#e1e1e6" ) }, { "caret", Color( "#93DDFA" ) }, - { "selection", Color( "#48484f" ) }, - { "line_highlight", Color( "#343438" ) }, + { "selection", Color( "#394484" ) }, + { "line_highlight", Color( "#2d303d" ) }, { "line_number", Color( "#525259" ) }, { "line_number2", Color( "#83838f" ) }, // eepp colors - { "line_number_background", Color( "#2e2e32" ) }, + { "line_number_background", Color( "#282a36" ) }, { "whitespace", Color( "#54575b" ) }, { "line_break_column", Color( "#54575b99" ) }, { "matching_bracket", Color( "#FFFFFF33" ) }, - { "matching_selection", Color( "#FFFFFF33" ) }, + { "matching_selection", Color( "#3e596e" ) }, { "matching_search", Color( "#181b1e" ) }, - { "suggestion", { Color( "#97979c" ), Color( "#252529" ), Text::Regular } }, - { "suggestion_selected", { Color( "#e1e1e6" ), Color( "#252529" ), Text::Regular } }, + { "suggestion", { Color( "#e1e1e6" ), Color( "#1d1f27" ), Text::Regular } }, + { "suggestion_selected", { Color( "#ffffff" ), Color( "#2f3240" ), Text::Regular } }, { "error", { Color::Red } }, { "warning", { Color::Yellow } } } }; } @@ -91,7 +91,9 @@ std::vector SyntaxColorScheme::loadFromStream( IOStream& stre style.background = Color::fromString( val ); } } else { - if ( "bold" == val ) + if ( "regular" == val ) + style.style |= Text::Regular; + else if ( "bold" == val ) style.style |= Text::Bold; else if ( "italic" == val ) style.style |= Text::Italic; diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp index da1106c48..4e50a19dc 100644 --- a/src/eepp/ui/uicodeeditor.cpp +++ b/src/eepp/ui/uicodeeditor.cpp @@ -103,6 +103,7 @@ UICodeEditor::UICodeEditor( const std::string& elementTag, const bool& autoRegis UIWidget( elementTag ), mFont( FontManager::instance()->getByName( "monospace" ) ), mDoc( std::make_shared() ), + mBlinkTime( Seconds( 0.5f ) ), mTabWidth( 4 ), mMouseWheelScroll( 50 ), mFontSize( mFontStyleConfig.getFontCharacterSize() ), @@ -301,7 +302,7 @@ void UICodeEditor::draw() { void UICodeEditor::scheduledUpdate( const Time& ) { if ( hasFocus() && getUISceneNode()->getWindow()->hasFocus() ) { - if ( mBlinkTimer.getElapsedTime().asSeconds() > 0.5f ) { + if ( mBlinkTimer.getElapsedTime() > mBlinkTime ) { mCursorVisible = !mCursorVisible; mBlinkTimer.restart(); invalidateDraw(); @@ -325,6 +326,9 @@ void UICodeEditor::scheduledUpdate( const Time& ) { } } + if ( !mVisible ) + return; + if ( mHighlighter.updateDirty( getVisibleLinesCount() ) ) { invalidateDraw(); } @@ -705,6 +709,8 @@ void UICodeEditor::updateColorScheme() { mLineBreakColumnColor = mColorScheme.getEditorColor( "line_break_column" ); mMatchingBracketColor = mColorScheme.getEditorColor( "matching_bracket" ); mSelectionMatchColor = mColorScheme.getEditorColor( "matching_selection" ); + mErrorColor = mColorScheme.getEditorColor( "error" ); + mWarningColor = mColorScheme.getEditorColor( "warning" ); } void UICodeEditor::setColorScheme( const SyntaxColorScheme& colorScheme ) { @@ -954,18 +960,19 @@ Uint32 UICodeEditor::onMouseDown( const Vector2i& position, const Uint32& flags return UIWidget::onMouseDown( position, flags ); if ( mMinimapEnabled ) { + updateMipmapHover( position.asFloat() ); + Rectf rect( getMinimapRect( getScreenStart() ) ); if ( ( flags & EE_BUTTON_LMASK ) && !getEventDispatcher()->isNodeDragging() && !mMinimapDragging && rect.contains( position.asFloat() ) ) { if ( mMouseDown ) return 1; - updateMipmapHover( position.asFloat() ); - mMouseDown = true; - if ( !mMinimapHover ) { + if ( !mMinimapHover && !mMouseDown ) { mMinimapScrollOffset = 0; scrollTo( { calculateMinimapClickedLine( position ), 0 }, true, true ); return 1; } + mMouseDown = true; mMinimapScrollOffset = calculateMinimapClickedLine( position ) - getVisibleLineRange().first; mMinimapDragging = true; @@ -974,7 +981,8 @@ Uint32 UICodeEditor::onMouseDown( const Vector2i& position, const Uint32& flags getUISceneNode()->setCursor( Cursor::Arrow ); return 1; } else if ( mMinimapDragging ) { - if ( mMouseDown ) { + if ( ( flags & EE_BUTTON_LMASK ) && mMouseDown && + rect.contains( position.asFloat() ) ) { scrollTo( { calculateMinimapClickedLine( position ) - mMinimapScrollOffset, 0 }, false, true ); getUISceneNode()->setCursor( Cursor::Arrow ); @@ -2721,7 +2729,7 @@ void UICodeEditor::drawMinimap( const Vector2f& start, const String& line( mDoc->line( ln ).getText() ); if ( line.size() > 300 ) return; - primitives.setColor( Color( mSelectionMatchColor ).blendAlpha( mAlpha ) ); + primitives.setColor( Color( mWarningColor ).blendAlpha( mAlpha ) ); do { pos = line.find( text, pos ); @@ -2733,7 +2741,8 @@ void UICodeEditor::drawMinimap( const Vector2f& start, selRect.Bottom = lineY + charHeight; selRect.Left = batchStart + getXOffsetCol( { ln, startCol } ) * widthScale; selRect.Right = batchStart + getXOffsetCol( { ln, endCol } ) * widthScale; - primitives.drawRectangle( selRect ); + if ( selRect.Left < minimapCutoffX ) + primitives.drawRectangle( selRect ); pos = endCol; } else { break; @@ -2741,6 +2750,23 @@ void UICodeEditor::drawMinimap( const Vector2f& start, } while ( true ); }; + String selectionString; + + if ( mDoc->hasSelection() ) { + TextRange selection = mDoc->getSelection( true ); + const String& selectionLine = mDoc->line( selection.start().line() ).getText(); + if ( selection.start().column() >= 0 && + selection.start().column() < (Int64)selectionLine.size() && + selection.end().column() >= 0 && + selection.end().column() < (Int64)selectionLine.size() ) { + String text( + selectionLine.substr( selection.start().column(), + selection.end().column() - selection.start().column() ) ); + if ( !text.empty() ) + selectionString = text; + } + } + if ( mMinimapConfig.syntaxHighlight ) { for ( int index = minimapStartLine; index <= endidx; index++ ) { batchSyntaxType = "normal"; @@ -2749,6 +2775,8 @@ void UICodeEditor::drawMinimap( const Vector2f& start, if ( !mHighlightWord.empty() ) drawWordMatch( mHighlightWord, index ); + if ( !selectionString.empty() ) + drawWordMatch( selectionString, index ); auto& tokens = mHighlighter.getLine( index ); for ( auto& token : tokens ) { @@ -2782,6 +2810,12 @@ void UICodeEditor::drawMinimap( const Vector2f& start, batchSyntaxType = "normal"; batchStart = rect.Left + gutterWidth; batchWidth = 0; + + if ( !mHighlightWord.empty() ) + drawWordMatch( mHighlightWord, index ); + if ( !selectionString.empty() ) + drawWordMatch( selectionString, index ); + const String& text( mDoc->line( index ).getText() ); for ( size_t i = 0; i < text.size(); ++i ) { String::StringBaseType ch = text[i]; @@ -2833,6 +2867,14 @@ bool UICodeEditor::isMinimapFileTooLarge() const { eefloor( getMinimapRect( getScreenStart() ).getHeight() / getMinimapLineSpacing() ); } +const Time& UICodeEditor::getBlinkTime() const { + return mBlinkTime; +} + +void UICodeEditor::setBlinkTime( const Time& blinkTime ) { + mBlinkTime = blinkTime; +} + bool UICodeEditor::getAutoCloseXMLTags() const { return mAutoCloseXMLTags; } diff --git a/src/tools/ecode/projectdirectorytree.cpp b/src/tools/ecode/projectdirectorytree.cpp index 8069b1000..be67a2b76 100644 --- a/src/tools/ecode/projectdirectorytree.cpp +++ b/src/tools/ecode/projectdirectorytree.cpp @@ -65,8 +65,11 @@ std::shared_ptr ProjectDirectoryTree::fuzzyMatchTree( const std:: std::multimap> matchesMap; std::vector files; std::vector names; - for ( size_t i = 0; i < mNames.size(); i++ ) - matchesMap.insert( { String::fuzzyMatch( mNames[i], match ), i } ); + for ( size_t i = 0; i < mNames.size(); i++ ) { + int matchName = String::fuzzyMatch( mNames[i], match ); + int matchPath = String::fuzzyMatch( mFiles[i], match ); + matchesMap.insert( { std::max( matchName, matchPath ), i } ); + } for ( auto& res : matchesMap ) { if ( names.size() < max ) { names.emplace_back( mNames[res.second] );