Optimize UIDiffView::NewMultiFileDiffViewer to not trash children creation with invalidations.

This commit is contained in:
Martín Lucas Golini
2026-08-29 19:02:26 -03:00
parent 0fa99ab9d2
commit e39e82fe55
2 changed files with 39 additions and 2 deletions
+19 -2
View File
@@ -4,6 +4,7 @@
#include <eepp/graphics/sprite.hpp>
#include <eepp/graphics/text.hpp>
#include <eepp/graphics/texturefactory.hpp>
#include <eepp/scene/scenemanager.hpp>
#include <eepp/system/filesystem.hpp>
#include <eepp/system/log.hpp>
#include <eepp/ui/doc/syntaxdefinitionmanager.hpp>
@@ -80,13 +81,17 @@ static Sprite* setImageViewerImage( UIImageViewer* viewer, Image* image ) {
UIScrollView* UIDiffView::NewMultiFileDiffViewer( const std::string& patchText,
const std::string& repoPath, ViewMode viewMode ) {
auto diffs = UIDiffView::splitDiff( patchText );
auto* uiSceneNode = SceneManager::instance()->getUISceneNode();
const bool wasLoading = uiSceneNode && uiSceneNode->isLoading();
if ( uiSceneNode )
uiSceneNode->setIsLoading( true );
auto scrollView = UIScrollView::New();
auto vbox = UILinearLayout::NewVertical();
vbox->setParent( scrollView );
vbox->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent );
auto diffs = UIDiffView::splitDiff( patchText );
for ( const auto& diff : diffs ) {
auto* diffView = UIDiffView::New();
diffView->setViewMode( viewMode );
@@ -98,6 +103,18 @@ UIScrollView* UIDiffView::NewMultiFileDiffViewer( const std::string& patchText,
diffView->loadFromPatch( diff, "", "", repoPath );
}
if ( uiSceneNode ) {
uiSceneNode->setIsLoading( wasLoading );
if ( !wasLoading ) {
// A diff view owns several editors, scroll bars, toggles and image viewers. Queueing
// each intermediate widget separately makes style invalidation scan an ever-growing
// dirty set. One recursive invalidation of the completed tree provides the same final
// styling.
uiSceneNode->invalidateStyle( scrollView, true );
uiSceneNode->invalidateStyleState( scrollView, true, true );
}
}
return scrollView;
}
+20
View File
@@ -6,6 +6,7 @@
#include <eepp/ui/tools/uiimageviewer.hpp>
#include <eepp/ui/uiapplication.hpp>
#include <eepp/ui/uicodeeditor.hpp>
#include <eepp/ui/uiscenenode.hpp>
#include <eepp/ui/uiscrollview.hpp>
using namespace EE;
@@ -143,6 +144,25 @@ diff --git a/second.txt b/second.txt
eeDelete( viewer );
}
UTEST( UIDiffView, MultiFileViewerHandlesLargePatches ) {
UIApplication app( WindowSettings{ 800, 600, "eepp - unit tests" } );
app.getUI()->flushDirtyStyleAndLayout();
constexpr size_t fileCount = 128;
std::string patchText;
patchText.reserve( fileCount * 160 );
for ( size_t i = 0; i < fileCount; ++i ) {
const std::string fileName( "file" + std::to_string( i ) + ".txt" );
patchText += "diff --git a/" + fileName + " b/" + fileName + "\n--- a/" + fileName +
"\n+++ b/" + fileName + "\n@@ -1 +1 @@\n-old\n+new\n";
}
auto* viewer = UIDiffView::NewMultiFileDiffViewer( patchText );
EXPECT_EQ( fileCount, viewer->findAllByType<UIDiffView>( UI_TYPE_DIFF_VIEW ).size() );
EXPECT_FALSE( viewer->getUISceneNode()->isLoading() );
eeDelete( viewer );
}
UTEST( UIDiffView, LoadFromFileImageDiffUsesImageViewers ) {
UIApplication app( WindowSettings{ 800, 600, "eepp - unit tests" } );