Fixed issues in document search.

This commit is contained in:
Martín Lucas Golini
2023-06-16 00:48:56 -03:00
parent c29f43ed34
commit 4e13d4d651
8 changed files with 80 additions and 18 deletions
+3 -1
View File
@@ -26,7 +26,9 @@
"includeCompletionsWithSnippetText": false,
"jsxAttributeCompletionStyle": "auto",
"providePrefixAndSuffixTextForRename": true,
"provideRefactorNotApplicableReason": true
"provideRefactorNotApplicableReason": true,
"importModuleSpecifierPreference": "shortest",
"disableSuggestions": false
}
}
},
+6 -2
View File
@@ -360,7 +360,7 @@ class EE_API TextDocument {
TextRanges findAll( const String& text, bool caseSensitive = true, bool wholeWord = false,
const FindReplaceType& type = FindReplaceType::Normal,
TextRange restrictRange = TextRange() );
TextRange restrictRange = TextRange(), size_t maxResults = 0 );
int replaceAll( const String& text, const String& replace, const bool& caseSensitive = true,
const bool& wholeWord = false,
@@ -569,6 +569,8 @@ class EE_API TextDocument {
const Uint64& getModificationId() const;
void stopActiveFindAll();
protected:
friend class UndoStack;
@@ -613,6 +615,8 @@ class EE_API TextDocument {
mutable Mutex mLoadingFilePathMutex;
size_t mLastSelection{ 0 };
std::unique_ptr<SyntaxHighlighter> mHighlighter;
Mutex mStopFlagsMutex;
std::unordered_map<bool*, std::unique_ptr<bool>> mStopFlags;
void initializeCommands();
@@ -694,7 +698,7 @@ struct TextSearchParams {
bool operator!=( const TextSearchParams& other ) { return !( *this == other ); }
bool isEmpty() { return text.empty(); }
bool isEmpty();
void reset() {
range = TextRange();
+2 -1
View File
@@ -642,7 +642,7 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client {
bool mFindReplaceEnabled{ true };
bool mShowIndentationGuides{ false };
bool mShowLinesRelativePosition{ false };
std::atomic<bool> mHighlightWordProcessing{ false };
std::atomic<size_t> mHighlightWordProcessing{ false };
TextRange mLinkPosition;
String mLink;
Uint32 mTabWidth;
@@ -683,6 +683,7 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client {
Clock mLongestLineWidthLastUpdate;
TextSearchParams mHighlightWord;
TextRanges mHighlightWordCache;
Mutex mHighlightWordCacheMutex;
TextRange mHighlightTextRange;
Color mPreviewColor;
TextRange mPreviewColorRange;
+1 -1
View File
@@ -155,7 +155,7 @@ class EE_API UIMenu : public UIWidget {
virtual void scheduledUpdate( const Time& time );
bool isChildOfMeOrSubMenu( Node* node );
bool isChildOrSubMenu( Node* node );
void unselectSelected();
};
+32 -1
View File
@@ -41,6 +41,12 @@ TextDocument::TextDocument( bool verbose ) :
}
TextDocument::~TextDocument() {
stopActiveFindAll();
// TODO: Use a condition variable to wait the thread pool to finish
while ( !mStopFlags.empty() )
Sys::sleep( Milliseconds( 0.1 ) );
if ( mLoading ) {
mLoading = false;
Lock l( mLoadingMutex );
@@ -2351,11 +2357,25 @@ TextRange TextDocument::findLast( const String& text, TextPosition from, bool ca
return TextRange();
}
void TextDocument::stopActiveFindAll() {
Lock l( mStopFlagsMutex );
for ( const auto& stopFlag : mStopFlags )
*stopFlag.second.get() = true;
}
TextRanges TextDocument::findAll( const String& text, bool caseSensitive, bool wholeWord,
const FindReplaceType& type, TextRange restrictRange ) {
const FindReplaceType& type, TextRange restrictRange,
size_t maxResults ) {
TextRanges all;
TextRange found;
TextPosition from = startOfDoc();
auto stopFlagUP = std::make_unique<bool>( false );
bool* stopFlag = stopFlagUP.get();
{
Lock l( mStopFlagsMutex );
mStopFlags.insert( { stopFlag, std::move( stopFlagUP ) } );
}
if ( restrictRange.isValid() )
from = restrictRange.normalized().start();
do {
@@ -2365,10 +2385,17 @@ TextRanges TextDocument::findAll( const String& text, bool caseSensitive, bool w
break;
from = found.end();
all.push_back( found );
if ( ( maxResults != 0 && all.size() >= maxResults ) || *stopFlag )
break;
}
} while ( found.isValid() );
if ( !all.empty() )
all.setSorted();
{
Lock l( mStopFlagsMutex );
mStopFlags.erase( stopFlag );
}
return all;
}
@@ -2733,4 +2760,8 @@ void TextDocument::addCursorBelow() {
TextDocument::Client::~Client() {}
bool TextSearchParams::isEmpty() {
return text.empty();
}
}}} // namespace EE::UI::Doc
+31 -9
View File
@@ -178,9 +178,13 @@ UICodeEditor::~UICodeEditor() {
for ( auto& plugin : mPlugins )
plugin->onUnregister( this );
// Remember to stop all the async find jobs
mDoc->stopActiveFindAll();
// TODO: Use a condition variable to wait the thread pool to finish
// Wait to end all the async find jobs
while ( mHighlightWordProcessing )
Sys::sleep( Milliseconds( 1 ) );
Sys::sleep( Milliseconds( 0.1 ) );
if ( mDoc.use_count() == 1 ) {
DocEvent event( this, mDoc.get(), Event::OnDocumentClosed );
@@ -294,8 +298,10 @@ void UICodeEditor::draw() {
}
}
if ( !mHighlightWord.isEmpty() )
if ( !mHighlightWord.isEmpty() ) {
Lock l( mHighlightWordCacheMutex );
drawWordRanges( mHighlightWordCache, lineRange, startScroll, lineHeight, true );
}
if ( mShowIndentationGuides ) {
drawIndentationGuides( lineRange, startScroll, lineHeight );
@@ -2543,21 +2549,29 @@ void UICodeEditor::updateHighlightWordCache() {
if ( mDoc->isRunningTransaction() )
return;
Clock docSearch;
mHighlightWordProcessing = true;
mHighlightWordCache = mDoc->findAll(
mHighlightWordProcessing++;
mDoc->stopActiveFindAll();
auto wordCache = mDoc->findAll(
mHighlightWord.escapeSequences ? String::unescape( mHighlightWord.text )
: mHighlightWord.text,
mHighlightWord.caseSensitive, mHighlightWord.wholeWord,
mHighlightWord.type, mHighlightWord.range );
{
Lock l( mHighlightWordCacheMutex );
mHighlightWordCache = std::move( wordCache );
}
Log::info( "Document search triggered in document: \"%s\", searched for "
"\"%s\" and took %.2f ms",
mDoc->getFilename().c_str(),
mHighlightWord.text.toUtf8().c_str(),
docSearch.getElapsedTime().asMilliseconds() );
},
[this]( const auto& ) { mHighlightWordProcessing = false; }, tag );
[this]( const auto& ) { mHighlightWordProcessing--; }, tag );
},
Milliseconds( 0 ), tag );
Milliseconds( 16 ), tag );
} else {
if ( mDoc->isRunningTransaction() )
return;
@@ -2565,7 +2579,7 @@ void UICodeEditor::updateHighlightWordCache() {
mDoc->findAll( mHighlightWord.escapeSequences ? String::unescape( mHighlightWord.text )
: mHighlightWord.text,
mHighlightWord.caseSensitive, mHighlightWord.wholeWord,
mHighlightWord.type, mHighlightWord.range );
mHighlightWord.type, mHighlightWord.range, 100 );
}
}
@@ -3433,7 +3447,7 @@ void UICodeEditor::drawMinimap( const Vector2f& start,
auto drawWordRanges = [&]( const TextRanges& ranges ) {
primitives.setColor( Color( mMinimapHighlightColor ).blendAlpha( mAlpha ) );
Int64 lineSkip = -1;
for ( const auto& range : ranges ) {
if ( !( range.start().line() >= minimapStartLine && range.end().line() <= endidx ) ||
!range.inSameLine() )
@@ -3442,12 +3456,18 @@ void UICodeEditor::drawMinimap( const Vector2f& start,
if ( ranges.isSorted() && range.end().line() > endidx )
break;
if ( lineSkip == range.start().line() )
continue;
Rectf selRect;
selRect.Top = rect.Top + ( range.start().line() - minimapStartLine ) * lineSpacing;
selRect.Bottom = selRect.Top + charHeight;
selRect.Left = minimapStart + getXOffsetCol( range.start() ) * widthScale;
selRect.Right = minimapStart + getXOffsetCol( range.end() ) * widthScale;
primitives.drawRectangle( selRect );
if ( selRect.Left > minimapCutoffX )
lineSkip = range.start().line();
}
};
@@ -3469,8 +3489,10 @@ void UICodeEditor::drawMinimap( const Vector2f& start,
}
}
if ( !mHighlightWord.isEmpty() )
if ( !mHighlightWord.isEmpty() ) {
Lock l( mHighlightWordCacheMutex );
drawWordRanges( mHighlightWordCache );
}
if ( mMinimapConfig.syntaxHighlight ) {
for ( int index = minimapStartLine; index <= endidx; index++ ) {
+3 -3
View File
@@ -669,15 +669,15 @@ void UIMenu::scheduledUpdate( const Time& ) {
if ( !mVisible )
return;
Node* node = getEventDispatcher()->getMouseOverNode();
if ( node && ( isChildOfMeOrSubMenu( node ) || getItemSelected() ) )
if ( node && ( isChildOrSubMenu( node ) || getItemSelected() ) )
mInactiveTime.restart();
if ( mInactiveTime.getElapsedTime() > Seconds( 1 ) )
hide();
}
bool UIMenu::isChildOfMeOrSubMenu( Node* node ) {
bool UIMenu::isChildOrSubMenu( Node* node ) {
return isParentOf( node ) || mOwnerNode == node ||
( mCurrentSubMenu && mCurrentSubMenu->isChildOfMeOrSubMenu( node ) );
( mCurrentSubMenu && mCurrentSubMenu->isChildOrSubMenu( node ) );
}
void UIMenu::findBestMenuPos( Vector2f& pos, UIMenu* menu, UIMenu* parent,
+2
View File
@@ -1212,6 +1212,8 @@ void App::init( const Float& pixelDensityConf, const bool& useAppTheme, const st
ContextSettings( false, GLv_default, true, 24, 1, 0, true ) );
if ( mWindow->isOpen() ) {
mWindow->setFrameRateLimit( displayManager->getDisplayIndex( 0 )->getRefreshRate() );
PixelDensity::setPixelDensity( eemax( mWindow->getScale(), pixelDensity ) );
mWindow->setCloseRequestCallback(