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.
This commit is contained in:
Martín Lucas Golini
2026-08-01 00:31:55 -03:00
parent 13508c20d1
commit 14207f228b
6 changed files with 217 additions and 2 deletions
+2 -1
View File
@@ -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<UITableRow>()->getCurIndex();
+113 -1
View File
@@ -1,6 +1,8 @@
#include "eeiv.hpp"
#include <eepp/network/http.hpp>
#include <eepp/ui/uifiledialog.hpp>
#include <eepp/ui/uiwindow.hpp>
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<UIFileDialog>()->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<UIFileDialog>()->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<ConsoleCommands>( 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 );
+9
View File
@@ -3,6 +3,7 @@
#include <eepp/ee.hpp>
#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<std::string> mFiles;
std::vector<std::string> 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<ConsoleCommands> mConsoleCommands;
+68
View File
@@ -0,0 +1,68 @@
#include "uiwelcomescreen.hpp"
#include "eeiv.hpp"
#include <eepp/ui/uiscenenode.hpp>
static const auto LAYOUT = R"xml(
<style>
<![CDATA[
#welcome_screen {
background-color: var(--back);
}
#welcome_screen TextView {
focusable: false;
color: var(--font-hint);
}
#welcome_screen #welcome_title {
font-size: 28dp;
font-style: bold|shadow;
color: var(--font-hint);
text-shadow-color: light-dark(#00000019, #00000066);
}
#welcome_screen #welcome_hint {
margin-top: 8dp;
}
#welcome_screen PushButton {
min-width: 200dp;
background-color: var(--list-back);
}
#welcome_screen PushButton:hover {
border-color: var(--primary);
}
#welcome_screen PushButton:pressed {
background-color: var(--primary);
color: var(--font-selected-pressed);
}
#welcome_screen #welcome_logo {
focusable: false;
background-image: icon(ecode,256dp);
background-position: center center;
background-tint: var(--font-hint);
background-size: 100% 100%;
}
#welcome_screen #welcome_logo:hover {
background-tint: var(--primary);
}
]]>
</style>
<vbox lw="wc" lh="wc" lg="center">
<image id="welcome_logo" lw="wc" min-width="128dp" lh="128dp" lg="center" />
<tv id="welcome_title" text="eeiv" lg="center" />
<tv id="welcome_hint" text="Open an image or a folder to get started" lg="center" margin-bottom="24dp" />
<PushButton id="open_image" text="Open Image" lg="center" margin-bottom="8dp" />
<PushButton id="open_folder" text="Open Folder" lg="center" />
</vbox>
)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(); } );
}
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#include <eepp/ui/uirelativelayout.hpp>
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 };
};
+7
View File
@@ -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<int>( currentDisplay->getBounds().getWidth() * 0.8 ) );
if ( winSize.getHeight() >= currentDisplay->getBounds().getHeight() )
winSize.setHeight( static_cast<int>( currentDisplay->getBounds().getHeight() * 0.75 ) );
win = Engine::instance()->createWindow(
WindowSettings( winSize.getWidth(), winSize.getHeight(), "eterm", WindowStyle::Default,
WindowBackend::Default, 32, resPath + "icon/eterm.png",