diff --git a/src/debugger/gui/DebuggerDialog.hxx b/src/debugger/gui/DebuggerDialog.hxx index 0affa5160..51633c825 100644 --- a/src/debugger/gui/DebuggerDialog.hxx +++ b/src/debugger/gui/DebuggerDialog.hxx @@ -76,7 +76,7 @@ class DebuggerDialog : public Dialog void saveConfig() override; private: - void center() override { positionAt(0); } + void setPosition() override { positionAt(0); } void loadConfig() override; void handleKeyDown(StellaKey key, StellaMod mod, bool repeated) override; void handleCommand(CommandSender* sender, int cmd, int data, int id) override; diff --git a/src/debugger/gui/RomListSettings.cxx b/src/debugger/gui/RomListSettings.cxx index 9c3baf3d2..93b555631 100644 --- a/src/debugger/gui/RomListSettings.cxx +++ b/src/debugger/gui/RomListSettings.cxx @@ -100,7 +100,7 @@ void RomListSettings::show(uInt32 x, uInt32 y, const Common::Rect& bossRect, int } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void RomListSettings::center() +void RomListSettings::setPosition() { // First set position according to original coordinates surface().setDstPos(_xorig, _yorig); diff --git a/src/debugger/gui/RomListSettings.hxx b/src/debugger/gui/RomListSettings.hxx index 0845dd8ab..a589b0334 100644 --- a/src/debugger/gui/RomListSettings.hxx +++ b/src/debugger/gui/RomListSettings.hxx @@ -38,8 +38,8 @@ class RomListSettings : public Dialog, public CommandSender ('data' will be the currently selected line number in RomListWidget) */ void show(uInt32 x, uInt32 y, const Common::Rect& bossRect, int data = -1); - /** This dialog uses its own positioning, so we override Dialog::center() */ - void center() override; + /** This dialog uses its own positioning, so we override Dialog::setPosition() */ + void setPosition() override; private: uInt32 _xorig{0}, _yorig{0}; diff --git a/src/emucore/FrameBuffer.cxx b/src/emucore/FrameBuffer.cxx index 3af48cd15..a151084d1 100644 --- a/src/emucore/FrameBuffer.cxx +++ b/src/emucore/FrameBuffer.cxx @@ -351,6 +351,7 @@ void FrameBuffer::update(bool force) #ifdef GUI_SUPPORT case EventHandlerState::OPTIONSMENU: { + myOSystem.menu().tick(); redraw |= myOSystem.menu().needsRedraw(); if(redraw) { @@ -363,6 +364,7 @@ void FrameBuffer::update(bool force) case EventHandlerState::CMDMENU: { + myOSystem.commandMenu().tick(); redraw |= myOSystem.commandMenu().needsRedraw(); if(redraw) { @@ -375,6 +377,7 @@ void FrameBuffer::update(bool force) case EventHandlerState::MESSAGEMENU: { + myOSystem.messageMenu().tick(); redraw |= myOSystem.messageMenu().needsRedraw(); if(redraw) { @@ -387,6 +390,7 @@ void FrameBuffer::update(bool force) case EventHandlerState::TIMEMACHINE: { + myOSystem.timeMachine().tick(); redraw |= myOSystem.timeMachine().needsRedraw(); if(redraw) { @@ -433,6 +437,7 @@ void FrameBuffer::update(bool force) case EventHandlerState::LAUNCHER: { + myOSystem.launcher().tick(); redraw |= myOSystem.launcher().needsRedraw(); if(redraw) myOSystem.launcher().draw(force); @@ -445,6 +450,7 @@ void FrameBuffer::update(bool force) #ifdef DEBUGGER_SUPPORT case EventHandlerState::DEBUGGER: { + myOSystem.debugger().tick(); redraw |= myOSystem.debugger().needsRedraw(); if(redraw) myOSystem.debugger().draw(force); diff --git a/src/gui/ContextMenu.cxx b/src/gui/ContextMenu.cxx index a53f1c4ae..ae1ee09be 100644 --- a/src/gui/ContextMenu.cxx +++ b/src/gui/ContextMenu.cxx @@ -77,7 +77,7 @@ void ContextMenu::show(uInt32 x, uInt32 y, const Common::Rect& bossRect, int ite } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ContextMenu::center() +void ContextMenu::setPosition() { // First set position according to original coordinates surface().setDstPos(_xorig, _yorig); diff --git a/src/gui/ContextMenu.hxx b/src/gui/ContextMenu.hxx index 423ef3074..f1736e517 100644 --- a/src/gui/ContextMenu.hxx +++ b/src/gui/ContextMenu.hxx @@ -71,8 +71,8 @@ class ContextMenu : public Dialog, public CommandSender const string& getSelectedName() const; const Variant& getSelectedTag() const; - /** This dialog uses its own positioning, so we override Dialog::center() */ - void center() override; + /** This dialog uses its own positioning, so we override Dialog::setPosition() */ + void setPosition() override; /** The following methods are used when we want to select *and* send a command for the new selection. They are only to be used diff --git a/src/gui/Dialog.cxx b/src/gui/Dialog.cxx index fe0d06d37..e58920e89 100644 --- a/src/gui/Dialog.cxx +++ b/src/gui/Dialog.cxx @@ -91,7 +91,7 @@ void Dialog::open() const uInt32 scale = instance().frameBuffer().hidpiScaleFactor(); _surface->setDstSize(_w * scale, _h * scale); - center(); + setPosition(); if(_myTabList.size()) // (Re)-build the focus list to use for all widgets of all tabs @@ -143,32 +143,20 @@ void Dialog::setTitle(const string& title) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Dialog::center() +void Dialog::setPosition() { positionAt(instance().settings().getInt("dialogpos")); } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Dialog::setDirty() -{ - _dirty = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Dialog::isDirty() -{ - return _dirty; -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool Dialog::isChainDirty() const { bool dirty = false; - // Check if widget or any subwidgets are dirty + // Recursively check if dialog or any chick dialogs or widgets are dirty Widget* w = _firstWidget; - while(!dirty && w) + while(w && !dirty) { dirty |= w->needsRedraw(); w = w->_next; @@ -177,6 +165,19 @@ bool Dialog::isChainDirty() const return dirty; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Dialog::tick() +{ + // Recursively tick dialog and all child dialogs and widgets + Widget* w = _firstWidget; + + while(w) + { + w->tick(); + w = w->_next; + } +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Dialog::positionAt(uInt32 pos) { @@ -224,7 +225,7 @@ void Dialog::redraw() return;// false; // Draw this dialog - center(); + setPosition(); drawDialog(); render(); } diff --git a/src/gui/Dialog.hxx b/src/gui/Dialog.hxx index d5405ef70..c594d93cd 100644 --- a/src/gui/Dialog.hxx +++ b/src/gui/Dialog.hxx @@ -56,16 +56,13 @@ class Dialog : public GuiObject bool isVisible() const override { return _visible; } bool isOnTop() const { return _onTop; } - virtual void center(); + virtual void setPosition(); virtual void drawDialog(); virtual void loadConfig() { } virtual void saveConfig() { } virtual void setDefaults() { } - // A dialog being dirty indicates that its underlying surface needs to be - // redrawn and then re-rendered; this is taken care of in ::render() - void setDirty() override; - bool isDirty() override; // TODO: remove + void tick() override; bool isChainDirty() const override; void redraw(); void render(); diff --git a/src/gui/DialogContainer.cxx b/src/gui/DialogContainer.cxx index 98deae834..1210e5d7c 100644 --- a/src/gui/DialogContainer.cxx +++ b/src/gui/DialogContainer.cxx @@ -107,6 +107,13 @@ void DialogContainer::draw(bool full) }); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void DialogContainer::tick() +{ + if(!myDialogStack.empty()) + myDialogStack.top()->tick(); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void DialogContainer::render() { diff --git a/src/gui/DialogContainer.hxx b/src/gui/DialogContainer.hxx index 70950606d..134d82e55 100644 --- a/src/gui/DialogContainer.hxx +++ b/src/gui/DialogContainer.hxx @@ -119,6 +119,11 @@ class DialogContainer */ void handleJoyHatEvent(int stick, int hat, JoyHatDir hdir, int button); + /** + Tick the dialog and all its widgets. + */ + void tick(); + /** Draw the stack of menus (full indicates to redraw all items). */ diff --git a/src/gui/EditableWidget.cxx b/src/gui/EditableWidget.cxx index 4032daae3..4c3928052 100644 --- a/src/gui/EditableWidget.cxx +++ b/src/gui/EditableWidget.cxx @@ -62,8 +62,9 @@ void EditableWidget::setText(const string& str, bool) setDirty(); } + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool EditableWidget::isDirty() +void EditableWidget::tick() { if(_hasFocus && _editable && isVisible() && _boss->isVisible()) { @@ -75,8 +76,7 @@ bool EditableWidget::isDirty() _dirty = true; } } - - return _dirty; + Widget::tick(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/gui/EditableWidget.hxx b/src/gui/EditableWidget.hxx index e4dfbc2f7..345a4c618 100644 --- a/src/gui/EditableWidget.hxx +++ b/src/gui/EditableWidget.hxx @@ -67,7 +67,7 @@ class EditableWidget : public Widget, public CommandSender protected: void receivedFocusWidget() override; void lostFocusWidget() override; - bool isDirty() override; + void tick() override; virtual void startEditMode() { setFlags(Widget::FLAG_WANTS_RAWDATA); } virtual void endEditMode() { clearFlags(Widget::FLAG_WANTS_RAWDATA); } diff --git a/src/gui/GuiObject.hxx b/src/gui/GuiObject.hxx index 811f1569b..581d498aa 100644 --- a/src/gui/GuiObject.hxx +++ b/src/gui/GuiObject.hxx @@ -91,11 +91,15 @@ class GuiObject : public CommandReceiver virtual void setHeight(int h) { _h = h; } virtual bool isVisible() const = 0; - virtual void setDirty() = 0; + virtual void setDirty() { _dirty = true; } virtual void clearDirty() { _dirty = false; } - virtual bool isDirty() { return _dirty; } + + virtual void tick() = 0; + virtual bool isDirty() const { return _dirty; } virtual bool isChainDirty() const = 0; - virtual bool needsRedraw() { return isDirty() || isChainDirty(); }; + // The GUI indicates if its underlying surface needs to be redrawn + // and then re-rendered + virtual bool needsRedraw() { return isDirty() || isChainDirty(); } void setFlags(uInt32 flags) { diff --git a/src/gui/InputTextDialog.cxx b/src/gui/InputTextDialog.cxx index 12e7a66d4..54b656a67 100644 --- a/src/gui/InputTextDialog.cxx +++ b/src/gui/InputTextDialog.cxx @@ -130,7 +130,7 @@ void InputTextDialog::show(uInt32 x, uInt32 y, const Common::Rect& bossRect) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void InputTextDialog::center() +void InputTextDialog::setPosition() { if(!myEnableCenter) { @@ -144,7 +144,7 @@ void InputTextDialog::center() surface().setDstPos(myXOrig, myYOrig); } else - Dialog::center(); + Dialog::setPosition(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/gui/InputTextDialog.hxx b/src/gui/InputTextDialog.hxx index e89e00651..a06ca4446 100644 --- a/src/gui/InputTextDialog.hxx +++ b/src/gui/InputTextDialog.hxx @@ -58,7 +58,7 @@ class InputTextDialog : public Dialog, public CommandSender void handleCommand(CommandSender* sender, int cmd, int data, int id) override; /** This dialog uses its own positioning, so we override Dialog::center() */ - void center() override; + void setPosition() override; private: vector myInput; diff --git a/src/gui/LauncherDialog.hxx b/src/gui/LauncherDialog.hxx index 0dd9b898d..cc265928b 100644 --- a/src/gui/LauncherDialog.hxx +++ b/src/gui/LauncherDialog.hxx @@ -101,7 +101,7 @@ class LauncherDialog : public Dialog static constexpr int MIN_ROMINFO_ROWS = 7; // full lines static constexpr int MIN_ROMINFO_LINES = 4; // extra lines - void center() override { positionAt(0); } + void setPosition() override { positionAt(0); } void handleKeyDown(StellaKey key, StellaMod mod, bool repeated) override; void handleMouseDown(int x, int y, MouseButton b, int clickCount) override; void handleCommand(CommandSender* sender, int cmd, int data, int id) override; diff --git a/src/gui/TimeMachineDialog.cxx b/src/gui/TimeMachineDialog.cxx index 1e983eb92..8e550d2a9 100644 --- a/src/gui/TimeMachineDialog.cxx +++ b/src/gui/TimeMachineDialog.cxx @@ -297,7 +297,7 @@ TimeMachineDialog::TimeMachineDialog(OSystem& osystem, DialogContainer& parent, } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void TimeMachineDialog::center() +void TimeMachineDialog::setPosition() { // Place on the bottom of the screen, centered horizontally const Common::Size& screen = instance().frameBuffer().screenSize(); diff --git a/src/gui/TimeMachineDialog.hxx b/src/gui/TimeMachineDialog.hxx index a4a489b79..1d15d6b15 100644 --- a/src/gui/TimeMachineDialog.hxx +++ b/src/gui/TimeMachineDialog.hxx @@ -44,8 +44,8 @@ class TimeMachineDialog : public Dialog /** initialize timeline bar */ void initBar(); - /** This dialog uses its own positioning, so we override Dialog::center() */ - void center() override; + /** This dialog uses its own positioning, so we override Dialog::setPosition() */ + void setPosition() override; /** convert cycles into time */ string getTimeString(uInt64 cycles); diff --git a/src/gui/Widget.cxx b/src/gui/Widget.cxx index 69c94b3ed..951a60282 100644 --- a/src/gui/Widget.cxx +++ b/src/gui/Widget.cxx @@ -51,48 +51,36 @@ Widget::~Widget() _focusList.clear(); } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Widget::setDirty() -{ - // A widget being dirty indicates that its parent dialog is dirty - // So we inform the parent about it - //_boss->dialog().setDirty(); - //cerr << "set dirty " << typeid(*this).name() << endl; - - _dirty = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Widget::isDirty() -{ - //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 + // Recursively check if widget or any child dialogs or widgets are dirty Widget* w = _firstWidget; - while(!dirty && w) + while(w && !dirty) { - dirty |= w->isDirty(); + dirty |= w->needsRedraw(); w = w->_next; } return dirty; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Widget::tick() +{ + // Recursively tick widget and all child dialogs and widgets + Widget* w = _firstWidget; + + while(w) + { + w->tick(); + w = w->_next; + } +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Widget::draw() { diff --git a/src/gui/Widget.hxx b/src/gui/Widget.hxx index 3e70523c0..6a505e8df 100644 --- a/src/gui/Widget.hxx +++ b/src/gui/Widget.hxx @@ -69,8 +69,7 @@ class Widget : public GuiObject virtual bool handleJoyHat(int stick, int hat, JoyHatDir hdir, int button = JOY_CTRL_NONE) { return false; } virtual bool handleEvent(Event::Type event) { return false; } - void setDirty() override; - bool isDirty() override; // TODO: remove + void tick() override; bool isChainDirty() const override; void draw() override; void receivedFocus();