From 0496ede62f8b86e1885d594e3aa5320c96b708eb Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Sat, 6 Jan 2018 14:40:02 +0100 Subject: GUI: Implement dirty-checking for widget redraws --- backends/keymapper/remap-dialog.cpp | 12 ++--- gui/KeysDialog.cpp | 10 ++-- gui/browser.cpp | 2 +- gui/chooser.cpp | 2 +- gui/console.cpp | 35 +++++++------- gui/dialog.cpp | 19 +++++++- gui/dialog.h | 9 +++- gui/downloaddialog.cpp | 6 +-- gui/editgamedialog.cpp | 24 +++++----- gui/filebrowser-dialog.cpp | 4 +- gui/fluidsynth-dialog.cpp | 18 +++---- gui/gui-manager.cpp | 11 +++-- gui/launcher.cpp | 16 +++---- gui/object.cpp | 2 +- gui/object.h | 4 +- gui/options.cpp | 44 ++++++++--------- gui/predictivedialog.cpp | 2 +- gui/recorderdialog.cpp | 6 +-- gui/remotebrowser.cpp | 2 +- gui/saveload-dialog.cpp | 32 ++++++------- gui/storagewizarddialog.cpp | 2 +- gui/themebrowser.cpp | 2 +- gui/widget.cpp | 94 +++++++++++++++++++------------------ gui/widget.h | 24 ++++++---- gui/widgets/editable.cpp | 2 +- gui/widgets/edittext.cpp | 2 +- gui/widgets/list.cpp | 22 ++++----- gui/widgets/popup.cpp | 4 +- gui/widgets/popup.h | 4 +- gui/widgets/scrollbar.cpp | 4 +- gui/widgets/scrollbar.h | 2 +- gui/widgets/scrollcontainer.cpp | 2 +- gui/widgets/tab.cpp | 15 ++++-- gui/widgets/tab.h | 3 +- 34 files changed, 244 insertions(+), 198 deletions(-) diff --git a/backends/keymapper/remap-dialog.cpp b/backends/keymapper/remap-dialog.cpp index 3aa3647048..78a95207ad 100644 --- a/backends/keymapper/remap-dialog.cpp +++ b/backends/keymapper/remap-dialog.cpp @@ -267,7 +267,7 @@ void RemapDialog::startRemapping(uint i) { _remapTimeout = g_system->getMillis() + kRemapTimeoutDelay; Action *activeRemapAction = _currentActions[_topAction + i].action; _keymapWidgets[i].keyButton->setLabel("..."); - _keymapWidgets[i].keyButton->draw(); + _keymapWidgets[i].keyButton->markAsDirty(); _keymapper->startRemappingMode(activeRemapAction); } @@ -414,8 +414,8 @@ void RemapDialog::refreshKeymap() { _topAction = newTopAction; - //_container->draw(); - _scrollBar->draw(); + //_container->markAsDirty(); + _scrollBar->markAsDirty(); uint actionI = _topAction; @@ -446,12 +446,12 @@ void RemapDialog::refreshKeymap() { widg.keyButton->setVisible(false); widg.clearButton->setVisible(false); } - //widg.actionText->draw(); - //widg.keyButton->draw(); + //widg.actionText->markAsDirty(); + //widg.keyButton->markAsDirty(); } // need to redraw entire Dialog so that invisible // widgets disappear - draw(); + markAsDirty(); } diff --git a/gui/KeysDialog.cpp b/gui/KeysDialog.cpp index fcf9201877..68e9bd836d 100644 --- a/gui/KeysDialog.cpp +++ b/gui/KeysDialog.cpp @@ -82,7 +82,7 @@ void KeysDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { selection = Common::String::format(_("Associated key : none")); _keyMapping->setLabel(selection); - _keyMapping->draw(); + _keyMapping->markAsDirty(); } break; case kMapCmd: @@ -105,11 +105,11 @@ void KeysDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { _actionTitle->setLabel(_("Press the key to associate")); _keyMapping->setLabel(selection); - _keyMapping->draw(); + _keyMapping->markAsDirty(); Actions::Instance()->beginMapping(true); _actionsList->setEnabled(false); } - _actionTitle->draw(); + _actionTitle->markAsDirty(); break; case kOKCmd: Actions::Instance()->saveMapping(); @@ -144,8 +144,8 @@ void KeysDialog::handleKeyUp(Common::KeyState state) { _actionTitle->setLabel(_("Choose an action to map")); _keyMapping->setLabel(selection); - _keyMapping->draw(); - _actionTitle->draw(); + _keyMapping->markAsDirty(); + _actionTitle->markAsDirty(); _actionSelected = -1; _actionsList->setEnabled(true); Actions::Instance()->beginMapping(false); diff --git a/gui/browser.cpp b/gui/browser.cpp index 19fa791cee..bbfe485ba4 100644 --- a/gui/browser.cpp +++ b/gui/browser.cpp @@ -191,7 +191,7 @@ void BrowserDialog::updateListing() { _fileList->scrollTo(0); // Finally, redraw - draw(); + markAsDirty(); } } // End of namespace GUI diff --git a/gui/chooser.cpp b/gui/chooser.cpp index 61af3de407..1351263121 100644 --- a/gui/chooser.cpp +++ b/gui/chooser.cpp @@ -64,7 +64,7 @@ void ChooserDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data break; case kListSelectionChangedCmd: _chooseButton->setEnabled(item >= 0); - _chooseButton->draw(); + _chooseButton->markAsDirty(); break; case kCloseCmd: setResult(-1); diff --git a/gui/console.cpp b/gui/console.cpp index f99197c32d..5d28f5a581 100644 --- a/gui/console.cpp +++ b/gui/console.cpp @@ -173,6 +173,7 @@ void ConsoleDialog::drawDialog() { drawLine(line, false); // Draw the scrollbar + _scrollBar->markAsDirty(); _scrollBar->draw(); } @@ -213,7 +214,7 @@ void ConsoleDialog::reflowLayout() { updateScrollBuffer(); Dialog::reflowLayout(); - draw(); + markAsDirty(); } void ConsoleDialog::handleTickle() { @@ -236,13 +237,13 @@ void ConsoleDialog::handleTickle() { // End the slide _slideMode = kNoSlideMode; _y = 0; - draw(); + markAsDirty(); } else if (_slideMode == kUpSlideMode && _y <= -_h) { // End the slide //_slideMode = kNoSlideMode; close(); } else - draw(); + markAsDirty(); } _scrollBar->handleTickle(); @@ -291,7 +292,7 @@ void ConsoleDialog::handleKeyDown(Common::KeyState state) { print(PROMPT); _promptStartPos = _promptEndPos = _currentPos; - draw(); + markAsDirty(); if (!keepRunning) slideUpAndClose(); break; @@ -376,7 +377,7 @@ void ConsoleDialog::handleKeyDown(Common::KeyState state) { } else { _currentPos = _promptEndPos; } - draw(); + markAsDirty(); break; case Common::KEYCODE_KP2: @@ -404,7 +405,7 @@ void ConsoleDialog::handleKeyDown(Common::KeyState state) { _scrollLine = _firstLineInBuffer + _linesPerPage - 1; } updateScrollBuffer(); - draw(); + markAsDirty(); } break; @@ -445,7 +446,7 @@ void ConsoleDialog::handleKeyDown(Common::KeyState state) { } else { _currentPos = _promptStartPos; } - draw(); + markAsDirty(); break; case Common::KEYCODE_KP8: @@ -470,7 +471,7 @@ void ConsoleDialog::handleKeyDown(Common::KeyState state) { if (_scrollLine < _firstLineInBuffer + _linesPerPage - 1) _scrollLine = _firstLineInBuffer + _linesPerPage - 1; updateScrollBuffer(); - draw(); + markAsDirty(); } break; @@ -507,7 +508,7 @@ void ConsoleDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data int newPos = (int)data + _linesPerPage - 1 + _firstLineInBuffer; if (newPos != _scrollLine) { _scrollLine = newPos; - draw(); + markAsDirty(); } break; } @@ -517,25 +518,25 @@ void ConsoleDialog::specialKeys(int keycode) { switch (keycode) { case Common::KEYCODE_a: _currentPos = _promptStartPos; - draw(); + markAsDirty(); break; case Common::KEYCODE_d: if (_currentPos < _promptEndPos) { killChar(); - draw(); + markAsDirty(); } break; case Common::KEYCODE_e: _currentPos = _promptEndPos; - draw(); + markAsDirty(); break; case Common::KEYCODE_k: killLine(); - draw(); + markAsDirty(); break; case Common::KEYCODE_w: killLastWord(); - draw(); + markAsDirty(); break; } } @@ -625,7 +626,7 @@ void ConsoleDialog::historyScroll(int direction) { // Ensure once more the caret is visible (in case of very long history entries) scrollToCurrent(); - draw(); + markAsDirty(); } void ConsoleDialog::nextLine() { @@ -703,7 +704,7 @@ void ConsoleDialog::print(const char *str) { while (*str) printCharIntern(*str++); - draw(); + markAsDirty(); } void ConsoleDialog::drawCaret(bool erase) { @@ -732,7 +733,7 @@ void ConsoleDialog::scrollToCurrent() { } else if (line > _scrollLine) { _scrollLine = line; updateScrollBuffer(); - draw(); + markAsDirty(); } } diff --git a/gui/dialog.cpp b/gui/dialog.cpp index 24b3db4d6d..7434118404 100644 --- a/gui/dialog.cpp +++ b/gui/dialog.cpp @@ -153,7 +153,7 @@ void Dialog::releaseFocus() { } } -void Dialog::draw() { +void Dialog::markAsDirty() { //TANOKU - FIXME when is this enabled? what does this do? // Update: called on tab drawing, mainly... // we can pass this as open a new dialog or something @@ -161,6 +161,14 @@ void Dialog::draw() { g_gui._redrawStatus = GUI::GuiManager::kRedrawTopDialog; } +void Dialog::markWidgetsAsDirty() { + Widget *w = _firstWidget; + while (w) { + w->markAsDirty(); + w = w->_next; + } +} + void Dialog::drawDialog() { if (!isVisible()) @@ -168,6 +176,15 @@ void Dialog::drawDialog() { g_gui.theme()->drawDialogBackground(Common::Rect(_x, _y, _x+_w, _y+_h), _backgroundType); + markWidgetsAsDirty(); + drawWidgets(); +} + +void Dialog::drawWidgets() { + + if (!isVisible()) + return; + // Draw all children Widget *w = _firstWidget; while (w) { diff --git a/gui/dialog.h b/gui/dialog.h index cf734a83f8..cb6e13f974 100644 --- a/gui/dialog.h +++ b/gui/dialog.h @@ -88,9 +88,16 @@ protected: virtual void open(); virtual void close(); - virtual void draw(); + void markAsDirty() override; + /** Recursively mark all the widgets in this dialog as dirty so they are redrawn */ + void markWidgetsAsDirty(); + + /** Draw the dialog in its entirety (background and widgets) */ virtual void drawDialog(); + /** Draw only the dialog's widgets */ + void drawWidgets(); + virtual void handleTickle(); // Called periodically (in every guiloop() ) virtual void handleMouseDown(int x, int y, int button, int clickCount); virtual void handleMouseUp(int x, int y, int button, int clickCount); diff --git a/gui/downloaddialog.cpp b/gui/downloaddialog.cpp index bcbe956ae2..dc6d7ff95f 100644 --- a/gui/downloaddialog.cpp +++ b/gui/downloaddialog.cpp @@ -81,7 +81,7 @@ void DownloadDialog::open() { if (!selectDirectories()) close(); reflowLayout(); - draw(); + markAsDirty(); } void DownloadDialog::close() { @@ -101,7 +101,7 @@ void DownloadDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat case kDownloadProgressCmd: if (!_close) { refreshWidgets(); - draw(); + markAsDirty(); } break; case kDownloadEndedCmd: @@ -196,7 +196,7 @@ void DownloadDialog::handleTickle() { int32 progress = (int32)(100 * CloudMan.getDownloadingProgress()); if (_progressBar->getValue() != progress) { refreshWidgets(); - draw(); + markAsDirty(); } Dialog::handleTickle(); diff --git a/gui/editgamedialog.cpp b/gui/editgamedialog.cpp index 348ba5cb91..b99b53c686 100644 --- a/gui/editgamedialog.cpp +++ b/gui/editgamedialog.cpp @@ -424,26 +424,26 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat switch (cmd) { case kCmdGlobalGraphicsOverride: setGraphicSettingsState(data != 0); - draw(); + markAsDirty(); break; case kCmdGlobalAudioOverride: setAudioSettingsState(data != 0); setSubtitleSettingsState(data != 0); if (_globalVolumeOverride == NULL) setVolumeSettingsState(data != 0); - draw(); + markAsDirty(); break; case kCmdGlobalMIDIOverride: setMIDISettingsState(data != 0); - draw(); + markAsDirty(); break; case kCmdGlobalMT32Override: setMT32SettingsState(data != 0); - draw(); + markAsDirty(); break; case kCmdGlobalVolumeOverride: setVolumeSettingsState(data != 0); - draw(); + markAsDirty(); break; case kCmdChooseSoundFontCmd: { @@ -459,7 +459,7 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat else _soundFontClearButton->setEnabled(false); - draw(); + markAsDirty(); } break; } @@ -477,9 +477,9 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat // FSList files = dir.listDir(FSNode::kListFilesOnly); _gamePathWidget->setLabel(dir.getPath()); - draw(); + markAsDirty(); } - draw(); + markAsDirty(); break; } @@ -491,9 +491,9 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat // User made his choice... Common::FSNode dir(browser.getResult()); _extraPathWidget->setLabel(dir.getPath()); - draw(); + markAsDirty(); } - draw(); + markAsDirty(); break; } // Change path for stored save game (perm and temp) data @@ -508,9 +508,9 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat MessageDialog warningMessage(_("Saved games sync feature doesn't work with non-default directories. If you want your saved games to sync, use default directory.")); warningMessage.runModal(); #endif - draw(); + markAsDirty(); } - draw(); + markAsDirty(); break; } diff --git a/gui/filebrowser-dialog.cpp b/gui/filebrowser-dialog.cpp index 93395ba909..95fc4d9e0a 100644 --- a/gui/filebrowser-dialog.cpp +++ b/gui/filebrowser-dialog.cpp @@ -88,7 +88,7 @@ void FileBrowserDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 break; case kListSelectionChangedCmd: _fileName->setEditString(_fileList->getList().operator[](_fileList->getSelected()).c_str()); - _fileName->draw(); + _fileName->markAsDirty(); break; case kListItemActivatedCmd: case kListItemDoubleClickedCmd: @@ -154,7 +154,7 @@ void FileBrowserDialog::updateListing() { _fileList->scrollTo(0); // Finally, redraw - draw(); + markAsDirty(); } } // End of namespace GUI diff --git a/gui/fluidsynth-dialog.cpp b/gui/fluidsynth-dialog.cpp index af5ee6fb10..fb729971ed 100644 --- a/gui/fluidsynth-dialog.cpp +++ b/gui/fluidsynth-dialog.cpp @@ -180,45 +180,45 @@ void FluidSynthSettingsDialog::handleCommand(CommandSender *sender, uint32 cmd, break; case kChorusVoiceCountChangedCmd: _chorusVoiceCountLabel->setLabel(Common::String::format("%d", _chorusVoiceCountSlider->getValue())); - _chorusVoiceCountLabel->draw(); + _chorusVoiceCountLabel->markAsDirty(); break; case kChorusLevelChangedCmd: _chorusLevelLabel->setLabel(Common::String::format("%d", _chorusLevelSlider->getValue())); - _chorusLevelLabel->draw(); + _chorusLevelLabel->markAsDirty(); break; case kChorusSpeedChangedCmd: _chorusSpeedLabel->setLabel(Common::String::format("%d", _chorusSpeedSlider->getValue())); - _chorusSpeedLabel->draw(); + _chorusSpeedLabel->markAsDirty(); break; case kChorusDepthChangedCmd: _chorusDepthLabel->setLabel(Common::String::format("%d", _chorusDepthSlider->getValue())); - _chorusDepthLabel->draw(); + _chorusDepthLabel->markAsDirty(); break; case kActivateReverbCmd: setReverbSettingsState(data); break; case kReverbRoomSizeChangedCmd: _reverbRoomSizeLabel->setLabel(Common::String::format("%d", _reverbRoomSizeSlider->getValue())); - _reverbRoomSizeLabel->draw(); + _reverbRoomSizeLabel->markAsDirty(); break; case kReverbDampingChangedCmd: _reverbDampingLabel->setLabel(Common::String::format("%d", _reverbDampingSlider->getValue())); - _reverbDampingLabel->draw(); + _reverbDampingLabel->markAsDirty(); break; case kReverbWidthChangedCmd: _reverbWidthLabel->setLabel(Common::String::format("%d", _reverbWidthSlider->getValue())); - _reverbWidthLabel->draw(); + _reverbWidthLabel->markAsDirty(); break; case kReverbLevelChangedCmd: _reverbLevelLabel->setLabel(Common::String::format("%d", _reverbLevelSlider->getValue())); - _reverbLevelLabel->draw(); + _reverbLevelLabel->markAsDirty(); break; case kResetSettingsCmd: { MessageDialog alert(_("Do you really want to reset all FluidSynth settings to their default values?"), _("Yes"), _("No")); if (alert.runModal() == GUI::kMessageOK) { resetSettings(); readSettings(); - draw(); + markAsDirty(); } break; } diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp index 2e947c6f32..4b91019372 100644 --- a/gui/gui-manager.cpp +++ b/gui/gui-manager.cpp @@ -208,7 +208,7 @@ bool GuiManager::loadNewTheme(Common::String id, ThemeEngine::GraphicsMode gfx, void GuiManager::redraw() { ThemeEngine::ShadingStyle shading; - if (_redrawStatus == kRedrawDisabled || _dialogStack.empty()) + if (_dialogStack.empty()) return; shading = (ThemeEngine::ShadingStyle)xmlEval()->getVar("Dialog." + _dialogStack.top()->_name + ".Shading", 0); @@ -241,9 +241,12 @@ void GuiManager::redraw() { break; default: - return; + break; } + // Redraw the widgets that are marked as dirty + _dialogStack.top()->drawWidgets(); + _theme->updateScreen(); _redrawStatus = kRedrawDisabled; } @@ -304,8 +307,6 @@ void GuiManager::runLoop() { while (!_dialogStack.empty() && activeDialog == getTopDialog() && !eventMan->shouldQuit()) { uint32 frameStartTime = _system->getMillis(true); - redraw(); - // Don't "tickle" the dialog until the theme has had a chance // to re-allocate buffers in case of a scaler change. @@ -365,7 +366,7 @@ void GuiManager::runLoop() { } } - _theme->updateScreen(); + redraw(); // Delay until the allocated frame time is elapsed to match the target frame rate uint32 actualFrameDuration = _system->getMillis(true) - frameStartTime; diff --git a/gui/launcher.cpp b/gui/launcher.cpp index fd75674300..5f73776392 100644 --- a/gui/launcher.cpp +++ b/gui/launcher.cpp @@ -323,7 +323,7 @@ void LauncherDialog::addGame() { selectTarget(newTarget); } - draw(); + markAsDirty(); } // We need to update the buttons here, so "Mass add" will revert to "Add game" @@ -427,7 +427,7 @@ void LauncherDialog::removeGame(int item) { // Update the ListWidget and force a redraw updateListing(); - draw(); + markAsDirty(); } } @@ -452,7 +452,7 @@ void LauncherDialog::editGame(int item) { // Update the ListWidget, reselect the edited game and force a redraw updateListing(); selectTarget(editDialog.getDomain()); - draw(); + markAsDirty(); } } @@ -614,7 +614,7 @@ bool LauncherDialog::doGameDetection(const Common::String &path) { // Update the ListWidget, select the new item, and force a redraw updateListing(); selectTarget(editDialog.getDomain()); - draw(); + markAsDirty(); } else { // User aborted, remove the the new domain again ConfMan.removeGameDomain(domain); @@ -688,15 +688,15 @@ void LauncherDialog::updateButtons() { bool enable = (_list->getSelected() >= 0); if (enable != _startButton->isEnabled()) { _startButton->setEnabled(enable); - _startButton->draw(); + _startButton->markAsDirty(); } if (enable != _editButton->isEnabled()) { _editButton->setEnabled(enable); - _editButton->draw(); + _editButton->markAsDirty(); } if (enable != _removeButton->isEnabled()) { _removeButton->setEnabled(enable); - _removeButton->draw(); + _removeButton->markAsDirty(); } int item = _list->getSelected(); @@ -707,7 +707,7 @@ void LauncherDialog::updateButtons() { if (en != _loadButton->isEnabled()) { _loadButton->setEnabled(en); - _loadButton->draw(); + _loadButton->markAsDirty(); } switchButtonsText(_addButton, "~A~dd Game...", _s("Mass Add...")); #ifdef ENABLE_EVENTRECORDER diff --git a/gui/object.cpp b/gui/object.cpp index de66d95492..327bc27894 100644 --- a/gui/object.cpp +++ b/gui/object.cpp @@ -30,7 +30,7 @@ namespace GUI { GuiObject::GuiObject(const Common::String &name) - : _x(-1000), _y(-1000), _w(0), _h(0), _name(name), _firstWidget(0), _textDrawableArea(Common::Rect(0, 0, 0, 0)) { + : _x(-1000), _y(-1000), _w(0), _h(0), _name(name), _firstWidget(nullptr) { reflowLayout(); } diff --git a/gui/object.h b/gui/object.h index 1541c35aa8..af64697d15 100644 --- a/gui/object.h +++ b/gui/object.h @@ -70,7 +70,7 @@ protected: Widget *_firstWidget; public: - GuiObject(int x, int y, int w, int h) : _x(x), _y(y), _w(w), _h(h), _firstWidget(0), _textDrawableArea(Common::Rect(0, 0, 0, 0)) { } + GuiObject(int x, int y, int w, int h) : _x(x), _y(y), _w(w), _h(h), _firstWidget(nullptr) { } GuiObject(const Common::String &name); ~GuiObject(); @@ -87,7 +87,7 @@ public: virtual bool isVisible() const = 0; - virtual void draw() = 0; + virtual void markAsDirty() = 0; virtual void reflowLayout(); diff --git a/gui/options.cpp b/gui/options.cpp index d1e2be1852..38ad185f50 100644 --- a/gui/options.cpp +++ b/gui/options.cpp @@ -709,12 +709,12 @@ void OptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data switch (cmd) { case kMidiGainChanged: _midiGainLabel->setLabel(Common::String::format("%.2f", (double)_midiGainSlider->getValue() / 100.0)); - _midiGainLabel->draw(); + _midiGainLabel->markAsDirty(); break; case kMusicVolumeChanged: { const int newValue = _musicVolumeSlider->getValue(); _musicVolumeLabel->setValue(newValue); - _musicVolumeLabel->draw(); + _musicVolumeLabel->markAsDirty(); if (_guioptions.contains(GUIO_LINKMUSICTOSFX)) { updateSfxVolume(newValue); @@ -729,7 +729,7 @@ void OptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data case kSfxVolumeChanged: { const int newValue = _sfxVolumeSlider->getValue(); _sfxVolumeLabel->setValue(_sfxVolumeSlider->getValue()); - _sfxVolumeLabel->draw(); + _sfxVolumeLabel->markAsDirty(); if (_guioptions.contains(GUIO_LINKMUSICTOSFX)) { updateMusicVolume(newValue); @@ -744,7 +744,7 @@ void OptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data case kSpeechVolumeChanged: { const int newValue = _speechVolumeSlider->getValue(); _speechVolumeLabel->setValue(newValue); - _speechVolumeLabel->draw(); + _speechVolumeLabel->markAsDirty(); if (_guioptions.contains(GUIO_LINKSPEECHTOSFX)) { updateSfxVolume(newValue); @@ -768,20 +768,20 @@ void OptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data break; case kSubtitleSpeedChanged: _subSpeedLabel->setValue(_subSpeedSlider->getValue()); - _subSpeedLabel->draw(); + _subSpeedLabel->markAsDirty(); break; case kClearSoundFontCmd: _soundFont->setLabel(_c("None", "soundfont")); _soundFontClearButton->setEnabled(false); - draw(); + markAsDirty(); break; case kKbdMouseSpeedChanged: _kbdMouseSpeedLabel->setLabel(_(kbdMouseSpeedLabels[_kbdMouseSpeedSlider->getValue()])); - _kbdMouseSpeedLabel->draw(); + _kbdMouseSpeedLabel->markAsDirty(); break; case kJoystickDeadzoneChanged: _joystickDeadzoneLabel->setValue(_joystickDeadzoneSlider->getValue()); - _joystickDeadzoneLabel->draw(); + _joystickDeadzoneLabel->markAsDirty(); break; case kApplyCmd: apply(); @@ -1320,22 +1320,22 @@ int OptionsDialog::getSubtitleMode(bool subtitles, bool speech_mute) { void OptionsDialog::updateMusicVolume(const int newValue) const { _musicVolumeLabel->setValue(newValue); _musicVolumeSlider->setValue(newValue); - _musicVolumeLabel->draw(); - _musicVolumeSlider->draw(); + _musicVolumeLabel->markAsDirty(); + _musicVolumeSlider->markAsDirty(); } void OptionsDialog::updateSfxVolume(const int newValue) const { _sfxVolumeLabel->setValue(newValue); _sfxVolumeSlider->setValue(newValue); - _sfxVolumeLabel->draw(); - _sfxVolumeSlider->draw(); + _sfxVolumeLabel->markAsDirty(); + _sfxVolumeSlider->markAsDirty(); } void OptionsDialog::updateSpeechVolume(const int newValue) const { _speechVolumeLabel->setValue(newValue); _speechVolumeSlider->setValue(newValue); - _speechVolumeLabel->draw(); - _speechVolumeSlider->draw(); + _speechVolumeLabel->markAsDirty(); + _speechVolumeSlider->markAsDirty(); } void OptionsDialog::reflowLayout() { @@ -1936,7 +1936,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3 error.runModal(); return; } - draw(); + markAsDirty(); } break; } @@ -1946,7 +1946,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3 // User made his choice... Common::FSNode dir(browser.getResult()); _themePath->setLabel(dir.getPath()); - draw(); + markAsDirty(); } break; } @@ -1956,7 +1956,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3 // User made his choice... Common::FSNode dir(browser.getResult()); _extraPath->setLabel(dir.getPath()); - draw(); + markAsDirty(); } break; } @@ -1967,7 +1967,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3 // User made his choice... Common::FSNode dir(browser.getResult()); _pluginsPath->setLabel(dir.getPath()); - draw(); + markAsDirty(); } break; } @@ -1982,7 +1982,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3 if (path.empty()) path = "/"; // absolute root _rootPath->setLabel(path); - draw(); + markAsDirty(); } break; } @@ -2013,7 +2013,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3 else _soundFontClearButton->setEnabled(false); - draw(); + markAsDirty(); } break; } @@ -2107,7 +2107,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3 if (_serverPort) { _serverPort->setEditString(Common::String::format("%u", Networking::LocalWebserver::DEFAULT_SERVER_PORT)); } - draw(); + markAsDirty(); break; } #endif // USE_SDL_NET @@ -2144,7 +2144,7 @@ void GlobalOptionsDialog::handleTickle() { #endif if (_redrawCloudTab) { setupCloudTab(); - draw(); + markAsDirty(); _redrawCloudTab = false; } #endif diff --git a/gui/predictivedialog.cpp b/gui/predictivedialog.cpp index 933667186e..5650fd8e94 100644 --- a/gui/predictivedialog.cpp +++ b/gui/predictivedialog.cpp @@ -995,7 +995,7 @@ void PredictiveDialog::pressEditText() { Common::strlcat(_predictiveResult, _currentWord.c_str(), sizeof(_predictiveResult)); _editText->setEditString(_predictiveResult); //_editText->setCaretPos(_prefix.size() + _currentWord.size()); - _editText->draw(); + _editText->markAsDirty(); } } // namespace GUI diff --git a/gui/recorderdialog.cpp b/gui/recorderdialog.cpp index 7e8e12bcf8..cd89b58f00 100644 --- a/gui/recorderdialog.cpp +++ b/gui/recorderdialog.cpp @@ -211,7 +211,7 @@ void RecorderDialog::updateList() { file.close(); } _list->setList(namesList); - _list->draw(); + _list->markAsDirty(); } int RecorderDialog::runModal(Common::String &target) { @@ -253,7 +253,7 @@ void RecorderDialog::updateSelection(bool redraw) { _screenShotsCount = -1; _currentScreenshot = 0; _gfxWidget->setGfx(-1, -1, 0, 0, 0); - _gfxWidget->draw(); + _gfxWidget->markAsDirty(); updateScreenShotsText(); } } @@ -283,7 +283,7 @@ void RecorderDialog::updateScreenshot() { } else { _gfxWidget->setGfx(-1, -1, 0, 0, 0); } - _gfxWidget->draw(); + _gfxWidget->markAsDirty(); } void RecorderDialog::updateScreenShotsText() { diff --git a/gui/remotebrowser.cpp b/gui/remotebrowser.cpp index 029320596f..1d503001e0 100644 --- a/gui/remotebrowser.cpp +++ b/gui/remotebrowser.cpp @@ -162,7 +162,7 @@ void RemoteBrowserDialog::updateListing() { _fileList->setEnabled(!_navigationLocked); // Finally, redraw - draw(); + markAsDirty(); } void RemoteBrowserDialog::goUp() { diff --git a/gui/saveload-dialog.cpp b/gui/saveload-dialog.cpp index 189760b4e1..6d2a43bfb3 100644 --- a/gui/saveload-dialog.cpp +++ b/gui/saveload-dialog.cpp @@ -60,7 +60,7 @@ SaveLoadCloudSyncProgressDialog::SaveLoadCloudSyncProgressDialog(bool canRunInBa new ButtonWidget(this, "SaveLoadCloudSyncProgress.Cancel", "Cancel", 0, kCancelSyncCmd, Common::ASCII_ESCAPE); // Cancel dialog ButtonWidget *backgroundButton = new ButtonWidget(this, "SaveLoadCloudSyncProgress.Background", "Run in background", 0, kBackgroundSyncCmd, Common::ASCII_RETURN); // Confirm dialog backgroundButton->setEnabled(canRunInBackground); - draw(); + markAsDirty(); } SaveLoadCloudSyncProgressDialog::~SaveLoadCloudSyncProgressDialog() { @@ -72,7 +72,7 @@ void SaveLoadCloudSyncProgressDialog::handleCommand(CommandSender *sender, uint3 case kSavesSyncProgressCmd: _percentLabel->setLabel(Common::String::format("%u%%", data)); _progressBar->setValue(data); - _progressBar->draw(); + _progressBar->markAsDirty(); break; case kCancelSyncCmd: @@ -594,14 +594,14 @@ void SaveLoadChooserSimple::updateSelection(bool redraw) { _deleteButton->setEnabled(isDeletable && !isLocked && (selItem >= 0) && (!_list->getSelectedString().empty())); if (redraw) { - _gfxWidget->draw(); - _date->draw(); - _time->draw(); - _playtime->draw(); - _chooseButton->draw(); - _deleteButton->draw(); - - draw(); + _gfxWidget->markAsDirty(); + _date->markAsDirty(); + _time->markAsDirty(); + _playtime->markAsDirty(); + _chooseButton->markAsDirty(); + _deleteButton->markAsDirty(); + + markAsDirty(); } } @@ -703,7 +703,7 @@ void SaveLoadChooserSimple::updateSaveList() { else _chooseButton->setEnabled(false); - draw(); + markAsDirty(); } // SaveLoadChooserGrid implementation @@ -761,13 +761,13 @@ void SaveLoadChooserGrid::handleCommand(CommandSender *sender, uint32 cmd, uint3 case kNextCmd: ++_curPage; updateSaves(); - draw(); + markAsDirty(); break; case kPrevCmd: --_curPage; updateSaves(); - draw(); + markAsDirty(); break; case kNewSaveCmd: @@ -788,13 +788,13 @@ void SaveLoadChooserGrid::handleMouseWheel(int x, int y, int direction) { if (_nextButton->isEnabled()) { ++_curPage; updateSaves(); - draw(); + markAsDirty(); } } else { if (_prevButton->isEnabled()) { --_curPage; updateSaves(); - draw(); + markAsDirty(); } } } @@ -802,7 +802,7 @@ void SaveLoadChooserGrid::handleMouseWheel(int x, int y, int direction) { void SaveLoadChooserGrid::updateSaveList() { SaveLoadChooserDialog::updateSaveList(); updateSaves(); - draw(); + markAsDirty(); } void SaveLoadChooserGrid::open() { diff --git a/gui/storagewizarddialog.cpp b/gui/storagewizarddialog.cpp index 085f901fc4..e7a684c5a1 100644 --- a/gui/storagewizarddialog.cpp +++ b/gui/storagewizarddialog.cpp @@ -231,7 +231,7 @@ void StorageWizardDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3 _codeWidget[i]->setEditString(subcode); } handleCommand(sender, kCodeBoxCmd, data); - draw(); + markAsDirty(); } break; } diff --git a/gui/themebrowser.cpp b/gui/themebrowser.cpp index 75be555e0a..d21979cac4 100644 --- a/gui/themebrowser.cpp +++ b/gui/themebrowser.cpp @@ -115,7 +115,7 @@ void ThemeBrowser::updateListing() { _fileList->setSelected(currentThemeIndex); // Finally, redraw - draw(); + markAsDirty(); } } // End of namespace GUI diff --git a/gui/widget.cpp b/gui/widget.cpp index 4b84e19c09..fa3767b605 100644 --- a/gui/widget.cpp +++ b/gui/widget.cpp @@ -51,6 +51,7 @@ void Widget::init() { // Insert into the widget list of the boss _next = _boss->_firstWidget; _boss->_firstWidget = this; + _needsRedraw = true; } Common::Rect Widget::getBossClipRect() const { @@ -112,38 +113,52 @@ void Widget::updateState(int oldFlags, int newFlags) { } } +void Widget::markAsDirty() { + _needsRedraw = true; + + Widget *w = _firstWidget; + while (w) { + w->markAsDirty(); + w = w->next(); + } +} + void Widget::draw() { if (!isVisible() || !_boss->isVisible()) return; - int oldX = _x, oldY = _y; + if (_needsRedraw) { + int oldX = _x, oldY = _y; - // Account for our relative position in the dialog - _x = getAbsX(); - _y = getAbsY(); + // Account for our relative position in the dialog + _x = getAbsX(); + _y = getAbsY(); - // Draw border - if (_flags & WIDGET_BORDER) { - g_gui.theme()->drawWidgetBackgroundClip(Common::Rect(_x, _y, _x+_w, _y+_h), getBossClipRect(), 0, ThemeEngine::kWidgetBackgroundBorder); - _x += 4; - _y += 4; - _w -= 8; - _h -= 8; - } + // Draw border + if (_flags & WIDGET_BORDER) { + g_gui.theme()->drawWidgetBackgroundClip(Common::Rect(_x, _y, _x+_w, _y+_h), getBossClipRect(), 0, ThemeEngine::kWidgetBackgroundBorder); + _x += 4; + _y += 4; + _w -= 8; + _h -= 8; + } - // Now perform the actual widget draw - drawWidget(); + // Now perform the actual widget draw + drawWidget(); - // Restore x/y - if (_flags & WIDGET_BORDER) { - _x -= 4; - _y -= 4; - _w += 8; - _h += 8; - } + // Restore x/y + if (_flags & WIDGET_BORDER) { + _x -= 4; + _y -= 4; + _w += 8; + _h += 8; + } - _x = oldX; - _y = oldY; + _x = oldX; + _y = oldY; + + _needsRedraw = false; + } // Draw all children Widget *w = _firstWidget; @@ -191,7 +206,7 @@ void Widget::setEnabled(bool e) { else clearFlags(WIDGET_ENABLED); - _boss->draw(); + _boss->markAsDirty(); } } @@ -273,7 +288,7 @@ StaticTextWidget::StaticTextWidget(GuiObject *boss, int x, int y, int w, int h, StaticTextWidget::StaticTextWidget(GuiObject *boss, const Common::String &name, const Common::String &text, const char *tooltip, ThemeEngine::FontStyle font) : Widget(boss, name, tooltip) { - setFlags(WIDGET_ENABLED); + setFlags(WIDGET_ENABLED | WIDGET_CLEARBG); _type = kStaticTextWidget; _label = text; @@ -289,12 +304,7 @@ void StaticTextWidget::setLabel(const Common::String &label) { if (_label != label) { _label = label; - // when changing the label, add the CLEARBG flag - // so the widget is completely redrawn, otherwise - // the new text is drawn on top of the old one. - setFlags(WIDGET_CLEARBG); - draw(); - clearFlags(WIDGET_CLEARBG); + markAsDirty(); } } @@ -302,14 +312,8 @@ void StaticTextWidget::setAlign(Graphics::TextAlign align) { if (_align != align){ _align = align; - // same as setLabel() actually, the text - // would be redrawn on top of the old one so - // we add the CLEARBG flag - setFlags(WIDGET_CLEARBG); - draw(); - clearFlags(WIDGET_CLEARBG); + markAsDirty(); } - } @@ -389,18 +393,18 @@ ButtonWidget *addClearButton(GuiObject *boss, const Common::String &name, uint32 void ButtonWidget::setHighLighted(bool enable) { (enable) ? setFlags(WIDGET_HILITED) : clearFlags(WIDGET_HILITED); - draw(); + markAsDirty(); } void ButtonWidget::setPressedState() { setFlags(WIDGET_PRESSED); clearFlags(WIDGET_HILITED); - draw(); + markAsDirty(); } void ButtonWidget::setUnpressedState() { clearFlags(WIDGET_PRESSED); - draw(); + markAsDirty(); } #pragma mark - @@ -563,7 +567,7 @@ void CheckboxWidget::setState(bool state) { if (_state != state) { _state = state; //_flags ^= WIDGET_INV_BORDER; - draw(); + markAsDirty(); } sendCommand(_cmd, _state); } @@ -632,7 +636,7 @@ void RadiobuttonWidget::setState(bool state, bool setGroup) { if (_state != state) { _state = state; //_flags ^= WIDGET_INV_BORDER; - draw(); + markAsDirty(); } sendCommand(_cmd, _state); } @@ -667,7 +671,7 @@ void SliderWidget::handleMouseMoved(int x, int y, int button) { if (newValue != _value) { _value = newValue; - draw(); + markAsDirty(); sendCommand(_cmd, _value); // FIXME - hack to allow for "live update" in sound dialog } } @@ -699,7 +703,7 @@ void SliderWidget::handleMouseWheel(int x, int y, int direction) { if (newValue != _value) { _value = newValue; - draw(); + markAsDirty(); sendCommand(_cmd, _value); // FIXME - hack to allow for "live update" in sound dialog } } diff --git a/gui/widget.h b/gui/widget.h index 0da071e596..e57f3cde51 100644 --- a/gui/widget.h +++ b/gui/widget.h @@ -103,6 +103,7 @@ protected: private: uint16 _flags; + bool _needsRedraw; public: static Widget *findWidgetInChain(Widget *start, int x, int y); @@ -137,7 +138,12 @@ public: virtual bool handleKeyUp(Common::KeyState state) { return false; } // Return true if the event was handled virtual void handleTickle() {} - void draw(); + /** Mark the widget and its children as dirty so they are redrawn on the next screen update */ + virtual void markAsDirty(); + + /** Redraw the widget if it was marked as dirty, and recursively proceed with its children */ + virtual void draw(); + void receivedFocus() { _hasFocus = true; receivedFocusWidget(); } void lostFocus() { _hasFocus = false; lostFocusWidget(); } virtual bool wantsFocus() { return false; } @@ -213,8 +219,8 @@ public: void handleMouseUp(int x, int y, int button, int clickCount); void handleMouseDown(int x, int y, int button, int clickCount); - void handleMouseEntered(int button) { if (_duringPress) { setFlags(WIDGET_PRESSED); } else { setFlags(WIDGET_HILITED); } draw(); } - void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED | WIDGET_PRESSED); draw(); } + void handleMouseEntered(int button) { if (_duringPress) { setFlags(WIDGET_PRESSED); } else { setFlags(WIDGET_HILITED); } markAsDirty(); } + void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED | WIDGET_PRESSED); markAsDirty(); } void setHighLighted(bool enable); void setPressedState(); @@ -262,8 +268,8 @@ public: CheckboxWidget(GuiObject *boss, const Common::String &name, const Common::String &label, const char *tooltip = 0, uint32 cmd = 0, uint8 hotkey = 0); void handleMouseUp(int x, int y, int button, int clickCount); - virtual void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); draw(); } - virtual void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); draw(); } + virtual void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); markAsDirty(); } + virtual void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); markAsDirty(); } void setState(bool state); void toggleState() { setState(!_state); } @@ -308,8 +314,8 @@ public: RadiobuttonWidget(GuiObject *boss, const Common::String &name, RadiobuttonGroup *group, int value, const Common::String &label, const char *tooltip = 0, uint8 hotkey = 0); void handleMouseUp(int x, int y, int button, int clickCount); - virtual void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); draw(); } - virtual void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); draw(); } + virtual void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); markAsDirty(); } + virtual void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); markAsDirty(); } void setState(bool state, bool setGroup = true); void toggleState() { setState(!_state); } @@ -348,8 +354,8 @@ public: void handleMouseMoved(int x, int y, int button); void handleMouseDown(int x, int y, int button, int clickCount); void handleMouseUp(int x, int y, int button, int clickCount); - void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); draw(); } - void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); draw(); } + void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); markAsDirty(); } + void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); markAsDirty(); } void handleMouseWheel(int x, int y, int direction); protected: diff --git a/gui/widgets/editable.cpp b/gui/widgets/editable.cpp index 02defe9a56..5e7c94b64a 100644 --- a/gui/widgets/editable.cpp +++ b/gui/widgets/editable.cpp @@ -235,7 +235,7 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) { } if (dirty) - draw(); + markAsDirty(); if (forcecaret) makeCaretVisible(); diff --git a/gui/widgets/edittext.cpp b/gui/widgets/edittext.cpp index 0a8725ac9e..97366741d0 100644 --- a/gui/widgets/edittext.cpp +++ b/gui/widgets/edittext.cpp @@ -87,7 +87,7 @@ void EditTextWidget::handleMouseDown(int x, int y, int button, int clickCount) { last = cur; } if (setCaretPos(i)) - draw(); + markAsDirty(); #ifdef TIZEN // Display the virtual keypad to allow text entry. Samsung app-store testers expected diff --git a/gui/widgets/list.cpp b/gui/widgets/list.cpp index e5690fb6f2..16d91f9a1e 100644 --- a/gui/widgets/list.cpp +++ b/gui/widgets/list.cpp @@ -145,7 +145,7 @@ void ListWidget::setSelected(int item) { _currentPos = _selectedItem - _entriesPerPage / 2; scrollToCurrent(); - draw(); + markAsDirty(); } } @@ -251,7 +251,7 @@ void ListWidget::handleMouseDown(int x, int y, int button, int clickCount) { // TODO: Determine where inside the string the user clicked and place the // caret accordingly. // See _editScrollOffset and EditTextWidget::handleMouseDown. - draw(); + markAsDirty(); } @@ -446,12 +446,12 @@ bool ListWidget::handleKeyDown(Common::KeyState state) { } if (dirty || _selectedItem != oldSelectedItem) - draw(); + markAsDirty(); if (_selectedItem != oldSelectedItem) { sendCommand(kListSelectionChangedCmd, _selectedItem); // also draw scrollbar - _scrollBar->draw(); + _scrollBar->markAsDirty(); } return handled; @@ -467,7 +467,7 @@ void ListWidget::receivedFocusWidget() { _inversion = ThemeEngine::kTextInversionFocus; // Redraw the widget so the selection color will change - draw(); + markAsDirty(); } void ListWidget::lostFocusWidget() { @@ -477,7 +477,7 @@ void ListWidget::lostFocusWidget() { _editMode = false; g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); drawCaret(true); - draw(); + markAsDirty(); } void ListWidget::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { @@ -486,7 +486,7 @@ void ListWidget::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { if (_currentPos != (int)data) { _currentPos = data; checkBounds(); - draw(); + markAsDirty(); // Scrollbar actions cause list focus (which triggers a redraw) // NOTE: ListWidget's boss is always GUI::Dialog @@ -600,7 +600,7 @@ void ListWidget::scrollToEnd() { _scrollBar->_currentPos = _currentPos; _scrollBar->recalc(); - _scrollBar->draw(); + _scrollBar->markAsDirty(); } void ListWidget::startEditMode() { @@ -616,7 +616,7 @@ void ListWidget::startEditMode() { else _editColor = _listColors[_listIndex[_selectedItem]]; } - draw(); + markAsDirty(); g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); } } @@ -636,7 +636,7 @@ void ListWidget::abortEditMode() { assert(_selectedItem >= 0); _editMode = false; //drawCaret(true); - //draw(); + //markAsDirty(); g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); } @@ -744,7 +744,7 @@ void ListWidget::setFilter(const String &filter, bool redraw) { // Such a widget could also (optionally) draw a border (or even different // kinds of borders) around the objects it groups; and also a 'title' // (I am borrowing these "ideas" from the NSBox class in Cocoa :). - _boss->draw(); + _boss->markAsDirty(); } } diff --git a/gui/widgets/popup.cpp b/gui/widgets/popup.cpp index 74fbc44823..f59a89e543 100644 --- a/gui/widgets/popup.cpp +++ b/gui/widgets/popup.cpp @@ -409,7 +409,7 @@ void PopUpWidget::handleMouseDown(int x, int y, int button, int clickCount) { if (newSel != -1 && _selectedItem != newSel) { _selectedItem = newSel; sendCommand(kPopUpItemSelectedCmd, _entries[_selectedItem].tag); - draw(); + markAsDirty(); } } } @@ -429,7 +429,7 @@ void PopUpWidget::handleMouseWheel(int x, int y, int direction) { (newSelection != _selectedItem)) { _selectedItem = newSelection; sendCommand(kPopUpItemSelectedCmd, _entries[_selectedItem].tag); - draw(); + markAsDirty(); } } } diff --git a/gui/widgets/popup.h b/gui/widgets/popup.h index 37ddc276ad..d2b1f1cb92 100644 --- a/gui/widgets/popup.h +++ b/gui/widgets/popup.h @@ -77,8 +77,8 @@ public: uint32 getSelectedTag() const { return (_selectedItem >= 0) ? _entries[_selectedItem].tag : (uint32)-1; } // const String& getSelectedString() const { return (_selectedItem >= 0) ? _entries[_selectedItem].name : String::emptyString; } - void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); draw(); } - void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); draw(); } + void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); markAsDirty(); } + void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); markAsDirty(); } virtual void reflowLayout(); protected: diff --git a/gui/widgets/scrollbar.cpp b/gui/widgets/scrollbar.cpp index d8bcb18336..b0e2576ec1 100644 --- a/gui/widgets/scrollbar.cpp +++ b/gui/widgets/scrollbar.cpp @@ -135,7 +135,7 @@ void ScrollBarWidget::handleMouseMoved(int x, int y, int button) { _part = kSliderPart; if (old_part != _part) - draw(); + markAsDirty(); } } @@ -165,7 +165,7 @@ void ScrollBarWidget::checkBounds(int old_pos) { if (old_pos != _currentPos) { recalc(); - draw(); + markAsDirty(); sendCommand(kSetPositionCmd, _currentPos); } } diff --git a/gui/widgets/scrollbar.h b/gui/widgets/scrollbar.h index de7c13ce03..a1181b9e6c 100644 --- a/gui/widgets/scrollbar.h +++ b/gui/widgets/scrollbar.h @@ -69,7 +69,7 @@ public: void handleMouseWheel(int x, int y, int direction); void handleMouseMoved(int x, int y, int button); void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); } - void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); _part = kNoPart; draw(); } + void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); _part = kNoPart; markAsDirty(); } void handleTickle(); // FIXME - this should be private, but then we also have to add accessors diff --git a/gui/widgets/scrollcontainer.cpp b/gui/widgets/scrollcontainer.cpp index 7c5ab6112c..0f3c96dcb6 100644 --- a/gui/widgets/scrollcontainer.cpp +++ b/gui/widgets/scrollcontainer.cpp @@ -102,7 +102,7 @@ void ScrollContainerWidget::handleCommand(CommandSender *sender, uint32 cmd, uin case kSetPositionCmd: _scrolledY = _verticalScroll->_currentPos; reflowLayout(); - draw(); + markAsDirty(); g_gui.doFullRedraw(); break; } diff --git a/gui/widgets/tab.cpp b/gui/widgets/tab.cpp index e2e3e72db0..9b045daf51 100644 --- a/gui/widgets/tab.cpp +++ b/gui/widgets/tab.cpp @@ -154,7 +154,7 @@ void TabWidget::removeTab(int tabID) { } // Finally trigger a redraw - _boss->draw(); + _boss->markAsDirty(); } void TabWidget::setActiveTab(int tabID) { @@ -174,7 +174,7 @@ void TabWidget::setActiveTab(int tabID) { while (_lastVisibleTab < tabID) setFirstVisible(_firstVisibleTab + 1, false); - _boss->draw(); + _boss->markAsDirty(); } } @@ -246,7 +246,7 @@ void TabWidget::setFirstVisible(int tabID, bool adjustIfRoom) { computeLastVisibleTab(adjustIfRoom); - _boss->draw(); // TODO: Necessary? + _boss->markAsDirty(); // TODO: Necessary? } void TabWidget::reflowLayout() { @@ -334,6 +334,15 @@ void TabWidget::draw() { } } +void TabWidget::markAsDirty() { + Widget::markAsDirty(); + + if (_navButtonsVisible) { + _navLeft->markAsDirty(); + _navRight->markAsDirty(); + } +} + bool TabWidget::containsWidget(Widget *w) const { if (w == _navLeft || w == _navRight || _navLeft->containsWidget(w) || _navRight->containsWidget(w)) return true; diff --git a/gui/widgets/tab.h b/gui/widgets/tab.h index fe5e4d82bc..bdd3e56b46 100644 --- a/gui/widgets/tab.h +++ b/gui/widgets/tab.h @@ -111,7 +111,8 @@ public: virtual void reflowLayout(); - virtual void draw(); + void draw() override; + void markAsDirty() override; protected: // We overload getChildY to make sure child widgets are positioned correctly. -- cgit v1.2.3