mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-10-01 18:50:16 +03:00
UIImageViewer expanded capabilities.
ecode image viewing will not auto-scale images to the pixel density. eeiv: Modernizing eeiv to use eepp GUI, already working just like before, there are probably a few things to fix.
This commit is contained in:
@@ -98,6 +98,7 @@ ResourcePtr<UIIconTheme> IconManager::init( const std::string& iconThemeName,
|
||||
{ "filetype-pic", 0xF3C5 },
|
||||
{ "filetype-pvr", 0xF3C5 },
|
||||
{ "filetype-pkm", 0xF3C5 },
|
||||
{ "filetype-webp", 0xF3C5 },
|
||||
{ "filetype-mp3", 0xEF83 },
|
||||
{ "filetype-ogg", 0xEF83 },
|
||||
{ "filetype-wav", 0xEF83 },
|
||||
|
||||
@@ -456,6 +456,7 @@ void UIDiffView::createImageViewers() {
|
||||
iv->setVisible( false );
|
||||
iv->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::Fixed );
|
||||
iv->setDisplayOptions( UIImageViewer::DisplayDimensions );
|
||||
iv->setUseNativeImageSize( true );
|
||||
return iv;
|
||||
};
|
||||
mLeftImageViewer = initImageView();
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <eepp/system/filesystem.hpp>
|
||||
#include <eepp/system/iostreamfile.hpp>
|
||||
#include <eepp/system/iostreammemory.hpp>
|
||||
#include <eepp/system/log.hpp>
|
||||
#include <eepp/system/scopedop.hpp>
|
||||
#include <eepp/ui/tools/uiimageviewer.hpp>
|
||||
#include <eepp/ui/uiimage.hpp>
|
||||
@@ -68,7 +69,9 @@ UIImageViewer::UIImageViewer() : UIWidget( "imageviewer" ) {
|
||||
mImage->setVisible( false );
|
||||
mImage->setDragEnabled( true );
|
||||
mImage->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::Fixed );
|
||||
mImage->setScaleType( UIScaleType::FitInside );
|
||||
// UIImageViewer calculates an aspect-preserving destination size. Expand makes UIImage render
|
||||
// into that exact box, including the optional density-aware upscale.
|
||||
mImage->setScaleType( UIScaleType::Expand );
|
||||
mLoader = UILoader::New();
|
||||
mLoader->setParent( this );
|
||||
mLoader->setIndeterminate( true );
|
||||
@@ -152,59 +155,109 @@ void UIImageViewer::loadImageAsync( std::string_view path, bool isContents, bool
|
||||
path.size() )
|
||||
: Image::getFormat( path );
|
||||
|
||||
if ( format == Image::Format::Unknown )
|
||||
if ( format == Image::Format::Unknown ) {
|
||||
Log::error( "UIImageViewer: unsupported or invalid image: %s",
|
||||
isContents ? "<memory>" : path.c_str() );
|
||||
runOnMainThread( [this] { mLoader->setVisible( false ); } );
|
||||
return;
|
||||
|
||||
DrawablePtr image;
|
||||
|
||||
if ( mClosing )
|
||||
return;
|
||||
|
||||
if ( format != Image::Format::GIF ) {
|
||||
auto tex = isContents ? TextureFactory::instance()->loadFromMemory(
|
||||
reinterpret_cast<const unsigned char*>( path.c_str() ),
|
||||
path.size() )
|
||||
: TextureFactory::instance()->loadFromFile( path );
|
||||
SpritePtr sprite = Sprite::New();
|
||||
sprite->createStatic( tex );
|
||||
image = std::move( sprite );
|
||||
} else {
|
||||
IOStream* stream = isContents
|
||||
? (IOStream*)new IOStreamMemory( path.c_str(), path.size() )
|
||||
: (IOStream*)new IOStreamFile( path );
|
||||
SpritePtr sprite = Sprite::fromGif( *stream );
|
||||
sprite->setAutoAnimate( false );
|
||||
image = std::move( sprite );
|
||||
delete stream;
|
||||
}
|
||||
|
||||
if ( mClosing )
|
||||
return;
|
||||
|
||||
if ( image ) {
|
||||
mCurFileSize = isContents ? path.size() : FileSystem::fileSize( path );
|
||||
mCurFileType = format;
|
||||
auto decodedImages = std::make_shared<std::vector<Image>>();
|
||||
int gifDelay = 0;
|
||||
if ( format == Image::Format::GIF ) {
|
||||
if ( isContents ) {
|
||||
IOStreamMemory stream( path.c_str(), path.size() );
|
||||
auto gif = Image::loadGif( stream );
|
||||
*decodedImages = std::move( gif.first );
|
||||
gifDelay = gif.second;
|
||||
} else {
|
||||
IOStreamFile stream( path );
|
||||
auto gif = Image::loadGif( stream );
|
||||
*decodedImages = std::move( gif.first );
|
||||
gifDelay = gif.second;
|
||||
}
|
||||
} else {
|
||||
Image decoded =
|
||||
isContents ? Image( reinterpret_cast<const Uint8*>( path.data() ), path.size() )
|
||||
: Image( path );
|
||||
if ( decoded.getPixelsPtr() )
|
||||
decodedImages->emplace_back( std::move( decoded ) );
|
||||
}
|
||||
if ( decodedImages->empty() )
|
||||
Log::error( "UIImageViewer: failed to decode image: %s",
|
||||
isContents ? "<memory>" : path.c_str() );
|
||||
|
||||
runOnMainThread( [this, image] {
|
||||
const Int64 fileSize = isContents ? path.size() : FileSystem::fileSize( path );
|
||||
std::string filePath( isContents ? std::string{} : path );
|
||||
|
||||
SpritePtr sprite = Sprite::New();
|
||||
for ( const Image& decoded : *decodedImages ) {
|
||||
auto texture = TextureFactory::instance()->loadFromPixels(
|
||||
decoded.getPixelsPtr(), decoded.getWidth(), decoded.getHeight(),
|
||||
decoded.getChannels(), false, Texture::ClampMode::ClampToEdge, false, false,
|
||||
filePath );
|
||||
if ( texture )
|
||||
sprite->addFrame( std::move( texture ) );
|
||||
else
|
||||
Log::error( "UIImageViewer: texture upload failed for a %ux%u image",
|
||||
decoded.getWidth(), decoded.getHeight() );
|
||||
}
|
||||
|
||||
runOnMainThread( [this, decodedImages, format, fileSize, gifDelay,
|
||||
filePath = std::move( filePath ), sprite = std::move( sprite )] {
|
||||
DrawablePtr image;
|
||||
if ( sprite->getNumFrames() ) {
|
||||
const size_t frameCount = sprite->getNumFrames();
|
||||
if ( format == Image::Format::GIF ) {
|
||||
sprite->setAnimationSpeed( 1000.f / static_cast<Float>( gifDelay ) );
|
||||
sprite->setAutoAnimate( false );
|
||||
}
|
||||
image = std::move( sprite );
|
||||
mCurFileSize = fileSize;
|
||||
mCurFileType = format;
|
||||
mImage->setDrawable( image );
|
||||
updateTextDisplay();
|
||||
auto s( image->getPixelsSize() );
|
||||
auto scale( s.x > mSize.x || s.y > mSize.y
|
||||
? eemin( mSize.x / s.getWidth(), mSize.y / s.getHeight() )
|
||||
: 1.f );
|
||||
mImage->setPixelsSize( eefloor( image->getPixelsSize().x * scale ),
|
||||
eefloor( image->getPixelsSize().y * scale ) );
|
||||
resetImageView();
|
||||
updateImageLayout();
|
||||
if ( !mPreserveImageView )
|
||||
resetImageView();
|
||||
else
|
||||
mImage->setVisible( true );
|
||||
Log::info( "UIImageViewer: loaded %s (%dx%d, %d frame%s)",
|
||||
Image::formatToString( format ).c_str(), (int)s.x, (int)s.y,
|
||||
(int)frameCount, frameCount == 1 ? "" : "s" );
|
||||
sendCommonEvent( Event::OnResourceLoaded );
|
||||
} );
|
||||
}
|
||||
|
||||
runOnMainThread( [this] { mLoader->setVisible( false ); } );
|
||||
}
|
||||
mLoader->setVisible( false );
|
||||
} );
|
||||
} );
|
||||
}
|
||||
|
||||
void UIImageViewer::onSizeChange() {
|
||||
mLoader->center();
|
||||
if ( mAutoFitOnSizeChange ) {
|
||||
mImage->setScale( 1.f );
|
||||
updateImageLayout();
|
||||
}
|
||||
}
|
||||
|
||||
void UIImageViewer::updateImageLayout() {
|
||||
if ( !mImage || !mImage->getDrawable() )
|
||||
return;
|
||||
|
||||
Sizef imageSize( mImage->getDrawable()->getPixelsSize() );
|
||||
if ( mUseNativeImageSize )
|
||||
imageSize /= PixelDensity::getPixelDensity();
|
||||
|
||||
const Float scale =
|
||||
imageSize.x > mSize.x || imageSize.y > mSize.y
|
||||
? eemin( mSize.x / imageSize.getWidth(), mSize.y / imageSize.getHeight() )
|
||||
: 1.f;
|
||||
mImage->setPixelsSize( eefloor( imageSize.x * scale ), eefloor( imageSize.y * scale ) );
|
||||
mImage->center();
|
||||
}
|
||||
|
||||
void UIImageViewer::reset() {
|
||||
|
||||
@@ -2543,6 +2543,7 @@ void App::loadImageFromMedium( const std::string& path, bool isMemory, bool forc
|
||||
}
|
||||
} else {
|
||||
UIImageViewer* imageView = UIImageViewer::New();
|
||||
imageView->setUseNativeImageSize( true );
|
||||
auto [tab, iv] =
|
||||
mSplitter->createWidget( imageView, i18n( "image_viewer", "Image Viewer" ) );
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,193 +0,0 @@
|
||||
#ifndef CAPP_H
|
||||
#define CAPP_H
|
||||
|
||||
#include <eepp/ee.hpp>
|
||||
|
||||
#include "consolecommands.hpp"
|
||||
|
||||
class App {
|
||||
public:
|
||||
struct ImageData {
|
||||
std::string Path;
|
||||
std::vector<TexturePtr> Tex;
|
||||
Float animFps{ 60 };
|
||||
};
|
||||
|
||||
struct Config {
|
||||
Uint32 Width;
|
||||
Uint32 Height;
|
||||
Uint8 BitColor;
|
||||
bool Windowed;
|
||||
bool Resizeable;
|
||||
bool VSync;
|
||||
bool DoubleBuffering;
|
||||
bool UseDesktopResolution;
|
||||
bool NoFrame;
|
||||
bool MaximizeAtStart;
|
||||
bool Fade;
|
||||
bool LateLoading;
|
||||
bool BlockWheelSpeed;
|
||||
bool ShowInfo;
|
||||
Uint32 FrameLimit;
|
||||
float TransitionTime;
|
||||
int ConsoleFontSize;
|
||||
int AppFontSize;
|
||||
float DefaultImageZoom;
|
||||
Uint32 WheelBlockTime;
|
||||
};
|
||||
|
||||
static bool isRawImage( const std::string& path );
|
||||
|
||||
static bool isImage( const std::string& _path );
|
||||
|
||||
static bool isHttpUrl( const std::string& path );
|
||||
|
||||
App( int argc, char* argv[] );
|
||||
|
||||
~App();
|
||||
|
||||
void process();
|
||||
|
||||
void loadDir( const std::string& path, const bool& getimages = true );
|
||||
|
||||
const std::string& getFileDirectoryPath() const { return mFilePath; }
|
||||
|
||||
const std::string& getFile() const { return mFile; }
|
||||
|
||||
std::string getFilePath() const { return mFilePath + mFile; }
|
||||
|
||||
bool getSlideShow() const { return mSlideShow; }
|
||||
|
||||
void setSlideShow( bool set ) { mSlideShow = set; }
|
||||
|
||||
void createSlideShow( Uint32 time );
|
||||
|
||||
void fastLoadImage( const Uint32& ImgNum );
|
||||
|
||||
void setImgScale( Float scale );
|
||||
|
||||
const std::vector<ImageData> getFiles() const { return mFiles; }
|
||||
|
||||
EE::Window::Window* getWindow() const { return mWindow; }
|
||||
|
||||
Config& getConfig() { return mConfig; }
|
||||
|
||||
protected:
|
||||
void updateConfig();
|
||||
bool init();
|
||||
void input();
|
||||
void render();
|
||||
void end();
|
||||
void prepareFrame();
|
||||
void scaleToScreen( const bool& force = false );
|
||||
void getImages();
|
||||
Uint32 curImagePos( const std::string& path );
|
||||
std::pair<std::vector<TexturePtr>, Float> loadImage( const std::string& path,
|
||||
const bool& SetAsCurrent = false );
|
||||
void loadNextImage();
|
||||
void loadPrevImage();
|
||||
void zoomImage();
|
||||
void unloadImage( const Uint32& img );
|
||||
void updateImages();
|
||||
void setImage( const std::vector<TexturePtr>& Tex, const std::string& path,
|
||||
Float animFps = 60 );
|
||||
void doFade();
|
||||
void createFade();
|
||||
void optUpdate();
|
||||
void printHelp();
|
||||
void loadFirstImage();
|
||||
void loadLastImage();
|
||||
void loadConfigValues();
|
||||
void loadConfig();
|
||||
void saveConfig();
|
||||
void clearTempDir();
|
||||
void videoResize();
|
||||
void restoreMouse();
|
||||
void setWindowCaption();
|
||||
void switchFade();
|
||||
void doSlideShow();
|
||||
void disableSlideShow();
|
||||
|
||||
Config mConfig;
|
||||
|
||||
Engine* EE;
|
||||
TextureFactory* TF;
|
||||
System::Log* Log;
|
||||
EE::Window::Window* mWindow{ nullptr };
|
||||
EE::Window::Input* KM;
|
||||
|
||||
std::string MyPath;
|
||||
|
||||
Font* Fon; //! Default App Font
|
||||
Font* Mon; //! Console App Font
|
||||
Text FonCache;
|
||||
|
||||
FontTrueTypePtr TTF, TTFMon;
|
||||
|
||||
UIConsole* Con; //! Console Instance
|
||||
|
||||
Vector2i Mouse; //! Mouse Position on Screen
|
||||
double ET; //! Elapsed Time Between Frames
|
||||
double RET; //! Relative Elapsed Time ( skip time in Input() )
|
||||
|
||||
Float Width, Height; //! Width and Height of the Window
|
||||
Float HWidth, HHeight; //! Half Width and Height of the Window
|
||||
|
||||
std::string SLASH; //! Default SLASH string
|
||||
|
||||
std::vector<ImageData> mFiles; //! Directory image file list
|
||||
|
||||
Int32 mLastTicks, mZoomTicks;
|
||||
std::string mInfo; //! Window caption string
|
||||
|
||||
std::string mFilePath; //! Directory path of files
|
||||
std::string mFile; //! Last used file name
|
||||
|
||||
Int32 mCurImg; //! Current Image Selected from mFile
|
||||
Sprite mImg, mOldImg;
|
||||
|
||||
bool mFading;
|
||||
Float mAlpha;
|
||||
Uint8 mCurAlpha;
|
||||
|
||||
bool mLaterLoad;
|
||||
Int32 mLastLaterTick;
|
||||
|
||||
Clock TEP;
|
||||
|
||||
bool mCursor;
|
||||
|
||||
bool mMouseLeftPressing;
|
||||
Vector2i mMouseLeftStartClick, mMouseLeftClick;
|
||||
|
||||
bool mMouseMiddlePressing;
|
||||
Vector2i mMouseMiddleStartClick, mMouseMiddleClick;
|
||||
|
||||
RenderMode mImgRT;
|
||||
Texture::Filter mFilter;
|
||||
|
||||
Int32 mLastWheelUse;
|
||||
bool mShowHelp;
|
||||
|
||||
bool mFirstLoad;
|
||||
|
||||
std::string mStorePath;
|
||||
std::string mTmpPath;
|
||||
bool mUsedTempDir;
|
||||
bool mLockZoomAndPosition;
|
||||
|
||||
Clock TE;
|
||||
|
||||
Text* mHelpCache;
|
||||
|
||||
bool mSlideShow;
|
||||
Uint32 mSlideTime;
|
||||
Uint32 mSlideTicks;
|
||||
|
||||
IniFile Ini;
|
||||
|
||||
Image::FormatConfiguration formatConfiguration;
|
||||
std::unique_ptr<ConsoleCommands> mConCmds;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "consolecommands.hpp"
|
||||
#include "app.hpp"
|
||||
#include "eeiv.hpp"
|
||||
|
||||
static std::string createSavePath( const std::string& oriPath, Uint32 width, Uint32 height,
|
||||
Image::SaveType saveType ) {
|
||||
@@ -507,7 +507,7 @@ void ConsoleCommands::cmdBatchImgChangeFormat( const std::vector<String>& params
|
||||
}
|
||||
|
||||
void ConsoleCommands::cmdMoveTo( const std::vector<String>& params ) {
|
||||
if ( params.size() >= 2 && mApp->getFiles().size() > 0 ) {
|
||||
if ( params.size() >= 2 && mApp->getFileCount() > 0 ) {
|
||||
Int32 tInt = 0;
|
||||
|
||||
bool Res = String::fromString( tInt, params[1] );
|
||||
@@ -515,12 +515,12 @@ void ConsoleCommands::cmdMoveTo( const std::vector<String>& params ) {
|
||||
if ( tInt )
|
||||
tInt--;
|
||||
|
||||
if ( Res && tInt >= 0 && tInt < (Int32)mApp->getFiles().size() ) {
|
||||
if ( Res && tInt >= 0 && tInt < (Int32)mApp->getFileCount() ) {
|
||||
Con->pushText( "moveto: moving to image number " + String::toString( tInt + 1 ) );
|
||||
mApp->fastLoadImage( tInt );
|
||||
} else if ( params[1] == "last" ) {
|
||||
Con->pushText( "moveto: moving to last" );
|
||||
mApp->fastLoadImage( mApp->getFiles().size() - 1 );
|
||||
mApp->fastLoadImage( mApp->getFileCount() - 1 );
|
||||
} else if ( params[1] == "first" ) {
|
||||
Con->pushText( "moveto: moving to first" );
|
||||
mApp->fastLoadImage( 0 );
|
||||
@@ -578,18 +578,30 @@ void ConsoleCommands::cmdSetImgFade( const std::vector<String>& params ) {
|
||||
}
|
||||
|
||||
void ConsoleCommands::cmdSetBackColor( const std::vector<String>& params ) {
|
||||
String Error(
|
||||
const String error(
|
||||
"Usage example: setbackcolor 255 255 255 (RGB Color, numbers between 0 and 255)" );
|
||||
|
||||
if ( params.size() >= 2 ) {
|
||||
if ( params.size() >= 2 ) {
|
||||
mApp->getWindow()->setClearColor( Color::fromString( params[1].toUtf8() ).toRGB() );
|
||||
if ( params.size() == 2 ) {
|
||||
mApp->setBackgroundColor( Color::fromString( params[1].toUtf8() ) );
|
||||
Con->pushText( "setbackcolor applied" );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( params.size() >= 4 ) {
|
||||
Int32 red;
|
||||
Int32 green;
|
||||
Int32 blue;
|
||||
if ( String::fromString( red, params[1] ) && String::fromString( green, params[2] ) &&
|
||||
String::fromString( blue, params[3] ) && red >= 0 && red <= 255 && green >= 0 &&
|
||||
green <= 255 && blue >= 0 && blue <= 255 ) {
|
||||
mApp->setBackgroundColor( Color( static_cast<Uint8>( red ), static_cast<Uint8>( green ),
|
||||
static_cast<Uint8>( blue ) ) );
|
||||
Con->pushText( "setbackcolor applied" );
|
||||
return;
|
||||
}
|
||||
|
||||
Con->pushText( Error );
|
||||
}
|
||||
|
||||
Con->pushText( error );
|
||||
}
|
||||
|
||||
void ConsoleCommands::cmdLoadImg( const std::vector<String>& params ) {
|
||||
|
||||
Executable → Regular
+507
-11
@@ -1,15 +1,511 @@
|
||||
#include "app.hpp"
|
||||
#include "eeiv.hpp"
|
||||
|
||||
EE_MAIN_FUNC int main(int argc, char *argv[]) {
|
||||
App * MyApp = eeNew( App, ( argc, argv ) );
|
||||
#include <eepp/network/http.hpp>
|
||||
|
||||
MyApp->process();
|
||||
using namespace EE::Network;
|
||||
using namespace EE::Window;
|
||||
|
||||
eeDelete( MyApp );
|
||||
|
||||
Engine::destroySingleton();
|
||||
|
||||
EE::MemoryManager::showResults();
|
||||
|
||||
return 0;
|
||||
bool App::isImage( const std::string& inputPath ) {
|
||||
std::string path( inputPath );
|
||||
if ( String::startsWith( path, "file://" ) )
|
||||
path.erase( 0, 7 );
|
||||
return !FileSystem::isDirectory( path ) && FileSystem::fileSize( path ) &&
|
||||
Image::isImage( path );
|
||||
}
|
||||
|
||||
bool App::isHttpUrl( const std::string& path ) {
|
||||
return String::startsWith( path, "http://" ) || String::startsWith( path, "https://" );
|
||||
}
|
||||
|
||||
App::App( int argc, char* argv[] ) :
|
||||
mStorePath( Sys::getConfigPath( "eeiv" ) + FileSystem::getOSSlash() ),
|
||||
mTmpPath( mStorePath + "tmp" + FileSystem::getOSSlash() ) {
|
||||
if ( argc > 1 ) {
|
||||
mInitialPath = argv[1];
|
||||
if ( FileSystem::isRelativePath( mInitialPath ) && !isHttpUrl( mInitialPath ) ) {
|
||||
std::string cwd( FileSystem::getCurrentWorkingDirectory() );
|
||||
FileSystem::dirAddSlashAtEnd( cwd );
|
||||
mInitialPath.insert( 0, cwd );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
App::~App() {
|
||||
if ( mUIApplication ) {
|
||||
saveConfig();
|
||||
Http::Pool::getGlobal().clear();
|
||||
Http::setThreadPool( nullptr );
|
||||
}
|
||||
}
|
||||
|
||||
EE::Window::Window* App::getWindow() const {
|
||||
return mUIApplication ? mUIApplication->getWindow() : nullptr;
|
||||
}
|
||||
|
||||
void App::setBackgroundColor( const Color& color ) {
|
||||
if ( getWindow() )
|
||||
getWindow()->setClearColor( color.toRGB() );
|
||||
if ( mMainLayout )
|
||||
mMainLayout->setBackgroundColor( color );
|
||||
}
|
||||
|
||||
void App::loadConfig() {
|
||||
const std::string configPath( mStorePath + "eeiv.ini" );
|
||||
mIni.loadFromFile( configPath );
|
||||
if ( FileSystem::fileExists( configPath ) )
|
||||
mIni.readFile();
|
||||
else
|
||||
FileSystem::makeDir( mStorePath );
|
||||
|
||||
mConfig.Fade = mIni.getValueB( "viewer", "fade", true );
|
||||
mConfig.LateLoading = mIni.getValueB( "viewer", "lateloading", true );
|
||||
mConfig.BlockWheelSpeed = mIni.getValueB( "viewer", "blockwheelspeed", true );
|
||||
mConfig.ShowInfo = mIni.getValueB( "viewer", "showinfo", true );
|
||||
mConfig.MaximizeAtStart = mIni.getValueB( "window", "maximizeatstart", true );
|
||||
mConfig.VSync = mIni.getValueB( "window", "vsync", false );
|
||||
const std::string frameRateLimit( mIni.getValue( "window", "frameratelimit" ) );
|
||||
mConfig.FrameLimit = frameRateLimit.empty()
|
||||
? mIni.getValueI( "window", "framelimit",
|
||||
ContextSettings::FrameRateLimitScreenRefreshRate )
|
||||
: mIni.getValueI( "window", "frameratelimit",
|
||||
ContextSettings::FrameRateLimitScreenRefreshRate );
|
||||
mConfig.TransitionTime = mIni.getValueF( "viewer", "transitiontime", 200 );
|
||||
mConfig.ConsoleFontSize = mIni.getValueI( "viewer", "consolefontsize", 12 );
|
||||
mConfig.AppFontSize = mIni.getValueI( "viewer", "appfontsize", 12 );
|
||||
mConfig.DefaultImageZoom = mIni.getValueF( "viewer", "defaultimagezoom", 1 );
|
||||
mConfig.WheelBlockTime = mIni.getValueI( "viewer", "wheelblocktime", 200 );
|
||||
}
|
||||
|
||||
void App::updateConfig() {
|
||||
if ( !getWindow() || !getWindow()->isOpen() )
|
||||
return;
|
||||
mIni.setValueI( "window", "width", getWindow()->getWidth() );
|
||||
mIni.setValueI( "window", "height", getWindow()->getHeight() );
|
||||
mConfig.MaximizeAtStart = getWindow()->isMaximized();
|
||||
}
|
||||
|
||||
void App::saveConfig() {
|
||||
updateConfig();
|
||||
mIni.setValueI( "viewer", "fade", mConfig.Fade );
|
||||
mIni.setValueI( "viewer", "lateloading", mConfig.LateLoading );
|
||||
mIni.setValueI( "viewer", "blockwheelspeed", mConfig.BlockWheelSpeed );
|
||||
mIni.setValueI( "viewer", "showinfo", mConfig.ShowInfo );
|
||||
mIni.setValueI( "window", "vsync", mConfig.VSync );
|
||||
mIni.setValueI( "window", "frameratelimit", mConfig.FrameLimit );
|
||||
mIni.setValueI( "window", "maximizeatstart", mConfig.MaximizeAtStart );
|
||||
mIni.setValueF( "viewer", "transitiontime", mConfig.TransitionTime );
|
||||
mIni.setValueI( "viewer", "consolefontsize", mConfig.ConsoleFontSize );
|
||||
mIni.setValueI( "viewer", "appfontsize", mConfig.AppFontSize );
|
||||
mIni.setValueF( "viewer", "defaultimagezoom", mConfig.DefaultImageZoom );
|
||||
mIni.setValueI( "viewer", "wheelblocktime", mConfig.WheelBlockTime );
|
||||
mIni.writeFile();
|
||||
}
|
||||
|
||||
bool App::init() {
|
||||
loadConfig();
|
||||
WindowSettings windowSettings = Engine::instance()->createWindowSettings( &mIni, "window" );
|
||||
ContextSettings contextSettings =
|
||||
Engine::instance()->createContextSettings( &mIni, "window", false );
|
||||
contextSettings.VSync = mConfig.VSync;
|
||||
contextSettings.FrameRateLimit = mConfig.FrameLimit;
|
||||
contextSettings.SharedGLContext = true;
|
||||
windowSettings.Title = "eeiv";
|
||||
windowSettings.Icon = Sys::getProcessPath() + "assets/eeiv.png";
|
||||
if ( !FileSystem::fileExists( windowSettings.Icon ) )
|
||||
windowSettings.Icon = Sys::getProcessPath() + "assets/icon/ee.png";
|
||||
|
||||
mUIApplication = std::make_unique<UIApplication>( windowSettings, UIApplication::Settings(),
|
||||
contextSettings );
|
||||
if ( !getWindow() || !getWindow()->isOpen() )
|
||||
return false;
|
||||
setBackgroundColor( Color::Black );
|
||||
|
||||
mThreadPool = ThreadPool::createShared( 2 );
|
||||
mUIApplication->getUI()->setThreadPool( mThreadPool );
|
||||
Http::setThreadPool( mThreadPool );
|
||||
if ( mConfig.MaximizeAtStart )
|
||||
getWindow()->maximize();
|
||||
getWindow()->setCloseRequestCallback( [this]( EE::Window::Window* ) {
|
||||
saveConfig();
|
||||
return true;
|
||||
} );
|
||||
|
||||
mMainLayout = mUIApplication->getUI()->loadLayoutFromString( R"xml(
|
||||
<RelativeLayout id="eeiv_layout" lw="mp" lh="mp" background-color="#000">
|
||||
<ImageViewer id="image_viewer" lw="mp" lh="mp" />
|
||||
<TextView id="key_help" lw="wc" lh="wc" lg="bottom|left" margin="8dp"
|
||||
padding="8dp" background-color="#141414DC" visible="false" enabled="false" />
|
||||
</RelativeLayout>
|
||||
)xml" );
|
||||
if ( !mMainLayout ) {
|
||||
Log::error( "eeiv: failed to create the main UI layout" );
|
||||
return false;
|
||||
}
|
||||
mImageViewer = mMainLayout->find<UIImageViewer>( "image_viewer" );
|
||||
mHelp = mMainLayout->find<UITextView>( "key_help" );
|
||||
if ( !mImageViewer || !mHelp ) {
|
||||
Log::error( "eeiv: one or more widgets are missing from the main UI layout" );
|
||||
return false;
|
||||
}
|
||||
|
||||
mImageViewer->setMinScale( 0.0125f );
|
||||
mImageViewer->setMaxScale( 50.f );
|
||||
mImageViewer->setAutoFitOnSizeChange( true );
|
||||
mImageViewer->setUseNativeImageSize( true );
|
||||
mImageViewer->setDisplayOptions( mConfig.ShowInfo ? UIImageViewer::DisplayName |
|
||||
UIImageViewer::DisplayDimensions |
|
||||
UIImageViewer::DisplayGalleryPosition
|
||||
: 0 );
|
||||
mImageViewer->on( Event::OnResourceLoaded, [this]( auto ) { syncLoadedImage(); } );
|
||||
|
||||
mHelp->setText( "H: Toggle this help\n"
|
||||
"F3: Toggle console\n"
|
||||
"F11: Open UI inspector\n"
|
||||
"F12: Take screenshot\n"
|
||||
"Mouse wheel: Previous / next image\n"
|
||||
"Page Up: Previous image\n"
|
||||
"Page Down: Next image\n"
|
||||
"Home: First image\n"
|
||||
"End: Last image\n"
|
||||
"Arrow keys: Move image\n"
|
||||
"Keypad + / -: Zoom image\n"
|
||||
"Z: Fit image\n"
|
||||
"Keypad *: Fit image\n"
|
||||
"Keypad /: Reset zoom\n"
|
||||
"X: Flip image\n"
|
||||
"C: Mirror image\n"
|
||||
"R: Rotate image\n"
|
||||
"T: Reset view\n"
|
||||
"A: Toggle filtering\n"
|
||||
"E: Start slideshow\n"
|
||||
"D: Stop slideshow\n"
|
||||
"L: Lock view\n"
|
||||
"F5: Reload image\n"
|
||||
"F: Toggle fullscreen\n"
|
||||
"S: Toggle cursor\n"
|
||||
"I: Toggle image info\n"
|
||||
"Q: Quit\n"
|
||||
"Escape: Quit" );
|
||||
|
||||
// Quake-mode consoles are root overlays by design. Keeping it outside the content layout also
|
||||
// preserves UIConsole's native show/hide animation.
|
||||
mConsole = UIConsole::NewOpt( nullptr, true, true, 1024000 );
|
||||
mConsole->setParent( mUIApplication->getUI()->getRoot() );
|
||||
mConsole->setQuakeMode( true );
|
||||
mConsole->setVisible( false );
|
||||
mConsole->setMaxLogLines( 1024000 );
|
||||
mConsole->setFontSize( mConfig.ConsoleFontSize );
|
||||
mConsoleCommands = std::make_unique<ConsoleCommands>( this, mConsole );
|
||||
registerConsoleCommands();
|
||||
registerKeyBindings();
|
||||
|
||||
if ( !mInitialPath.empty() )
|
||||
loadDir( mInitialPath, true );
|
||||
if ( mFiles.empty() )
|
||||
mConsole->toggle();
|
||||
return true;
|
||||
}
|
||||
|
||||
void App::registerConsoleCommands() {
|
||||
const auto add = [this]( const char* name, auto command ) {
|
||||
mConsole->addCommand( name, [this, command]( const auto& event ) {
|
||||
( mConsoleCommands.get()->*command )( event );
|
||||
} );
|
||||
};
|
||||
add( "loaddir", &ConsoleCommands::cmdLoadDir );
|
||||
add( "loadimg", &ConsoleCommands::cmdLoadImg );
|
||||
add( "setbackcolor", &ConsoleCommands::cmdSetBackColor );
|
||||
add( "setimgfade", &ConsoleCommands::cmdSetImgFade );
|
||||
add( "setlateloading", &ConsoleCommands::cmdSetLateLoading );
|
||||
add( "setblockwheel", &ConsoleCommands::cmdSetBlockWheel );
|
||||
add( "moveto", &ConsoleCommands::cmdMoveTo );
|
||||
add( "batchimgscale", &ConsoleCommands::cmdBatchImgScale );
|
||||
add( "batchimgchangeformat", &ConsoleCommands::cmdBatchImgChangeFormat );
|
||||
add( "batchimgthumbnail", &ConsoleCommands::cmdBatchImgThumbnail );
|
||||
add( "imgchangeformat", &ConsoleCommands::cmdImgChangeFormat );
|
||||
add( "imgresize", &ConsoleCommands::cmdImgResize );
|
||||
add( "imgscale", &ConsoleCommands::cmdImgScale );
|
||||
add( "imgthumbnail", &ConsoleCommands::cmdImgThumbnail );
|
||||
add( "imgcentercrop", &ConsoleCommands::cmdImgCenterCrop );
|
||||
add( "slideshow", &ConsoleCommands::cmdSlideShow );
|
||||
add( "setzoom", &ConsoleCommands::cmdSetZoom );
|
||||
}
|
||||
|
||||
void App::registerKeyBindings() {
|
||||
mUIApplication->getUI()->on( Event::KeyUp, [this]( const Event* event ) {
|
||||
const auto* keyEvent = event->asKeyEvent();
|
||||
const Keycode key = keyEvent->getKeyCode();
|
||||
if ( key == KEY_F11 ) {
|
||||
UIWidgetInspector::create( mUIApplication->getUI() );
|
||||
return;
|
||||
}
|
||||
if ( key == KEY_F3 ) {
|
||||
mHelp->setVisible( false );
|
||||
mConsole->toggle();
|
||||
return;
|
||||
}
|
||||
if ( mConsole->isActive() )
|
||||
return;
|
||||
if ( key == KEY_ESCAPE || key == KEY_Q )
|
||||
getWindow()->close();
|
||||
else if ( key == KEY_TAB && keyEvent->getMod() & KEYMOD_ALT )
|
||||
getWindow()->minimize();
|
||||
else if ( key == KEY_F || ( key == KEY_RETURN && keyEvent->getMod() & KEYMOD_ALT ) )
|
||||
getWindow()->toggleFullscreen();
|
||||
else if ( key == KEY_F12 )
|
||||
getWindow()->takeScreenshot();
|
||||
else if ( key == KEY_H )
|
||||
toggleHelp();
|
||||
else if ( key == KEY_S || key == KEY_F4 ) {
|
||||
mCursorVisible = !mCursorVisible;
|
||||
getWindow()->getCursorManager()->setVisible( mCursorVisible );
|
||||
} else if ( ( key == KEY_V && keyEvent->getMod() & KEYMOD_CTRL ) ||
|
||||
( key == KEY_INSERT && keyEvent->getMod() & KEYMOD_SHIFT ) ) {
|
||||
const std::string path( getWindow()->getClipboard()->getText() );
|
||||
if ( isImage( path ) || isHttpUrl( path ) || FileSystem::isDirectory( path ) )
|
||||
loadDir( path );
|
||||
} else if ( key == KEY_HOME && !mFiles.empty() )
|
||||
fastLoadImage( 0 );
|
||||
else if ( key == KEY_END && !mFiles.empty() )
|
||||
fastLoadImage( mFiles.size() - 1 );
|
||||
else if ( key == KEY_PAGEUP && mCurImg > 0 ) {
|
||||
mSlideShow = false;
|
||||
fastLoadImage( mCurImg - 1 );
|
||||
} else if ( key == KEY_PAGEDOWN && mCurImg + 1 < static_cast<Int32>( mFiles.size() ) ) {
|
||||
mSlideShow = false;
|
||||
fastLoadImage( mCurImg + 1 );
|
||||
} else if ( key == KEY_I ) {
|
||||
mConfig.ShowInfo = !mConfig.ShowInfo;
|
||||
mImageViewer->setDisplayOptions(
|
||||
mConfig.ShowInfo ? UIImageViewer::DisplayName | UIImageViewer::DisplayDimensions |
|
||||
UIImageViewer::DisplayGalleryPosition
|
||||
: 0 );
|
||||
} else if ( key == KEY_KP_MULTIPLY || key == KEY_Z ) {
|
||||
fitImage();
|
||||
} else if ( key == KEY_KP_DIVIDE ) {
|
||||
setImgScale( mConfig.DefaultImageZoom );
|
||||
} else if ( key == KEY_N && mImageViewer->getImage()->getDrawable() ) {
|
||||
const Sizef size( mImageViewer->getImage()->getDrawable()->getPixelsSize() );
|
||||
getWindow()->setSize( size.getWidth(), size.getHeight() );
|
||||
} else if ( key == KEY_A ) {
|
||||
if ( Sprite* sprite = getImageSprite() ) {
|
||||
mTextureFilter = mTextureFilter == Texture::Filter::Linear
|
||||
? Texture::Filter::Nearest
|
||||
: Texture::Filter::Linear;
|
||||
for ( size_t i = 0; i < sprite->getNumFrames(); ++i ) {
|
||||
Texture* texture = sprite->getTextureRegion( i )->getTexture().get();
|
||||
if ( texture )
|
||||
texture->setFilter( mTextureFilter );
|
||||
}
|
||||
}
|
||||
} else if ( key == KEY_L ) {
|
||||
mImageViewer->setPreserveImageView( !mImageViewer->getPreserveImageView() );
|
||||
} else if ( key == KEY_M ) {
|
||||
fitImage();
|
||||
if ( getWindow()->isMaximized() && mImageViewer->getImage()->getDrawable() ) {
|
||||
const Sizef size( mImageViewer->getImage()->getDrawable()->getPixelsSize() );
|
||||
getWindow()->setSize( size.getWidth(), size.getHeight() );
|
||||
}
|
||||
} else if ( key == KEY_K ) {
|
||||
if ( Sprite* sprite = getImageSprite() ) {
|
||||
if ( TextureRegion* region = sprite->getCurrentTextureRegion() ) {
|
||||
if ( Texture* texture = region->getTexture().get() ) {
|
||||
texture->setMipmap( !texture->getMipmap() );
|
||||
texture->reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ( key == KEY_F5 && !getFilePath().empty() ) {
|
||||
loadImagePath( getFilePath() );
|
||||
} else if ( key == KEY_E ) {
|
||||
createSlideShow( mSlideTime );
|
||||
} else if ( key == KEY_D ) {
|
||||
mSlideShow = false;
|
||||
}
|
||||
} );
|
||||
mUIApplication->getUI()->on( Event::KeyDown, [this]( const Event* event ) {
|
||||
if ( mConsole->isActive() || !mImageViewer->hasImage() )
|
||||
return;
|
||||
const Keycode key = event->asKeyEvent()->getKeyCode();
|
||||
Vector2f position( mImageViewer->getImage()->getPixelsPosition() );
|
||||
if ( key == KEY_LEFT )
|
||||
position.x += 20.f;
|
||||
else if ( key == KEY_RIGHT )
|
||||
position.x -= 20.f;
|
||||
else if ( key == KEY_UP )
|
||||
position.y += 20.f;
|
||||
else if ( key == KEY_DOWN )
|
||||
position.y -= 20.f;
|
||||
else
|
||||
return;
|
||||
mImageViewer->getImage()->setPixelsPosition( position );
|
||||
} );
|
||||
}
|
||||
|
||||
void App::toggleHelp() {
|
||||
mHelp->setVisible( !mHelp->isVisible() );
|
||||
if ( mHelp->isVisible() )
|
||||
mHelp->toFront();
|
||||
}
|
||||
|
||||
void App::fitImage() {
|
||||
if ( mImageViewer && mImageViewer->hasImage() )
|
||||
mImageViewer->resetImageView();
|
||||
}
|
||||
|
||||
Sprite* App::getImageSprite() const {
|
||||
if ( !mImageViewer || !mImageViewer->getImage() || !mImageViewer->getImage()->getDrawable() )
|
||||
return nullptr;
|
||||
return static_cast<Sprite*>( mImageViewer->getImage()->getDrawable().get() );
|
||||
}
|
||||
|
||||
void App::getImages() {
|
||||
mFiles.clear();
|
||||
if ( !FileSystem::isDirectory( mFilePath ) )
|
||||
return;
|
||||
for ( const std::string& file : FileSystem::filesGetInPath( mFilePath, true ) ) {
|
||||
if ( isImage( mFilePath + file ) )
|
||||
mFiles.push_back( file );
|
||||
}
|
||||
}
|
||||
|
||||
void App::loadDir( const std::string& inputPath, const bool& getImagesList ) {
|
||||
std::string path( inputPath );
|
||||
String::replaceAll( path, "%20", " " );
|
||||
if ( String::startsWith( path, "file://" ) )
|
||||
path.erase( 0, 7 );
|
||||
|
||||
if ( isHttpUrl( path ) ) {
|
||||
loadImageUrl( path );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( FileSystem::isDirectory( path ) ) {
|
||||
mFilePath = path;
|
||||
FileSystem::dirAddSlashAtEnd( mFilePath );
|
||||
mFile.clear();
|
||||
} else {
|
||||
if ( !isImage( path ) )
|
||||
return;
|
||||
mFilePath = FileSystem::fileRemoveFileName( path );
|
||||
FileSystem::dirAddSlashAtEnd( mFilePath );
|
||||
mFile = FileSystem::fileNameFromPath( path );
|
||||
}
|
||||
|
||||
if ( getImagesList )
|
||||
getImages();
|
||||
if ( mFiles.empty() )
|
||||
return;
|
||||
|
||||
mCurImg = 0;
|
||||
if ( !mFile.empty() ) {
|
||||
auto it = std::find( mFiles.begin(), mFiles.end(), mFile );
|
||||
if ( it != mFiles.end() )
|
||||
mCurImg = std::distance( mFiles.begin(), it );
|
||||
}
|
||||
fastLoadImage( mCurImg );
|
||||
}
|
||||
|
||||
void App::loadImagePath( const std::string& path, bool loadGallery ) {
|
||||
Log::info( "eeiv: loading image: %s", path.c_str() );
|
||||
mImageViewer->loadImageAsync( path, false, loadGallery );
|
||||
}
|
||||
|
||||
void App::loadImageUrl( const std::string& url ) {
|
||||
FileSystem::makeDir( mTmpPath );
|
||||
const std::string outputPath( mTmpPath + "download" );
|
||||
mConsole->pushText( "Downloading \"" + url + "\"..." );
|
||||
Http::getAsync(
|
||||
[this, outputPath]( const Http&, Http::Request&, Http::Response& response ) {
|
||||
if ( !response.isOK() ) {
|
||||
mConsole->runOnMainThread( [this, status = response.getStatus()] {
|
||||
mConsole->pushText( "Couldn't download the image (HTTP %d).", status );
|
||||
} );
|
||||
return;
|
||||
}
|
||||
const std::string& body = response.getBody();
|
||||
if ( !FileSystem::fileWrite( outputPath, reinterpret_cast<const Uint8*>( body.data() ),
|
||||
body.size() ) ) {
|
||||
mConsole->runOnMainThread( [this] {
|
||||
mConsole->pushText( "Couldn't write the downloaded image to disk." );
|
||||
} );
|
||||
return;
|
||||
}
|
||||
mConsole->runOnMainThread( [this, outputPath] { loadDir( outputPath ); } );
|
||||
},
|
||||
URI( url ) );
|
||||
}
|
||||
|
||||
void App::fastLoadImage( const Uint32& imageNum ) {
|
||||
if ( imageNum >= mFiles.size() )
|
||||
return;
|
||||
mCurImg = imageNum;
|
||||
mFile = mFiles[mCurImg];
|
||||
loadImagePath( mFilePath + mFile );
|
||||
}
|
||||
|
||||
void App::syncLoadedImage() {
|
||||
const std::string path( mImageViewer->getImagePath() );
|
||||
if ( path.empty() )
|
||||
return;
|
||||
mFilePath = FileSystem::fileRemoveFileName( path );
|
||||
FileSystem::dirAddSlashAtEnd( mFilePath );
|
||||
mFile = FileSystem::fileNameFromPath( path );
|
||||
auto it = std::find( mFiles.begin(), mFiles.end(), mFile );
|
||||
if ( it != mFiles.end() )
|
||||
mCurImg = std::distance( mFiles.begin(), it );
|
||||
if ( Sprite* sprite = getImageSprite() ) {
|
||||
for ( size_t i = 0; i < sprite->getNumFrames(); ++i ) {
|
||||
if ( Texture* texture = sprite->getTextureRegion( i )->getTexture().get() )
|
||||
texture->setFilter( mTextureFilter );
|
||||
}
|
||||
}
|
||||
getWindow()->setTitle( "eeiv - " + mFile );
|
||||
mImageViewer->getImage()->setFocus();
|
||||
Log::info( "eeiv: displaying image %d/%d: %s", mCurImg + 1, mFiles.size(), path.c_str() );
|
||||
}
|
||||
|
||||
void App::setImgScale( Float scale ) {
|
||||
if ( mImageViewer && mImageViewer->getImage() )
|
||||
mImageViewer->getImage()->setScale( scale );
|
||||
}
|
||||
|
||||
void App::createSlideShow( Uint32 time ) {
|
||||
mSlideTime = eemax<Uint32>( 250, time );
|
||||
mSlideTicks = Sys::getTicks();
|
||||
mSlideShow = true;
|
||||
}
|
||||
|
||||
void App::updateSlideShow() {
|
||||
if ( !mSlideShow || Sys::getTicks() - mSlideTicks < mSlideTime )
|
||||
return;
|
||||
mSlideTicks = Sys::getTicks();
|
||||
if ( mCurImg + 1 < static_cast<Int32>( mFiles.size() ) )
|
||||
fastLoadImage( mCurImg + 1 );
|
||||
else
|
||||
mSlideShow = false;
|
||||
}
|
||||
|
||||
void App::process() {
|
||||
if ( !init() )
|
||||
return;
|
||||
getWindow()->runMainLoop( [this] {
|
||||
getWindow()->getInput()->update();
|
||||
updateSlideShow();
|
||||
SceneManager::instance()->update();
|
||||
if ( mUIApplication->getUI()->invalidated() ) {
|
||||
getWindow()->clear();
|
||||
SceneManager::instance()->draw();
|
||||
getWindow()->display();
|
||||
} else {
|
||||
getWindow()->getInput()->waitEvent(
|
||||
Milliseconds( getWindow()->hasFocus() ? 16 : 100 ) );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
EE_MAIN_FUNC int main( int argc, char* argv[] ) {
|
||||
App app( argc, argv );
|
||||
app.process();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
#pragma once
|
||||
|
||||
#include <eepp/ee.hpp>
|
||||
|
||||
#include "consolecommands.hpp"
|
||||
|
||||
using namespace EE;
|
||||
using namespace EE::Graphics;
|
||||
using namespace EE::System;
|
||||
using namespace EE::UI;
|
||||
using namespace EE::UI::Tools;
|
||||
|
||||
class App {
|
||||
public:
|
||||
struct Config {
|
||||
bool Fade{ true };
|
||||
bool LateLoading{ true };
|
||||
bool BlockWheelSpeed{ true };
|
||||
bool ShowInfo{ true };
|
||||
bool MaximizeAtStart{ true };
|
||||
bool VSync{ false };
|
||||
Uint32 FrameLimit{ ContextSettings::FrameRateLimitScreenRefreshRate };
|
||||
float TransitionTime{ 200 };
|
||||
int ConsoleFontSize{ 12 };
|
||||
int AppFontSize{ 12 };
|
||||
float DefaultImageZoom{ 1 };
|
||||
Uint32 WheelBlockTime{ 200 };
|
||||
};
|
||||
|
||||
static bool isImage( const std::string& path );
|
||||
static bool isHttpUrl( const std::string& path );
|
||||
|
||||
App( int argc, char* argv[] );
|
||||
~App();
|
||||
|
||||
void process();
|
||||
void loadDir( const std::string& path, const bool& getImages = true );
|
||||
void fastLoadImage( const Uint32& imageNum );
|
||||
void setImgScale( Float scale );
|
||||
void createSlideShow( Uint32 time );
|
||||
void setBackgroundColor( const Color& color );
|
||||
|
||||
const std::string& getFileDirectoryPath() const { return mFilePath; }
|
||||
const std::string& getFile() const { return mFile; }
|
||||
std::string getFilePath() const { return mFilePath + mFile; }
|
||||
bool getSlideShow() const { return mSlideShow; }
|
||||
void setSlideShow( bool enabled ) { mSlideShow = enabled; }
|
||||
size_t getFileCount() const { return mFiles.size(); }
|
||||
EE::Window::Window* getWindow() const;
|
||||
Config& getConfig() { return mConfig; }
|
||||
|
||||
private:
|
||||
bool init();
|
||||
void loadConfig();
|
||||
void saveConfig();
|
||||
void updateConfig();
|
||||
void getImages();
|
||||
void registerConsoleCommands();
|
||||
void registerKeyBindings();
|
||||
void loadImagePath( const std::string& path, bool loadGallery = true );
|
||||
void loadImageUrl( const std::string& url );
|
||||
void syncLoadedImage();
|
||||
void updateSlideShow();
|
||||
void toggleHelp();
|
||||
void fitImage();
|
||||
Sprite* getImageSprite() const;
|
||||
|
||||
std::string mInitialPath;
|
||||
Config mConfig;
|
||||
IniFile mIni;
|
||||
std::string mStorePath;
|
||||
std::string mTmpPath;
|
||||
std::string mFilePath;
|
||||
std::string mFile;
|
||||
std::vector<std::string> mFiles;
|
||||
Int32 mCurImg{ 0 };
|
||||
bool mSlideShow{ false };
|
||||
Uint32 mSlideTime{ 4000 };
|
||||
Uint32 mSlideTicks{ 0 };
|
||||
std::shared_ptr<ThreadPool> mThreadPool;
|
||||
std::unique_ptr<UIApplication> mUIApplication;
|
||||
UIWidget* mMainLayout{ nullptr };
|
||||
UIImageViewer* mImageViewer{ nullptr };
|
||||
UITextView* mHelp{ nullptr };
|
||||
UIConsole* mConsole{ nullptr };
|
||||
bool mCursorVisible{ true };
|
||||
Texture::Filter mTextureFilter{ Texture::Filter::Linear };
|
||||
std::unique_ptr<ConsoleCommands> mConsoleCommands;
|
||||
};
|
||||
Reference in New Issue
Block a user