diff --git a/include/eepp/core/string.hpp b/include/eepp/core/string.hpp index f28fa5593..03583baec 100644 --- a/include/eepp/core/string.hpp +++ b/include/eepp/core/string.hpp @@ -838,6 +838,12 @@ class EE_API String { const StringBaseType& back() const; + String& trim( char character = ' ' ); + + String& lTrim( char character = ' ' ); + + String& rTrim( char character = ' ' ); + private: friend EE_API bool operator==( const String& left, const String& right ); friend EE_API bool operator<( const String& left, const String& right ); diff --git a/include/eepp/ui/keyboardshortcut.hpp b/include/eepp/ui/keyboardshortcut.hpp index 3eb746537..a352ee375 100644 --- a/include/eepp/ui/keyboardshortcut.hpp +++ b/include/eepp/ui/keyboardshortcut.hpp @@ -73,6 +73,8 @@ class EE_API KeyBindings { const ShortcutMap& getShortcutMap() const; + const std::map getKeybindings() const; + std::string getShortcutString( Shortcut shortcut ) const; protected: diff --git a/include/eepp/ui/models/itemlistmodel.hpp b/include/eepp/ui/models/itemlistmodel.hpp index e2c5dd1f0..edb54ffe3 100644 --- a/include/eepp/ui/models/itemlistmodel.hpp +++ b/include/eepp/ui/models/itemlistmodel.hpp @@ -9,10 +9,12 @@ namespace EE { namespace UI { namespace Models { template class ItemListModel final : public Model { public: - static std::shared_ptr create( std::vector& data ) { - return std::make_shared( *new ItemListModel( data ) ); + static std::shared_ptr create( const std::vector& data ) { + return std::make_shared>( data ); } + explicit ItemListModel( const std::vector& data ) : mData( data ) {} + virtual ~ItemListModel() {} virtual size_t rowCount( const ModelIndex& ) const { return mData.size(); } @@ -30,17 +32,17 @@ template class ItemListModel final : public Model { virtual void update() { onModelUpdate(); } private: - explicit ItemListModel( std::vector& data ) : mData( data ) {} - - std::vector& mData; + const std::vector& mData; }; template class ItemPairListModel final : public Model { public: - static std::shared_ptr create( std::vector>& data ) { - return std::make_shared( *new ItemPairListModel( data ) ); + static std::shared_ptr create( const std::vector>& data ) { + return std::make_shared>( data ); } + explicit ItemPairListModel( const std::vector>& data ) : mData( data ) {} + virtual ~ItemPairListModel() {} virtual size_t rowCount( const ModelIndex& ) const { return mData.size(); } @@ -73,12 +75,132 @@ template class ItemPairListModel final : public Model { virtual void update() { onModelUpdate(); } private: - explicit ItemPairListModel( std::vector& data ) : mData( data ) {} - - std::vector>& mData; + const std::vector>& mData; std::vector mColumnNames{ "Title", "Description" }; }; +template class ItemListOwnerModel final : public Model { + public: + static std::shared_ptr create( const std::vector& data ) { + return std::make_shared>( data ); + } + + explicit ItemListOwnerModel( const std::vector& data ) : mData( data ) {} + + virtual ~ItemListOwnerModel() {} + + virtual size_t rowCount( const ModelIndex& ) const { return mData.size(); } + + virtual size_t columnCount( const ModelIndex& ) const { return 1; } + + virtual std::string columnName( const size_t& ) const { return "Data"; } + + virtual Variant data( const ModelIndex& index, ModelRole role = ModelRole::Display ) const { + if ( role == ModelRole::Display ) + return Variant( mData[index.row()] ); + return {}; + } + + virtual void update() { onModelUpdate(); } + + private: + std::vector mData; +}; + +template class ItemPairListOwnerModel final : public Model { + public: + static std::shared_ptr + create( const std::vector>& data ) { + return std::make_shared>( data ); + } + + explicit ItemPairListOwnerModel( const std::vector>& data ) : mData( data ) {} + + virtual ~ItemPairListOwnerModel() {} + + virtual size_t rowCount( const ModelIndex& ) const { return mData.size(); } + + virtual size_t columnCount( const ModelIndex& ) const { return 2; } + + virtual std::string columnName( const size_t& index ) const { + eeASSERT( index < 2 ); + return mColumnNames[index]; + } + + virtual void setColumnName( const size_t& index, const std::string& name ) { + eeASSERT( index < 2 ); + mColumnNames[index] = name; + } + + virtual Variant data( const ModelIndex& index, ModelRole role = ModelRole::Display ) const { + if ( role == ModelRole::Display ) { + switch ( index.column() ) { + case 0: + return Variant( mData[index.row()].first ); + case 1: + default: + return Variant( mData[index.row()].second ); + } + } + return {}; + } + + virtual void update() { onModelUpdate(); } + + private: + std::vector> mData; + std::vector mColumnNames{ "Title", "Description" }; +}; + +template class ItemVectorListOwnerModel final : public Model { + public: + static std::shared_ptr + create( const size_t& columnCount, const std::vector>& data ) { + return std::make_shared>( columnCount, data ); + } + + explicit ItemVectorListOwnerModel( const size_t& columnCount, + const std::vector>& data ) : + mData( data ) { + mColumnNames.resize( columnCount ); + } + + virtual ~ItemVectorListOwnerModel() {} + + virtual size_t rowCount( const ModelIndex& ) const { return mData.size(); } + + virtual size_t columnCount( const ModelIndex& ) const { return mColumnNames.size(); } + + virtual std::string columnName( const size_t& index ) const { + eeASSERT( index < mColumnNames.size() ); + return mColumnNames[index]; + } + + virtual void setColumnName( const size_t& index, const std::string& name ) { + eeASSERT( index < mColumnNames.size() ); + mColumnNames[index] = name; + } + + virtual Variant data( const ModelIndex& index, ModelRole role = ModelRole::Display ) const { + eeASSERT( index.row() < (Int64)mData.size() ); + eeASSERT( index.column() < (Int64)mData[index.row()].size() ); + if ( index.row() >= (Int64)mData.size() || + index.column() >= (Int64)mData[index.row()].size() ) + return {}; + + if ( role == ModelRole::Display ) + return Variant( mData[index.row()][index.column()] ); + + return {}; + } + + virtual void update() { onModelUpdate(); } + + private: + std::vector> mData; + std::vector mColumnNames; +}; + }}} // namespace EE::UI::Models #endif // EE_UI_MODELS_ITEMLISTMODEL_HPP diff --git a/include/eepp/ui/widgetcommandexecuter.hpp b/include/eepp/ui/widgetcommandexecuter.hpp index 2acba6f69..50701be56 100644 --- a/include/eepp/ui/widgetcommandexecuter.hpp +++ b/include/eepp/ui/widgetcommandexecuter.hpp @@ -16,7 +16,15 @@ class EE_API WidgetCommandExecuter { WidgetCommandExecuter( const KeyBindings& keybindings ) : mKeyBindings( keybindings ) {} - void setCommand( const std::string& name, const CommandCallback& cb ) { mCommands[name] = cb; } + void setCommand( const std::string& name, const CommandCallback& cb ) { + auto cmdIt = mCommands.find( name ); + if ( cmdIt == mCommands.end() ) { + mCommands[name] = cb; + mCommandList.emplace_back( name ); + } else { + cmdIt->second = cb; + } + } bool hasCommand( const std::string& name ) const { return mCommands.find( name ) != mCommands.end(); @@ -32,9 +40,12 @@ class EE_API WidgetCommandExecuter { KeyBindings& getKeyBindings() { return mKeyBindings; } + const std::vector& getCommandList() const { return mCommandList; } + protected: KeyBindings mKeyBindings; std::unordered_map> mCommands; + std::vector mCommandList; Uint32 onKeyDown( const KeyEvent& event ) { std::string cmd = diff --git a/premake4.lua b/premake4.lua index bc084677c..1bca4e54c 100644 --- a/premake4.lua +++ b/premake4.lua @@ -560,7 +560,7 @@ function build_link_configuration( package_name, use_ee_icon ) set_ios_config() set_xcode_config() build_arch_configuration() - + configuration "debug" defines { "DEBUG", "EE_DEBUG", "EE_MEMORY_MANAGER" } flags { "Symbols" } diff --git a/projects/linux/ee.files b/projects/linux/ee.files index e03b188d4..171d79f03 100644 --- a/projects/linux/ee.files +++ b/projects/linux/ee.files @@ -1145,6 +1145,8 @@ ../../src/thirdparty/efsw/src/test/efsw-test.cpp ../../src/tools/ecode/appconfig.cpp ../../src/tools/ecode/appconfig.hpp +../../src/tools/ecode/commandpalette.cpp +../../src/tools/ecode/commandpalette.hpp ../../src/tools/ecode/ecode.cpp ../../src/tools/ecode/ecode.hpp ../../src/tools/ecode/docsearchcontroller.cpp diff --git a/src/eepp/core/string.cpp b/src/eepp/core/string.cpp index 9aad8ea89..0c7b21784 100644 --- a/src/eepp/core/string.cpp +++ b/src/eepp/core/string.cpp @@ -723,6 +723,21 @@ const String::StringBaseType& String::back() const { return mString.back(); } +String& String::trim( char character ) { + trimInPlace( *this, character ); + return *this; +} + +String& String::lTrim( char character ) { + *this = lTrim( *this, character ); + return *this; +} + +String& String::rTrim( char character ) { + *this = rTrim( *this, character ); + return *this; +} + void String::replace( std::string& target, const std::string& that, const std::string& with ) { std::size_t start_pos = target.find( that ); if ( start_pos == std::string::npos ) diff --git a/src/eepp/ui/keyboardshortcut.cpp b/src/eepp/ui/keyboardshortcut.cpp index 3e5dc947c..228bf485d 100644 --- a/src/eepp/ui/keyboardshortcut.cpp +++ b/src/eepp/ui/keyboardshortcut.cpp @@ -159,6 +159,10 @@ const ShortcutMap& KeyBindings::getShortcutMap() const { return mShortcuts; } +const std::map KeyBindings::getKeybindings() const { + return mKeybindingsInvert; +} + std::string KeyBindings::getShortcutString( KeyBindings::Shortcut shortcut ) const { std::vector mods; std::string keyname( String::toLower( mInput->getKeyName( shortcut.key ) ) ); diff --git a/src/tools/ecode/commandpalette.cpp b/src/tools/ecode/commandpalette.cpp new file mode 100644 index 000000000..57d95f1b5 --- /dev/null +++ b/src/tools/ecode/commandpalette.cpp @@ -0,0 +1,68 @@ +#include "commandpalette.hpp" + +namespace ecode { + +std::vector> +CommandPalette::build( const std::vector& commandList, + const EE::UI::KeyBindings& keybindings ) { + std::vector> ret; + for ( const auto& cmd : commandList ) { + std::string cmdName( cmd ); + String::capitalizeInPlace( cmdName ); + String::replaceAll( cmdName, "-", " " ); + ret.push_back( { cmdName, keybindings.getCommandKeybindString( cmd ), cmd } ); + } + return ret; +} + +std::shared_ptr +CommandPalette::asModel( const std::vector& commandList, + const EE::UI::KeyBindings& keybindings ) { + return CommandPaletteModel::create( 3, build( commandList, keybindings ) ); +} + +CommandPalette::CommandPalette( const std::shared_ptr& pool ) : mPool( pool ) {} + +void CommandPalette::setCommandPalette( const std::vector& commandList, + const UI::KeyBindings& keybindings ) { + mCommandPalette = build( commandList, keybindings ); + mBaseModel = CommandPaletteModel::create( 3, mCommandPalette ); +} + +const std::vector>& CommandPalette::getCommandPalette() const { + return mCommandPalette; +} + +const std::shared_ptr& CommandPalette::getBaseModel() const { + return mBaseModel; +} + +std::shared_ptr CommandPalette::fuzzyMatch( const std::string& match, + const size_t& max ) const { + if ( mCommandPalette.empty() ) + return {}; + + Lock rl( mMatchingMutex ); + std::multimap> matchesMap; + std::vector> ret; + + for ( size_t i = 0; i < mCommandPalette.size(); i++ ) { + int matchName = String::fuzzyMatch( mCommandPalette[i][0], match ); + int matchKeybind = String::fuzzyMatch( mCommandPalette[i][1], match ); + matchesMap.insert( { std::max( matchName, matchKeybind ), i } ); + } + for ( auto& res : matchesMap ) { + if ( ret.size() < max ) { + ret.push_back( { mCommandPalette[res.second][0], mCommandPalette[res.second][1], + mCommandPalette[res.second][2] } ); + } + } + return CommandPaletteModel::create( 3, ret ); +} + +void CommandPalette::asyncFuzzyMatch( const std::string& match, const size_t& max, + MatchResultCb res ) const { + mPool->run( [&, match, max, res]() { res( fuzzyMatch( match, max ) ); } ); +} + +} // namespace ecode diff --git a/src/tools/ecode/commandpalette.hpp b/src/tools/ecode/commandpalette.hpp new file mode 100644 index 000000000..cbfbe393d --- /dev/null +++ b/src/tools/ecode/commandpalette.hpp @@ -0,0 +1,53 @@ +#ifndef ECODE_COMMANDPALETTE_HPP +#define ECODE_COMMANDPALETTE_HPP + +#include +#include +#include +#include +#include + +using namespace EE; +using namespace EE::UI::Models; +using namespace EE::System; + +namespace ecode { + +using CommandPaletteModel = ItemVectorListOwnerModel; + +class CommandPalette { + public: + CommandPalette( const std::shared_ptr& pool ); + + typedef std::function )> MatchResultCb; + + static std::vector> build( const std::vector& commandList, + const EE::UI::KeyBindings& keybindings ); + + static std::shared_ptr + asModel( const std::vector& commandList, const EE::UI::KeyBindings& keybindings ); + + void asyncFuzzyMatch( const std::string& match, const size_t& max, MatchResultCb res ) const; + + std::shared_ptr fuzzyMatch( const std::string& match, + const size_t& max ) const; + + void setCommandPalette( const std::vector& commandList, + const EE::UI::KeyBindings& keybindings ); + + const std::vector>& getCommandPalette() const; + + bool isSet() const { return !mCommandPalette.empty(); } + + const std::shared_ptr& getBaseModel() const; + + protected: + mutable Mutex mMatchingMutex; + std::shared_ptr mPool; + std::vector> mCommandPalette; + std::shared_ptr mBaseModel; +}; + +} // namespace ecode + +#endif // ECODE_COMMANDPALETTE_HPP diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index a5442c78d..8929dbce8 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -1377,6 +1377,7 @@ std::map App::getLocalKeybindings() { { { KEY_O, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "open-folder" }, { { KEY_F11, KEYMOD_NONE }, "debug-widget-tree-view" }, { { KEY_K, KeyMod::getDefaultModifier() }, "open-locatebar" }, + { { KEY_P, KeyMod::getDefaultModifier() }, "open-command-palette" }, { { KEY_F, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "open-global-search" }, { { KEY_L, KeyMod::getDefaultModifier() }, "go-to-line" }, { { KEY_M, KeyMod::getDefaultModifier() }, "menu-toggle" }, @@ -1398,6 +1399,7 @@ std::vector App::getUnlockedCommands() { "console-toggle", "close-app", "open-locatebar", + "open-command-palette", "open-global-search", "menu-toggle", "switch-side-panel", @@ -1887,7 +1889,7 @@ void App::loadDirTree( const std::string& path ) { eeDelete( clock ); mDirTreeReady = true; mUISceneNode->runOnMainThread( [&] { - mFileLocator->updateLocateTable(); + mFileLocator->updateFilesTable(); if ( mSplitter->curEditorExistsAndFocused() ) syncProjectTreeWithEditor( mSplitter->getCurEditor() ); } ); diff --git a/src/tools/ecode/ecode.hpp b/src/tools/ecode/ecode.hpp index 88b52fb3b..e88e0a193 100644 --- a/src/tools/ecode/ecode.hpp +++ b/src/tools/ecode/ecode.hpp @@ -211,6 +211,7 @@ class App : public UICodeEditorSplitter::Client { t.setCommand( "find-replace", [&] { showFindView(); } ); t.setCommand( "open-global-search", [&] { showGlobalSearch( false ); } ); t.setCommand( "open-locatebar", [&] { mFileLocator->showLocateBar(); } ); + t.setCommand( "open-command-palette", [&] { mFileLocator->showCommandPalette(); } ); t.setCommand( "editor-set-line-breaking-column", [&] { setLineBreakingColumn(); } ); t.setCommand( "editor-set-line-spacing", [&] { setLineSpacing(); } ); t.setCommand( "editor-set-cursor-blinking-time", [&] { setCursorBlinkingTime(); } ); diff --git a/src/tools/ecode/filelocator.cpp b/src/tools/ecode/filelocator.cpp index 7ab0976f3..4db41f088 100644 --- a/src/tools/ecode/filelocator.cpp +++ b/src/tools/ecode/filelocator.cpp @@ -7,14 +7,17 @@ static int LOCATEBAR_MAX_VISIBLE_ITEMS = 18; static int LOCATEBAR_MAX_RESULTS = 100; FileLocator::FileLocator( UICodeEditorSplitter* editorSplitter, UISceneNode* sceneNode, App* app ) : - mEditorSplitter( editorSplitter ), mUISceneNode( sceneNode ), mApp( app ) {} + mEditorSplitter( editorSplitter ), + mUISceneNode( sceneNode ), + mApp( app ), + mCommandPalette( mApp->getThreadPool() ) {} void FileLocator::hideLocateBar() { mLocateBarLayout->setVisible( false ); mLocateTable->setVisible( false ); } -void FileLocator::updateLocateTable() { +void FileLocator::updateFilesTable() { if ( !mLocateInput->getText().empty() ) { #if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ ) mApp->getDirTree()->asyncFuzzyMatchTree( @@ -35,6 +38,41 @@ void FileLocator::updateLocateTable() { } } +void FileLocator::updateCommandPaletteTable() { + if ( !mCommandPalette.isSet() ) + mCommandPalette.setCommandPalette( mApp->getMainLayout()->getCommandList(), + mApp->getMainLayout()->getKeyBindings() ); + + auto txt( mLocateInput->getText() ); + txt.trim(); + + if ( txt.size() > 1 ) { +#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ ) + mCommandPalette.asyncFuzzyMatch( txt.substr( 1 ), 1000, [&]( auto res ) { + mUISceneNode->runOnMainThread( [&, res] { + mLocateTable->setModel( res ); + mLocateTable->getSelection().set( mLocateTable->getModel()->index( 0 ) ); + } ); + } ); +#else + mLocateTable->setModel( mCommandPalette.fuzzyMatch( txt.substr(), 1000 ) ); + mLocateTable->getSelection().set( mLocateTable->getModel()->index( 0 ) ); +#endif + } else { + mLocateTable->setModel( mCommandPalette.getBaseModel() ); + mLocateTable->getSelection().set( mLocateTable->getModel()->index( 0 ) ); + } + + mLocateTable->setColumnsVisible( { 0, 1 } ); +} + +void FileLocator::showLocateTable() { + mLocateTable->setVisible( true ); + Vector2f pos( mLocateInput->convertToWorldSpace( { 0, 0 } ) ); + pos.y -= mLocateTable->getPixelsSize().getHeight(); + mLocateTable->setPixelsPosition( pos ); +} + void FileLocator::goToLine() { showLocateBar(); mLocateInput->setText( "l " ); @@ -56,23 +94,23 @@ void FileLocator::initLocateBar( UILocateBar* locateBar, UITextInput* locateInpu mLocateTable->setHeadersVisible( false ); mLocateTable->setVisible( false ); mLocateInput->addEventListener( Event::OnTextChanged, [&]( const Event* ) { + const String& txt = mLocateInput->getText(); if ( mEditorSplitter->curEditorExistsAndFocused() && - String::startsWith( mLocateInput->getText(), String( "l " ) ) ) { - String number( mLocateInput->getText().substr( 2 ) ); + String::startsWith( txt, String( "l " ) ) ) { + String number( txt.substr( 2 ) ); Int64 val; if ( String::fromString( val, number ) && val - 1 >= 0 ) { if ( mEditorSplitter->curEditorExistsAndFocused() ) mEditorSplitter->getCurEditor()->goToLine( { val - 1, 0 } ); mLocateTable->setVisible( false ); } + } else if ( !txt.empty() && mLocateInput->getText()[0] == '>' ) { + showCommandPalette(); } else { - mLocateTable->setVisible( true ); - Vector2f pos( mLocateInput->convertToWorldSpace( { 0, 0 } ) ); - pos.y -= mLocateTable->getPixelsSize().getHeight(); - mLocateTable->setPixelsPosition( pos ); + showLocateTable(); if ( !mApp->isDirTreeReady() ) return; - updateLocateTable(); + updateFilesTable(); } } ); mLocateInput->addEventListener( Event::OnPressEnter, [&]( const Event* ) { @@ -100,20 +138,31 @@ void FileLocator::initLocateBar( UILocateBar* locateBar, UITextInput* locateInpu mLocateTable->addEventListener( Event::OnModelEvent, [&]( const Event* event ) { const ModelEvent* modelEvent = static_cast( event ); if ( modelEvent->getModelEventType() == ModelEventType::Open ) { - Variant vPath( modelEvent->getModel()->data( - modelEvent->getModel()->index( modelEvent->getModelIndex().row(), 1 ), - ModelRole::Display ) ); - if ( vPath.isValid() && vPath.is( Variant::Type::cstr ) ) { - std::string path( vPath.asCStr() ); - UITab* tab = mEditorSplitter->isDocumentOpen( path, true ); - if ( !tab ) { - FileInfo fileInfo( path ); - if ( fileInfo.exists() && fileInfo.isRegularFile() ) - mApp->loadFileFromPath( path ); - } else { - tab->getTabWidget()->setTabSelected( tab ); + // Keep it simple for now, command palette has 3 columns + if ( modelEvent->getModel()->columnCount() == 3 ) { + ModelIndex idx( + modelEvent->getModel()->index( modelEvent->getModelIndex().row(), 2 ) ); + if ( idx.isValid() ) { + mApp->runCommand( + modelEvent->getModel()->data( idx, ModelRole::Display ).toString() ); + } + hideLocateBar(); + } else { + Variant vPath( modelEvent->getModel()->data( + modelEvent->getModel()->index( modelEvent->getModelIndex().row(), 1 ), + ModelRole::Display ) ); + if ( vPath.isValid() && vPath.is( Variant::Type::cstr ) ) { + std::string path( vPath.asCStr() ); + UITab* tab = mEditorSplitter->isDocumentOpen( path, true ); + if ( !tab ) { + FileInfo fileInfo( path ); + if ( fileInfo.exists() && fileInfo.isRegularFile() ) + mApp->loadFileFromPath( path ); + } else { + tab->getTabWidget()->setTabSelected( tab ); + } + mLocateBarLayout->execute( "close-locatebar" ); } - mLocateBarLayout->execute( "close-locatebar" ); } } } ); @@ -125,6 +174,7 @@ void FileLocator::updateLocateBar() { mLocateTable->setPixelsSize( width, mLocateTable->getRowHeight() * LOCATEBAR_MAX_VISIBLE_ITEMS ); width -= mLocateTable->getVerticalScrollBar()->getPixelsSize().getWidth(); + mLocateTable->setColumnsVisible( { 0, 1 } ); mLocateTable->setColumnWidth( 0, eeceil( width * 0.5 ) ); mLocateTable->setColumnWidth( 1, width - mLocateTable->getColumnWidth( 0 ) ); Vector2f pos( mLocateInput->convertToWorldSpace( { 0, 0 } ) ); @@ -133,7 +183,7 @@ void FileLocator::updateLocateBar() { } ); } -void FileLocator::showLocateBar() { +void FileLocator::showBar() { mApp->hideGlobalSearchBar(); mApp->hideSearchBar(); @@ -143,10 +193,29 @@ void FileLocator::showLocateBar() { mLocateInput->getDocument().selectAll(); mLocateInput->addEventListener( Event::OnSizeChange, [&]( const Event* ) { updateLocateBar(); } ); +} + +void FileLocator::showLocateBar() { + showBar(); + + if ( !mLocateInput->getText().empty() && mLocateInput->getText()[0] == '>' ) + mLocateInput->setText( "" ); + if ( mApp->getDirTree() && !mLocateTable->getModel() ) { mLocateTable->setModel( mApp->getDirTree()->asModel( LOCATEBAR_MAX_RESULTS ) ); mLocateTable->getSelection().set( mLocateTable->getModel()->index( 0 ) ); } + + updateLocateBar(); +} + +void FileLocator::showCommandPalette() { + showBar(); + + if ( mLocateInput->getText().empty() || mLocateInput->getText()[0] != '>' ) + mLocateInput->setText( "> " ); + + updateCommandPaletteTable(); updateLocateBar(); } diff --git a/src/tools/ecode/filelocator.hpp b/src/tools/ecode/filelocator.hpp index c10ad9252..9f29c023a 100644 --- a/src/tools/ecode/filelocator.hpp +++ b/src/tools/ecode/filelocator.hpp @@ -1,6 +1,7 @@ #ifndef ECODE_FILELOCATOR_HPP #define ECODE_FILELOCATOR_HPP +#include "commandpalette.hpp" #include "widgetcommandexecuter.hpp" #include @@ -18,9 +19,15 @@ class FileLocator { void hideLocateBar(); + void showCommandPalette(); + void goToLine(); - void updateLocateTable(); + void updateFilesTable(); + + void updateCommandPaletteTable(); + + void showLocateTable(); protected: UILocateBar* mLocateBarLayout{ nullptr }; @@ -29,8 +36,11 @@ class FileLocator { UICodeEditorSplitter* mEditorSplitter{ nullptr }; UISceneNode* mUISceneNode{ nullptr }; App* mApp{ nullptr }; + CommandPalette mCommandPalette; void updateLocateBar(); + + void showBar(); }; } // namespace ecode diff --git a/src/tools/ecode/settingsmenu.cpp b/src/tools/ecode/settingsmenu.cpp index 41c41049e..58eac463b 100644 --- a/src/tools/ecode/settingsmenu.cpp +++ b/src/tools/ecode/settingsmenu.cpp @@ -1189,6 +1189,10 @@ UIPopUpMenu* SettingsMenu::createToolsMenu() { mToolsMenu ->add( i18n( "locate", "Locate..." ), findIcon( "search" ), getKeybind( "open-locatebar" ) ) ->setId( "open-locatebar" ); + mToolsMenu + ->add( i18n( "command_palette", "Command Palette..." ), findIcon( "search" ), + getKeybind( "open-command-palette" ) ) + ->setId( "open-command-palette" ); mToolsMenu ->add( i18n( "project_find", "Project Find..." ), findIcon( "search" ), getKeybind( "open-global-search" ) ) @@ -1447,7 +1451,7 @@ void SettingsMenu::createProjectTreeMenu() { showProjectTreeMenu(); } -static void fsRemoveAll(const std::string& fpath) { +static void fsRemoveAll( const std::string& fpath ) { #if EE_PLATFORM == EE_PLATFORM_WIN fs::remove_all( std::filesystem::path( String( fpath ).toWideString() ) ); #else diff --git a/src/tools/ecode/terminalmanager.cpp b/src/tools/ecode/terminalmanager.cpp index 7f898967c..d23360643 100644 --- a/src/tools/ecode/terminalmanager.cpp +++ b/src/tools/ecode/terminalmanager.cpp @@ -205,7 +205,8 @@ UITerminal* TerminalManager::createNewTerminal( const std::string& title, UITabW term->getKeyBindings().removeCommandsKeybind( { "open-file", "download-file-web", "open-folder", "debug-draw-highlight-toggle", "debug-draw-boxes-toggle", "debug-draw-debug-data", "debug-widget-tree-view", - "open-locatebar", "open-global-search", "menu-toggle", "console-toggle", "go-to-line" } ); + "open-locatebar", "open-command-palette", "open-global-search", "menu-toggle", + "console-toggle", "go-to-line" } ); term->setCommand( "terminal-rename", [&, term] { UIMessageBox* msgBox = UIMessageBox::New( UIMessageBox::INPUT, mApp->i18n( "new_terminal_name", "New terminal name:" ) );