Browse Source

TreeView: Coalesce item position recalculation to fix performance issues with large trees

v6.1.6
ed 3 years ago
parent
commit
70968d46c8
1 changed files with 73 additions and 42 deletions
  1. +73
    -42
      modules/juce_gui_basics/widgets/juce_TreeView.cpp

+ 73
- 42
modules/juce_gui_basics/widgets/juce_TreeView.cpp View File

@@ -632,36 +632,20 @@ private:
//==============================================================================
class TreeView::TreeViewport : public Viewport,
private Timer
private AsyncUpdater
{
public:
TreeViewport() = default;
void updateComponents (bool triggerResize)
{
if (auto* tvc = getContentComp())
{
if (triggerResize)
tvc->resized();
else
tvc->updateComponents();
}
repaint();
}
explicit TreeViewport (TreeView& treeView) : owner (treeView) {}
void visibleAreaChanged (const Rectangle<int>& newVisibleArea) override
{
const auto hasScrolledSideways = (newVisibleArea.getX() != lastX);
lastX = newVisibleArea.getX();
updateComponents (hasScrolledSideways);
startTimer (50);
}
ContentComponent* getContentComp() const noexcept
{
return static_cast<ContentComponent*> (getViewedComponent());
structureChanged = true;
triggerAsyncUpdate();
}
bool keyPressed (const KeyPress& key) override
@@ -673,22 +657,76 @@ public:
return Viewport::keyPressed (key);
}
ContentComponent* getContentComp() const noexcept
{
return static_cast<ContentComponent*> (getViewedComponent());
}
enum class Async { yes, no };
void recalculatePositions (Async useAsyncUpdate)
{
needsRecalculating = true;
if (useAsyncUpdate == Async::yes)
triggerAsyncUpdate();
else
handleAsyncUpdate();
}
private:
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override
{
return createIgnoredAccessibilityHandler (*this);
}
void timerCallback() override
void handleAsyncUpdate() override
{
stopTimer();
if (auto* tree = getParentComponent())
if (auto* handler = tree->getAccessibilityHandler())
if (structureChanged)
{
if (auto* handler = owner.getAccessibilityHandler())
handler->notifyAccessibilityEvent (AccessibilityEvent::structureChanged);
structureChanged = false;
}
if (needsRecalculating)
{
if (auto* root = owner.rootItem)
{
const auto startY = owner.rootItemVisible ? 0 : -root->itemHeight;
root->updatePositions (startY);
getViewedComponent()->setSize (jmax (getMaximumVisibleWidth(), root->totalWidth + 50),
root->totalHeight + startY);
}
else
{
getViewedComponent()->setSize (0, 0);
}
updateComponents (false);
needsRecalculating = false;
}
}
void updateComponents (bool triggerResize)
{
if (auto* content = getContentComp())
{
if (triggerResize)
content->resized();
else
content->updateComponents();
}
repaint();
}
TreeView& owner;
int lastX = -1;
bool structureChanged = false, needsRecalculating = false;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TreeViewport)
};
@@ -696,7 +734,7 @@ private:
//==============================================================================
TreeView::TreeView (const String& name) : Component (name)
{
viewport = std::make_unique<TreeViewport>();
viewport = std::make_unique<TreeViewport> (*this);
addAndMakeVisible (viewport.get());
viewport->setViewedComponent (new ContentComponent (*this));
@@ -737,7 +775,7 @@ void TreeView::setRootItem (TreeViewItem* const newRootItem)
rootItem->setOpen (true);
}
updateVisibleItems();
viewport->recalculatePositions (TreeViewport::Async::no);
}
}
@@ -1097,20 +1135,7 @@ bool TreeView::keyPressed (const KeyPress& key)
void TreeView::updateVisibleItems()
{
if (rootItem != nullptr)
{
rootItem->updatePositions (rootItemVisible ? 0 : -rootItem->itemHeight);
viewport->getViewedComponent()
->setSize (jmax (viewport->getMaximumVisibleWidth(), rootItem->totalWidth + 50),
rootItem->totalHeight - (rootItemVisible ? 0 : rootItem->itemHeight));
}
else
{
viewport->getViewedComponent()->setSize (0, 0);
}
viewport->updateComponents (false);
viewport->recalculatePositions (TreeViewport::Async::yes);
}
//==============================================================================
@@ -1774,6 +1799,9 @@ void TreeViewItem::setOwnerView (TreeView* const newOwner) noexcept
int TreeViewItem::getIndentX() const noexcept
{
if (ownerView == nullptr)
return 0;
int x = ownerView->rootItemVisible ? 1 : 0;
if (! ownerView->openCloseButtonsVisible)
@@ -2053,6 +2081,9 @@ TreeViewItem::OpennessRestorer::~OpennessRestorer()
void TreeViewItem::draw (Graphics& g, int width, bool isMouseOverButton)
{
if (ownerView == nullptr)
return;
const auto indent = getIndentX();
const auto itemW = (itemWidth < 0 || drawsInRightMargin) ? width - indent : itemWidth;


Loading…
Cancel
Save