Open folder if valid on press enter in path input (SpartanJ/ecode#872).

Improved resources path solving.
Minor changes in tests.
This commit is contained in:
Martín Lucas Golini
2026-04-08 20:05:52 -03:00
parent b2a4239c14
commit 8bbb61d8f5
18 changed files with 59 additions and 34 deletions

View File

@@ -1,8 +1,4 @@
body {
margin-top: 8px;
margin-right: 8px;
margin-bottom: 8px;
margin-left: 8px;
font-size: 11px;
color: black;
background-color: white;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -3,12 +3,14 @@
#include <eepp/core/core.hpp>
#include <eepp/graphics/drawable.hpp>
#include <eepp/network/uri.hpp>
namespace EE { namespace Graphics {
class EE_API DrawableSearcher {
public:
static Drawable* searchByName( const std::string& name, bool firstSearchSprite = false );
static Drawable* searchByName( const std::string& name, bool firstSearchSprite = false,
Network::URI referer = "" );
static Drawable* searchById( const Uint32& id );

View File

@@ -115,6 +115,9 @@ class EE_API Http : NonCopyable {
** @return Status code of the response */
Status getStatus() const;
/** @return True if the response status is successful (2XX status) */
bool isOK() const;
/** @brief Get the response status description */
const char* getStatusDescription() const;

View File

@@ -33,6 +33,7 @@ class EE_API StyleSheetLength {
Dprd,
Dpru,
Dpr,
Ch,
};
static Unit unitFromString( std::string unitStr );

View File

@@ -715,6 +715,9 @@ class EE_API UISceneNode : public SceneNode {
*/
URI solveRelativePath( URI uri, URI baseURI = {} );
/** @return The document referer */
URI getReferer() const { return mReferer; };
protected:
friend class EE::UI::UIWindow;
friend class EE::UI::UIWidget;
@@ -743,6 +746,7 @@ class EE_API UISceneNode : public SceneNode {
Uint32 mCurOnSizeChangeListener{ 0 };
std::shared_ptr<ThreadPool> mThreadPool;
URI mURI;
URI mReferer;
std::function<bool( URI uri )> mURLInterceptorCb;
/**
@@ -957,8 +961,7 @@ class EE_API UISceneNode : public SceneNode {
/** @return The document / scene URI used to resolve paths from a complete URI (with
* path+query+fragment+etc) */
URI getURIFromURL( const URI& url );
URI getURIFromURL( const URI& url ) const;
};
}} // namespace EE::UI

View File

@@ -107,7 +107,8 @@ static Drawable* parseDataURI( const std::string& name ) {
return drawable;
}
Drawable* DrawableSearcher::searchByName( const std::string& name, bool firstSearchSprite ) {
Drawable* DrawableSearcher::searchByName( const std::string& name, bool firstSearchSprite,
Network::URI referer ) {
Drawable* drawable = NULL;
if ( name.size() ) {
@@ -147,12 +148,12 @@ Drawable* DrawableSearcher::searchByName( const std::string& name, bool firstSea
} else if ( String::startsWith( name, "file://" ) ) {
std::string filePath( name.substr( 7 ) );
#if EE_PLATFORM == EE_PLATFORM_WIN
#if EE_PLATFORM == EE_PLATFORM_WIN
if ( filePath.size() >= 3 && filePath[0] == '/' && String::isLetter( filePath[1] ) &&
filePath[2] == ':' ) {
filePath = filePath.substr( 1 );
}
#endif
#endif
drawable = TextureFactory::instance()->getByName( filePath );
@@ -171,17 +172,25 @@ Drawable* DrawableSearcher::searchByName( const std::string& name, bool firstSea
1, 1, 4, Color::Transparent, false, Texture::ClampMode::ClampToEdge, false,
false, name );
std::map<std::string, std::string> headers;
if ( !referer.empty() )
headers["referer"] = referer.toString();
Http::getAsync(
[texture]( const Http&, Http::Request&, Http::Response& response ) {
if ( !response.getBody().empty() ) {
[texture, name]( const Http&, Http::Request&, Http::Response& response ) {
if ( response.isOK() && !response.getBody().empty() ) {
Image image( (const Uint8*)&response.getBody()[0],
response.getBody().size() );
if ( image.getPixels() != NULL )
texture->replace( &image );
} else {
Log::debug( "DrawableSearcher::searchByName: could not download image: "
"%s. Error: %d\n%s",
name, response.getStatus(), response.getBody() );
}
},
URI( name ), Seconds( 5 ) );
URI( name ), Seconds( 5 ), {}, headers );
}
drawable = texture;

View File

@@ -469,6 +469,10 @@ Http::Response::Status Http::Response::getStatus() const {
return mStatus;
}
bool Http::Response::isOK() const {
return mStatus >= 200 && mStatus < 300;
}
const char* Http::Response::getStatusDescription() const {
switch ( mStatus ) {
// 2xx: success

View File

@@ -36,7 +36,8 @@ Drawable* DrawableImageParser::createDrawable( const std::string& value, const S
if ( !functionType.isEmpty() ) {
if ( exists( functionType.getName() ) )
return mFuncs[functionType.getName()]( functionType, size, ownIt, node );
} else if ( NULL != ( res = DrawableSearcher::searchByName( value ) ) ) {
} else if ( NULL != ( res = DrawableSearcher::searchByName(
value, false, node->getUISceneNode()->getReferer() ) ) ) {
if ( res->getDrawableType() == Drawable::SPRITE )
ownIt = true;
return res;
@@ -334,7 +335,8 @@ void DrawableImageParser::registerBaseParsers() {
return DrawableSearcher::searchByName(
node->getUISceneNode()
->solveRelativePath( functionType.getParameters().at( 0 ) )
.toString() );
.toString(),
false, node->getUISceneNode()->getReferer() );
};
mFuncs["icon"] = []( const FunctionString& functionType, const Sizef& size, bool&,

View File

@@ -94,14 +94,7 @@ MediaQuery::ptr MediaQuery::parse( const std::string& str ) {
StyleSheetLength length =
StyleSheetLength::fromString( exprTokens[1] );
expr.valStr = String::toLower( exprTokens[1] );
if ( length.getUnit() == StyleSheetLength::Unit::Dpcm ||
length.getUnit() == StyleSheetLength::Unit::Dpi ) {
expr.val = (int)( length.getValue() * 2.54 );
} else {
expr.val = (int)length.asPixels( 0, Sizef::Zero, dpi );
}
expr.val = (int)length.asPixels( 0, Sizef::Zero, dpi );
expr.fval = length.getValue();
}
}

View File

@@ -30,6 +30,7 @@ enum UnitHashes : String::HashType {
Dprd = String::hash( "dprd" ),
Dpru = String::hash( "dpru" ),
Dpr = String::hash( "dpr" ),
Ch = String::hash( "ch" ),
};
enum PercentagePositions : String::HashType {
@@ -116,6 +117,8 @@ StyleSheetLength::Unit StyleSheetLength::unitFromString( std::string unitStr ) {
return Unit::Dpru;
case UnitHashes::Dpr:
return Unit::Dpr;
case UnitHashes::Ch:
return Unit::Ch;
}
return Unit::Dp;
}
@@ -162,6 +165,8 @@ std::string StyleSheetLength::unitToString( const StyleSheetLength::Unit& unit )
return "dpru";
case Unit::Dpr:
return "dpr";
case Unit::Ch:
return "ch";
}
return "px";
}
@@ -234,6 +239,7 @@ Float StyleSheetLength::asPixels( const Float& parentSize, const Sizef& viewSize
ret = Math::roundUp( PixelDensity::dpToPx( mValue ) );
break;
case Unit::Em:
case Unit::Ch: // Using Em for Ch is incorrect but not that incorrect, close enough
ret = Math::round( mValue * elFontSize );
break;
case Unit::Pt:
@@ -266,6 +272,10 @@ Float StyleSheetLength::asPixels( const Float& parentSize, const Sizef& viewSize
case Unit::Rem:
ret = globalFontSize * mValue;
break;
case Unit::Dpi:
case Unit::Dpcm:
ret = (int)( mValue * 2.54 );
break;
case Unit::Px:
default:
ret = mValue;

View File

@@ -667,8 +667,12 @@ void UIFileDialog::open() {
}
void UIFileDialog::onPressEnter( const Event* ) {
if ( FileSystem::isDirectory( mPath->getText() ) ||
( FDLG_DRIVE_PATH == mPath->getText().toUtf8() && !Sys::getLogicalDrives().empty() ) ) {
if ( allowFolderSelect() && FileSystem::isDirectory( mPath->getText() ) ) {
setCurPath( mPath->getText() );
open();
} else if ( FileSystem::isDirectory( mPath->getText() ) ||
( FDLG_DRIVE_PATH == mPath->getText().toUtf8() &&
!Sys::getLogicalDrives().empty() ) ) {
setCurPath( mPath->getText() );
} else if ( !allowFolderSelect() && FileSystem::fileExists( mPath->getText() ) ) {
String folderPath( FileSystem::fileRemoveFileName( mPath->getText() ) );

View File

@@ -363,12 +363,7 @@ bool UIImage::applyProperty( const StyleSheetProperty& attribute ) {
bool ownIt;
if ( uri.getScheme().empty() && !getUISceneNode()->getURI().empty() ) {
uri = getUISceneNode()->getURI();
std::string newPath = uri.getPath();
if ( !path.empty() && path[0] != '/' )
FileSystem::dirAddSlashAtEnd( newPath );
newPath += path;
uri.setPath( newPath );
uri = getUISceneNode()->solveRelativePath( uri );
path = uri.toString();
}
@@ -379,7 +374,8 @@ bool UIImage::applyProperty( const StyleSheetProperty& attribute ) {
setDrawable( createdDrawable, ownIt );
} else {
Drawable* res = NULL;
if ( NULL != ( res = DrawableSearcher::searchByName( path ) ) )
if ( NULL != ( res = DrawableSearcher::searchByName(
path, false, getUISceneNode()->getReferer() ) ) )
setDrawable( res, res->getDrawableType() == Drawable::SPRITE );
}
break;

View File

@@ -1368,7 +1368,7 @@ void UISceneNode::setURI( const URI& uri ) {
mURI = uri;
}
URI UISceneNode::getURIFromURL( const URI& url ) {
URI UISceneNode::getURIFromURL( const URI& url ) const {
URI baseURI( url );
std::string path = baseURI.getPath();
@@ -1396,6 +1396,7 @@ URI UISceneNode::getURIFromURL( const URI& url ) {
void UISceneNode::setURIFromURL( const URI& url ) {
setURI( getURIFromURL( url ) );
mReferer = url;
}
void UISceneNode::openURL( URI uri ) {

View File

@@ -170,6 +170,7 @@ void UIWidgetCreator::createBaseWidgetList() {
registeredWidget["article"] = [] { return UIRichText::NewWithTag( "article" ); };
registeredWidget["footer"] = [] { return UIRichText::NewWithTag( "footer" ); };
registeredWidget["main"] = [] { return UIRichText::NewWithTag( "main" ); };
registeredWidget["section"] = [] { return UIRichText::NewWithTag( "section" ); };
registeredWidget["nav"] = [] { return UIRichText::NewWithTag( "nav" ); };
registeredWidget["center"] = [] { return UIRichText::NewWithTag( "center" ); };
registeredWidget["html"] = [] { return UIRichText::NewWithTag( "html" ); };

View File

@@ -49,7 +49,7 @@ UTEST( UIHTMLTable, complexLayout ) {
32, {}, 1, false, true ),
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );