mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-05-29 17:46:29 +03:00
Ups, staged the wrong files:
Improved ThreadPool. ecode: Make consistent the find/search highlighting with the actual results (Closes SpartanJ/ecode#73). Fixed $NPROC in LSP client commands.
This commit is contained in:
@@ -53,7 +53,7 @@
|
||||
"language": "c",
|
||||
"name": "clangd",
|
||||
"url": "https://clang.llvm.org/extra/clangd/",
|
||||
"command": "clangd -log=error --background-index --header-insertion=never --limit-results=0 --limit-references=0 --clang-tidy=0 --use-dirty-headers --completion-style=bundled -j=$NPROC",
|
||||
"command": "clangd -log=error --background-index --header-insertion=never --limit-results=0 --limit-references=0 --clang-tidy=0 --use-dirty-headers --completion-style=bundled -j $NPROC",
|
||||
"file_patterns": ["%.c$", "%.h$", "%.C$", "%.H$", "%.objc$"]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef EE_SYSTEM_THREADPOOL_HPP
|
||||
#define EE_SYSTEM_THREADPOOL_HPP
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <deque>
|
||||
#include <eepp/core/noncopyable.hpp>
|
||||
@@ -27,8 +28,10 @@ class EE_API ThreadPool : NonCopyable {
|
||||
|
||||
virtual ~ThreadPool();
|
||||
|
||||
void run(
|
||||
const std::function<void()>& func, const std::function<void()>& doneCallback = []() {} );
|
||||
Uint64 run(
|
||||
const std::function<void()>& func,
|
||||
const std::function<void( const Uint64& )>& doneCallback = []( const Uint64& ) {},
|
||||
const Uint64& tag = 0 );
|
||||
|
||||
Uint32 numThreads() const;
|
||||
|
||||
@@ -36,16 +39,27 @@ class EE_API ThreadPool : NonCopyable {
|
||||
|
||||
void setTerminateOnClose( bool terminateOnClose );
|
||||
|
||||
bool existsIdInQueue( const Uint64& id );
|
||||
|
||||
bool existsTagInQueue( const Uint64& tag );
|
||||
|
||||
bool removeId( const Uint64& id );
|
||||
|
||||
bool removeWithTag( const Uint64& tag );
|
||||
|
||||
private:
|
||||
struct Work {
|
||||
Uint64 id{ 0 };
|
||||
const std::function<void()> func;
|
||||
const std::function<void()> callback;
|
||||
const std::function<void( const Uint64& )> callback;
|
||||
Uint64 tag{ 0 };
|
||||
};
|
||||
|
||||
void threadFunc();
|
||||
|
||||
std::vector<std::unique_ptr<Thread>> mThreads;
|
||||
std::deque<std::unique_ptr<Work>> mWork;
|
||||
std::atomic<Uint64> mLastWorkId;
|
||||
bool mShuttingDown = false;
|
||||
bool mTerminateOnClose = false;
|
||||
mutable std::mutex mMutex;
|
||||
|
||||
@@ -653,6 +653,30 @@ class EE_API TextDocument {
|
||||
TextRange restrictRange = TextRange() );
|
||||
};
|
||||
|
||||
struct TextSearchParams {
|
||||
String text;
|
||||
TextRange range = TextRange();
|
||||
bool caseSensitive{ false };
|
||||
bool wholeWord{ false };
|
||||
bool escapeSequences{ false };
|
||||
TextDocument::FindReplaceType type{ TextDocument::FindReplaceType::Normal };
|
||||
|
||||
bool operator==( const TextSearchParams& other ) {
|
||||
return text == other.text && range == other.range && caseSensitive == other.caseSensitive &&
|
||||
wholeWord == other.wholeWord && escapeSequences == other.escapeSequences &&
|
||||
type == other.type;
|
||||
}
|
||||
|
||||
bool operator!=( const TextSearchParams& other ) { return !( *this == other ); }
|
||||
|
||||
bool isEmpty() { return text.empty(); }
|
||||
|
||||
void reset() {
|
||||
range = TextRange();
|
||||
text = "";
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace EE::UI::Doc
|
||||
|
||||
#endif
|
||||
|
||||
@@ -40,19 +40,6 @@ class EE_API UIDocFindReplace : public UILinearLayout, public WidgetCommandExecu
|
||||
virtual void hide();
|
||||
|
||||
protected:
|
||||
struct SearchState {
|
||||
String text;
|
||||
TextRange range = TextRange();
|
||||
bool caseSensitive{ false };
|
||||
bool wholeWord{ false };
|
||||
bool escapeSequences{ false };
|
||||
TextDocument::FindReplaceType type{ TextDocument::FindReplaceType::Normal };
|
||||
void reset() {
|
||||
range = TextRange();
|
||||
text = "";
|
||||
}
|
||||
};
|
||||
|
||||
bool mReady{ false };
|
||||
UITextInput* mFindInput{ nullptr };
|
||||
UITextInput* mReplaceInput{ nullptr };
|
||||
@@ -70,16 +57,16 @@ class EE_API UIDocFindReplace : public UILinearLayout, public WidgetCommandExecu
|
||||
UIWidget* parent, const std::shared_ptr<Doc::TextDocument>& doc,
|
||||
std::unordered_map<std::string, std::string> keybindings = getDefaultKeybindings() );
|
||||
|
||||
SearchState mSearchState;
|
||||
TextSearchParams mSearchState;
|
||||
String mLastSearch;
|
||||
|
||||
bool findAndReplace( SearchState& search, const String& replace );
|
||||
bool findAndReplace( TextSearchParams& search, const String& replace );
|
||||
|
||||
bool findPrevText( SearchState& search );
|
||||
bool findPrevText( TextSearchParams& search );
|
||||
|
||||
bool findNextText( SearchState& search );
|
||||
bool findNextText( TextSearchParams& search );
|
||||
|
||||
int replaceAll( SearchState& search, const String& replace );
|
||||
int replaceAll( TextSearchParams& search, const String& replace );
|
||||
|
||||
virtual Uint32 onKeyDown( const KeyEvent& event );
|
||||
};
|
||||
|
||||
@@ -426,9 +426,9 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client {
|
||||
|
||||
void setShowWhitespaces( const bool& showWhitespaces );
|
||||
|
||||
const String& getHighlightWord() const;
|
||||
const TextSearchParams& getHighlightWord() const;
|
||||
|
||||
void setHighlightWord( const String& highlightWord );
|
||||
void setHighlightWord( const TextSearchParams& highlightWord );
|
||||
|
||||
const TextRange& getHighlightTextRange() const;
|
||||
|
||||
@@ -628,6 +628,7 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client {
|
||||
bool mAutoCloseXMLTags{ false };
|
||||
bool mFindReplaceEnabled{ true };
|
||||
bool mShowIndentationGuides{ false };
|
||||
std::atomic<bool> mHighlightWordProcessing{ false };
|
||||
TextRange mLinkPosition;
|
||||
String mLink;
|
||||
Uint32 mTabWidth;
|
||||
@@ -666,7 +667,8 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client {
|
||||
Float mLongestLineWidth{ 0 };
|
||||
Time mFindLongestLineWidthUpdateFrequency;
|
||||
Clock mLongestLineWidthLastUpdate;
|
||||
String mHighlightWord;
|
||||
TextSearchParams mHighlightWord;
|
||||
TextRanges mHighlightWordCache;
|
||||
TextRange mHighlightTextRange;
|
||||
Color mPreviewColor;
|
||||
TextRange mPreviewColorRange;
|
||||
@@ -859,6 +861,12 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client {
|
||||
bool createContextMenu();
|
||||
|
||||
bool stopMinimapDragging( const Vector2f& mousePos );
|
||||
|
||||
void drawWordRanges( const TextRanges& ranges, const std::pair<int, int>& lineRange,
|
||||
const Vector2f& startScroll, const Float& lineHeight,
|
||||
bool ignoreSelectionMatch );
|
||||
|
||||
void updateHighlightWordCache();
|
||||
};
|
||||
|
||||
}} // namespace EE::UI
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define EE_UISCENENODE_HPP
|
||||
|
||||
#include <eepp/scene/scenenode.hpp>
|
||||
#include <eepp/system/threadpool.hpp>
|
||||
#include <eepp/system/translator.hpp>
|
||||
#include <eepp/ui/css/stylesheet.hpp>
|
||||
#include <eepp/ui/keyboardshortcut.hpp>
|
||||
@@ -158,6 +159,12 @@ class EE_API UISceneNode : public SceneNode {
|
||||
|
||||
void reloadStyle( bool disableAnimations = false, bool forceReApplyProperties = false );
|
||||
|
||||
bool hasThreadPool() const;
|
||||
|
||||
std::shared_ptr<ThreadPool> getThreadPool();
|
||||
|
||||
void setThreadPool( const std::shared_ptr<ThreadPool>& threadPool );
|
||||
|
||||
protected:
|
||||
friend class EE::UI::UIWindow;
|
||||
friend class EE::UI::UIWidget;
|
||||
@@ -184,6 +191,7 @@ class EE_API UISceneNode : public SceneNode {
|
||||
Uint32 mMaxInvalidationDepth{ 2 };
|
||||
Node* mCurParent{ nullptr };
|
||||
Uint32 mCurOnSizeChangeListener{ 0 };
|
||||
std::shared_ptr<ThreadPool> mThreadPool;
|
||||
|
||||
virtual void resizeNode( EE::Window::Window* win );
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ void ResourceLoader::taskRunner() {
|
||||
auto pool = ThreadPool::createUnique( eemin( mThreads, (Uint32)mTasks.size() ) );
|
||||
|
||||
for ( auto& task : mTasks ) {
|
||||
pool->run( task, [&] { mTotalLoaded++; } );
|
||||
pool->run( task, [&]( const auto& ) { mTotalLoaded++; } );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ void ThreadPool::threadFunc() {
|
||||
work->func();
|
||||
|
||||
if ( work->callback != nullptr ) {
|
||||
work->callback();
|
||||
work->callback( work->id );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -73,18 +73,58 @@ void ThreadPool::setTerminateOnClose( bool terminateOnClose ) {
|
||||
mTerminateOnClose = terminateOnClose;
|
||||
}
|
||||
|
||||
void ThreadPool::run( const std::function<void()>& func,
|
||||
const std::function<void()>& doneCallback ) {
|
||||
bool ThreadPool::existsIdInQueue( const Uint64& id ) {
|
||||
std::unique_lock<std::mutex> lock( mMutex );
|
||||
return std::any_of( mWork.begin(), mWork.end(),
|
||||
[id]( const std::unique_ptr<Work>& work ) { return work->id == id; } );
|
||||
}
|
||||
|
||||
bool ThreadPool::existsTagInQueue( const Uint64& tag ) {
|
||||
std::unique_lock<std::mutex> lock( mMutex );
|
||||
return std::any_of( mWork.begin(), mWork.end(),
|
||||
[tag]( const std::unique_ptr<Work>& work ) { return work->tag == tag; } );
|
||||
}
|
||||
|
||||
bool ThreadPool::removeId( const Uint64& id ) {
|
||||
std::unique_lock<std::mutex> lock( mMutex );
|
||||
for ( auto it = mWork.begin(); it != mWork.end(); ++it ) {
|
||||
if ( it->get()->id == id ) {
|
||||
mWork.erase( it );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ThreadPool::removeWithTag( const Uint64& tag ) {
|
||||
std::vector<Uint64> ids;
|
||||
{
|
||||
std::unique_lock<std::mutex> lock( mMutex );
|
||||
for ( const auto& work : mWork )
|
||||
if ( work->tag == tag )
|
||||
ids.emplace_back( work->id );
|
||||
}
|
||||
for ( const auto& id : ids )
|
||||
removeId( id );
|
||||
return !ids.empty();
|
||||
}
|
||||
|
||||
Uint64 ThreadPool::run( const std::function<void()>& func,
|
||||
const std::function<void( const Uint64& )>& doneCallback,
|
||||
const Uint64& tag ) {
|
||||
Uint64 id = ++mLastWorkId;
|
||||
{
|
||||
std::unique_lock<std::mutex> lock( mMutex );
|
||||
|
||||
if ( mShuttingDown )
|
||||
return;
|
||||
return id;
|
||||
|
||||
mWork.emplace_back( new Work{ func, doneCallback } );
|
||||
mWork.emplace_back( new Work{ id, func, doneCallback, tag } );
|
||||
}
|
||||
|
||||
mWorkAvailable.notify_one();
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
Uint32 ThreadPool::numThreads() const {
|
||||
|
||||
@@ -391,21 +391,19 @@ bool TextDocument::loadAsyncFromFile( const std::string& path, std::shared_ptr<T
|
||||
mLoadingFilePath = path;
|
||||
mLoadingFileURI = URI( "file://" + mLoadingFilePath );
|
||||
}
|
||||
pool->run(
|
||||
[this, path, onLoaded] {
|
||||
auto loaded = loadFromFile( path );
|
||||
if ( loaded != LoadStatus::Interrupted && onLoaded ) {
|
||||
onLoaded( this, loaded == LoadStatus::Loaded );
|
||||
}
|
||||
{
|
||||
Lock l( mLoadingFilePathMutex );
|
||||
mLoadingFilePath.clear();
|
||||
mLoadingFileURI = URI();
|
||||
}
|
||||
mLoadingAsync = false;
|
||||
notifyDocumentLoaded();
|
||||
},
|
||||
[] {} );
|
||||
pool->run( [this, path, onLoaded] {
|
||||
auto loaded = loadFromFile( path );
|
||||
if ( loaded != LoadStatus::Interrupted && onLoaded ) {
|
||||
onLoaded( this, loaded == LoadStatus::Loaded );
|
||||
}
|
||||
{
|
||||
Lock l( mLoadingFilePathMutex );
|
||||
mLoadingFilePath.clear();
|
||||
mLoadingFileURI = URI();
|
||||
}
|
||||
mLoadingAsync = false;
|
||||
notifyDocumentLoaded();
|
||||
} );
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2032,7 +2030,7 @@ TextRange TextDocument::findText( String text, TextPosition from, const bool& ca
|
||||
return TextRange();
|
||||
}
|
||||
|
||||
if ( !caseSensitive )
|
||||
if ( !caseSensitive && type != FindReplaceType::LuaPattern )
|
||||
text.toLower();
|
||||
|
||||
for ( Int64 i = from.line(); i <= to.line(); i++ ) {
|
||||
@@ -2081,7 +2079,7 @@ TextRange TextDocument::findTextLast( String text, TextPosition from, const bool
|
||||
return TextRange();
|
||||
}
|
||||
|
||||
if ( !caseSensitive )
|
||||
if ( !caseSensitive && type != FindReplaceType::LuaPattern )
|
||||
text.toLower();
|
||||
|
||||
for ( Int64 i = from.line(); i >= to.line(); i-- ) {
|
||||
@@ -2279,6 +2277,8 @@ TextRanges TextDocument::findAll( const String& text, const bool& caseSensitive,
|
||||
do {
|
||||
found = find( text, from, caseSensitive, wholeWord, type, restrictRange );
|
||||
if ( found.isValid() ) {
|
||||
if ( !all.empty() && all.back() == found )
|
||||
break;
|
||||
from = found.end();
|
||||
all.push_back( found );
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ UIDocFindReplace::UIDocFindReplace( UIWidget* parent, const std::shared_ptr<Doc:
|
||||
mFindInput->addEventListener( Event::OnTextChanged, [&, editor]( const Event* ) {
|
||||
mSearchState.text = mFindInput->getText();
|
||||
if ( editor )
|
||||
editor->setHighlightWord( mSearchState.text );
|
||||
editor->setHighlightWord( mSearchState );
|
||||
if ( !mSearchState.text.empty() ) {
|
||||
mDoc->setSelection( { 0, 0 } );
|
||||
if ( !findNextText( mSearchState ) ) {
|
||||
@@ -374,7 +374,7 @@ void UIDocFindReplace::show( bool expanded ) {
|
||||
|
||||
if ( editor ) {
|
||||
editor->setHighlightTextRange( mSearchState.range );
|
||||
editor->setHighlightWord( mSearchState.text );
|
||||
editor->setHighlightWord( mSearchState );
|
||||
mDoc->setActiveClient( editor );
|
||||
}
|
||||
}
|
||||
@@ -391,14 +391,14 @@ void UIDocFindReplace::hide() {
|
||||
mSearchState.range = TextRange();
|
||||
mSearchState.text = "";
|
||||
if ( editor ) {
|
||||
editor->setHighlightWord( "" );
|
||||
editor->setHighlightWord( { "" } );
|
||||
editor->setHighlightTextRange( TextRange() );
|
||||
}
|
||||
|
||||
getParent()->setFocus();
|
||||
}
|
||||
|
||||
bool UIDocFindReplace::findPrevText( SearchState& search ) {
|
||||
bool UIDocFindReplace::findPrevText( TextSearchParams& search ) {
|
||||
if ( search.text.empty() )
|
||||
search.text = mLastSearch;
|
||||
|
||||
@@ -433,7 +433,7 @@ bool UIDocFindReplace::findPrevText( SearchState& search ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UIDocFindReplace::findNextText( SearchState& search ) {
|
||||
bool UIDocFindReplace::findNextText( TextSearchParams& search ) {
|
||||
if ( search.text.empty() )
|
||||
search.text = mLastSearch;
|
||||
|
||||
@@ -469,7 +469,7 @@ bool UIDocFindReplace::findNextText( SearchState& search ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int UIDocFindReplace::replaceAll( SearchState& search, const String& replace ) {
|
||||
int UIDocFindReplace::replaceAll( TextSearchParams& search, const String& replace ) {
|
||||
if ( search.text.empty() )
|
||||
search.text = mLastSearch;
|
||||
if ( search.text.empty() )
|
||||
@@ -495,7 +495,7 @@ Uint32 UIDocFindReplace::onKeyDown( const KeyEvent& event ) {
|
||||
return WidgetCommandExecuter::onKeyDown( event );
|
||||
}
|
||||
|
||||
bool UIDocFindReplace::findAndReplace( SearchState& search, const String& replace ) {
|
||||
bool UIDocFindReplace::findAndReplace( TextSearchParams& search, const String& replace ) {
|
||||
if ( search.text.empty() )
|
||||
search.text = mLastSearch;
|
||||
if ( search.text.empty() )
|
||||
|
||||
@@ -173,6 +173,10 @@ UICodeEditor::~UICodeEditor() {
|
||||
for ( auto& plugin : mPlugins )
|
||||
plugin->onUnregister( this );
|
||||
|
||||
// TODO: Use a condition variable to wait the thread pool to finish
|
||||
while ( mHighlightWordProcessing )
|
||||
Sys::sleep( Milliseconds( 1 ) );
|
||||
|
||||
if ( mDoc.use_count() == 1 ) {
|
||||
DocEvent event( this, mDoc.get(), Event::OnDocumentClosed );
|
||||
sendEvent( &event );
|
||||
@@ -285,9 +289,8 @@ void UICodeEditor::draw() {
|
||||
}
|
||||
}
|
||||
|
||||
if ( !mHighlightWord.empty() ) {
|
||||
drawWordMatch( mHighlightWord, lineRange, startScroll, lineHeight );
|
||||
}
|
||||
if ( !mHighlightWord.isEmpty() )
|
||||
drawWordRanges( mHighlightWordCache, lineRange, startScroll, lineHeight, true );
|
||||
|
||||
if ( mShowIndentationGuides ) {
|
||||
drawIndentationGuides( lineRange, startScroll, lineHeight );
|
||||
@@ -1562,6 +1565,9 @@ void UICodeEditor::onDocumentLineChanged( const Int64& lineNumber ) {
|
||||
mDoc->getHighlighter()->invalidate( lineNumber );
|
||||
if ( mFont && !mFont->isMonospace() )
|
||||
updateLineCache( lineNumber );
|
||||
|
||||
if ( !mHighlightWord.isEmpty() )
|
||||
updateHighlightWordCache();
|
||||
}
|
||||
|
||||
void UICodeEditor::onDocumentUndoRedo( const TextDocument::UndoRedo& ) {
|
||||
@@ -2470,13 +2476,33 @@ void UICodeEditor::setShowWhitespaces( const bool& showWhitespaces ) {
|
||||
}
|
||||
}
|
||||
|
||||
const String& UICodeEditor::getHighlightWord() const {
|
||||
const TextSearchParams& UICodeEditor::getHighlightWord() const {
|
||||
return mHighlightWord;
|
||||
}
|
||||
|
||||
void UICodeEditor::setHighlightWord( const String& highlightWord ) {
|
||||
void UICodeEditor::updateHighlightWordCache() {
|
||||
if ( getUISceneNode()->hasThreadPool() ) {
|
||||
Uint64 tag = reinterpret_cast<Uint64>( this );
|
||||
getUISceneNode()->getThreadPool()->removeWithTag( tag );
|
||||
getUISceneNode()->getThreadPool()->run(
|
||||
[this]() {
|
||||
mHighlightWordProcessing = true;
|
||||
mHighlightWordCache = mDoc->findAll(
|
||||
mHighlightWord.text, mHighlightWord.caseSensitive, mHighlightWord.wholeWord,
|
||||
mHighlightWord.type, mHighlightWord.range );
|
||||
},
|
||||
[this]( const auto& ) { mHighlightWordProcessing = false; }, tag );
|
||||
} else {
|
||||
mHighlightWordCache =
|
||||
mDoc->findAll( mHighlightWord.text, mHighlightWord.caseSensitive,
|
||||
mHighlightWord.wholeWord, mHighlightWord.type, mHighlightWord.range );
|
||||
}
|
||||
}
|
||||
|
||||
void UICodeEditor::setHighlightWord( const TextSearchParams& highlightWord ) {
|
||||
if ( mHighlightWord != highlightWord ) {
|
||||
mHighlightWord = highlightWord;
|
||||
updateHighlightWordCache();
|
||||
invalidateDraw();
|
||||
}
|
||||
}
|
||||
@@ -2572,6 +2598,43 @@ void UICodeEditor::drawSelectionMatch( const std::pair<int, int>& lineRange,
|
||||
}
|
||||
}
|
||||
|
||||
void UICodeEditor::drawWordRanges( const TextRanges& ranges, const std::pair<int, int>& lineRange,
|
||||
const Vector2f& startScroll, const Float& lineHeight,
|
||||
bool ignoreSelectionMatch ) {
|
||||
if ( ranges.empty() )
|
||||
return;
|
||||
Primitives primitives;
|
||||
primitives.setForceDraw( false );
|
||||
primitives.setColor( Color( mSelectionMatchColor ).blendAlpha( mAlpha ) );
|
||||
TextRange selection = mDoc->getSelection( true );
|
||||
|
||||
for ( const auto& range : ranges ) {
|
||||
if ( !( range.start().line() >= lineRange.first &&
|
||||
range.end().line() <= lineRange.second ) )
|
||||
continue;
|
||||
|
||||
if ( ignoreSelectionMatch && selection.inSameLine() &&
|
||||
selection.start().line() == range.start().line() &&
|
||||
selection.start().column() == range.start().column() ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !range.inSameLine() )
|
||||
continue;
|
||||
|
||||
Rectf selRect;
|
||||
Int64 startCol = range.start().column();
|
||||
Int64 endCol = range.end().column();
|
||||
selRect.Top = startScroll.y + range.start().line() * lineHeight;
|
||||
selRect.Bottom = selRect.Top + lineHeight;
|
||||
selRect.Left = startScroll.x + getXOffsetCol( { range.start().line(), startCol } );
|
||||
selRect.Right = startScroll.x + getXOffsetCol( { range.start().line(), endCol } );
|
||||
primitives.drawRectangle( selRect );
|
||||
}
|
||||
|
||||
primitives.setForceDraw( true );
|
||||
}
|
||||
|
||||
void UICodeEditor::drawWordMatch( const String& text, const std::pair<int, int>& lineRange,
|
||||
const Vector2f& startScroll, const Float& lineHeight,
|
||||
bool ignoreSelectionMatch ) {
|
||||
@@ -3267,6 +3330,23 @@ void UICodeEditor::drawMinimap( const Vector2f& start,
|
||||
primitives.drawRectangle( selRect );
|
||||
};
|
||||
|
||||
auto drawWordRanges = [&]( const TextRanges& ranges ) {
|
||||
primitives.setColor( Color( mMinimapHighlightColor ).blendAlpha( mAlpha ) );
|
||||
|
||||
for ( const auto& range : ranges ) {
|
||||
if ( !( range.start().line() >= minimapStartLine && range.end().line() <= endidx ) ||
|
||||
!range.inSameLine() )
|
||||
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 );
|
||||
}
|
||||
};
|
||||
|
||||
String selectionString;
|
||||
|
||||
if ( mDoc->hasSelection() &&
|
||||
@@ -3285,16 +3365,16 @@ void UICodeEditor::drawMinimap( const Vector2f& start,
|
||||
}
|
||||
}
|
||||
|
||||
if ( !mHighlightWord.isEmpty() )
|
||||
drawWordRanges( mHighlightWordCache );
|
||||
|
||||
if ( mMinimapConfig.syntaxHighlight ) {
|
||||
for ( int index = minimapStartLine; index <= endidx; index++ ) {
|
||||
batchSyntaxType = "normal";
|
||||
batchStart = rect.Left + gutterWidth;
|
||||
batchWidth = 0;
|
||||
|
||||
if ( !mHighlightWord.empty() )
|
||||
drawWordMatch( mHighlightWord, index );
|
||||
|
||||
if ( !selectionString.empty() )
|
||||
if ( mHighlightWord.isEmpty() && !selectionString.empty() )
|
||||
drawWordMatch( selectionString, index );
|
||||
|
||||
for ( auto* plugin : mPlugins )
|
||||
@@ -3363,9 +3443,7 @@ void UICodeEditor::drawMinimap( const Vector2f& start,
|
||||
batchStart = rect.Left + gutterWidth;
|
||||
batchWidth = 0;
|
||||
|
||||
if ( !mHighlightWord.empty() )
|
||||
drawWordMatch( mHighlightWord, index );
|
||||
if ( !selectionString.empty() )
|
||||
if ( mHighlightWord.isEmpty() && !selectionString.empty() )
|
||||
drawWordMatch( selectionString, index );
|
||||
|
||||
const String& text( mDoc->line( index ).getText() );
|
||||
|
||||
@@ -402,6 +402,18 @@ void UISceneNode::reloadStyle( bool disableAnimations, bool forceReApplyProperti
|
||||
}
|
||||
}
|
||||
|
||||
bool UISceneNode::hasThreadPool() const {
|
||||
return mThreadPool != nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<ThreadPool> UISceneNode::getThreadPool() {
|
||||
return mThreadPool;
|
||||
}
|
||||
|
||||
void UISceneNode::setThreadPool( const std::shared_ptr<ThreadPool>& threadPool ) {
|
||||
mThreadPool = threadPool;
|
||||
}
|
||||
|
||||
UIWidget* UISceneNode::loadLayoutFromFile( const std::string& layoutPath, Node* parent,
|
||||
const Uint32& marker ) {
|
||||
if ( FileSystem::fileExists( layoutPath ) ) {
|
||||
|
||||
@@ -80,7 +80,7 @@ void DocSearchController::initSearchBar(
|
||||
mFindInput->addEventListener( Event::OnTextChanged, [&]( const Event* ) {
|
||||
if ( mSearchState.editor && mEditorSplitter->editorExists( mSearchState.editor ) ) {
|
||||
mSearchState.text = mFindInput->getText();
|
||||
mSearchState.editor->setHighlightWord( mSearchState.text );
|
||||
mSearchState.editor->setHighlightWord( mSearchState.toTextSearchParams() );
|
||||
if ( !mSearchState.text.empty() ) {
|
||||
mSearchState.editor->getDocument().setSelection( { 0, 0 } );
|
||||
if ( !findNextText( mSearchState ) ) {
|
||||
@@ -108,7 +108,7 @@ void DocSearchController::initSearchBar(
|
||||
mEditorSplitter->getCurWidget()->setFocus();
|
||||
if ( mSearchState.editor ) {
|
||||
if ( mEditorSplitter->editorExists( mSearchState.editor ) ) {
|
||||
mSearchState.editor->setHighlightWord( "" );
|
||||
mSearchState.editor->setHighlightWord( { "" } );
|
||||
mSearchState.editor->setHighlightTextRange( TextRange() );
|
||||
}
|
||||
}
|
||||
@@ -187,7 +187,7 @@ void DocSearchController::showFindView() {
|
||||
}
|
||||
mSearchState.text = mFindInput->getText();
|
||||
editor->setHighlightTextRange( mSearchState.range );
|
||||
editor->setHighlightWord( mSearchState.text );
|
||||
editor->setHighlightWord( mSearchState.toTextSearchParams() );
|
||||
editor->getDocument().setActiveClient( editor );
|
||||
}
|
||||
|
||||
@@ -350,8 +350,8 @@ void DocSearchController::hideSearchBar() {
|
||||
|
||||
void DocSearchController::onCodeEditorFocusChange( UICodeEditor* editor ) {
|
||||
if ( mSearchState.editor && mSearchState.editor != editor ) {
|
||||
String word = mSearchState.editor->getHighlightWord();
|
||||
mSearchState.editor->setHighlightWord( "" );
|
||||
auto word = mSearchState.editor->getHighlightWord();
|
||||
mSearchState.editor->setHighlightWord( { "" } );
|
||||
mSearchState.editor->setHighlightTextRange( TextRange() );
|
||||
mSearchState.text = "";
|
||||
mSearchState.range = TextRange();
|
||||
|
||||
@@ -19,6 +19,10 @@ struct SearchState {
|
||||
range = TextRange();
|
||||
text = "";
|
||||
}
|
||||
|
||||
TextSearchParams toTextSearchParams() {
|
||||
return { text, range, caseSensitive, wholeWord, escapeSequences, type };
|
||||
}
|
||||
};
|
||||
|
||||
class App;
|
||||
|
||||
@@ -1832,24 +1832,22 @@ void App::loadFileFromPath(
|
||||
mImageLayout->setEnabled( true )->setVisible( true );
|
||||
loaderView->setVisible( true );
|
||||
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ )
|
||||
mThreadPool->run(
|
||||
[&, imageView, loaderView, path]() {
|
||||
mThreadPool->run( [&, imageView, loaderView, path]() {
|
||||
#endif
|
||||
Texture* image = TextureFactory::instance()->getTexture(
|
||||
TextureFactory::instance()->loadFromFile( path ) );
|
||||
if ( mImageLayout->isVisible() ) {
|
||||
imageView->runOnMainThread( [imageView, loaderView, image]() {
|
||||
imageView->setDrawable( image, true );
|
||||
loaderView->setVisible( false );
|
||||
} );
|
||||
} else {
|
||||
TextureFactory::instance()->remove( image );
|
||||
imageView->setDrawable( nullptr );
|
||||
Texture* image = TextureFactory::instance()->getTexture(
|
||||
TextureFactory::instance()->loadFromFile( path ) );
|
||||
if ( mImageLayout->isVisible() ) {
|
||||
imageView->runOnMainThread( [imageView, loaderView, image]() {
|
||||
imageView->setDrawable( image, true );
|
||||
loaderView->setVisible( false );
|
||||
}
|
||||
} );
|
||||
} else {
|
||||
TextureFactory::instance()->remove( image );
|
||||
imageView->setDrawable( nullptr );
|
||||
loaderView->setVisible( false );
|
||||
}
|
||||
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ )
|
||||
},
|
||||
[]() {} );
|
||||
} );
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
@@ -2841,6 +2839,7 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe
|
||||
eemax( mWindow->getScale(), mConfig.windowState.pixelDensity ) );
|
||||
|
||||
mUISceneNode = UISceneNode::New();
|
||||
mUISceneNode->setThreadPool( mThreadPool );
|
||||
mUIColorScheme = mConfig.ui.colorScheme;
|
||||
if ( !colorScheme.empty() ) {
|
||||
mUIColorScheme =
|
||||
|
||||
@@ -142,12 +142,10 @@ void AutoCompletePlugin::onRegister( UICodeEditor* editor ) {
|
||||
std::string oldLang = event->getOldLang();
|
||||
std::string newLang = event->getNewLang();
|
||||
#if AUTO_COMPLETE_THREADED
|
||||
mPool->run(
|
||||
[&, oldLang, newLang] {
|
||||
updateLangCache( oldLang );
|
||||
updateLangCache( newLang );
|
||||
},
|
||||
[] {} );
|
||||
mPool->run( [&, oldLang, newLang] {
|
||||
updateLangCache( oldLang );
|
||||
updateLangCache( newLang );
|
||||
} );
|
||||
#else
|
||||
updateLangCache( oldLang );
|
||||
updateLangCache( newLang );
|
||||
@@ -589,7 +587,7 @@ void AutoCompletePlugin::update( UICodeEditor* ) {
|
||||
continue;
|
||||
}
|
||||
#if AUTO_COMPLETE_THREADED
|
||||
mPool->run( [&, doc] { updateDocCache( doc ); }, [] {} );
|
||||
mPool->run( [&, doc] { updateDocCache( doc ); } );
|
||||
#else
|
||||
updateDocCache( doc );
|
||||
#endif
|
||||
@@ -980,8 +978,7 @@ void AutoCompletePlugin::updateSuggestions( const std::string& symbol, UICodeEdi
|
||||
{
|
||||
#if AUTO_COMPLETE_THREADED
|
||||
mPool->run(
|
||||
[this, symbol, symbols, editor] { runUpdateSuggestions( symbol, symbols, editor ); },
|
||||
[] {} );
|
||||
[this, symbol, symbols, editor] { runUpdateSuggestions( symbol, symbols, editor ); } );
|
||||
#else
|
||||
runUpdateSuggestions( symbol, symbols, editor );
|
||||
#endif
|
||||
|
||||
@@ -37,7 +37,7 @@ FormatterPlugin::FormatterPlugin( PluginManager* pluginManager, bool sync ) :
|
||||
load( pluginManager );
|
||||
} else {
|
||||
#if FORMATTER_THREADED
|
||||
mPool->run( [&, pluginManager] { load( pluginManager ); }, [] {} );
|
||||
mPool->run( [&, pluginManager] { load( pluginManager ); } );
|
||||
#else
|
||||
load( pluginManager );
|
||||
#endif
|
||||
|
||||
@@ -36,7 +36,7 @@ LinterPlugin::LinterPlugin( PluginManager* pluginManager, bool sync ) :
|
||||
load( pluginManager );
|
||||
} else {
|
||||
#if LINTER_THREADED
|
||||
mPool->run( [&, pluginManager] { load( pluginManager ); }, [] {} );
|
||||
mPool->run( [&, pluginManager] { load( pluginManager ); } );
|
||||
#else
|
||||
load( pluginManager );
|
||||
#endif
|
||||
@@ -440,7 +440,7 @@ void LinterPlugin::update( UICodeEditor* editor ) {
|
||||
if ( it != mDirtyDoc.end() && it->second->getElapsedTime() >= mDelayTime ) {
|
||||
mDirtyDoc.erase( doc.get() );
|
||||
#if LINTER_THREADED
|
||||
mPool->run( [&, doc] { lintDoc( doc ); }, [] {} );
|
||||
mPool->run( [&, doc] { lintDoc( doc ); } );
|
||||
#else
|
||||
lintDoc( doc );
|
||||
#endif
|
||||
|
||||
@@ -121,7 +121,7 @@ LSPClientPlugin::LSPClientPlugin( PluginManager* pluginManager, bool sync ) :
|
||||
if ( sync ) {
|
||||
load( pluginManager );
|
||||
} else {
|
||||
mThreadPool->run( [&, pluginManager] { load( pluginManager ); }, [] {} );
|
||||
mThreadPool->run( [&, pluginManager] { load( pluginManager ); } );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ static LSPURIAndServer getServerURIFromTextDocumentURI( LSPClientServerManager&
|
||||
return { uri, manager.getOneLSPClientServer( uri ) };
|
||||
}
|
||||
|
||||
static void sanitizeCommand( std::string cmd ) {
|
||||
static void sanitizeCommand( std::string& cmd ) {
|
||||
String::replaceAll( cmd, "$NPROC", String::toString( Sys::getCPUCount() ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -187,7 +187,7 @@ void LSPClientServerManager::applyWorkspaceEdit(
|
||||
}
|
||||
|
||||
void LSPClientServerManager::run( const std::shared_ptr<TextDocument>& doc ) {
|
||||
mThreadPool->run( [&, doc]() { tryRunServer( doc ); }, []() {} );
|
||||
mThreadPool->run( [&, doc]() { tryRunServer( doc ); } );
|
||||
}
|
||||
|
||||
size_t LSPClientServerManager::clientCount() const {
|
||||
|
||||
@@ -86,7 +86,7 @@ void ProjectDirectoryTree::scan( const ProjectDirectoryTree::ScanCompleteEvent&
|
||||
#endif
|
||||
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ )
|
||||
},
|
||||
[scanComplete, this] {
|
||||
[scanComplete, this] ( const auto& ) {
|
||||
if ( scanComplete )
|
||||
scanComplete( *this );
|
||||
} );
|
||||
@@ -155,12 +155,12 @@ std::shared_ptr<FileListModel> ProjectDirectoryTree::matchTree( const std::strin
|
||||
|
||||
void ProjectDirectoryTree::asyncFuzzyMatchTree( const std::string& match, const size_t& max,
|
||||
ProjectDirectoryTree::MatchResultCb res ) const {
|
||||
mPool->run( [&, match, max, res]() { res( fuzzyMatchTree( match, max ) ); }, []() {} );
|
||||
mPool->run( [&, match, max, res]() { res( fuzzyMatchTree( match, max ) ); } );
|
||||
}
|
||||
|
||||
void ProjectDirectoryTree::asyncMatchTree( const std::string& match, const size_t& max,
|
||||
ProjectDirectoryTree::MatchResultCb res ) const {
|
||||
mPool->run( [&, match, max, res]() { res( matchTree( match, max ) ); }, []() {} );
|
||||
mPool->run( [&, match, max, res]() { res( matchTree( match, max ) ); } );
|
||||
}
|
||||
|
||||
std::shared_ptr<FileListModel>
|
||||
|
||||
@@ -169,7 +169,7 @@ void ProjectSearch::find( const std::vector<std::string> files, std::string stri
|
||||
findData->res.push_back( { file, fileRes } );
|
||||
}
|
||||
},
|
||||
[result, findData] {
|
||||
[result, findData]( const auto& ) {
|
||||
int count;
|
||||
{
|
||||
Lock l( findData->countMutex );
|
||||
|
||||
Reference in New Issue
Block a user