diff --git a/.ecode/project_build.json b/.ecode/project_build.json index 60f6498ea..9eb5a84c0 100644 --- a/.ecode/project_build.json +++ b/.ecode/project_build.json @@ -345,6 +345,18 @@ "command": "${project_root}/bin/eepp-treeviewmodel-debug", "name": "eepp-treeviewmodel-debug", "working_dir": "${project_root}/bin" + }, + { + "args": "", + "command": "${project_root}/bin/eepp-ui-hello-world", + "name": "eepp-ui-hello-world-debug", + "working_dir": "${project_root}/bin" + }, + { + "args": "", + "command": "${project_root}/bin/eepp-ui-application-hello-world", + "name": "eepp-ui-application-hello-world-debug", + "working_dir": "${project_root}/bin" } ], "var": { diff --git a/docs/articles/uiintroduction.md b/docs/articles/uiintroduction.md index 1057a53ee..6a2e1469f 100644 --- a/docs/articles/uiintroduction.md +++ b/docs/articles/uiintroduction.md @@ -263,3 +263,5 @@ uiSceneNode->setStyleSheet( parser.getStyleSheet() ); For a complete example of this introduction you can look into: [src/examples/ui_hello_world/ui_hello_world.cpp](https://github.com/SpartanJ/eepp/blob/develop/src/examples/ui_hello_world/ui_hello_world.cpp). + +Also is important to notice that for applications that wants to use the default eepp UI theme and fonts you can simply take advantage of the EE::UI::UIApplication class which controls the initialization and loading of the core components of the UI. You can look at the simplest example at [src/examples/ui_application_hello_world/ui_application_hello_world.cpp](https://github.com/SpartanJ/eepp/blob/develop/src/examples/ui_application_hello_world/ui_application_hello_world.cpp). diff --git a/include/eepp/ui/abstract/uiabstractview.hpp b/include/eepp/ui/abstract/uiabstractview.hpp index 0f9189b07..6267d6f4a 100644 --- a/include/eepp/ui/abstract/uiabstractview.hpp +++ b/include/eepp/ui/abstract/uiabstractview.hpp @@ -53,6 +53,8 @@ class EE_API UIAbstractView : public UIScrollableWidget { enum SelectionKind { Single, Multiple }; + enum class FindRowWithTextMatchKind { Equals, StartsWith, Contains }; + bool isCellSelection() const; bool isRowSelection() const; @@ -85,8 +87,9 @@ class EE_API UIAbstractView : public UIScrollableWidget { void setOnSelection( const std::function& onSelection ); - virtual ModelIndex findRowWithText( const std::string& text, const bool& caseSensitive = false, - const bool& exactMatch = false ) const; + virtual ModelIndex findRowWithText( + const std::string& text, const bool& caseSensitive = false, + FindRowWithTextMatchKind matchKind = FindRowWithTextMatchKind::StartsWith ) const; bool isEditable() const; diff --git a/include/eepp/ui/uitableview.hpp b/include/eepp/ui/uitableview.hpp index 48c81f89b..02c47f1b9 100644 --- a/include/eepp/ui/uitableview.hpp +++ b/include/eepp/ui/uitableview.hpp @@ -21,8 +21,9 @@ class EE_API UITableView : public UIAbstractTableView { Float getMaxColumnContentWidth( const size_t& colIndex, bool bestGuess = false ); - virtual ModelIndex findRowWithText( const std::string& text, const bool& caseSensitive = false, - const bool& exactMatch = false ) const; + virtual ModelIndex findRowWithText( + const std::string& text, const bool& caseSensitive = false, + FindRowWithTextMatchKind matchKind = FindRowWithTextMatchKind::StartsWith ) const; protected: Sizef mContentSize; diff --git a/include/eepp/ui/uitreeview.hpp b/include/eepp/ui/uitreeview.hpp index 88eaa0be3..2e0f57352 100644 --- a/include/eepp/ui/uitreeview.hpp +++ b/include/eepp/ui/uitreeview.hpp @@ -86,8 +86,9 @@ class EE_API UITreeView : public UIAbstractTableView { void setExpanderIconSize( const size_t& expanderSize ); - virtual ModelIndex findRowWithText( const std::string& text, const bool& caseSensitive = false, - const bool& exactMatch = false ) const; + virtual ModelIndex findRowWithText( + const std::string& text, const bool& caseSensitive = false, + FindRowWithTextMatchKind matchKind = FindRowWithTextMatchKind::StartsWith ) const; ModelIndex openRowWithPath( std::string path, bool selectOpenedRow = true ); diff --git a/premake4.lua b/premake4.lua index a667289de..1fca5de6c 100644 --- a/premake4.lua +++ b/premake4.lua @@ -1559,6 +1559,12 @@ solution "eepp" files { "src/examples/ui_hello_world/*.cpp" } build_link_configuration( "eepp-ui-hello-world", true ) + project "eepp-ui-application-hello-world" + set_kind() + language "C++" + files { "src/examples/ui_application_hello_world/*.cpp" } + build_link_configuration( "eepp-ui-application-hello-world", true ) + project "eepp-richtext" set_kind() language "C++" diff --git a/premake5.lua b/premake5.lua index c7aca6939..bc68dc381 100644 --- a/premake5.lua +++ b/premake5.lua @@ -1435,6 +1435,12 @@ workspace "eepp" files { "src/examples/ui_hello_world/*.cpp" } build_link_configuration( "eepp-ui-hello-world", true ) + project "eepp-ui-application-hello-world" + set_kind() + language "C++" + files { "src/examples/ui_application_hello_world/*.cpp" } + build_link_configuration( "eepp-ui-application-hello-world", true ) + project "eepp-richtext" set_kind() language "C++" diff --git a/src/eepp/ui/abstract/uiabstractview.cpp b/src/eepp/ui/abstract/uiabstractview.cpp index 3cfe3cb0b..d103ce953 100644 --- a/src/eepp/ui/abstract/uiabstractview.cpp +++ b/src/eepp/ui/abstract/uiabstractview.cpp @@ -163,7 +163,8 @@ void UIAbstractView::notifySelectionChange() { mOnSelectionChange(); } -ModelIndex UIAbstractView::findRowWithText( const std::string&, const bool&, const bool& ) const { +ModelIndex UIAbstractView::findRowWithText( const std::string&, const bool&, + FindRowWithTextMatchKind ) const { return {}; } diff --git a/src/eepp/ui/uifiledialog.cpp b/src/eepp/ui/uifiledialog.cpp index cd9ac0f31..5ae111b17 100644 --- a/src/eepp/ui/uifiledialog.cpp +++ b/src/eepp/ui/uifiledialog.cpp @@ -138,8 +138,8 @@ UIFileDialog::UIFileDialog( Uint32 dialogFlags, const std::string& defaultFilePa FileSystem::makeDir( newFolderPath ) ) { refreshFolder(); - ModelIndex index = - mMultiView->getCurrentView()->findRowWithText( folderName, true, true ); + ModelIndex index = mMultiView->getCurrentView()->findRowWithText( + folderName, true, UIAbstractView::FindRowWithTextMatchKind::Equals ); if ( index.isValid() ) mMultiView->setSelection( index ); } @@ -565,7 +565,8 @@ void UIFileDialog::goFolderUp() { } else { setCurPath( newPath ); } - ModelIndex index = mMultiView->getCurrentView()->findRowWithText( prevFolderName, true, true ); + ModelIndex index = mMultiView->getCurrentView()->findRowWithText( + prevFolderName, true, UIAbstractView::FindRowWithTextMatchKind::Equals ); if ( index.isValid() ) mMultiView->setSelection( index ); } @@ -675,7 +676,8 @@ void UIFileDialog::onPressEnter( const Event* ) { if ( FileSystem::isDirectory( folderPath ) ) { setCurPath( folderPath ); setFileName( fileName ); - auto index = mMultiView->getCurrentView()->findRowWithText( fileName, true, true ); + auto index = mMultiView->getCurrentView()->findRowWithText( + fileName, true, UIAbstractView::FindRowWithTextMatchKind::Equals ); if ( index.isValid() ) mMultiView->setSelection( index ); } @@ -945,8 +947,8 @@ bool UIFileDialog::show() { if ( mFilePatterns != "*" ) ptrns.push_back( mFilePatterns ); - mHandler->saveFile = std::make_unique( - getTitle().toUtf8(), savePath, ptrns ); + mHandler->saveFile = + std::make_unique( getTitle().toUtf8(), savePath, ptrns ); } else { pfd::opt opt = pfd::opt::none; if ( mDialogFlags & UIFileDialog::AllowMultiFileSelection ) diff --git a/src/eepp/ui/uitableview.cpp b/src/eepp/ui/uitableview.cpp index 3bbad6747..b5ea6218d 100644 --- a/src/eepp/ui/uitableview.cpp +++ b/src/eepp/ui/uitableview.cpp @@ -381,7 +381,7 @@ Uint32 UITableView::onKeyDown( const KeyEvent& event ) { } ModelIndex UITableView::findRowWithText( const std::string& text, const bool& caseSensitive, - const bool& exactMatch ) const { + FindRowWithTextMatchKind matchKind ) const { const Model* model = getModel(); ConditionalLock l( getModel() != nullptr, getModel() ? &const_cast( getModel() )->resourceMutex() : nullptr ); @@ -393,12 +393,26 @@ ModelIndex UITableView::findRowWithText( const std::string& text, const bool& ca i, model->keyColumn() != -1 ? model->keyColumn() : ( model->treeColumn() >= 0 ? model->treeColumn() : 0 ) ); Variant var = model->data( index ); - if ( var.isValid() && - ( exactMatch ? var.toString() == text - : String::startsWith( caseSensitive ? var.toString() - : String::toLower( var.toString() ), - caseSensitive ? text : String::toLower( text ) ) ) ) - return model->index( index.row(), 0 ); + if ( var.isValid() ) { + bool matches = false; + switch ( matchKind ) { + case Abstract::UIAbstractView::FindRowWithTextMatchKind::Equals: + matches = var.toString() == text; + break; + case Abstract::UIAbstractView::FindRowWithTextMatchKind::StartsWith: + matches = String::startsWith( caseSensitive ? var.toString() + : String::toLower( var.toString() ), + caseSensitive ? text : String::toLower( text ) ); + break; + case Abstract::UIAbstractView::FindRowWithTextMatchKind::Contains: + matches = caseSensitive ? String::contains( var.toString(), text ) + : String::icontains( var.toString(), text ); + break; + } + + if ( matches ) + return model->index( index.row(), 0 ); + } } return {}; } diff --git a/src/eepp/ui/uitreeview.cpp b/src/eepp/ui/uitreeview.cpp index e787335a2..a7bebdb48 100644 --- a/src/eepp/ui/uitreeview.cpp +++ b/src/eepp/ui/uitreeview.cpp @@ -762,7 +762,7 @@ void UITreeView::onSortColumn( const size_t& ) { } ModelIndex UITreeView::findRowWithText( const std::string& text, const bool& caseSensitive, - const bool& exactMatch ) const { + FindRowWithTextMatchKind matchKind ) const { const Model* model = getModel(); ConditionalLock l( getModel() != nullptr, getModel() ? &const_cast( getModel() )->resourceMutex() : nullptr ); @@ -771,13 +771,27 @@ ModelIndex UITreeView::findRowWithText( const std::string& text, const bool& cas ModelIndex foundIndex = {}; traverseTree( [&]( const int&, const ModelIndex& index, const size_t&, const Float& ) { Variant var = model->data( index ); - if ( var.isValid() && - ( exactMatch ? var.toString() == text - : String::startsWith( - caseSensitive ? var.toString() : String::toLower( var.toString() ), - caseSensitive ? text : String::toLower( text ) ) ) ) { - foundIndex = index; - return IterationDecision::Stop; + if ( var.isValid() ) { + bool matches = false; + switch ( matchKind ) { + case Abstract::UIAbstractView::FindRowWithTextMatchKind::Equals: + matches = var.toString() == text; + break; + case Abstract::UIAbstractView::FindRowWithTextMatchKind::StartsWith: + matches = String::startsWith( caseSensitive ? var.toString() + : String::toLower( var.toString() ), + caseSensitive ? text : String::toLower( text ) ); + break; + case Abstract::UIAbstractView::FindRowWithTextMatchKind::Contains: + matches = caseSensitive ? String::contains( var.toString(), text ) + : String::icontains( var.toString(), text ); + break; + } + + if ( matches ) { + foundIndex = index; + return IterationDecision::Stop; + } } return IterationDecision::Continue; } ); diff --git a/src/examples/empty_window/empty_window.cpp b/src/examples/empty_window/empty_window.cpp index d3899737b..b0eee342a 100644 --- a/src/examples/empty_window/empty_window.cpp +++ b/src/examples/empty_window/empty_window.cpp @@ -1,54 +1,51 @@ #include -EE::Window::Window* win = NULL; - -void mainLoop() { - // Clear the screen buffer - win->clear(); - - // Create an instance of the primitive renderer - Primitives p; - - // Change the color - p.setColor( Color( 0, 255, 0, 150 ) ); - - // Update the input - win->getInput()->update(); - - // Check if ESCAPE key is pressed - if ( win->getInput()->isKeyDown( KEY_ESCAPE ) ) { - // Close the window - win->close(); - } - - // Draw a circle - p.drawCircle( win->getCenter(), 200, 60 ); - - // Draw frame - win->display(); -} - // EE_MAIN_FUNC is needed by some platforms to be able to find the real application main EE_MAIN_FUNC int main( int, char*[] ) { // Create a new window with vsync enabled - win = Engine::instance()->createWindow( WindowSettings( 960, 640, "eepp - Empty Window" ), - ContextSettings( true ) ); + auto win = Engine::instance()->createWindow( WindowSettings( 960, 640, "eepp - Empty Window" ), + ContextSettings( true ) ); // Check if created - if ( win->isOpen() ) { - // Set window background color - win->setClearColor( RGB( 50, 50, 50 ) ); + if ( !win->isOpen() ) + return EXIT_FAILURE; - // Set the MainLoop function and run it - // This is the application loop, it will loop until the window is closed. - // This is only a requirement if you want to support Emscripten builds ( WebGL + Canvas ). - // This is the same as, except for Emscripten. - // while ( win->isRunning() ) - // { - // MainLoop(); - // } - win->runMainLoop( &mainLoop ); - } + // Set window background color + win->setClearColor( RGB( 50, 50, 50 ) ); + + // Set the MainLoop function and run it + // This is the application loop, it will loop until the window is closed. + // This is only a requirement if you want to support Emscripten builds ( WebGL + Canvas ). + // This is the same as, except for Emscripten. + // while ( win->isRunning() ) + // { + // MainLoop(); + // } + win->runMainLoop( [win] { + // Clear the screen buffer + win->clear(); + + // Create an instance of the primitive renderer + Primitives p; + + // Change the color + p.setColor( Color( 0, 255, 0, 150 ) ); + + // Update the input + win->getInput()->update(); + + // Check if ESCAPE key is pressed + if ( win->getInput()->isKeyDown( KEY_ESCAPE ) ) { + // Close the window + win->close(); + } + + // Draw a circle + p.drawCircle( win->getCenter(), 200, 60 ); + + // Draw frame + win->display(); + } ); // Destroy the engine instance. Destroys all the windows and engine singletons. Engine::destroySingleton(); diff --git a/src/examples/external_shader/external_shader.cpp b/src/examples/external_shader/external_shader.cpp index 71abc7eaf..e63d9e2c5 100644 --- a/src/examples/external_shader/external_shader.cpp +++ b/src/examples/external_shader/external_shader.cpp @@ -42,7 +42,7 @@ void videoResize( EE::Window::Window* ) { float x = ( 2 * nearPlane ) / ( right - left ); float y = ( 2 * nearPlane ) / ( top - bottom ); - float perspectiveMatrix[16] = {x, 0, a, 0, 0, y, b, 0, 0, 0, c, d, 0, 0, -1, 0}; + float perspectiveMatrix[16] = { x, 0, a, 0, 0, y, b, 0, 0, 0, c, d, 0, 0, -1, 0 }; /// Load the our default projection GLi->matrixMode( GL_PROJECTION ); @@ -155,7 +155,7 @@ void mainLoop() { #if !defined( EE_ARM ) && EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN Float d = eesqrt( distance ); #else - Float d = sqrt_approx[( Int32 )( distance * 1000 )]; + Float d = sqrt_approx[(Int32)( distance * 1000 )]; #endif if ( d < 2.f ) { @@ -201,25 +201,27 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) { win = Engine::instance()->createWindow( WindowSettings( 960, 640, "eepp - External Shaders" ), ContextSettings( true ) ); - if ( win->isOpen() ) { - /// This will work without shaders too - ShadersSupported = GLi->shadersSupported(); + if ( !win->isOpen() ) + return EXIT_FAILURE; - imp = win->getInput(); + /// This will work without shaders too + ShadersSupported = GLi->shadersSupported(); - /// We really don't need shaders for this, but the purpose of the example is to show how to - /// work with external shaders - if ( ShadersSupported ) { - /// Disable the automatic shader conversion from fixed-pipeline to programmable-pipeline - Shader::ensure( false ); + imp = win->getInput(); - std::string fs( "#ifdef GL_ES\n\ + /// We really don't need shaders for this, but the purpose of the example is to show how to + /// work with external shaders + if ( ShadersSupported ) { + /// Disable the automatic shader conversion from fixed-pipeline to programmable-pipeline + Shader::ensure( false ); + + std::string fs( "#ifdef GL_ES\n\ precision highp float;\n\ #endif\n\ varying vec4 dgl_Color;\n\ void main() { gl_FragColor = dgl_Color; }" ); - std::string vs( "#ifdef GL_ES\n\ + std::string vs( "#ifdef GL_ES\n\ precision highp float;\n\ #endif\n\ attribute vec3 dgl_Vertex;\n\ @@ -232,49 +234,46 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) { gl_Position = dgl_ProjectionMatrix * dgl_ModelViewMatrix * vec4(dgl_Vertex, 1.0);\n\ }" ); - /// Since fixed-pipeline OpenGL use gl_FrontColor for glColorPointer, we need to replace - /// the color attribute This is all to show how it works, in a real world scenario, you - /// will choose to work fixed-pipeline or programmable-pipeline. - if ( GLi->version() == GLv_2 ) { - String::replaceAll( fs, "gl_FragColor = dgl_Color", - "gl_FragColor = gl_FrontColor" ); - } - - /// Create the new shader program - shaderProgram = ShaderProgram::New( vs.c_str(), vs.size(), fs.c_str(), fs.size() ); + /// Since fixed-pipeline OpenGL use gl_FrontColor for glColorPointer, we need to replace + /// the color attribute This is all to show how it works, in a real world scenario, you + /// will choose to work fixed-pipeline or programmable-pipeline. + if ( GLi->version() == GLv_2 ) { + String::replaceAll( fs, "gl_FragColor = dgl_Color", "gl_FragColor = gl_FrontColor" ); } - /// Set the projection - videoResize( win ); + /// Create the new shader program + shaderProgram = ShaderProgram::New( vs.c_str(), vs.size(), fs.c_str(), fs.size() ); + } - /// Push a window resize callback the reset the projection when needed - win->pushResizeCallback( videoResize ); + /// Set the projection + videoResize( win ); - Uint32 i; + /// Push a window resize callback the reset the projection when needed + win->pushResizeCallback( videoResize ); - for ( i = 0; i < ParticlesNum; i++ ) { - vertices[i] = Vector3ff( 0, 0, 1.83f ); - velocities[i] = - Vector3ff( ( Math::randf() * 2 - 1 ) * .05f, ( Math::randf() * 2 - 1 ) * .05f, - .93f + Math::randf() * .02f ); - colors[i] = ColorAf( Math::randf() * 0.5f, 0.1f, 0.8f, 0.5f ); - } + Uint32 i; + + for ( i = 0; i < ParticlesNum; i++ ) { + vertices[i] = Vector3ff( 0, 0, 1.83f ); + velocities[i] = Vector3ff( ( Math::randf() * 2 - 1 ) * .05f, + ( Math::randf() * 2 - 1 ) * .05f, .93f + Math::randf() * .02f ); + colors[i] = ColorAf( Math::randf() * 0.5f, 0.1f, 0.8f, 0.5f ); + } /** Optimized for ARM ( pre-cache sqrt ) */ #if defined( EE_ARM ) || EE_PLATFORM == EE_PLATFORM_EMSCRIPTEN - Float tFloat = 0; - for ( int i = 0; i <= 20000; i++ ) { - sqrt_approx[i] = eesqrt( tFloat ); - tFloat += 0.001; - } + Float tFloat = 0; + for ( int i = 0; i <= 20000; i++ ) { + sqrt_approx[i] = eesqrt( tFloat ); + tFloat += 0.001; + } #endif - win->runMainLoop( &mainLoop ); + win->runMainLoop( &mainLoop ); - eeSAFE_DELETE_ARRAY( vertices ); - eeSAFE_DELETE_ARRAY( velocities ); - eeSAFE_DELETE_ARRAY( colors ); - } + eeSAFE_DELETE_ARRAY( vertices ); + eeSAFE_DELETE_ARRAY( velocities ); + eeSAFE_DELETE_ARRAY( colors ); Engine::destroySingleton(); diff --git a/src/examples/fonts/fonts.cpp b/src/examples/fonts/fonts.cpp index 8def746a8..4858da0ab 100644 --- a/src/examples/fonts/fonts.cpp +++ b/src/examples/fonts/fonts.cpp @@ -1,138 +1,137 @@ #include EE_MAIN_FUNC int main( int, char*[] ) { - EE::Window::Window* win = NULL; - // Create a new window - win = Engine::instance()->createWindow( WindowSettings( 1024, 768, "eepp - Fonts" ), - ContextSettings( true ) ); + auto win = Engine::instance()->createWindow( WindowSettings( 1024, 768, "eepp - Fonts" ), + ContextSettings( true ) ); + + // Check if created + if ( !win->isOpen() ) + return EXIT_FAILURE; // Set window background color win->setClearColor( RGB( 230, 230, 230 ) ); - // Check if created - if ( win->isOpen() ) { - // Change the current working directory to the binary path to ensure the assets location - // is always correct even if we load the application from other directory than the binary - // path. - FileSystem::changeWorkingDirectory( Sys::getProcessPath() ); + // Change the current working directory to the binary path to ensure the assets location + // is always correct even if we load the application from other directory than the binary + // path. + FileSystem::changeWorkingDirectory( Sys::getProcessPath() ); - // Create a new text string - String Txt( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod " - "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, " - "quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo " - "consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse " - "cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non " - "proident, sunt in culpa qui officia deserunt mollit anim id est laborum." ); + // Create a new text string + String Txt( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod " + "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, " + "quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo " + "consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse " + "cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non " + "proident, sunt in culpa qui officia deserunt mollit anim id est laborum." ); - FontTrueType* fontTest = FontTrueType::New( "DejaVuSansMono" ); - fontTest->loadFromFile( "assets/fonts/DejaVuSansMono.ttf" ); + FontTrueType* fontTest = FontTrueType::New( "DejaVuSansMono" ); + fontTest->loadFromFile( "assets/fonts/DejaVuSansMono.ttf" ); - FontTrueType* fontTest2 = FontTrueType::New( "NotoSans-Regular" ); - fontTest2->loadFromFile( "assets/fonts/NotoSans-Regular.ttf" ); + FontTrueType* fontTest2 = FontTrueType::New( "NotoSans-Regular" ); + fontTest2->loadFromFile( "assets/fonts/NotoSans-Regular.ttf" ); - FontTrueType* fontEmoji = FontTrueType::New( "NotoEmoji-Regular" ); - fontEmoji->loadFromFile( "assets/fonts/NotoEmoji-Regular.ttf" ); + FontTrueType* fontEmoji = FontTrueType::New( "NotoEmoji-Regular" ); + fontEmoji->loadFromFile( "assets/fonts/NotoEmoji-Regular.ttf" ); - FontTrueType* fontEmojiColor = FontTrueType::New( "NotoColorEmoji" ); - fontEmojiColor->loadFromFile( "assets/fonts/NotoColorEmoji.ttf" ); + FontTrueType* fontEmojiColor = FontTrueType::New( "NotoColorEmoji" ); + fontEmojiColor->loadFromFile( "assets/fonts/NotoColorEmoji.ttf" ); - FontBMFont* fontBMFont = FontBMFont::New( "bmfont" ); - fontBMFont->loadFromFile( "assets/fonts/bmfont.fnt" ); + FontBMFont* fontBMFont = FontBMFont::New( "bmfont" ); + fontBMFont->loadFromFile( "assets/fonts/bmfont.fnt" ); - FontSprite* fontSprite = FontSprite::New( - "alagard" ); // Alagard - Hewett Tsoi ( https://www.dafont.com/alagard.font ) - fontSprite->loadFromFile( "assets/fonts/custom_alagard.png", Color::Fuchsia, 32, -4 ); + FontSprite* fontSprite = FontSprite::New( + "alagard" ); // Alagard - Hewett Tsoi ( https://www.dafont.com/alagard.font ) + fontSprite->loadFromFile( "assets/fonts/custom_alagard.png", Color::Fuchsia, 32, -4 ); - Text text; - text.setFont( fontTest ); - text.setFontSize( 24 ); - text.setAlign( TEXT_ALIGN_CENTER ); - text.setString( Txt ); - text.hardWrapText( win->getWidth() - 96 ); + Text text; + text.setFont( fontTest ); + text.setFontSize( 24 ); + text.setAlign( TEXT_ALIGN_CENTER ); + text.setString( Txt ); + text.hardWrapText( win->getWidth() - 96 ); - // Set the font color to a substring of the text - // Create a gradient - int size = (int)text.getString().size(); + // Set the font color to a substring of the text + // Create a gradient + int size = (int)text.getString().size(); - for ( int i = 0; i < size; i++ ) { - text.setFillColor( Color( 255 * i / size, 0, 0, 255 ), i, i + 1 ); + for ( int i = 0; i < size; i++ ) { + text.setFillColor( Color( 255 * i / size, 0, 0, 255 ), i, i + 1 ); + } + + Text text2; + text2.setFont( fontTest2 ); + text2.setString( "Lorem ipsum dolor sit amet, consectetur adipisicing elit. 👽" ); + text2.setFontSize( 32 ); + text2.setFillColor( Color::Black ); + + Text text3; + text3.setFont( fontTest ); + text3.setString( text2.getString() ); + text3.setFontSize( 24 ); + text3.setFillColor( Color( 255, 255, 255, 255 ) ); + text3.setOutlineThickness( 2 ); + text3.setOutlineColor( Color( 0, 0, 0, 255 ) ); + + Text text4; + text4.setFont( fontBMFont ); + text4.setString( text2.getString() ); + text4.setFontSize( 45 ); + text4.setFillColor( Color::Black ); + + Text text5; + text5.setFont( fontSprite ); + text5.setString( text2.getString() ); + text5.setFontSize( 38 ); + + Text text6; + text6.setFont( fontEmojiColor ); + text6.setFontSize( 64 ); + text6.setString( "👽 😀 💩 😃 👻" ); + + Text text7; + text7.setFont( fontEmoji ); + text7.setFontSize( 32 ); + text7.setString( "👽 😀 💩 😃 👻" ); + text7.setFillColor( Color::Gray ); + text7.setOutlineThickness( 2 ); + text7.setOutlineColor( Color( 0, 0, 0, 255 ) ); + + // Application loop + win->runMainLoop( [&] { + // Clear the screen buffer + win->clear(); + + // Update the input + win->getInput()->update(); + + // Check if ESCAPE key is pressed + if ( win->getInput()->isKeyDown( KEY_ESCAPE ) ) { + // Close the window + win->close(); } - Text text2; - text2.setFont( fontTest2 ); - text2.setString( "Lorem ipsum dolor sit amet, consectetur adipisicing elit. 👽" ); - text2.setFontSize( 32 ); - text2.setFillColor( Color::Black ); + text.draw( ( win->getWidth() - text.getTextWidth() ) * 0.5f, 32 ); - Text text3; - text3.setFont( fontTest ); - text3.setString( text2.getString() ); - text3.setFontSize( 24 ); - text3.setFillColor( Color( 255, 255, 255, 255 ) ); - text3.setOutlineThickness( 2 ); - text3.setOutlineColor( Color( 0, 0, 0, 255 ) ); + text2.draw( ( win->getWidth() - text2.getTextWidth() ) * 0.5f, 300 ); - Text text4; - text4.setFont( fontBMFont ); - text4.setString( text2.getString() ); - text4.setFontSize( 45 ); - text4.setFillColor( Color::Black ); + text7.draw( ( win->getWidth() - text7.getTextWidth() ) * 0.5f, 400 ); - Text text5; - text5.setFont( fontSprite ); - text5.setString( text2.getString() ); - text5.setFontSize( 38 ); + // Text rotated and scaled + text2.draw( ( win->getWidth() - text2.getTextWidth() ) * 0.5f, 430, Vector2f( 1.1f, 1.1f ), + 12.5f ); - Text text6; - text6.setFont( fontEmojiColor ); - text6.setFontSize( 64 ); - text6.setString( "👽 😀 💩 😃 👻" ); + text3.draw( ( win->getWidth() - text3.getTextWidth() ) * 0.5f, 560 ); - Text text7; - text7.setFont( fontEmoji ); - text7.setFontSize( 32 ); - text7.setString( "👽 😀 💩 😃 👻" ); - text7.setFillColor( Color::Gray ); - text7.setOutlineThickness( 2 ); - text7.setOutlineColor( Color( 0, 0, 0, 255 ) ); + text4.draw( ( win->getWidth() - text4.getTextWidth() ) * 0.5f, 590 ); - // Application loop - win->runMainLoop( [&] { - // Clear the screen buffer - win->clear(); + text5.draw( ( win->getWidth() - text5.getTextWidth() ) * 0.5f, 640 ); - // Update the input - win->getInput()->update(); + text6.draw( ( win->getWidth() - text6.getTextWidth() ) * 0.5f, 690 ); - // Check if ESCAPE key is pressed - if ( win->getInput()->isKeyDown( KEY_ESCAPE ) ) { - // Close the window - win->close(); - } - - text.draw( ( win->getWidth() - text.getTextWidth() ) * 0.5f, 32 ); - - text2.draw( ( win->getWidth() - text2.getTextWidth() ) * 0.5f, 300 ); - - text7.draw( ( win->getWidth() - text7.getTextWidth() ) * 0.5f, 400 ); - - // Text rotated and scaled - text2.draw( ( win->getWidth() - text2.getTextWidth() ) * 0.5f, 430, - Vector2f( 1.1f, 1.1f ), 12.5f ); - - text3.draw( ( win->getWidth() - text3.getTextWidth() ) * 0.5f, 560 ); - - text4.draw( ( win->getWidth() - text4.getTextWidth() ) * 0.5f, 590 ); - - text5.draw( ( win->getWidth() - text5.getTextWidth() ) * 0.5f, 640 ); - - text6.draw( ( win->getWidth() - text6.getTextWidth() ) * 0.5f, 690 ); - - // Draw frame - win->display(); - } ); - } + // Draw frame + win->display(); + } ); // Destroy the engine instance. Destroys all the windows and engine singletons. // Fonts are autoreleased by the engine diff --git a/src/examples/richtext/richtext.cpp b/src/examples/richtext/richtext.cpp index cec36d1d0..ce3d00266 100644 --- a/src/examples/richtext/richtext.cpp +++ b/src/examples/richtext/richtext.cpp @@ -1,18 +1,10 @@ #include -#include -#include -#include -#include -using namespace EE; -using namespace EE::Graphics; -using namespace EE::Window; - -void runRichTextTest() { +EE_MAIN_FUNC int main( int argc, char* argv[] ) { auto win = Engine::instance()->createWindow( WindowSettings( 1024, 768, "RichText Example" ) ); if ( !win->isOpen() ) - return; + return EXIT_FAILURE; FileSystem::changeWorkingDirectory( Sys::getProcessPath() ); @@ -20,7 +12,7 @@ void runRichTextTest() { FontTrueType::New( "NotoSans-Regular", "assets/fonts/NotoSans-Regular.ttf" ); if ( !font || !font->loaded() ) - return; + return EXIT_FAILURE; FontFamily::loadFromRegular( font ); @@ -77,7 +69,7 @@ void runRichTextTest() { } } ); - while ( win->isRunning() ) { + win->runMainLoop( [&] { win->getInput()->update(); if ( win->getInput()->isKeyUp( KEY_ESCAPE ) ) { @@ -104,12 +96,10 @@ void runRichTextTest() { richText3.draw(); win->display(); - } + } ); Engine::destroySingleton(); -} + MemoryManager::showResults(); -EE_MAIN_FUNC int main( int argc, char* argv[] ) { - runRichTextTest(); - return 0; + return EXIT_SUCCESS; } diff --git a/src/examples/ui_application_hello_world/ui_application_hello_world.cpp b/src/examples/ui_application_hello_world/ui_application_hello_world.cpp new file mode 100644 index 000000000..0fb3b5fc1 --- /dev/null +++ b/src/examples/ui_application_hello_world/ui_application_hello_world.cpp @@ -0,0 +1,20 @@ +#include + +EE_MAIN_FUNC int main( int, char** ) { + UIApplication app( { 640, 480, "eepp - UIApplication Hello World" } ); + app.getUI()->loadLayoutFromString( R"xml( + + + + + )xml" ); + return app.run(); +} diff --git a/src/examples/ui_hello_world/ui_hello_world.cpp b/src/examples/ui_hello_world/ui_hello_world.cpp index 0528b6d90..37d40b4cd 100644 --- a/src/examples/ui_hello_world/ui_hello_world.cpp +++ b/src/examples/ui_hello_world/ui_hello_world.cpp @@ -2,59 +2,34 @@ EE::Window::Window* win = NULL; -void mainLoop() { - win->getInput()->update(); - - if ( win->getInput()->isKeyUp( KEY_ESCAPE ) ) { - win->close(); - } - - // Update the UI scene. - SceneManager::instance()->update(); - - // Check if the UI has been invalidated ( needs redraw ). - if ( SceneManager::instance()->getUISceneNode()->invalidated() ) { - win->clear(); - - // Redraw the UI scene. - SceneManager::instance()->draw(); - - // Display the scene to the screen. - win->display(); - } else { -#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN - // For for an input event or timeout after 16ms if has focus, otherwise wait 100ms. - win->getInput()->waitEvent( Milliseconds( win->hasFocus() ? 16 : 100 ) ); -#endif - } -} - EE_MAIN_FUNC int main( int, char** ) { win = Engine::instance()->createWindow( WindowSettings( 640, 480, "eepp - UI Hello World" ), ContextSettings( true ) ); + // Early exit if window was not opened + if ( !win->isOpen() ) + return EXIT_FAILURE; - if ( win->isOpen() ) { - // Change the current working directory to the binary path to ensure the assets location - // is always correct even if we load the application from other directory than the binary - // path. - FileSystem::changeWorkingDirectory( Sys::getProcessPath() ); + // Change the current working directory to the binary path to ensure the assets location + // is always correct even if we load the application from other directory than the binary + // path. + FileSystem::changeWorkingDirectory( Sys::getProcessPath() ); - // Load a font to use as the default font in our UI. - FontTrueType* font = - FontTrueType::New( "NotoSans-Regular", "assets/fonts/NotoSans-Regular.ttf" ); + // Load a font to use as the default font in our UI. + FontTrueType* font = + FontTrueType::New( "NotoSans-Regular", "assets/fonts/NotoSans-Regular.ttf" ); - // Create a new scene node to add our widgets. - UISceneNode* uiSceneNode = UISceneNode::New(); + // Create a new scene node to add our widgets. + UISceneNode* uiSceneNode = UISceneNode::New(); - // Set the default font used in the scene node (otherwise we won't have any font to create - // text views. - uiSceneNode->getUIThemeManager()->setDefaultFont( font ); + // Set the default font used in the scene node (otherwise we won't have any font to create + // text views. + uiSceneNode->getUIThemeManager()->setDefaultFont( font ); - // Add the new scene node to the scene manager. - SceneManager::instance()->add( uiSceneNode ); + // Add the new scene node to the scene manager. + SceneManager::instance()->add( uiSceneNode ); - // Create a very simple Hello World with a TextView and a PushButton. - static const char* layout = R"xml( + // Create a very simple Hello World with a TextView and a PushButton. + static const char* layout = R"xml( @@ -68,10 +43,10 @@ EE_MAIN_FUNC int main( int, char** ) { text="Hello, I am a PushButton" /> )xml"; - uiSceneNode->loadLayoutFromString( layout ); + uiSceneNode->loadLayoutFromString( layout ); - // Set the style to our "Hello World" widgets. - uiSceneNode->setStyleSheet( R"css( + // Set the style to our "Hello World" widgets. + uiSceneNode->setStyleSheet( R"css( * { font-size: 22dp; } @@ -88,8 +63,34 @@ EE_MAIN_FUNC int main( int, char** ) { } )css" ); - win->runMainLoop( &mainLoop ); - } + win->runMainLoop( [] { + // Update the input state + win->getInput()->update(); + + // Check if escape was pressed + if ( win->getInput()->isKeyUp( KEY_ESCAPE ) ) { + win->close(); + } + + // Update the UI scene. + SceneManager::instance()->update(); + + // Check if the UI has been invalidated ( needs redraw ). + if ( SceneManager::instance()->getUISceneNode()->invalidated() ) { + win->clear(); + + // Redraw the UI scene. + SceneManager::instance()->draw(); + + // Display the scene to the screen. + win->display(); + } else { +#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN + // For for an input event or timeout after 16ms if has focus, otherwise wait 100ms. + win->getInput()->waitEvent( Milliseconds( win->hasFocus() ? 16 : 100 ) ); +#endif + } + } ); Engine::destroySingleton(); MemoryManager::showResults(); diff --git a/src/examples/ui_treeview_model/treeviewmodel.cpp b/src/examples/ui_treeview_model/treeviewmodel.cpp index 6d01bf531..2f1fd91c6 100644 --- a/src/examples/ui_treeview_model/treeviewmodel.cpp +++ b/src/examples/ui_treeview_model/treeviewmodel.cpp @@ -1,9 +1,5 @@ #include -using namespace EE; -using namespace EE::UI; -using namespace EE::UI::Models; - EE_MAIN_FUNC int main( int, char** ) { UIApplication app( { 800, 600, "eepp - StringMapModel Example" } ); diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index a1edfd1c9..52725a397 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -447,7 +447,8 @@ void App::openFontDialog( std::string& fontPath, bool loadingMonoFont, bool term FileSystem::fileRemoveFileName( absoluteFontPath ) ); if ( dialog->getMultiView() ) { ModelIndex index = dialog->getMultiView()->getListView()->findRowWithText( - FileSystem::fileNameFromPath( fontPath ), true, true ); + FileSystem::fileNameFromPath( fontPath ), true, + UIAbstractView::FindRowWithTextMatchKind::Equals ); if ( index.isValid() ) dialog->runOnMainThread( [dialog, index]() { dialog->getMultiView()->setSelection( index ); } ); diff --git a/src/tools/ecode/universallocator.cpp b/src/tools/ecode/universallocator.cpp index 48cb91c60..4f76dfb99 100644 --- a/src/tools/ecode/universallocator.cpp +++ b/src/tools/ecode/universallocator.cpp @@ -778,8 +778,7 @@ UniversalLocator::openBuildModel( const std::string& pattern ) { return ItemListOwnerModel::create( {} ); buildNames.reserve( builds.size() ); for ( const auto& build : builds ) { - if ( pattern.empty() || - String::startsWith( String::toLower( build.first ), String::toLower( pattern ) ) ) + if ( pattern.empty() || String::icontains( build.first, pattern ) ) buildNames.push_back( build.first ); } std::sort( buildNames.begin(), buildNames.end() ); @@ -839,8 +838,7 @@ UniversalLocator::openBuildTypeModel( const std::string& pattern ) { std::vector buildTypeNames; buildTypeNames.reserve( buildTypes.size() ); for ( const auto& build : buildTypes ) { - if ( pattern.empty() || - String::startsWith( String::toLower( build ), String::toLower( pattern ) ) ) + if ( pattern.empty() || String::icontains( build, pattern ) ) buildTypeNames.push_back( build ); } std::sort( buildTypeNames.begin(), buildTypeNames.end() ); @@ -864,8 +862,7 @@ UniversalLocator::openRunTargetModel( const std::string& pattern ) { std::vector runTargetNames; runTargetNames.reserve( runs.size() ); for ( const auto& run : runs ) { - if ( pattern.empty() || - String::startsWith( String::toLower( run->name ), String::toLower( pattern ) ) ) + if ( pattern.empty() || String::icontains( run->name, pattern ) ) runTargetNames.push_back( run->name ); } std::sort( runTargetNames.begin(), runTargetNames.end() );