From ac35e9ca0eaea474df447cacff27e75e5588d9b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Sun, 17 Dec 2023 14:44:00 -0300 Subject: [PATCH] Git Plugin more WIP. --- include/eepp/ui/uitextview.hpp | 2 + src/eepp/ui/uitextview.cpp | 4 + src/tools/ecode/applayout.xml.hpp | 2 + src/tools/ecode/ecode.cpp | 2 + src/tools/ecode/plugins/git/gitplugin.cpp | 107 +++++++++++++++++++--- src/tools/ecode/plugins/git/gitplugin.hpp | 15 ++- src/tools/ecode/plugins/plugin.cpp | 4 + src/tools/ecode/plugins/plugin.hpp | 2 + src/tools/ecode/plugins/pluginmanager.cpp | 6 +- src/tools/ecode/plugins/pluginmanager.hpp | 3 + 10 files changed, 130 insertions(+), 17 deletions(-) diff --git a/include/eepp/ui/uitextview.hpp b/include/eepp/ui/uitextview.hpp index 0d5ee0130..4ca8c60b0 100644 --- a/include/eepp/ui/uitextview.hpp +++ b/include/eepp/ui/uitextview.hpp @@ -98,6 +98,8 @@ class EE_API UITextView : public UIWidget { const Text* getTextCache() const; + Text* getTextCache(); + const Vector2f& getRealAlignOffset() const; const TextTransform::Value& getTextTransform() const; diff --git a/src/eepp/ui/uitextview.cpp b/src/eepp/ui/uitextview.cpp index 52922e534..950c6846e 100644 --- a/src/eepp/ui/uitextview.cpp +++ b/src/eepp/ui/uitextview.cpp @@ -232,6 +232,10 @@ const Text* UITextView::getTextCache() const { return mTextCache; } +Text* UITextView::getTextCache() { + return mTextCache; +} + const Vector2f& UITextView::getRealAlignOffset() const { return mRealAlignOffset; } diff --git a/src/tools/ecode/applayout.xml.hpp b/src/tools/ecode/applayout.xml.hpp index 0185f5cf2..22e1a3fa7 100644 --- a/src/tools/ecode/applayout.xml.hpp +++ b/src/tools/ecode/applayout.xml.hpp @@ -50,6 +50,7 @@ RelativeLayout > #doc_info { padding: 6dp; opacity: 0.8; layout-gravity: bottom|right; + font-size: 1rem; } StatusBar > #doc_info { background-color: transparent; @@ -60,6 +61,7 @@ StatusBar > #doc_info { padding: 0dp 4dp 0dp 4dp; opacity: 1; layout-gravity: center; + font-size: 10dp; } #doc_info { color: var(--font); diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index 3986a296a..52b278bf8 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -3627,6 +3627,8 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe } #endif + mPluginManager->setUIReady(); + mWindow->runMainLoop( &appLoop, mBenchmarkMode ? 0 : mConfig.context.FrameRateLimit ); } } diff --git a/src/tools/ecode/plugins/git/gitplugin.cpp b/src/tools/ecode/plugins/git/gitplugin.cpp index 4fbef98f2..853959f22 100644 --- a/src/tools/ecode/plugins/git/gitplugin.cpp +++ b/src/tools/ecode/plugins/git/gitplugin.cpp @@ -1,4 +1,5 @@ #include "gitplugin.hpp" +#include "eepp/ui/uistyle.hpp" #include #include #include @@ -40,6 +41,8 @@ GitPlugin::GitPlugin( PluginManager* pluginManager, bool sync ) : PluginBase( pl GitPlugin::~GitPlugin() { mShuttingDown = true; + if ( mStatusButton ) + mStatusButton->close(); } void GitPlugin::load( PluginManager* pluginManager ) { @@ -75,6 +78,13 @@ void GitPlugin::load( PluginManager* pluginManager ) { if ( j.contains( "config" ) ) { auto& config = j["config"]; + if ( config.contains( "ui_refresh_frequency" ) ) + mRefreshFreq = Time::fromString( config.value( "ui_refresh_frequency", "5s" ) ); + else { + config["ui_refresh_frequency"] = mRefreshFreq.toString(); + updateConfigFile = true; + } + if ( config.contains( "statusbar_display_branch" ) ) mStatusBarDisplayBranch = config.value( "statusbar_display_branch", true ); else { @@ -117,24 +127,85 @@ void GitPlugin::load( PluginManager* pluginManager ) { } } - mGit = std::make_unique( "", pluginManager->getWorkspaceFolder() ); + mGit = std::make_unique( pluginManager->getWorkspaceFolder() ); mGitFound = !mGit->getGitPath().empty(); + if ( getUISceneNode() ) + updateStatusBar(); + subscribeFileSystemListener(); mReady = true; fireReadyCbs(); setReady(); } +void GitPlugin::updateUINow() { + if ( !mGit || !getUISceneNode() ) + return; + + updateStatusBar(); +} + +void GitPlugin::updateUI() { + if ( !mGit || !getUISceneNode() ) + return; + + getUISceneNode()->debounce( [this] { updateUINow(); }, mRefreshFreq, + String::hash( "git::status-update" ) ); +} + +void GitPlugin::updateStatusBar() { + if ( !mGit || !mStatusBarDisplayBranch ) + return; + mThreadPool->run( [this] { + if ( !mGit ) + return; + mGitBranch = mGit->branch(); + mGitStatus = mGit->status(); + getUISceneNode()->runOnMainThread( [this] { + if ( !mStatusBar ) + getUISceneNode()->bind( "status_bar", mStatusBar ); + if ( !mStatusBar ) + return; + + if ( !mStatusButton ) { + mStatusButton = UIPushButton::New(); + mStatusButton->setLayoutSizePolicy( SizePolicy::WrapContent, + SizePolicy::MatchParent ); + mStatusButton->setId( "status_git" ); + mStatusButton->setClass( "status_but" ); + mStatusButton->setIcon( getManager() + ->getUISceneNode() + ->findIcon( "source-control" ) + ->getSize( PixelDensity::dpToPxI( 12 ) ) ); + mStatusButton->setParent( mStatusBar ); + auto childCount = mStatusBar->getChildCount(); + if ( childCount > 2 ) + mStatusButton->toPosition( mStatusBar->getChildCount() - 2 ); + } + + std::string text( mStatusBarDisplayModifications + ? String::format( "%s (+%d / -%d)", mGitBranch.c_str(), + mGitStatus.totalInserts, + mGitStatus.totalDeletions ) + : mGitBranch ); + + mStatusButton->setText( text ); + } ); + } ); +} + PluginRequestHandle GitPlugin::processMessage( const PluginMessage& msg ) { switch ( msg.type ) { case PluginMessageType::WorkspaceFolderChanged: { - if ( !mGit ) - mGit = std::make_unique( "", msg.asJSON()["folder"] ); - else + if ( mGit ) mGit->setProjectPath( msg.asJSON()["folder"] ); break; } + case ecode::PluginMessageType::UIReady: { + updateStatusBar(); + break; + } default: break; } @@ -146,10 +217,23 @@ void GitPlugin::onFileSystemEvent( const FileEvent& ev, const FileInfo& file ) { if ( mShuttingDown || isLoading() ) return; + + updateUI(); } void GitPlugin::displayTooltip( UICodeEditor* editor, const Git::Blame& blame, const Vector2f& position ) { + static std::vector patterns; + + if ( patterns.empty() ) { + patterns.emplace_back( SyntaxPattern( { "([%w:]+)%s(%x+)%s%((%x+)%)" }, + { "normal", "keyword", "number", "number" } ) ); + patterns.emplace_back( SyntaxPattern( { "([%w:]+)%s(.*)%(([%w%.-]+@[%w-]+%.%w+)%)" }, + { "normal", "keyword", "function", "link" } ) ); + patterns.emplace_back( SyntaxPattern( { "([%w:]+)%s(%d%d%d%d%-%d%d%-%d%d[%s%d%-+:]+)" }, + { "normal", "keyword", "warning" } ) ); + } + // HACK: Gets the old font style to restore it when the tooltip is hidden UITooltip* tooltip = editor->createTooltip(); if ( tooltip == nullptr ) @@ -181,15 +265,10 @@ void GitPlugin::displayTooltip( UICodeEditor* editor, const Git::Blame& blame, tooltip->setDontAutoHideOnMouseMove( true ); tooltip->setUsingCustomStyling( true ); tooltip->setData( String::hash( "git" ) ); - tooltip->setBackgroundColor( editor->getColorScheme().getEditorColor( "background"_sst ) ); - - std::vector patterns; - patterns.emplace_back( SyntaxPattern( { "([%w:]+)%s(%x+)%s%((%x+)%)" }, - { "normal", "keyword", "number", "number" } ) ); - patterns.emplace_back( SyntaxPattern( { "([%w:]+)%s(.*)%(([%w%.-]+@[%w-]+%.%w+)%)" }, - { "normal", "keyword", "function", "link" } ) ); - patterns.emplace_back( SyntaxPattern( { "([%w:]+)%s(%d%d%d%d%-%d%d%-%d%d[%s%d%-:]+)" }, - { "normal", "keyword", "warning" } ) ); + tooltip->getUIStyle()->setStyleSheetProperty( StyleSheetProperty( + "background-color", + editor->getColorScheme().getEditorColor( "background"_sst ).toRgbaString(), true, + StyleSheetSelectorRule::SpecificityImportant ) ); SyntaxDefinition syntaxDef( "custom_build", {}, std::move( patterns ) ); @@ -251,7 +330,7 @@ void GitPlugin::blame( UICodeEditor* editor ) { } mThreadPool->run( [this, editor]() { auto blame = mGit->blame( editor->getDocument().getFilePath(), - editor->getDocument().getSelection().start().line() ); + editor->getDocument().getSelection().start().line() + 1 ); editor->runOnMainThread( [this, editor, blame] { displayTooltip( editor, blame, diff --git a/src/tools/ecode/plugins/git/gitplugin.hpp b/src/tools/ecode/plugins/git/gitplugin.hpp index 44c8b659b..cd28d9e55 100644 --- a/src/tools/ecode/plugins/git/gitplugin.hpp +++ b/src/tools/ecode/plugins/git/gitplugin.hpp @@ -4,6 +4,7 @@ #include "../plugin.hpp" #include "../pluginmanager.hpp" #include "git.hpp" +#include namespace ecode { @@ -42,6 +43,11 @@ class GitPlugin : public PluginBase { protected: std::unique_ptr mGit; + std::string mGitBranch; + Git::Status mGitStatus; + UILinearLayout* mStatusBar{ nullptr }; + UIPushButton* mStatusButton{ nullptr }; + Time mRefreshFreq{ Seconds( 5 ) }; GitPlugin( PluginManager* pluginManager, bool sync ); @@ -49,8 +55,7 @@ class GitPlugin : public PluginBase { PluginRequestHandle processMessage( const PluginMessage& msg ); - void displayTooltip( UICodeEditor* editor, const Git::Blame& blame, - const Vector2f& position ); + void displayTooltip( UICodeEditor* editor, const Git::Blame& blame, const Vector2f& position ); void hideTooltip( UICodeEditor* editor ); @@ -71,6 +76,12 @@ class GitPlugin : public PluginBase { Color mOldBackgroundColor; void blame( UICodeEditor* editor ); + + void updateStatusBar(); + + void updateUI(); + + void updateUINow(); }; } // namespace ecode diff --git a/src/tools/ecode/plugins/plugin.cpp b/src/tools/ecode/plugins/plugin.cpp index 24a7b64a5..e0b0b583f 100644 --- a/src/tools/ecode/plugins/plugin.cpp +++ b/src/tools/ecode/plugins/plugin.cpp @@ -45,6 +45,10 @@ PluginManager* Plugin::getManager() const { return mManager; } +UISceneNode* Plugin::getUISceneNode() const { + return mManager->getUISceneNode(); +} + String Plugin::i18n( const std::string& key, const String& def ) const { return getManager()->getUISceneNode()->i18n( key, def ); } diff --git a/src/tools/ecode/plugins/plugin.hpp b/src/tools/ecode/plugins/plugin.hpp index 7105531c2..391b0f826 100644 --- a/src/tools/ecode/plugins/plugin.hpp +++ b/src/tools/ecode/plugins/plugin.hpp @@ -32,6 +32,8 @@ class Plugin : public UICodeEditorPlugin { PluginManager* getManager() const; + UISceneNode* getUISceneNode() const; + virtual String::HashType getConfigFileHash() { return 0; } virtual void onFileSystemEvent( const FileEvent& ev, const FileInfo& file ); diff --git a/src/tools/ecode/plugins/pluginmanager.cpp b/src/tools/ecode/plugins/pluginmanager.cpp index 4db78dfee..69fc9c5c0 100644 --- a/src/tools/ecode/plugins/pluginmanager.cpp +++ b/src/tools/ecode/plugins/pluginmanager.cpp @@ -1,6 +1,6 @@ +#include "pluginmanager.hpp" #include "../filesystemlistener.hpp" #include "plugin.hpp" -#include "pluginmanager.hpp" #include #include #include @@ -30,6 +30,10 @@ void PluginManager::registerPlugin( const PluginDefinition& def ) { mDefinitions[def.id] = def; } +void PluginManager::setUIReady() { + sendBroadcast( PluginMessageType::UIReady, PluginMessageFormat::Empty, nullptr ); +} + UICodeEditorPlugin* ecode::PluginManager::get( const std::string& id ) { auto findIt = mPlugins.find( id ); if ( findIt != mPlugins.end() ) diff --git a/src/tools/ecode/plugins/pluginmanager.hpp b/src/tools/ecode/plugins/pluginmanager.hpp index 0c06db679..8bd63bf95 100644 --- a/src/tools/ecode/plugins/pluginmanager.hpp +++ b/src/tools/ecode/plugins/pluginmanager.hpp @@ -88,6 +88,7 @@ enum class PluginMessageType { // particular document location GetDiagnostics, // Request the diagnostic information from a cursor position QueryPluginCapability, // Requests / queries if a plugin providers a capability + UIReady, // Informs the Plugins that the UI is ready to be used Undefined }; @@ -265,6 +266,8 @@ class PluginManager { void registerPlugin( const PluginDefinition& def ); + void setUIReady(); + UICodeEditorPlugin* get( const std::string& id ); bool setEnabled( const std::string& id, bool enable, bool sync = false );