mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-05-28 17:16:29 +03:00
ecode: IgnoreMatcherManager fixes. Implemented a new plugin manager.
This commit is contained in:
@@ -35,6 +35,50 @@ template <typename T> class ItemListModel final : public Model {
|
||||
std::vector<T>& mData;
|
||||
};
|
||||
|
||||
template <typename K, typename V> class ItemPairListModel final : public Model {
|
||||
public:
|
||||
static std::shared_ptr<ItemPairListModel> create( std::vector<std::pair<K, V>>& data ) {
|
||||
return std::make_shared( *new ItemPairListModel<K, V>( data ) );
|
||||
}
|
||||
|
||||
virtual ~ItemPairListModel() {}
|
||||
|
||||
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:
|
||||
explicit ItemPairListModel( std::vector<K, V>& data ) : mData( data ) {}
|
||||
|
||||
std::vector<std::pair<K, V>>& mData;
|
||||
std::vector<std::string> mColumnNames{ "Title", "Description" };
|
||||
};
|
||||
|
||||
}}} // namespace EE::UI::Models
|
||||
|
||||
#endif // EE_UI_MODELS_ITEMLISTMODEL_HPP
|
||||
|
||||
@@ -31,12 +31,14 @@ class UIMenuItem;
|
||||
|
||||
class UICodeEditorPlugin {
|
||||
public:
|
||||
virtual std::string getId() = 0;
|
||||
virtual std::string getTitle() = 0;
|
||||
virtual std::string getDescription() = 0;
|
||||
virtual bool hasGUIConfig() { return false; }
|
||||
virtual bool hasFileConfig() { return false; }
|
||||
virtual UIWindow* getGUIConfig() { return nullptr; }
|
||||
virtual std::string getFileConfigPath() { return ""; }
|
||||
virtual ~UICodeEditorPlugin() {}
|
||||
|
||||
virtual void onRegister( UICodeEditor* ) = 0;
|
||||
virtual void onUnregister( UICodeEditor* ) = 0;
|
||||
|
||||
@@ -56,6 +56,8 @@ class EE_API UISceneNode : public SceneNode {
|
||||
|
||||
String getTranslatorStringFromKey( const std::string& key, const String& defaultValue );
|
||||
|
||||
String i18n( const std::string& key, const String& defaultValue );
|
||||
|
||||
UIWidget* loadLayoutNodes( pugi::xml_node node, Node* parent, const Uint32& marker );
|
||||
|
||||
UIWidget* loadLayoutFromFile( const std::string& layoutPath, Node* parent = NULL,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 8.0.1, 2022-09-03T02:48:17. -->
|
||||
<!-- Written by QtCreator 8.0.1, 2022-09-16T02:40:37. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
@@ -109,7 +109,7 @@
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{388e5431-b31b-42b3-b9ad-9002d279d75d}</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">10</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">15</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">19</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">../../make/linux</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
@@ -1105,7 +1105,7 @@
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">eepp-UIEditor-debug</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey"></value>
|
||||
<value type="QString" key="RunConfiguration.Arguments">--xml=/home/downloads/temp/eepp/search_box.xml -u</value>
|
||||
<value type="QString" key="RunConfiguration.Arguments">-u</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebugger">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
||||
@@ -1203,6 +1203,7 @@
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">ecode-debug</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey"></value>
|
||||
<value type="QString" key="RunConfiguration.Arguments">../</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebugger">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
||||
@@ -1429,109 +1430,9 @@
|
||||
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">21</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.1</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="DeviceType">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Replacement for "Desktop"</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Replacement for "Desktop"</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{6d057187-158a-4883-8d5b-d470a6b6b025}</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/programming/eepp/projects/linux</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
|
||||
<value type="QString">all</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericMakeStep</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
|
||||
<value type="QString">clean</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericMakeStep</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Default</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericBuildConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.FilterExternalIssues">false</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.KCachegrindExecutable">/usr/bin/kcachegrind</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.LeakCheckOnFinish">2</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.SelfModifyingCodeDetection">2</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.ShowReachable">true</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">/usr/bin/valgrind</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
|
||||
<value type="QString">11</value>
|
||||
<value type="QString">14</value>
|
||||
<value type="QString">12</value>
|
||||
<value type="QString">13</value>
|
||||
<value type="QString">2</value>
|
||||
<value type="QString">3</value>
|
||||
<value type="QString">4</value>
|
||||
<value type="QString">5</value>
|
||||
<value type="QString">6</value>
|
||||
<value type="QString">7</value>
|
||||
<value type="QString">8</value>
|
||||
<value type="QString">9</value>
|
||||
<value type="QString">10</value>
|
||||
<value type="QString">0</value>
|
||||
<value type="QString">1</value>
|
||||
</valuelist>
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey"></value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="int">2</value>
|
||||
<value type="int">1</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||
|
||||
@@ -1161,6 +1161,8 @@
|
||||
../../src/tools/ecode/notificationcenter.hpp
|
||||
../../src/tools/ecode/plugins/linter/linterplugin.cpp
|
||||
../../src/tools/ecode/plugins/linter/linterplugin.hpp
|
||||
../../src/tools/ecode/plugins/pluginmanager.cpp
|
||||
../../src/tools/ecode/plugins/pluginmanager.hpp
|
||||
../../src/tools/ecode/projectdirectorytree.cpp
|
||||
../../src/tools/ecode/projectdirectorytree.hpp
|
||||
../../src/tools/ecode/projectsearch.cpp
|
||||
|
||||
@@ -130,8 +130,7 @@ void UIAbstractTableView::createOrUpdateColumns() {
|
||||
for ( size_t col = 0; col < count; col++ ) {
|
||||
if ( col != mMainColumn && !isColumnHidden( col ) ) {
|
||||
Float colWidth = getMaxColumnContentWidth( col, true );
|
||||
if ( colWidth == 0 )
|
||||
colWidth = columnData( col ).widget->getPixelsSize().getWidth();
|
||||
colWidth = eemax( colWidth, columnData( col ).widget->getPixelsSize().getWidth() );
|
||||
usedWidth += colWidth;
|
||||
columnData( col ).width = colWidth;
|
||||
}
|
||||
@@ -336,8 +335,17 @@ void UIAbstractTableView::setColumnsVisible( const std::vector<size_t> columns )
|
||||
return;
|
||||
for ( size_t i = 0; i < getModel()->columnCount(); i++ )
|
||||
columnData( i ).visible = false;
|
||||
for ( auto col : columns )
|
||||
|
||||
bool foundMainColumn = false;
|
||||
for ( auto col : columns ) {
|
||||
columnData( col ).visible = true;
|
||||
if ( col == mMainColumn )
|
||||
foundMainColumn = true;
|
||||
}
|
||||
|
||||
if ( !foundMainColumn && !columns.empty() )
|
||||
mMainColumn = columns[0];
|
||||
|
||||
createOrUpdateColumns();
|
||||
}
|
||||
|
||||
|
||||
@@ -193,6 +193,10 @@ String UISceneNode::getTranslatorStringFromKey( const std::string& key,
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
String UISceneNode::i18n( const std::string& key, const String& defaultValue ) {
|
||||
return getTranslatorStringFromKey( key, defaultValue );
|
||||
}
|
||||
|
||||
void UISceneNode::setFocusLastWindow( UIWindow* window ) {
|
||||
if ( NULL == mParentNode && NULL != mEventDispatcher && !mWindowsList.empty() &&
|
||||
window != mWindowsList.front() ) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "appconfig.hpp"
|
||||
#include "ecode.hpp"
|
||||
#include "plugins/pluginmanager.hpp"
|
||||
#include "thirdparty/json.hpp"
|
||||
#include <eepp/network/uri.hpp>
|
||||
#include <eepp/system/filesystem.hpp>
|
||||
@@ -42,7 +43,7 @@ static std::vector<std::string> urlDecode( const std::vector<std::string>& vec )
|
||||
void AppConfig::load( const std::string& confPath, std::string& keybindingsPath,
|
||||
std::string& initColorScheme, std::vector<std::string>& recentFiles,
|
||||
std::vector<std::string>& recentFolders, const std::string& resPath,
|
||||
const Float& displayDPI ) {
|
||||
const Float& displayDPI, PluginManager* pluginManager ) {
|
||||
keybindingsPath = confPath + "keybindings.cfg";
|
||||
ini.loadFromFile( confPath + "config.cfg" );
|
||||
iniState.loadFromFile( confPath + "state.cfg" );
|
||||
@@ -95,9 +96,6 @@ void AppConfig::load( const std::string& confPath, std::string& keybindingsPath,
|
||||
editor.colorPickerSelection = ini.getValueB( "editor", "color_picker_selection", true );
|
||||
editor.colorPreview = ini.getValueB( "editor", "color_preview", true );
|
||||
editor.minimap = ini.getValueB( "editor", "minimap", true );
|
||||
editor.autoComplete = ini.getValueB( "editor", "auto_complete", true );
|
||||
editor.linter = ini.getValueB( "editor", "linter", true );
|
||||
editor.formatter = ini.getValueB( "editor", "formatter", true );
|
||||
editor.showDocInfo = ini.getValueB( "editor", "show_doc_info", true );
|
||||
editor.hideTabBarOnSingleTab = ini.getValueB( "editor", "hide_tab_bar_on_single_tab", true );
|
||||
editor.singleClickTreeNavigation =
|
||||
@@ -121,6 +119,15 @@ void AppConfig::load( const std::string& confPath, std::string& keybindingsPath,
|
||||
term.fontSize = ini.getValue( "terminal", "font_size", "11dp" );
|
||||
term.colorScheme = ini.getValue( "terminal", "colorscheme", "eterm" );
|
||||
|
||||
std::map<std::string, bool> pluginsEnabled;
|
||||
const auto& creators = pluginManager->getDefinitions();
|
||||
for ( const auto& creator : creators )
|
||||
pluginsEnabled[creator.first] =
|
||||
ini.getValueB( "plugins", creator.first,
|
||||
"autocomplete" == creator.first || "linter" == creator.first ||
|
||||
"autoformatter" == creator.first );
|
||||
pluginManager->setPluginsEnabled( pluginsEnabled );
|
||||
|
||||
iniInfo = FileInfo( ini.path() );
|
||||
}
|
||||
|
||||
@@ -128,7 +135,8 @@ void AppConfig::save( const std::vector<std::string>& recentFiles,
|
||||
const std::vector<std::string>& recentFolders,
|
||||
const std::string& panelPartition, EE::Window::Window* win,
|
||||
const std::string& colorSchemeName, const SearchBarConfig& searchBarConfig,
|
||||
const GlobalSearchBarConfig& globalSearchBarConfig ) {
|
||||
const GlobalSearchBarConfig& globalSearchBarConfig,
|
||||
PluginManager* pluginManager ) {
|
||||
|
||||
FileInfo configInfo( ini.path() );
|
||||
if ( iniInfo.getModificationTime() != 0 &&
|
||||
@@ -186,9 +194,6 @@ void AppConfig::save( const std::vector<std::string>& recentFiles,
|
||||
ini.setValueB( "editor", "color_picker_selection", editor.colorPickerSelection );
|
||||
ini.setValueB( "editor", "color_preview", editor.colorPreview );
|
||||
ini.setValueB( "editor", "minimap", editor.minimap );
|
||||
ini.setValueB( "editor", "auto_complete", editor.autoComplete );
|
||||
ini.setValueB( "editor", "linter", editor.linter );
|
||||
ini.setValueB( "editor", "formatter", editor.formatter );
|
||||
ini.setValueB( "editor", "show_doc_info", editor.showDocInfo );
|
||||
ini.setValueB( "editor", "hide_tab_bar_on_single_tab", editor.hideTabBarOnSingleTab );
|
||||
ini.setValueB( "editor", "single_click_tree_navigation", editor.singleClickTreeNavigation );
|
||||
@@ -214,6 +219,10 @@ void AppConfig::save( const std::vector<std::string>& recentFiles,
|
||||
ini.setValueI( "window", "multisamples", context.Multisamples );
|
||||
ini.setValueI( "window", "frameratelimit", context.FrameRateLimit );
|
||||
|
||||
const auto& pluginsEnabled = pluginManager->getPluginsEnabled();
|
||||
for ( const auto& plugin : pluginsEnabled )
|
||||
ini.setValueB( "plugins", plugin.first, plugin.second );
|
||||
|
||||
ini.writeFile();
|
||||
iniState.writeFile();
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ using namespace EE::Window;
|
||||
|
||||
namespace ecode {
|
||||
class App;
|
||||
class PluginManager;
|
||||
|
||||
enum class PanelPosition { Left, Right };
|
||||
|
||||
@@ -54,10 +55,7 @@ struct CodeEditorConfig {
|
||||
bool colorPickerSelection{ false };
|
||||
bool colorPreview{ false };
|
||||
bool minimap{ true };
|
||||
bool autoComplete{ true };
|
||||
bool showDocInfo{ true };
|
||||
bool linter{ true };
|
||||
bool formatter{ true };
|
||||
bool hideTabBarOnSingleTab{ true };
|
||||
bool singleClickTreeNavigation{ false };
|
||||
bool syncProjectTreeWithEditor{ true };
|
||||
@@ -109,6 +107,7 @@ struct AppConfig {
|
||||
CodeEditorConfig editor;
|
||||
DocumentConfig doc;
|
||||
TerminalConfig term;
|
||||
std::map<std::string, bool> pluginsConfig;
|
||||
UIConfig ui;
|
||||
IniFile ini;
|
||||
IniFile iniState;
|
||||
@@ -119,13 +118,13 @@ struct AppConfig {
|
||||
void load( const std::string& confPath, std::string& keybindingsPath,
|
||||
std::string& initColorScheme, std::vector<std::string>& recentFiles,
|
||||
std::vector<std::string>& recentFolders, const std::string& resPath,
|
||||
const Float& displayDPI );
|
||||
const Float& displayDPI, PluginManager* pluginManager );
|
||||
|
||||
void save( const std::vector<std::string>& recentFiles,
|
||||
const std::vector<std::string>& recentFolders, const std::string& panelPartition,
|
||||
EE::Window::Window* win, const std::string& colorSchemeName,
|
||||
const SearchBarConfig& searchBarConfig,
|
||||
const GlobalSearchBarConfig& globalSearchBarConfig );
|
||||
const GlobalSearchBarConfig& globalSearchBarConfig, PluginManager* pluginManager );
|
||||
|
||||
void saveProject( std::string projectFolder, UICodeEditorSplitter* editorSplitter,
|
||||
const std::string& configPath, const ProjectDocumentConfig& docConfig );
|
||||
|
||||
@@ -342,6 +342,18 @@ void App::runCommand( const std::string& command ) {
|
||||
}
|
||||
}
|
||||
|
||||
void App::initPluginManager() {
|
||||
mPluginManager = std::make_unique<PluginManager>( mResPath, mPluginsPath, mThreadPool );
|
||||
mPluginManager->onPluginEnabled = [&]( UICodeEditorPlugin* plugin ) {
|
||||
if ( mSplitter )
|
||||
mSplitter->forEachEditor(
|
||||
[&]( UICodeEditor* editor ) { editor->registerPlugin( plugin ); } );
|
||||
};
|
||||
mPluginManager->registerPlugin( LinterPlugin::Definition() );
|
||||
mPluginManager->registerPlugin( FormatterPlugin::Definition() );
|
||||
mPluginManager->registerPlugin( AutoCompletePlugin::Definition() );
|
||||
}
|
||||
|
||||
void App::loadConfig( const LogLevel& logLevel ) {
|
||||
mConfigPath = Sys::getConfigPath( "ecode" );
|
||||
if ( !FileSystem::fileExists( mConfigPath ) )
|
||||
@@ -363,8 +375,10 @@ void App::loadConfig( const LogLevel& logLevel ) {
|
||||
Log::create( mConfigPath + "ecode.log", logLevel, true, true );
|
||||
#endif
|
||||
|
||||
initPluginManager();
|
||||
|
||||
mConfig.load( mConfigPath, mKeybindingsPath, mInitColorScheme, mRecentFiles, mRecentFolders,
|
||||
mResPath, mDisplayDPI );
|
||||
mResPath, mDisplayDPI, mPluginManager.get() );
|
||||
}
|
||||
|
||||
void App::saveConfig() {
|
||||
@@ -373,7 +387,7 @@ void App::saveConfig() {
|
||||
mWindow,
|
||||
mSplitter ? mSplitter->getCurrentColorSchemeName() : mConfig.editor.colorScheme,
|
||||
mDocSearchController->getSearchBarConfig(),
|
||||
mGlobalSearchController->getGlobalSearchBarConfig() );
|
||||
mGlobalSearchController->getGlobalSearchBarConfig(), mPluginManager.get() );
|
||||
}
|
||||
|
||||
static std::string keybindFormat( std::string str ) {
|
||||
@@ -1009,25 +1023,6 @@ UIMenu* App::createViewMenu() {
|
||||
"Enables the color picker tool when a double click selection\n"
|
||||
"is done over a word representing a color." ) )
|
||||
->setId( "enable-color-picker" );
|
||||
mViewMenu->addCheckBox( i18n( "enable_autocomplete", "Enable Auto Complete" ) )
|
||||
->setActive( mConfig.editor.autoComplete )
|
||||
->setTooltipText(
|
||||
i18n( "enable_autocomplete_tooltip",
|
||||
"Auto complete shows the completion popup as you type, so you can fill\n"
|
||||
"in long words by typing only a few characters." ) )
|
||||
->setId( "enable-autocomplete" );
|
||||
mViewMenu->addCheckBox( i18n( "enable_linter", "Enable Linter" ) )
|
||||
->setActive( mConfig.editor.linter )
|
||||
->setTooltipText(
|
||||
i18n( "enable_linter_tooltip",
|
||||
"Use static code analysis tool used to flag programming errors, bugs,\n"
|
||||
"stylistic errors, and suspicious constructs." ) )
|
||||
->setId( "enable-linter" );
|
||||
mViewMenu->addCheckBox( i18n( "enable_code_formatter", "Enable Code Formatter" ) )
|
||||
->setActive( mConfig.editor.formatter )
|
||||
->setTooltipText( i18n( "enable_code_formatter_tooltip",
|
||||
"Enables the code formatter/prettifier plugin." ) )
|
||||
->setId( "enable-code-formatter" );
|
||||
mViewMenu->addCheckBox( i18n( "hide_tabbar_on_single_tab", "Hide tabbar on single tab" ) )
|
||||
->setActive( mConfig.editor.hideTabBarOnSingleTab )
|
||||
->setTooltipText(
|
||||
@@ -1108,12 +1103,6 @@ UIMenu* App::createViewMenu() {
|
||||
mSplitter->forEachEditor( [&]( UICodeEditor* editor ) {
|
||||
editor->setEnableColorPickerOnSelection( mConfig.editor.colorPickerSelection );
|
||||
} );
|
||||
} else if ( item->getId() == "enable-autocomplete" ) {
|
||||
setAutoComplete( item->asType<UIMenuCheckBox>()->isActive() );
|
||||
} else if ( item->getId() == "enable-linter" ) {
|
||||
setLinter( item->asType<UIMenuCheckBox>()->isActive() );
|
||||
} else if ( item->getId() == "enable-code-formatter" ) {
|
||||
setFormatter( item->asType<UIMenuCheckBox>()->isActive() );
|
||||
} else if ( item->getId() == "hide-tabbar-on-single-tab" ) {
|
||||
mConfig.editor.hideTabBarOnSingleTab = item->asType<UIMenuCheckBox>()->isActive();
|
||||
mSplitter->setHideTabBarOnSingleTab( mConfig.editor.hideTabBarOnSingleTab );
|
||||
@@ -1218,6 +1207,16 @@ makeAutoClosePairs( const std::string& strPairs ) {
|
||||
UIMenu* App::createTerminalMenu() {
|
||||
mTerminalMenu = UIPopUpMenu::New();
|
||||
|
||||
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN
|
||||
UIMenuSubMenu* termColorSchemeMenu = mTerminalMenu->addSubMenu(
|
||||
i18n( "terminal_color_scheme", "Terminal Color Scheme" ), findIcon( "palette" ),
|
||||
mTerminalManager->createColorSchemeMenu() );
|
||||
termColorSchemeMenu->addEventListener(
|
||||
Event::OnMenuShow, [&, termColorSchemeMenu]( const Event* ) {
|
||||
mTerminalManager->updateMenuColorScheme( termColorSchemeMenu );
|
||||
} );
|
||||
#endif
|
||||
|
||||
UIMenuCheckBox* exclusiveChk =
|
||||
mTerminalMenu->addCheckBox( i18n( "exclusive_mode", "Exclusive Mode" ), false,
|
||||
getKeybind( UITerminal::getExclusiveModeToggleCommandName() ) );
|
||||
@@ -1787,6 +1786,10 @@ void App::updateTerminalMenu() {
|
||||
->setActive( mSplitter->getCurWidget()->asType<UITerminal>()->getExclusiveMode() );
|
||||
}
|
||||
|
||||
void App::createPluginManagerUI() {
|
||||
UIPluginManager::New( mUISceneNode, mPluginManager.get() )->showWhenReady();
|
||||
}
|
||||
|
||||
void App::updateDocumentMenu() {
|
||||
if ( !mSplitter->getCurWidget() || !mSplitter->getCurWidget()->isType( UI_TYPE_CODEEDITOR ) ) {
|
||||
mSettingsMenu->getItemId( "doc-menu" )->setEnabled( false );
|
||||
@@ -2129,7 +2132,7 @@ std::vector<std::string> App::getUnlockedCommands() {
|
||||
"open-global-search", "menu-toggle", "switch-side-panel",
|
||||
"download-file-web", "create-new-terminal", "terminal-split-left",
|
||||
"terminal-split-right", "terminal-split-top", "terminal-split-bottom",
|
||||
"terminal-split-swap", "reopen-closed-tab" };
|
||||
"terminal-split-swap", "reopen-closed-tab", "plugin-manager" };
|
||||
}
|
||||
|
||||
bool App::isUnlockedCommand( const std::string& command ) {
|
||||
@@ -2428,6 +2431,7 @@ void App::onCodeEditorCreated( UICodeEditor* editor, TextDocument& doc ) {
|
||||
doc.execute( "create-new-terminal" );
|
||||
} );
|
||||
doc.setCommand( "reopen-closed-tab", [&] { reopenClosedTab(); } );
|
||||
doc.setCommand( "plugin-manager", [&] { createPluginManagerUI(); } );
|
||||
|
||||
editor->addEventListener( Event::OnDocumentSave, [&]( const Event* event ) {
|
||||
UICodeEditor* editor = event->getNode()->asType<UICodeEditor>();
|
||||
@@ -2518,68 +2522,7 @@ void App::onCodeEditorCreated( UICodeEditor* editor, TextDocument& doc ) {
|
||||
|
||||
editor->showMinimap( config.minimap );
|
||||
|
||||
if ( config.autoComplete && !mAutoCompletePlugin )
|
||||
setAutoComplete( config.autoComplete );
|
||||
|
||||
if ( config.linter && !mLinterPlugin )
|
||||
setLinter( config.linter );
|
||||
|
||||
if ( config.formatter && !mFormatterPlugin )
|
||||
setFormatter( config.formatter );
|
||||
|
||||
if ( config.autoComplete && mAutoCompletePlugin )
|
||||
editor->registerPlugin( mAutoCompletePlugin );
|
||||
|
||||
if ( config.linter && mLinterPlugin )
|
||||
editor->registerPlugin( mLinterPlugin );
|
||||
|
||||
if ( config.formatter && mFormatterPlugin )
|
||||
editor->registerPlugin( mFormatterPlugin );
|
||||
}
|
||||
|
||||
bool App::setAutoComplete( bool enable ) {
|
||||
mConfig.editor.autoComplete = enable;
|
||||
if ( enable && !mAutoCompletePlugin ) {
|
||||
mAutoCompletePlugin = eeNew( AutoCompletePlugin, ( mThreadPool ) );
|
||||
mSplitter->forEachEditor(
|
||||
[&]( UICodeEditor* editor ) { editor->registerPlugin( mAutoCompletePlugin ); } );
|
||||
return true;
|
||||
}
|
||||
if ( !enable && mAutoCompletePlugin )
|
||||
eeSAFE_DELETE( mAutoCompletePlugin );
|
||||
return false;
|
||||
}
|
||||
|
||||
bool App::setLinter( bool enable ) {
|
||||
mConfig.editor.linter = enable;
|
||||
if ( enable && !mLinterPlugin ) {
|
||||
std::string path( mResPath + "plugins/linters.json" );
|
||||
if ( FileSystem::fileExists( mPluginsPath + "linters.json" ) )
|
||||
path = mPluginsPath + "linters.json";
|
||||
mLinterPlugin = eeNew( LinterPlugin, ( path, mThreadPool ) );
|
||||
mSplitter->forEachEditor(
|
||||
[&]( UICodeEditor* editor ) { editor->registerPlugin( mLinterPlugin ); } );
|
||||
return true;
|
||||
}
|
||||
if ( !enable && mLinterPlugin )
|
||||
eeSAFE_DELETE( mLinterPlugin );
|
||||
return false;
|
||||
}
|
||||
|
||||
bool App::setFormatter( bool enable ) {
|
||||
mConfig.editor.formatter = enable;
|
||||
if ( enable && !mFormatterPlugin ) {
|
||||
std::string path( mResPath + "plugins/formatters.json" );
|
||||
if ( FileSystem::fileExists( mPluginsPath + "formatters.json" ) )
|
||||
path = mPluginsPath + "formatter.json";
|
||||
mFormatterPlugin = eeNew( FormatterPlugin, ( path, mThreadPool ) );
|
||||
mSplitter->forEachEditor(
|
||||
[&]( UICodeEditor* editor ) { editor->registerPlugin( mFormatterPlugin ); } );
|
||||
return true;
|
||||
}
|
||||
if ( !enable && mFormatterPlugin )
|
||||
eeSAFE_DELETE( mFormatterPlugin );
|
||||
return false;
|
||||
mPluginManager->onNewEditor( editor );
|
||||
}
|
||||
|
||||
void App::loadCurrentDirectory() {
|
||||
@@ -2707,8 +2650,8 @@ void App::createSettingsMenu() {
|
||||
getKeybind( "save-all" ) )
|
||||
->setId( "save-all" );
|
||||
mSettingsMenu->addSeparator();
|
||||
UIMenuSubMenu* fileTypeMenu = mSettingsMenu->addSubMenu( i18n( "file_type", "File Type" ),
|
||||
nullptr, createFileTypeMenu() );
|
||||
UIMenuSubMenu* fileTypeMenu = mSettingsMenu->addSubMenu(
|
||||
i18n( "file_type", "File Type" ), findIcon( "file-code" ), createFileTypeMenu() );
|
||||
fileTypeMenu->addEventListener( Event::OnMenuShow, [&, fileTypeMenu]( const Event* ) {
|
||||
if ( mFileTypeMenuesCreatedWithHeight != mUISceneNode->getPixelsSize().getHeight() ) {
|
||||
for ( UIPopUpMenu* menu : mFileTypeMenues )
|
||||
@@ -2719,8 +2662,9 @@ void App::createSettingsMenu() {
|
||||
fileTypeMenu->setSubMenu( newMenu );
|
||||
}
|
||||
} );
|
||||
UIMenuSubMenu* colorSchemeMenu = mSettingsMenu->addSubMenu(
|
||||
i18n( "syntax_color_scheme", "Syntax Color Scheme" ), nullptr, createColorSchemeMenu() );
|
||||
UIMenuSubMenu* colorSchemeMenu =
|
||||
mSettingsMenu->addSubMenu( i18n( "syntax_color_scheme", "Syntax Color Scheme" ),
|
||||
findIcon( "palette" ), createColorSchemeMenu() );
|
||||
colorSchemeMenu->addEventListener( Event::OnMenuShow, [&, colorSchemeMenu]( const Event* ) {
|
||||
if ( mColorSchemeMenuesCreatedWithHeight != mUISceneNode->getPixelsSize().getHeight() ) {
|
||||
for ( UIPopUpMenu* menu : mColorSchemeMenues )
|
||||
@@ -2731,14 +2675,6 @@ void App::createSettingsMenu() {
|
||||
colorSchemeMenu->setSubMenu( newMenu );
|
||||
}
|
||||
} );
|
||||
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN
|
||||
UIMenuSubMenu* termColorSchemeMenu =
|
||||
mSettingsMenu->addSubMenu( i18n( "terminal_color_scheme", "Terminal Color Scheme" ),
|
||||
nullptr, mTerminalManager->createColorSchemeMenu() );
|
||||
colorSchemeMenu->addEventListener( Event::OnMenuShow, [&, termColorSchemeMenu]( const Event* ) {
|
||||
mTerminalManager->updateMenuColorScheme( termColorSchemeMenu );
|
||||
} );
|
||||
#endif
|
||||
mSettingsMenu
|
||||
->addSubMenu( i18n( "document", "Document" ), findIcon( "file" ), createDocumentMenu() )
|
||||
->setId( "doc-menu" );
|
||||
@@ -2749,6 +2685,8 @@ void App::createSettingsMenu() {
|
||||
mSettingsMenu->addSubMenu( i18n( "view", "View" ), nullptr, createViewMenu() );
|
||||
mSettingsMenu->addSubMenu( i18n( "tools", "Tools" ), nullptr, createToolsMenu() );
|
||||
mSettingsMenu->addSubMenu( i18n( "window", "Window" ), nullptr, createWindowMenu() );
|
||||
mSettingsMenu->add( i18n( "plugin_manager", "Plugin Manager" ), findIcon( "package" ) )
|
||||
->setId( "plugin-manager" );
|
||||
mSettingsMenu->addSubMenu( i18n( "help", "Help" ), findIcon( "help" ), createHelpMenu() );
|
||||
mSettingsMenu->addSeparator();
|
||||
mSettingsMenu
|
||||
@@ -3397,13 +3335,6 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe
|
||||
mUseFrameBuffer = frameBuffer;
|
||||
mBenchmarkMode = benchmarkMode;
|
||||
|
||||
loadConfig( logLevel );
|
||||
|
||||
currentDisplay = displayManager->getDisplayIndex( mConfig.windowState.displayIndex <
|
||||
displayManager->getDisplayCount()
|
||||
? mConfig.windowState.displayIndex
|
||||
: 0 );
|
||||
mDisplayDPI = currentDisplay->getDPI();
|
||||
mResPath = Sys::getProcessPath();
|
||||
#if EE_PLATFORM == EE_PLATFORM_MACOSX
|
||||
if ( String::contains( mResPath, "ecode.app" ) ) {
|
||||
@@ -3423,6 +3354,14 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe
|
||||
mResPath += "assets";
|
||||
FileSystem::dirAddSlashAtEnd( mResPath );
|
||||
|
||||
loadConfig( logLevel );
|
||||
|
||||
currentDisplay = displayManager->getDisplayIndex( mConfig.windowState.displayIndex <
|
||||
displayManager->getDisplayCount()
|
||||
? mConfig.windowState.displayIndex
|
||||
: 0 );
|
||||
mDisplayDPI = currentDisplay->getDPI();
|
||||
|
||||
mConfig.windowState.pixelDensity =
|
||||
pidelDensity > 0
|
||||
? pidelDensity
|
||||
@@ -3790,6 +3729,8 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe
|
||||
{ "arrow-down-s", 0xea4e },
|
||||
{ "arrow-right-s", 0xea6e },
|
||||
{ "match-case", 0xed8d },
|
||||
{ "palette", 0xefc5 },
|
||||
{ "file-code", 0xecd1 },
|
||||
};
|
||||
for ( const auto& icon : icons )
|
||||
iconTheme->add( UIGlyphIcon::New( icon.first, iconFont, icon.second ) );
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "filesystemlistener.hpp"
|
||||
#include "globalsearchcontroller.hpp"
|
||||
#include "notificationcenter.hpp"
|
||||
#include "plugins/pluginmanager.hpp"
|
||||
#include "projectdirectorytree.hpp"
|
||||
#include "terminalmanager.hpp"
|
||||
#include <eepp/ee.hpp>
|
||||
@@ -144,6 +145,8 @@ class App : public UICodeEditorSplitter::Client {
|
||||
|
||||
void updateTerminalMenu();
|
||||
|
||||
void createPluginManagerUI();
|
||||
|
||||
protected:
|
||||
EE::Window::Window* mWindow{ nullptr };
|
||||
UISceneNode* mUISceneNode{ nullptr };
|
||||
@@ -220,6 +223,7 @@ class App : public UICodeEditorSplitter::Client {
|
||||
std::string mLastFileFolder;
|
||||
ColorSchemePreference mUIColorScheme;
|
||||
std::unique_ptr<TerminalManager> mTerminalManager;
|
||||
std::unique_ptr<PluginManager> mPluginManager;
|
||||
|
||||
void saveAllProcess();
|
||||
|
||||
@@ -305,12 +309,6 @@ class App : public UICodeEditorSplitter::Client {
|
||||
|
||||
void onCodeEditorFocusChange( UICodeEditor* editor );
|
||||
|
||||
bool setAutoComplete( bool enable );
|
||||
|
||||
bool setLinter( bool enable );
|
||||
|
||||
bool setFormatter( bool enable );
|
||||
|
||||
void updateDocInfo( TextDocument& doc );
|
||||
|
||||
void setFocusEditorOnClose( UIMessageBox* msgBox );
|
||||
@@ -345,6 +343,8 @@ class App : public UICodeEditorSplitter::Client {
|
||||
UIMessageBox* fileAlreadyExistsMsgBox();
|
||||
|
||||
void renameFile( const FileInfo& file );
|
||||
|
||||
void initPluginManager();
|
||||
};
|
||||
|
||||
} // namespace ecode
|
||||
|
||||
@@ -203,6 +203,11 @@ bool GitIgnoreMatcher::match( const std::string& value ) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
IgnoreMatcherManager::IgnoreMatcherManager( IgnoreMatcherManager&& ignoreMatcher ) :
|
||||
mMatchers( ignoreMatcher.mMatchers ) {
|
||||
ignoreMatcher.mMatchers.clear();
|
||||
}
|
||||
|
||||
IgnoreMatcherManager::IgnoreMatcherManager( std::string rootPath ) {
|
||||
FileSystem::dirAddSlashAtEnd( rootPath );
|
||||
GitIgnoreMatcher git( rootPath );
|
||||
@@ -210,6 +215,12 @@ IgnoreMatcherManager::IgnoreMatcherManager( std::string rootPath ) {
|
||||
mMatchers.emplace_back( eeNew( GitIgnoreMatcher, ( rootPath ) ) );
|
||||
}
|
||||
|
||||
IgnoreMatcherManager& IgnoreMatcherManager::operator=( IgnoreMatcherManager&& other ) {
|
||||
mMatchers = other.mMatchers;
|
||||
other.mMatchers.clear();
|
||||
return *this;
|
||||
}
|
||||
|
||||
IgnoreMatcherManager::~IgnoreMatcherManager() {
|
||||
for ( size_t i = 0; i < mMatchers.size(); ++i )
|
||||
eeDelete( mMatchers[i] );
|
||||
|
||||
@@ -45,8 +45,12 @@ class GitIgnoreMatcher : public IgnoreMatcher {
|
||||
|
||||
class IgnoreMatcherManager {
|
||||
public:
|
||||
IgnoreMatcherManager( IgnoreMatcherManager&& ignoreMatcher );
|
||||
|
||||
IgnoreMatcherManager( std::string rootPath );
|
||||
|
||||
IgnoreMatcherManager& operator=( IgnoreMatcherManager&& other );
|
||||
|
||||
virtual ~IgnoreMatcherManager();
|
||||
|
||||
bool foundMatch() const;
|
||||
|
||||
@@ -15,20 +15,15 @@ namespace ecode {
|
||||
#define AUTO_COMPLETE_THREADED 0
|
||||
#endif
|
||||
|
||||
AutoCompletePlugin::AutoCompletePlugin() :
|
||||
#if AUTO_COMPLETE_THREADED
|
||||
AutoCompletePlugin( ThreadPool::createShared( eemin<int>( 2, Sys::getCPUCount() ) ) )
|
||||
#else
|
||||
AutoCompletePlugin( nullptr )
|
||||
#endif
|
||||
{
|
||||
UICodeEditorPlugin* AutoCompletePlugin::New( const PluginManager* pluginManager ) {
|
||||
return eeNew( AutoCompletePlugin, ( pluginManager ) );
|
||||
}
|
||||
|
||||
AutoCompletePlugin::AutoCompletePlugin( std::shared_ptr<ThreadPool> pool ) :
|
||||
AutoCompletePlugin::AutoCompletePlugin( const PluginManager* pluginManager ) :
|
||||
mSymbolPattern( "[%a_ñàáâãäåèéêëìíîïòóôõöùúûüýÿÑÀÁÂÃÄÅÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝ][%w_"
|
||||
"ñàáâãäåèéêëìíîïòóôõöùúûüýÿÑÀÁÂÃÄÅÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝ]*" ),
|
||||
mBoxPadding( PixelDensity::dpToPx( Rectf( 4, 4, 4, 4 ) ) ),
|
||||
mPool( pool ) {}
|
||||
mPool( pluginManager->getThreadPool() ) {}
|
||||
|
||||
AutoCompletePlugin::~AutoCompletePlugin() {
|
||||
mClosing = true;
|
||||
@@ -478,4 +473,4 @@ void AutoCompletePlugin::updateSuggestions( const std::string& symbol, UICodeEdi
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace ecode
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef ECODE_AUTOCOMPLETEPLUGIN_HPP
|
||||
#define ECODE_AUTOCOMPLETEPLUGIN_HPP
|
||||
|
||||
#include "../pluginmanager.hpp"
|
||||
#include <eepp/config.hpp>
|
||||
#include <eepp/system/clock.hpp>
|
||||
#include <eepp/system/mutex.hpp>
|
||||
@@ -18,18 +19,22 @@ class AutoCompletePlugin : public UICodeEditorPlugin {
|
||||
public:
|
||||
typedef std::unordered_set<std::string> SymbolsList;
|
||||
|
||||
AutoCompletePlugin();
|
||||
static PluginDefinition Definition() {
|
||||
return { "autocomplete", "Auto Complete",
|
||||
"Auto complete shows the completion popup as you type, so you can fill\n"
|
||||
"in long words by typing only a few characters.",
|
||||
AutoCompletePlugin::New };
|
||||
}
|
||||
|
||||
AutoCompletePlugin( std::shared_ptr<ThreadPool> pool );
|
||||
static UICodeEditorPlugin* New( const PluginManager* pluginManager );
|
||||
|
||||
virtual ~AutoCompletePlugin();
|
||||
|
||||
std::string getTitle() { return "Auto Complete"; }
|
||||
std::string getId() { return Definition().id; }
|
||||
|
||||
std::string getDescription() {
|
||||
return "Auto complete shows the completion popup as you type, so you can fill\n"
|
||||
"in long words by typing only a few characters.";
|
||||
}
|
||||
std::string getTitle() { return Definition().name; }
|
||||
|
||||
std::string getDescription() { return Definition().description; }
|
||||
|
||||
void onRegister( UICodeEditor* );
|
||||
void onUnregister( UICodeEditor* );
|
||||
@@ -96,6 +101,8 @@ class AutoCompletePlugin : public UICodeEditorPlugin {
|
||||
Float mRowHeight{ 0 };
|
||||
Rectf mBoxRect;
|
||||
|
||||
AutoCompletePlugin( const PluginManager* pluginManager );
|
||||
|
||||
void resetSuggestions( UICodeEditor* editor );
|
||||
|
||||
void updateSuggestions( const std::string& symbol, UICodeEditor* editor );
|
||||
@@ -114,6 +121,6 @@ class AutoCompletePlugin : public UICodeEditorPlugin {
|
||||
void pickSuggestion( UICodeEditor* editor );
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace ecode
|
||||
|
||||
#endif // ECODE_AUTOCOMPLETEPLUGIN_HPP
|
||||
|
||||
@@ -22,11 +22,14 @@ namespace ecode {
|
||||
#define FORMATTER_THREADED 0
|
||||
#endif
|
||||
|
||||
FormatterPlugin::FormatterPlugin( const std::string& formattersPath,
|
||||
std::shared_ptr<ThreadPool> pool ) :
|
||||
mPool( pool ) {
|
||||
UICodeEditorPlugin* FormatterPlugin::New( const PluginManager* pluginManager ) {
|
||||
return eeNew( FormatterPlugin, ( pluginManager ) );
|
||||
}
|
||||
|
||||
FormatterPlugin::FormatterPlugin( const PluginManager* pluginManager ) :
|
||||
mPool( pluginManager->getThreadPool() ) {
|
||||
#if FORMATTER_THREADED
|
||||
mPool->run( [&, formattersPath] { load( formattersPath ); }, [] {} );
|
||||
mPool->run( [&, pluginManager] { load( pluginManager ); }, [] {} );
|
||||
#else
|
||||
load( formattersPath );
|
||||
#endif
|
||||
@@ -84,13 +87,16 @@ void FormatterPlugin::unregisterNativeFormatter( const std::string& cmd ) {
|
||||
mNativeFormatters.erase( cmd );
|
||||
}
|
||||
|
||||
void FormatterPlugin::load( const std::string& formatterPath ) {
|
||||
void FormatterPlugin::load( const PluginManager* pluginManager ) {
|
||||
registerNativeFormatters();
|
||||
|
||||
if ( !FileSystem::fileExists( formatterPath ) )
|
||||
std::string path( pluginManager->getResourcesPath() + "plugins/formatters.json" );
|
||||
if ( FileSystem::fileExists( pluginManager->getPluginsPath() + "formatters.json" ) )
|
||||
path = pluginManager->getPluginsPath() + "formatter.json";
|
||||
if ( !FileSystem::fileExists( path ) )
|
||||
return;
|
||||
try {
|
||||
std::ifstream stream( formatterPath );
|
||||
std::ifstream stream( path );
|
||||
json j;
|
||||
stream >> j;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef ECODE_FORMATTERPLUGIN_HPP
|
||||
#define ECODE_FORMATTERPLUGIN_HPP
|
||||
|
||||
#include "../pluginmanager.hpp"
|
||||
#include <eepp/config.hpp>
|
||||
#include <eepp/system/mutex.hpp>
|
||||
#include <eepp/system/threadpool.hpp>
|
||||
@@ -20,13 +21,20 @@ class FormatterPlugin : public UICodeEditorPlugin {
|
||||
std::string err;
|
||||
};
|
||||
|
||||
FormatterPlugin( const std::string& formatterPath, std::shared_ptr<ThreadPool> pool );
|
||||
static PluginDefinition Definition() {
|
||||
return { "autoformatter", "Auto Formatter", "Enables the code formatter/prettifier plugin.",
|
||||
FormatterPlugin::New };
|
||||
}
|
||||
|
||||
static UICodeEditorPlugin* New( const PluginManager* pluginManager );
|
||||
|
||||
virtual ~FormatterPlugin();
|
||||
|
||||
std::string getTitle() { return "Auto Formatter"; }
|
||||
std::string getId() { return Definition().id; }
|
||||
|
||||
std::string getDescription() { return "Enables the code formatter/prettifier plugin."; }
|
||||
std::string getTitle() { return Definition().name; }
|
||||
|
||||
std::string getDescription() { return Definition().description; }
|
||||
|
||||
void onRegister( UICodeEditor* );
|
||||
|
||||
@@ -41,6 +49,7 @@ class FormatterPlugin : public UICodeEditorPlugin {
|
||||
const std::function<NativeFormatterResult( const std::string& file )>& nativeFormatter );
|
||||
|
||||
void unregisterNativeFormatter( const std::string& cmd );
|
||||
|
||||
protected:
|
||||
enum class FormatterType { Inplace, Output, Native };
|
||||
|
||||
@@ -63,7 +72,9 @@ class FormatterPlugin : public UICodeEditorPlugin {
|
||||
bool mShuttingDown{ false };
|
||||
bool mReady{ false };
|
||||
|
||||
void load( const std::string& formatterPath );
|
||||
FormatterPlugin( const PluginManager* pluginManager );
|
||||
|
||||
void load( const PluginManager* pluginManager );
|
||||
|
||||
void formatDoc( UICodeEditor* editor );
|
||||
|
||||
|
||||
@@ -22,10 +22,14 @@ namespace ecode {
|
||||
#define LINTER_THREADED 0
|
||||
#endif
|
||||
|
||||
LinterPlugin::LinterPlugin( const std::string& lintersPath, std::shared_ptr<ThreadPool> pool ) :
|
||||
mPool( pool ) {
|
||||
UICodeEditorPlugin* LinterPlugin::New( const PluginManager* pluginManager ) {
|
||||
return eeNew( LinterPlugin, ( pluginManager ) );
|
||||
}
|
||||
|
||||
LinterPlugin::LinterPlugin( const PluginManager* pluginManager ) :
|
||||
mPool( pluginManager->getThreadPool() ) {
|
||||
#if LINTER_THREADED
|
||||
mPool->run( [&, lintersPath] { load( lintersPath ); }, [] {} );
|
||||
mPool->run( [&, pluginManager] { load( pluginManager ); }, [] {} );
|
||||
#else
|
||||
load( lintersPath );
|
||||
#endif
|
||||
@@ -46,11 +50,14 @@ LinterPlugin::~LinterPlugin() {
|
||||
}
|
||||
}
|
||||
|
||||
void LinterPlugin::load( const std::string& lintersPath ) {
|
||||
if ( !FileSystem::fileExists( lintersPath ) )
|
||||
void LinterPlugin::load( const PluginManager* pluginManager ) {
|
||||
std::string path( pluginManager->getResourcesPath() + "plugins/linters.json" );
|
||||
if ( FileSystem::fileExists( pluginManager->getPluginsPath() + "linters.json" ) )
|
||||
path = pluginManager->getPluginsPath() + "linters.json";
|
||||
if ( !FileSystem::fileExists( path ) )
|
||||
return;
|
||||
try {
|
||||
std::ifstream stream( lintersPath );
|
||||
std::ifstream stream( path );
|
||||
json j;
|
||||
stream >> j;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef ECODE_LINTERPLUGIN_HPP
|
||||
#define ECODE_LINTERPLUGIN_HPP
|
||||
|
||||
#include "../pluginmanager.hpp"
|
||||
#include <eepp/config.hpp>
|
||||
#include <eepp/system/mutex.hpp>
|
||||
#include <eepp/system/threadpool.hpp>
|
||||
@@ -43,16 +44,21 @@ struct LinterMatch {
|
||||
|
||||
class LinterPlugin : public UICodeEditorPlugin {
|
||||
public:
|
||||
LinterPlugin( const std::string& lintersPath, std::shared_ptr<ThreadPool> pool );
|
||||
static PluginDefinition Definition() {
|
||||
return { "linter", "Linter",
|
||||
"Use static code analysis tool used to flag programming errors, bugs,\n"
|
||||
"stylistic errors, and suspicious constructs.",
|
||||
LinterPlugin::New };
|
||||
}
|
||||
static UICodeEditorPlugin* New( const PluginManager* pluginManager );
|
||||
|
||||
virtual ~LinterPlugin();
|
||||
|
||||
std::string getTitle() { return "Linter"; }
|
||||
std::string getId() { return Definition().id; }
|
||||
|
||||
std::string getDescription() {
|
||||
return "Use static code analysis tool used to flag programming errors, bugs,\n"
|
||||
"stylistic errors, and suspicious constructs.";
|
||||
}
|
||||
std::string getTitle() { return Definition().name; }
|
||||
|
||||
std::string getDescription() { return Definition().description; }
|
||||
|
||||
void onRegister( UICodeEditor* );
|
||||
|
||||
@@ -92,7 +98,9 @@ class LinterPlugin : public UICodeEditorPlugin {
|
||||
bool mReady{ false };
|
||||
bool mShuttingDown{ false };
|
||||
|
||||
void load( const std::string& lintersPath );
|
||||
LinterPlugin( const PluginManager* pluginManager );
|
||||
|
||||
void load( const PluginManager* pluginManager );
|
||||
|
||||
void lintDoc( std::shared_ptr<TextDocument> doc );
|
||||
|
||||
|
||||
194
src/tools/ecode/plugins/pluginmanager.cpp
Normal file
194
src/tools/ecode/plugins/pluginmanager.cpp
Normal file
@@ -0,0 +1,194 @@
|
||||
#include "pluginmanager.hpp"
|
||||
#include <eepp/ui/uitableview.hpp>
|
||||
|
||||
namespace ecode {
|
||||
|
||||
PluginManager::PluginManager( const std::string& resourcesPath, const std::string& pluginsPath,
|
||||
std::shared_ptr<ThreadPool> pool ) :
|
||||
mResourcesPath( resourcesPath ), mPluginsPath( pluginsPath ), mThreadPool( pool ) {}
|
||||
|
||||
PluginManager::~PluginManager() {
|
||||
for ( auto& plugin : mPlugins )
|
||||
eeDelete( plugin.second );
|
||||
}
|
||||
|
||||
void PluginManager::registerPlugin( const PluginDefinition& def ) {
|
||||
mDefinitions[def.id] = def;
|
||||
}
|
||||
|
||||
UICodeEditorPlugin* ecode::PluginManager::get( const std::string& id ) {
|
||||
auto findIt = mPlugins.find( id );
|
||||
if ( findIt != mPlugins.end() )
|
||||
return findIt->second;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool PluginManager::setEnabled( const std::string& id, bool enable ) {
|
||||
mPluginsEnabled[id] = enable;
|
||||
UICodeEditorPlugin* plugin = get( id );
|
||||
if ( enable && plugin == nullptr && hasDefinition( id ) ) {
|
||||
UICodeEditorPlugin* newPlugin = mDefinitions[id].creatorFn( this );
|
||||
mPlugins.insert( std::pair<std::string, UICodeEditorPlugin*>( id, newPlugin ) );
|
||||
if ( onPluginEnabled )
|
||||
onPluginEnabled( newPlugin );
|
||||
return true;
|
||||
}
|
||||
if ( !enable && plugin != nullptr ) {
|
||||
eeSAFE_DELETE( plugin );
|
||||
mPlugins.erase( id );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PluginManager::isEnabled( const std::string& id ) const {
|
||||
return mPluginsEnabled.find( id ) != mPluginsEnabled.end() ? mPluginsEnabled.at( id ) : false;
|
||||
}
|
||||
|
||||
const std::string& PluginManager::getResourcesPath() const {
|
||||
return mResourcesPath;
|
||||
}
|
||||
|
||||
const std::string& PluginManager::getPluginsPath() const {
|
||||
return mPluginsPath;
|
||||
}
|
||||
|
||||
const std::map<std::string, bool>& PluginManager::getPluginsEnabled() const {
|
||||
return mPluginsEnabled;
|
||||
}
|
||||
|
||||
void PluginManager::onNewEditor( UICodeEditor* editor ) {
|
||||
for ( auto& plugin : mPlugins )
|
||||
editor->registerPlugin( plugin.second );
|
||||
}
|
||||
|
||||
void PluginManager::setPluginsEnabled( const std::map<std::string, bool>& pluginsEnabled ) {
|
||||
mPluginsEnabled = pluginsEnabled;
|
||||
for ( const auto& plugin : pluginsEnabled ) {
|
||||
if ( plugin.second && get( plugin.first ) == nullptr )
|
||||
setEnabled( plugin.first, true );
|
||||
}
|
||||
}
|
||||
|
||||
const std::shared_ptr<ThreadPool>& PluginManager::getThreadPool() const {
|
||||
return mThreadPool;
|
||||
}
|
||||
|
||||
const std::map<std::string, PluginDefinition>& PluginManager::getDefinitions() const {
|
||||
return mDefinitions;
|
||||
}
|
||||
|
||||
const PluginDefinition* PluginManager::getDefinitionIndex( const Int64& index ) const {
|
||||
const PluginDefinition* def = nullptr;
|
||||
Int64 i = 0;
|
||||
for ( const auto& curDef : mDefinitions ) {
|
||||
if ( index == i )
|
||||
def = &curDef.second;
|
||||
++i;
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
bool PluginManager::hasDefinition( const std::string& id ) {
|
||||
return mDefinitions.find( id ) != mDefinitions.end();
|
||||
}
|
||||
|
||||
std::shared_ptr<PluginsModel> PluginsModel::create( PluginManager* manager ) {
|
||||
return std::make_shared<PluginsModel>( manager );
|
||||
}
|
||||
|
||||
size_t PluginsModel::rowCount( const ModelIndex& ) const {
|
||||
return mManager->getDefinitions().size();
|
||||
}
|
||||
|
||||
std::string PluginsModel::columnName( const size_t& col ) const {
|
||||
eeASSERT( col < mColumnNames.size() );
|
||||
return mColumnNames[col];
|
||||
}
|
||||
|
||||
Variant PluginsModel::data( const ModelIndex& index, ModelRole role ) const {
|
||||
if ( role == ModelRole::Display ) {
|
||||
const PluginDefinition* def = mManager->getDefinitionIndex( index.row() );
|
||||
if ( def == nullptr )
|
||||
return {};
|
||||
switch ( index.column() ) {
|
||||
case Columns::Version:
|
||||
return Variant( def->versionString.c_str() );
|
||||
case Columns::Description:
|
||||
return Variant( def->description.c_str() );
|
||||
case Columns::Title:
|
||||
return Variant( def->name.c_str() );
|
||||
case Columns::Id:
|
||||
return Variant( def->id.c_str() );
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
UIWindow* UIPluginManager::New( UISceneNode* sceneNode, PluginManager* manager ) {
|
||||
UIWindow* win = sceneNode
|
||||
->loadLayoutFromString( R"xml(
|
||||
<window
|
||||
id="plugin-manager-window"
|
||||
lw="800dp" lh="400dp"
|
||||
padding="8dp"
|
||||
window-title="Plugin Manager"
|
||||
window-flags="default|maximize|shadow"
|
||||
window-min-size="300dp 300dp">
|
||||
<vbox lw="mp" lh="mp">
|
||||
<tableview id="plugin-manager-table" lw="mp" lh="fixed" layout_weight="1">
|
||||
</tableview>
|
||||
<vbox lw="mp" lh="wc">
|
||||
<hbox margin-top="4dp" layout-gravity="right">
|
||||
<pushbutton id="plugin-manager-enabled" enabled="false" />
|
||||
<!-- <pushbutton id="plugin-manager-preferences" enabled="false" text="Enabled" /> -->
|
||||
<pushbutton id="plugin-manager-close" text="Close" icon="close" margin-left="4dp" />
|
||||
</hbox>
|
||||
</vbox>
|
||||
</vbox>
|
||||
</window>
|
||||
)xml" )
|
||||
->asType<UIWindow>();
|
||||
UIWidget* cont = win->getContainer();
|
||||
UIPushButton* enable = cont->find<UIPushButton>( "plugin-manager-enabled" );
|
||||
UIPushButton* close = cont->find<UIPushButton>( "plugin-manager-close" );
|
||||
UITableView* tv = win->getContainer()->find<UITableView>( "plugin-manager-table" );
|
||||
close->addEventListener( Event::MouseClick, [win]( const Event* event ) {
|
||||
const MouseEvent* mevent = static_cast<const MouseEvent*>( event );
|
||||
if ( mevent->getFlags() & EE_BUTTON_LMASK )
|
||||
win->closeWindow();
|
||||
} );
|
||||
|
||||
win->setTitle( sceneNode->i18n( "plugin_manager", "Plugin Manager" ) );
|
||||
enable->setText( sceneNode->i18n( "enable", "Select a Plugin" ) );
|
||||
|
||||
auto updateButtonsState = [sceneNode, enable, manager]( const ModelIndex& index ) {
|
||||
const PluginDefinition* def = manager->getDefinitionIndex( index.row() );
|
||||
if ( def == nullptr )
|
||||
return;
|
||||
enable->setEnabled( true );
|
||||
enable->setText( manager->isEnabled( def->id ) ? sceneNode->i18n( "disable", "Disable" )
|
||||
: sceneNode->i18n( "enable", "Enable" ) );
|
||||
};
|
||||
enable->addEventListener(
|
||||
Event::MouseClick, [updateButtonsState, tv, manager]( const Event* event ) {
|
||||
const MouseEvent* mevent = static_cast<const MouseEvent*>( event );
|
||||
if ( mevent->getFlags() & EE_BUTTON_LMASK && !tv->getSelection().isEmpty() ) {
|
||||
const PluginDefinition* def =
|
||||
manager->getDefinitionIndex( tv->getSelection().first().row() );
|
||||
if ( def == nullptr )
|
||||
return;
|
||||
manager->setEnabled( def->id, !manager->isEnabled( def->id ) );
|
||||
updateButtonsState( tv->getSelection().first() );
|
||||
}
|
||||
} );
|
||||
tv->setOnSelection( updateButtonsState );
|
||||
tv->setModel( PluginsModel::create( manager ) );
|
||||
tv->setColumnsVisible(
|
||||
{ PluginsModel::Title, PluginsModel::Description, PluginsModel::Version } );
|
||||
tv->setAutoColumnsWidth( true );
|
||||
tv->setRowHeight( PixelDensity::dpToPx( 64 ) );
|
||||
win->center();
|
||||
return win;
|
||||
}
|
||||
|
||||
} // namespace ecode
|
||||
112
src/tools/ecode/plugins/pluginmanager.hpp
Normal file
112
src/tools/ecode/plugins/pluginmanager.hpp
Normal file
@@ -0,0 +1,112 @@
|
||||
#ifndef ECODE_PLUGINMANAGER_HPP
|
||||
#define ECODE_PLUGINMANAGER_HPP
|
||||
|
||||
#include <eepp/ui/models/model.hpp>
|
||||
#include <eepp/ui/uicodeeditor.hpp>
|
||||
#include <eepp/ui/uiscenenode.hpp>
|
||||
#include <eepp/ui/uiwindow.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
using namespace EE;
|
||||
using namespace EE::System;
|
||||
using namespace EE::UI;
|
||||
using namespace EE::UI::Models;
|
||||
|
||||
namespace ecode {
|
||||
|
||||
class PluginManager;
|
||||
|
||||
typedef std::function<UICodeEditorPlugin*( const PluginManager* pluginManager )> PluginCreatorFn;
|
||||
|
||||
struct PluginDefinition {
|
||||
std::string id;
|
||||
std::string name;
|
||||
std::string description;
|
||||
PluginCreatorFn creatorFn;
|
||||
int versionNumber{ 0 };
|
||||
std::string versionString{ "0" };
|
||||
};
|
||||
|
||||
class PluginManager {
|
||||
public:
|
||||
PluginManager( const std::string& resourcesPath, const std::string& pluginsPath,
|
||||
std::shared_ptr<ThreadPool> pool );
|
||||
|
||||
~PluginManager();
|
||||
|
||||
void registerPlugin( const PluginDefinition& def );
|
||||
|
||||
UICodeEditorPlugin* get( const std::string& id );
|
||||
|
||||
bool setEnabled( const std::string& id, bool enable );
|
||||
|
||||
bool isEnabled( const std::string& id ) const;
|
||||
|
||||
const std::string& getResourcesPath() const;
|
||||
|
||||
const std::string& getPluginsPath() const;
|
||||
|
||||
const std::map<std::string, bool>& getPluginsEnabled() const;
|
||||
|
||||
void onNewEditor( UICodeEditor* editor );
|
||||
|
||||
void setPluginsEnabled( const std::map<std::string, bool>& pluginsEnabled );
|
||||
|
||||
const std::shared_ptr<ThreadPool>& getThreadPool() const;
|
||||
|
||||
std::function<void( UICodeEditorPlugin* )> onPluginEnabled;
|
||||
|
||||
const std::map<std::string, PluginDefinition>& getDefinitions() const;
|
||||
|
||||
const PluginDefinition* getDefinitionIndex( const Int64& index ) const;
|
||||
|
||||
protected:
|
||||
std::string mResourcesPath;
|
||||
std::string mPluginsPath;
|
||||
std::map<std::string, UICodeEditorPlugin*> mPlugins;
|
||||
std::map<std::string, bool> mPluginsEnabled;
|
||||
std::map<std::string, PluginDefinition> mDefinitions;
|
||||
std::shared_ptr<ThreadPool> mThreadPool;
|
||||
|
||||
bool hasDefinition( const std::string& id );
|
||||
};
|
||||
|
||||
class PluginsModel : public Model {
|
||||
public:
|
||||
enum Columns { Id, Enabled, Title, Description, Version };
|
||||
|
||||
static std::shared_ptr<PluginsModel> create( PluginManager* manager );
|
||||
|
||||
PluginsModel( PluginManager* manager ) : mManager( manager ) {}
|
||||
|
||||
virtual ~PluginsModel() {}
|
||||
|
||||
virtual size_t rowCount( const ModelIndex& ) const;
|
||||
|
||||
virtual size_t columnCount( const ModelIndex& ) const { return mColumnNames.size(); }
|
||||
|
||||
virtual std::string columnName( const size_t& col ) const;
|
||||
|
||||
virtual void setColumnName( const size_t& index, const std::string& name ) {
|
||||
eeASSERT( index <= Columns::Version );
|
||||
mColumnNames[index] = name;
|
||||
}
|
||||
|
||||
virtual Variant data( const ModelIndex& index, ModelRole role = ModelRole::Display ) const;
|
||||
|
||||
virtual void update() { onModelUpdate(); }
|
||||
|
||||
protected:
|
||||
PluginManager* mManager;
|
||||
std::vector<std::string> mColumnNames{ "Id", "Enabled", "Title", "Description", "Version" };
|
||||
};
|
||||
|
||||
class UIPluginManager {
|
||||
public:
|
||||
static UIWindow* New( UISceneNode* sceneNode, PluginManager* manager );
|
||||
};
|
||||
|
||||
} // namespace ecode
|
||||
|
||||
#endif // ECODE_PLUGINMANAGER_HPP
|
||||
@@ -344,6 +344,7 @@ UITerminal* TerminalManager::createNewTerminal( const std::string& title, UITabW
|
||||
: mTerminalColorSchemes.begin()->first );
|
||||
} );
|
||||
term->setCommand( "reopen-closed-tab", [&] { mApp->reopenClosedTab(); } );
|
||||
term->setCommand( "plugin-manager", [&] { mApp->createPluginManagerUI(); } );
|
||||
// debug-draw-highlight-toggle
|
||||
// debug-draw-boxes-toggle
|
||||
// debug-draw-debug-data
|
||||
|
||||
Reference in New Issue
Block a user