mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-10-27 08:37:58 +03:00
Add multi-thread protection to: ModelSelection.
Make UIAbstractView::notifySelectionChange thread-safe. Added new UI Test (FontRendering.UITextTest).
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 7.8 KiB |
@@ -0,0 +1,65 @@
|
||||
<style>
|
||||
.main TextView,
|
||||
.main PushButton {
|
||||
margin: 4dp;
|
||||
layout-height: wrap_content;
|
||||
layout-width: 0;
|
||||
layout-weight: 0.5;
|
||||
}
|
||||
.main > .singleline TextView,
|
||||
.main > .singleline PushButton {
|
||||
text: "Example Text";
|
||||
}
|
||||
.main > .multiline TextView,
|
||||
.main > .multiline PushButton {
|
||||
text-selection: true;
|
||||
word-wrap: true;
|
||||
text: "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. 😀";
|
||||
}
|
||||
.main TextView {
|
||||
border: 1dp var(--button-border);
|
||||
}
|
||||
</style>
|
||||
<vbox class="main" lw="mp" lh="mp" padding="4dp">
|
||||
<vbox class="singleline" lw="mp" lh="wc">
|
||||
<hbox lw="mp" lh="wc">
|
||||
<TextView text-align="left" />
|
||||
<TextView text-align="right" />
|
||||
</hbox>
|
||||
<hbox lw="mp" lh="wc">
|
||||
<TextView text-align="center" />
|
||||
<TextView text-align="center" />
|
||||
</hbox>
|
||||
<hbox lw="mp" lh="wc">
|
||||
<TextView text-align="left" />
|
||||
<TextView text-align="right" />
|
||||
</hbox>
|
||||
<hbox lw="mp" lh="wc">
|
||||
<PushButton text-align="left" />
|
||||
<PushButton text-align="right" />
|
||||
</hbox>
|
||||
<hbox lw="mp" lh="wc">
|
||||
<PushButton text-align="center" />
|
||||
<PushButton text-align="center" />
|
||||
</hbox>
|
||||
<hbox lw="mp" lh="wc">
|
||||
<PushButton text-align="left" />
|
||||
<PushButton text-align="right" />
|
||||
</hbox>
|
||||
</vbox>
|
||||
|
||||
<vbox class="multiline" lw="mp" lh="wc">
|
||||
<hbox lw="mp" lh="wc">
|
||||
<TextView text-align="left" />
|
||||
<TextView text-align="right" />
|
||||
</hbox>
|
||||
<hbox lw="mp" lh="wc">
|
||||
<TextView text-align="center" />
|
||||
<TextView text-align="center" />
|
||||
</hbox>
|
||||
<hbox lw="mp" lh="wc">
|
||||
<TextView text-align="left" />
|
||||
<TextView text-align="right" />
|
||||
</hbox>
|
||||
</vbox>
|
||||
</vbox>
|
||||
@@ -2,6 +2,8 @@
|
||||
#define EE_UI_MODEL_MODELSELECTION_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <eepp/system/lock.hpp>
|
||||
#include <eepp/system/mutex.hpp>
|
||||
#include <eepp/ui/models/modelindex.hpp>
|
||||
#include <functional>
|
||||
|
||||
@@ -17,12 +19,20 @@ class EE_API ModelSelection {
|
||||
public:
|
||||
ModelSelection( UIAbstractView* view ) : mView( view ) {}
|
||||
|
||||
int size() const { return mIndexes.size(); }
|
||||
bool isEmpty() const { return mIndexes.empty(); }
|
||||
int size() const {
|
||||
Lock l( mMutex );
|
||||
return mIndexes.size();
|
||||
}
|
||||
bool isEmpty() const {
|
||||
Lock l( mMutex );
|
||||
return mIndexes.empty();
|
||||
}
|
||||
bool contains( const ModelIndex& index ) const {
|
||||
Lock l( mMutex );
|
||||
return std::find( mIndexes.begin(), mIndexes.end(), index ) != mIndexes.end();
|
||||
}
|
||||
bool containsRow( int row ) const {
|
||||
Lock l( mMutex );
|
||||
for ( auto& index : mIndexes ) {
|
||||
if ( index.row() == row )
|
||||
return true;
|
||||
@@ -48,13 +58,16 @@ class EE_API ModelSelection {
|
||||
}
|
||||
|
||||
std::vector<ModelIndex> indexes() const {
|
||||
Lock l( mMutex );
|
||||
std::vector<ModelIndex> indexes;
|
||||
indexes.reserve( mIndexes.size() );
|
||||
for ( auto& index : mIndexes )
|
||||
indexes.push_back( index );
|
||||
return indexes;
|
||||
}
|
||||
|
||||
ModelIndex first() const {
|
||||
Lock l( mMutex );
|
||||
if ( mIndexes.empty() )
|
||||
return {};
|
||||
return *mIndexes.begin();
|
||||
@@ -79,6 +92,8 @@ class EE_API ModelSelection {
|
||||
bool mDisableNotify{ false };
|
||||
bool mNotifyPending{ false };
|
||||
void notifySelectionChanged();
|
||||
|
||||
mutable Mutex mMutex;
|
||||
};
|
||||
|
||||
}}} // namespace EE::UI::Models
|
||||
|
||||
@@ -151,6 +151,12 @@ void UIAbstractView::onModelSelectionChange() {
|
||||
}
|
||||
|
||||
void UIAbstractView::notifySelectionChange() {
|
||||
if ( !Engine::isMainThread() ) {
|
||||
debounce( [this] { notifySelectionChange(); }, Time::Zero,
|
||||
String::hash( "notifySelectionChange" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
onModelSelectionChange();
|
||||
sendCommonEvent( Event::OnSelectionChanged );
|
||||
if ( mOnSelectionChange )
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
namespace EE { namespace UI { namespace Models {
|
||||
|
||||
void ModelSelection::removeAllMatching( std::function<bool( const ModelIndex& )> filter ) {
|
||||
Lock l( mMutex );
|
||||
std::vector<ModelIndex> notMatching;
|
||||
for ( auto& index : mIndexes ) {
|
||||
if ( !filter( index ) )
|
||||
@@ -18,6 +19,7 @@ void ModelSelection::removeAllMatching( std::function<bool( const ModelIndex& )>
|
||||
|
||||
void ModelSelection::set( const ModelIndex& index ) {
|
||||
eeASSERT( index.isValid() );
|
||||
Lock l( mMutex );
|
||||
if ( mIndexes.size() == 1 && contains( index ) )
|
||||
return;
|
||||
mIndexes.clear();
|
||||
@@ -30,6 +32,7 @@ void ModelSelection::set( const std::vector<ModelIndex>& indexes, bool notify )
|
||||
for ( auto& index : indexes )
|
||||
eeASSERT( index.isValid() );
|
||||
#endif
|
||||
Lock l( mMutex );
|
||||
mIndexes.clear();
|
||||
mIndexes = indexes;
|
||||
if ( notify )
|
||||
@@ -38,6 +41,7 @@ void ModelSelection::set( const std::vector<ModelIndex>& indexes, bool notify )
|
||||
|
||||
void ModelSelection::add( const ModelIndex& index ) {
|
||||
eeASSERT( index.isValid() );
|
||||
Lock l( mMutex );
|
||||
auto contains = std::find( mIndexes.begin(), mIndexes.end(), index );
|
||||
if ( contains == mIndexes.end() )
|
||||
return;
|
||||
@@ -47,6 +51,7 @@ void ModelSelection::add( const ModelIndex& index ) {
|
||||
|
||||
void ModelSelection::toggle( const ModelIndex& index ) {
|
||||
eeASSERT( index.isValid() );
|
||||
Lock l( mMutex );
|
||||
auto contains = std::find( mIndexes.begin(), mIndexes.end(), index );
|
||||
if ( contains != mIndexes.end() )
|
||||
mIndexes.erase( contains );
|
||||
@@ -57,6 +62,7 @@ void ModelSelection::toggle( const ModelIndex& index ) {
|
||||
|
||||
bool ModelSelection::remove( const ModelIndex& index ) {
|
||||
eeASSERT( index.isValid() );
|
||||
Lock l( mMutex );
|
||||
auto contains = std::find( mIndexes.begin(), mIndexes.end(), index );
|
||||
if ( contains == mIndexes.end() )
|
||||
return false;
|
||||
@@ -66,6 +72,7 @@ bool ModelSelection::remove( const ModelIndex& index ) {
|
||||
}
|
||||
|
||||
void ModelSelection::clear( bool notify ) {
|
||||
Lock l( mMutex );
|
||||
if ( mIndexes.empty() )
|
||||
return;
|
||||
mIndexes.clear();
|
||||
@@ -74,6 +81,7 @@ void ModelSelection::clear( bool notify ) {
|
||||
}
|
||||
|
||||
void ModelSelection::notifySelectionChanged() {
|
||||
Lock l( mMutex );
|
||||
if ( !mDisableNotify ) {
|
||||
mView->notifySelectionChange();
|
||||
mNotifyPending = false;
|
||||
|
||||
@@ -795,3 +795,33 @@ UTEST( FontRendering, textSetFillColor ) {
|
||||
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
UTEST( FontRendering, UITextTest ) {
|
||||
const auto runTest = [&]() {
|
||||
UIApplication app(
|
||||
WindowSettings( 1024, 650, "eepp - UI Text Test", WindowStyle::Default,
|
||||
WindowBackend::Default, 32, {}, 1, false, true ),
|
||||
UIApplication::Settings( Sys::getProcessPath() + ".." + FileSystem::getOSSlash(), 1 ) );
|
||||
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
|
||||
app.getUI()->loadLayoutFromFile( "assets/layouts/ui_text_test.xml" );
|
||||
SceneManager::instance()->update();
|
||||
SceneManager::instance()->draw();
|
||||
compareImages( utest_state, utest_result, app.getWindow(), "eepp-ui-text-test" );
|
||||
};
|
||||
|
||||
UTEST_PRINT_STEP( "Text Shaper disabled" );
|
||||
{
|
||||
BoolScopedOp op( Text::TextShaperEnabled, false );
|
||||
runTest();
|
||||
}
|
||||
|
||||
UTEST_PRINT_STEP( "Text Shaper enabled" );
|
||||
{
|
||||
BoolScopedOp op( Text::TextShaperEnabled, true );
|
||||
runTest();
|
||||
|
||||
UTEST_PRINT_STEP( "Text Shaper enabled w/o optimizations" );
|
||||
BoolScopedOp op2( Text::TextShaperOptimizations, false );
|
||||
runTest();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user