mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-05-31 02:26:29 +03:00
eepp:
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:
@@ -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
|
||||
|
||||
@@ -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" );
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 );
|
||||
|
||||
|
||||
Reference in New Issue
Block a user