diff --git a/.gitignore b/.gitignore index 436c671c6..c96ba8b72 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -fonts/ assets/temp/ obj/ libs/ diff --git a/bin/assets/fonts/remixicon.ttf b/bin/assets/fonts/remixicon.ttf new file mode 100644 index 000000000..c461f40e1 Binary files /dev/null and b/bin/assets/fonts/remixicon.ttf differ diff --git a/include/eepp/ui/uicodeeditor.hpp b/include/eepp/ui/uicodeeditor.hpp index db21791c8..7b48ad097 100644 --- a/include/eepp/ui/uicodeeditor.hpp +++ b/include/eepp/ui/uicodeeditor.hpp @@ -23,7 +23,11 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { public: static UICodeEditor* New(); - UICodeEditor(); + static UICodeEditor* NewOpt( const bool& autoRegisterBaseCommands, + const bool& autoRegisterBaseKeybindings ); + + UICodeEditor( const bool& autoRegisterBaseCommands = true, + const bool& autoRegisterBaseKeybindings = true ); virtual ~UICodeEditor(); @@ -211,6 +215,41 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { void setEnableColorPickerOnSelection( const bool& enableColorPickerOnSelection ); + /** Doc commands executed in this editor. */ + TextPosition moveToLineOffset( const TextPosition& position, int offset ); + + void moveToPreviousLine(); + + void moveToNextLine(); + + void selectToPreviousLine(); + + void selectToNextLine(); + + void registerKeybindings(); + + void registerCommands(); + + void moveScrollUp(); + + void moveScrollDown(); + + void indent(); + + void unindent(); + + void copy(); + + void cut(); + + void paste(); + + void fontSizeGrow(); + + void fontSizeShrink(); + + void fontSizeReset(); + /** Doc commands executed in this editor. */ protected: struct LastXOffset { TextPosition position; @@ -333,40 +372,6 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client { void updateScrollBar(); - TextPosition moveToLineOffset( const TextPosition& position, int offset ); - - void moveToPreviousLine(); - - void moveToNextLine(); - - void selectToPreviousLine(); - - void selectToNextLine(); - - void registerKeybindings(); - - void registerCommands(); - - void moveScrollUp(); - - void moveScrollDown(); - - void indent(); - - void unindent(); - - void copy(); - - void cut(); - - void paste(); - - void fontSizeGrow(); - - void fontSizeShrink(); - - void fontSizeReset(); - void checkColorPickerAction(); virtual void drawMatchingBrackets( const Vector2f& startScroll, const Float& lineHeight ); diff --git a/include/eepp/ui/uicommondialog.hpp b/include/eepp/ui/uicommondialog.hpp index 3a411d0f7..5ae1dd129 100644 --- a/include/eepp/ui/uicommondialog.hpp +++ b/include/eepp/ui/uicommondialog.hpp @@ -114,6 +114,8 @@ class EE_API UICommonDialog : public UIWindow { void openFileOrFolder(); void goFolderUp(); + + void updateClickStep(); }; }} // namespace EE::UI diff --git a/include/eepp/window/window.hpp b/include/eepp/window/window.hpp index 26c8c58ba..6ad087878 100644 --- a/include/eepp/window/window.hpp +++ b/include/eepp/window/window.hpp @@ -200,12 +200,22 @@ class EE_API Window { /** Set as current context the default context ( the context used for the window creation ) */ virtual void setDefaultContext(); - /** @return If the current window is active */ + /** @return If the current window is active. This means that the window hasInputFocus() and + * hasMouseFocus(). */ virtual bool isActive() = 0; /** @return If the current window is visible */ virtual bool isVisible() = 0; + /** @return If the current window has focus (same as hasInputFocus() or(||) hasMouseFocus()) */ + virtual bool hasFocus() = 0; + + /** @return If the current window has input focus */ + virtual bool hasInputFocus() = 0; + + /** @return If the current window has input focus */ + virtual bool hasMouseFocus() = 0; + /** Set the size of the window for a windowed window */ virtual void setSize( Uint32 Width, Uint32 Height ); diff --git a/src/eepp/ui/tools/uicolorpicker.cpp b/src/eepp/ui/tools/uicolorpicker.cpp index 86c826bce..27af64f38 100644 --- a/src/eepp/ui/tools/uicolorpicker.cpp +++ b/src/eepp/ui/tools/uicolorpicker.cpp @@ -252,17 +252,20 @@ UIColorPicker::UIColorPicker( UIWindow* attachTo, const UIColorPicker::ColorPick if ( NULL != mUIWindow && mUIWindow->isModal() ) { if ( mModalAlpha != 0.f ) { mUIWindow->getModalControl()->setBackgroundColor( Color( 0, 0, 0, mModalAlpha ) ); - mUIWindow->getModalControl()->runAction( Actions::Fade::New( - 0.f, mModalAlpha, - mRoot->getUISceneNode()->getUIThemeManager()->getControlsFadeOutTime() ) ); + + if ( mRoot->getUISceneNode()->getUIThemeManager()->getDefaultEffectsEnabled() ) { + mUIWindow->getModalControl()->runAction( Actions::Fade::New( + 0.f, mModalAlpha, + mRoot->getUISceneNode()->getUIThemeManager()->getControlsFadeOutTime() ) ); + } } - mUIWindow->getModalControl()->addEventListener( - Event::MouseClick, [&]( const Event* ) { - if ( mModalAlpha != 0.f ) - mUIWindow->getModalControl()->runAction( Actions::FadeOut::New( - mRoot->getUISceneNode()->getUIThemeManager()->getControlsFadeOutTime() ) ); - mUIWindow->closeWindow(); - } ); + mUIWindow->getModalControl()->addEventListener( Event::MouseClick, [&]( const Event* ) { + if ( mModalAlpha != 0.f && + mRoot->getUISceneNode()->getUIThemeManager()->getDefaultEffectsEnabled() ) + mUIWindow->getModalControl()->runAction( Actions::FadeOut::New( + mRoot->getUISceneNode()->getUIThemeManager()->getControlsFadeOutTime() ) ); + mUIWindow->closeWindow(); + } ); } mRoot->bind( "color_picker_rect", mColorPicker ); diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp index 91a2598bc..91ca734ee 100644 --- a/src/eepp/ui/uicodeeditor.cpp +++ b/src/eepp/ui/uicodeeditor.cpp @@ -19,10 +19,16 @@ using namespace EE::UI::Tools; namespace EE { namespace UI { UICodeEditor* UICodeEditor::New() { - return eeNew( UICodeEditor, () ); + return eeNew( UICodeEditor, ( true, true ) ); } -UICodeEditor::UICodeEditor() : +UICodeEditor* UICodeEditor::NewOpt( const bool& autoRegisterBaseCommands, + const bool& autoRegisterBaseKeybindings ) { + return eeNew( UICodeEditor, ( autoRegisterBaseCommands, autoRegisterBaseKeybindings ) ); +} + +UICodeEditor::UICodeEditor( const bool& autoRegisterBaseCommands, + const bool& autoRegisterBaseKeybindings ) : UIWidget( "codeeditor" ), mFont( FontManager::instance()->getByName( "monospace" ) ), mDirtyEditor( false ), @@ -64,8 +70,10 @@ UICodeEditor::UICodeEditor() : mDoc.registerClient( this ); subscribeScheduledUpdate(); - registerCommands(); - registerKeybindings(); + if ( autoRegisterBaseCommands ) + registerCommands(); + if ( autoRegisterBaseKeybindings ) + registerKeybindings(); } UICodeEditor::~UICodeEditor() { @@ -160,7 +168,7 @@ void UICodeEditor::draw() { } void UICodeEditor::scheduledUpdate( const Time& ) { - if ( hasFocus() && getUISceneNode()->getWindow()->isActive() ) { + if ( hasFocus() && getUISceneNode()->getWindow()->hasFocus() ) { if ( mBlinkTimer.getElapsedTime().asSeconds() > 0.5f ) { mCursorVisible = !mCursorVisible; mBlinkTimer.restart(); diff --git a/src/eepp/ui/uicommondialog.cpp b/src/eepp/ui/uicommondialog.cpp index c29446bea..fce07e4fd 100644 --- a/src/eepp/ui/uicommondialog.cpp +++ b/src/eepp/ui/uicommondialog.cpp @@ -158,7 +158,7 @@ UICommonDialog::UICommonDialog( Uint32 CDLFlags, std::string DefaultFilePattern, UICommonDialog::~UICommonDialog() {} void UICommonDialog::onWindowReady() { - refreshFolder(); + updateClickStep(); } Uint32 UICommonDialog::getType() const { @@ -240,13 +240,17 @@ void UICommonDialog::refreshFolder() { mList->addListBoxItems( files ); + updateClickStep(); + + mList->setFocus(); +} + +void UICommonDialog::updateClickStep() { if ( NULL != mList->getVerticalScrollBar() ) { mList->getVerticalScrollBar()->setClickStep( 1.f / ( ( mList->getCount() * mList->getRowHeight() ) / (Float)mList->getSize().getHeight() ) ); } - - mList->setFocus(); } void UICommonDialog::openSaveClick() { diff --git a/src/eepp/ui/uiscenenode.cpp b/src/eepp/ui/uiscenenode.cpp index ada68cdb0..fe272d86f 100644 --- a/src/eepp/ui/uiscenenode.cpp +++ b/src/eepp/ui/uiscenenode.cpp @@ -457,9 +457,19 @@ void UISceneNode::update( const Time& elapsed ) { // ready before being drawn. Also the reverse case could happen, we need to have the styles and // layouts updated before and after the update to avoid weird issues. The cost of doing this is // minimal and the benefit is huge and simplifies implementation. - updateDirtyStyles(); - updateDirtyStyleStates(); - updateDirtyLayouts(); + // invalidationDepth allows to retry to apply any pending state as many times as set. + // This is required in some very edge cases where widgets are being created during the update + // of any of these 3 steps. Usually during the layout update, this could trigger resizes that + // provokes the creation of dynamic elements. This is the case of the UIListBox for example + // that creates childs dynamically only when they are visible. + int invalidationDepth = 2; + while ( ( !mDirtyStyle.empty() || !mDirtyStyleState.empty() || !mDirtyLayouts.empty() ) && + invalidationDepth > 0 ) { + updateDirtyStyles(); + updateDirtyStyleStates(); + updateDirtyLayouts(); + invalidationDepth--; + } SceneManager::instance()->setCurrentUISceneNode( uiSceneNode ); } diff --git a/src/eepp/ui/uiwindow.cpp b/src/eepp/ui/uiwindow.cpp index c1610b93d..15f4e339b 100644 --- a/src/eepp/ui/uiwindow.cpp +++ b/src/eepp/ui/uiwindow.cpp @@ -474,11 +474,11 @@ void UIWindow::closeWindow() { if ( NULL != mButtonMinimize ) mButtonMinimize->setEnabled( false ); - if ( Time::Zero != getUISceneNode()->getUIThemeManager()->getControlsFadeOutTime() ) { - runAction( Actions::Sequence::New( - Actions::FadeOut::New( - getUISceneNode()->getUIThemeManager()->getControlsFadeOutTime() ), - Actions::Close::New() ) ); + UIThemeManager* themeManager = getUISceneNode()->getUIThemeManager(); + if ( themeManager->getDefaultEffectsEnabled() ) { + runAction( + Actions::Sequence::New( Actions::FadeOut::New( themeManager->getControlsFadeOutTime() ), + Actions::Close::New() ) ); } else { close(); } @@ -1060,10 +1060,12 @@ bool UIWindow::show() { setFocus(); - runAction( Actions::Fade::New( - mStyleConfig.BaseAlpha == getAlpha() ? 0.f : mAlpha, mStyleConfig.BaseAlpha, - getUISceneNode()->getUIThemeManager()->getControlsFadeOutTime() ) ); - + UIThemeManager* themeManager = getUISceneNode()->getUIThemeManager(); + if ( themeManager->getDefaultEffectsEnabled() ) { + runAction( Actions::Fade::New( mStyleConfig.BaseAlpha == getAlpha() ? 0.f : mAlpha, + mStyleConfig.BaseAlpha, + themeManager->getControlsFadeOutTime() ) ); + } setupModal(); return true; @@ -1076,10 +1078,10 @@ bool UIWindow::show() { bool UIWindow::hide() { if ( isVisible() ) { - if ( getUISceneNode()->getUIThemeManager()->getDefaultEffectsEnabled() ) { + UIThemeManager* themeManager = getUISceneNode()->getUIThemeManager(); + if ( themeManager->getDefaultEffectsEnabled() ) { runAction( Actions::Sequence::New( - Actions::FadeOut::New( - getUISceneNode()->getUIThemeManager()->getControlsFadeOutTime() ), + Actions::FadeOut::New( themeManager->getControlsFadeOutTime() ), Actions::Spawn::New( Actions::Disable::New(), Actions::Visible::New( false ) ) ) ); } else { setEnabled( false ); diff --git a/src/eepp/window/backend/SDL2/windowsdl2.cpp b/src/eepp/window/backend/SDL2/windowsdl2.cpp index 69dc880c9..7af9e0d76 100644 --- a/src/eepp/window/backend/SDL2/windowsdl2.cpp +++ b/src/eepp/window/backend/SDL2/windowsdl2.cpp @@ -498,21 +498,28 @@ void WindowSDL::setTitle( const std::string& title ) { } bool WindowSDL::isActive() { - Uint32 flags = 0; - - flags = SDL_GetWindowFlags( mSDLWindow ); - + Uint32 flags = SDL_GetWindowFlags( mSDLWindow ); return 0 != ( ( flags & SDL_WINDOW_INPUT_FOCUS ) && ( flags & SDL_WINDOW_MOUSE_FOCUS ) ); } bool WindowSDL::isVisible() { - Uint32 flags = 0; - - flags = SDL_GetWindowFlags( mSDLWindow ); - + Uint32 flags = SDL_GetWindowFlags( mSDLWindow ); return 0 != ( ( flags & SDL_WINDOW_SHOWN ) && !( flags & SDL_WINDOW_MINIMIZED ) ); } +bool WindowSDL::hasFocus() { + return 0 != ( SDL_GetWindowFlags( mSDLWindow ) & + ( SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_MOUSE_FOCUS ) ); +} + +bool WindowSDL::hasInputFocus() { + return 0 != ( SDL_GetWindowFlags( mSDLWindow ) & ( SDL_WINDOW_INPUT_FOCUS ) ); +} + +bool WindowSDL::hasMouseFocus() { + return 0 != ( SDL_GetWindowFlags( mSDLWindow ) & ( SDL_WINDOW_MOUSE_FOCUS ) ); +} + void WindowSDL::onWindowResize( Uint32 Width, Uint32 Height ) { if ( Width == mWindow.WindowConfig.Width && Height == mWindow.WindowConfig.Height ) return; diff --git a/src/eepp/window/backend/SDL2/windowsdl2.hpp b/src/eepp/window/backend/SDL2/windowsdl2.hpp index 80844df03..b7025cb07 100644 --- a/src/eepp/window/backend/SDL2/windowsdl2.hpp +++ b/src/eepp/window/backend/SDL2/windowsdl2.hpp @@ -35,6 +35,12 @@ class EE_API WindowSDL : public Window { bool isVisible(); + bool hasFocus(); + + bool hasInputFocus(); + + bool hasMouseFocus(); + void setSize( Uint32 Width, Uint32 Height, bool isWindowed ); std::vector getDisplayModes() const; diff --git a/src/tools/codeeditor/codeeditor.cpp b/src/tools/codeeditor/codeeditor.cpp index 864d67cf4..a1ea332ed 100644 --- a/src/tools/codeeditor/codeeditor.cpp +++ b/src/tools/codeeditor/codeeditor.cpp @@ -178,6 +178,7 @@ void App::applyColorScheme( const SyntaxColorScheme& colorScheme ) { colorScheme ); } } + updateColorSchemeMenu(); } UICodeEditor* App::createCodeEditor() { @@ -188,11 +189,11 @@ UICodeEditor* App::createCodeEditor() { codeEditor->getDocument().setCommand( "switch-to-previous-colorscheme", [&] { auto it = mColorSchemes.find( mCurrentColorScheme ); auto prev = std::prev( it, 1 ); - if ( prev != mColorSchemes.end() ) - mCurrentColorScheme = prev->first; - else - mCurrentColorScheme = mColorSchemes.rbegin()->first; - applyColorScheme( mColorSchemes[mCurrentColorScheme] ); + if ( prev != mColorSchemes.end() ) { + setColorScheme( prev->first ); + } else { + setColorScheme( mColorSchemes.rbegin()->first ); + } } ); codeEditor->getDocument().setCommand( "switch-to-next-colorscheme", [&] { auto it = mColorSchemes.find( mCurrentColorScheme ); @@ -272,6 +273,7 @@ UICodeEditor* App::createCodeEditor() { codeEditor->addKeyBindingString( "f3", "repeat-find", false ); codeEditor->addKeyBindingString( "f12", "console-toggle", true ); codeEditor->addKeyBindingString( "alt+return", "fullscreen-toggle", true ); + codeEditor->addKeyBindingString( "alt+keypad enter", "fullscreen-toggle", true ); codeEditor->addKeyBindingString( "ctrl+s", "save-doc", false ); codeEditor->addKeyBindingString( "ctrl+f", "find", false ); codeEditor->addKeyBindingString( "ctrl+q", "close-app", true ); @@ -703,7 +705,7 @@ void App::mainLoop() { mConsole->draw(); mWindow->display(); } else { - Sys::sleep( Milliseconds( mWindow->isVisible() ? 1 : 16 ) ); + Sys::sleep( Milliseconds( mWindow->hasFocus() ? 1 : 16 ) ); } } @@ -778,23 +780,32 @@ void App::createSettingsMenu() { } ); } -UIMenu* App::createColorSchemeMenu() { - UIPopUpMenu* colorSchemeMenu = UIPopUpMenu::New(); - for ( auto& colorScheme : mColorSchemes ) { - colorSchemeMenu->addCheckBox( colorScheme.first, mCurrentColorScheme == colorScheme.first ); +void App::setColorScheme( const std::string& name ) { + if ( name != mCurrentColorScheme ) { + mCurrentColorScheme = name; + applyColorScheme( mColorSchemes[mCurrentColorScheme] ); } - colorSchemeMenu->addEventListener( - Event::OnItemClicked, [&, colorSchemeMenu]( const Event* event ) { - UIMenuItem* item = event->getNode()->asType(); - const String& name = item->getText(); - mCurrentColorScheme = name; - applyColorScheme( mColorSchemes[mCurrentColorScheme] ); - for ( size_t i = 0; i < colorSchemeMenu->getCount(); i++ ) { - UIMenuCheckBox* menuItem = colorSchemeMenu->getItem( i )->asType(); - menuItem->setActive( mCurrentColorScheme == menuItem->getText() ); - } - } ); - return colorSchemeMenu; +} + +void App::updateColorSchemeMenu() { + for ( size_t i = 0; i < mColorSchemeMenu->getCount(); i++ ) { + UIMenuCheckBox* menuItem = mColorSchemeMenu->getItem( i )->asType(); + menuItem->setActive( mCurrentColorScheme == menuItem->getText() ); + } +} + +UIMenu* App::createColorSchemeMenu() { + mColorSchemeMenu = UIPopUpMenu::New(); + for ( auto& colorScheme : mColorSchemes ) { + mColorSchemeMenu->addCheckBox( colorScheme.first, + mCurrentColorScheme == colorScheme.first ); + } + mColorSchemeMenu->addEventListener( Event::OnItemClicked, [&]( const Event* event ) { + UIMenuItem* item = event->getNode()->asType(); + const String& name = item->getText(); + setColorScheme( name ); + } ); + return mColorSchemeMenu; } void App::init( const std::string& file ) { @@ -839,14 +850,13 @@ void App::init( const std::string& file ) { SceneManager::instance()->add( mUISceneNode ); - UITheme* theme = - UITheme::load( "uitheme", "uitheme", "", font, resPath + "assets/ui/breeze.css" ); - mUISceneNode->setStyleSheet( theme->getStyleSheet() ); + mTheme = UITheme::load( "uitheme", "uitheme", "", font, resPath + "assets/ui/breeze.css" ); + mUISceneNode->setStyleSheet( mTheme->getStyleSheet() ); mUISceneNode->getUIThemeManager() ->setDefaultEffectsEnabled( true ) - ->setDefaultTheme( theme ) + ->setDefaultTheme( mTheme ) ->setDefaultFont( font ) - ->add( theme ); + ->add( mTheme ); auto colorSchemes = SyntaxColorScheme::loadFromFile( resPath + "assets/colorschemes/colorschemes.conf" ); @@ -889,7 +899,7 @@ void App::init( const std::string& file ) { color: #eff0f188; font-family: icon; font-size: 16dp; - margin-top: 2dp; + margin-top: 6dp; margin-right: 22dp; transition: all 0.15s; } diff --git a/src/tools/codeeditor/codeeditor.hpp b/src/tools/codeeditor/codeeditor.hpp index 9b075d610..3e9c14f3b 100644 --- a/src/tools/codeeditor/codeeditor.hpp +++ b/src/tools/codeeditor/codeeditor.hpp @@ -92,6 +92,7 @@ class App { void findAndReplace( String find, String replace, const bool& caseSensitive ); void runCommand( const std::string& command ); + protected: EE::Window::Window* mWindow{NULL}; UISceneNode* mUISceneNode{NULL}; @@ -107,6 +108,8 @@ class App { std::string mCurrentColorScheme; UIPopUpMenu* mSettingsMenu; UITextView* mSettingsButton; + UIPopUpMenu* mColorSchemeMenu; + UITheme* mTheme; void onFileDropped( String file ); @@ -135,6 +138,10 @@ class App { void createSettingsMenu(); UIMenu* createColorSchemeMenu(); + + void updateColorSchemeMenu(); + + void setColorScheme( const std::string& name ); }; #endif // EE_TOOLS_CODEEDITOR_HPP