From 14207f228bcca42bb642c92e91bda509025fa804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Sat, 1 Aug 2026 00:31:55 -0300 Subject: [PATCH] eepp: Fixed a crash on single click navigation when selecting folder or file in UIFileDialog. eeiv: Add drag & drop of images and folders. Added small welcome screen. eterm: Detect windows below the default width and height and resize the window to fix the screen. --- src/eepp/ui/abstract/uiabstracttableview.cpp | 3 +- src/tools/eeiv/eeiv.cpp | 114 ++++++++++++++++++- src/tools/eeiv/eeiv.hpp | 9 ++ src/tools/eeiv/uiwelcomescreen.cpp | 68 +++++++++++ src/tools/eeiv/uiwelcomescreen.hpp | 18 +++ src/tools/eterm/eterm.cpp | 7 ++ 6 files changed, 217 insertions(+), 2 deletions(-) create mode 100644 src/tools/eeiv/uiwelcomescreen.cpp create mode 100644 src/tools/eeiv/uiwelcomescreen.hpp diff --git a/src/eepp/ui/abstract/uiabstracttableview.cpp b/src/eepp/ui/abstract/uiabstracttableview.cpp index 28ad64f64..2679266c4 100644 --- a/src/eepp/ui/abstract/uiabstracttableview.cpp +++ b/src/eepp/ui/abstract/uiabstracttableview.cpp @@ -540,7 +540,8 @@ UITableRow* UIAbstractTableView::createRow() { } } ); rowWidget->on( Event::MouseClick, [this]( const Event* event ) { - if ( !( event->asMouseEvent()->getFlags() & ( EE_BUTTON_LMASK ) ) || !isRowSelection() ) + if ( !( event->asMouseEvent()->getFlags() & EE_BUTTON_LMASK ) || !isRowSelection() || + mSingleClickNavigation ) return; auto index = event->getNode()->asType()->getCurIndex(); diff --git a/src/tools/eeiv/eeiv.cpp b/src/tools/eeiv/eeiv.cpp index 191af69bb..ddf1ec0bc 100644 --- a/src/tools/eeiv/eeiv.cpp +++ b/src/tools/eeiv/eeiv.cpp @@ -1,6 +1,8 @@ #include "eeiv.hpp" #include +#include +#include using namespace EE::Network; using namespace EE::Window; @@ -20,6 +22,7 @@ bool App::isHttpUrl( const std::string& path ) { App::App( int argc, char* argv[] ) : mStorePath( Sys::getConfigPath( "eeiv" ) + FileSystem::getOSSlash() ), mTmpPath( mStorePath + "tmp" + FileSystem::getOSSlash() ) { + Log::instance()->setKeepLog( true ); if ( argc > 1 ) { mInitialPath = argv[1]; if ( FileSystem::isRelativePath( mInitialPath ) && !isHttpUrl( mInitialPath ) ) { @@ -42,6 +45,78 @@ EE::Window::Window* App::getWindow() const { return mUIApplication ? mUIApplication->getWindow() : nullptr; } +void App::showWelcomeScreen() { + if ( !mWelcomeScreen ) + return; + mWelcomeScreen->setVisible( true ); + mWelcomeScreen->toFront(); + mWelcomeScreen->setFocus(); +} + +void App::hideWelcomeScreen() { + if ( mWelcomeScreen ) + mWelcomeScreen->setVisible( false ); +} + +void App::openFileDialog() { + const auto& extensions = Image::getImageExtensionsSupported(); + std::string fileTypes; + fileTypes.reserve( extensions.size() * 6 ); + for ( const auto& ext : extensions ) { + if ( !fileTypes.empty() ) + fileTypes += ";"; + fileTypes += "*." + ext; + } + + UIFileDialog* dialog = UIFileDialog::New( + UIFileDialog::DefaultFlags, fileTypes, + mFilePath.empty() ? FileSystem::getCurrentWorkingDirectory() : mFilePath ); + dialog->setWindowFlags( UI_WIN_DEFAULT_FLAGS | UI_WIN_MAXIMIZE_BUTTON | UI_WIN_MODAL ); + dialog->setTitle( "Open Image" ); + dialog->setCloseShortcut( KEY_ESCAPE ); + dialog->on( Event::OpenFile, [this]( const Event* event ) { + const std::string path( event->getNode()->asType()->getFullPath() ); + if ( isImage( path ) || isHttpUrl( path ) || FileSystem::isDirectory( path ) ) + loadDir( path ); + } ); + dialog->on( Event::OnWindowClose, [this]( const Event* ) { + if ( mWelcomeScreen && mWelcomeScreen->isVisible() ) + mWelcomeScreen->setFocus(); + } ); + dialog->center(); + dialog->show(); +} + +void App::openFolderDialog() { + UIFileDialog* dialog = UIFileDialog::New( + UIFileDialog::DefaultFlags | UIFileDialog::AllowFolderSelect | + UIFileDialog::ShowOnlyFolders, + "*", mFilePath.empty() ? FileSystem::getCurrentWorkingDirectory() : mFilePath ); + dialog->setWindowFlags( UI_WIN_DEFAULT_FLAGS | UI_WIN_MAXIMIZE_BUTTON | UI_WIN_MODAL ); + dialog->setTitle( "Open Folder" ); + dialog->setCloseShortcut( KEY_ESCAPE ); + dialog->on( Event::OpenFile, [this]( const Event* event ) { + const std::string path( event->getNode()->asType()->getFullPath() ); + if ( FileSystem::isDirectory( path ) ) + loadDir( path ); + } ); + dialog->on( Event::OnWindowClose, [this]( const Event* ) { + if ( mWelcomeScreen && mWelcomeScreen->isVisible() ) + mWelcomeScreen->setFocus(); + } ); + dialog->center(); + dialog->show(); +} + +void App::processDroppedFiles() { + if ( mPathsToLoad.empty() ) + return; + std::string path( std::move( mPathsToLoad.back() ) ); + mPathsToLoad.clear(); + if ( isImage( path ) || isHttpUrl( path ) || FileSystem::isDirectory( path ) ) + loadDir( path ); +} + void App::setBackgroundColor( const Color& color ) { if ( getWindow() ) getWindow()->setClearColor( color.toRGB() ); @@ -120,6 +195,16 @@ bool App::init() { return false; setBackgroundColor( Color::Black ); + ResourceScope& resourceScope = *mUIApplication->getUI()->getResourceScope(); + FontTrueTypePtr remixIconFont = + FontTrueType::New( "icon", "assets/fonts/remixicon.ttf", resourceScope ); + FontTrueTypePtr noniconsFont = + FontTrueType::New( "nonicons", "assets/fonts/nonicons.ttf", resourceScope ); + FontTrueTypePtr codIconFont = + FontTrueType::New( "codicon", "assets/fonts/codicon.ttf", resourceScope ); + mUIApplication->getUI()->getUIIconThemeManager()->setCurrentTheme( + IconManager::init( "icons", remixIconFont.get(), noniconsFont.get(), codIconFont.get() ) ); + mThreadPool = ThreadPool::createShared( 2 ); mUIApplication->getUI()->setThreadPool( mThreadPool ); Http::setThreadPool( mThreadPool ); @@ -195,14 +280,40 @@ bool App::init() { mConsole->setVisible( false ); mConsole->setMaxLogLines( 1024000 ); mConsole->setFontSize( mConfig.ConsoleFontSize ); + mConsole->on( Event::KeyDown, [this]( const Event* event ) { + if ( event->asKeyEvent()->getKeyCode() == KEY_ESCAPE ) + mUIApplication->getWindow()->close(); + } ); mConsoleCommands = std::make_unique( this, mConsole ); registerConsoleCommands(); registerKeyBindings(); + mWelcomeScreen = UIWelcomeScreen::New( this ); + mWelcomeScreen->setParent( mMainLayout ); + mWelcomeScreen->setVisible( false ); + + mUIApplication->getWindow()->getInput()->pushCallback( [this]( InputEvent* event ) { + switch ( event->Type ) { + case InputEvent::FileDropped: { + mPathsToLoad.emplace_back( event->file.file ); + break; + } + case InputEvent::EventsSent: { + processDroppedFiles(); + break; + } + default: + break; + } + } ); + if ( !mInitialPath.empty() ) loadDir( mInitialPath, true ); + if ( mFiles.empty() ) - mConsole->toggle(); + showWelcomeScreen(); + + Log::instance()->setKeepLog( false ); return true; } @@ -448,6 +559,7 @@ void App::syncLoadedImage() { const std::string path( mImageViewer->getImagePath() ); if ( path.empty() ) return; + hideWelcomeScreen(); mFilePath = FileSystem::fileRemoveFileName( path ); FileSystem::dirAddSlashAtEnd( mFilePath ); mFile = FileSystem::fileNameFromPath( path ); diff --git a/src/tools/eeiv/eeiv.hpp b/src/tools/eeiv/eeiv.hpp index 47ddaf1c1..f3b0abab5 100644 --- a/src/tools/eeiv/eeiv.hpp +++ b/src/tools/eeiv/eeiv.hpp @@ -3,6 +3,7 @@ #include #include "consolecommands.hpp" +#include "uiwelcomescreen.hpp" using namespace EE; using namespace EE::Graphics; @@ -49,6 +50,11 @@ class App { EE::Window::Window* getWindow() const; Config& getConfig() { return mConfig; } + void showWelcomeScreen(); + void hideWelcomeScreen(); + void openFileDialog(); + void openFolderDialog(); + private: bool init(); void loadConfig(); @@ -64,6 +70,7 @@ class App { void toggleHelp(); void fitImage(); Sprite* getImageSprite() const; + void processDroppedFiles(); std::string mInitialPath; Config mConfig; @@ -73,6 +80,7 @@ class App { std::string mFilePath; std::string mFile; std::vector mFiles; + std::vector mPathsToLoad; Int32 mCurImg{ 0 }; bool mSlideShow{ false }; Uint32 mSlideTime{ 4000 }; @@ -83,6 +91,7 @@ class App { UIImageViewer* mImageViewer{ nullptr }; UITextView* mHelp{ nullptr }; UIConsole* mConsole{ nullptr }; + UIWelcomeScreen* mWelcomeScreen{ nullptr }; bool mCursorVisible{ true }; Texture::Filter mTextureFilter{ Texture::Filter::Linear }; std::unique_ptr mConsoleCommands; diff --git a/src/tools/eeiv/uiwelcomescreen.cpp b/src/tools/eeiv/uiwelcomescreen.cpp new file mode 100644 index 000000000..1606230a3 --- /dev/null +++ b/src/tools/eeiv/uiwelcomescreen.cpp @@ -0,0 +1,68 @@ +#include "uiwelcomescreen.hpp" +#include "eeiv.hpp" + +#include + +static const auto LAYOUT = R"xml( + + + + + + + + +)xml"; + +UIWelcomeScreen* UIWelcomeScreen::New( App* app ) { + return eeNew( UIWelcomeScreen, ( app ) ); +} + +UIWelcomeScreen::UIWelcomeScreen( App* app ) : UIRelativeLayout(), mApp( app ) { + setId( "welcome_screen" ); + setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent ); + getUISceneNode()->loadLayoutFromString( LAYOUT, this, String::hash( "UIWelcomeScreen" ) ); + + find( "open_image" )->onClick( [this]( auto ) { mApp->openFileDialog(); } ); + find( "open_folder" )->onClick( [this]( auto ) { mApp->openFolderDialog(); } ); +} diff --git a/src/tools/eeiv/uiwelcomescreen.hpp b/src/tools/eeiv/uiwelcomescreen.hpp new file mode 100644 index 000000000..46be8ebc2 --- /dev/null +++ b/src/tools/eeiv/uiwelcomescreen.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include + +using namespace EE; +using namespace EE::UI; + +class App; + +class UIWelcomeScreen : public UIRelativeLayout { + public: + static UIWelcomeScreen* New( App* app ); + + explicit UIWelcomeScreen( App* app ); + + protected: + App* mApp{ nullptr }; +}; diff --git a/src/tools/eterm/eterm.cpp b/src/tools/eterm/eterm.cpp index e1450be0a..9cd45f67d 100644 --- a/src/tools/eterm/eterm.cpp +++ b/src/tools/eterm/eterm.cpp @@ -280,6 +280,13 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) { defaultResourceScope().getFontService().setAntialiasing( fontAntialiasing.Get() ); Sizei winSize( width.Get(), height.Get() ); + + if ( winSize.getWidth() >= currentDisplay->getBounds().getWidth() ) + winSize.setWidth( static_cast( currentDisplay->getBounds().getWidth() * 0.8 ) ); + + if ( winSize.getHeight() >= currentDisplay->getBounds().getHeight() ) + winSize.setHeight( static_cast( currentDisplay->getBounds().getHeight() * 0.75 ) ); + win = Engine::instance()->createWindow( WindowSettings( winSize.getWidth(), winSize.getHeight(), "eterm", WindowStyle::Default, WindowBackend::Default, 32, resPath + "icon/eterm.png",