diff --git a/include/eepp/math/rect.hpp b/include/eepp/math/rect.hpp index 67a0bbfed..bd69eef8c 100644 --- a/include/eepp/math/rect.hpp +++ b/include/eepp/math/rect.hpp @@ -18,11 +18,11 @@ template class tRECT { tRECT copy() const; - bool intersect( const tRECT& rect ); + bool intersect( const tRECT& rect ) const; - bool contains( const tRECT& rect ); + bool contains( const tRECT& rect ) const; - bool contains( const Vector2& Vect ); + bool contains( const Vector2& Vect ) const; void expand( const tRECT& rect ); @@ -209,15 +209,15 @@ tRECT::tRECT( const Vector2& Pos, const tSize& Size ) : template tRECT::tRECT() : Left( 0 ), Right( 0 ), Top( 0 ), Bottom( 0 ) {} -template bool tRECT::contains( const tRECT& rect ) { +template bool tRECT::contains( const tRECT& rect ) const { return ( Left <= rect.Left && Right >= rect.Right && Top <= rect.Top && Bottom >= rect.Bottom ); } -template bool tRECT::intersect( const tRECT& rect ) { +template bool tRECT::intersect( const tRECT& rect ) const { return !( Left > rect.Right || Right < rect.Left || Top > rect.Bottom || Bottom < rect.Top ); } -template bool tRECT::contains( const Vector2& Vect ) { +template bool tRECT::contains( const Vector2& Vect ) const { return ( Left <= Vect.x && Right >= Vect.x && Top <= Vect.y && Bottom >= Vect.y ); } diff --git a/include/eepp/scene/node.hpp b/include/eepp/scene/node.hpp index 6960d6508..b6eac49be 100644 --- a/include/eepp/scene/node.hpp +++ b/include/eepp/scene/node.hpp @@ -194,6 +194,8 @@ class EE_API Node : public Transformable { void removeEventListener( const Uint32& callbackId ); + void clearEventListener(); + Node* getFirstChild() const; Node* getLastChild() const; diff --git a/src/eepp/scene/node.cpp b/src/eepp/scene/node.cpp index 40386a64a..41763d8ff 100644 --- a/src/eepp/scene/node.cpp +++ b/src/eepp/scene/node.cpp @@ -1104,6 +1104,10 @@ void Node::removeEventListener( const Uint32& callbackId ) { } } +void Node::clearEventListener() { + mEvents.clear(); +} + void Node::sendEvent( const Event* event ) { if ( 0 != mEvents.count( event->getType() ) ) { std::map eventMap = mEvents[event->getType()]; diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp index 455e717a4..2952c7a54 100644 --- a/src/eepp/ui/uicodeeditor.cpp +++ b/src/eepp/ui/uicodeeditor.cpp @@ -82,6 +82,7 @@ const std::map UICodeEditor::getDefaultKeybi {{KEY_C, KEYMOD_CTRL}, "copy"}, {{KEY_X, KEYMOD_CTRL}, "cut"}, {{KEY_V, KEYMOD_CTRL}, "paste"}, + {{KEY_INSERT, KEYMOD_SHIFT}, "paste"}, {{KEY_A, KEYMOD_CTRL}, "select-all"}, {{KEY_PLUS, KEYMOD_CTRL}, "font-size-grow"}, {{KEY_KP_PLUS, KEYMOD_CTRL}, "font-size-grow"}, diff --git a/src/eepp/ui/uidropdownlist.cpp b/src/eepp/ui/uidropdownlist.cpp index dcac7b1da..656e85c6b 100644 --- a/src/eepp/ui/uidropdownlist.cpp +++ b/src/eepp/ui/uidropdownlist.cpp @@ -132,29 +132,6 @@ void UIDropDownList::showList() { return; if ( !mListBox->isVisible() ) { - if ( !mStyleConfig.PopUpToRoot ) - mListBox->setParent( getWindowContainer() ); - else - mListBox->setParent( getUISceneNode()->getRoot() ); - - mListBox->toFront(); - - Vector2f Pos( mDpPos.x, mDpPos.y + getSize().getHeight() ); - - if ( mStyleConfig.PopUpToRoot ) { - getParent()->nodeToWorld( Pos ); - Pos = PixelDensity::pxToDp( Pos ); - } else { - Node* ParentLoop = getParent(); - Node* rp = getWindowContainer(); - while ( rp != ParentLoop ) { - Pos += ParentLoop->getPosition(); - ParentLoop = ParentLoop->getParent(); - } - } - - mListBox->setPosition( Pos ); - if ( mListBox->getCount() ) { Rectf tPadding = mListBox->getContainerPadding(); @@ -174,6 +151,36 @@ void UIDropDownList::showList() { mListBox->getVerticalScrollBar()->setValue( sliderValue ); + if ( !mStyleConfig.PopUpToRoot ) + mListBox->setParent( getWindowContainer() ); + else + mListBox->setParent( getUISceneNode()->getRoot() ); + + mListBox->toFront(); + + Vector2f pos( mDpPos.x, mDpPos.y + getSize().getHeight() ); + Vector2f posCpy( pos ); + nodeToWorld( posCpy ); + + if ( !getUISceneNode()->getWorldBounds().contains( + Rectf( posCpy, mListBox->getSize() ) ) ) { + pos = Vector2f( mDpPos.x, mDpPos.y - mListBox->getSize().getHeight() ); + } + + if ( mStyleConfig.PopUpToRoot ) { + getParent()->nodeToWorld( pos ); + pos = PixelDensity::pxToDp( pos ); + } else { + Node* parentNode = getParent(); + Node* rp = getWindowContainer(); + while ( rp != parentNode ) { + pos += parentNode->getPosition(); + parentNode = parentNode->getParent(); + } + } + + mListBox->setPosition( pos ); + show(); mListBox->setFocus(); diff --git a/src/eepp/ui/uifiledialog.cpp b/src/eepp/ui/uifiledialog.cpp index 6d63ccc95..0ca78c31f 100644 --- a/src/eepp/ui/uifiledialog.cpp +++ b/src/eepp/ui/uifiledialog.cpp @@ -242,7 +242,7 @@ void UIFileDialog::refreshFolder() { FileSystemModel::DisplayConfig( getSortAlphabetically(), getFoldersFirst(), !getShowHidden(), patterns ) ) ); - mList->setColumnsVisible( {FileSystemModel::Name} ); + mList->setColumnsVisible( { FileSystemModel::Name } ); mList->setHeadersVisible( false ); updateClickStep(); @@ -367,12 +367,15 @@ void UIFileDialog::save() { } void UIFileDialog::open() { - if ( mList->getSelection().isEmpty() ) + if ( mList->getSelection().isEmpty() && + !( getAllowFolderSelect() && FileSystem::isDirectory( getFullPath() ) ) ) return; - auto* node = (FileSystemModel::Node*)mList->getSelection().first().data(); + auto* node = !mList->getSelection().isEmpty() + ? (FileSystemModel::Node*)mList->getSelection().first().data() + : nullptr; - if ( "" != node->getName() || getAllowFolderSelect() ) { + if ( ( node && "" != node->getName() ) || getAllowFolderSelect() ) { if ( !getAllowFolderSelect() ) { if ( FileSystem::isDirectory( getFullPath() ) ) return; diff --git a/src/eepp/ui/uilistboxitem.cpp b/src/eepp/ui/uilistboxitem.cpp index 1458e6ffc..ac1253b5e 100644 --- a/src/eepp/ui/uilistboxitem.cpp +++ b/src/eepp/ui/uilistboxitem.cpp @@ -64,9 +64,14 @@ Uint32 UIListBoxItem::onMouseUp( const Vector2i& Pos, const Uint32& Flags ) { Uint32 UIListBoxItem::onMouseClick( const Vector2i& Pos, const Uint32& Flags ) { if ( Flags & EE_BUTTONS_LRM ) { - getParent()->getParent()->asType()->itemClicked( this ); + UIListBox* LBParent = getParent()->getParent()->asType(); + + LBParent->itemClicked( this ); select(); + + if ( !LBParent->isMultiSelect() ) + setFocus(); } return UITextView::onMouseClick( Pos, Flags ); @@ -107,8 +112,6 @@ void UIListBoxItem::select() { if ( !wasSelected ) { LBParent->onSelected(); } - - setFocus(); } } diff --git a/src/tools/codeeditor/codeeditor.cpp b/src/tools/codeeditor/codeeditor.cpp index d5f84c88e..2ea602dde 100644 --- a/src/tools/codeeditor/codeeditor.cpp +++ b/src/tools/codeeditor/codeeditor.cpp @@ -1,6 +1,5 @@ #include "codeeditor.hpp" #include "autocompletemodule.hpp" -#include "projectsearch.hpp" #include #include @@ -674,6 +673,15 @@ void App::hideGlobalSearchBar() { loader->setVisible( false ); } +void App::updateGlobalSearchBarResults( const std::string& search, + std::shared_ptr model ) { + updateGlobalSearchBar(); + mGlobalSearchTree->setSearchStr( search ); + mGlobalSearchTree->setModel( model ); + if ( mGlobalSearchTree->getModel()->rowCount() < 50 ) + mGlobalSearchTree->expandAll(); +} + void App::initGlobalSearchBar() { auto addClickListener = [&]( UIWidget* widget, std::string cmd ) { widget->addEventListener( Event::MouseClick, [this, cmd]( const Event* event ) { @@ -682,10 +690,12 @@ void App::initGlobalSearchBar() { mGlobalSearchBarLayout->execute( cmd ); } ); }; - UIPushButton* searchButton = mGlobalSearchBarLayout->find( "search" ); + UIPushButton* searchButton = mGlobalSearchBarLayout->find( "global_search" ); UICheckBox* caseSensitiveChk = mGlobalSearchBarLayout->find( "case_sensitive" ); UIWidget* searchBarClose = mGlobalSearchBarLayout->find( "global_searchbar_close" ); mGlobalSearchInput = mGlobalSearchBarLayout->find( "global_search_find" ); + mGlobalSearchHistoryList = + mGlobalSearchBarLayout->find( "global_search_history" ); mGlobalSearchBarLayout->addCommand( "search-in-files", [&, caseSensitiveChk] { if ( mDirTree && mDirTree->getFilesCount() > 0 && !mGlobalSearchInput->getText().empty() ) { UILoader* loader = UILoader::New(); @@ -708,11 +718,35 @@ void App::initGlobalSearchBar() { clock->getElapsedTime().asMilliseconds() ); eeDelete( clock ); mUISceneNode->runOnMainThread( [&, loader, res, search] { - updateGlobalSearchBar(); - mGlobalSearchTree->setSearchStr( search ); - mGlobalSearchTree->setModel( ProjectSearch::asModel( res ) ); - if ( mGlobalSearchTree->getModel()->rowCount() < 50 ) - mGlobalSearchTree->expandAll(); + auto model = ProjectSearch::asModel( res ); + mGlobalSearchHistory.push_back( std::make_pair( search, model ) ); + if ( mGlobalSearchHistory.size() > 10 ) + mGlobalSearchHistory.pop_front(); + + std::vector items; + for ( auto item = mGlobalSearchHistory.rbegin(); + item != mGlobalSearchHistory.rend(); item++ ) { + items.push_back( item->first ); + } + + auto listBox = mGlobalSearchHistoryList->getListBox(); + listBox->clear(); + listBox->addListBoxItems( items ); + if ( mGlobalSearchHistoryOnItemSelectedCb ) + mGlobalSearchHistoryList->removeEventListener( + mGlobalSearchHistoryOnItemSelectedCb ); + listBox->setSelected( 0 ); + mGlobalSearchHistoryOnItemSelectedCb = + mGlobalSearchHistoryList->addEventListener( + Event::OnItemSelected, [&]( const Event* ) { + auto idx = mGlobalSearchHistoryList->getListBox() + ->getItemSelectedIndex(); + auto idxItem = mGlobalSearchHistory.at( + mGlobalSearchHistory.size() - 1 - idx ); + updateGlobalSearchBarResults( idxItem.first, idxItem.second ); + } ); + + updateGlobalSearchBarResults( search, model ); loader->setVisible( false ); loader->close(); } ); @@ -2008,6 +2042,9 @@ void App::initProjectTreeView( const std::string& path ) { } void App::loadFolder( const std::string& path ) { + if ( !mCurrentProject.empty() ) + closeEditors(); + std::string rpath( FileSystem::getRealPath( path ) ); mCurrentProject = rpath; loadDirTree( rpath ); @@ -2188,6 +2225,10 @@ void App::init( const std::string& file, const Float& pidelDensity ) { #search_tree treeview::cell { font-family: monospace; } + #global_search_history { + padding-top: 0dp; + padding-bottom: 0dp; + } @@ -2239,7 +2280,9 @@ void App::init( const std::string& file, const Float& pidelDensity ) { - + + + diff --git a/src/tools/codeeditor/codeeditor.hpp b/src/tools/codeeditor/codeeditor.hpp index e4af73758..cfb378fd5 100644 --- a/src/tools/codeeditor/codeeditor.hpp +++ b/src/tools/codeeditor/codeeditor.hpp @@ -3,6 +3,7 @@ #include "appconfig.hpp" #include "projectdirectorytree.hpp" +#include "projectsearch.hpp" #include "uitreeviewglobalsearch.hpp" #include @@ -184,7 +185,11 @@ class App : public UICodeEditorSplitter::Client { UITableView* mLocateTable{ nullptr }; UITextInput* mLocateInput{ nullptr }; UITreeViewGlobalSearch* mGlobalSearchTree{ nullptr }; - UITextInput* mGlobalSearchInput; + UITextInput* mGlobalSearchInput{ nullptr }; + UIDropDownList* mGlobalSearchHistoryList{ nullptr }; + Uint32 mGlobalSearchHistoryOnItemSelectedCb{ 0 }; + std::deque>> + mGlobalSearchHistory; size_t mMenuIconSize; bool mDirTreeReady{ false }; std::unordered_set mTmpDocs; @@ -310,6 +315,9 @@ class App : public UICodeEditorSplitter::Client { void closeFolder(); void closeEditors(); + + void updateGlobalSearchBarResults( const std::string& search, + std::shared_ptr model ); }; #endif // EE_TOOLS_CODEEDITOR_HPP