diff --git a/bin/assets/colorschemes/colorschemes.conf b/bin/assets/colorschemes/colorschemes.conf index cc3f92c13..736081c68 100644 --- a/bin/assets/colorschemes/colorschemes.conf +++ b/bin/assets/colorschemes/colorschemes.conf @@ -1,33 +1,3 @@ -[lite] -background = #2e2e32 -text = #e1e1e6 -caret = #93DDFA -selection = #48484f -line_highlight = #343438 -line_number = #525259 -line_number2 = #83838f -line_number_background = #2e2e32 -whitespace = #54575b -line_break_column = #54575b99 -matching_bracket = #FFFFFF33 -matching_selection = #FFFFFF66 -matching_search = #181b1e -suggestion = #97979c,#252529 -suggestion_selected = #e1e1e6,#252529 - -normal = #e1e1e6 -symbol = #e1e1e6 -comment = #676b6f -keyword = #E58AC9 -keyword2 = #F77483 -number = #FFA94D -literal = #FFA94D -string = #f7c95c -operator = #93DDFA -function = #93DDFA -link = #93DDFA -link_hover = transparent,underline - [eepp] background = #282a36 text = #e1e1e6 @@ -58,6 +28,36 @@ function = #00dc7f,shadow link = #6ae0f9,shadow link_hover = transparent,shadow,underline +[lite] +background = #2e2e32 +text = #e1e1e6 +caret = #93DDFA +selection = #48484f +line_highlight = #343438 +line_number = #525259 +line_number2 = #83838f +line_number_background = #2e2e32 +whitespace = #54575b +line_break_column = #54575b99 +matching_bracket = #FFFFFF33 +matching_selection = #FFFFFF66 +matching_search = #181b1e +suggestion = #97979c,#252529 +suggestion_selected = #e1e1e6,#252529 + +normal = #e1e1e6 +symbol = #e1e1e6 +comment = #676b6f +keyword = #E58AC9 +keyword2 = #F77483 +number = #FFA94D +literal = #FFA94D +string = #f7c95c +operator = #93DDFA +function = #93DDFA +link = #93DDFA +link_hover = transparent,underline + [fall] background = #343233 text = #c4b398 @@ -269,3 +269,173 @@ literal = #2aa198 string = #2aa198 operator = #859900 function = #268bd2 + +[cold lime] +background = #073642 +text = #00d1d1 +caret = #f053f3 +accent = #f053f3 +selection = #415256 +line_number = #586e75 +line_number2 = #f053f3 +line_highlight = #415256 + +normal = #00d1d1 +symbol = #00ff7f +comment = #6c71c4 +keyword = #6c71c4 +keyword2 = #6c71c4 +number = #00ff7f +literal = #1586d2 +string = #f7f97d +operator = #00ff7f +function = #55ffff + +[duotone] +background = #151515 +text = #707070 +caret = #dfdfdf +accent = #d0d0d0 +selection = #242424 +line_number = #252525 +line_number2 = #444444 +line_highlight = #101010 + +normal = #a0a0a0 +symbol = #a0a0a0 +comment = #404040 +keyword = #dfdfdf +keyword2 = #dfdfdf +number = #dfdfdf +literal = #dfdfdf +string = #dfdfdf +operator = #01A870 +function = #01A870 + +[vscode dark] +background = #1E1E1E +text = #D4D4D4 +caret = #FFFFFF +accent = #76BCFF +selection = #264F78 +line_number = #707070 +line_number2 = #A0A0A0 +line_highlight = #333A40 + +normal = #D4D4D4 +symbol = #D4D4D4 +comment = #6A9955 +keyword = #569CD6 +keyword2 = #C586C0 +number = #B5CEA8 +literal = #569CD6 +string = #CE9178 +operator = #8590A5 +function = #DCDCAA + +[zenburn] +background = #404040 +text = #dcdccc +caret = #f8f8f0 +accent = #dcdccc +selection = #2f2f2f +line_number = #545454 +line_number2 = #545454 +line_highlight = #383838 + +normal = #dcdccc +symbol = #dcdccc +comment = #7f9f7f +keyword = #f0dfaf +keyword2 = #dfdfbf +number = #8cd0d3 +literal = #dfaf8f +string = #cc9393 +operator = #f0efd0 +function = #efef8f + +[nord] +background = #2E3440 +text = #D8DEE9 +caret = #D8DEE9 +accent = #88C0D0 +selection = #434C5E +line_number = #4C566A +line_number2 = #D8DEE9 +line_highlight = #434C5E + +normal = #ECEFF4 +symbol = #D8DEE9 +comment = #4C566A +keyword = #81A1C1 +keyword2 = #81A1C1 +number = #B48EAD +literal = #81A1C1 +string = #A3BE8C +operator = #81A1C1 +function = #88C0D0 + +[only dark] +background = #242424 +text = #fffff0 +caret = #69FF94 +accent = #ff0fff +dim = #0fffff +divider = #7b7f8b +selection = #48484f +line_number = #525259 +line_number2 = #f6f6e0 +line_highlight = #343438 + +normal = #e1e1e6 +symbol = #97e1f1 +comment = #676b6f +keyword = #E58AC9 +keyword2 = #F77483 +number = #FFA94D +literal = #ee6666 +string = #f7c95c +operator = #93DDFA +function = #bf9eee + +[moe] +background = #f7f9f9 +text = #404040 +caret = #ff5971 +accent = #ff5971 +selection = #fde6eb +line_number = #d0d0d0 +line_number2 = #808080 +line_highlight = #f2f2f2 + +normal = #181818 +symbol = #181818 +comment = #43cdbd +keyword = #5f7dcd +keyword2 = #9c53c6 +number = #3daee9 +literal = #3daee9 +string = #3daee9 +operator = #5f7dcd +function = #9c53c6 + +[solarobj] +background = #fdf6e3 +text = #b2ada1 +caret = #b2ada1 +accent = #6c71c4 +selection = #eee8d5 +line_number = #93a1a1 +line_number2 = #002b36 +line_highlight = #fcefcd + +normal = #3e3c37 +symbol = #4c4f82 +comment = #93a1a1 +keyword = #d33682 +keyword2 = #6c71c4 +number = #859900 +literal = #b58900 +string = #cb4b16 +operator = #859900 +function = #268bd2 diff --git a/include/eepp/scene/event.hpp b/include/eepp/scene/event.hpp index 56b57ea10..06870b6a1 100644 --- a/include/eepp/scene/event.hpp +++ b/include/eepp/scene/event.hpp @@ -81,6 +81,8 @@ class EE_API Event { OnCreateContextMenu, OnDocumentMoved, UserEvent, + OnMenuShow, + OnMenuHide, NoEvent = eeINDEX_NOT_FOUND }; diff --git a/include/eepp/ui/uimenu.hpp b/include/eepp/ui/uimenu.hpp index 1da270e94..204734b56 100644 --- a/include/eepp/ui/uimenu.hpp +++ b/include/eepp/ui/uimenu.hpp @@ -41,7 +41,9 @@ class EE_API UIMenu : public UIWidget { UIWidget* getItem( const Uint32& index ); - UIWidget* getItem( const String& text ); + UIMenuItem* getItem( const String& text ); + + UIMenuItem* getItemId( const String& id ); Uint32 getItemIndex( UIWidget* item ); diff --git a/include/eepp/ui/uiscenenode.hpp b/include/eepp/ui/uiscenenode.hpp index ceead6f08..16c349126 100644 --- a/include/eepp/ui/uiscenenode.hpp +++ b/include/eepp/ui/uiscenenode.hpp @@ -52,6 +52,8 @@ class EE_API UISceneNode : public SceneNode { String getTranslatorString( const std::string& str, const String& defaultValue ); + String getTranslatorStringFromKey( const std::string& key, const String& defaultValue ); + UIWidget* loadLayoutFromFile( const std::string& layoutPath, Node* parent = NULL ); UIWidget* loadLayoutFromString( const std::string& layoutString, Node* parent = NULL ); diff --git a/src/eepp/ui/doc/textdocument.cpp b/src/eepp/ui/doc/textdocument.cpp index 31e94d38f..4aef6f86d 100644 --- a/src/eepp/ui/doc/textdocument.cpp +++ b/src/eepp/ui/doc/textdocument.cpp @@ -232,6 +232,8 @@ bool TextDocument::getAutoDetectIndentType() const { } void TextDocument::setAutoDetectIndentType( bool autodetect ) { + if ( !mAutoDetectIndentType && autodetect ) + guessIndentType(); mAutoDetectIndentType = autodetect; } diff --git a/src/eepp/ui/uimenu.cpp b/src/eepp/ui/uimenu.cpp index afc5c8d8d..957a7b162 100644 --- a/src/eepp/ui/uimenu.cpp +++ b/src/eepp/ui/uimenu.cpp @@ -161,12 +161,14 @@ UIWidget* UIMenu::add( UIWidget* widget ) { widget->setPixelsPosition( mPaddingPx.Left, mPaddingPx.Top + mNextPosY ); mNextPosY += widget->getPixelsSize().getHeight(); mItems.push_back( widget ); - widget->addEventListener( Event::OnSizeChange, [&]( const Event* ) { + auto cb = [&]( const Event* ) { if ( !mResizing ) { widgetsSetPos(); widgetsResize(); } - } ); + }; + widget->addEventListener( Event::OnVisibleChange, cb ); + widget->addEventListener( Event::OnSizeChange, cb ); resizeMe(); return widget; } @@ -200,7 +202,7 @@ UIWidget* UIMenu::getItem( const Uint32& index ) { return mItems[index]; } -UIWidget* UIMenu::getItem( const String& text ) { +UIMenuItem* UIMenu::getItem( const String& text ) { for ( Uint32 i = 0; i < mItems.size(); i++ ) { if ( mItems[i]->isType( UI_TYPE_MENUITEM ) ) { UIMenuItem* tMenuItem = mItems[i]->asType(); @@ -211,6 +213,17 @@ UIWidget* UIMenu::getItem( const String& text ) { return nullptr; } +UIMenuItem* UIMenu::getItemId( const String& id ) { + for ( Uint32 i = 0; i < mItems.size(); i++ ) { + if ( mItems[i]->isType( UI_TYPE_MENUITEM ) ) { + UIMenuItem* tMenuItem = mItems[i]->asType(); + if ( tMenuItem->getId() == id ) + return tMenuItem; + } + } + return nullptr; +} + Uint32 UIMenu::getItemIndex( UIWidget* item ) { for ( Uint32 i = 0; i < mItems.size(); i++ ) { if ( mItems[i] == item ) @@ -353,8 +366,10 @@ void UIMenu::widgetsSetPos() { for ( i = 0; i < mItems.size(); i++ ) { UIWidget* widget = mItems[i]; - widget->setPixelsPosition( mPaddingPx.Left, mPaddingPx.Top + mNextPosY ); - mNextPosY += widget->getPixelsSize().getHeight(); + if ( widget->isVisible() ) { + widget->setPixelsPosition( mPaddingPx.Left, mPaddingPx.Top + mNextPosY ); + mNextPosY += widget->getPixelsSize().getHeight(); + } } resizeMe(); diff --git a/src/eepp/ui/uimenusubmenu.cpp b/src/eepp/ui/uimenusubmenu.cpp index 86fac9a9c..b7364d189 100644 --- a/src/eepp/ui/uimenusubmenu.cpp +++ b/src/eepp/ui/uimenusubmenu.cpp @@ -82,6 +82,7 @@ UIMenu* UIMenuSubMenu::getSubMenu() const { } void UIMenuSubMenu::showSubMenu() { + sendCommonEvent( Event::OnMenuShow ); UIMenu* menu = getParent()->asType(); mSubMenu->setParent( menu->getParent() ); Vector2f pos = getPixelsPosition(); diff --git a/src/eepp/ui/uipopupmenu.cpp b/src/eepp/ui/uipopupmenu.cpp index 723e68fb6..d92d41a5b 100644 --- a/src/eepp/ui/uipopupmenu.cpp +++ b/src/eepp/ui/uipopupmenu.cpp @@ -52,6 +52,7 @@ bool UIPopUpMenu::show() { getUISceneNode()->getUIThemeManager()->getWidgetsFadeOutTime() ), Actions::Spawn::New( Actions::Enable::New(), Actions::Visible::New( true ) ) ) ); } + sendCommonEvent( Event::OnMenuShow ); setFocus(); return true; } @@ -80,6 +81,7 @@ bool UIPopUpMenu::hide() { close(); } safeHide(); + sendCommonEvent( Event::OnMenuHide ); return true; } return false; diff --git a/src/eepp/ui/uiscenenode.cpp b/src/eepp/ui/uiscenenode.cpp index 43fc78a67..a3ad05822 100644 --- a/src/eepp/ui/uiscenenode.cpp +++ b/src/eepp/ui/uiscenenode.cpp @@ -128,6 +128,16 @@ String UISceneNode::getTranslatorString( const std::string& str, const String& d return defaultValue; } +String UISceneNode::getTranslatorStringFromKey( const std::string& key, + const String& defaultValue ) { + String tstr = mTranslator.getString( key ); + + if ( !tstr.empty() ) + return tstr; + + return defaultValue; +} + void UISceneNode::setFocusLastWindow( UIWindow* window ) { if ( NULL != mEventDispatcher && !mWindowsList.empty() && window != mWindowsList.front() ) { mEventDispatcher->setFocusNode( mWindowsList.front() ); diff --git a/src/tools/ecode/appconfig.cpp b/src/tools/ecode/appconfig.cpp index f3af41b30..1b0c89b19 100644 --- a/src/tools/ecode/appconfig.cpp +++ b/src/tools/ecode/appconfig.cpp @@ -70,17 +70,17 @@ void AppConfig::load( const std::string& confPath, std::string& keybindingsPath, ui.colorScheme = ini.getValue( "ui", "ui_color_scheme", "dark" ) == "light" ? ColorSchemePreference::Light : ColorSchemePreference::Dark; - editor.trimTrailingWhitespaces = ini.getValueB( "editor", "trim_trailing_whitespaces", false ); - editor.forceNewLineAtEndOfFile = - ini.getValueB( "editor", "force_new_line_at_end_of_file", false ); - editor.autoDetectIndentType = ini.getValueB( "editor", "auto_detect_indent_type", true ); - editor.writeUnicodeBOM = ini.getValueB( "editor", "write_bom", false ); + doc.trimTrailingWhitespaces = ini.getValueB( "document", "trim_trailing_whitespaces", false ); + doc.forceNewLineAtEndOfFile = + ini.getValueB( "document", "force_new_line_at_end_of_file", false ); + doc.autoDetectIndentType = ini.getValueB( "document", "auto_detect_indent_type", true ); + doc.writeUnicodeBOM = ini.getValueB( "document", "write_bom", false ); + doc.indentWidth = ini.getValueI( "document", "indent_width", 4 ); + doc.indentSpaces = ini.getValueB( "document", "indent_spaces", false ); + doc.windowsLineEndings = ini.getValueB( "document", "windows_line_endings", false ); + doc.tabWidth = eemax( 2, ini.getValueI( "document", "tab_width", 4 ) ); + doc.lineBreakingColumn = eemax( 0, ini.getValueI( "document", "line_breaking_column", 100 ) ); editor.autoCloseBrackets = ini.getValue( "editor", "auto_close_brackets", "" ); - editor.indentWidth = ini.getValueI( "editor", "indent_width", 4 ); - editor.indentSpaces = ini.getValueB( "editor", "indent_spaces", false ); - editor.windowsLineEndings = ini.getValueB( "editor", "windows_line_endings", false ); - editor.tabWidth = eemax( 2, ini.getValueI( "editor", "tab_width", 4 ) ); - editor.lineBreakingColumn = eemax( 0, ini.getValueI( "editor", "line_breaking_column", 100 ) ); editor.highlightSelectionMatch = ini.getValueB( "editor", "highlight_selection_match", true ); editor.colorPickerSelection = ini.getValueB( "editor", "color_picker_selection", true ); editor.colorPreview = ini.getValueB( "editor", "color_preview", true ); @@ -140,16 +140,16 @@ void AppConfig::save( const std::vector& recentFiles, ini.setValue( "ui", "monospace_font", ui.monospaceFont ); ini.setValue( "ui", "ui_color_scheme", ui.colorScheme == ColorSchemePreference::Light ? "light" : "dark" ); - ini.setValueB( "editor", "trim_trailing_whitespaces", editor.trimTrailingWhitespaces ); - ini.setValueB( "editor", "force_new_line_at_end_of_file", editor.forceNewLineAtEndOfFile ); - ini.setValueB( "editor", "auto_detect_indent_type", editor.autoDetectIndentType ); - ini.setValueB( "editor", "write_bom", editor.writeUnicodeBOM ); + ini.setValueB( "document", "trim_trailing_whitespaces", doc.trimTrailingWhitespaces ); + ini.setValueB( "document", "force_new_line_at_end_of_file", doc.forceNewLineAtEndOfFile ); + ini.setValueB( "document", "auto_detect_indent_type", doc.autoDetectIndentType ); + ini.setValueB( "document", "write_bom", doc.writeUnicodeBOM ); + ini.setValueI( "document", "indent_width", doc.indentWidth ); + ini.setValueB( "document", "indent_spaces", doc.indentSpaces ); + ini.setValueB( "document", "windows_line_endings", doc.windowsLineEndings ); + ini.setValueI( "document", "tab_width", doc.tabWidth ); + ini.setValueI( "document", "line_breaking_column", doc.lineBreakingColumn ); ini.setValue( "editor", "auto_close_brackets", editor.autoCloseBrackets ); - ini.setValueI( "editor", "indent_width", editor.indentWidth ); - ini.setValueB( "editor", "indent_spaces", editor.indentSpaces ); - ini.setValueB( "editor", "windows_line_endings", editor.windowsLineEndings ); - ini.setValueI( "editor", "tab_width", editor.tabWidth ); - ini.setValueI( "editor", "line_breaking_column", editor.lineBreakingColumn ); ini.setValueB( "editor", "highlight_selection_match", editor.highlightSelectionMatch ); ini.setValueB( "editor", "color_picker_selection", editor.colorPickerSelection ); ini.setValueB( "editor", "color_preview", editor.colorPreview ); diff --git a/src/tools/ecode/appconfig.hpp b/src/tools/ecode/appconfig.hpp index df6e93d52..5d32abebc 100644 --- a/src/tools/ecode/appconfig.hpp +++ b/src/tools/ecode/appconfig.hpp @@ -46,12 +46,6 @@ struct CodeEditorConfig { bool verticalScrollbar{ true }; bool horizontalScrollbar{ true }; bool highlightCurrentLine{ true }; - bool trimTrailingWhitespaces{ false }; - bool forceNewLineAtEndOfFile{ false }; - bool autoDetectIndentType{ true }; - bool writeUnicodeBOM{ false }; - bool indentSpaces{ false }; - bool windowsLineEndings{ false }; bool highlightSelectionMatch{ true }; bool colorPickerSelection{ false }; bool colorPreview{ false }; @@ -65,6 +59,15 @@ struct CodeEditorConfig { bool syncProjectTreeWithEditor{ true }; bool autoCloseXMLTags{ true }; std::string autoCloseBrackets{ "" }; +}; + +struct DocumentConfig { + bool trimTrailingWhitespaces{ false }; + bool forceNewLineAtEndOfFile{ false }; + bool autoDetectIndentType{ true }; + bool writeUnicodeBOM{ false }; + bool indentSpaces{ false }; + bool windowsLineEndings{ false }; int indentWidth{ 4 }; int tabWidth{ 4 }; int lineBreakingColumn{ 100 }; @@ -73,6 +76,7 @@ struct CodeEditorConfig { struct AppConfig { WindowConfig window; CodeEditorConfig editor; + DocumentConfig doc; UIConfig ui; IniFile ini; IniFile iniState; diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index 786eb2b83..9fb1ed9e6 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -781,13 +781,12 @@ UIMenu* App::createViewMenu() { msgBox->setTitle( mWindowTitle ); msgBox->setCloseShortcut( { KEY_ESCAPE, 0 } ); msgBox->getTextInput()->setAllowOnlyNumbers( true, false ); - msgBox->getTextInput()->setText( - String::toString( mConfig.editor.lineBreakingColumn ) ); + msgBox->getTextInput()->setText( String::toString( mConfig.doc.lineBreakingColumn ) ); msgBox->showWhenReady(); msgBox->addEventListener( Event::MsgBoxConfirmClick, [&, msgBox]( const Event* ) { int val; if ( String::fromString( val, msgBox->getTextInput()->getText() ) && val >= 0 ) { - mConfig.editor.lineBreakingColumn = val; + mConfig.doc.lineBreakingColumn = val; mEditorSplitter->forEachEditor( [val]( UICodeEditor* editor ) { editor->setLineBreakingColumn( val ); } ); msgBox->closeWindow(); @@ -818,31 +817,55 @@ Drawable* App::findIcon( const std::string& name ) { return nullptr; } +String App::i18n( const std::string& name, const String& def ) { + return mUISceneNode->getTranslatorString( name, def ); +} + UIMenu* App::createEditMenu() { UIPopUpMenu* menu = UIPopUpMenu::New(); - menu->add( "Undo", findIcon( "undo" ), getKeybind( "undo" ) ); - menu->add( "Redo", findIcon( "redo" ), getKeybind( "redo" ) ); + menu->add( i18n( "undo", "Undo" ), findIcon( "undo" ), getKeybind( "undo" ) )->setId( "undo" ); + menu->add( i18n( "redo", "Redo" ), findIcon( "redo" ), getKeybind( "redo" ) )->setId( "redo" ); menu->addSeparator(); - menu->add( "Cut", findIcon( "cut" ), getKeybind( "cut" ) ); - menu->add( "Copy", findIcon( "copy" ), getKeybind( "copy" ) ); - menu->add( "Paste", findIcon( "paste" ), getKeybind( "paste" ) ); + menu->add( i18n( "cut", "Cut" ), findIcon( "cut" ), getKeybind( "cut" ) )->setId( "cut" ); + menu->add( i18n( "copy", "Copy" ), findIcon( "copy" ), getKeybind( "copy" ) )->setId( "copy" ); + menu->add( i18n( "paste", "Paste" ), findIcon( "paste" ), getKeybind( "paste" ) ) + ->setId( "paste" ); + menu->add( i18n( "delete", "Delete" ), findIcon( "delete-text" ), + getKeybind( "delete-to-next-char" ) ) + ->setId( "delete-to-next-char" ); menu->addSeparator(); - menu->add( "Select All", findIcon( "select-all" ), getKeybind( "select-all" ) ); + menu->add( i18n( "select_all", "Select All" ), findIcon( "select-all" ), + getKeybind( "select-all" ) ) + ->setId( "select-all" ); menu->addSeparator(); - menu->add( "Find/Replace", findIcon( "find-replace" ), getKeybind( "find-replace" ) ); + menu->add( i18n( "find_replace", "Find/Replace" ), findIcon( "find-replace" ), + getKeybind( "find-replace" ) ) + ->setId( "find-replace" ); menu->addSeparator(); - menu->add( "Key Bindings", findIcon( "keybindings" ), getKeybind( "keybindings" ) ); + menu->add( i18n( "key_bindings", "Key Bindings" ), findIcon( "keybindings" ), + getKeybind( "keybindings" ) ) + ->setId( "keybindings" ); + menu->add( i18n( "open_containing_folder", "Open Containing Folder..." ), + findIcon( "folder-open" ), getKeybind( "open-containing-folder" ) ) + ->setId( "open-containing-folder" ); + menu->add( i18n( "copy_file_path", "Copy File Path" ), findIcon( "copy" ), + getKeybind( "copy-file-path" ) ) + ->setId( "copy-file-path" ); menu->addEventListener( Event::OnItemClicked, [&]( const Event* event ) { if ( !event->getNode()->isType( UI_TYPE_MENUITEM ) ) return; - String text = String( event->getNode()->asType()->getText() ).toLower(); - if ( "key bindings" == text ) { - runCommand( "keybindings" ); - } else { - String::replaceAll( text, " ", "-" ); - String::replaceAll( text, "/", "-" ); - runCommand( text ); - } + runCommand( event->getNode()->getId() ); + } ); + menu->addEventListener( Event::OnMenuShow, [&, menu]( const Event* ) { + if ( nullptr == mEditorSplitter->getCurEditor() ) + return; + auto doc = mEditorSplitter->getCurEditor()->getDocumentRef(); + menu->getItemId( "undo" )->setEnabled( doc->hasUndo() ); + menu->getItemId( "redo" )->setEnabled( doc->hasRedo() ); + menu->getItemId( "copy" )->setEnabled( doc->hasSelection() ); + menu->getItemId( "cut" )->setEnabled( doc->hasSelection() ); + menu->getItemId( "open-containing-folder" )->setVisible( doc->hasFilepath() ); + menu->getItemId( "copy-file-path" )->setVisible( doc->hasFilepath() ); } ); return menu; } @@ -861,13 +884,16 @@ makeAutoClosePairs( const std::string& strPairs ) { UIMenu* App::createDocumentMenu() { mDocMenu = UIPopUpMenu::New(); - mDocMenu->addCheckBox( "Auto Detect Indent Type", mConfig.editor.autoDetectIndentType ) - ->setId( "auto_indent" ); + // **** CURRENT DOCUMENT **** + mDocMenu->add( "Current Document" )->setTextAlign( UI_HALIGN_CENTER ); + + mDocMenu->addCheckBox( "Auto Detect Indent Type & Width", mConfig.doc.autoDetectIndentType ) + ->setId( "auto_indent_cur" ); UIPopUpMenu* tabTypeMenu = UIPopUpMenu::New(); tabTypeMenu->addRadioButton( "Tabs" )->setId( "tabs" ); tabTypeMenu->addRadioButton( "Spaces" )->setId( "spaces" ); - mDocMenu->addSubMenu( "Indentation Type", nullptr, tabTypeMenu )->setId( "indent_type" ); + mDocMenu->addSubMenu( "Indentation Type", nullptr, tabTypeMenu )->setId( "indent_type_cur" ); tabTypeMenu->addEventListener( Event::OnItemClicked, [&]( const Event* event ) { const String& text = event->getNode()->asType()->getId(); if ( mEditorSplitter->getCurEditor() ) { @@ -875,7 +901,6 @@ UIMenu* App::createDocumentMenu() { ? TextDocument::IndentType::IndentTabs : TextDocument::IndentType::IndentSpaces; mEditorSplitter->getCurEditor()->getDocument().setIndentType( indentType ); - mConfig.editor.indentSpaces = indentType == TextDocument::IndentType::IndentSpaces; } } ); @@ -888,12 +913,11 @@ UIMenu* App::createDocumentMenu() { w ) ->setId( String::format( "indent_width_%zu", w ) ) ->setData( w ); - mDocMenu->addSubMenu( "Indent Width", nullptr, indentWidthMenu )->setId( "indent_width" ); + mDocMenu->addSubMenu( "Indent Width", nullptr, indentWidthMenu )->setId( "indent_width_cur" ); indentWidthMenu->addEventListener( Event::OnItemClicked, [&]( const Event* event ) { if ( mEditorSplitter->getCurEditor() ) { int width = event->getNode()->getData(); mEditorSplitter->getCurEditor()->getDocument().setIndentWidth( width ); - mConfig.editor.indentWidth = width; } } ); @@ -905,33 +929,124 @@ UIMenu* App::createDocumentMenu() { mEditorSplitter->getCurEditor()->getTabWidth() == w ) ->setId( String::format( "tab_width_%zu", w ) ) ->setData( w ); - mDocMenu->addSubMenu( "Tab Width", nullptr, tabWidthMenu )->setId( "tab_width" ); + mDocMenu->addSubMenu( "Tab Width", nullptr, tabWidthMenu )->setId( "tab_width_cur" ); tabWidthMenu->addEventListener( Event::OnItemClicked, [&]( const Event* event ) { if ( mEditorSplitter->getCurEditor() ) { int width = event->getNode()->getData(); mEditorSplitter->getCurEditor()->setTabWidth( width ); - mConfig.editor.tabWidth = width; } } ); UIPopUpMenu* lineEndingsMenu = UIPopUpMenu::New(); - lineEndingsMenu->addRadioButton( "Windows (CR/LF)", mConfig.editor.windowsLineEndings ) + lineEndingsMenu->addRadioButton( "Windows (CR/LF)", mConfig.doc.windowsLineEndings ) ->setId( "windows" ); - lineEndingsMenu->addRadioButton( "Unix (LF)", !mConfig.editor.windowsLineEndings ) + lineEndingsMenu->addRadioButton( "Unix (LF)", !mConfig.doc.windowsLineEndings ) ->setId( "unix" ); - mDocMenu->addSubMenu( "Line Endings", nullptr, lineEndingsMenu )->setId( "line_endings" ); + mDocMenu->addSubMenu( "Line Endings", nullptr, lineEndingsMenu )->setId( "line_endings_cur" ); lineEndingsMenu->addEventListener( Event::OnItemClicked, [&]( const Event* event ) { bool winLe = event->getNode()->asType()->getId() == "windows"; if ( mEditorSplitter->getCurEditor() ) { - mConfig.editor.windowsLineEndings = winLe; mEditorSplitter->getCurEditor()->getDocument().setLineEnding( winLe ? TextDocument::LineEnding::CRLF : TextDocument::LineEnding::LF ); updateDocInfo( mEditorSplitter->getCurEditor()->getDocument() ); } } ); + mDocMenu->addCheckBox( "Read Only" )->setId( "read_only" ); + + mDocMenu->addCheckBox( "Trim Trailing Whitespaces", mConfig.doc.trimTrailingWhitespaces ) + ->setId( "trim_whitespaces_cur" ); + + mDocMenu->addCheckBox( "Force New Line at End of File", mConfig.doc.forceNewLineAtEndOfFile ) + ->setId( "force_nl_cur" ); + + mDocMenu->addCheckBox( "Write Unicode BOM", mConfig.doc.writeUnicodeBOM ) + ->setId( "write_bom_cur" ); + + mDocMenu->addSeparator(); + + mDocMenu->addEventListener( Event::OnItemClicked, [&]( const Event* event ) { + if ( !mEditorSplitter->getCurEditor() || + event->getNode()->isType( UI_TYPE_MENU_SEPARATOR ) || + event->getNode()->isType( UI_TYPE_MENUSUBMENU ) ) + return; + const String& id = event->getNode()->getId(); + TextDocument& doc = mEditorSplitter->getCurEditor()->getDocument(); + + if ( event->getNode()->isType( UI_TYPE_MENUCHECKBOX ) ) { + UIMenuCheckBox* item = event->getNode()->asType(); + if ( "auto_indent_cur" == id ) { + doc.setAutoDetectIndentType( item->isActive() ); + } else if ( "trim_whitespaces_cur" == id ) { + doc.setTrimTrailingWhitespaces( item->isActive() ); + } else if ( "force_nl_cur" == id ) { + doc.setForceNewLineAtEndOfFile( item->isActive() ); + } else if ( "write_bom_cur" == id ) { + doc.setBOM( item->isActive() ); + } else if ( "read_only" == id ) { + mEditorSplitter->getCurEditor()->setLocked( item->isActive() ); + } + } + } ); + + // **** GLOBAL OPTIONS **** + UIPopUpMenu* globalMenu = UIPopUpMenu::New(); + mDocMenu->addSubMenu( "Global Settings", findIcon( "global_settings" ), globalMenu ); + + globalMenu->addCheckBox( "Auto Detect Indent Type & Width", mConfig.doc.autoDetectIndentType ) + ->setId( "auto_indent" ); + + UIPopUpMenu* tabTypeMenuGlobal = UIPopUpMenu::New(); + tabTypeMenuGlobal->addRadioButton( "Tabs" ) + ->setActive( !mConfig.doc.indentSpaces ) + ->setId( "tabs" ); + tabTypeMenuGlobal->addRadioButton( "Spaces" ) + ->setActive( mConfig.doc.indentSpaces ) + ->setId( "spaces" ); + globalMenu->addSubMenu( "Indentation Type", nullptr, tabTypeMenuGlobal ) + ->setId( "indent_type" ); + tabTypeMenuGlobal->addEventListener( Event::OnItemClicked, [&]( const Event* event ) { + const String& text = event->getNode()->asType()->getId(); + mConfig.doc.indentSpaces = text != "tabs"; + } ); + + UIPopUpMenu* indentWidthMenuGlobal = UIPopUpMenu::New(); + for ( int w = 2; w <= 12; w++ ) + indentWidthMenuGlobal->addRadioButton( String::toString( w ), mConfig.doc.indentWidth == w ) + ->setId( String::format( "indent_width_%d", w ) ) + ->setData( w ); + globalMenu->addSubMenu( "Indent Width", nullptr, indentWidthMenuGlobal ) + ->setId( "indent_width" ); + indentWidthMenuGlobal->addEventListener( Event::OnItemClicked, [&]( const Event* event ) { + int width = event->getNode()->getData(); + mConfig.doc.indentWidth = width; + } ); + + UIPopUpMenu* tabWidthMenuGlobal = UIPopUpMenu::New(); + for ( int w = 2; w <= 12; w++ ) + tabWidthMenuGlobal->addRadioButton( String::toString( w ), mConfig.doc.tabWidth == w ) + ->setId( String::format( "tab_width_%d", w ) ) + ->setData( w ); + globalMenu->addSubMenu( "Tab Width", nullptr, tabWidthMenuGlobal )->setId( "tab_width_cur" ); + tabWidthMenuGlobal->addEventListener( Event::OnItemClicked, [&]( const Event* event ) { + int width = event->getNode()->getData(); + mConfig.doc.tabWidth = width; + } ); + + UIPopUpMenu* lineEndingsGlobalMenu = UIPopUpMenu::New(); + lineEndingsGlobalMenu->addRadioButton( "Windows (CR/LF)", mConfig.doc.windowsLineEndings ) + ->setId( "windows" ); + lineEndingsGlobalMenu->addRadioButton( "Unix (LF)", !mConfig.doc.windowsLineEndings ) + ->setId( "unix" ); + globalMenu->addSubMenu( "Line Endings", nullptr, lineEndingsGlobalMenu ) + ->setId( "line_endings" ); + lineEndingsGlobalMenu->addEventListener( Event::OnItemClicked, [&]( const Event* event ) { + bool winLe = event->getNode()->asType()->getId() == "windows"; + mConfig.doc.windowsLineEndings = winLe; + } ); + UIPopUpMenu* bracketsMenu = UIPopUpMenu::New(); - mDocMenu->addSubMenu( "Auto-Close Brackets & Tags", nullptr, bracketsMenu ); + globalMenu->addSubMenu( "Auto-Close Brackets & Tags", nullptr, bracketsMenu ); auto& closeBrackets = mConfig.editor.autoCloseBrackets; auto shouldCloseCb = []( UIMenuItem* ) -> bool { return false; }; bracketsMenu->addCheckBox( "Brackets ()", closeBrackets.find( '(' ) != std::string::npos ) @@ -985,46 +1100,36 @@ UIMenu* App::createDocumentMenu() { } } ); - mDocMenu->addSeparator(); - - mDocMenu->addCheckBox( "Read Only" )->setId( "read_only" ); - - mDocMenu->addCheckBox( "Trim Trailing Whitespaces", mConfig.editor.trimTrailingWhitespaces ) + globalMenu->addCheckBox( "Trim Trailing Whitespaces", mConfig.doc.trimTrailingWhitespaces ) ->setId( "trim_whitespaces" ); - mDocMenu->addCheckBox( "Force New Line at End of File", mConfig.editor.forceNewLineAtEndOfFile ) + globalMenu->addCheckBox( "Force New Line at End of File", mConfig.doc.forceNewLineAtEndOfFile ) ->setId( "force_nl" ); - mDocMenu->addCheckBox( "Write Unicode BOM", mConfig.editor.writeUnicodeBOM ) + globalMenu->addCheckBox( "Write Unicode BOM", mConfig.doc.writeUnicodeBOM ) ->setId( "write_bom" ); - mDocMenu->addEventListener( Event::OnItemClicked, [&]( const Event* event ) { + globalMenu->addEventListener( Event::OnItemClicked, [&]( const Event* event ) { if ( !mEditorSplitter->getCurEditor() || event->getNode()->isType( UI_TYPE_MENU_SEPARATOR ) || event->getNode()->isType( UI_TYPE_MENUSUBMENU ) ) return; const String& id = event->getNode()->getId(); - TextDocument& doc = mEditorSplitter->getCurEditor()->getDocument(); if ( event->getNode()->isType( UI_TYPE_MENUCHECKBOX ) ) { UIMenuCheckBox* item = event->getNode()->asType(); - if ( "auto_indent" == id ) { - doc.setAutoDetectIndentType( item->isActive() ); - mConfig.editor.autoDetectIndentType = item->isActive(); - } else if ( "trim_whitespaces" == id ) { - doc.setTrimTrailingWhitespaces( item->isActive() ); - mConfig.editor.trimTrailingWhitespaces = item->isActive(); + if ( "trim_whitespaces" == id ) { + mConfig.doc.trimTrailingWhitespaces = item->isActive(); } else if ( "force_nl" == id ) { - doc.setForceNewLineAtEndOfFile( item->isActive() ); - mConfig.editor.forceNewLineAtEndOfFile = item->isActive(); + mConfig.doc.forceNewLineAtEndOfFile = item->isActive(); } else if ( "write_bom" == id ) { - doc.setBOM( item->isActive() ); - mConfig.editor.writeUnicodeBOM = item->isActive(); - } else if ( "read_only" == id ) { - mEditorSplitter->getCurEditor()->setLocked( item->isActive() ); + mConfig.doc.writeUnicodeBOM = item->isActive(); + } else if ( "auto_indent" == id ) { + mConfig.doc.autoDetectIndentType = item->isActive(); } } } ); + return mDocMenu; } @@ -1034,42 +1139,42 @@ void App::updateDocumentMenu() { const TextDocument& doc = mEditorSplitter->getCurEditor()->getDocument(); - mDocMenu->find( "auto_indent" ) + mDocMenu->find( "auto_indent_cur" ) ->asType() ->setActive( doc.getAutoDetectIndentType() ); - auto* curIndent = mDocMenu->find( "indent_width" ) + auto* curIndent = mDocMenu->find( "indent_width_cur" ) ->asType() ->getSubMenu() ->find( String::format( "indent_width_%d", doc.getIndentWidth() ) ); if ( curIndent ) curIndent->asType()->setActive( true ); - mDocMenu->find( "indent_type" ) + mDocMenu->find( "indent_type_cur" ) ->asType() ->getSubMenu() ->find( doc.getIndentType() == TextDocument::IndentType::IndentTabs ? "tabs" : "spaces" ) ->asType() ->setActive( true ); - mDocMenu->find( "tab_width" ) + mDocMenu->find( "tab_width_cur" ) ->asType() ->getSubMenu() ->find( String::format( "tab_width_%d", mEditorSplitter->getCurEditor()->getTabWidth() ) ) ->asType() ->setActive( true ); - mDocMenu->find( "trim_whitespaces" ) + mDocMenu->find( "trim_whitespaces_cur" ) ->asType() ->setActive( doc.getTrimTrailingWhitespaces() ); - mDocMenu->find( "force_nl" ) + mDocMenu->find( "force_nl_cur" ) ->asType() ->setActive( doc.getForceNewLineAtEndOfFile() ); - mDocMenu->find( "write_bom" )->asType()->setActive( doc.getBOM() ); + mDocMenu->find( "write_bom_cur" )->asType()->setActive( doc.getBOM() ); - mDocMenu->find( "line_endings" ) + mDocMenu->find( "line_endings_cur" ) ->asType() ->getSubMenu() ->find( doc.getLineEnding() == TextDocument::LineEnding::CRLF ? "windows" : "unix" ) @@ -1164,7 +1269,7 @@ void App::onColorSchemeChanged( const std::string& ) { void App::onDocumentLoaded( UICodeEditor* editor, const std::string& path ) { updateEditorTitle( editor ); if ( editor == mEditorSplitter->getCurEditor() ) - updateCurrentFiletype(); + updateCurrentFileType(); mEditorSplitter->removeUnusedTab( mEditorSplitter->tabWidgetFromEditor( editor ) ); auto found = std::find( mRecentFiles.begin(), mRecentFiles.end(), path ); if ( found != mRecentFiles.end() ) @@ -1383,6 +1488,7 @@ NotificationCenter* App::getNotificationCenter() const { void App::onCodeEditorCreated( UICodeEditor* editor, TextDocument& doc ) { const CodeEditorConfig& config = mConfig.editor; + const DocumentConfig& docc = mConfig.doc; editor->setFontSize( config.fontSize.asDp( 0, Sizef(), mUISceneNode->getDPI() ) ); editor->setEnableColorPickerOnSelection( true ); editor->setColorScheme( mEditorSplitter->getCurrentColorScheme() ); @@ -1392,8 +1498,8 @@ void App::onCodeEditorCreated( UICodeEditor* editor, TextDocument& doc ) { editor->setVerticalScrollBarEnabled( config.verticalScrollbar ); editor->setHorizontalScrollBarEnabled( config.horizontalScrollbar ); editor->setHighlightCurrentLine( config.highlightCurrentLine ); - editor->setTabWidth( config.tabWidth ); - editor->setLineBreakingColumn( config.lineBreakingColumn ); + editor->setTabWidth( docc.tabWidth ); + editor->setLineBreakingColumn( docc.lineBreakingColumn ); editor->setHighlightSelectionMatch( config.highlightSelectionMatch ); editor->setEnableColorPickerOnSelection( config.colorPickerSelection ); editor->setColorPreview( config.colorPreview ); @@ -1402,15 +1508,15 @@ void App::onCodeEditorCreated( UICodeEditor* editor, TextDocument& doc ) { editor->setAutoCloseXMLTags( config.autoCloseXMLTags ); doc.setAutoCloseBrackets( !mConfig.editor.autoCloseBrackets.empty() ); doc.setAutoCloseBracketsPairs( makeAutoClosePairs( mConfig.editor.autoCloseBrackets ) ); - doc.setAutoDetectIndentType( config.autoDetectIndentType ); - doc.setLineEnding( config.windowsLineEndings ? TextDocument::LineEnding::CRLF - : TextDocument::LineEnding::LF ); - doc.setTrimTrailingWhitespaces( config.trimTrailingWhitespaces ); - doc.setIndentType( config.indentSpaces ? TextDocument::IndentType::IndentSpaces - : TextDocument::IndentType::IndentTabs ); - doc.setForceNewLineAtEndOfFile( config.forceNewLineAtEndOfFile ); - doc.setIndentWidth( config.indentWidth ); - doc.setBOM( config.writeUnicodeBOM ); + doc.setLineEnding( docc.windowsLineEndings ? TextDocument::LineEnding::CRLF + : TextDocument::LineEnding::LF ); + doc.setTrimTrailingWhitespaces( docc.trimTrailingWhitespaces ); + doc.setForceNewLineAtEndOfFile( docc.forceNewLineAtEndOfFile ); + doc.setIndentType( docc.indentSpaces ? TextDocument::IndentType::IndentSpaces + : TextDocument::IndentType::IndentTabs ); + doc.setIndentWidth( docc.indentWidth ); + doc.setAutoDetectIndentType( docc.autoDetectIndentType ); + doc.setBOM( docc.writeUnicodeBOM ); editor->addKeyBinds( getLocalKeybindings() ); editor->addUnlockedCommands( getUnlockedCommands() ); @@ -1692,8 +1798,30 @@ void App::createSettingsMenu() { mSettingsMenu->add( "Save as...", findIcon( "document-save-as" ), getKeybind( "save-as-doc" ) ); mSettingsMenu->add( "Save All", findIcon( "document-save-as" ), getKeybind( "save-all" ) ); mSettingsMenu->addSeparator(); - mSettingsMenu->addSubMenu( "Filetype", nullptr, createFiletypeMenu() ); - mSettingsMenu->addSubMenu( "Color Scheme", nullptr, createColorSchemeMenu() ); + UIMenuSubMenu* fileTypeMenu = + mSettingsMenu->addSubMenu( "File Type", nullptr, createFileTypeMenu() ); + fileTypeMenu->addEventListener( Event::OnMenuShow, [&, fileTypeMenu]( const Event* ) { + if ( mFileTypeMenuesCreatedWithHeight != mUISceneNode->getPixelsSize().getHeight() ) { + for ( UIPopUpMenu* menu : mFileTypeMenues ) + menu->close(); + mFileTypeMenues.clear(); + auto* newMenu = createFileTypeMenu(); + newMenu->reloadStyle( true, true ); + fileTypeMenu->setSubMenu( newMenu ); + } + } ); + UIMenuSubMenu* colorSchemeMenu = + mSettingsMenu->addSubMenu( "Color Scheme", nullptr, createColorSchemeMenu() ); + colorSchemeMenu->addEventListener( Event::OnMenuShow, [&, fileTypeMenu]( const Event* ) { + if ( mFileTypeMenuesCreatedWithHeight != mUISceneNode->getPixelsSize().getHeight() ) { + for ( UIPopUpMenu* menu : mFileTypeMenues ) + menu->close(); + mFileTypeMenues.clear(); + auto* newMenu = createFileTypeMenu(); + newMenu->reloadStyle( true, true ); + fileTypeMenu->setSubMenu( newMenu ); + } + } ); mSettingsMenu->addSubMenu( "Document", nullptr, createDocumentMenu() ); mSettingsMenu->addSubMenu( "Edit", nullptr, createEditMenu() ); mSettingsMenu->addSubMenu( "View", nullptr, createViewMenu() ); @@ -1739,63 +1867,123 @@ void App::createSettingsMenu() { } void App::updateColorSchemeMenu() { - for ( size_t i = 0; i < mColorSchemeMenu->getCount(); i++ ) { - UIMenuRadioButton* menuItem = mColorSchemeMenu->getItem( i )->asType(); - menuItem->setActive( mEditorSplitter->getCurrentColorSchemeName() == menuItem->getText() ); + for ( UIPopUpMenu* menu : mFileTypeMenues ) { + for ( size_t i = 0; i < menu->getCount(); i++ ) { + UIWidget* widget = menu->getItem( i ); + if ( widget->isType( UI_TYPE_MENURADIOBUTTON ) ) { + auto* menuItem = widget->asType(); + menuItem->setActive( mEditorSplitter->getCurrentColorSchemeName() == + menuItem->getText() ); + } + } } } UIMenu* App::createColorSchemeMenu() { - mColorSchemeMenu = UIPopUpMenu::New(); - for ( auto& colorScheme : mEditorSplitter->getColorSchemes() ) { - mColorSchemeMenu->addRadioButton( - colorScheme.first, mEditorSplitter->getCurrentColorSchemeName() == colorScheme.first ); - } - mColorSchemeMenu->addEventListener( Event::OnItemClicked, [&]( const Event* event ) { + mColorSchemeMenuesCreatedWithHeight = mUISceneNode->getPixelsSize().getHeight(); + size_t maxItems = 19; + auto cb = [&]( const Event* event ) { UIMenuItem* item = event->getNode()->asType(); const String& name = item->getText(); mEditorSplitter->setColorScheme( name ); - } ); - return mColorSchemeMenu; + }; + + UIPopUpMenu* menu = UIPopUpMenu::New(); + menu->addEventListener( Event::OnItemClicked, cb ); + mColorSchemeMenues.push_back( menu ); + size_t total = 0; + const auto& colorSchemes = mEditorSplitter->getColorSchemes(); + + for ( auto& colorScheme : colorSchemes ) { + menu->addRadioButton( + colorScheme.first, mEditorSplitter->getCurrentColorSchemeName() == colorScheme.first ); + + if ( mColorSchemeMenues.size() == 1 && menu->getCount() == 1 ) { + menu->reloadStyle( true, true ); + Float height = menu->getPixelsSize().getHeight(); + Float tHeight = mUISceneNode->getPixelsSize().getHeight(); + maxItems = (int)eeceil( tHeight / height ) - 2; + } + + total++; + + if ( menu->getCount() == maxItems && colorSchemes.size() - total > 1 ) { + UIPopUpMenu* newMenu = UIPopUpMenu::New(); + menu->addSubMenu( i18n( "more...", "More..." ), nullptr, newMenu ); + newMenu->addEventListener( Event::OnItemClicked, cb ); + mColorSchemeMenues.push_back( newMenu ); + menu = newMenu; + } + } + + return mColorSchemeMenues[0]; } -UIMenu* App::createFiletypeMenu() { +UIMenu* App::createFileTypeMenu() { + mFileTypeMenuesCreatedWithHeight = mUISceneNode->getPixelsSize().getHeight(); + size_t maxItems = 19; auto* dM = SyntaxDefinitionManager::instance(); - mFiletypeMenu = UIPopUpMenu::New(); auto names = dM->getLanguageNames(); - for ( auto& name : names ) { - mFiletypeMenu->addRadioButton( - name, - mEditorSplitter->getCurEditor() && - mEditorSplitter->getCurEditor()->getSyntaxDefinition().getLanguageName() == name ); - } - mFiletypeMenu->addEventListener( Event::OnItemClicked, [&, dM]( const Event* event ) { + auto cb = [&, dM]( const Event* event ) { UIMenuItem* item = event->getNode()->asType(); const String& name = item->getText(); if ( mEditorSplitter->getCurEditor() ) { mEditorSplitter->getCurEditor()->setSyntaxDefinition( dM->getStyleByLanguageName( name ) ); - updateCurrentFiletype(); + updateCurrentFileType(); } - } ); - return mFiletypeMenu; + }; + + UIPopUpMenu* menu = UIPopUpMenu::New(); + menu->addEventListener( Event::OnItemClicked, cb ); + mFileTypeMenues.push_back( menu ); + size_t total = 0; + + for ( const auto& name : names ) { + menu->addRadioButton( + name, + mEditorSplitter->getCurEditor() && + mEditorSplitter->getCurEditor()->getSyntaxDefinition().getLanguageName() == name ); + + if ( mFileTypeMenues.size() == 1 && menu->getCount() == 1 ) { + menu->reloadStyle( true, true ); + Float height = menu->getPixelsSize().getHeight(); + Float tHeight = mUISceneNode->getPixelsSize().getHeight(); + maxItems = (int)eeceil( tHeight / height ) - 2; + } + + total++; + + if ( menu->getCount() == maxItems && names.size() - total > 1 ) { + UIPopUpMenu* newMenu = UIPopUpMenu::New(); + menu->addSubMenu( i18n( "more...", "More..." ), nullptr, newMenu ); + newMenu->addEventListener( Event::OnItemClicked, cb ); + mFileTypeMenues.push_back( newMenu ); + menu = newMenu; + } + } + + return mFileTypeMenues[0]; } -void App::updateCurrentFiletype() { +void App::updateCurrentFileType() { if ( !mEditorSplitter->getCurEditor() ) return; std::string curLang( mEditorSplitter->getCurEditor()->getSyntaxDefinition().getLanguageName() ); - for ( size_t i = 0; i < mFiletypeMenu->getCount(); i++ ) { - UIMenuRadioButton* menuItem = mFiletypeMenu->getItem( i )->asType(); - std::string itemLang( menuItem->getText() ); - menuItem->setActive( curLang == itemLang ); + for ( UIPopUpMenu* menu : mFileTypeMenues ) { + for ( size_t i = 0; i < menu->getCount(); i++ ) { + if ( menu->getItem( i )->isType( UI_TYPE_MENURADIOBUTTON ) ) { + UIMenuRadioButton* menuItem = menu->getItem( i )->asType(); + menuItem->setActive( curLang == menuItem->getText() ); + } + } } } void App::updateEditorState() { if ( mEditorSplitter->getCurEditor() ) { updateEditorTitle( mEditorSplitter->getCurEditor() ); - updateCurrentFiletype(); + updateCurrentFileType(); updateDocumentMenu(); } } @@ -2489,6 +2677,7 @@ void App::init( std::string file, const Float& pidelDensity, const std::string& { "layout-left", 0xee94 }, { "layout-right", 0xee9b }, { "color-scheme", 0xebd4 }, + { "global_settings", 0xedcf }, }; for ( const auto& icon : icons ) iconTheme->add( UIGlyphIcon::New( icon.first, iconFont, icon.second ) ); diff --git a/src/tools/ecode/ecode.hpp b/src/tools/ecode/ecode.hpp index 094cd2349..8300dc300 100644 --- a/src/tools/ecode/ecode.hpp +++ b/src/tools/ecode/ecode.hpp @@ -83,8 +83,10 @@ class App : public UICodeEditorSplitter::Client { UILayout* mImageLayout{ nullptr }; UIPopUpMenu* mSettingsMenu{ nullptr }; UITextView* mSettingsButton{ nullptr }; - UIPopUpMenu* mColorSchemeMenu{ nullptr }; - UIPopUpMenu* mFiletypeMenu{ nullptr }; + std::vector mColorSchemeMenues; + Float mColorSchemeMenuesCreatedWithHeight{ 0 }; + std::vector mFileTypeMenues; + Float mFileTypeMenuesCreatedWithHeight{ 0 }; UILinearLayout* mDocInfo{ nullptr }; UITextView* mDocInfoText{ nullptr }; std::vector mRecentFiles; @@ -164,9 +166,9 @@ class App : public UICodeEditorSplitter::Client { void updateColorSchemeMenu(); - UIMenu* createFiletypeMenu(); + UIMenu* createFileTypeMenu(); - void updateCurrentFiletype(); + void updateCurrentFileType(); void updateEditorState(); @@ -186,6 +188,8 @@ class App : public UICodeEditorSplitter::Client { Drawable* findIcon( const std::string& name ); + String i18n( const std::string& name, const String& def ); + UIMenu* createDocumentMenu(); void updateDocumentMenu();