Reduced the default indent in UITreeView.
ecode:
Search Project every minute when editor is active.
Added "Copy Error Message" in editor right-click context menu
This commit is contained in:
Martín Lucas Golini
2023-06-30 00:37:10 -03:00
parent 93c3971c94
commit d11c4ce865
8 changed files with 129 additions and 87 deletions

View File

@@ -241,6 +241,17 @@ class EE_API UIWidget : public UINode {
void setTooltipEnabled( bool enabled );
UIWidget* getPrevWidget() const;
UIWidget* getNextWidget() const;
String getTranslatorString( const std::string& str );
String getTranslatorString( const std::string& str, const String& defaultValue );
String i18n( const std::string& str );
String i18n( const std::string& str, const String& defaultValue );
protected:
friend class UIManager;
friend class UISceneNode;
@@ -341,17 +352,6 @@ class EE_API UIWidget : public UINode {
void reloadFontFamily();
UIWidget* getPrevWidget() const;
UIWidget* getNextWidget() const;
String getTranslatorString( const std::string& str );
String getTranslatorString( const std::string& str, const String& defaultValue );
String i18n( const std::string& str );
String i18n( const std::string& str, const String& defaultValue );
};
}} // namespace EE::UI

View File

@@ -16,7 +16,7 @@ UITreeView* UITreeView::New() {
UITreeView::UITreeView() :
UIAbstractTableView( "treeview" ),
mIndentWidth( PixelDensity::dpToPx( 12 ) ),
mIndentWidth( PixelDensity::dpToPx( 6 ) ),
mExpanderIconSize( PixelDensity::dpToPxI( 12 ) ) {
setClipType( ClipType::ContentBox );
mExpandIcon = getUISceneNode()->findIcon( "tree-expanded" );

View File

@@ -351,38 +351,32 @@ void AppConfig::saveProject( std::string projectFolder, UICodeEditorSplitter* ed
const std::string& configPath, const ProjectDocumentConfig& docConfig,
const ProjectBuildConfiguration& buildConfig ) {
FileSystem::dirAddSlashAtEnd( projectFolder );
std::vector<UICodeEditor*> editors = editorSplitter->getAllEditors();
std::vector<ProjectPath> paths;
for ( auto editor : editors )
if ( editor->getDocument().hasFilepath() )
paths.emplace_back( ProjectPath{ editor->getDocument().getFilePath(),
editor->getDocument().getSelection() } );
std::string projectsPath( configPath + "projects" + FileSystem::getOSSlash() );
if ( !FileSystem::fileExists( projectsPath ) )
FileSystem::makeDir( projectsPath );
MD5::Result hash = MD5::fromString( projectFolder );
std::string projectCfgPath( projectsPath + hash.toHexString() + ".cfg" );
IniFile ini( projectCfgPath, false );
ini.setValue( "path", "folder_path", projectFolder );
ini.setValueB( "document", "use_global_settings", docConfig.useGlobalSettings );
ini.setValueB( "document", "h_as_cpp", docConfig.hAsCPP );
ini.setValueB( "document", "trim_trailing_whitespaces", docConfig.doc.trimTrailingWhitespaces );
ini.setValueB( "document", "force_new_line_at_end_of_file",
IniFile cfg( projectCfgPath, false );
cfg.setValue( "path", "folder_path", projectFolder );
cfg.setValueB( "document", "use_global_settings", docConfig.useGlobalSettings );
cfg.setValueB( "document", "h_as_cpp", docConfig.hAsCPP );
cfg.setValueB( "document", "trim_trailing_whitespaces", docConfig.doc.trimTrailingWhitespaces );
cfg.setValueB( "document", "force_new_line_at_end_of_file",
docConfig.doc.forceNewLineAtEndOfFile );
ini.setValueB( "document", "auto_detect_indent_type", docConfig.doc.autoDetectIndentType );
ini.setValueB( "document", "write_bom", docConfig.doc.writeUnicodeBOM );
ini.setValueI( "document", "indent_width", docConfig.doc.indentWidth );
ini.setValueB( "document", "indent_spaces", docConfig.doc.indentSpaces );
ini.setValue( "document", "line_endings",
cfg.setValueB( "document", "auto_detect_indent_type", docConfig.doc.autoDetectIndentType );
cfg.setValueB( "document", "write_bom", docConfig.doc.writeUnicodeBOM );
cfg.setValueI( "document", "indent_width", docConfig.doc.indentWidth );
cfg.setValueB( "document", "indent_spaces", docConfig.doc.indentSpaces );
cfg.setValue( "document", "line_endings",
TextDocument::lineEndingToString( docConfig.doc.lineEndings ) );
ini.setValueI( "document", "tab_width", docConfig.doc.tabWidth );
ini.setValueI( "document", "line_breaking_column", docConfig.doc.lineBreakingColumn );
ini.setValue( "build", "build_name", buildConfig.buildName );
ini.setValue( "build", "build_type", buildConfig.buildType );
ini.setValue( "nodes", "documents",
cfg.setValueI( "document", "tab_width", docConfig.doc.tabWidth );
cfg.setValueI( "document", "line_breaking_column", docConfig.doc.lineBreakingColumn );
cfg.setValue( "build", "build_name", buildConfig.buildName );
cfg.setValue( "build", "build_type", buildConfig.buildType );
cfg.setValue( "nodes", "documents",
saveNode( editorSplitter->getBaseLayout()->getFirstChild() ).dump() );
ini.deleteKey( "files" );
ini.writeFile();
cfg.deleteKey( "files" );
cfg.writeFile();
}
static void countTotalEditors( json j, size_t& curTotal ) {
@@ -431,14 +425,15 @@ void AppConfig::loadDocuments( UICodeEditorSplitter* editorSplitter, json j,
UITab* tab = nullptr;
if ( ( tab = editorSplitter->isDocumentOpen( path, false, true ) ) != nullptr ) {
auto tabAndEditor = editorSplitter->createCodeEditorInTabWidget( curTabWidget );
UICodeEditor* editor = tabAndEditor.second;
editor->setDocument(
UICodeEditor* teditor = tabAndEditor.second;
teditor->setDocument(
tab->getOwnedWidget()->asType<UICodeEditor>()->getDocumentRef() );
editorSplitter->removeUnusedTab( curTabWidget );
if ( !editor->getDocument().getSelection().isValid() ||
editor->getDocument().getSelection() == TextRange( { 0, 0 }, { 0, 0 } ) ) {
editor->getDocument().setSelection( selection );
editor->scrollToCursor();
if ( !teditor->getDocument().getSelection().isValid() ||
teditor->getDocument().getSelection() ==
TextRange( { 0, 0 }, { 0, 0 } ) ) {
teditor->getDocument().setSelection( selection );
teditor->scrollToCursor();
}
if ( curTabWidget->getTabCount() == totalToLoad )
curTabWidget->setTabSelected(
@@ -492,44 +487,44 @@ void AppConfig::loadDocuments( UICodeEditorSplitter* editorSplitter, json j,
void AppConfig::loadProject( std::string projectFolder, UICodeEditorSplitter* editorSplitter,
const std::string& configPath, ProjectDocumentConfig& docConfig,
std::shared_ptr<ThreadPool> pool, ecode::App* app ) {
ecode::App* app ) {
FileSystem::dirAddSlashAtEnd( projectFolder );
std::string projectsPath( configPath + "projects" + FileSystem::getOSSlash() );
MD5::Result hash = MD5::fromString( projectFolder );
std::string projectCfgPath( projectsPath + hash.toHexString() + ".cfg" );
if ( !FileSystem::fileExists( projectCfgPath ) )
return;
IniFile ini( projectCfgPath );
IniFile cfg( projectCfgPath );
docConfig.useGlobalSettings = ini.getValueB( "document", "use_global_settings", true );
docConfig.hAsCPP = ini.getValueB( "document", "h_as_cpp", false );
docConfig.useGlobalSettings = cfg.getValueB( "document", "use_global_settings", true );
docConfig.hAsCPP = cfg.getValueB( "document", "h_as_cpp", false );
docConfig.doc.trimTrailingWhitespaces =
ini.getValueB( "document", "trim_trailing_whitespaces", false );
cfg.getValueB( "document", "trim_trailing_whitespaces", false );
docConfig.doc.forceNewLineAtEndOfFile =
ini.getValueB( "document", "force_new_line_at_end_of_file", false );
cfg.getValueB( "document", "force_new_line_at_end_of_file", false );
docConfig.doc.autoDetectIndentType =
ini.getValueB( "document", "auto_detect_indent_type", true );
docConfig.doc.writeUnicodeBOM = ini.getValueB( "document", "write_bom", false );
docConfig.doc.indentWidth = ini.getValueI( "document", "indent_width", 4 );
docConfig.doc.indentSpaces = ini.getValueB( "document", "indent_spaces", false );
cfg.getValueB( "document", "auto_detect_indent_type", true );
docConfig.doc.writeUnicodeBOM = cfg.getValueB( "document", "write_bom", false );
docConfig.doc.indentWidth = cfg.getValueI( "document", "indent_width", 4 );
docConfig.doc.indentSpaces = cfg.getValueB( "document", "indent_spaces", false );
docConfig.doc.lineEndings =
TextDocument::stringToLineEnding( ini.getValue( "document", "line_endings", "LF" ) );
TextDocument::stringToLineEnding( cfg.getValue( "document", "line_endings", "LF" ) );
docConfig.doc.tabWidth = eemax( 2, ini.getValueI( "document", "tab_width", 4 ) );
docConfig.doc.tabWidth = eemax( 2, cfg.getValueI( "document", "tab_width", 4 ) );
docConfig.doc.lineBreakingColumn =
eemax( 0, ini.getValueI( "document", "line_breaking_column", 100 ) );
eemax( 0, cfg.getValueI( "document", "line_breaking_column", 100 ) );
if ( app->getProjectBuildManager() ) {
ProjectBuildConfiguration prjCfg;
prjCfg.buildName = ini.getValue( "build", "build_name", "" );
prjCfg.buildType = ini.getValue( "build", "build_type", "" );
prjCfg.buildName = cfg.getValue( "build", "build_name", "" );
prjCfg.buildType = cfg.getValue( "build", "build_type", "" );
app->getProjectBuildManager()->setConfig( prjCfg );
}
if ( ini.keyValueExists( "nodes", "documents" ) ) {
if ( cfg.keyValueExists( "nodes", "documents" ) ) {
json j;
try {
j = json::parse( ini.getValue( "nodes", "documents" ) );
j = json::parse( cfg.getValue( "nodes", "documents" ) );
} catch ( const json::exception& e ) {
Log::error( "AppConfig::loadProject: error loading project: %s", e.what() );
return;

View File

@@ -187,7 +187,7 @@ class AppConfig {
void loadProject( std::string projectFolder, UICodeEditorSplitter* editorSplitter,
const std::string& configPath, ProjectDocumentConfig& docConfig,
std::shared_ptr<ThreadPool> pool, ecode::App* app );
ecode::App* app );
protected:
Int64 editorsToLoad{ 0 };

View File

@@ -52,10 +52,7 @@ bool App::onCloseRequestCallback( EE::Window::Window* ) {
"Do you really want to close the code editor?\nAll changes will be lost." )
.unescape() );
msgBox->addEventListener( Event::OnConfirm, [this]( const Event* ) {
if ( !mCurrentProject.empty() )
mConfig.saveProject( mCurrentProject, mSplitter, mConfigPath, mProjectDocConfig,
mProjectBuildManager ? mProjectBuildManager->getConfig()
: ProjectBuildConfiguration() );
saveProject();
saveConfig();
mWindow->close();
} );
@@ -65,10 +62,7 @@ bool App::onCloseRequestCallback( EE::Window::Window* ) {
msgBox->showWhenReady();
return false;
} else {
if ( !mCurrentProject.empty() )
mConfig.saveProject( mCurrentProject, mSplitter, mConfigPath, mProjectDocConfig,
mProjectBuildManager ? mProjectBuildManager->getConfig()
: ProjectBuildConfiguration() );
saveProject();
saveConfig();
return true;
}
@@ -1892,6 +1886,13 @@ bool App::isUnlockedCommand( const std::string& command ) {
return std::find( cmds.begin(), cmds.end(), command ) != cmds.end();
}
void App::saveProject() {
if ( !mCurrentProject.empty() )
mConfig.saveProject( mCurrentProject, mSplitter, mConfigPath, mProjectDocConfig,
mProjectBuildManager ? mProjectBuildManager->getConfig()
: ProjectBuildConfiguration() );
}
void App::closeEditors() {
mRecentClosedFiles = {};
@@ -1899,9 +1900,8 @@ void App::closeEditors() {
mSplitter->clearNavigationHistory();
mStatusBar->setVisible( mConfig.ui.showStatusBar );
mConfig.saveProject( mCurrentProject, mSplitter, mConfigPath, mProjectDocConfig,
mProjectBuildManager ? mProjectBuildManager->getConfig()
: ProjectBuildConfiguration() );
saveProject();
std::vector<UICodeEditor*> editors = mSplitter->getAllEditors();
while ( !editors.empty() ) {
UICodeEditor* editor = editors[0];
@@ -2938,7 +2938,7 @@ void App::loadFolder( const std::string& path ) {
Clock projClock;
mProjectBuildManager =
std::make_unique<ProjectBuildManager>( rpath, mThreadPool, mSidePanel, this );
mConfig.loadProject( rpath, mSplitter, mConfigPath, mProjectDocConfig, mThreadPool, this );
mConfig.loadProject( rpath, mSplitter, mConfigPath, mProjectDocConfig, this );
Log::info( "Load project took: %.2f ms", projClock.getElapsedTime().asMilliseconds() );
loadFileSystemMatcher( rpath );
@@ -4001,17 +4001,18 @@ Anchor.error:hover {
if ( mConfig.workspace.checkForUpdatesAtStartup )
checkForUpdates( true );
#if EE_PLATFORM == EE_PLATFORM_LINUX
mUISceneNode->setInterval(
[this] {
if ( mWindow && mThreadPool &&
mWindow->getInput()->getElapsedSinceLastKeyboardOrMouseEvent().asSeconds() <
60.f ) {
saveProject();
#if EE_PLATFORM == EE_PLATFORM_LINUX
mThreadPool->run( [] { malloc_trim( 0 ); } );
#endif
}
},
Seconds( 60.f ) );
#endif
mWindow->runMainLoop( &appLoop, mBenchmarkMode ? 0 : mConfig.context.FrameRateLimit );
}

View File

@@ -411,6 +411,8 @@ class App : public UICodeEditorSplitter::Client {
const std::string& getFileToOpen() const;
void saveProject();
protected:
std::vector<std::string> mArgs;
EE::Window::Window* mWindow{ nullptr };

View File

@@ -9,7 +9,10 @@
#include <eepp/system/process.hpp>
#include <eepp/system/scopedop.hpp>
#include <eepp/ui/uiiconthememanager.hpp>
#include <eepp/ui/uipopupmenu.hpp>
#include <eepp/ui/uitooltip.hpp>
#include <eepp/window/clipboard.hpp>
#include <eepp/window/window.hpp>
#include <nlohmann/json.hpp>
#include <random>
@@ -487,10 +490,14 @@ void LinterPlugin::onRegister( UICodeEditor* editor ) {
if ( editor->hasDocument() ) {
auto& doc = editor->getDocument();
doc.setCommand( "linter-go-to-next-error", [this, editor]() { goToNextError( editor ); } );
doc.setCommand( "linter-go-to-next-error", [this, editor] { goToNextError( editor ); } );
doc.setCommand( "linter-go-to-previous-error",
[this, editor]() { goToPrevError( editor ); } );
[this, editor] { goToPrevError( editor ); } );
doc.setCommand( "linter-copy-error-message", [this, editor] {
editor->getUISceneNode()->getWindow()->getClipboard()->setText( mErrorMsg );
} );
}
mEditors.insert( { editor, listeners } );
@@ -858,18 +865,21 @@ void LinterPlugin::drawAfterLineText( UICodeEditor* editor, const Int64& index,
!match.codeActions.empty() ) {
rLineWidth = editor->getLineWidth( index );
Color wcolor( editor->getColorScheme().getEditorSyntaxStyle( "warning" ).color );
UIIcon* notification =
editor->getUISceneNode()->getUIIconThemeManager()->findIcon( "lightbulb-autofix" );
Float size = lineHeight;
Drawable* drawable = notification->getSize( (int)eefloor( size ) );
if ( drawable == nullptr )
return;
if ( nullptr == mLightbulbIcon ) {
mLightbulbIcon = editor->getUISceneNode()->getUIIconThemeManager()->findIcon(
"lightbulb-autofix" );
}
if ( nullptr != mLightbulbIcon ) {
Drawable* drawable = mLightbulbIcon->getSize( (int)eefloor( lineHeight ) );
if ( drawable == nullptr )
return;
Color oldColor( drawable->getColor() );
drawable->setColor( wcolor );
drawable->draw( { position.x + rLineWidth, position.y } );
drawable->setColor( oldColor );
quickFixRendered = true;
Color oldColor( drawable->getColor() );
drawable->setColor( wcolor );
drawable->draw( { position.x + rLineWidth, position.y } );
drawable->setColor( oldColor );
quickFixRendered = true;
}
}
if ( !mErrorLens || i != 0 )
@@ -1120,4 +1130,33 @@ void LinterPlugin::invalidateEditors( TextDocument* doc ) {
}
}
bool LinterPlugin::onCreateContextMenu( UICodeEditor* editor, UIPopUpMenu* menu,
const Vector2i& pos, const Uint32& /*flags*/ ) {
Lock l( mMatchesMutex );
auto it = mMatches.find( editor->getDocumentRef().get() );
if ( it == mMatches.end() )
return false;
Vector2f localPos( editor->convertToNodeSpace( pos.asFloat() ) );
TextPosition cursorPosition = editor->resolveScreenPosition( pos.asFloat() );
auto matchIt = it->second.find( cursorPosition.line() );
if ( matchIt == it->second.end() )
return false;
auto& matches = matchIt->second;
for ( auto& match : matches ) {
if ( match.box[editor].contains( localPos ) ) {
menu->addSeparator();
menu->add( editor->i18n( "copy_error_message", "Copy Error Message" ),
mManager->getUISceneNode()->findIcon( "copy" )->getSize(
PixelDensity::dpToPxI( 12 ) ) )
->setId( "linter-copy-error-message" );
mErrorMsg = match.text;
break;
}
}
return false;
}
} // namespace ecode

View File

@@ -106,6 +106,9 @@ class LinterPlugin : public Plugin {
Linter getLinterForLang( const std::string& lang, const std::vector<std::string>& extensions );
virtual bool onCreateContextMenu( UICodeEditor* editor, UIPopUpMenu* menu,
const Vector2i& position, const Uint32& flags );
protected:
std::vector<Linter> mLinters;
std::unordered_map<UICodeEditor*, std::vector<Uint32>> mEditors;
@@ -128,6 +131,8 @@ class LinterPlugin : public Plugin {
std::set<std::string> mLanguagesDisabled;
std::set<std::string> mLSPLanguagesDisabled;
String::HashType mConfigHash{ 0 };
UIIcon* mLightbulbIcon{ nullptr };
std::string mErrorMsg;
LinterPlugin( PluginManager* pluginManager, bool sync );