From 1c5d31db6004bc4e17dad2b42e57c51ae64f739c Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sat, 14 Nov 2020 12:07:44 +0100 Subject: [PATCH] improved dirty chain detection --- src/gui/Dialog.cxx | 52 +++++++++++++++++++------------------- src/gui/Dialog.hxx | 6 +++-- src/gui/EditableWidget.cxx | 2 +- src/gui/GuiObject.hxx | 7 +++-- src/gui/Widget.cxx | 29 ++++++++++++--------- src/gui/Widget.hxx | 4 ++- 6 files changed, 56 insertions(+), 44 deletions(-) diff --git a/src/gui/Dialog.cxx b/src/gui/Dialog.cxx index a2b9c14e3..84c4c9dac 100644 --- a/src/gui/Dialog.cxx +++ b/src/gui/Dialog.cxx @@ -147,20 +147,15 @@ void Dialog::setPosition() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Dialog::isChainDirty() const +void Dialog::setDirty() { - bool dirty = false; + _dirty = true; +} - // Recursively check if dialog or any chick dialogs or widgets are dirty - Widget* w = _firstWidget; - - while(w && !dirty) - { - dirty |= w->needsRedraw(); - w = w->_next; - } - - return dirty; +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Dialog::setDirtyChain() +{ + _dirtyChain = true; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -440,6 +435,7 @@ void Dialog::drawDialog() if(isDirty()) { //cerr << "*** draw dialog " << typeid(*this).name() << " ***" << endl; + cerr << "d"; if(clearsBackground()) { @@ -458,7 +454,7 @@ void Dialog::drawDialog() } else { s.invalidate(); - cerr << "invalidate " << typeid(*this).name() << endl; + //cerr << "invalidate " << typeid(*this).name() << endl; } if(hasBorder()) // currently only used by Dialog itself s.frameRect(_x, _y, _w, _h, kColor); @@ -471,19 +467,6 @@ void Dialog::drawDialog() // Draw all children drawChain(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Dialog::drawChain() -{ - Widget* w = _firstWidget; - - while(w) - { - if(w->needsRedraw()) - w->draw(); - w = w->_next; - } // Draw outlines for focused widgets // Don't change focus, since this will trigger lost and received @@ -497,6 +480,23 @@ void Dialog::drawChain() } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Dialog::drawChain() +{ + // Clear chain *before* drawing, because some widgets may set it again when + // being drawn (e.g. RomListWidget) + clearDirtyChain(); + + Widget* w = _firstWidget; + + while(w) + { + if(w->needsRedraw()) + w->draw(); + w = w->_next; + } +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Dialog::handleText(char text) { diff --git a/src/gui/Dialog.hxx b/src/gui/Dialog.hxx index 3966e5db9..0d0c57bc3 100644 --- a/src/gui/Dialog.hxx +++ b/src/gui/Dialog.hxx @@ -62,12 +62,14 @@ class Dialog : public GuiObject virtual void saveConfig() { } virtual void setDefaults() { } - void tick() override; - bool isChainDirty() const override; + void setDirty() override; + void setDirtyChain() override; void redraw(bool force = false); void drawChain() override; void render(); + void tick() override; + void addFocusWidget(Widget* w) override; void addToFocusList(WidgetArray& list) override; void addToFocusList(WidgetArray& list, TabWidget* w, int tabId); diff --git a/src/gui/EditableWidget.cxx b/src/gui/EditableWidget.cxx index 8e19cb0a2..3e86ea947 100644 --- a/src/gui/EditableWidget.cxx +++ b/src/gui/EditableWidget.cxx @@ -73,7 +73,7 @@ void EditableWidget::tick() { _caretTimer = 0; _caretEnabled = !_caretEnabled; - _dirty = true; + setDirty(); } } Widget::tick(); diff --git a/src/gui/GuiObject.hxx b/src/gui/GuiObject.hxx index 893686e5f..c276698f8 100644 --- a/src/gui/GuiObject.hxx +++ b/src/gui/GuiObject.hxx @@ -92,10 +92,12 @@ class GuiObject : public CommandReceiver virtual bool isVisible() const = 0; - void setDirty() { _dirty = true; } + virtual void setDirty() = 0; + virtual void setDirtyChain() = 0; void clearDirty() { _dirty = false; } + void clearDirtyChain() { _dirtyChain = false; } bool isDirty() const { return _dirty; } - virtual bool isChainDirty() const = 0; + bool isChainDirty() const { return _dirtyChain; } // The GUI indicates if its underlying surface needs to be redrawn // and then re-rendered @@ -152,6 +154,7 @@ class GuiObject : public CommandReceiver protected: int _x{0}, _y{0}, _w{0}, _h{0}; bool _dirty{false}; + bool _dirtyChain{false}; uInt32 _flags{0}; Widget* _firstWidget{nullptr}; diff --git a/src/gui/Widget.cxx b/src/gui/Widget.cxx index e04da70d9..f33d27146 100644 --- a/src/gui/Widget.cxx +++ b/src/gui/Widget.cxx @@ -52,20 +52,21 @@ Widget::~Widget() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Widget::isChainDirty() const +void Widget::setDirty() { - bool dirty = false; + _dirty = true; - // Recursively check if widget or any child dialogs or widgets are dirty - Widget* w = _firstWidget; + // Inform the parent object that its children chain is dirty + _boss->setDirtyChain(); +} - while(w && !dirty) - { - dirty |= w->needsRedraw(); - w = w->_next; - } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Widget::setDirtyChain() +{ + _dirtyChain = true; - return dirty; + // Inform the parent object that its children chain is dirty + _boss->setDirtyChain(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -98,7 +99,8 @@ void Widget::draw() if(isDirty()) { - cerr << " *** draw widget " << typeid(*this).name() << " ***" << endl; + //cerr << " *** draw widget " << typeid(*this).name() << " ***" << endl; + cerr << "w"; FBSurface& s = _boss->dialog().surface(); @@ -163,6 +165,10 @@ void Widget::draw() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Widget::drawChain() { + // Clear chain *before* drawing, because some widgets may set it again when + // being drawn (e.g. RomListWidget) + clearDirtyChain(); + Widget* w = _firstWidget; while(w) @@ -508,7 +514,6 @@ void ButtonWidget::setBitmap(const uInt32* bitmap, int bmw, int bmh) _bmh = bmh; _bmw = bmw; - cerr << "setBitmap" << endl; setDirty(); } diff --git a/src/gui/Widget.hxx b/src/gui/Widget.hxx index 38f8fecfa..5ee8ef0b1 100644 --- a/src/gui/Widget.hxx +++ b/src/gui/Widget.hxx @@ -70,7 +70,9 @@ class Widget : public GuiObject virtual bool handleEvent(Event::Type event) { return false; } void tick() override; - bool isChainDirty() const override; + + void setDirty() override; + void setDirtyChain() override; void draw() override; void drawChain() override; void receivedFocus();