mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-10-02 03:00:23 +03:00
ecode: add centralized settings panel
- add user and project settings windows with searchable tree navigation - centralize setting definitions with reusable bool, choice, text, numeric, and action controls - apply supported configuration changes reactively - add inline validation and editable choices for complex value types - disable project document options while inheriting global settings - migrate font, theme, language, renderer, screenshot, and terminal settings - improve keyboard navigation and modal shortcut isolation - make configuration dialogs modal - persist settings when the panel closes - add responsive dark and light theme styling - update translations for new settings labels and descriptions - add regression coverage for modal keybinding propagation
This commit is contained in:
@@ -148,6 +148,7 @@ Diese Operation kann nicht rückgängig gemacht werden!</string>
|
|||||||
<string name="configure_ellipsis">Verwalten...</string>
|
<string name="configure_ellipsis">Verwalten...</string>
|
||||||
<string name="configure_ignore_files_ellipsis">Ignorierte Dateien verwalten...</string>
|
<string name="configure_ignore_files_ellipsis">Ignorierte Dateien verwalten...</string>
|
||||||
<string name="configure_terminal_scrollback">Konsolenverlaufslänge ändern</string>
|
<string name="configure_terminal_scrollback">Konsolenverlaufslänge ändern</string>
|
||||||
|
<string name="terminal_scrollback">Terminal-Verlauf</string>
|
||||||
<string name="configure_terminal_shell">Konsolen-Shell wählen</string>
|
<string name="configure_terminal_shell">Konsolen-Shell wählen</string>
|
||||||
<string name="configured_debugger">Gewählter Debugger</string>
|
<string name="configured_debugger">Gewählter Debugger</string>
|
||||||
<string name="configured_formatter">Gewählter Formatter</string>
|
<string name="configured_formatter">Gewählter Formatter</string>
|
||||||
@@ -1024,10 +1025,10 @@ Verwendet strftime-Formatbezeichner. Die Dateierweiterung richtet sich nach dem
|
|||||||
<string name="ui_panel_font_size_desc">Schriftgröße der Seitenbereiche festlegen.</string>
|
<string name="ui_panel_font_size_desc">Schriftgröße der Seitenbereiche festlegen.</string>
|
||||||
<string name="editor_font_size_desc">Standardschriftgröße des Code-Editors festlegen.</string>
|
<string name="editor_font_size_desc">Standardschriftgröße des Code-Editors festlegen.</string>
|
||||||
<string name="terminal_font_size_desc">Standardschriftgröße des Terminals festlegen.</string>
|
<string name="terminal_font_size_desc">Standardschriftgröße des Terminals festlegen.</string>
|
||||||
<string name="ui_scale_factor_desc">Gesamte Benutzeroberfläche skalieren.</string>
|
<string name="ui_scale_factor_desc">Gesamte Benutzeroberfläche von 1 bis 6 skalieren. Neustart erforderlich.</string>
|
||||||
<string name="line_spacing_desc">Zusätzlichen vertikalen Abstand zwischen Editorzeilen festlegen.</string>
|
<string name="line_spacing_desc">Zusätzlichen vertikalen Abstand zwischen Editorzeilen festlegen. Zum Deaktivieren 0 einstellen.</string>
|
||||||
<string name="cursor_blinking_time_desc">Blinkintervall des Textcursors festlegen.</string>
|
<string name="cursor_blinking_time_desc">Blinkintervall des Textcursors festlegen. Zum Deaktivieren 0 einstellen.</string>
|
||||||
<string name="folds_refresh_freq_desc">Häufigkeit der Neuberechnung von Faltungsbereichen festlegen.</string>
|
<string name="folds_refresh_freq_desc">Häufigkeit der Neuberechnung von Faltungsbereichen festlegen (mindestens 1 Sekunde).</string>
|
||||||
<string name="screenshot_save_path_desc">Speicherort für Bildschirmfotos auswählen.</string>
|
<string name="screenshot_save_path_desc">Speicherort für Bildschirmfotos auswählen.</string>
|
||||||
<string name="screenshot_filename_pattern_desc">Zeitstempel-Dateinamensmuster für Bildschirmfotos konfigurieren.</string>
|
<string name="screenshot_filename_pattern_desc">Zeitstempel-Dateinamensmuster für Bildschirmfotos konfigurieren.</string>
|
||||||
<string name="screenshot_save_format_desc">Bildformat für Bildschirmfotos auswählen.</string>
|
<string name="screenshot_save_format_desc">Bildformat für Bildschirmfotos auswählen.</string>
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ This operation cannot be reverted!</string>
|
|||||||
<string name="configure_ellipsis">Configure...</string>
|
<string name="configure_ellipsis">Configure...</string>
|
||||||
<string name="configure_ignore_files_ellipsis">Configure Ignore Files...</string>
|
<string name="configure_ignore_files_ellipsis">Configure Ignore Files...</string>
|
||||||
<string name="configure_terminal_scrollback">Configure Terminal Scrollback</string>
|
<string name="configure_terminal_scrollback">Configure Terminal Scrollback</string>
|
||||||
|
<string name="terminal_scrollback">Terminal Scrollback</string>
|
||||||
<string name="configure_terminal_shell">Configure Terminal Shell</string>
|
<string name="configure_terminal_shell">Configure Terminal Shell</string>
|
||||||
<string name="configured_debugger">Configured debugger</string>
|
<string name="configured_debugger">Configured debugger</string>
|
||||||
<string name="configured_formatter">Configured formatter</string>
|
<string name="configured_formatter">Configured formatter</string>
|
||||||
@@ -1008,10 +1009,10 @@ Uses strftime format specifiers. The file extension follows the selected screens
|
|||||||
<string name="ui_panel_font_size_desc">Set the font size used by side panels.</string>
|
<string name="ui_panel_font_size_desc">Set the font size used by side panels.</string>
|
||||||
<string name="editor_font_size_desc">Set the default code editor font size.</string>
|
<string name="editor_font_size_desc">Set the default code editor font size.</string>
|
||||||
<string name="terminal_font_size_desc">Set the default integrated terminal font size.</string>
|
<string name="terminal_font_size_desc">Set the default integrated terminal font size.</string>
|
||||||
<string name="ui_scale_factor_desc">Scale the complete user interface.</string>
|
<string name="ui_scale_factor_desc">Scale the complete user interface from 1 to 6. Restart required.</string>
|
||||||
<string name="line_spacing_desc">Set additional vertical spacing between editor lines.</string>
|
<string name="line_spacing_desc">Set additional vertical spacing between editor lines. Set 0 to disable.</string>
|
||||||
<string name="cursor_blinking_time_desc">Set the text cursor blink interval.</string>
|
<string name="cursor_blinking_time_desc">Set the text cursor blink interval. Set 0 to disable.</string>
|
||||||
<string name="folds_refresh_freq_desc">Set how frequently code folding ranges are recalculated.</string>
|
<string name="folds_refresh_freq_desc">Set how frequently code folding ranges are recalculated (minimum 1 second).</string>
|
||||||
<string name="screenshot_save_path_desc">Choose where screenshots are saved.</string>
|
<string name="screenshot_save_path_desc">Choose where screenshots are saved.</string>
|
||||||
<string name="screenshot_filename_pattern_desc">Configure the timestamp-based screenshot filename pattern.</string>
|
<string name="screenshot_filename_pattern_desc">Configure the timestamp-based screenshot filename pattern.</string>
|
||||||
<string name="screenshot_save_format_desc">Choose the image format for screenshots.</string>
|
<string name="screenshot_save_format_desc">Choose the image format for screenshots.</string>
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ Cette opération est irréversible !</string>
|
|||||||
<string name="configure_ellipsis">Configurer...</string>
|
<string name="configure_ellipsis">Configurer...</string>
|
||||||
<string name="configure_ignore_files_ellipsis">Configurer les fichiers ignorés...</string>
|
<string name="configure_ignore_files_ellipsis">Configurer les fichiers ignorés...</string>
|
||||||
<string name="configure_terminal_scrollback">Configurer le défilement de l'historique du terminal</string>
|
<string name="configure_terminal_scrollback">Configurer le défilement de l'historique du terminal</string>
|
||||||
|
<string name="terminal_scrollback">Historique du terminal</string>
|
||||||
<string name="configure_terminal_shell">Configurer l'interpréteur de commandes du terminal</string>
|
<string name="configure_terminal_shell">Configurer l'interpréteur de commandes du terminal</string>
|
||||||
<string name="configured_debugger">Débogueur configuré</string>
|
<string name="configured_debugger">Débogueur configuré</string>
|
||||||
<string name="configured_formatter">Formatteur configuré</string>
|
<string name="configured_formatter">Formatteur configuré</string>
|
||||||
@@ -1003,10 +1004,10 @@ Utilise les spécificateurs de format strftime. L’extension du fichier corresp
|
|||||||
<string name="ui_panel_font_size_desc">Set the font size used by side panels.</string>
|
<string name="ui_panel_font_size_desc">Set the font size used by side panels.</string>
|
||||||
<string name="editor_font_size_desc">Set the default code editor font size.</string>
|
<string name="editor_font_size_desc">Set the default code editor font size.</string>
|
||||||
<string name="terminal_font_size_desc">Set the default integrated terminal font size.</string>
|
<string name="terminal_font_size_desc">Set the default integrated terminal font size.</string>
|
||||||
<string name="ui_scale_factor_desc">Scale the complete user interface.</string>
|
<string name="ui_scale_factor_desc">Mettre l’interface à l’échelle de 1 à 6. Redémarrage requis.</string>
|
||||||
<string name="line_spacing_desc">Set additional vertical spacing between editor lines.</string>
|
<string name="line_spacing_desc">Définir l’espace vertical supplémentaire entre les lignes. Utiliser 0 pour désactiver.</string>
|
||||||
<string name="cursor_blinking_time_desc">Set the text cursor blink interval.</string>
|
<string name="cursor_blinking_time_desc">Définir l’intervalle de clignotement du curseur. Utiliser 0 pour désactiver.</string>
|
||||||
<string name="folds_refresh_freq_desc">Set how frequently code folding ranges are recalculated.</string>
|
<string name="folds_refresh_freq_desc">Définir la fréquence de recalcul des zones de pliage du code (minimum 1 seconde).</string>
|
||||||
<string name="screenshot_save_path_desc">Choose where screenshots are saved.</string>
|
<string name="screenshot_save_path_desc">Choose where screenshots are saved.</string>
|
||||||
<string name="screenshot_filename_pattern_desc">Configure the timestamp-based screenshot filename pattern.</string>
|
<string name="screenshot_filename_pattern_desc">Configure the timestamp-based screenshot filename pattern.</string>
|
||||||
<string name="screenshot_save_format_desc">Choose the image format for screenshots.</string>
|
<string name="screenshot_save_format_desc">Choose the image format for screenshots.</string>
|
||||||
|
|||||||
@@ -110,6 +110,7 @@
|
|||||||
<string name="configure_default_shell">配置默认终端</string>
|
<string name="configure_default_shell">配置默认终端</string>
|
||||||
<string name="configure_ignore_files_ellipsis">设置忽略的文件...</string>
|
<string name="configure_ignore_files_ellipsis">设置忽略的文件...</string>
|
||||||
<string name="configure_terminal_scrollback">Configure Terminal Scrollback</string>
|
<string name="configure_terminal_scrollback">Configure Terminal Scrollback</string>
|
||||||
|
<string name="terminal_scrollback">终端回滚行数</string>
|
||||||
<string name="configure_terminal_shell">设置终端程序</string>
|
<string name="configure_terminal_shell">设置终端程序</string>
|
||||||
<string name="confirm_build_delete">你确定要删除构建设置吗?</string>
|
<string name="confirm_build_delete">你确定要删除构建设置吗?</string>
|
||||||
<string name="confirm_close_folder">确定要关闭此文件夹吗?
|
<string name="confirm_close_folder">确定要关闭此文件夹吗?
|
||||||
@@ -782,10 +783,10 @@ file in the directory tree.</string>
|
|||||||
<string name="ui_panel_font_size_desc">Set the font size used by side panels.</string>
|
<string name="ui_panel_font_size_desc">Set the font size used by side panels.</string>
|
||||||
<string name="editor_font_size_desc">Set the default code editor font size.</string>
|
<string name="editor_font_size_desc">Set the default code editor font size.</string>
|
||||||
<string name="terminal_font_size_desc">Set the default integrated terminal font size.</string>
|
<string name="terminal_font_size_desc">Set the default integrated terminal font size.</string>
|
||||||
<string name="ui_scale_factor_desc">Scale the complete user interface.</string>
|
<string name="ui_scale_factor_desc">将整个用户界面缩放为 1 到 6。需要重新启动。</string>
|
||||||
<string name="line_spacing_desc">Set additional vertical spacing between editor lines.</string>
|
<string name="line_spacing_desc">设置编辑器行之间的额外垂直间距。设置为 0 可禁用。</string>
|
||||||
<string name="cursor_blinking_time_desc">Set the text cursor blink interval.</string>
|
<string name="cursor_blinking_time_desc">设置文本光标闪烁间隔。设置为 0 可禁用。</string>
|
||||||
<string name="folds_refresh_freq_desc">Set how frequently code folding ranges are recalculated.</string>
|
<string name="folds_refresh_freq_desc">设置重新计算代码折叠区域的频率(最少 1 秒)。</string>
|
||||||
<string name="screenshot_save_path_desc">Choose where screenshots are saved.</string>
|
<string name="screenshot_save_path_desc">Choose where screenshots are saved.</string>
|
||||||
<string name="screenshot_filename_pattern_desc">Configure the timestamp-based screenshot filename pattern.</string>
|
<string name="screenshot_filename_pattern_desc">Configure the timestamp-based screenshot filename pattern.</string>
|
||||||
<string name="screenshot_save_format_desc">Choose the image format for screenshots.</string>
|
<string name="screenshot_save_format_desc">Choose the image format for screenshots.</string>
|
||||||
|
|||||||
@@ -1771,7 +1771,8 @@ Uint32 UIWindow::onKeyDown( const KeyEvent& event ) {
|
|||||||
executeKeyBindingCommand( cmd );
|
executeKeyBindingCommand( cmd );
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return UIWidget::onKeyDown( event );
|
Uint32 handled = UIWidget::onKeyDown( event );
|
||||||
|
return handled || isModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyBindings& UIWindow::getKeyBindings() {
|
KeyBindings& UIWindow::getKeyBindings() {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <eepp/graphics/fontfamily.hpp>
|
#include <eepp/graphics/fontfamily.hpp>
|
||||||
#include <eepp/graphics/fonttruetype.hpp>
|
#include <eepp/graphics/fonttruetype.hpp>
|
||||||
|
#include <eepp/scene/eventdispatcher.hpp>
|
||||||
#include <eepp/scene/scenemanager.hpp>
|
#include <eepp/scene/scenemanager.hpp>
|
||||||
#include <eepp/system/filesystem.hpp>
|
#include <eepp/system/filesystem.hpp>
|
||||||
#include <eepp/system/sys.hpp>
|
#include <eepp/system/sys.hpp>
|
||||||
@@ -10,6 +11,7 @@
|
|||||||
#include <eepp/ui/uiscenenode.hpp>
|
#include <eepp/ui/uiscenenode.hpp>
|
||||||
#include <eepp/ui/uithememanager.hpp>
|
#include <eepp/ui/uithememanager.hpp>
|
||||||
#include <eepp/ui/uiwidget.hpp>
|
#include <eepp/ui/uiwidget.hpp>
|
||||||
|
#include <eepp/ui/uiwindow.hpp>
|
||||||
#include <eepp/window/cursor.hpp>
|
#include <eepp/window/cursor.hpp>
|
||||||
#include <eepp/window/engine.hpp>
|
#include <eepp/window/engine.hpp>
|
||||||
#include <eepp/window/input.hpp>
|
#include <eepp/window/input.hpp>
|
||||||
@@ -391,3 +393,31 @@ UTEST( UISceneNode, StyleStateUpdateAllowsWidgetCreation ) {
|
|||||||
|
|
||||||
Engine::destroySingleton();
|
Engine::destroySingleton();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UTEST( UIWindow, ModalWindowStopsKeyBindingsFromReachingScene ) {
|
||||||
|
Engine::instance()->createWindow( WindowSettings( 1024, 768, "Modal Key Binding Test",
|
||||||
|
WindowStyle::Default, WindowBackend::Default,
|
||||||
|
32, {}, 1, false, true ),
|
||||||
|
ContextSettings( false, 0, 0, GLv_default, true, false ) );
|
||||||
|
|
||||||
|
UISceneNode* sceneNode = init_test_scene_node();
|
||||||
|
int executedCommands = 0;
|
||||||
|
sceneNode->setKeyBindingCommand( "global-command",
|
||||||
|
[&executedCommands] { executedCommands++; } );
|
||||||
|
sceneNode->addKeyBinding( { KEY_F, KEYMOD_LMETA | KEYMOD_LSHIFT }, "global-command" );
|
||||||
|
|
||||||
|
UIWindow* window = UIWindow::New();
|
||||||
|
window->setParent( sceneNode->getRoot() );
|
||||||
|
sceneNode->getEventDispatcher()->setFocusNode( window->getContainer() );
|
||||||
|
|
||||||
|
sceneNode->getEventDispatcher()->sendKeyDown( KEY_F, SCANCODE_UNKNOWN, 0,
|
||||||
|
KEYMOD_LMETA | KEYMOD_LSHIFT );
|
||||||
|
EXPECT_EQ( executedCommands, 1 );
|
||||||
|
|
||||||
|
window->setWindowFlags( window->getWinFlags() | UI_WIN_MODAL );
|
||||||
|
sceneNode->getEventDispatcher()->sendKeyDown( KEY_F, SCANCODE_UNKNOWN, 0,
|
||||||
|
KEYMOD_LMETA | KEYMOD_LSHIFT );
|
||||||
|
EXPECT_EQ( executedCommands, 1 );
|
||||||
|
|
||||||
|
Engine::destroySingleton();
|
||||||
|
}
|
||||||
|
|||||||
@@ -410,30 +410,31 @@ void SettingsActions::setUIPanelFontSize() {
|
|||||||
msgBox->setCloseShortcut( { KEY_ESCAPE, 0 } );
|
msgBox->setCloseShortcut( { KEY_ESCAPE, 0 } );
|
||||||
msgBox->showWhenReady();
|
msgBox->showWhenReady();
|
||||||
msgBox->on( Event::OnConfirm, [this, msgBox]( const Event* ) {
|
msgBox->on( Event::OnConfirm, [this, msgBox]( const Event* ) {
|
||||||
mApp->getConfig().ui.panelFontSize = StyleSheetLength( msgBox->getTextInput()->getText() );
|
setUIPanelFontSize( StyleSheetLength( msgBox->getTextInput()->getText() ) );
|
||||||
|
|
||||||
// Update the CSS
|
|
||||||
auto selsFound = mApp->getUISceneNode()->getStyleSheet().findStyleFromSelectorName(
|
|
||||||
"#project_view > treeview::row > treeview::cell" );
|
|
||||||
if ( !selsFound.empty() ) {
|
|
||||||
for ( auto sel : selsFound )
|
|
||||||
sel->updatePropertyValue( "font-size",
|
|
||||||
mApp->getConfig().ui.panelFontSize.toString() );
|
|
||||||
mApp->getUISceneNode()->getStyleSheet().refreshCacheFromStyles( selsFound );
|
|
||||||
}
|
|
||||||
|
|
||||||
UITreeView* treeView = mApp->getUISceneNode()->find<UITreeView>( "project_view" );
|
|
||||||
if ( !treeView ) {
|
|
||||||
msgBox->closeWindow();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
treeView->reloadStyle( true, true, true, true );
|
|
||||||
treeView->updateContentSize();
|
|
||||||
msgBox->closeWindow();
|
msgBox->closeWindow();
|
||||||
} );
|
} );
|
||||||
mApp->setFocusEditorOnClose( msgBox );
|
mApp->setFocusEditorOnClose( msgBox );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SettingsActions::setUIPanelFontSize( const StyleSheetLength& size ) {
|
||||||
|
mApp->getConfig().ui.panelFontSize = size;
|
||||||
|
|
||||||
|
// Update the CSS
|
||||||
|
auto selsFound = mApp->getUISceneNode()->getStyleSheet().findStyleFromSelectorName(
|
||||||
|
"#project_view > treeview::row > treeview::cell" );
|
||||||
|
if ( !selsFound.empty() ) {
|
||||||
|
for ( auto sel : selsFound )
|
||||||
|
sel->updatePropertyValue( "font-size", size.toString() );
|
||||||
|
mApp->getUISceneNode()->getStyleSheet().refreshCacheFromStyles( selsFound );
|
||||||
|
}
|
||||||
|
|
||||||
|
UITreeView* treeView = mApp->getUISceneNode()->find<UITreeView>( "project_view" );
|
||||||
|
if ( !treeView )
|
||||||
|
return;
|
||||||
|
treeView->reloadStyle( true, true, true, true );
|
||||||
|
treeView->updateContentSize();
|
||||||
|
}
|
||||||
|
|
||||||
void SettingsActions::setScreenshotSavePath() {
|
void SettingsActions::setScreenshotSavePath() {
|
||||||
std::string initialPath = mApp->getConfig().screenshot.savePath;
|
std::string initialPath = mApp->getConfig().screenshot.savePath;
|
||||||
if ( !FileSystem::isDirectory( initialPath ) ) {
|
if ( !FileSystem::isDirectory( initialPath ) ) {
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ class SettingsActions {
|
|||||||
void setTerminalFontSize( const StyleSheetLength& size );
|
void setTerminalFontSize( const StyleSheetLength& size );
|
||||||
|
|
||||||
void setUIPanelFontSize();
|
void setUIPanelFontSize();
|
||||||
|
void setUIPanelFontSize( const StyleSheetLength& size );
|
||||||
|
|
||||||
void setScreenshotSavePath();
|
void setScreenshotSavePath();
|
||||||
|
|
||||||
|
|||||||
+442
-143
@@ -1,7 +1,9 @@
|
|||||||
#include "settingspanel.hpp"
|
#include "settingspanel.hpp"
|
||||||
|
#include "datetimecontroller.hpp"
|
||||||
#include "ecode.hpp"
|
#include "ecode.hpp"
|
||||||
#include "uitreeviewfs.hpp"
|
#include "uitreeviewfs.hpp"
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
using namespace EE::UI::Models;
|
using namespace EE::UI::Models;
|
||||||
|
|
||||||
@@ -110,49 +112,82 @@ class SettingsCategoryModel final : public Model {
|
|||||||
static constexpr const char* SETTINGS_PANEL_LAYOUT = R"xml(
|
static constexpr const char* SETTINGS_PANEL_LAYOUT = R"xml(
|
||||||
<style>
|
<style>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
|
.settings_panel #settings_sidebar {
|
||||||
|
background-color: var(--list-back);
|
||||||
|
padding: 10dp 8dp 8dp 8dp;
|
||||||
|
}
|
||||||
.settings_panel #settings_filter {
|
.settings_panel #settings_filter {
|
||||||
margin-top: 8dp;
|
margin-bottom: 10dp;
|
||||||
margin-bottom: 8dp;
|
}
|
||||||
|
.settings_panel #settings_categories * {
|
||||||
|
focusable: false;
|
||||||
|
}
|
||||||
|
.settings_panel #settings_categories {
|
||||||
|
background-color: var(--list-back);
|
||||||
|
}
|
||||||
|
.settings_panel #settings_categories treeview::row {
|
||||||
|
border-left: 0dp solid var(--primary);
|
||||||
|
transition: border-left-width 0.1s;
|
||||||
|
}
|
||||||
|
.settings_panel #settings_categories treeview::row:selected {
|
||||||
|
background-color: var(--tab-hover);
|
||||||
|
border-left: 2dp solid var(--primary);
|
||||||
|
}
|
||||||
|
.settings_panel #settings_categories treeview::row:selected treeview::cell {
|
||||||
|
color: var(--font);
|
||||||
}
|
}
|
||||||
.settings_panel #settings_rows {
|
.settings_panel #settings_rows {
|
||||||
padding-left: 16dp;
|
max-width: 820dp;
|
||||||
padding-right: 16dp;
|
padding: 20dp 28dp 28dp 28dp;
|
||||||
margin-bottom: 8dp;
|
layout-gravity: center_horizontal;
|
||||||
}
|
}
|
||||||
.settings_panel #settings_page_title {
|
.settings_panel #settings_page_title {
|
||||||
font-size: 16dp;
|
font-size: 18dp;
|
||||||
padding-bottom: 2dp;
|
margin-bottom: 18dp;
|
||||||
margin-bottom: 6dp;
|
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-style: shadow;
|
|
||||||
border-bottom: 1dp solid var(--tab-line);
|
|
||||||
}
|
}
|
||||||
.settings_panel .settings_category_heading {
|
.settings_panel .settings_category_heading {
|
||||||
font-size: 15dp;
|
font-size: 14dp;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin: 12dp 8dp 8dp 0dp;
|
margin: 12dp 0dp 6dp 0dp;
|
||||||
font-style: shadow;
|
padding-bottom: 6dp;
|
||||||
border-bottom: 1dp solid var(--tab-line);
|
border-bottom: 1dp solid var(--tab-line);
|
||||||
}
|
}
|
||||||
.settings_panel .settings_option {
|
.settings_panel .settings_option {
|
||||||
border-bottom: 1dp solid var(--tab-line);
|
border-bottom: 1dp solid var(--disabled-border);
|
||||||
padding: 4dp 8dp 8dp 0dp;
|
padding: 9dp 4dp 11dp 4dp;
|
||||||
margin-bottom: 12dp;
|
margin-bottom: 0dp;
|
||||||
|
}
|
||||||
|
.settings_panel .settings_option:disabled {
|
||||||
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
.settings_panel .settings_option_name {
|
.settings_panel .settings_option_name {
|
||||||
font-weight: bold;
|
font-style: normal;
|
||||||
font-style: shadow;
|
|
||||||
}
|
}
|
||||||
.settings_panel .settings_option_description {
|
.settings_panel .settings_option_description {
|
||||||
margin-top: 4dp;
|
color: var(--disabled-color);
|
||||||
|
font-size: 10dp;
|
||||||
|
margin-top: 3dp;
|
||||||
word-wrap: true;
|
word-wrap: true;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.settings_panel .settings_option_name,
|
||||||
|
.settings_panel .settings_option_description {
|
||||||
|
font-style: shadow;
|
||||||
|
}
|
||||||
|
.settings_panel .settings_option_description {
|
||||||
|
color: var(--font-hint);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.settings_panel .settings_boolean_option .settings_option_name,
|
.settings_panel .settings_boolean_option .settings_option_name,
|
||||||
.settings_panel .settings_boolean_option .settings_option_description {
|
.settings_panel .settings_boolean_option .settings_option_description {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.settings_panel .settings_option_control {
|
.settings_panel .settings_option_control {
|
||||||
margin-left: 12dp;
|
layout-width: 210dp;
|
||||||
|
gravity: right|center_vertical;
|
||||||
|
margin-left: 20dp;
|
||||||
layout-gravity: center_vertical;
|
layout-gravity: center_vertical;
|
||||||
}
|
}
|
||||||
.settings_panel .settings_bool,
|
.settings_panel .settings_bool,
|
||||||
@@ -167,6 +202,14 @@ static constexpr const char* SETTINGS_PANEL_LAYOUT = R"xml(
|
|||||||
layout-width: 190dp;
|
layout-width: 190dp;
|
||||||
layout-height: wrap_content;
|
layout-height: wrap_content;
|
||||||
}
|
}
|
||||||
|
.settings_panel .settings_editable_choice {
|
||||||
|
layout-width: 210dp;
|
||||||
|
layout-height: wrap_content;
|
||||||
|
}
|
||||||
|
.settings_panel .settings_text {
|
||||||
|
layout-width: 210dp;
|
||||||
|
layout-height: wrap_content;
|
||||||
|
}
|
||||||
.settings_panel .settings_integer {
|
.settings_panel .settings_integer {
|
||||||
layout-width: 110dp;
|
layout-width: 110dp;
|
||||||
layout-height: wrap_content;
|
layout-height: wrap_content;
|
||||||
@@ -174,12 +217,14 @@ static constexpr const char* SETTINGS_PANEL_LAYOUT = R"xml(
|
|||||||
]]>
|
]]>
|
||||||
</style>
|
</style>
|
||||||
<vbox lw="mp" lh="mp" class="settings_panel">
|
<vbox lw="mp" lh="mp" class="settings_panel">
|
||||||
<TextInput id="settings_filter" lw="mp" lh="wc" hint="@string(search_settings, Search settings...)" />
|
<Splitter id="settings_splitter" lw="mp" lh="mp" orientation="horizontal" splitter-partition="220dp">
|
||||||
<Splitter id="settings_splitter" lw="mp" lh="0" lw8="1" orientation="horizontal" splitter-partition="160dp">
|
<vbox id="settings_sidebar" lw="0" lh="0" min-width="160dp">
|
||||||
<TreeView id="settings_categories" lw="mp" lh="mp" />
|
<TextInput id="settings_filter" lw="mp" lh="wc" hint="@string(search_settings, Search settings...)" />
|
||||||
<ScrollView id="settings_scroll" lw="0" lw8="1" lh="mp">
|
<TreeView id="settings_categories" lw="mp" lh="mp" />
|
||||||
|
</vbox>
|
||||||
|
<ScrollView id="settings_scroll" lw="0" lw8="1" lh="mp" focusable="false">
|
||||||
<vbox id="settings_rows" lw="mp" lh="wc">
|
<vbox id="settings_rows" lw="mp" lh="wc">
|
||||||
<TextView id="settings_page_title" lw="mp" lh="wc" />
|
<TextView id="settings_page_title" lw="mp" lh="wc" focusable="false" />
|
||||||
</vbox>
|
</vbox>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</Splitter>
|
</Splitter>
|
||||||
@@ -190,24 +235,35 @@ static constexpr const char* SETTINGS_ROW_LAYOUT = R"xml(
|
|||||||
<vbox lw="mp" lh="wc" class="settings_option">
|
<vbox lw="mp" lh="wc" class="settings_option">
|
||||||
<hbox lw="mp" lh="wc" class="settings_option_content">
|
<hbox lw="mp" lh="wc" class="settings_option_content">
|
||||||
<vbox lw="0" lw8="1" lh="wc">
|
<vbox lw="0" lw8="1" lh="wc">
|
||||||
<TextView id="setting_name" lw="mp" lh="wc" class="settings_option_name" />
|
<TextView id="setting_name" lw="mp" lh="wc" class="settings_option_name" focusable="false" />
|
||||||
<TextView id="setting_description" lw="mp" lh="wc" class="settings_option_description" />
|
<TextView id="setting_description" lw="mp" lh="wc" class="settings_option_description" focusable="false" />
|
||||||
</vbox>
|
</vbox>
|
||||||
<hbox id="setting_control" lw="wc" lh="wc" class="settings_option_control" />
|
<hbox id="setting_control" lw="wc" lh="wc" class="settings_option_control" />
|
||||||
</hbox>
|
</hbox>
|
||||||
</vbox>
|
</vbox>
|
||||||
)xml";
|
)xml";
|
||||||
|
|
||||||
static constexpr const char* SETTINGS_CATEGORY_HEADING_LAYOUT =
|
static constexpr const char* SETTINGS_CATEGORY_HEADING_LAYOUT = R"xml(
|
||||||
R"xml(<TextView lw="mp" lh="wc" class="settings_category_heading" visible="false" />)xml";
|
<TextView lw="mp" lh="wc" class="settings_category_heading" visible="false" focusable="false" />
|
||||||
|
)xml";
|
||||||
static constexpr const char* SETTINGS_BOOL_LAYOUT = R"xml(<CheckBox class="settings_bool" />)xml";
|
static constexpr const char* SETTINGS_BOOL_LAYOUT = R"xml(<CheckBox class="settings_bool" />)xml";
|
||||||
static constexpr const char* SETTINGS_CHOICE_LAYOUT =
|
static constexpr const char* SETTINGS_CHOICE_LAYOUT =
|
||||||
R"xml(<DropDownList class="settings_choice" />)xml";
|
R"xml(<DropDownList class="settings_choice" />)xml";
|
||||||
|
static constexpr const char* SETTINGS_EDITABLE_CHOICE_LAYOUT =
|
||||||
|
R"xml(<ComboBox class="settings_editable_choice" popup-to-root="true" />)xml";
|
||||||
static constexpr const char* SETTINGS_INTEGER_LAYOUT =
|
static constexpr const char* SETTINGS_INTEGER_LAYOUT =
|
||||||
R"xml(<SpinBox class="settings_integer" />)xml";
|
R"xml(<SpinBox class="settings_integer" />)xml";
|
||||||
|
static constexpr const char* SETTINGS_TEXT_LAYOUT = R"xml(<TextInput class="settings_text" />)xml";
|
||||||
static constexpr const char* SETTINGS_ACTION_LAYOUT =
|
static constexpr const char* SETTINGS_ACTION_LAYOUT =
|
||||||
R"xml(<PushButton class="settings_action" />)xml";
|
R"xml(<PushButton class="settings_action" />)xml";
|
||||||
|
|
||||||
|
static void disableTabFocusTree( Node* node ) {
|
||||||
|
if ( node->isWidget() )
|
||||||
|
node->asType<UIWidget>()->unsetTabFocusable();
|
||||||
|
for ( auto* child = node->getFirstChild(); child; child = child->getNextNode() )
|
||||||
|
disableTabFocusTree( child );
|
||||||
|
}
|
||||||
|
|
||||||
SettingsPanel::SettingsPanel( App* app ) : mApp( app ) {}
|
SettingsPanel::SettingsPanel( App* app ) : mApp( app ) {}
|
||||||
|
|
||||||
SettingsPanel::PanelState& SettingsPanel::state( Scope scope ) {
|
SettingsPanel::PanelState& SettingsPanel::state( Scope scope ) {
|
||||||
@@ -242,7 +298,10 @@ void SettingsPanel::show( Scope scope ) {
|
|||||||
panel.categories->setFocus();
|
panel.categories->setFocus();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Clock c;
|
||||||
create( scope );
|
create( scope );
|
||||||
|
Log::info( "Settings Panel %s created in %s", scope == Scope::User ? "User" : "Project",
|
||||||
|
c.getElapsedTime().toString() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsPanel::create( Scope scope ) {
|
void SettingsPanel::create( Scope scope ) {
|
||||||
@@ -274,11 +333,31 @@ void SettingsPanel::create( Scope scope ) {
|
|||||||
panel.scroll = layout->find<UIScrollView>( "settings_scroll" );
|
panel.scroll = layout->find<UIScrollView>( "settings_scroll" );
|
||||||
panel.scroll->setVerticalScrollMode( ScrollBarMode::Auto );
|
panel.scroll->setVerticalScrollMode( ScrollBarMode::Auto );
|
||||||
panel.scroll->setHorizontalScrollMode( ScrollBarMode::AlwaysOff );
|
panel.scroll->setHorizontalScrollMode( ScrollBarMode::AlwaysOff );
|
||||||
|
disableTabFocusTree( panel.categories->getVerticalScrollBar() );
|
||||||
|
disableTabFocusTree( panel.categories->getHorizontalScrollBar() );
|
||||||
|
disableTabFocusTree( panel.scroll->getVerticalScrollBar() );
|
||||||
|
disableTabFocusTree( panel.scroll->getHorizontalScrollBar() );
|
||||||
|
panel.window->setKeyBindingCommand( "focusSettingsFilter", [&panel] {
|
||||||
|
panel.search->setFocus();
|
||||||
|
panel.search->getDocument().selectAll();
|
||||||
|
} );
|
||||||
|
panel.window->setKeyBindingCommand( "focusSettingsCategories", [&panel] {
|
||||||
|
auto selected = panel.categories->getSelection().first();
|
||||||
|
if ( selected.isValid() )
|
||||||
|
panel.categories->setSelection( selected );
|
||||||
|
panel.categories->setFocus();
|
||||||
|
} );
|
||||||
|
panel.window->getKeyBindings().addKeybind( { KEY_F, KeyMod::getDefaultModifier() },
|
||||||
|
"focusSettingsFilter" );
|
||||||
|
panel.window->getKeyBindings().addKeybind(
|
||||||
|
{ KEY_E, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "focusSettingsCategories" );
|
||||||
|
panel.settings->beginAttributesTransaction();
|
||||||
if ( scope == Scope::User )
|
if ( scope == Scope::User )
|
||||||
addUserSettings( panel );
|
addUserSettings( panel );
|
||||||
else
|
else
|
||||||
addProjectSettings( panel );
|
addProjectSettings( panel );
|
||||||
setupCategories( panel );
|
setupCategories( panel );
|
||||||
|
panel.settings->endAttributesTransaction();
|
||||||
filter( panel );
|
filter( panel );
|
||||||
panel.connections += panel.search->connect(
|
panel.connections += panel.search->connect(
|
||||||
Event::OnTextChanged, [this, &panel]( const Event* ) { filter( panel ); } );
|
Event::OnTextChanged, [this, &panel]( const Event* ) { filter( panel ); } );
|
||||||
@@ -426,17 +505,87 @@ void SettingsPanel::addChoice( PanelState& panel, SettingBinding binding,
|
|||||||
panel.bindings.emplace_back( std::move( binding ) );
|
panel.bindings.emplace_back( std::move( binding ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SettingsPanel::addEditableChoice( PanelState& panel, SettingBinding binding,
|
||||||
|
const std::vector<String>& choices,
|
||||||
|
std::function<String()> get,
|
||||||
|
std::function<bool( const String& )> set ) {
|
||||||
|
auto* row = createRow( panel, binding );
|
||||||
|
auto* combo = mApp->getUISceneNode()
|
||||||
|
->loadLayoutFromString( SETTINGS_EDITABLE_CHOICE_LAYOUT,
|
||||||
|
row->find<UILinearLayout>( "setting_control" ) )
|
||||||
|
->asType<UIComboBox>();
|
||||||
|
combo->getListBox()->addListBoxItems( choices );
|
||||||
|
combo->setText( get() );
|
||||||
|
panel.connections +=
|
||||||
|
combo->connect( Event::OnValueChange, [combo, set = std::move( set )]( const Event* ) {
|
||||||
|
if ( !set( combo->getText() ) ) {
|
||||||
|
combo->addClass( "error" );
|
||||||
|
combo->getDropDownList()->addClass( "error" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
combo->removeClass( "error" );
|
||||||
|
combo->getDropDownList()->removeClass( "error" );
|
||||||
|
} );
|
||||||
|
panel.bindings.emplace_back( std::move( binding ) );
|
||||||
|
}
|
||||||
|
|
||||||
void SettingsPanel::addInteger( PanelState& panel, SettingBinding binding, int min, int max,
|
void SettingsPanel::addInteger( PanelState& panel, SettingBinding binding, int min, int max,
|
||||||
int* value, std::function<void( int )> apply ) {
|
std::function<int()> get, std::function<void( int )> set ) {
|
||||||
auto* row = createRow( panel, binding );
|
auto* row = createRow( panel, binding );
|
||||||
auto* spin = mApp->getUISceneNode()
|
auto* spin = mApp->getUISceneNode()
|
||||||
->loadLayoutFromString( SETTINGS_INTEGER_LAYOUT,
|
->loadLayoutFromString( SETTINGS_INTEGER_LAYOUT,
|
||||||
row->find<UILinearLayout>( "setting_control" ) )
|
row->find<UILinearLayout>( "setting_control" ) )
|
||||||
->asType<UISpinBox>();
|
->asType<UISpinBox>();
|
||||||
spin->setMinValue( min )->setMaxValue( max );
|
spin->setMinValue( min )->setMaxValue( max );
|
||||||
auto valueBinding = UIDataBind<int>::New( value, spin );
|
spin->unsetTabFocusable();
|
||||||
valueBinding->onValueChangeCb = std::move( apply );
|
spin->getButtonPushUp()->asType<UIWidget>()->unsetTabFocusable();
|
||||||
panel.bindingGroup += std::move( valueBinding );
|
spin->getButtonPushDown()->asType<UIWidget>()->unsetTabFocusable();
|
||||||
|
spin->setValue( get() );
|
||||||
|
panel.connections +=
|
||||||
|
spin->connect( Event::OnValueChange, [spin, set = std::move( set )]( const Event* ) {
|
||||||
|
set( static_cast<int>( spin->getValue() ) );
|
||||||
|
} );
|
||||||
|
panel.bindings.emplace_back( std::move( binding ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsPanel::addText( PanelState& panel, SettingBinding binding,
|
||||||
|
std::function<std::string()> get,
|
||||||
|
std::function<bool( const std::string& )> set ) {
|
||||||
|
auto* row = createRow( panel, binding );
|
||||||
|
auto* input = mApp->getUISceneNode()
|
||||||
|
->loadLayoutFromString( SETTINGS_TEXT_LAYOUT,
|
||||||
|
row->find<UILinearLayout>( "setting_control" ) )
|
||||||
|
->asType<UITextInput>();
|
||||||
|
input->setText( String::fromUtf8( get() ) );
|
||||||
|
panel.connections +=
|
||||||
|
input->connect( Event::OnTextChanged, [input, set = std::move( set )]( const Event* ) {
|
||||||
|
std::string text = input->getText().toUtf8();
|
||||||
|
if ( !set( text ) ) {
|
||||||
|
input->addClass( "error" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
input->removeClass( "error" );
|
||||||
|
} );
|
||||||
|
panel.bindings.emplace_back( std::move( binding ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsPanel::addFloat( PanelState& panel, SettingBinding binding, double min, double max,
|
||||||
|
double step, std::function<double()> get,
|
||||||
|
std::function<void( double )> set ) {
|
||||||
|
auto* row = createRow( panel, binding );
|
||||||
|
auto* spin = mApp->getUISceneNode()
|
||||||
|
->loadLayoutFromString( SETTINGS_INTEGER_LAYOUT,
|
||||||
|
row->find<UILinearLayout>( "setting_control" ) )
|
||||||
|
->asType<UISpinBox>();
|
||||||
|
spin->setMinValue( min )->setMaxValue( max )->setClickStep( step );
|
||||||
|
spin->allowFloatingPoint( true )->setValue( get() );
|
||||||
|
spin->unsetTabFocusable();
|
||||||
|
spin->getButtonPushUp()->asType<UIWidget>()->unsetTabFocusable();
|
||||||
|
spin->getButtonPushDown()->asType<UIWidget>()->unsetTabFocusable();
|
||||||
|
panel.connections +=
|
||||||
|
spin->connect( Event::OnValueChange, [spin, set = std::move( set )]( const Event* ) {
|
||||||
|
set( spin->getValue() );
|
||||||
|
} );
|
||||||
panel.bindings.emplace_back( std::move( binding ) );
|
panel.bindings.emplace_back( std::move( binding ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -453,6 +602,43 @@ void SettingsPanel::addAction( PanelState& panel, SettingBinding binding, const
|
|||||||
panel.bindings.emplace_back( std::move( binding ) );
|
panel.bindings.emplace_back( std::move( binding ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void setNodeTreeEnabled( Node* node, bool enabled ) {
|
||||||
|
node->setEnabled( enabled );
|
||||||
|
for ( Node* child = node->getFirstChild(); child; child = child->getNextNode() )
|
||||||
|
setNodeTreeEnabled( child, enabled );
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool parseNonNegativeTime( const std::string& text, Time& time ) {
|
||||||
|
auto parts = String::split( text, " " );
|
||||||
|
bool hasValue = false;
|
||||||
|
for ( auto& part : parts ) {
|
||||||
|
String::trimInPlace( part );
|
||||||
|
if ( part.empty() )
|
||||||
|
continue;
|
||||||
|
size_t suffixLength =
|
||||||
|
String::endsWith( part, "ms" )
|
||||||
|
? 2
|
||||||
|
: ( String::endsWith( part, "s" ) || String::endsWith( part, "m" ) ? 1 : 0 );
|
||||||
|
std::string number = part.substr( 0, part.size() - suffixLength );
|
||||||
|
double value;
|
||||||
|
if ( number.empty() || !String::fromString( value, number ) || value < 0 )
|
||||||
|
return false;
|
||||||
|
hasValue = true;
|
||||||
|
}
|
||||||
|
if ( !hasValue )
|
||||||
|
return false;
|
||||||
|
time = Time::fromString( text );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsPanel::setCategoryEnabled( PanelState& panel, const std::string& category,
|
||||||
|
bool enabled, const std::string& excludedSetting ) {
|
||||||
|
for ( auto& binding : panel.bindings ) {
|
||||||
|
if ( binding.category == category && binding.id != excludedSetting && binding.row )
|
||||||
|
setNodeTreeEnabled( binding.row, enabled );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SettingsPanel::addUserSettings( PanelState& panel ) {
|
void SettingsPanel::addUserSettings( PanelState& panel ) {
|
||||||
addCategory( panel, "general.behavior", mApp->i18n( "general", "General" ),
|
addCategory( panel, "general.behavior", mApp->i18n( "general", "General" ),
|
||||||
mApp->i18n( "behavior", "Behavior" ) );
|
mApp->i18n( "behavior", "Behavior" ) );
|
||||||
@@ -665,7 +851,9 @@ void SettingsPanel::addUserSettings( PanelState& panel ) {
|
|||||||
mApp->i18n( "line_breaking_column", "Line Breaking Column" ),
|
mApp->i18n( "line_breaking_column", "Line Breaking Column" ),
|
||||||
mApp->i18n( "line_breaking_column_desc",
|
mApp->i18n( "line_breaking_column_desc",
|
||||||
"Column used for wrapping and the editor width guide. Set 0 to disable." ) },
|
"Column used for wrapping and the editor width guide. Set 0 to disable." ) },
|
||||||
0, 1000, &mApp->getConfig().doc.lineBreakingColumn, [this]( int value ) {
|
0, 1000, [this] { return mApp->getConfig().doc.lineBreakingColumn; },
|
||||||
|
[this]( int value ) {
|
||||||
|
mApp->getConfig().doc.lineBreakingColumn = value;
|
||||||
mApp->getSplitter()->forEachEditor(
|
mApp->getSplitter()->forEachEditor(
|
||||||
[value]( UICodeEditor* editor ) { editor->setLineBreakingColumn( value ); } );
|
[value]( UICodeEditor* editor ) { editor->setLineBreakingColumn( value ); } );
|
||||||
} );
|
} );
|
||||||
@@ -848,14 +1036,18 @@ void SettingsPanel::addUserSettings( PanelState& panel ) {
|
|||||||
editor->getDocument().setTabOutEnabled( value );
|
editor->getDocument().setTabOutEnabled( value );
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
addInteger( panel,
|
addInteger(
|
||||||
{ "indentWidth", "editor.document", mApp->i18n( "indent_width", "Indent Width" ),
|
panel,
|
||||||
mApp->i18n( "indent_width_desc", "Columns in one indentation level." ) },
|
{ "indentWidth", "editor.document", mApp->i18n( "indent_width", "Indent Width" ),
|
||||||
1, 16, &mApp->getConfig().doc.indentWidth );
|
mApp->i18n( "indent_width_desc", "Columns in one indentation level." ) },
|
||||||
addInteger( panel,
|
1, 16, [this] { return mApp->getConfig().doc.indentWidth; },
|
||||||
{ "tabWidth", "editor.document", mApp->i18n( "tab_width", "Tab Width" ),
|
[this]( int value ) { mApp->getConfig().doc.indentWidth = value; } );
|
||||||
mApp->i18n( "tab_width_desc", "Columns used to display a tab character." ) },
|
addInteger(
|
||||||
1, 16, &mApp->getConfig().doc.tabWidth );
|
panel,
|
||||||
|
{ "tabWidth", "editor.document", mApp->i18n( "tab_width", "Tab Width" ),
|
||||||
|
mApp->i18n( "tab_width_desc", "Columns used to display a tab character." ) },
|
||||||
|
1, 16, [this] { return mApp->getConfig().doc.tabWidth; },
|
||||||
|
[this]( int value ) { mApp->getConfig().doc.tabWidth = value; } );
|
||||||
addChoice(
|
addChoice(
|
||||||
panel,
|
panel,
|
||||||
{ "lineEndings", "editor.document", mApp->i18n( "line_endings", "Line Endings" ),
|
{ "lineEndings", "editor.document", mApp->i18n( "line_endings", "Line Endings" ),
|
||||||
@@ -1079,38 +1271,56 @@ void SettingsPanel::addUserSettings( PanelState& panel ) {
|
|||||||
mApp->i18n( "fallback_font_desc", "Choose the font used for missing glyphs." ) },
|
mApp->i18n( "fallback_font_desc", "Choose the font used for missing glyphs." ) },
|
||||||
mApp->i18n( "choose_font", "Choose Font..." ),
|
mApp->i18n( "choose_font", "Choose Font..." ),
|
||||||
[this] { mApp->runCommand( "fallback-font" ); } );
|
[this] { mApp->runCommand( "fallback-font" ); } );
|
||||||
addAction(
|
auto addFontSize = [this, &panel]( SettingBinding binding, std::function<std::string()> get,
|
||||||
panel,
|
std::function<void( const StyleSheetLength& )> set ) {
|
||||||
|
addText( panel, std::move( binding ), std::move( get ),
|
||||||
|
[set = std::move( set )]( const std::string& text ) {
|
||||||
|
if ( !StyleSheetLength::isLength( text ) )
|
||||||
|
return false;
|
||||||
|
set( StyleSheetLength::fromString( text ) );
|
||||||
|
return true;
|
||||||
|
} );
|
||||||
|
};
|
||||||
|
addFontSize(
|
||||||
{ "uiFontSize", "appearance.fonts", mApp->i18n( "ui_font_size", "UI Font Size" ),
|
{ "uiFontSize", "appearance.fonts", mApp->i18n( "ui_font_size", "UI Font Size" ),
|
||||||
mApp->i18n( "ui_font_size_desc", "Set the font size used by the application UI." ) },
|
mApp->i18n( "ui_font_size_desc", "Set the font size used by the application UI." ) },
|
||||||
mApp->i18n( "configure", "Configure..." ),
|
[this] { return mApp->getConfig().ui.fontSize.toString(); },
|
||||||
[this] { mApp->getSettingsActions()->setUIFontSize(); } );
|
[this]( const StyleSheetLength& size ) {
|
||||||
addAction(
|
mApp->getSettingsActions()->setUIFontSize( size );
|
||||||
panel,
|
} );
|
||||||
|
addFontSize(
|
||||||
{ "panelFontSize", "appearance.fonts",
|
{ "panelFontSize", "appearance.fonts",
|
||||||
mApp->i18n( "ui_panel_font_size", "Panel Font Size" ),
|
mApp->i18n( "ui_panel_font_size", "Panel Font Size" ),
|
||||||
mApp->i18n( "ui_panel_font_size_desc", "Set the font size used by side panels." ) },
|
mApp->i18n( "ui_panel_font_size_desc", "Set the font size used by side panels." ) },
|
||||||
mApp->i18n( "configure", "Configure..." ),
|
[this] { return mApp->getConfig().ui.panelFontSize.toString(); },
|
||||||
[this] { mApp->getSettingsActions()->setUIPanelFontSize(); } );
|
[this]( const StyleSheetLength& size ) {
|
||||||
addAction( panel,
|
mApp->getSettingsActions()->setUIPanelFontSize( size );
|
||||||
{ "editorFontSize", "appearance.fonts",
|
} );
|
||||||
mApp->i18n( "editor_font_size", "Editor Font Size" ),
|
addFontSize(
|
||||||
mApp->i18n( "editor_font_size_desc", "Set the default code editor font size." ) },
|
{ "editorFontSize", "appearance.fonts",
|
||||||
mApp->i18n( "configure", "Configure..." ),
|
mApp->i18n( "editor_font_size", "Editor Font Size" ),
|
||||||
[this] { mApp->getSettingsActions()->setEditorFontSize(); } );
|
mApp->i18n( "editor_font_size_desc", "Set the default code editor font size." ) },
|
||||||
addAction( panel,
|
[this] { return mApp->getConfig().editor.fontSize.toString(); },
|
||||||
{ "terminalFontSize", "appearance.fonts",
|
[this]( const StyleSheetLength& size ) {
|
||||||
mApp->i18n( "terminal_font_size", "Terminal Font Size" ),
|
mApp->getSettingsActions()->setEditorFontSize( size );
|
||||||
mApp->i18n( "terminal_font_size_desc",
|
} );
|
||||||
"Set the default integrated terminal font size." ) },
|
addFontSize(
|
||||||
mApp->i18n( "configure", "Configure..." ),
|
{ "terminalFontSize", "appearance.fonts",
|
||||||
[this] { mApp->getSettingsActions()->setTerminalFontSize(); } );
|
mApp->i18n( "terminal_font_size", "Terminal Font Size" ),
|
||||||
addAction( panel,
|
mApp->i18n( "terminal_font_size_desc",
|
||||||
{ "uiScaleFactor", "appearance.fonts",
|
"Set the default integrated terminal font size." ) },
|
||||||
mApp->i18n( "ui_scale_factor", "UI Scale Factor" ),
|
[this] { return mApp->getConfig().term.fontSize.toString(); },
|
||||||
mApp->i18n( "ui_scale_factor_desc", "Scale the complete user interface." ) },
|
[this]( const StyleSheetLength& size ) {
|
||||||
mApp->i18n( "configure", "Configure..." ),
|
mApp->getSettingsActions()->setTerminalFontSize( size );
|
||||||
[this] { mApp->getSettingsActions()->setUIScaleFactor(); } );
|
} );
|
||||||
|
addFloat(
|
||||||
|
panel,
|
||||||
|
{ "uiScaleFactor", "appearance.fonts", mApp->i18n( "ui_scale_factor", "UI Scale Factor" ),
|
||||||
|
mApp->i18n( "ui_scale_factor_desc",
|
||||||
|
"Scale the complete user interface from 1 to 6. Restart required." ) },
|
||||||
|
1, 6, 0.1,
|
||||||
|
[this] { return std::max<Float>( 1, mApp->getConfig().windowState.pixelDensity ); },
|
||||||
|
[this]( double value ) { mApp->getConfig().windowState.pixelDensity = value; } );
|
||||||
addBool( panel,
|
addBool( panel,
|
||||||
{ "editorFontInInputFields", "appearance.fonts",
|
{ "editorFontInInputFields", "appearance.fonts",
|
||||||
mApp->i18n( "editor_font_in_input_fields", "Editor Font in Input Fields" ),
|
mApp->i18n( "editor_font_in_input_fields", "Editor Font in Input Fields" ),
|
||||||
@@ -1202,25 +1412,59 @@ void SettingsPanel::addUserSettings( PanelState& panel ) {
|
|||||||
|
|
||||||
addCategory( panel, "editor.advanced", mApp->i18n( "editor", "Editor" ),
|
addCategory( panel, "editor.advanced", mApp->i18n( "editor", "Editor" ),
|
||||||
mApp->i18n( "advanced", "Advanced" ) );
|
mApp->i18n( "advanced", "Advanced" ) );
|
||||||
addAction( panel,
|
addText(
|
||||||
{ "lineSpacing", "editor.advanced", mApp->i18n( "line_spacing", "Line Spacing" ),
|
panel,
|
||||||
mApp->i18n( "line_spacing_desc",
|
{ "lineSpacing", "editor.advanced", mApp->i18n( "line_spacing", "Line Spacing" ),
|
||||||
"Set additional vertical spacing between editor lines." ) },
|
mApp->i18n( "line_spacing_desc",
|
||||||
mApp->i18n( "configure", "Configure..." ),
|
"Set additional vertical spacing between editor lines. Set 0 to disable." ) },
|
||||||
[this] { mApp->getSettingsActions()->setLineSpacing(); } );
|
[this] { return mApp->getConfig().editor.lineSpacing.toString(); },
|
||||||
addAction( panel,
|
[this]( const std::string& text ) {
|
||||||
{ "cursorBlinkingTime", "editor.advanced",
|
if ( !StyleSheetLength::isLength( text ) )
|
||||||
mApp->i18n( "cursor_blinking_time", "Cursor Blinking Time" ),
|
return false;
|
||||||
mApp->i18n( "cursor_blinking_time_desc", "Set the text cursor blink interval." ) },
|
mApp->getConfig().editor.lineSpacing = StyleSheetLength::fromString( text );
|
||||||
mApp->i18n( "configure", "Configure..." ),
|
mApp->getSplitter()->forEachEditor( [this]( UICodeEditor* editor ) {
|
||||||
[this] { mApp->getSettingsActions()->setCursorBlinkingTime(); } );
|
editor->setLineSpacing( mApp->getConfig().editor.lineSpacing );
|
||||||
addAction( panel,
|
} );
|
||||||
{ "indentTabCharacter", "editor.advanced",
|
return true;
|
||||||
mApp->i18n( "indent_tab_character", "Indent Tab Character" ),
|
} );
|
||||||
mApp->i18n( "indent_tab_character_desc",
|
addText(
|
||||||
"Choose the character inserted when indenting with Tab." ) },
|
panel,
|
||||||
mApp->i18n( "configure", "Configure..." ),
|
{ "cursorBlinkingTime", "editor.advanced",
|
||||||
[this] { mApp->getSettingsActions()->setIndentTabCharacter(); } );
|
mApp->i18n( "cursor_blinking_time", "Cursor Blinking Time" ),
|
||||||
|
mApp->i18n( "cursor_blinking_time_desc",
|
||||||
|
"Set the text cursor blink interval. Set 0 to disable." ) },
|
||||||
|
[this] { return mApp->getConfig().editor.cursorBlinkingTime.toString(); },
|
||||||
|
[this]( const std::string& text ) {
|
||||||
|
Time value;
|
||||||
|
if ( !parseNonNegativeTime( text, value ) )
|
||||||
|
return false;
|
||||||
|
mApp->getConfig().editor.cursorBlinkingTime = value;
|
||||||
|
mApp->getSplitter()->forEachEditor(
|
||||||
|
[value]( UICodeEditor* editor ) { editor->setCursorBlinkTime( value ); } );
|
||||||
|
return true;
|
||||||
|
} );
|
||||||
|
addEditableChoice(
|
||||||
|
panel,
|
||||||
|
{ "indentTabCharacter", "editor.advanced",
|
||||||
|
mApp->i18n( "indent_tab_character", "Indent Tab Character" ),
|
||||||
|
mApp->i18n( "indent_tab_character_desc",
|
||||||
|
"Choose the character inserted when indenting with Tab." ) },
|
||||||
|
{ String( u8"»" ), String( u8"→" ), String( u8"⇒" ), String( u8"↪" ), String( u8"⇢" ),
|
||||||
|
String( u8"↣" ) },
|
||||||
|
[this] {
|
||||||
|
return mApp->getConfig().editor.tabIndentCharacter.empty()
|
||||||
|
? String( u8"»" )
|
||||||
|
: String::fromUtf8( mApp->getConfig().editor.tabIndentCharacter );
|
||||||
|
},
|
||||||
|
[this]( const String& value ) {
|
||||||
|
if ( value.size() != 1 )
|
||||||
|
return false;
|
||||||
|
mApp->getConfig().editor.tabIndentCharacter = value.toUtf8();
|
||||||
|
mApp->getSplitter()->forEachEditor( [character = value[0]]( UICodeEditor* editor ) {
|
||||||
|
editor->setTabIndentCharacter( character );
|
||||||
|
} );
|
||||||
|
return true;
|
||||||
|
} );
|
||||||
addChoice(
|
addChoice(
|
||||||
panel,
|
panel,
|
||||||
{ "indentTabAlignment", "editor.advanced",
|
{ "indentTabAlignment", "editor.advanced",
|
||||||
@@ -1244,20 +1488,38 @@ void SettingsPanel::addUserSettings( PanelState& panel ) {
|
|||||||
mApp->getSplitter()->forEachEditor(
|
mApp->getSplitter()->forEachEditor(
|
||||||
[value]( UICodeEditor* editor ) { editor->setTabIndentAlignment( value ); } );
|
[value]( UICodeEditor* editor ) { editor->setTabIndentAlignment( value ); } );
|
||||||
} );
|
} );
|
||||||
addAction( panel,
|
addText(
|
||||||
{ "foldRefreshFrequency", "editor.advanced",
|
panel,
|
||||||
mApp->i18n( "folds_refresh_freq", "Folds Refresh Frequency" ),
|
{ "foldRefreshFrequency", "editor.advanced",
|
||||||
mApp->i18n( "folds_refresh_freq_desc",
|
mApp->i18n( "folds_refresh_freq", "Folds Refresh Frequency" ),
|
||||||
"Set how frequently code folding ranges are recalculated." ) },
|
mApp->i18n(
|
||||||
mApp->i18n( "configure", "Configure..." ),
|
"folds_refresh_freq_desc",
|
||||||
[this] { mApp->getSettingsActions()->setFoldRefreshFreq(); } );
|
"Set how frequently code folding ranges are recalculated (minimum 1 second)." ) },
|
||||||
addAction( panel,
|
[this] { return mApp->getConfig().editor.codeFoldingRefreshFreq.toString(); },
|
||||||
{ "tabOutCharacters", "editor.advanced",
|
[this]( const std::string& text ) {
|
||||||
mApp->i18n( "set_tab_out_characters", "Set Tab Out Characters" ),
|
Time value;
|
||||||
mApp->i18n( "set_tab_out_characters_message",
|
if ( !parseNonNegativeTime( text, value ) || value < Seconds( 1 ) )
|
||||||
"Set the characters the cursor can move past when pressing Tab." ) },
|
return false;
|
||||||
mApp->i18n( "configure", "Configure..." ),
|
mApp->getConfig().editor.codeFoldingRefreshFreq = value;
|
||||||
[this] { mApp->getSettingsActions()->setTabOutChars(); } );
|
mApp->getSplitter()->forEachEditor(
|
||||||
|
[value]( UICodeEditor* editor ) { editor->setFoldsRefreshTime( value ); } );
|
||||||
|
return true;
|
||||||
|
} );
|
||||||
|
addText(
|
||||||
|
panel,
|
||||||
|
{ "tabOutCharacters", "editor.advanced",
|
||||||
|
mApp->i18n( "set_tab_out_characters", "Set Tab Out Characters" ),
|
||||||
|
mApp->i18n( "set_tab_out_characters_message",
|
||||||
|
"Set the characters the cursor can move past when pressing Tab." ) },
|
||||||
|
[this] { return mApp->getConfig().doc.tabOutChars; },
|
||||||
|
[this]( const std::string& text ) {
|
||||||
|
mApp->getConfig().doc.tabOutChars = text;
|
||||||
|
String characters = String::fromUtf8( text );
|
||||||
|
mApp->getSplitter()->forEachEditor( [&characters]( UICodeEditor* editor ) {
|
||||||
|
editor->getDocument().setTabOutChars( characters );
|
||||||
|
} );
|
||||||
|
return true;
|
||||||
|
} );
|
||||||
|
|
||||||
addCategory( panel, "window.screenshots", mApp->i18n( "window", "Window" ),
|
addCategory( panel, "window.screenshots", mApp->i18n( "window", "Window" ),
|
||||||
mApp->i18n( "screenshots", "Screenshots" ) );
|
mApp->i18n( "screenshots", "Screenshots" ) );
|
||||||
@@ -1267,20 +1529,40 @@ void SettingsPanel::addUserSettings( PanelState& panel ) {
|
|||||||
mApp->i18n( "screenshot_save_path_desc", "Choose where screenshots are saved." ) },
|
mApp->i18n( "screenshot_save_path_desc", "Choose where screenshots are saved." ) },
|
||||||
mApp->i18n( "configure", "Configure..." ),
|
mApp->i18n( "configure", "Configure..." ),
|
||||||
[this] { mApp->getSettingsActions()->setScreenshotSavePath(); } );
|
[this] { mApp->getSettingsActions()->setScreenshotSavePath(); } );
|
||||||
addAction( panel,
|
addText(
|
||||||
{ "screenshotFilenamePattern", "window.screenshots",
|
panel,
|
||||||
mApp->i18n( "set_screenshot_filename_pattern", "Screenshot Filename Pattern" ),
|
{ "screenshotFilenamePattern", "window.screenshots",
|
||||||
mApp->i18n( "screenshot_filename_pattern_desc",
|
mApp->i18n( "set_screenshot_filename_pattern", "Screenshot Filename Pattern" ),
|
||||||
"Configure the timestamp-based screenshot filename pattern." ) },
|
mApp->i18n( "screenshot_filename_pattern_desc",
|
||||||
mApp->i18n( "configure", "Configure..." ),
|
"Set the timestamp-based screenshot filename pattern." ) },
|
||||||
[this] { mApp->getSettingsActions()->setScreenshotFilenamePattern(); } );
|
[this] { return mApp->getConfig().screenshot.filenamePattern; },
|
||||||
addAction(
|
[this]( const std::string& pattern ) {
|
||||||
|
std::string filename = DateTimeController::formatCurrentDate( pattern );
|
||||||
|
if ( !DateTimeController::isValidDateFormat( pattern ) || filename.empty() ||
|
||||||
|
filename.find_first_of( "<>:\"/\\|?*" ) != std::string::npos )
|
||||||
|
return false;
|
||||||
|
mApp->getConfig().screenshot.filenamePattern = pattern;
|
||||||
|
return true;
|
||||||
|
} );
|
||||||
|
static const std::vector<String> screenshotFormats{ "PNG", "JPG", "WEBP", "QOI",
|
||||||
|
"BMP", "TGA", "DDS" };
|
||||||
|
auto screenshotFormat = String( mApp->getConfig().screenshot.saveFormat ).toUpper().toUtf8();
|
||||||
|
auto selectedScreenshotFormat = std::find( screenshotFormats.begin(), screenshotFormats.end(),
|
||||||
|
String::fromUtf8( screenshotFormat ) );
|
||||||
|
addChoice(
|
||||||
panel,
|
panel,
|
||||||
{ "screenshotSaveFormat", "window.screenshots",
|
{ "screenshotSaveFormat", "window.screenshots",
|
||||||
mApp->i18n( "set_screenshot_save_format", "Screenshot Save Format" ),
|
mApp->i18n( "set_screenshot_save_format", "Screenshot Save Format" ),
|
||||||
mApp->i18n( "screenshot_save_format_desc", "Choose the image format for screenshots." ) },
|
mApp->i18n( "screenshot_save_format_desc", "Choose the image format for screenshots." ) },
|
||||||
mApp->i18n( "configure", "Configure..." ),
|
screenshotFormats,
|
||||||
[this] { mApp->getSettingsActions()->setScreenshotSaveFormat(); } );
|
[selected = static_cast<size_t>(
|
||||||
|
selectedScreenshotFormat == screenshotFormats.end()
|
||||||
|
? 0
|
||||||
|
: selectedScreenshotFormat - screenshotFormats.begin() )] { return selected; },
|
||||||
|
[this]( size_t selected ) {
|
||||||
|
String format = screenshotFormats[std::min( selected, screenshotFormats.size() - 1 )];
|
||||||
|
mApp->getConfig().screenshot.saveFormat = format.toLower().toUtf8();
|
||||||
|
} );
|
||||||
|
|
||||||
addCategory( panel, "window.renderer", mApp->i18n( "window", "Window" ),
|
addCategory( panel, "window.renderer", mApp->i18n( "window", "Window" ),
|
||||||
mApp->i18n( "renderer", "Renderer" ) );
|
mApp->i18n( "renderer", "Renderer" ) );
|
||||||
@@ -1296,17 +1578,19 @@ void SettingsPanel::addUserSettings( PanelState& panel ) {
|
|||||||
"Vsync configuration changed.\nRestart ecode to see the changes." )
|
"Vsync configuration changed.\nRestart ecode to see the changes." )
|
||||||
.unescape() );
|
.unescape() );
|
||||||
} );
|
} );
|
||||||
addInteger( panel,
|
addInteger(
|
||||||
{ "frameRateLimit", "window.renderer",
|
panel,
|
||||||
mApp->i18n( "frame_rate_limit", "Frame Rate Limit" ),
|
{ "frameRateLimit", "window.renderer", mApp->i18n( "frame_rate_limit", "Frame Rate Limit" ),
|
||||||
mApp->i18n( "frame_rate_limit_desc",
|
mApp->i18n( "frame_rate_limit_desc",
|
||||||
"Limit rendered frames per second. Set 0 to disable." ) },
|
"Limit rendered frames per second. Set 0 to disable." ) },
|
||||||
0, 1000, &mApp->getConfig().context.FrameRateLimit, [this]( int value ) {
|
0, 1000, [this] { return mApp->getConfig().context.FrameRateLimit; },
|
||||||
mApp->saveConfig();
|
[this]( int value ) {
|
||||||
mApp->getWindow()->setFrameRateLimit( value );
|
mApp->getConfig().context.FrameRateLimit = value;
|
||||||
mApp->getNotificationCenter()->addNotification(
|
mApp->saveConfig();
|
||||||
mApp->i18n( "frame_rate_limit_applied", "Frame Rate Limit Applied" ) );
|
mApp->getWindow()->setFrameRateLimit( value );
|
||||||
} );
|
mApp->getNotificationCenter()->addNotification(
|
||||||
|
mApp->i18n( "frame_rate_limit_applied", "Frame Rate Limit Applied" ) );
|
||||||
|
} );
|
||||||
std::vector<GraphicsLibraryVersion> rendererVersions =
|
std::vector<GraphicsLibraryVersion> rendererVersions =
|
||||||
Renderer::getAvailableGraphicsLibraryVersions();
|
Renderer::getAvailableGraphicsLibraryVersions();
|
||||||
std::vector<String> rendererVersionNames;
|
std::vector<String> rendererVersionNames;
|
||||||
@@ -1427,13 +1711,18 @@ void SettingsPanel::addUserSettings( PanelState& panel ) {
|
|||||||
"Set the shell executable and command-line arguments." ) },
|
"Set the shell executable and command-line arguments." ) },
|
||||||
mApp->i18n( "configure", "Configure..." ),
|
mApp->i18n( "configure", "Configure..." ),
|
||||||
[this] { mApp->runCommand( "configure-terminal-shell" ); } );
|
[this] { mApp->runCommand( "configure-terminal-shell" ); } );
|
||||||
addAction( panel,
|
addInteger(
|
||||||
{ "terminalScrollback", "terminal.behavior",
|
panel,
|
||||||
mApp->i18n( "configure_terminal_scrollback", "Configure Terminal Scrollback" ),
|
{ "terminalScrollback", "terminal.behavior",
|
||||||
mApp->i18n( "configure_terminal_scrollback_desc",
|
mApp->i18n( "terminal_scrollback", "Terminal Scrollback" ),
|
||||||
"Set the number of terminal history lines retained." ) },
|
mApp->i18n( "configure_terminal_scrollback_desc",
|
||||||
mApp->i18n( "configure", "Configure..." ),
|
"Set the number of terminal history lines retained." ) },
|
||||||
[this] { mApp->runCommand( "configure-terminal-scrollback" ); } );
|
0, std::numeric_limits<int>::max(),
|
||||||
|
[this] {
|
||||||
|
return static_cast<int>( std::min<Uint64>( mApp->getConfig().term.scrollback,
|
||||||
|
std::numeric_limits<int>::max() ) );
|
||||||
|
},
|
||||||
|
[this]( int value ) { mApp->getConfig().term.scrollback = static_cast<Uint64>( value ); } );
|
||||||
addAction( panel,
|
addAction( panel,
|
||||||
{ "terminalWorkingDirectory", "terminal.behavior",
|
{ "terminalWorkingDirectory", "terminal.behavior",
|
||||||
mApp->i18n( "configure_terminal_working_dir",
|
mApp->i18n( "configure_terminal_working_dir",
|
||||||
@@ -1558,7 +1847,10 @@ void SettingsPanel::addProjectSettings( PanelState& panel ) {
|
|||||||
mApp->i18n( "use_global_settings", "Use Global Settings" ),
|
mApp->i18n( "use_global_settings", "Use Global Settings" ),
|
||||||
mApp->i18n( "use_global_settings_desc",
|
mApp->i18n( "use_global_settings_desc",
|
||||||
"Inherit document defaults from the user settings." ) },
|
"Inherit document defaults from the user settings." ) },
|
||||||
&mApp->getProjectConfig().useGlobalSettings );
|
&mApp->getProjectConfig().useGlobalSettings, [this, &panel]( bool useGlobalSettings ) {
|
||||||
|
setCategoryEnabled( panel, "editor.document", !useGlobalSettings,
|
||||||
|
"useGlobalSettings" );
|
||||||
|
} );
|
||||||
auto addProjectBool = [this, &panel]( std::string id, const char* nameKey, const char* name,
|
auto addProjectBool = [this, &panel]( std::string id, const char* nameKey, const char* name,
|
||||||
const char* descriptionKey, const char* description,
|
const char* descriptionKey, const char* description,
|
||||||
bool DocumentConfig::* member ) {
|
bool DocumentConfig::* member ) {
|
||||||
@@ -1602,22 +1894,27 @@ void SettingsPanel::addProjectSettings( PanelState& panel ) {
|
|||||||
addProjectBool( "writeUnicodeBOM", "write_unicode_bom", "Write Unicode BOM",
|
addProjectBool( "writeUnicodeBOM", "write_unicode_bom", "Write Unicode BOM",
|
||||||
"write_unicode_bom_desc", "Write a Unicode byte-order mark when saving.",
|
"write_unicode_bom_desc", "Write a Unicode byte-order mark when saving.",
|
||||||
&DocumentConfig::writeUnicodeBOM );
|
&DocumentConfig::writeUnicodeBOM );
|
||||||
addInteger( panel,
|
addInteger(
|
||||||
{ "indentWidth", "editor.document", mApp->i18n( "indent_width", "Indent Width" ),
|
panel,
|
||||||
mApp->i18n( "indent_width_desc",
|
{ "indentWidth", "editor.document", mApp->i18n( "indent_width", "Indent Width" ),
|
||||||
"Number of columns inserted for one indentation level." ) },
|
mApp->i18n( "indent_width_desc",
|
||||||
1, 16, &mApp->getProjectConfig().doc.indentWidth );
|
"Number of columns inserted for one indentation level." ) },
|
||||||
|
1, 16, [this] { return mApp->getProjectConfig().doc.indentWidth; },
|
||||||
|
[this]( int value ) { mApp->getProjectConfig().doc.indentWidth = value; } );
|
||||||
addInteger(
|
addInteger(
|
||||||
panel,
|
panel,
|
||||||
{ "tabWidth", "editor.document", mApp->i18n( "tab_width", "Tab Width" ),
|
{ "tabWidth", "editor.document", mApp->i18n( "tab_width", "Tab Width" ),
|
||||||
mApp->i18n( "tab_width_desc", "Number of columns used to display a tab character." ) },
|
mApp->i18n( "tab_width_desc", "Number of columns used to display a tab character." ) },
|
||||||
1, 16, &mApp->getProjectConfig().doc.tabWidth );
|
1, 16, [this] { return mApp->getProjectConfig().doc.tabWidth; },
|
||||||
addInteger( panel,
|
[this]( int value ) { mApp->getProjectConfig().doc.tabWidth = value; } );
|
||||||
{ "lineBreakingColumn", "editor.document",
|
addInteger(
|
||||||
mApp->i18n( "line_breaking_column", "Line Breaking Column" ),
|
panel,
|
||||||
mApp->i18n( "line_breaking_column_desc",
|
{ "lineBreakingColumn", "editor.document",
|
||||||
"Column used for wrapping and the editor width guide." ) },
|
mApp->i18n( "line_breaking_column", "Line Breaking Column" ),
|
||||||
0, 1000, &mApp->getProjectConfig().doc.lineBreakingColumn );
|
mApp->i18n( "line_breaking_column_desc",
|
||||||
|
"Column used for wrapping and the editor width guide." ) },
|
||||||
|
0, 1000, [this] { return mApp->getProjectConfig().doc.lineBreakingColumn; },
|
||||||
|
[this]( int value ) { mApp->getProjectConfig().doc.lineBreakingColumn = value; } );
|
||||||
addChoice(
|
addChoice(
|
||||||
panel,
|
panel,
|
||||||
{ "lineEndings", "editor.document", mApp->i18n( "line_endings", "Line Endings" ),
|
{ "lineEndings", "editor.document", mApp->i18n( "line_endings", "Line Endings" ),
|
||||||
@@ -1639,6 +1936,8 @@ void SettingsPanel::addProjectSettings( PanelState& panel ) {
|
|||||||
? TextFormat::LineEnding::CRLF
|
? TextFormat::LineEnding::CRLF
|
||||||
: ( selected == 2 ? TextFormat::LineEnding::CR : TextFormat::LineEnding::LF );
|
: ( selected == 2 ? TextFormat::LineEnding::CR : TextFormat::LineEnding::LF );
|
||||||
} );
|
} );
|
||||||
|
setCategoryEnabled( panel, "editor.document", !mApp->getProjectConfig().useGlobalSettings,
|
||||||
|
"useGlobalSettings" );
|
||||||
|
|
||||||
addCategory( panel, "languages.file_associations", mApp->i18n( "languages", "Languages" ),
|
addCategory( panel, "languages.file_associations", mApp->i18n( "languages", "Languages" ),
|
||||||
mApp->i18n( "file_associations", "File Associations" ) );
|
mApp->i18n( "file_associations", "File Associations" ) );
|
||||||
|
|||||||
@@ -67,12 +67,21 @@ class SettingsPanel {
|
|||||||
void addChoice( PanelState& state, SettingBinding binding, const std::vector<String>& choices,
|
void addChoice( PanelState& state, SettingBinding binding, const std::vector<String>& choices,
|
||||||
std::function<size_t()> get, std::function<void( size_t )> set,
|
std::function<size_t()> get, std::function<void( size_t )> set,
|
||||||
std::vector<String> choiceDescriptions = {} );
|
std::vector<String> choiceDescriptions = {} );
|
||||||
void addInteger( PanelState& state, SettingBinding binding, int min, int max, int* value,
|
void addEditableChoice( PanelState& state, SettingBinding binding,
|
||||||
std::function<void( int )> apply = {} );
|
const std::vector<String>& choices, std::function<String()> get,
|
||||||
|
std::function<bool( const String& )> set );
|
||||||
|
void addInteger( PanelState& state, SettingBinding binding, int min, int max,
|
||||||
|
std::function<int()> get, std::function<void( int )> set );
|
||||||
|
void addText( PanelState& state, SettingBinding binding, std::function<std::string()> get,
|
||||||
|
std::function<bool( const std::string& )> set );
|
||||||
|
void addFloat( PanelState& state, SettingBinding binding, double min, double max, double step,
|
||||||
|
std::function<double()> get, std::function<void( double )> set );
|
||||||
void addAction( PanelState& state, SettingBinding binding, const String& buttonText,
|
void addAction( PanelState& state, SettingBinding binding, const String& buttonText,
|
||||||
std::function<void()> action );
|
std::function<void()> action );
|
||||||
UIWidget* createRow( PanelState& state, SettingBinding& binding );
|
UIWidget* createRow( PanelState& state, SettingBinding& binding );
|
||||||
UICheckBox* createBoolControl( PanelState& state, SettingBinding& binding );
|
UICheckBox* createBoolControl( PanelState& state, SettingBinding& binding );
|
||||||
|
void setCategoryEnabled( PanelState& state, const std::string& category, bool enabled,
|
||||||
|
const std::string& excludedSetting = {} );
|
||||||
void filter( PanelState& state );
|
void filter( PanelState& state );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ void TerminalManager::setUseFrameBuffer( bool useFrameBuffer ) {
|
|||||||
|
|
||||||
void TerminalManager::configureTerminalShell() {
|
void TerminalManager::configureTerminalShell() {
|
||||||
static const auto layout( R"xml(
|
static const auto layout( R"xml(
|
||||||
<window layout_width="300dp" layout_height="150dp" window-flags="default|shadow" window-title='@string(shell_configuration, "Shell Configuration")'>
|
<window layout_width="300dp" layout_height="150dp" window-flags="default|shadow|modal" window-title='@string(shell_configuration, "Shell Configuration")'>
|
||||||
<vbox lw="mp" lh="mp" padding="4dp">
|
<vbox lw="mp" lh="mp" padding="4dp">
|
||||||
<vbox lw="mp" lh="0" lw8="1">
|
<vbox lw="mp" lh="0" lw8="1">
|
||||||
<TextView text='@string(configure_default_shell, "Configure default shell")' font-size="14dp" margin-bottom="8dp" />
|
<TextView text='@string(configure_default_shell, "Configure default shell")' font-size="14dp" margin-bottom="8dp" />
|
||||||
@@ -265,7 +265,7 @@ void TerminalManager::configureTerminalScrollback() {
|
|||||||
|
|
||||||
void TerminalManager::configureTerminalWorkingDir() {
|
void TerminalManager::configureTerminalWorkingDir() {
|
||||||
static const auto layout( R"xml(
|
static const auto layout( R"xml(
|
||||||
<window layout_width="450dp" layout_height="154dp" window-flags="default|shadow"
|
<window layout_width="450dp" layout_height="154dp" window-flags="default|shadow|modal"
|
||||||
window-title='@string(terminal_working_dir_configuration, "Terminal Default Working Directory Configuration")'>
|
window-title='@string(terminal_working_dir_configuration, "Terminal Default Working Directory Configuration")'>
|
||||||
<vbox lw="mp" lh="wrap_content" padding="4dp">
|
<vbox lw="mp" lh="wrap_content" padding="4dp">
|
||||||
<TextView text='@string(configure_terminal_default_working_dir, "Configure Terminal default working directory:")' font-size="14dp" margin-bottom="8dp" />
|
<TextView text='@string(configure_terminal_default_working_dir, "Configure Terminal default working directory:")' font-size="14dp" margin-bottom="8dp" />
|
||||||
|
|||||||
Reference in New Issue
Block a user