improved dirty chain detection

This commit is contained in:
thrust26 2020-11-14 12:07:44 +01:00
parent 36a3f9843e
commit 3eb1ce9116
6 changed files with 56 additions and 44 deletions

View File

@ -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; void Dialog::setDirtyChain()
{
while(w && !dirty) _dirtyChain = true;
{
dirty |= w->needsRedraw();
w = w->_next;
}
return dirty;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -440,6 +435,7 @@ void Dialog::drawDialog()
if(isDirty()) if(isDirty())
{ {
//cerr << "*** draw dialog " << typeid(*this).name() << " ***" << endl; //cerr << "*** draw dialog " << typeid(*this).name() << " ***" << endl;
cerr << "d";
if(clearsBackground()) if(clearsBackground())
{ {
@ -458,7 +454,7 @@ void Dialog::drawDialog()
} }
else { else {
s.invalidate(); s.invalidate();
cerr << "invalidate " << typeid(*this).name() << endl; //cerr << "invalidate " << typeid(*this).name() << endl;
} }
if(hasBorder()) // currently only used by Dialog itself if(hasBorder()) // currently only used by Dialog itself
s.frameRect(_x, _y, _w, _h, kColor); s.frameRect(_x, _y, _w, _h, kColor);
@ -471,19 +467,6 @@ void Dialog::drawDialog()
// Draw all children // Draw all children
drawChain(); drawChain();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Dialog::drawChain()
{
Widget* w = _firstWidget;
while(w)
{
if(w->needsRedraw())
w->draw();
w = w->_next;
}
// Draw outlines for focused widgets // Draw outlines for focused widgets
// Don't change focus, since this will trigger lost and received // 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) void Dialog::handleText(char text)
{ {

View File

@ -62,12 +62,14 @@ class Dialog : public GuiObject
virtual void saveConfig() { } virtual void saveConfig() { }
virtual void setDefaults() { } virtual void setDefaults() { }
void tick() override; void setDirty() override;
bool isChainDirty() const override; void setDirtyChain() override;
void redraw(bool force = false); void redraw(bool force = false);
void drawChain() override; void drawChain() override;
void render(); void render();
void tick() override;
void addFocusWidget(Widget* w) override; void addFocusWidget(Widget* w) override;
void addToFocusList(WidgetArray& list) override; void addToFocusList(WidgetArray& list) override;
void addToFocusList(WidgetArray& list, TabWidget* w, int tabId); void addToFocusList(WidgetArray& list, TabWidget* w, int tabId);

View File

@ -73,7 +73,7 @@ void EditableWidget::tick()
{ {
_caretTimer = 0; _caretTimer = 0;
_caretEnabled = !_caretEnabled; _caretEnabled = !_caretEnabled;
_dirty = true; setDirty();
} }
} }
Widget::tick(); Widget::tick();

View File

@ -92,10 +92,12 @@ class GuiObject : public CommandReceiver
virtual bool isVisible() const = 0; virtual bool isVisible() const = 0;
void setDirty() { _dirty = true; } virtual void setDirty() = 0;
virtual void setDirtyChain() = 0;
void clearDirty() { _dirty = false; } void clearDirty() { _dirty = false; }
void clearDirtyChain() { _dirtyChain = false; }
bool isDirty() const { return _dirty; } 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 // The GUI indicates if its underlying surface needs to be redrawn
// and then re-rendered // and then re-rendered
@ -152,6 +154,7 @@ class GuiObject : public CommandReceiver
protected: protected:
int _x{0}, _y{0}, _w{0}, _h{0}; int _x{0}, _y{0}, _w{0}, _h{0};
bool _dirty{false}; bool _dirty{false};
bool _dirtyChain{false};
uInt32 _flags{0}; uInt32 _flags{0};
Widget* _firstWidget{nullptr}; Widget* _firstWidget{nullptr};

View File

@ -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 // Inform the parent object that its children chain is dirty
Widget* w = _firstWidget; _boss->setDirtyChain();
}
while(w && !dirty) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{ void Widget::setDirtyChain()
dirty |= w->needsRedraw(); {
w = w->_next; _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()) if(isDirty())
{ {
cerr << " *** draw widget " << typeid(*this).name() << " ***" << endl; //cerr << " *** draw widget " << typeid(*this).name() << " ***" << endl;
cerr << "w";
FBSurface& s = _boss->dialog().surface(); FBSurface& s = _boss->dialog().surface();
@ -163,6 +165,10 @@ void Widget::draw()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Widget::drawChain() void Widget::drawChain()
{ {
// Clear chain *before* drawing, because some widgets may set it again when
// being drawn (e.g. RomListWidget)
clearDirtyChain();
Widget* w = _firstWidget; Widget* w = _firstWidget;
while(w) while(w)
@ -508,7 +514,6 @@ void ButtonWidget::setBitmap(const uInt32* bitmap, int bmw, int bmh)
_bmh = bmh; _bmh = bmh;
_bmw = bmw; _bmw = bmw;
cerr << "setBitmap" << endl;
setDirty(); setDirty();
} }

View File

@ -70,7 +70,9 @@ class Widget : public GuiObject
virtual bool handleEvent(Event::Type event) { return false; } virtual bool handleEvent(Event::Type event) { return false; }
void tick() override; void tick() override;
bool isChainDirty() const override;
void setDirty() override;
void setDirtyChain() override;
void draw() override; void draw() override;
void drawChain() override; void drawChain() override;
void receivedFocus(); void receivedFocus();