• Fixed the keybinding merge bug. The helper was restoring missing default commands

by overwriting an occupied default shortcut, which treated user bindings like mod+d=duplicate-line-or-selection as stale
  because that command is not in the default keybinding table. Now it only adds a default when the default shortcut is actually
  free.

  Added a regression test in src/tests/unit_tests/uicodeeditor_tests.cpp:108 covering the reported case: mod+d reassigned, then
  an extra mod+e=show-markdown-preview binding exists. This was reported in SpartanJ/ecode#914.

• Implemented the splitter-level focus state cache, it will remember closed documents cursor state when reopened and it will restore cursor state per-code editor and not per-document (SpartanJ/ecode#893).
This commit is contained in:
Martín Lucas Golini
2026-06-25 11:26:31 -03:00
parent 0693688f73
commit e720b70863
9 changed files with 172 additions and 53 deletions
@@ -9,6 +9,7 @@
#include <eepp/ui/uitabwidget.hpp> #include <eepp/ui/uitabwidget.hpp>
#include <eepp/system/log.hpp> #include <eepp/system/log.hpp>
#include <unordered_map>
using namespace EE::UI::Doc; using namespace EE::UI::Doc;
@@ -387,6 +388,10 @@ class EE_API UICodeEditorSplitter {
bool openDocumentsInMainSplit() const { return mOpenDocumentsInMainSplit; } bool openDocumentsInMainSplit() const { return mOpenDocumentsInMainSplit; }
void setRestoreEditorSelectionOnFocus( bool restore );
bool getRestoreEditorSelectionOnFocus() const { return mRestoreEditorSelectionOnFocus; }
UITabWidget* getFirstTabWidget() const; UITabWidget* getFirstTabWidget() const;
UITabWidget* getPreferredTabWidget() const; UITabWidget* getPreferredTabWidget() const;
@@ -413,6 +418,7 @@ class EE_API UICodeEditorSplitter {
bool mFirstCodeEditor{ true }; bool mFirstCodeEditor{ true };
bool mVisualSplitting{ true }; bool mVisualSplitting{ true };
bool mOpenDocumentsInMainSplit{ false }; bool mOpenDocumentsInMainSplit{ false };
bool mRestoreEditorSelectionOnFocus{ true };
UICodeEditor* mAboutToAddEditor{ nullptr }; UICodeEditor* mAboutToAddEditor{ nullptr };
UIMessageBox* mTryCloseMsgBox{ nullptr }; UIMessageBox* mTryCloseMsgBox{ nullptr };
Mutex mTabWidgetMutex; Mutex mTabWidgetMutex;
@@ -424,6 +430,7 @@ class EE_API UICodeEditorSplitter {
size_t mNavigationHistoryMaxSize{ 100 }; size_t mNavigationHistoryMaxSize{ 100 };
std::vector<NavigationRecord> mNavigationHistory; std::vector<NavigationRecord> mNavigationHistory;
size_t mNavigationHistoryPos{ std::numeric_limits<size_t>::max() }; size_t mNavigationHistoryPos{ std::numeric_limits<size_t>::max() };
std::unordered_map<UICodeEditor*, TextRanges> mEditorSelections;
std::function<void( UITabWidget* )> mOnTabWidgetCreateCb; std::function<void( UITabWidget* )> mOnTabWidgetCreateCb;
Float mVisualSplitEdgePercent{ 0.1 }; Float mVisualSplitEdgePercent{ 0.1 };
TabTryCloseCallback mTabTryCloseCb; TabTryCloseCallback mTabTryCloseCb;
@@ -436,6 +443,10 @@ class EE_API UICodeEditorSplitter {
virtual void onTabClosed( const TabEvent* tabEvent ); virtual void onTabClosed( const TabEvent* tabEvent );
void saveEditorSelection( UICodeEditor* editor );
void restoreEditorSelection( UICodeEditor* editor );
void closeAllTabs( std::vector<UITab*> tabs, UITabWidget::FocusTabBehavior focusTabBehavior ); void closeAllTabs( std::vector<UITab*> tabs, UITabWidget::FocusTabBehavior focusTabBehavior );
UITabWidget* createTabWidget( Node* parent ); UITabWidget* createTabWidget( Node* parent );
+49 -3
View File
@@ -257,7 +257,18 @@ UICodeEditor* UICodeEditorSplitter::createCodeEditor() {
/* Splitter commands */ /* Splitter commands */
editor->on( Event::OnFocus, [this]( const Event* event ) { editor->on( Event::OnFocus, [this]( const Event* event ) {
setCurrentWidget( event->getNode()->asType<UICodeEditor>() ); UICodeEditor* editor = event->getNode()->asType<UICodeEditor>();
UICodeEditor* prevEditor = mCurEditor;
if ( mRestoreEditorSelectionOnFocus && prevEditor && prevEditor != editor &&
!prevEditor->hasFocus() )
saveEditorSelection( prevEditor );
setCurrentWidget( editor );
if ( mRestoreEditorSelectionOnFocus && prevEditor && prevEditor != editor )
restoreEditorSelection( editor );
} );
editor->on( Event::OnFocusLoss, [this]( const Event* event ) {
if ( mRestoreEditorSelectionOnFocus )
saveEditorSelection( event->getNode()->asType<UICodeEditor>() );
} ); } );
editor->on( Event::OnTextChanged, [this]( const Event* event ) { editor->on( Event::OnTextChanged, [this]( const Event* event ) {
mClient->onDocumentModified( event->getNode()->asType<UICodeEditor>(), mClient->onDocumentModified( event->getNode()->asType<UICodeEditor>(),
@@ -559,8 +570,9 @@ UICodeEditorSplitter::createCodeEditorInTabWidget( UITabWidget* tabWidget ) {
UICodeEditor* editor = createCodeEditor(); UICodeEditor* editor = createCodeEditor();
mAboutToAddEditor = editor; mAboutToAddEditor = editor;
editor->on( Event::OnDocumentChanged, [this]( const Event* event ) { editor->on( Event::OnDocumentChanged, [this]( const Event* event ) {
mClient->onDocumentStateChanged( event->getNode()->asType<UICodeEditor>(), UICodeEditor* editor = event->getNode()->asType<UICodeEditor>();
event->getNode()->asType<UICodeEditor>()->getDocument() ); mEditorSelections.erase( editor );
mClient->onDocumentStateChanged( editor, editor->getDocument() );
} ); } );
UITab* tab = tabWidget->add( editor->getDocument().getFilename(), editor ); UITab* tab = tabWidget->add( editor->getDocument().getFilename(), editor );
editor->setData( (UintPtr)tab ); editor->setData( (UintPtr)tab );
@@ -1716,6 +1728,38 @@ void UICodeEditorSplitter::clearNavigationHistory() {
mNavigationHistoryPos = std::numeric_limits<size_t>::max(); mNavigationHistoryPos = std::numeric_limits<size_t>::max();
} }
void UICodeEditorSplitter::setRestoreEditorSelectionOnFocus( bool restore ) {
if ( mRestoreEditorSelectionOnFocus == restore )
return;
mRestoreEditorSelectionOnFocus = restore;
if ( !mRestoreEditorSelectionOnFocus )
mEditorSelections.clear();
}
void UICodeEditorSplitter::saveEditorSelection( UICodeEditor* editor ) {
if ( editor && editor->hasDocument() )
mEditorSelections[editor] = editor->getDocument().getSelections();
}
void UICodeEditorSplitter::restoreEditorSelection( UICodeEditor* editor ) {
if ( !editor || !editor->hasDocument() )
return;
auto it = mEditorSelections.find( editor );
if ( it == mEditorSelections.end() )
return;
TextRanges selection = editor->getDocument().sanitizeRange( it->second );
if ( selection.empty() )
return;
// resetSelection() drops stale extra cursors; setSelection() updates the active cursor index.
editor->getDocument().resetSelection( selection );
editor->getDocument().setSelection( selection );
editor->scrollToCursor();
}
std::shared_ptr<ThreadPool> UICodeEditorSplitter::getThreadPool() const { std::shared_ptr<ThreadPool> UICodeEditorSplitter::getThreadPool() const {
return mThreadPool; return mThreadPool;
} }
@@ -1798,6 +1842,8 @@ void UICodeEditorSplitter::closeSplitter( UISplitter* splitter ) {
void UICodeEditorSplitter::onTabClosed( const TabEvent* tabEvent ) { void UICodeEditorSplitter::onTabClosed( const TabEvent* tabEvent ) {
UIWidget* widget = tabEvent->getTab()->getOwnedWidget()->asType<UIWidget>(); UIWidget* widget = tabEvent->getTab()->getOwnedWidget()->asType<UIWidget>();
UITabWidget* tabWidget = tabEvent->getTab()->getTabWidget(); UITabWidget* tabWidget = tabEvent->getTab()->getTabWidget();
if ( widget && widget->isType( UI_TYPE_CODEEDITOR ) )
mEditorSelections.erase( widget->asType<UICodeEditor>() );
if ( tabWidget->getTabCount() == 0 ) { if ( tabWidget->getTabCount() == 0 ) {
UISplitter* splitter = splitterFromWidget( widget ); UISplitter* splitter = splitterFromWidget( widget );
if ( splitter ) { if ( splitter ) {
+7 -2
View File
@@ -1605,6 +1605,11 @@ Uint32 UICodeEditor::onMouseDown( const Vector2i& position, const Uint32& flags
if ( localPos.y < mPluginsTopSpace ) if ( localPos.y < mPluginsTopSpace )
return UIWidget::onMouseDown( position, flags ); return UIWidget::onMouseDown( position, flags );
const auto resetSelectionTo = [this]( const TextPosition& pos ) {
mDoc->resetSelection();
mDoc->setSelection( pos );
};
bool downOverGutter = localPos.x < mPaddingPx.Left + getGutterWidth(); bool downOverGutter = localPos.x < mPaddingPx.Left + getGutterWidth();
if ( flags & EE_BUTTON_LMASK ) { if ( flags & EE_BUTTON_LMASK ) {
@@ -1620,14 +1625,14 @@ Uint32 UICodeEditor::onMouseDown( const Vector2i& position, const Uint32& flags
return UIWidget::onMouseDown( position, flags ); return UIWidget::onMouseDown( position, flags );
if ( !downOverGutter || mAllowSelectingTextFromGutter ) if ( !downOverGutter || mAllowSelectingTextFromGutter )
mDoc->setSelection( textScreenPos ); resetSelectionTo( textScreenPos );
if ( downOverGutter && mAllowSelectingTextFromGutter ) if ( downOverGutter && mAllowSelectingTextFromGutter )
mDoc->selectLine(); mDoc->selectLine();
} }
} else if ( !downOverGutter && tryExecuteMouseBinding( shortcut ) ) { } else if ( !downOverGutter && tryExecuteMouseBinding( shortcut ) ) {
return UIWidget::onMouseDown( position, flags ); return UIWidget::onMouseDown( position, flags );
} else if ( !mDoc->hasSelection() ) { } else if ( !mDoc->hasSelection() ) {
mDoc->setSelection( textScreenPos ); resetSelectionTo( textScreenPos );
} }
} else if ( !( flags & ( EE_BUTTON_LMASK | EE_BUTTON_RMASK ) ) ) { } else if ( !( flags & ( EE_BUTTON_LMASK | EE_BUTTON_RMASK ) ) ) {
tryExecuteMouseBinding( shortcut ); tryExecuteMouseBinding( shortcut );
@@ -2,14 +2,18 @@
#include <eepp/scene/node.hpp> #include <eepp/scene/node.hpp>
#include <eepp/scene/scenemanager.hpp> #include <eepp/scene/scenemanager.hpp>
#include <eepp/system/filesystem.hpp> #include <eepp/system/filesystem.hpp>
#include <eepp/system/inifile.hpp>
#include <eepp/ui/doc/syntaxdefinitionmanager.hpp> #include <eepp/ui/doc/syntaxdefinitionmanager.hpp>
#include <eepp/ui/uiapplication.hpp> #include <eepp/ui/uiapplication.hpp>
#include <eepp/ui/uicodeeditor.hpp> #include <eepp/ui/uicodeeditor.hpp>
#include "../../tools/ecode/keybindingshelper.cpp"
using namespace EE; using namespace EE;
using namespace EE::UI; using namespace EE::UI;
using namespace EE::UI::Doc; using namespace EE::UI::Doc;
using namespace EE::Scene; using namespace EE::Scene;
using namespace EE::System;
static const std::string userCode = R"objcpp(#import "common.h" static const std::string userCode = R"objcpp(#import "common.h"
#import <cmath> #import <cmath>
@@ -101,6 +105,87 @@ OF_APPLICATION_DELEGATE(test)
} \ } \
} }
UTEST( KeybindingsHelper, PreservesUserShortcutWhenAddingBinding ) {
UIApplication app(
WindowSettings( 320, 240, "eepp - KeybindingsHelper Test", WindowStyle::Default,
WindowBackend::Default, 32 ),
UIApplication::Settings( Sys::getProcessPath() + ".." + FileSystem::getOSSlash(), 1 ) );
const std::string path = Sys::getTempPath() + "eepp_keybindingshelper.cfg";
const std::string statePath = Sys::getTempPath() + "eepp_keybindingshelper_state.cfg";
FileSystem::fileRemove( path );
FileSystem::fileRemove( statePath );
IniFile ini( path, false );
IniFile iniState( statePath, false );
const std::string group( "editor" );
const std::string modD( "mod+d" );
const std::string modX( "mod+x" );
const std::string modE( "mod+e" );
ini.setValue( group, modD, std::string( "duplicate-line-or-selection" ) );
ini.setValue( group, modX, std::string( "cut" ) );
ini.setValue( group, modE, std::string( "show-markdown-preview" ) );
std::unordered_map<std::string, std::string> keybindings;
std::unordered_map<std::string, std::string> invertedKeybindings;
const std::map<KeyBindings::Shortcut, std::string> defaultKeybindings{
{ { KEY_D, KeyMod::getDefaultModifier() }, "select-word" },
{ { KEY_X, KeyMod::getDefaultModifier() }, "cut" },
};
ecode::KeybindingsHelper::updateKeybindings( ini, group, app.getWindow()->getInput(),
keybindings, invertedKeybindings,
defaultKeybindings, false, {}, iniState );
ASSERT_TRUE( keybindings.find( modD ) != keybindings.end() );
const std::string savedModD = ini.getValue( group, modD, "" );
EXPECT_STREQ( keybindings[modD].c_str(), "duplicate-line-or-selection" );
EXPECT_STREQ( savedModD.c_str(), "duplicate-line-or-selection" );
EXPECT_STREQ( invertedKeybindings["duplicate-line-or-selection"].c_str(), modD.c_str() );
FileSystem::fileRemove( path );
FileSystem::fileRemove( statePath );
}
UTEST( KeybindingsHelper, RestoresMissingCommandWhenShortcutIsFree ) {
UIApplication app(
WindowSettings( 320, 240, "eepp - KeybindingsHelper Test", WindowStyle::Default,
WindowBackend::Default, 32 ),
UIApplication::Settings( Sys::getProcessPath() + ".." + FileSystem::getOSSlash(), 1 ) );
const std::string path = Sys::getTempPath() + "eepp_keybindingshelper_restore.cfg";
const std::string statePath = Sys::getTempPath() + "eepp_keybindingshelper_restore_state.cfg";
FileSystem::fileRemove( path );
FileSystem::fileRemove( statePath );
IniFile ini( path, false );
IniFile iniState( statePath, false );
const std::string group( "editor" );
const std::string modD( "mod+d" );
const std::string modX( "mod+x" );
ini.setValue( group, modX, std::string( "cut" ) );
std::unordered_map<std::string, std::string> keybindings;
std::unordered_map<std::string, std::string> invertedKeybindings;
const std::map<KeyBindings::Shortcut, std::string> defaultKeybindings{
{ { KEY_D, KeyMod::getDefaultModifier() }, "select-word" },
{ { KEY_X, KeyMod::getDefaultModifier() }, "cut" },
};
ecode::KeybindingsHelper::updateKeybindings( ini, group, app.getWindow()->getInput(),
keybindings, invertedKeybindings,
defaultKeybindings, false, {}, iniState );
ASSERT_TRUE( keybindings.find( modD ) != keybindings.end() );
const std::string savedModD = ini.getValue( group, modD, "" );
EXPECT_STREQ( keybindings[modD].c_str(), "select-word" );
EXPECT_STREQ( savedModD.c_str(), "select-word" );
EXPECT_STREQ( invertedKeybindings["select-word"].c_str(), modD.c_str() );
FileSystem::fileRemove( path );
FileSystem::fileRemove( statePath );
}
UTEST( UICodeEditor, DocumentViewStressTest ) { UTEST( UICodeEditor, DocumentViewStressTest ) {
UIApplication app( UIApplication app(
WindowSettings( 800, 600, "eepp - Stress Test", WindowStyle::Default, WindowSettings( 800, 600, "eepp - Stress Test", WindowStyle::Default,
+4
View File
@@ -196,6 +196,8 @@ void AppConfig::load( const std::string& confPath, std::string& keybindingsPath,
editor.hideTabBarOnSingleTab = ini.getValueB( "editor", "hide_tab_bar_on_single_tab", false ); editor.hideTabBarOnSingleTab = ini.getValueB( "editor", "hide_tab_bar_on_single_tab", false );
editor.hideTabBar = ini.getValueB( "editor", "hide_tab_bar", false ); editor.hideTabBar = ini.getValueB( "editor", "hide_tab_bar", false );
editor.tabSwitcher = ini.getValueB( "editor", "tab_switcher", false ); editor.tabSwitcher = ini.getValueB( "editor", "tab_switcher", false );
editor.restoreEditorSelectionOnFocus =
ini.getValueB( "editor", "restore_editor_selection_on_focus", true );
editor.tabJumpMode = editor.tabJumpMode =
UITabWidget::tabJumpModefromString( ini.getValue( "editor", "tab_jump_mode", "linear" ) ); UITabWidget::tabJumpModefromString( ini.getValue( "editor", "tab_jump_mode", "linear" ) );
@@ -388,6 +390,8 @@ void AppConfig::save( const std::vector<std::string>& recentFiles,
ini.setValueB( "editor", "hide_tab_bar_on_single_tab", editor.hideTabBarOnSingleTab ); ini.setValueB( "editor", "hide_tab_bar_on_single_tab", editor.hideTabBarOnSingleTab );
ini.setValueB( "editor", "hide_tab_bar", editor.hideTabBar ); ini.setValueB( "editor", "hide_tab_bar", editor.hideTabBar );
ini.setValueB( "editor", "tab_switcher", editor.tabSwitcher ); ini.setValueB( "editor", "tab_switcher", editor.tabSwitcher );
ini.setValueB( "editor", "restore_editor_selection_on_focus",
editor.restoreEditorSelectionOnFocus );
ini.setValue( "editor", "tab_jump_mode", ini.setValue( "editor", "tab_jump_mode",
UITabWidget::tabJumpModeToString( editor.tabJumpMode ) ); UITabWidget::tabJumpModeToString( editor.tabJumpMode ) );
ini.setValue( "editor", "new_tab_position", NewTabPosition::toString( editor.newTabPosition ) ); ini.setValue( "editor", "new_tab_position", NewTabPosition::toString( editor.newTabPosition ) );
+1
View File
@@ -118,6 +118,7 @@ struct CodeEditorConfig {
bool hideTabBar{ false }; bool hideTabBar{ false };
bool tabSwitcher{ false }; bool tabSwitcher{ false };
bool openDocumentsInMainSplit{ false }; bool openDocumentsInMainSplit{ false };
bool restoreEditorSelectionOnFocus{ true };
UITabWidget::TabJumpMode tabJumpMode{ UITabWidget::TabJumpMode::Linear }; UITabWidget::TabJumpMode tabJumpMode{ UITabWidget::TabJumpMode::Linear };
NewTabPosition::Position newTabPosition{ NewTabPosition::Last }; NewTabPosition::Position newTabPosition{ NewTabPosition::Last };
+1
View File
@@ -4966,6 +4966,7 @@ void App::init( InitParameters& params ) {
mSplitter->setHideTabBarOnSingleTab( mConfig.editor.hideTabBarOnSingleTab ); mSplitter->setHideTabBarOnSingleTab( mConfig.editor.hideTabBarOnSingleTab );
mSplitter->setHideTabBar( mConfig.editor.hideTabBar ); mSplitter->setHideTabBar( mConfig.editor.hideTabBar );
mSplitter->setOpenDocumentsInMainSplit( mConfig.editor.openDocumentsInMainSplit ); mSplitter->setOpenDocumentsInMainSplit( mConfig.editor.openDocumentsInMainSplit );
mSplitter->setRestoreEditorSelectionOnFocus( mConfig.editor.restoreEditorSelectionOnFocus );
mSplitter->setOnTabWidgetCreateCb( [this]( UITabWidget* tabWidget ) { mSplitter->setOnTabWidgetCreateCb( [this]( UITabWidget* tabWidget ) {
tabWidget->getTabBar()->onDoubleClick( tabWidget->getTabBar()->onDoubleClick(
[this]( const MouseEvent* ) { mSplitter->createEditorInNewTab(); } ); [this]( const MouseEvent* ) { mSplitter->createEditorInNewTab(); } );
-48
View File
@@ -58,22 +58,6 @@ void KeybindingsHelper::updateKeybindings(
invertedKeybindings[key.second] = shortcutStr; invertedKeybindings[key.second] = shortcutStr;
ini.setValue( group, shortcutStr, key.second ); ini.setValue( group, shortcutStr, key.second );
added = true; added = true;
} else if ( foundCmd == invertedKeybindings.end() ) {
// Override the shortcut if the command that holds that
// shortcut does not exists anymore
auto kb = keybindings.find( shortcutStr );
if ( kb != keybindings.end() ) {
bool found = false;
for ( const auto& val : defKeybindings )
if ( val.second == kb->second )
found = true;
if ( !found ) {
keybindings[shortcutStr] = key.second;
invertedKeybindings[key.second] = shortcutStr;
ini.setValue( group, shortcutStr, key.second );
added = true;
}
}
} }
} }
} }
@@ -147,22 +131,6 @@ void KeybindingsHelper::updateKeybindings(
invertedKeybindings[key.second] = shortcutStr; invertedKeybindings[key.second] = shortcutStr;
ini.setValue( group, shortcutStr, key.second ); ini.setValue( group, shortcutStr, key.second );
added = true; added = true;
} else if ( foundCmd == invertedKeybindings.end() ) {
// Override the shortcut if the command that holds that
// shortcut does not exists anymore
auto kb = keybindings.find( shortcutStr );
if ( kb != keybindings.end() ) {
bool found = false;
for ( const auto& val : defKeybindings )
if ( val.second == kb->second )
found = true;
if ( !found ) {
keybindings[shortcutStr] = key.second;
invertedKeybindings[key.second] = shortcutStr;
ini.setValue( group, shortcutStr, key.second );
added = true;
}
}
} }
} }
} }
@@ -235,22 +203,6 @@ void KeybindingsHelper::updateKeybindings(
invertedKeybindings[key.second] = shortcutStr; invertedKeybindings[key.second] = shortcutStr;
ini.setValue( group, shortcutStr, key.second ); ini.setValue( group, shortcutStr, key.second );
added = true; added = true;
} else if ( foundCmd == invertedKeybindings.end() ) {
// Override the shortcut if the command that holds that
// shortcut does not exists anymore
auto kb = keybindings.find( shortcutStr );
if ( kb != keybindings.end() ) {
bool found = false;
for ( const auto& val : defKeybindings )
if ( val.second == kb->second )
found = true;
if ( !found ) {
keybindings[shortcutStr] = key.second;
invertedKeybindings[key.second] = shortcutStr;
ini.setValue( group, shortcutStr, key.second );
added = true;
}
}
} }
} }
} }
+14
View File
@@ -2077,6 +2077,15 @@ UIMenu* SettingsMenu::createViewMenu() {
"Synchronizes the current focused document as the selected\nfile in the " "Synchronizes the current focused document as the selected\nfile in the "
"directory tree." ) ) "directory tree." ) )
->setId( "sync-project-tree" ); ->setId( "sync-project-tree" );
mViewMenu
->addCheckBox(
i18n( "restore_editor_selection_on_focus", "Restore editor selection on focus" ) )
->setActive( mApp->getConfig().editor.restoreEditorSelectionOnFocus )
->setTooltipText(
i18n( "restore_editor_selection_on_focus_tooltip",
"Restores each editor split's last cursor and selection state when it regains "
"focus." ) )
->setId( "restore-editor-selection-on-focus" );
mViewMenu->addSeparator(); mViewMenu->addSeparator();
mViewMenu mViewMenu
@@ -2210,6 +2219,11 @@ UIMenu* SettingsMenu::createViewMenu() {
} else if ( item->getId() == "sync-project-tree" ) { } else if ( item->getId() == "sync-project-tree" ) {
mApp->getConfig().editor.syncProjectTreeWithEditor = mApp->getConfig().editor.syncProjectTreeWithEditor =
item->asType<UIMenuCheckBox>()->isActive(); item->asType<UIMenuCheckBox>()->isActive();
} else if ( item->getId() == "restore-editor-selection-on-focus" ) {
mApp->getConfig().editor.restoreEditorSelectionOnFocus =
item->asType<UIMenuCheckBox>()->isActive();
mSplitter->setRestoreEditorSelectionOnFocus(
mApp->getConfig().editor.restoreEditorSelectionOnFocus );
} else { } else {
String text = String( event->getNode()->asType<UIMenuItem>()->getId() ).toLower(); String text = String( event->getNode()->asType<UIMenuItem>()->getId() ).toLower();
String::replaceAll( text, " ", "-" ); String::replaceAll( text, " ", "-" );