From fc458a825d70583c6812e5fc65bbd0dc0d8f0d34 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 9 Sep 2024 23:14:54 +0200 Subject: [PATCH] page/Container: new class This class makes handling of the "dirty" flag more robust and allows removing a dirty kludge from class ProxyPage. --- src/ChatPage.cxx | 2 -- src/EditPlaylistPage.cxx | 6 +++--- src/FileBrowserPage.cxx | 8 ++++---- src/FileListPage.cxx | 18 +++++++++--------- src/FileListPage.hxx | 2 +- src/HelpPage.cxx | 5 +++-- src/KeyDefPage.cxx | 23 ++++++++++++----------- src/LibraryPage.cxx | 15 ++++++++------- src/LyricsPage.cxx | 20 +++----------------- src/OutputsPage.cxx | 7 ++++--- src/QueuePage.cxx | 21 ++++++++------------- src/SearchPage.cxx | 11 ++++++----- src/SongPage.cxx | 6 +++--- src/TagListPage.cxx | 11 ++++++----- src/TagListPage.hxx | 4 ++-- src/page/Container.hxx | 15 +++++++++++++++ src/page/ListPage.hxx | 9 ++++----- src/page/Page.cxx | 7 +++++++ src/page/Page.hxx | 21 ++++++++------------- src/page/ProxyPage.cxx | 31 ++++++++++++------------------- src/page/ProxyPage.hxx | 19 ++++++++----------- src/page/TextPage.cxx | 12 +++++++++++- src/page/TextPage.hxx | 13 +------------ src/screen.cxx | 16 ++++++++++++++-- src/screen.hxx | 12 +++++++++++- src/screen_paint.cxx | 4 ++-- 26 files changed, 165 insertions(+), 153 deletions(-) create mode 100644 src/page/Container.hxx diff --git a/src/ChatPage.cxx b/src/ChatPage.cxx index 7d7b8b7e..5a85b45f 100644 --- a/src/ChatPage.cxx +++ b/src/ChatPage.cxx @@ -87,8 +87,6 @@ ChatPage::ProcessMessage(const struct mpd_message &message) assert(StringIsEqual(mpd_message_get_channel(&message), chat_channel)); Append(mpd_message_get_text(&message)); - - SetDirty(); } void diff --git a/src/EditPlaylistPage.cxx b/src/EditPlaylistPage.cxx index 5668856d..ea5fb021 100644 --- a/src/EditPlaylistPage.cxx +++ b/src/EditPlaylistPage.cxx @@ -29,7 +29,7 @@ class EditPlaylistPage final : public FileListPage { public: EditPlaylistPage(ScreenManager &_screen, const Window _window, Size size) noexcept - :FileListPage(_screen, _window, size, + :FileListPage(_screen, _screen, _window, size, options.list_format.c_str()) { } @@ -83,7 +83,7 @@ EditPlaylistPage::Reload(struct mpdclient &c) { filelist = LoadPlaylist(c, name.c_str()); lw.SetLength(filelist->size()); - SetDirty(); + SchedulePaint(); } void @@ -178,7 +178,7 @@ EditPlaylistPage::OnMouse(struct mpdclient &c, Point p, mmask_t bstate) } SaveSelection(); - SetDirty(); + SchedulePaint(); return true; } diff --git a/src/FileBrowserPage.cxx b/src/FileBrowserPage.cxx index 24240931..25f9648f 100644 --- a/src/FileBrowserPage.cxx +++ b/src/FileBrowserPage.cxx @@ -33,7 +33,7 @@ class FileBrowserPage final : public FileListPage { public: FileBrowserPage(ScreenManager &_screen, const Window _window, Size size) noexcept - :FileListPage(_screen, _window, size, + :FileListPage(_screen, _screen, _window, size, options.list_format.c_str()) {} bool GotoSong(struct mpdclient &c, const struct mpd_song &song) noexcept; @@ -100,7 +100,7 @@ FileBrowserPage::Reload(struct mpdclient &c) noexcept lw.SetLength(filelist->size()); - SetDirty(); + SchedulePaint(); } bool @@ -174,7 +174,7 @@ FileBrowserPage::GotoSong(struct mpdclient &c, const struct mpd_song &song) noex i = 0; lw.SetCursor(i); - SetDirty(); + SchedulePaint(); return true; } @@ -300,7 +300,7 @@ FileBrowserPage::Update(struct mpdclient &c, unsigned events) noexcept #endif )) { screen_browser_sync_highlights(*filelist, c.playlist); - SetDirty(); + SchedulePaint(); } } diff --git a/src/FileListPage.cxx b/src/FileListPage.cxx index bd347805..f2d1f626 100644 --- a/src/FileListPage.cxx +++ b/src/FileListPage.cxx @@ -35,10 +35,10 @@ using std::string_view_literals::operator""sv; static constexpr unsigned HIGHLIGHT = 0x01; #endif -FileListPage::FileListPage(ScreenManager &_screen, Window _window, +FileListPage::FileListPage(PageContainer &_parent, ScreenManager &_screen, Window _window, Size size, const char *_song_format) noexcept - :ListPage(_window, size), + :ListPage(_parent, _window, size), screen(_screen), song_format(_song_format) { @@ -289,7 +289,7 @@ FileListPage::HandleSelect(struct mpdclient &c) noexcept success = browser_select_entry(c, *entry, true); } - SetDirty(); + SchedulePaint(); return range.end_index == range.start_index + 1 && success; } @@ -342,7 +342,7 @@ FileListPage::HandleSelectAll(struct mpdclient &c) noexcept browser_select_entry(c, entry, false); } - SetDirty(); + SchedulePaint(); } #ifdef HAVE_GETMOUSE @@ -368,7 +368,7 @@ FileListPage::OnMouse(struct mpdclient &c, Point p, HandleSelect(c); } - SetDirty(); + SchedulePaint(); return true; } @@ -390,11 +390,11 @@ FileListPage::OnCommand(struct mpdclient &c, Command cmd) case Command::LIST_FIND_NEXT: case Command::LIST_RFIND_NEXT: screen_find(screen, lw, cmd, *this); - SetDirty(); + SchedulePaint(); return true; case Command::LIST_JUMP: screen_jump(screen, lw, *this, *this); - SetDirty(); + SchedulePaint(); return true; #ifdef ENABLE_SONG_SCREEN @@ -435,13 +435,13 @@ FileListPage::OnCommand(struct mpdclient &c, Command cmd) case Command::SELECT: if (HandleSelect(c)) lw.HandleCommand(Command::LIST_NEXT); - SetDirty(); + SchedulePaint(); return true; case Command::ADD: if (HandleAdd(c)) lw.HandleCommand(Command::LIST_NEXT); - SetDirty(); + SchedulePaint(); return true; #ifdef ENABLE_PLAYLIST_EDITOR diff --git a/src/FileListPage.hxx b/src/FileListPage.hxx index 56bf2f46..abb610fe 100644 --- a/src/FileListPage.hxx +++ b/src/FileListPage.hxx @@ -24,7 +24,7 @@ protected: const char *const song_format; public: - FileListPage(ScreenManager &_screen, Window _window, + FileListPage(PageContainer &_parent, ScreenManager &_screen, Window _window, Size size, const char *_song_format) noexcept; diff --git a/src/HelpPage.cxx b/src/HelpPage.cxx index 53808341..19c45abe 100644 --- a/src/HelpPage.cxx +++ b/src/HelpPage.cxx @@ -8,6 +8,7 @@ #include "GlobalBindings.hxx" #include "config.h" #include "i18n.h" +#include "screen.hxx" #include "page/ListPage.hxx" #include "ui/ListRenderer.hxx" #include "ui/ListText.hxx" @@ -210,7 +211,7 @@ class HelpPage final : public ListPage, ListRenderer, ListText { public: HelpPage(ScreenManager &_screen, const Window _window, Size size) - :ListPage(_window, size), screen(_screen) { + :ListPage(_screen, _window, size), screen(_screen) { lw.HideCursor(); lw.SetLength(std::size(help_text)); } @@ -310,7 +311,7 @@ HelpPage::OnCommand(struct mpdclient &c, Command cmd) lw.SetCursorFromOrigin(0); if (screen_find(screen, lw, cmd, *this)) { - SetDirty(); + SchedulePaint(); return true; } diff --git a/src/KeyDefPage.cxx b/src/KeyDefPage.cxx index c8f767cc..9864425f 100644 --- a/src/KeyDefPage.cxx +++ b/src/KeyDefPage.cxx @@ -3,6 +3,7 @@ #include "KeyDefPage.hxx" #include "PageMeta.hxx" +#include "screen.hxx" #include "screen_status.hxx" #include "screen_find.hxx" #include "KeyName.hxx" @@ -42,9 +43,9 @@ class CommandKeysPage final : public ListPage, ListText { unsigned n_keys = 0; public: - CommandKeysPage(ScreenManager &_screen, Page *_parent, + CommandKeysPage(PageContainer &_container, ScreenManager &_screen, Page *_parent, const Window _window, Size size) noexcept - :ListPage(_window, size), screen(_screen), parent(_parent) {} + :ListPage(_container, _window, size), screen(_screen), parent(_parent) {} void SetCommand(KeyBindings *_bindings, unsigned _cmd) { bindings = _bindings; @@ -148,7 +149,7 @@ CommandKeysPage::DeleteKey(int key_index) screen_status_message(_("Deleted")); /* repaint */ - SetDirty(); + SchedulePaint(); /* update key conflict flags */ bindings->Check(nullptr, 0); @@ -193,7 +194,7 @@ CommandKeysPage::OverwriteKey(int key_index) UpdateListLength(); /* repaint */ - SetDirty(); + SchedulePaint(); /* update key conflict flags */ bindings->Check(nullptr, 0); @@ -277,7 +278,7 @@ CommandKeysPage::OnCommand(struct mpdclient &c, Command cmd) case Command::LIST_FIND_NEXT: case Command::LIST_RFIND_NEXT: screen_find(screen, lw, cmd, *this); - SetDirty(); + SchedulePaint(); return true; default: @@ -294,8 +295,8 @@ class CommandListPage final : public ListPage, ListText { static constexpr size_t command_n_commands = size_t(Command::NONE); public: - CommandListPage(ScreenManager &_screen, const Window _window, Size size) - :ListPage(_window, size), screen(_screen) {} + CommandListPage(PageContainer &_container, ScreenManager &_screen, const Window _window, Size size) + :ListPage(_container, _window, size), screen(_screen) {} ~CommandListPage() override { delete bindings; @@ -485,7 +486,7 @@ CommandListPage::OnCommand(struct mpdclient &c, Command cmd) case Command::LIST_FIND_NEXT: case Command::LIST_RFIND_NEXT: screen_find(screen, lw, cmd, *this); - SetDirty(); + SchedulePaint(); return true; default: @@ -501,9 +502,9 @@ class KeyDefPage final : public ProxyPage { public: KeyDefPage(ScreenManager &screen, const Window _window, Size size) - :ProxyPage(_window), - command_list_page(screen, _window, size), - command_keys_page(screen, this, _window, size) {} + :ProxyPage(screen, _window), + command_list_page(*this, screen, _window, size), + command_keys_page(*this, screen, this, _window, size) {} public: /* virtual methods from class Page */ diff --git a/src/LibraryPage.cxx b/src/LibraryPage.cxx index 81b584d5..209787f9 100644 --- a/src/LibraryPage.cxx +++ b/src/LibraryPage.cxx @@ -11,6 +11,7 @@ #include "mpdclient.hxx" #include "filelist.hxx" #include "Options.hxx" +#include "screen.hxx" #include "page/ProxyPage.hxx" #include "lib/fmt/ToSpan.hxx" @@ -56,9 +57,9 @@ class SongListPage final : public FileListPage { TagFilter filter; public: - SongListPage(ScreenManager &_screen, Page *_parent, + SongListPage(PageContainer &_container, ScreenManager &_screen, Page *_parent, const Window _window, Size size) noexcept - :FileListPage(_screen, _window, size, + :FileListPage(_container, _screen, _window, size, options.list_format.c_str()), parent(_parent) {} @@ -99,13 +100,13 @@ class LibraryTagListPage final : public TagListPage { ArtistBrowserPage &library_page; public: - LibraryTagListPage(ScreenManager &_screen, + LibraryTagListPage(PageContainer &_container, ScreenManager &_screen, ArtistBrowserPage &_library_page, Page *_parent, const enum mpd_tag_type _tag, const char *_all_text, const Window _window, Size size) noexcept - :TagListPage(_screen, _parent, _tag, _all_text, _window, size), + :TagListPage(_container, _screen, _parent, _tag, _all_text, _window, size), library_page(_library_page) {} protected: @@ -121,13 +122,13 @@ class ArtistBrowserPage final : public ProxyPage { public: ArtistBrowserPage(ScreenManager &_screen, const Window _window, Size size) - :ProxyPage(_window), - song_list_page(_screen, this, + :ProxyPage(_screen, _window), + song_list_page(*this, _screen, this, _window, size) { bool first = true; for (const auto &tag : options.library_page_tags) { - tag_list_pages.emplace_back(_screen, *this, + tag_list_pages.emplace_back(*this, _screen, *this, first ? nullptr : this, tag, first ? nullptr : _("All"), diff --git a/src/LyricsPage.cxx b/src/LyricsPage.cxx index 6e9f6f0a..cc4e42a7 100644 --- a/src/LyricsPage.cxx +++ b/src/LyricsPage.cxx @@ -77,16 +77,6 @@ class LyricsPage final : public TextPage, PluginResponseHandler { void Cancel() noexcept; - /** - * Repaint and update the screen, if it is currently active. - */ - void RepaintIfActive() noexcept { - if (screen.IsVisible(*this)) - Repaint(); - - /* XXX repaint the screen title */ - } - void Set(const char *s) noexcept; void StartPluginCycle() noexcept; @@ -170,10 +160,6 @@ LyricsPage::Set(const char *s) noexcept } reloading = false; - - /* paint new data */ - - RepaintIfActive(); } void @@ -193,7 +179,7 @@ LyricsPage::OnPluginSuccess(const char *_plugin_name, StopPluginCycle(); /* schedule a full repaint so the page title gets updated */ - screen.SchedulePaint(); + SchedulePaint(); } void @@ -210,7 +196,7 @@ LyricsPage::OnPluginError(std::string error) noexcept StopPluginCycle(); /* schedule a full repaint so the page title gets updated */ - screen.SchedulePaint(); + SchedulePaint(); } void @@ -277,7 +263,7 @@ LyricsPage::Reload() noexcept if (plugin_cycle == nullptr && artist != nullptr && title != nullptr) { reloading = true; StartPluginCycle(); - Repaint(); + SchedulePaint(); } } diff --git a/src/OutputsPage.cxx b/src/OutputsPage.cxx index cff9230f..7f7a0558 100644 --- a/src/OutputsPage.cxx +++ b/src/OutputsPage.cxx @@ -4,6 +4,7 @@ #include "OutputsPage.hxx" #include "Deleter.hxx" #include "PageMeta.hxx" +#include "screen.hxx" #include "screen_status.hxx" #include "Command.hxx" #include "screen_utils.hxx" @@ -108,7 +109,7 @@ class OutputsPage final : public ListPage, ListRenderer { public: OutputsPage(ScreenManager &_screen, const Window window, Size size) - :ListPage(window, size), screen(_screen) {} + :ListPage(_screen, window, size), screen(_screen) {} private: void Clear(); @@ -339,7 +340,7 @@ OutputsPage::Reload(struct mpdclient &c) noexcept #endif lw.SetLength(items.size()); - SetDirty(); + SchedulePaint(); /* restore the cursor position */ lw.SetCursorHash(items, hash); @@ -446,7 +447,7 @@ OutputsPage::OnCommand(struct mpdclient &c, Command cmd) Clear(); fill_outputs_list(&c, items); lw.SetLength(items.size()); - SetDirty(); + SchedulePaint(); return true; #if LIBMPDCLIENT_CHECK_VERSION(2,18,0) diff --git a/src/QueuePage.cxx b/src/QueuePage.cxx index ceb40cf9..235311cf 100644 --- a/src/QueuePage.cxx +++ b/src/QueuePage.cxx @@ -69,7 +69,7 @@ class QueuePage final : public ListPage, ListRenderer, ListText { public: QueuePage(ScreenManager &_screen, Window _window, Size size) - :ListPage(_window, size), + :ListPage(_screen, _window, size), screen(_screen), #ifndef NCMPC_MINI hscroll(screen.GetEventLoop(), @@ -91,11 +91,6 @@ class QueuePage final : public ListPage, ListRenderer, ListText { void SaveSelection(); void RestoreSelection(); - void Repaint() const { - Paint(); - lw.Refresh(); - } - void CenterPlayingItem(const struct mpd_status *status, bool center_cursor); @@ -337,7 +332,7 @@ QueuePage::OnHideCursorTimer() noexcept if (playing) { lw.HideCursor(); - Repaint(); + SchedulePaint(); } else ScheduleHideCursor(); } @@ -467,7 +462,7 @@ QueuePage::Update(struct mpdclient &c, unsigned events) noexcept events & MPD_IDLE_QUEUE) /* the queue or the current song has changed, we must paint the new version */ - SetDirty(); + SchedulePaint(); } #ifdef HAVE_GETMOUSE @@ -510,7 +505,7 @@ QueuePage::OnMouse(struct mpdclient &c, Point p, mmask_t bstate) } SaveSelection(); - SetDirty(); + SchedulePaint(); return true; } @@ -539,13 +534,13 @@ QueuePage::OnCommand(struct mpdclient &c, Command cmd) switch(cmd) { case Command::SCREEN_UPDATE: CenterPlayingItem(c.status, prev_cmd == Command::SCREEN_UPDATE); - SetDirty(); + SchedulePaint(); return false; case Command::SELECT_PLAYING: if (int pos = c.GetCurrentSongPos(); pos >= 0) { lw.SetCursor(pos); SaveSelection(); - SetDirty(); + SchedulePaint(); return true; } else return false; @@ -556,12 +551,12 @@ QueuePage::OnCommand(struct mpdclient &c, Command cmd) case Command::LIST_RFIND_NEXT: screen_find(screen, lw, cmd, *this); SaveSelection(); - SetDirty(); + SchedulePaint(); return true; case Command::LIST_JUMP: screen_jump(screen, lw, *this, *this); SaveSelection(); - SetDirty(); + SchedulePaint(); return true; #ifdef ENABLE_SONG_SCREEN diff --git a/src/SearchPage.cxx b/src/SearchPage.cxx index cb465bc7..ead8b72d 100644 --- a/src/SearchPage.cxx +++ b/src/SearchPage.cxx @@ -3,6 +3,7 @@ #include "SearchPage.hxx" #include "PageMeta.hxx" +#include "screen.hxx" #include "screen_status.hxx" #include "i18n.h" #include "Options.hxx" @@ -103,7 +104,7 @@ class SearchPage final : public FileListPage { public: SearchPage(ScreenManager &_screen, const Window _window, Size size) noexcept - :FileListPage(_screen, _window, size, + :FileListPage(_screen, _screen, _window, size, !options.search_format.empty() ? options.search_format.c_str() : options.list_format.c_str()) { @@ -157,7 +158,7 @@ SearchPage::Clear(bool clear_pattern) noexcept if (clear_pattern) pattern.clear(); - SetDirty(); + SchedulePaint(); } static std::unique_ptr @@ -400,7 +401,7 @@ SearchPage::Reload(struct mpdclient &c) screen_browser_sync_highlights(*filelist, c.playlist); - SetDirty(); + SchedulePaint(); } void @@ -459,7 +460,7 @@ SearchPage::Update(struct mpdclient &c, unsigned events) noexcept { if (filelist != nullptr && events & MPD_IDLE_QUEUE) { screen_browser_sync_highlights(*filelist, c.playlist); - SetDirty(); + SchedulePaint(); } } @@ -476,7 +477,7 @@ SearchPage::OnCommand(struct mpdclient &c, Command cmd) if (pattern.empty()) /* show the new mode in the help text */ - SetDirty(); + SchedulePaint(); else if (!advanced_search_mode) /* reload only if the new search mode is going to be considered */ diff --git a/src/SongPage.cxx b/src/SongPage.cxx index 663d9892..3c568d63 100644 --- a/src/SongPage.cxx +++ b/src/SongPage.cxx @@ -111,7 +111,7 @@ class SongPage final : public ListPage, ListText { public: SongPage(ScreenManager &_screen, const Window _window, Size size) noexcept - :ListPage(_window, size), + :ListPage(_screen, _window, size), screen(_screen) { lw.HideCursor(); } @@ -469,7 +469,7 @@ SongPage::Update(struct mpdclient &c, unsigned) noexcept c.HandleError(); lw.SetLength(lines.size()); - SetDirty(); + SchedulePaint(); } bool @@ -518,7 +518,7 @@ SongPage::OnCommand(struct mpdclient &c, Command cmd) } if (screen_find(screen, lw, cmd, *this)) { - SetDirty(); + SchedulePaint(); return true; } diff --git a/src/TagListPage.cxx b/src/TagListPage.cxx index 5a6d2398..90630793 100644 --- a/src/TagListPage.cxx +++ b/src/TagListPage.cxx @@ -93,6 +93,8 @@ TagListPage::LoadValues(struct mpdclient &c) noexcept /* sort list */ std::sort(values.begin(), values.end(), CompareUTF8); lw.SetLength((parent != nullptr) + values.size() + (all_text != nullptr)); + + SchedulePaint(); } void @@ -148,7 +150,6 @@ TagListPage::Update(struct mpdclient &c, unsigned events) noexcept if (events & MPD_IDLE_DATABASE) { /* the db has changed -> update the list */ Reload(c); - SetDirty(); } } @@ -240,12 +241,12 @@ TagListPage::OnCommand(struct mpdclient &c, Command cmd) case Command::LIST_FIND_NEXT: case Command::LIST_RFIND_NEXT: screen_find(screen, lw, cmd, *this); - SetDirty(); + SchedulePaint(); return true; case Command::LIST_JUMP: screen_jump(screen, lw, *this, *this); - SetDirty(); + SchedulePaint(); return true; default: @@ -253,7 +254,7 @@ TagListPage::OnCommand(struct mpdclient &c, Command cmd) } if (lw.HandleCommand(cmd)) { - SetDirty(); + SchedulePaint(); return true; } @@ -283,7 +284,7 @@ TagListPage::OnMouse(struct mpdclient &c, Point p, HandleSelect(c); } - SetDirty(); + SchedulePaint(); return true; } diff --git a/src/TagListPage.hxx b/src/TagListPage.hxx index 43f7d00e..8e6fd161 100644 --- a/src/TagListPage.hxx +++ b/src/TagListPage.hxx @@ -26,11 +26,11 @@ class TagListPage : public ListPage, ListRenderer, ListText { std::vector values; public: - TagListPage(ScreenManager &_screen, Page *_parent, + TagListPage(PageContainer &_container, ScreenManager &_screen, Page *_parent, const enum mpd_tag_type _tag, const char *_all_text, Window _window, Size size) noexcept - :ListPage(_window, size), screen(_screen), parent(_parent), + :ListPage(_container, _window, size), screen(_screen), parent(_parent), tag(_tag), all_text(_all_text) {} auto GetTag() const noexcept { diff --git a/src/page/Container.hxx b/src/page/Container.hxx new file mode 100644 index 00000000..9e7c5acc --- /dev/null +++ b/src/page/Container.hxx @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0-or-lateryes +// Copyright The Music Player Daemon Project + +#pragma once + +class Page; + +/** + * An abstract interface for classes which host one (or more) #Page + * instances. + */ +class PageContainer { +public: + virtual void SchedulePaint(Page &page) noexcept = 0; +}; diff --git a/src/page/ListPage.hxx b/src/page/ListPage.hxx index 2255da6b..49509014 100644 --- a/src/page/ListPage.hxx +++ b/src/page/ListPage.hxx @@ -13,9 +13,8 @@ class ListPage : public Page { protected: ListWindow lw; -public: - ListPage(Window window, Size size) - :lw(window, size) {} + ListPage(PageContainer &_parent, Window window, Size size) noexcept + :Page(_parent), lw(window, size) {} public: /* virtual methods from class Page */ @@ -27,7 +26,7 @@ public: if (lw.HasCursor() ? lw.HandleCommand(cmd) : lw.HandleScrollCommand(cmd)) { - SetDirty(); + SchedulePaint(); return true; } @@ -38,7 +37,7 @@ public: bool OnMouse(struct mpdclient &, Point p, mmask_t bstate) override { if (lw.HandleMouse(bstate, p.y)) { - SetDirty(); + SchedulePaint(); return true; } diff --git a/src/page/Page.cxx b/src/page/Page.cxx index b4043d4a..2bf32b89 100644 --- a/src/page/Page.cxx +++ b/src/page/Page.cxx @@ -2,8 +2,15 @@ // Copyright The Music Player Daemon Project #include "Page.hxx" +#include "Container.hxx" #include "ui/Window.hxx" +void +Page::SchedulePaint() noexcept +{ + parent.SchedulePaint(*this); +} + bool Page::PaintStatusBarOverride(Window) const noexcept { diff --git a/src/page/Page.hxx b/src/page/Page.hxx index dd906036..7757da8c 100644 --- a/src/page/Page.hxx +++ b/src/page/Page.hxx @@ -16,8 +16,11 @@ enum class Command : unsigned; struct mpdclient; struct Window; +class PageContainer; class Page { + PageContainer &parent; + Size last_size{0, 0}; /** @@ -26,28 +29,18 @@ class Page { */ unsigned pending_events = ~0u; - /** - * Does this page need to be repainted? - */ - bool dirty = true; +protected: + explicit Page(PageContainer &_parent) noexcept + :parent(_parent) {} public: virtual ~Page() noexcept = default; - bool IsDirty() const noexcept { - return dirty; - } - - void SetDirty(bool _dirty=true) noexcept { - dirty = _dirty; - } - void Resize(Size new_size) noexcept { if (new_size == last_size) return; last_size = new_size; - SetDirty(); OnResize(new_size); } @@ -64,6 +57,8 @@ protected: return last_size; } + void SchedulePaint() noexcept; + public: virtual void OnOpen(struct mpdclient &) noexcept {} virtual void OnClose() noexcept {} diff --git a/src/page/ProxyPage.cxx b/src/page/ProxyPage.cxx index 5b0787e3..896f01c7 100644 --- a/src/page/ProxyPage.cxx +++ b/src/page/ProxyPage.cxx @@ -17,10 +17,9 @@ ProxyPage::SetCurrentPage(struct mpdclient &c, Page *new_page) noexcept current_page->OnOpen(c); current_page->Resize(GetLastSize()); current_page->Update(c); - current_page->SetDirty(false); } - SetDirty(); + SchedulePaint(); } void @@ -31,8 +30,6 @@ ProxyPage::OnOpen(struct mpdclient &c) noexcept if (current_page != nullptr) current_page->OnOpen(c); - - MoveDirty(); } void @@ -50,8 +47,6 @@ ProxyPage::OnResize(Size size) noexcept { if (current_page != nullptr) current_page->Resize(size); - - MoveDirty(); } void @@ -69,31 +64,22 @@ ProxyPage::Update(struct mpdclient &c, unsigned events) noexcept if (current_page != nullptr) { current_page->AddPendingEvents(events); current_page->Update(c); - MoveDirty(); } } bool ProxyPage::OnCommand(struct mpdclient &c, Command cmd) { - if (current_page != nullptr) { - bool result = current_page->OnCommand(c, cmd); - MoveDirty(); - return result; - } else - return false; + return current_page != nullptr && + current_page->OnCommand(c, cmd); } #ifdef HAVE_GETMOUSE bool ProxyPage::OnMouse(struct mpdclient &c, Point p, mmask_t bstate) { - if (current_page != nullptr) { - bool result = current_page->OnMouse(c, p, bstate); - MoveDirty(); - return result; - } else - return false; + return current_page != nullptr && + current_page->OnMouse(c, p, bstate); } #endif @@ -104,3 +90,10 @@ ProxyPage::GetTitle(std::span buffer) const noexcept ? current_page->GetTitle(buffer) : std::string_view{}; } + +void +ProxyPage::SchedulePaint(Page &page) noexcept +{ + if (&page == current_page) + SchedulePaint(); +} diff --git a/src/page/ProxyPage.hxx b/src/page/ProxyPage.hxx index 8456dd95..1dc51eb0 100644 --- a/src/page/ProxyPage.hxx +++ b/src/page/ProxyPage.hxx @@ -4,10 +4,11 @@ #pragma once #include "Page.hxx" +#include "Container.hxx" #include "ui/Window.hxx" #include "config.h" -class ProxyPage : public Page { +class ProxyPage : public Page, public PageContainer { const Window window; Page *current_page = nullptr; @@ -15,8 +16,8 @@ class ProxyPage : public Page { bool is_open = false; public: - explicit ProxyPage(const Window _window) noexcept - :window(_window) {} + explicit ProxyPage(PageContainer &_parent, const Window _window) noexcept + :Page(_parent), window(_window) {} [[nodiscard]] const Page *GetCurrentPage() const noexcept { @@ -30,15 +31,8 @@ public: void SetCurrentPage(struct mpdclient &c, Page *new_page) noexcept; -private: - void MoveDirty() { - if (current_page != nullptr && current_page->IsDirty()) { - current_page->SetDirty(false); - SetDirty(); - } - } + using Page::SchedulePaint; -public: /* virtual methods from Page */ void OnOpen(struct mpdclient &c) noexcept override; void OnClose() noexcept override; @@ -52,4 +46,7 @@ public: #endif std::string_view GetTitle(std::span buffer) const noexcept override; + + // virtual methods from PageContainer + void SchedulePaint(Page &page) noexcept override; }; diff --git a/src/page/TextPage.cxx b/src/page/TextPage.cxx index 96096e70..d65c262b 100644 --- a/src/page/TextPage.cxx +++ b/src/page/TextPage.cxx @@ -5,12 +5,20 @@ #include "screen_find.hxx" #include "charset.hxx" #include "ui/TextListRenderer.hxx" +#include "screen.hxx" #include #include #include +TextPage::TextPage(ScreenManager &_screen, + Window window, Size size) noexcept + :ListPage(_screen, window, size), screen(_screen) +{ + lw.HideCursor(); +} + void TextPage::Clear() noexcept { @@ -51,6 +59,8 @@ TextPage::Append(const char *str) noexcept lines.emplace_back(str); lw.SetLength(lines.size()); + + SchedulePaint(); } std::string_view @@ -81,7 +91,7 @@ TextPage::OnCommand(struct mpdclient &c, Command cmd) lw.SetCursorFromOrigin(0); if (screen_find(screen, lw, cmd, *this)) { - SetDirty(); + SchedulePaint(); return true; } diff --git a/src/page/TextPage.hxx b/src/page/TextPage.hxx index 0e687aee..5c34a23f 100644 --- a/src/page/TextPage.hxx +++ b/src/page/TextPage.hxx @@ -23,10 +23,7 @@ protected: public: TextPage(ScreenManager &_screen, - Window window, Size size) noexcept - :ListPage(window, size), screen(_screen) { - lw.HideCursor(); - } + Window window, Size size) noexcept; protected: bool IsEmpty() const noexcept { @@ -48,14 +45,6 @@ protected: Append(str); } - /** - * Repaint and update the screen. - */ - void Repaint() noexcept { - Paint(); - lw.Refresh(); - } - public: /* virtual methods from class Page */ void Paint() const noexcept override; diff --git a/src/screen.cxx b/src/screen.cxx index 04884f23..744504a5 100644 --- a/src/screen.cxx +++ b/src/screen.cxx @@ -50,12 +50,13 @@ ScreenManager::Switch(const PageMeta &sf, struct mpdclient &c) noexcept /* get functions for the new mode */ current_page = page; + main_dirty = true; + /* open the new mode */ auto &p = *page->second; p.OnOpen(c); p.Resize(layout.GetMainSize()); p.Update(c); - p.SetDirty(); } void @@ -239,7 +240,8 @@ ScreenManager::OnCommand(struct mpdclient &c, DelayedSeek &seek, Command cmd) _("Auto center mode: Off")); break; case Command::SCREEN_UPDATE: - current_page->second->SetDirty(); + main_dirty = true; + SchedulePaint(); break; case Command::SCREEN_PREVIOUS: NextMode(c, -1); @@ -276,3 +278,13 @@ ScreenManager::OnMouse(struct mpdclient &c, DelayedSeek &seek, } #endif + +void +ScreenManager::SchedulePaint(Page &page) noexcept +{ + if (!IsVisible(page)) + return; + + main_dirty = true; + SchedulePaint(); +} diff --git a/src/screen.hxx b/src/screen.hxx index 8b33bdb6..854dbbea 100644 --- a/src/screen.hxx +++ b/src/screen.hxx @@ -9,6 +9,7 @@ #include "ProgressBar.hxx" #include "StatusBar.hxx" #include "History.hxx" +#include "page/Container.hxx" #include "ui/Point.hxx" #include "ui/Window.hxx" #include "event/IdleEvent.hxx" @@ -28,7 +29,7 @@ class Page; class DelayedSeek; class EventLoop; -class ScreenManager { +class ScreenManager final : public PageContainer { /** * This event defers Paint() calls until after the EventLoop * has handled all other events. @@ -86,6 +87,11 @@ private: char *buf; size_t buf_size; + /** + * Does the main area (the current page) need to be repainted? + */ + bool main_dirty = true; + public: std::string findbuf; History find_history; @@ -138,6 +144,10 @@ private: void NextMode(struct mpdclient &c, int offset) noexcept; void Paint() noexcept; + +public: + // virtual methods from PageContainer + void SchedulePaint(Page &page) noexcept override; }; #endif diff --git a/src/screen_paint.cxx b/src/screen_paint.cxx index 52535693..2202432a 100644 --- a/src/screen_paint.cxx +++ b/src/screen_paint.cxx @@ -27,9 +27,9 @@ ScreenManager::Paint() noexcept /* paint the main window */ - if (current_page->second->IsDirty()) { + if (main_dirty) { + main_dirty = false; current_page->second->Paint(); - current_page->second->SetDirty(false); } /* move the cursor to the origin */