initial commit for #719

This commit is contained in:
thrust26 2020-11-10 19:53:36 +01:00
parent eae7808ddf
commit e7b7bfa3cd
10 changed files with 235 additions and 118 deletions

View File

@ -439,7 +439,7 @@ void FrameBuffer::update(bool force)
force = force || myOSystem.launcher().needsRedraw(); force = force || myOSystem.launcher().needsRedraw();
if(force) if(force)
{ {
clear(); //clear();
myOSystem.launcher().draw(force); myOSystem.launcher().draw(force);
} }
break; // EventHandlerState::LAUNCHER break; // EventHandlerState::LAUNCHER

View File

@ -621,5 +621,5 @@ void ContextMenu::drawDialog()
s.drawBitmap(_downImg, ((_w-_x)>>1)-4, (_rowHeight>>1)+y-4, _scrollDnColor, _arrowSize); s.drawBitmap(_downImg, ((_w-_x)>>1)-4, (_rowHeight>>1)+y-4, _scrollDnColor, _arrowSize);
} }
setDirty(); clearDirty();
} }

View File

@ -149,6 +149,35 @@ void Dialog::center()
positionAt(instance().settings().getInt("dialogpos")); positionAt(instance().settings().getInt("dialogpos"));
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Dialog::setDirty()
{
_dirty = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Dialog::isDirty() const
{
return _dirty;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Dialog::isChainDirty() const
{
bool dirty = false;
// Check if widget or any subwidgets are dirty
Widget* w = _firstWidget;
while(!dirty && w)
{
dirty |= w->needsRedraw();
w = w->_next;
}
return dirty;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Dialog::positionAt(uInt32 pos) void Dialog::positionAt(uInt32 pos)
{ {
@ -192,7 +221,9 @@ void Dialog::positionAt(uInt32 pos)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Dialog::render() bool Dialog::render()
{ {
if(!_dirty || !isVisible()) //assert(_dirty);
if(!isVisible() || !needsRedraw())
return false; return false;
// Draw this dialog // Draw this dialog
@ -207,7 +238,7 @@ bool Dialog::render()
surface->render(); surface->render();
}); });
} }
_dirty = false; //_dirty = false;
return true; return true;
} }
@ -371,6 +402,10 @@ void Dialog::drawDialog()
FBSurface& s = surface(); FBSurface& s = surface();
if(isDirty())
{
//cerr << "*** draw dialog " << typeid(*this).name() << " ***" << endl;
// Dialog is still on top if e.g a ContextMenu is opened // Dialog is still on top if e.g a ContextMenu is opened
_onTop = parent().myDialogStack.top() == this _onTop = parent().myDialogStack.top() == this
|| (parent().myDialogStack.get(parent().myDialogStack.size() - 2) == this || (parent().myDialogStack.get(parent().myDialogStack.size() - 2) == this
@ -388,19 +423,27 @@ void Dialog::drawDialog()
_onTop ? kColorTitleText : kColorTitleTextLo); _onTop ? kColorTitleText : kColorTitleTextLo);
} }
} }
else else {
s.invalidate(); s.invalidate();
cerr << "invalidate " << typeid(*this).name() << endl;
}
if(_flags & Widget::FLAG_BORDER) // currently only used by Dialog itself if(_flags & Widget::FLAG_BORDER) // currently only used by Dialog itself
s.frameRect(_x, _y, _w, _h, _onTop ? kColor : kShadowColor); s.frameRect(_x, _y, _w, _h, _onTop ? kColor : kShadowColor);
// Make all child widget dirty // Make all child widgets dirty
Widget::setDirtyInChain(_firstWidget);
clearDirty();
}
Widget* w = _firstWidget; Widget* w = _firstWidget;
Widget::setDirtyInChain(w);
// Draw all children // Draw all children
w = _firstWidget; w = _firstWidget;
while(w) while(w)
{ {
// only redraw changed widgets
if(w->needsRedraw())
w->draw(); w->draw();
w = w->_next; w = w->_next;
} }

View File

@ -64,8 +64,9 @@ class Dialog : public GuiObject
// A dialog being dirty indicates that its underlying surface needs to be // A dialog being dirty indicates that its underlying surface needs to be
// redrawn and then re-rendered; this is taken care of in ::render() // redrawn and then re-rendered; this is taken care of in ::render()
void setDirty() override { _dirty = true; } void setDirty() override;
bool isDirty() const { return _dirty; } bool isDirty() const override;
bool isChainDirty() const override;
bool render(); bool render();
void addFocusWidget(Widget* w) override; void addFocusWidget(Widget* w) override;
@ -235,7 +236,7 @@ class Dialog : public GuiObject
int _tabID{0}; int _tabID{0};
int _flags{0}; int _flags{0};
bool _dirty{false}; //bool _dirty{false};
uInt32 _max_w{0}; // maximum wanted width uInt32 _max_w{0}; // maximum wanted width
uInt32 _max_h{0}; // maximum wanted height uInt32 _max_h{0}; // maximum wanted height

View File

@ -91,21 +91,32 @@ void DialogContainer::updateTime(uInt64 time)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool DialogContainer::draw(bool full) bool DialogContainer::draw(bool full)
{ {
cerr << "draw " << full << endl;
if(myDialogStack.empty()) if(myDialogStack.empty())
return false; return false;
// Make the top dialog dirty if a full redraw is requested // Make the top dialog dirty if a full redraw is requested
if(full) //if(full)
myDialogStack.top()->setDirty(); // myDialogStack.top()->setDirty();
// If the top dialog is dirty, then all below it must be redrawn too // If the top dialog is dirty, then all below it must be redrawn too
const bool dirty = needsRedraw(); const bool dirty = needsRedraw();
//if(dirty)
// myDialogStack.top()->setDirty();
myDialogStack.applyAll([&](Dialog*& d){ //myDialogStack.applyAll([&](Dialog*& d){
if(dirty) // if(dirty)
d->setDirty(); // d->setDirty();
// full |= d->render();
//});
//if(dirty)
{
myDialogStack.applyAll([&](Dialog*& d) {
if(d->needsRedraw())
//d->setDirty();
full |= d->render(); full |= d->render();
}); });
}
return full; return full;
} }
@ -113,7 +124,9 @@ bool DialogContainer::draw(bool full)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool DialogContainer::needsRedraw() const bool DialogContainer::needsRedraw() const
{ {
return !myDialogStack.empty() ? myDialogStack.top()->isDirty() : false; return !myDialogStack.empty()
? myDialogStack.top()->needsRedraw()
: false;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -133,6 +146,9 @@ int DialogContainer::addDialog(Dialog* d)
"Unable to show dialog box; FIX THE CODE"); "Unable to show dialog box; FIX THE CODE");
else else
{ {
// fade out current top dialog
if(!myDialogStack.empty())
myDialogStack.top()->setDirty();
d->setDirty(); d->setDirty();
myDialogStack.push(d); myDialogStack.push(d);
} }
@ -145,8 +161,16 @@ void DialogContainer::removeDialog()
if(!myDialogStack.empty()) if(!myDialogStack.empty())
{ {
myDialogStack.pop(); myDialogStack.pop();
// necessary as long as all dialogs share the same surface
if(!myDialogStack.empty()) if(!myDialogStack.empty())
myDialogStack.top()->setDirty(); {
//myDialogStack.top()->setDirty();
// Mark all dialogs for redraw
myDialogStack.applyAll([&](Dialog*& d){
d->setDirty();
});
}
} }
} }

View File

@ -78,6 +78,10 @@ class GuiObject : public CommandReceiver
virtual bool isVisible() const = 0; virtual bool isVisible() const = 0;
virtual void setDirty() = 0; virtual void setDirty() = 0;
virtual void clearDirty() { _dirty = false; }
virtual bool isDirty() const { return _dirty; }
virtual bool isChainDirty() const = 0;
virtual bool needsRedraw() const { return isDirty() || isChainDirty(); };
/** Add given widget(s) to the focus list */ /** Add given widget(s) to the focus list */
virtual void addFocusWidget(Widget* w) = 0; virtual void addFocusWidget(Widget* w) = 0;
@ -104,6 +108,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};
Widget* _firstWidget{nullptr}; Widget* _firstWidget{nullptr};
WidgetArray _focusList; WidgetArray _focusList;

View File

@ -315,6 +315,7 @@ void ScrollBarWidget::drawWidget(bool hilite)
s.fillRect(_x + 1, _y + _sliderPos - 1, _w - 2, _sliderHeight + 2, s.fillRect(_x + 1, _y + _sliderPos - 1, _w - 2, _sliderHeight + 2,
onTop ? (hilite && _part == Part::Slider) ? kScrollColorHi : kScrollColor : kColor); onTop ? (hilite && _part == Part::Slider) ? kScrollColorHi : kScrollColor : kColor);
} }
clearDirty();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -275,17 +275,18 @@ void TabWidget::drawWidget(bool hilite)
// The tab widget is strange in that it acts as both a widget (obviously) // The tab widget is strange in that it acts as both a widget (obviously)
// and a dialog (it contains other widgets). Because of the latter, // and a dialog (it contains other widgets). Because of the latter,
// it must assume responsibility for refreshing all its children. // it must assume responsibility for refreshing all its children.
Widget::setDirtyInChain(_tabs[_activeTab].firstWidget);
if(isDirty())
{
FBSurface& s = dialog().surface(); FBSurface& s = dialog().surface();
bool onTop = _boss->dialog().isOnTop(); bool onTop = _boss->dialog().isOnTop();
// Iterate over all tabs and draw them // Iterate over all tabs and draw them
int i, x = _x + kTabLeftOffset; int i, x = _x + kTabLeftOffset;
for (i = 0; i < int(_tabs.size()); ++i) for(i = 0; i < int(_tabs.size()); ++i)
{ {
int tabWidth = _tabs[i].tabWidth ? _tabs[i].tabWidth : _tabWidth; int tabWidth = _tabs[i].tabWidth ? _tabs[i].tabWidth : _tabWidth;
ColorId fontcolor = _tabs[i].enabled && onTop? kTextColor : kColor; ColorId fontcolor = _tabs[i].enabled && onTop ? kTextColor : kColor;
int yOffset = (i == _activeTab) ? 0 : 1; int yOffset = (i == _activeTab) ? 0 : 1;
s.fillRect(x, _y + 1, tabWidth, _tabHeight - 1, s.fillRect(x, _y + 1, tabWidth, _tabHeight - 1,
(i == _activeTab) (i == _activeTab)
@ -308,6 +309,11 @@ void TabWidget::drawWidget(bool hilite)
// fill empty right space // fill empty right space
s.hLine(x - kTabSpacing + 1, _y + _tabHeight, _x + _w - 1, onTop ? kWidColor : kDlgColor); s.hLine(x - kTabSpacing + 1, _y + _tabHeight, _x + _w - 1, onTop ? kWidColor : kDlgColor);
s.hLine(_x, _y + _h - 1, _x + _w - 1, onTop ? kBGColorLo : kColor); s.hLine(_x, _y + _h - 1, _x + _w - 1, onTop ? kBGColorLo : kColor);
clearDirty();
// Make all child widgets of currently active tab dirty
Widget::setDirtyInChain(_tabs[_activeTab].firstWidget);
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -56,7 +56,41 @@ void Widget::setDirty()
{ {
// A widget being dirty indicates that its parent dialog is dirty // A widget being dirty indicates that its parent dialog is dirty
// So we inform the parent about it // So we inform the parent about it
_boss->dialog().setDirty(); //_boss->dialog().setDirty();
//cerr << "set dirty " << typeid(*this).name() << endl;
_dirty = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Widget::isDirty() const
{
string name = typeid(*this).name();
if(_dirty && name == "class TabWidget")
cerr << "is dirty " << typeid(*this).name() << endl;
return _dirty;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Widget::isChainDirty() const
{
string name = typeid(*this).name();
if(_dirty && name == "class TabWidget")
cerr << "is chain dirty " << typeid(*this).name() << endl;
bool dirty = false;
// Check if widget or any subwidgets are dirty
Widget* w = _firstWidget;
while(!dirty && w)
{
dirty |= w->isDirty();
w = w->_next;
}
return dirty;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -65,6 +99,10 @@ void Widget::draw()
if(!isVisible() || !_boss->isVisible()) if(!isVisible() || !_boss->isVisible())
return; return;
if(isDirty())
{
//cerr << " *** draw widget " << typeid(*this).name() << " ***" << endl;
FBSurface& s = _boss->dialog().surface(); FBSurface& s = _boss->dialog().surface();
bool onTop = _boss->dialog().isOnTop(); bool onTop = _boss->dialog().isOnTop();
@ -82,7 +120,7 @@ void Widget::draw()
int x = _x, y = _y, w = _w, h = _h; int x = _x, y = _y, w = _w, h = _h;
if(hasBorder) if(hasBorder)
{ {
x++; y++; w-=2; h-=2; x++; y++; w -= 2; h -= 2;
} }
s.fillRect(x, y, w, h, !onTop ? _bgcolorlo : (_flags & Widget::FLAG_HILITED) && isEnabled() ? _bgcolorhi : _bgcolor); s.fillRect(x, y, w, h, !onTop ? _bgcolorlo : (_flags & Widget::FLAG_HILITED) && isEnabled() ? _bgcolorhi : _bgcolor);
} }
@ -101,7 +139,7 @@ void Widget::draw()
drawWidget((_flags & Widget::FLAG_HILITED) ? true : false); drawWidget((_flags & Widget::FLAG_HILITED) ? true : false);
// Restore x/y // Restore x/y
if (hasBorder) if(hasBorder)
{ {
_x -= 4; _x -= 4;
_y -= 4; _y -= 4;
@ -111,14 +149,17 @@ void Widget::draw()
_x = oldX; _x = oldX;
_y = oldY; _y = oldY;
}
// Draw all children // Draw all children
Widget* w = _firstWidget; Widget* w = _firstWidget;
while(w) while(w)
{ {
if(w->needsRedraw())
w->draw(); w->draw();
w = w->_next; w = w->_next;
} }
clearDirty();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -290,6 +331,7 @@ void Widget::setDirtyInChain(Widget* start)
{ {
while(start) while(start)
{ {
//cerr << "setDirtyInChain " << typeid(*start).name() << endl;
start->setDirty(); start->setDirty();
start = start->_next; start = start->_next;
} }
@ -345,8 +387,6 @@ void StaticTextWidget::drawWidget(bool hilite)
bool onTop = _boss->dialog().isOnTop(); bool onTop = _boss->dialog().isOnTop();
s.drawString(_font, _label, _x, _y, _w, s.drawString(_font, _label, _x, _y, _w,
isEnabled() && onTop ? _textcolor : kColor, _align, 0, true, _shadowcolor); isEnabled() && onTop ? _textcolor : kColor, _align, 0, true, _shadowcolor);
setDirty();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -454,6 +494,7 @@ void ButtonWidget::setBitmap(const uInt32* bitmap, int bmw, int bmh)
_bmh = bmh; _bmh = bmh;
_bmw = bmw; _bmw = bmw;
cerr << "setBitmap" << endl;
setDirty(); setDirty();
} }
@ -474,8 +515,6 @@ void ButtonWidget::drawWidget(bool hilite)
!(isEnabled() && onTop) ? _textcolorlo : !(isEnabled() && onTop) ? _textcolorlo :
hilite ? _textcolorhi : _textcolor, hilite ? _textcolorhi : _textcolor,
_bmw, _bmh); _bmw, _bmh);
setDirty();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -635,8 +674,6 @@ void CheckboxWidget::drawWidget(bool hilite)
// Finally draw the label // Finally draw the label
s.drawString(_font, _label, _x + prefixSize(_font), _y + _textY, _w, s.drawString(_font, _label, _x + prefixSize(_font), _y + _textY, _w,
onTop && isEnabled() ? kTextColor : kColor); onTop && isEnabled() ? kTextColor : kColor);
setDirty();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -652,7 +689,7 @@ SliderWidget::SliderWidget(GuiObject* boss, const GUI::Font& font,
_valueLabelWidth(valueLabelWidth), _valueLabelWidth(valueLabelWidth),
_forceLabelSign(forceLabelSign) _forceLabelSign(forceLabelSign)
{ {
_flags = Widget::FLAG_ENABLED | Widget::FLAG_TRACK_MOUSE; _flags = Widget::FLAG_ENABLED | Widget::FLAG_TRACK_MOUSE | Widget::FLAG_CLEARBG;;
_bgcolor = kDlgColor; _bgcolor = kDlgColor;
_bgcolorhi = kDlgColor; _bgcolorhi = kDlgColor;
@ -870,8 +907,6 @@ void SliderWidget::drawWidget(bool hilite)
if(_valueLabelWidth > 0) if(_valueLabelWidth > 0)
s.drawString(_font, _valueLabel + _valueUnit, _x + _w - _valueLabelWidth, _y + 2, s.drawString(_font, _valueLabel + _valueUnit, _x + _w - _valueLabelWidth, _y + 2,
_valueLabelWidth, isEnabled() ? kTextColor : kColor); _valueLabelWidth, isEnabled() ? kTextColor : kColor);
setDirty();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -83,6 +83,8 @@ class Widget : public GuiObject
virtual bool handleEvent(Event::Type event) { return false; } virtual bool handleEvent(Event::Type event) { return false; }
void setDirty() override; void setDirty() override;
bool isDirty() const override;
bool isChainDirty() const override;
void draw() override; void draw() override;
void receivedFocus(); void receivedFocus();
void lostFocus(); void lostFocus();