From 6ffda350392deed4e0a16b040aa62ee749184c0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Sat, 11 Jun 2022 02:39:27 -0300 Subject: [PATCH] UICodeEditorSplitter: several fixes and added some sanity checks for debug builds. ecode: Some minor fixes. --- include/eepp/scene/scenenode.hpp | 2 + .../eepp/ui/tools/uicodeeditorsplitter.hpp | 16 +++- src/eepp/scene/node.cpp | 1 + src/eepp/scene/scenenode.cpp | 9 ++ src/eepp/ui/doc/syntaxcolorscheme.cpp | 2 +- src/eepp/ui/doc/syntaxdefinitionmanager.cpp | 13 +-- src/eepp/ui/tools/uicodeeditorsplitter.cpp | 96 +++++++++++++++---- src/eepp/ui/uicodeeditor.cpp | 4 + src/examples/vbo_fbo_batch/vbo_fbo_batch.cpp | 2 +- src/tools/ecode/docsearchcontroller.cpp | 3 + src/tools/ecode/ecode.cpp | 13 ++- 11 files changed, 127 insertions(+), 34 deletions(-) diff --git a/include/eepp/scene/scenenode.hpp b/include/eepp/scene/scenenode.hpp index e875a0cdb..c26f587a6 100644 --- a/include/eepp/scene/scenenode.hpp +++ b/include/eepp/scene/scenenode.hpp @@ -155,6 +155,8 @@ class EE_API SceneNode : public Node { void addToCloseQueue( Node* node ); + bool removeFromCloseQueue( Node* node ); + void checkClose(); void createFrameBuffer(); diff --git a/include/eepp/ui/tools/uicodeeditorsplitter.hpp b/include/eepp/ui/tools/uicodeeditorsplitter.hpp index 3984ea2bc..e82f94db0 100644 --- a/include/eepp/ui/tools/uicodeeditorsplitter.hpp +++ b/include/eepp/ui/tools/uicodeeditorsplitter.hpp @@ -101,11 +101,11 @@ class EE_API UICodeEditorSplitter { void applyColorScheme( const SyntaxColorScheme& colorScheme ); - void forEachEditor( std::function run ); + void forEachEditor( std::function run ) const; - void forEachDoc( std::function run ); + void forEachDoc( std::function run ) const; - void forEachTabWidget( std::function run ); + void forEachTabWidget( std::function run ) const; void zoomIn(); @@ -133,11 +133,11 @@ class EE_API UICodeEditorSplitter { bool isAnyEditorDirty(); - void forEachEditorStoppable( std::function run ); + void forEachEditorStoppable( std::function run ) const; std::vector getAllEditors(); - void forEachDocStoppable( std::function run ); + void forEachDocStoppable( std::function run ) const; std::shared_ptr findDocFromPath( const std::string& path ); @@ -158,11 +158,17 @@ class EE_API UICodeEditorSplitter { Node* mBaseLayout{ nullptr }; Client* mClient; bool mHideTabBarOnSingleTab{ true }; + bool mFirstCodeEditor{ true }; + UICodeEditor* mAboutToAddEditor{ nullptr }; UICodeEditorSplitter( UICodeEditorSplitter::Client* client, UISceneNode* sceneNode, const std::vector& colorSchemes, const std::string& initColorScheme ); + bool curEditorExists() const; + + bool checkEditorExists( UICodeEditor* ) const; + virtual void onTabClosed( const TabEvent* tabEvent ); }; diff --git a/src/eepp/scene/node.cpp b/src/eepp/scene/node.cpp index d63dfc5f7..0f9520f27 100644 --- a/src/eepp/scene/node.cpp +++ b/src/eepp/scene/node.cpp @@ -948,6 +948,7 @@ void Node::forEachChild( std::function func ) { void Node::onSceneChange() { mSceneNode = findSceneNode(); + eeASSERT( !mSceneNode->removeFromCloseQueue( this ) ); Node* child = mChild; diff --git a/src/eepp/scene/scenenode.cpp b/src/eepp/scene/scenenode.cpp index 22a1d6ef9..54ac8221f 100644 --- a/src/eepp/scene/scenenode.cpp +++ b/src/eepp/scene/scenenode.cpp @@ -219,6 +219,15 @@ void SceneNode::addToCloseQueue( Node* node ) { mCloseList.insert( node ); } +bool SceneNode::removeFromCloseQueue( Node* node ) { + auto it = mCloseList.find( node ); + if ( it != mCloseList.end() ) { + mCloseList.erase( it ); + return true; + } + return false; +} + void SceneNode::checkClose() { if ( !mCloseList.empty() ) { // First we need to create a temporal copy of the close list because it can change its diff --git a/src/eepp/ui/doc/syntaxcolorscheme.cpp b/src/eepp/ui/doc/syntaxcolorscheme.cpp index ae0806fa2..cf8973dc6 100644 --- a/src/eepp/ui/doc/syntaxcolorscheme.cpp +++ b/src/eepp/ui/doc/syntaxcolorscheme.cpp @@ -205,7 +205,7 @@ SyntaxColorScheme::getEditorSyntaxStyle( const std::string& type ) const { auto it = mEditorColors.find( type ); if ( it != mEditorColors.end() ) return it->second; - if ( type == "gutter_background" || "minimap_background" ) + if ( type == "gutter_background" || type == "minimap_background" ) return getEditorSyntaxStyle( "background" ); else if ( type == "whitespace" || type == "line_break_column" || type == "matching_bracket" || type == "matching_selection" || type == "selection_region" ) diff --git a/src/eepp/ui/doc/syntaxdefinitionmanager.cpp b/src/eepp/ui/doc/syntaxdefinitionmanager.cpp index 6d6b27781..459285a73 100644 --- a/src/eepp/ui/doc/syntaxdefinitionmanager.cpp +++ b/src/eepp/ui/doc/syntaxdefinitionmanager.cpp @@ -235,10 +235,10 @@ SyntaxDefinitionManager::SyntaxDefinitionManager() { { "normal", "keyword2", "function", "operator", "keyword" } }, { { "([%w_][%w_]+)%.([%w_][%w%d_]*)%s*(=)%s*(async%s*function)" }, { "normal", "keyword2", "function", "operator", "keyword" } }, - { { "([%w_][%w_]+)%.([%w_][%w%d_]*)%s*(=)%s*%b()%s*(=>)" }, - { "normal", "keyword2", "function", "operator", "operator" } }, - { { "([%w_][%w_]+)%.([%w_][%w%d_]*)%s*(=)%s*(async)%s*%b()%s*(=>)" }, - { "normal", "keyword2", "function", "operator", "function", "operator" } }, + { { "([%w_][%w_]+)%.([%w_][%w%d_]*)%s*(=)%s*%f[(]" }, + { "normal", "keyword2", "function", "operator" } }, + { { "([%w_][%w_]+)%.([%w_][%w%d_]*)%s*(=)%s*(async)%s*%f[(]" }, + { "normal", "keyword2", "function", "operator", "function" } }, { { "[%a_][%w_]*%s*%f[(]" }, "function" }, { { "[%a_][%w_]*" }, "symbol" }, }, @@ -1021,9 +1021,10 @@ SyntaxDefinitionManager::SyntaxDefinitionManager() { add( { "Config File", { "%.ini$", "%.conf$", "%.desktop$", "%.service$", "%.cfg$", "%.env$", "%.properties$", "Doxyfile" }, - { { { "^#.-\n" }, "comment" }, + { { { "%s?#%x%x%x%x%x%x%x%x" }, "string" }, + { { "%s?#%x%x%x%x%x%x" }, "string" }, + { { "^#.-\n" }, "comment" }, { { "%s#.-\n" }, "comment" }, - { { "%s?#%x+" }, "string" }, { { "[%a_][%w-+_%s%p]-%f[=]" }, "keyword" }, { { "\"", "\"", "\\" }, "string" }, { { "'", "'", "\\" }, "string" }, diff --git a/src/eepp/ui/tools/uicodeeditorsplitter.cpp b/src/eepp/ui/tools/uicodeeditorsplitter.cpp index a04830c70..c290d58c7 100644 --- a/src/eepp/ui/tools/uicodeeditorsplitter.cpp +++ b/src/eepp/ui/tools/uicodeeditorsplitter.cpp @@ -263,9 +263,11 @@ UICodeEditor* UICodeEditorSplitter::createCodeEditor() { "switch-to-next-split", "switch-to-previous-colorscheme", "switch-to-next-colorscheme" } ); - if ( nullptr == mCurEditor ) + if ( nullptr == mCurEditor ) { + mAboutToAddEditor = editor; setCurrentEditor( editor ); - + mAboutToAddEditor = nullptr; + } mClient->onCodeEditorCreated( editor, doc ); return editor; @@ -382,6 +384,7 @@ void UICodeEditorSplitter::loadAsyncFileFromPathInNewTab( } void UICodeEditorSplitter::setCurrentEditor( UICodeEditor* editor ) { + eeASSERT( checkEditorExists( editor ) ); bool isNew = mCurEditor != editor; mCurEditor = editor; if ( isNew ) @@ -392,9 +395,11 @@ void UICodeEditorSplitter::setCurrentEditor( UICodeEditor* editor ) { std::pair UICodeEditorSplitter::createCodeEditorInTabWidget( UITabWidget* tabWidget ) { + eeASSERT( curEditorExists() ); if ( nullptr == tabWidget ) return std::make_pair( (UITab*)nullptr, (UICodeEditor*)nullptr ); UICodeEditor* editor = createCodeEditor(); + mAboutToAddEditor = editor; editor->addEventListener( Event::OnDocumentChanged, [&]( const Event* event ) { mClient->onDocumentStateChanged( event->getNode()->asType(), event->getNode()->asType()->getDocument() ); @@ -403,6 +408,8 @@ UICodeEditorSplitter::createCodeEditorInTabWidget( UITabWidget* tabWidget ) { editor->setData( (UintPtr)tab ); DocEvent docEvent( editor, &editor->getDocument(), Event::OnEditorTabReady ); editor->sendEvent( static_cast( &docEvent ) ); + mAboutToAddEditor = nullptr; + mFirstCodeEditor = false; return std::make_pair( tab, editor ); } @@ -418,6 +425,7 @@ void UICodeEditorSplitter::removeUnusedTab( UITabWidget* tabWidget ) { } UITabWidget* UICodeEditorSplitter::createEditorWithTabWidget( Node* parent, bool openCurEditor ) { + eeASSERT( curEditorExists() ); if ( nullptr == mBaseLayout ) mBaseLayout = parent; UICodeEditor* prevCurEditor = mCurEditor; @@ -441,10 +449,12 @@ UITabWidget* UICodeEditorSplitter::createEditorWithTabWidget( Node* parent, bool onTabClosed( static_cast( event ) ); } ); auto editorData = createCodeEditorInTabWidget( tabWidget ); + mAboutToAddEditor = editorData.second; // Open same document in the new split if ( openCurEditor && prevCurEditor && prevCurEditor != editorData.second && !prevCurEditor->getDocument().isEmpty() ) editorData.second->setDocument( prevCurEditor->getDocumentRef() ); + mAboutToAddEditor = nullptr; mTabWidgets.push_back( tabWidget ); return tabWidget; } @@ -484,25 +494,26 @@ void UICodeEditorSplitter::applyColorScheme( const SyntaxColorScheme& colorSchem mClient->onColorSchemeChanged( mCurrentColorScheme ); } -void UICodeEditorSplitter::forEachEditor( std::function run ) { +void UICodeEditorSplitter::forEachEditor( std::function run ) const { for ( auto tabWidget : mTabWidgets ) for ( size_t i = 0; i < tabWidget->getTabCount(); i++ ) run( tabWidget->getTab( i )->getOwnedWidget()->asType() ); } -void UICodeEditorSplitter::forEachDoc( std::function run ) { +void UICodeEditorSplitter::forEachDoc( std::function run ) const { std::unordered_set docs; forEachEditor( [&]( UICodeEditor* editor ) { docs.insert( editor->getDocumentRef().get() ); } ); for ( auto doc : docs ) run( *doc ); } -void UICodeEditorSplitter::forEachTabWidget( std::function run ) { +void UICodeEditorSplitter::forEachTabWidget( std::function run ) const { for ( auto widget : mTabWidgets ) run( widget ); } -void UICodeEditorSplitter::forEachEditorStoppable( std::function run ) { +void UICodeEditorSplitter::forEachEditorStoppable( + std::function run ) const { for ( auto tabWidget : mTabWidgets ) { for ( size_t i = 0; i < tabWidget->getTabCount(); i++ ) { if ( run( tabWidget->getTab( i )->getOwnedWidget()->asType() ) ) { @@ -512,7 +523,7 @@ void UICodeEditorSplitter::forEachEditorStoppable( std::function run ) { +void UICodeEditorSplitter::forEachDocStoppable( std::function run ) const { for ( auto tabWidget : mTabWidgets ) { for ( size_t i = 0; i < tabWidget->getTabCount(); i++ ) { if ( run( *tabWidget->getTab( i ) @@ -741,19 +752,40 @@ void UICodeEditorSplitter::focusSomeEditor( Node* searchFrom ) { UICodeEditor* editor = searchFrom ? searchFrom->findByType( UI_TYPE_CODEEDITOR ) : mUISceneNode->getRoot()->findByType( UI_TYPE_CODEEDITOR ); + if ( searchFrom && !editor ) editor = mUISceneNode->getRoot()->findByType( UI_TYPE_CODEEDITOR ); - if ( editor && tabWidgetFromEditor( editor ) && !tabWidgetFromEditor( editor )->isClosing() ) { + + if ( editor && tabWidgetFromEditor( editor ) && !tabWidgetFromEditor( editor )->isClosing() && + tabWidgetFromEditor( editor )->getTabCount() > 1 ) { UITabWidget* tabW = tabWidgetFromEditor( editor ); - if ( tabW && tabW->getTabCount() > 0 ) { - tabW->setTabSelected( tabW->getTabSelected() ); - } - } else { - UITabWidget* tabW = mUISceneNode->getRoot()->findByType( UI_TYPE_TABWIDGET ); - if ( tabW && tabW->getTabCount() > 0 ) { + if ( tabW && tabW->getTabSelected()->getOwnedWidget() != editor ) { tabW->setTabSelected( tabW->getTabSelected() ); + return; + } else if ( tabW ) { + for ( size_t i = 0; i < tabW->getTabCount(); ++i ) { + if ( tabW->getTab( i )->getOwnedWidget() != editor ) { + tabW->setTabSelected( i ); + return; + } + } } } + + for ( auto widget : mTabWidgets ) { + if ( !widget->isClosing() && widget->getTabCount() > 0 ) { + if ( widget->getTabSelected() != nullptr ) { + widget->setTabSelected( widget->getTabSelected() ); + } else { + widget->setTabSelected( (Uint32)0 ); + } + return; + } + } + + UITabWidget* tabW = mUISceneNode->getRoot()->findByType( UI_TYPE_TABWIDGET ); + if ( tabW && tabW->getTabCount() > 0 ) + tabW->setTabSelected( tabW->getTabSelected() ); } void UICodeEditorSplitter::closeTabWidgets( UISplitter* splitter ) { @@ -772,7 +804,32 @@ void UICodeEditorSplitter::closeTabWidgets( UISplitter* splitter ) { } } +bool UICodeEditorSplitter::checkEditorExists( UICodeEditor* checkEditor ) const { + bool found = false; + forEachEditorStoppable( [&found, checkEditor]( UICodeEditor* editor ) { + if ( editor == checkEditor ) { + found = true; + return true; + } + return false; + } ); + return found || checkEditor == nullptr || mAboutToAddEditor == checkEditor || mFirstCodeEditor; +} + +bool UICodeEditorSplitter::curEditorExists() const { + bool found = false; + forEachEditorStoppable( [&]( UICodeEditor* editor ) { + if ( editor == mCurEditor ) { + found = true; + return true; + } + return false; + } ); + return found || mCurEditor == nullptr || mAboutToAddEditor == mCurEditor || mFirstCodeEditor; +} + UICodeEditor* UICodeEditorSplitter::getCurEditor() const { + eeASSERT( curEditorExists() ); return mCurEditor; } @@ -798,7 +855,7 @@ void UICodeEditorSplitter::closeSplitter( UISplitter* splitter ) { } void UICodeEditorSplitter::onTabClosed( const TabEvent* tabEvent ) { - UICodeEditor* editor = mCurEditor; + UICodeEditor* editor = tabEvent->getTab()->getOwnedWidget()->asType(); UITabWidget* tabWidget = tabEvent->getTab()->getTabWidget(); if ( tabWidget->getTabCount() == 0 ) { UISplitter* splitter = splitterFromEditor( editor ); @@ -839,11 +896,13 @@ void UICodeEditorSplitter::onTabClosed( const TabEvent* tabEvent ) { addRemainingTabWidgets( remainingNode ); focusSomeEditor( nullptr ); } - if ( tabEvent->getTab()->getOwnedWidget() == mCurEditor ) - setCurrentEditor( nullptr ); + + eeASSERT( !mTabWidgets.empty() ); + eeASSERT( !( mTabWidgets.size() == 1 && mTabWidgets[0]->getTabCount() == 0 ) ); return; } } + mCurEditor = nullptr; auto d = createCodeEditorInTabWidget( tabWidget ); d.first->getTabWidget()->setTabSelected( d.first ); } else { @@ -852,7 +911,8 @@ void UICodeEditorSplitter::onTabClosed( const TabEvent* tabEvent ) { eemin( tabWidget->getTabCount() - 1, tabEvent->getTabIndex() ) ); } if ( tabEvent->getTab()->getOwnedWidget() == mCurEditor ) - setCurrentEditor( nullptr ); + focusSomeEditor( nullptr ); + eeASSERT( curEditorExists() ); } }}} // namespace EE::UI::Tools diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp index 97cdac9a8..42ee49599 100644 --- a/src/eepp/ui/uicodeeditor.cpp +++ b/src/eepp/ui/uicodeeditor.cpp @@ -1205,6 +1205,10 @@ Uint32 UICodeEditor::onMouseOver( const Vector2i& position, const Uint32& flags } Uint32 UICodeEditor::onMouseLeave( const Vector2i& position, const Uint32& flags ) { + if ( mMinimapHover ) { + mMinimapHover = false; + invalidateDraw(); + } for ( auto& plugin : mPlugins ) if ( plugin->onMouseLeave( this, position, flags ) ) return UIWidget::onMouseLeave( position, flags ); diff --git a/src/examples/vbo_fbo_batch/vbo_fbo_batch.cpp b/src/examples/vbo_fbo_batch/vbo_fbo_batch.cpp index 489ddd97c..a255fcc72 100644 --- a/src/examples/vbo_fbo_batch/vbo_fbo_batch.cpp +++ b/src/examples/vbo_fbo_batch/vbo_fbo_batch.cpp @@ -125,7 +125,7 @@ EE_MAIN_FUNC int main( int, char*[] ) { // Create the Vertex Buffer, the vertex buffer stores the vertex data in the GPU, making the // rendering much faster In the case that Vertex Buffer Object is not supported by the GPU, - // it will fallback to a inmediate-mode vertex buffer + // it will fallback to a immediate-mode vertex buffer VBO = VertexBuffer::New( VERTEX_FLAGS_PRIMITIVE, PRIMITIVE_TRIANGLE_FAN ); VBO2 = VertexBuffer::New( VERTEX_FLAGS_PRIMITIVE, PRIMITIVE_TRIANGLE_FAN ); diff --git a/src/tools/ecode/docsearchcontroller.cpp b/src/tools/ecode/docsearchcontroller.cpp index 5fa7b8956..5872bf4e1 100644 --- a/src/tools/ecode/docsearchcontroller.cpp +++ b/src/tools/ecode/docsearchcontroller.cpp @@ -165,6 +165,9 @@ void DocSearchController::showFindView() { mSearchState.wholeWord = mSearchBarLayout->find( "whole_word" )->isChecked(); mSearchState.escapeSequences = mSearchBarLayout->find( "escape_sequence" )->isChecked(); + mSearchState.type = mSearchBarLayout->find( "lua_pattern" )->isChecked() + ? TextDocument::FindReplaceType::LuaPattern + : TextDocument::FindReplaceType::Normal; mSearchBarLayout->setEnabled( true )->setVisible( true ); UITextInput* findInput = mSearchBarLayout->find( "search_find" ); diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index cf3949481..6887b1b6c 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -1725,10 +1725,15 @@ std::vector App::getUnlockedCommands() { void App::closeEditors() { mConfig.saveProject( mCurrentProject, mEditorSplitter, mConfigPath, mProjectDocConfig ); std::vector editors = mEditorSplitter->getAllEditors(); - for ( auto editor : editors ) { + while ( !editors.empty() ) { + UICodeEditor* editor = editors[0]; UITabWidget* tabWidget = mEditorSplitter->tabWidgetFromEditor( editor ); tabWidget->removeTab( (UITab*)editor->getData(), true, true ); - } + editors = mEditorSplitter->getAllEditors(); + if ( editors.size() == 1 && editors[0]->getDocument().isEmpty() ) + break; + }; + mCurrentProject = ""; mDirTree = nullptr; if ( mFileSystemListener ) @@ -1736,7 +1741,9 @@ void App::closeEditors() { mProjectDocConfig = ProjectDocumentConfig( mConfig.doc ); updateProjectSettingsMenu(); - mEditorSplitter->createCodeEditorInTabWidget( mEditorSplitter->getTabWidgets()[0] ); + if ( !mEditorSplitter->getTabWidgets().empty() && + mEditorSplitter->getTabWidgets()[0]->getTabCount() == 0 ) + mEditorSplitter->createCodeEditorInTabWidget( mEditorSplitter->getTabWidgets()[0] ); } void App::closeFolder() {