reapack

Package manager for REAPER
Log | Files | Refs | Submodules | README | LICENSE

commit a4df126ba851ec1b325a6bb35df83ef098dff981
parent f7ff871a1ee888e1e4787a74fd2b714e1025cb47
Author: cfillion <cfillion@users.noreply.github.com>
Date:   Sat, 20 Aug 2016 20:59:09 -0400

about: make the about dialog modeless

Diffstat:
Msrc/about.cpp | 406++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Msrc/about.hpp | 86++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Msrc/browser.cpp | 2+-
Msrc/dialog.hpp | 2+-
Msrc/listview.cpp | 17++++++++++++++++-
Msrc/listview.hpp | 3++-
Msrc/reapack.cpp | 36+++++++++++++++++++++---------------
Msrc/reapack.hpp | 5++++-
Msrc/resource.rc | 18+++++++++---------
Msrc/tabbar.cpp | 15+++++++++++++--
Msrc/tabbar.hpp | 3++-
11 files changed, 336 insertions(+), 257 deletions(-)

diff --git a/src/about.cpp b/src/about.cpp @@ -25,10 +25,12 @@ #include "ostream.hpp" #include "reapack.hpp" #include "registry.hpp" +#include "remote.hpp" #include "report.hpp" #include "resource.hpp" #include "richedit.hpp" #include "tabbar.hpp" +#include "transaction.hpp" #include <boost/algorithm/string/replace.hpp> @@ -36,46 +38,54 @@ using namespace std; enum { ACTION_ABOUT_PKG = 300, ACTION_COPY_URL }; -AboutDialog::AboutDialog(const Metadata *metadata) - : Dialog(IDD_ABOUT_DIALOG), m_metadata(metadata), m_currentIndex(-255) +About::About() : Dialog(IDD_ABOUT_DIALOG), m_currentIndex(-255) { RichEdit::Init(); } -void AboutDialog::onInit() +void About::onInit() { Dialog::onInit(); - auto_char title[255] = {}; - const auto_string &name = make_autostring(what()); - auto_snprintf(title, auto_size(title), AUTO_STR("About %s"), name.c_str()); - SetWindowText(handle(), title); - - m_tabs = createControl<TabBar>(IDC_TABS, TabBar::Tabs{}); - - string aboutText = m_metadata->about(); - if(name == AUTO_STR("ReaPack")) { - boost::replace_all(aboutText, "[[REAPACK_VERSION]]", ReaPack::VERSION); - boost::replace_all(aboutText, "[[REAPACK_BUILDTIME]]", ReaPack::BUILDTIME); - } - - RichEdit *desc = createControl<RichEdit>(IDC_ABOUT); - if(desc->setRichText(aboutText)) - tabs()->addTab({AUTO_STR("About"), {desc->handle()}}); + m_tabs = createControl<TabBar>(IDC_TABS); + m_desc = createControl<RichEdit>(IDC_ABOUT); - m_menu = createMenu(); - m_menu->sortByColumn(0); - m_menu->onSelect(bind(&AboutDialog::callUpdateList, this)); + m_menu = createControl<ListView>(IDC_MENU); + m_menu->onSelect(bind(&About::updateList, this)); - m_list = createList(); - m_list->sortByColumn(0); + m_list = createControl<ListView>(IDC_LIST); + m_list->onContextMenu([=] (Menu &m, int i) { return m_delegate->fillContextMenu(m, i); }); + m_list->onActivate([=] { m_delegate->itemActivated(); }); m_report = getControl(IDC_REPORT); +} - populate(); - populateLinks(); +void About::onCommand(const int id, int) +{ + switch(id) { + case IDOK: + case IDCANCEL: + close(); + break; + default: + if(m_links.count(id)) + selectLink(id); + else if(m_links.count(id >> 8)) + openLink(m_links[id >> 8][id & 0xff]); + else if(m_delegate) + m_delegate->onCommand(id); + break; + } +} + +void About::setDelegate(const DelegatePtr &model) +{ + clear(); + m_delegate = model; + m_delegate->init(this); m_menu->sort(); - callUpdateList(); + + updateList(); #ifdef LVSCW_AUTOSIZE_USEHEADER m_menu->resizeColumn(m_menu->columnCount() - 1, LVSCW_AUTOSIZE_USEHEADER); @@ -83,8 +93,52 @@ void AboutDialog::onInit() #endif } -void AboutDialog::populateLinks() +void About::clear() +{ + m_tabs->clear(); + m_menu->reset(); + m_menu->sortByColumn(0); + m_list->reset(); + m_list->sortByColumn(0); + + m_delegate = nullptr; + m_links.clear(); + + const int controls[] = { + IDC_ABOUT, + IDC_MENU, + IDC_LIST, + IDC_REPORT, + IDC_WEBSITE, + IDC_SCREENSHOT, + IDC_DONATE, + IDC_INSTALL, + }; + + for(const int control : controls) + hide(getControl(control)); +} + +void About::setTitle(const string &what) { + auto_char title[255] = {}; + auto_snprintf(title, auto_size(title), + AUTO_STR("About %s"), make_autostring(what).c_str()); + SetWindowText(handle(), title); +} + +void About::setMetadata(const Metadata *metadata, const bool substitution) +{ + string aboutText = metadata->about(); + + if(substitution) { + boost::replace_all(aboutText, "[[REAPACK_VERSION]]", ReaPack::VERSION); + boost::replace_all(aboutText, "[[REAPACK_BUILDTIME]]", ReaPack::BUILDTIME); + } + + if(m_desc->setRichText(aboutText)) + m_tabs->addTab({AUTO_STR("About"), {m_desc->handle()}}); + const auto &getLinkControl = [](const Metadata::LinkType type) { switch(type) { case Metadata::WebsiteLink: @@ -105,56 +159,25 @@ void AboutDialog::populateLinks() const int shift = (rect.right - rect.left) + 4; - for(const auto &pair : m_metadata->links()) { + for(const auto &pair : metadata->links()) { const int control = getLinkControl(pair.first); + if(!m_links.count(control)) { HWND handle = getControl(control); + SetWindowPos(handle, nullptr, rect.left, rect.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); show(handle); rect.left += shift; - m_links[control] = {}; } - m_links[control].push_back(&pair.second); - } -} -void AboutDialog::onCommand(const int id, int) -{ - switch(id) { - case IDOK: - case IDCANCEL: - close(); - break; - default: - if(m_links.count(id)) - selectLink(id); - else if(m_links.count(id >> 8)) - openLink(m_links[id >> 8][id & 0xff]); - break; + m_links[control].push_back(&pair.second); } } -void AboutDialog::callUpdateList() -{ - const int index = m_menu->currentIndex(); - - // do nothing when the selection is cleared, except for the initial execution - if((index < 0 && m_currentIndex >= -1) || index == m_currentIndex) - return; - - InhibitControl lock(m_list); - m_list->clear(); - - updateList(index); - m_currentIndex = index; - - m_list->sort(); -} - -void AboutDialog::selectLink(const int ctrl) +void About::selectLink(const int ctrl) { const auto &links = m_links[ctrl]; const int count = (int)links.size(); @@ -178,99 +201,70 @@ void AboutDialog::selectLink(const int ctrl) menu.show(rect.left, rect.bottom - 1, handle()); } -void AboutDialog::openLink(const Link *link) +void About::openLink(const Link *link) { const auto_string &url = make_autostring(link->url); ShellExecute(nullptr, AUTO_STR("open"), url.c_str(), nullptr, nullptr, SW_SHOW); } -AboutRemote::AboutRemote(const IndexPtr &index) - : AboutDialog(index->metadata()), m_index(index) +void About::updateList() { -} + const int index = m_menu->currentIndex(); -const string &AboutRemote::what() const -{ - return m_index->name(); -} + // do nothing when the selection is cleared, except for the initial execution + if((index < 0 && m_currentIndex >= -1) || index == m_currentIndex) + return; -ListView *AboutRemote::createMenu() -{ - return createControl<ListView>(IDC_MENU, ListView::Columns{ - {AUTO_STR("Category"), 142} - }); -} + InhibitControl lock(m_list); + m_list->clear(); -ListView *AboutRemote::createList() -{ - return createControl<ListView>(IDC_LIST, ListView::Columns{ - {AUTO_STR("Package"), 382}, - {AUTO_STR("Version"), 80}, - {AUTO_STR("Author"), 90}, - }); -} + m_delegate->updateList(index); + m_currentIndex = index; -void AboutRemote::onCommand(const int id, const int event) -{ - switch(id) { - case IDC_INSTALL: - close(InstallResult); - break; - case ACTION_ABOUT_PKG: - aboutPackage(); - break; - default: - AboutDialog::onCommand(id, event); - break; - } + m_list->sort(); } -void AboutRemote::populate() +void AboutIndexDelegate::init(About *dialog) { - HWND installBtn = getControl(IDC_INSTALL); + m_dialog = dialog; + + dialog->setTitle(m_index->name()); + dialog->setMetadata(m_index->metadata(), m_index->name() == "ReaPack"); + + // restore report size after being possibly modified by AboutPackageDelegate + RECT rect; + GetWindowRect(dialog->desc()->handle(), &rect); + ScreenToClient(dialog->handle(), (LPPOINT)&rect); + ScreenToClient(dialog->handle(), ((LPPOINT)&rect)+1); + SetWindowPos(dialog->report(), nullptr, rect.left, rect.top, + rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOACTIVATE); + + HWND installBtn = dialog->getControl(IDC_INSTALL); auto_char btnLabel[32] = {}; auto_snprintf(btnLabel, auto_size(btnLabel), - AUTO_STR("Install/update %s"), make_autostring(what()).c_str()); + AUTO_STR("Install/update %s"), make_autostring(m_index->name()).c_str()); SetWindowText(installBtn, btnLabel); - show(installBtn); + dialog->show(installBtn); - tabs()->addTab({AUTO_STR("Packages"), {menu()->handle(), list()->handle()}}); - tabs()->addTab({AUTO_STR("Installed Files"), {report()}}); + dialog->tabs()->addTab({AUTO_STR("Packages"), + {dialog->menu()->handle(), dialog->list()->handle()}}); + dialog->tabs()->addTab({AUTO_STR("Installed Files"), {dialog->report()}}); - list()->onActivate(bind(&AboutRemote::aboutPackage, this)); + dialog->menu()->addColumn({AUTO_STR("Category"), 142}); - menu()->addRow({AUTO_STR("<All Packages>")}); + dialog->menu()->addRow({AUTO_STR("<All Packages>")}); for(const Category *cat : m_index->categories()) - menu()->addRow({make_autostring(cat->name())}); + dialog->menu()->addRow({make_autostring(cat->name())}); - updateInstalledFiles(); + dialog->list()->addColumn({AUTO_STR("Package"), 382}); + dialog->list()->addColumn({AUTO_STR("Version"), 80}); + dialog->list()->addColumn({AUTO_STR("Author"), 90}); - list()->onContextMenu(bind(&AboutRemote::fillContextMenu, - this, placeholders::_1, placeholders::_2)); + initInstalledFiles(); } -void AboutRemote::updateList(const int index) -{ - // -1: all packages, >0 selected category - const int catIndex = max(-1, index - 1); - - if(catIndex < 0) - m_packagesData = &m_index->packages(); - else - m_packagesData = &m_index->category(catIndex)->packages(); - - for(const Package *pkg : *m_packagesData) { - const Version *lastVer = pkg->lastVersion(); - const auto_string &name = make_autostring(pkg->displayName()); - const auto_string &version = make_autostring(lastVer->name()); - const auto_string &author = make_autostring(lastVer->displayAuthor()); - - list()->addRow({name, version, author}); - } -} - -void AboutRemote::updateInstalledFiles() +void AboutIndexDelegate::initInstalledFiles() { set<Registry::File> allFiles; @@ -289,12 +283,12 @@ void AboutRemote::updateInstalledFiles() AUTO_STR("Retry later when all installation task are completed.\r\n") AUTO_STR("\r\nError description: %s"), desc.c_str()); - SetWindowText(report(), msg); + SetWindowText(m_dialog->report(), msg); return; } if(allFiles.empty()) { - SetWindowText(report(), + SetWindowText(m_dialog->report(), AUTO_STR( "This repository does not own any file on your computer at this time.\r\n") @@ -311,97 +305,122 @@ void AboutRemote::updateInstalledFiles() stream << "\r\n"; } - SetWindowText(report(), make_autostring(stream.str()).c_str()); + SetWindowText(m_dialog->report(), make_autostring(stream.str()).c_str()); } } -bool AboutRemote::fillContextMenu(Menu &menu, const int) const +void AboutIndexDelegate::updateList(const int index) { - if(list()->currentIndex() < 0) - return false; + // -1: all packages, >0 selected category + const int catIndex = index - 1; - menu.addAction(AUTO_STR("About this &package"), ACTION_ABOUT_PKG); + if(catIndex < 0) + m_packagesData = &m_index->packages(); + else + m_packagesData = &m_index->category(catIndex)->packages(); - return true; + for(const Package *pkg : *m_packagesData) { + const Version *lastVer = pkg->lastVersion(); + const auto_string &name = make_autostring(pkg->displayName()); + const auto_string &version = make_autostring(lastVer->name()); + const auto_string &author = make_autostring(lastVer->displayAuthor()); + + m_dialog->list()->addRow({name, version, author}); + } } -void AboutRemote::aboutPackage() +bool AboutIndexDelegate::fillContextMenu(Menu &menu, const int index) const { - const int index = list()->currentIndex(); - if(index < 0) - return; + return false; - const Package *pkg = m_packagesData->at(index); - Dialog::Show<AboutPackage>(instance(), handle(), pkg); -} + menu.addAction(AUTO_STR("About this &package"), ACTION_ABOUT_PKG); -AboutPackage::AboutPackage(const Package *pkg) - : AboutDialog(pkg->metadata()), m_package(pkg) -{ + return true; } -void AboutPackage::onCommand(const int id, const int event) +void AboutIndexDelegate::onCommand(const int id) { switch(id) { - case ACTION_COPY_URL: - copySourceUrl(); + case ACTION_ABOUT_PKG: + aboutPackage(); break; - default: - AboutDialog::onCommand(id, event); + case IDC_INSTALL: + install(); + m_dialog->close(); break; } } -const string &AboutPackage::what() const +void AboutIndexDelegate::aboutPackage() { - return m_package->displayName(); + const int index = m_dialog->list()->currentIndex(); + + if(index < 0) + return; + + const Package *pkg = m_packagesData->at(index); + m_dialog->setDelegate(make_shared<AboutPackageDelegate>(pkg)); } -ListView *AboutPackage::createMenu() +void AboutIndexDelegate::install() { - return createControl<ListView>(IDC_MENU, ListView::Columns{ - {AUTO_STR("Version"), 142} - }); + const Remote &remote = m_reapack->remote(m_index->name()); + + if(!remote) + return; + + Transaction *tx = m_reapack->setupTransaction(); + + if(!tx) + return; + + m_reapack->enable(remote); + + tx->synchronize(remote, true); + tx->runTasks(); } -ListView *AboutPackage::createList() +AboutPackageDelegate::AboutPackageDelegate(const Package *pkg) + : m_package(pkg), m_index(pkg->category()->index()->shared_from_this()) { - return createControl<ListView>(IDC_LIST, ListView::Columns{ - {AUTO_STR("File"), 502}, - {AUTO_STR("Main"), 50}, - }); } -void AboutPackage::populate() +void AboutPackageDelegate::init(About *dialog) { - tabs()->addTab({AUTO_STR("History"), {menu()->handle(), - report()}}); - tabs()->addTab({AUTO_STR("Contents"), {menu()->handle(), - list()->handle()}}); + m_dialog = dialog; + + dialog->setTitle(m_package->displayName()); + dialog->setMetadata(m_package->metadata()); + + dialog->tabs()->addTab({AUTO_STR("History"), {dialog->menu()->handle(), dialog->report()}}); + dialog->tabs()->addTab({AUTO_STR("Contents"), {dialog->menu()->handle(), dialog->list()->handle()}}); RECT rect; - GetWindowRect(list()->handle(), &rect); - ScreenToClient(handle(), (LPPOINT)&rect); - ScreenToClient(handle(), ((LPPOINT)&rect)+1); + GetWindowRect(dialog->list()->handle(), &rect); + ScreenToClient(dialog->handle(), (LPPOINT)&rect); + ScreenToClient(dialog->handle(), ((LPPOINT)&rect)+1); - SetWindowPos(report(), nullptr, rect.left, rect.top, + SetWindowPos(dialog->report(), nullptr, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOACTIVATE); + dialog->menu()->addColumn({AUTO_STR("Version"), 142}); + + dialog->list()->addColumn({AUTO_STR("File"), 502}); + dialog->list()->addColumn({AUTO_STR("Main"), 50}); + for(const Version *ver : m_package->versions()) - menu()->addRow({make_autostring(ver->name())}); + dialog->menu()->addRow({make_autostring(ver->name())}); - menu()->setSortCallback(0, [&] (const int a, const int b) { + dialog->menu()->setSortCallback(0, [&] (const int a, const int b) { return m_package->version(a)->compare(*m_package->version(b)); }); - menu()->sortByColumn(0, ListView::DescendingOrder); - menu()->setSelected(menu()->rowCount() - 1, true); - list()->onContextMenu(bind(&AboutPackage::fillContextMenu, - this, placeholders::_1, placeholders::_2)); + dialog->menu()->sortByColumn(0, ListView::DescendingOrder); + dialog->menu()->setSelected(dialog->menu()->rowCount() - 1, true); } -void AboutPackage::updateList(const int index) +void AboutPackageDelegate::updateList(const int index) { if(index < 0) return; @@ -409,7 +428,7 @@ void AboutPackage::updateList(const int index) const Version *ver = m_package->version(index); OutputStream stream; stream << *ver; - SetWindowText(report(), make_autostring(stream.str()).c_str()); + SetWindowText(m_dialog->report(), make_autostring(stream.str()).c_str()); vector<const Source *> uniqueSources; @@ -418,7 +437,7 @@ void AboutPackage::updateList(const int index) const Path &path = it->first; const Source *src = it->second; - list()->addRow({make_autostring(path.join()), + m_dialog->list()->addRow({make_autostring(path.join()), make_autostring(src->isMain() ? "Yes" : "No")}); uniqueSources.push_back(src); @@ -430,9 +449,9 @@ void AboutPackage::updateList(const int index) swap(m_sources, uniqueSources); } -bool AboutPackage::fillContextMenu(Menu &menu, const int) const +bool AboutPackageDelegate::fillContextMenu(Menu &menu, const int index) const { - if(list()->currentIndex() < 0) + if(index < 0) return false; menu.addAction(AUTO_STR("Copy source URL"), ACTION_COPY_URL); @@ -440,12 +459,21 @@ bool AboutPackage::fillContextMenu(Menu &menu, const int) const return true; } -void AboutPackage::copySourceUrl() +void AboutPackageDelegate::onCommand(const int id) +{ + switch(id) { + case ACTION_COPY_URL: + copySourceUrl(); + break; + } +} + +void AboutPackageDelegate::copySourceUrl() { - const int index = list()->currentIndex(); + const int index = m_dialog->list()->currentIndex(); if(index < 0) return; - setClipboard(m_sources[index]->url()); + m_dialog->setClipboard(m_sources[index]->url()); } diff --git a/src/about.hpp b/src/about.hpp @@ -24,11 +24,13 @@ #include <memory> #include <vector> +class AboutDelegate; class Index; class ListView; class Menu; class Metadata; class Package; +class ReaPack; class RichEdit; class Source; class TabBar; @@ -36,85 +38,97 @@ struct Link; typedef std::shared_ptr<const Index> IndexPtr; -class AboutDialog : public Dialog { +class About : public Dialog { public: - AboutDialog(const Metadata *); + typedef std::shared_ptr<AboutDelegate> DelegatePtr; -protected: - void onInit() override; - void onCommand(int, int) override; + About(); + void setDelegate(const DelegatePtr &); - virtual const std::string &what() const = 0; - virtual ListView *createMenu() = 0; - virtual ListView *createList() = 0; - - virtual void populate() = 0; - virtual void updateList(int) = 0; + void setTitle(const std::string &); + void setMetadata(const Metadata *, bool substitution = false); TabBar *tabs() const { return m_tabs; } + RichEdit *desc() const { return m_desc; } ListView *menu() const { return m_menu; } ListView *list() const { return m_list; } HWND report() const { return m_report; } +protected: + void onInit() override; + void onCommand(int, int) override; + private: - void populateLinks(); + void clear(); void selectLink(int control); void openLink(const Link *); - void callUpdateList(); + void updateList(); - const Metadata *m_metadata; int m_currentIndex; + std::map<int, std::vector<const Link *> > m_links; + TabBar *m_tabs; + RichEdit *m_desc; ListView *m_menu; ListView *m_list; HWND m_report; - std::map<int, std::vector<const Link *> > m_links; + DelegatePtr m_delegate; }; -class AboutRemote : public AboutDialog { -public: - enum { InstallResult = 100 }; +class AboutDelegate { +protected: + friend About; - AboutRemote(const IndexPtr &); + virtual void init(About *) = 0; + virtual void updateList(int) {} + virtual bool fillContextMenu(Menu &, int) const { return false; } + virtual void itemActivated() {}; + virtual void onCommand(int) {}; +}; -protected: - const std::string &what() const override; - ListView *createMenu() override; - ListView *createList() override; +class AboutIndexDelegate : public AboutDelegate { +public: + AboutIndexDelegate(const IndexPtr &index, ReaPack *reapack) + : m_index(index), m_reapack(reapack) {} - void onCommand(int, int) override; - void populate() override; +protected: + void init(About *) override; void updateList(int) override; + bool fillContextMenu(Menu &, int) const override; + void itemActivated() override { aboutPackage(); } + void onCommand(int) override; private: - bool fillContextMenu(Menu &, int) const; - void updateInstalledFiles(); + void initInstalledFiles(); void aboutPackage(); + void install(); IndexPtr m_index; const std::vector<const Package *> *m_packagesData; + + ReaPack *m_reapack; + About *m_dialog; }; -class AboutPackage : public AboutDialog { +class AboutPackageDelegate : public AboutDelegate { public: - AboutPackage(const Package *); + AboutPackageDelegate(const Package *); protected: - const std::string &what() const override; - ListView *createMenu() override; - ListView *createList() override; - - void onCommand(int, int) override; - void populate() override; + void init(About *) override; void updateList(int) override; + bool fillContextMenu(Menu &, int) const override; + void onCommand(int) override; private: - bool fillContextMenu(Menu &, int) const; void copySourceUrl(); const Package *m_package; + IndexPtr m_index; // keeps the package loaded in memory std::vector<const Source *> m_sources; + + About *m_dialog; }; #endif diff --git a/src/browser.cpp b/src/browser.cpp @@ -804,7 +804,7 @@ void Browser::aboutPackage(const int index) const Entry *entry = getEntry(index); if(entry && entry->package) - m_reapack->about(entry->package, handle()); + m_reapack->about(entry->package); } void Browser::aboutRemote(const int index) diff --git a/src/dialog.hpp b/src/dialog.hpp @@ -133,7 +133,7 @@ protected: HWND handle = getControl(id); - T *ctrl = new T(args..., handle); + T *ctrl = new T(handle, args...); m_controls[id] = ctrl; return ctrl; diff --git a/src/listview.cpp b/src/listview.cpp @@ -27,7 +27,7 @@ using namespace std; -ListView::ListView(const Columns &columns, HWND handle) +ListView::ListView(HWND handle, const Columns &columns) : Control(handle), m_customizable(false), m_sort(), m_defaultSort() { for(const Column &col : columns) @@ -214,6 +214,21 @@ void ListView::clear() m_rows.clear(); } +void ListView::reset() +{ + clear(); + + for(int i = columnCount(); i > 0; i--) + ListView_DeleteColumn(handle(), i - 1); + + m_cols.clear(); + + m_customizable = false; + m_sort = boost::none; + m_defaultSort = boost::none; + m_sortFuncs.clear(); +} + void ListView::setSelected(const int index, const bool select) { ListView_SetItemState(handle(), translate(index), diff --git a/src/listview.hpp b/src/listview.hpp @@ -54,7 +54,7 @@ public: typedef boost::signals2::signal<bool (Menu &, int index)> MenuSignal; typedef std::function<int (int, int)> SortCallback; - ListView(const Columns &, HWND handle); + ListView(HWND handle, const Columns & = {}); int addRow(const Row &); const Row &row(int index) const { return m_rows[index]; } @@ -63,6 +63,7 @@ public: int rowCount() const { return (int)m_rows.size(); } bool empty() const { return rowCount() < 1; } void clear(); + void reset(); int currentIndex() const; int itemUnderMouse() const; diff --git a/src/reapack.cpp b/src/reapack.cpp @@ -73,7 +73,7 @@ std::string ReaPack::resourcePath() ReaPack::ReaPack(REAPER_PLUGIN_HINSTANCE instance) : syncAction(), browseAction(), importAction(), configAction(), m_tx(nullptr), m_progress(nullptr), m_browser(nullptr), m_manager(nullptr), - m_instance(instance) + m_about(nullptr), m_instance(instance) { m_mainWindow = GetMainHwnd(); m_useRootPath = new UseRootPath(resourcePath()); @@ -226,6 +226,19 @@ void ReaPack::aboutSelf() about(remote("ReaPack"), m_mainWindow); } +void ReaPack::setupAbout() +{ + if(m_about) + return; + + m_about = Dialog::Create<About>(m_instance, m_mainWindow); + + m_about->setCloseHandler([=] (INT_PTR) { + Dialog::Destroy(m_about); + m_about = nullptr; + }); +} + void ReaPack::about(const Remote &remote, HWND parent) { if(!remote) @@ -236,25 +249,18 @@ void ReaPack::about(const Remote &remote, HWND parent) if(!index) return; - const auto ret = Dialog::Show<AboutRemote>(m_instance, parent, index); - - if(ret == AboutRemote::InstallResult) { - Transaction *tx = setupTransaction(); - - if(!tx) - return; + setupAbout(); + m_about->setDelegate(std::make_shared<AboutIndexDelegate>(index, this)); + m_about->show(); - enable(remote); - - tx->synchronize(remote, true); - tx->runTasks(); - } }, parent); } -void ReaPack::about(const Package *pkg, HWND parent) +void ReaPack::about(const Package *pkg) { - Dialog::Show<AboutPackage>(m_instance, parent, pkg); + setupAbout(); + m_about->setDelegate(std::make_shared<AboutPackageDelegate>(pkg)); + m_about->show(); } void ReaPack::browsePackages() diff --git a/src/reapack.hpp b/src/reapack.hpp @@ -28,6 +28,7 @@ #include <reaper_plugin.h> +class About; class Browser; class Config; class DownloadQueue; @@ -72,7 +73,7 @@ public: void manageRemotes(); void aboutSelf(); void about(const Remote &, HWND parent); - void about(const Package *, HWND parent); + void about(const Package *); void browsePackages(); void refreshManager(); void refreshBrowser(); @@ -91,6 +92,7 @@ private: void registerSelf(); void doFetchIndex(const Remote &remote, DownloadQueue *, HWND, bool stale); IndexPtr loadIndex(const Remote &remote, HWND); + void setupAbout(); std::map<int, ActionCallback> m_actions; @@ -99,6 +101,7 @@ private: Progress *m_progress; Browser *m_browser; Manager *m_manager; + About *m_about; REAPER_PLUGIN_HINSTANCE m_instance; HWND m_mainWindow; diff --git a/src/resource.rc b/src/resource.rc @@ -48,21 +48,21 @@ BEGIN CONTROL "", IDC_TABS, WC_TABCONTROL, 0, 0, 2, 460, 243 #ifdef _WIN32 CONTROL "", IDC_ABOUT, MSFTEDIT_CLASS, WS_VSCROLL | ES_MULTILINE | - ES_READONLY | NOT WS_TABSTOP | NOT WS_VISIBLE, 10, 20, 440, 220 + ES_READONLY | NOT WS_TABSTOP, 10, 20, 440, 220 #else EDITTEXT IDC_ABOUT, 10, 20, 440, 220, - WS_VSCROLL | ES_MULTILINE | ES_READONLY | NOT WS_TABSTOP | NOT WS_VISIBLE + WS_VSCROLL | ES_MULTILINE | ES_READONLY | NOT WS_TABSTOP #endif CONTROL "", IDC_MENU, WC_LISTVIEW, LVS_REPORT | LVS_SINGLESEL | - LVS_SHOWSELALWAYS | WS_BORDER | WS_TABSTOP | NOT WS_VISIBLE, 10, 20, 96, 220 + LVS_SHOWSELALWAYS | WS_BORDER | WS_TABSTOP, 10, 20, 96, 220 CONTROL "", IDC_LIST, WC_LISTVIEW, LVS_REPORT | LVS_SINGLESEL | - LVS_SHOWSELALWAYS | WS_BORDER | WS_TABSTOP | NOT WS_VISIBLE, 110, 20, 340, 220 + LVS_SHOWSELALWAYS | WS_BORDER | WS_TABSTOP, 110, 20, 340, 220 EDITTEXT IDC_REPORT, 10, 20, 440, 220, - WS_VSCROLL | ES_MULTILINE | ES_READONLY | NOT WS_TABSTOP | NOT WS_VISIBLE - PUSHBUTTON "&Website", IDC_WEBSITE, 5, 248, 45, 14, NOT WS_VISIBLE - PUSHBUTTON "&Screenshot", IDC_SCREENSHOT, 5, 248, 45, 14, NOT WS_VISIBLE - PUSHBUTTON "&Donate...", IDC_DONATE, 5, 248, 45, 14, NOT WS_VISIBLE - PUSHBUTTON "", IDC_INSTALL, 286, 248, 120, 14, NOT WS_VISIBLE + WS_VSCROLL | ES_MULTILINE | ES_READONLY | NOT WS_TABSTOP + PUSHBUTTON "&Website", IDC_WEBSITE, 5, 248, 45, 14 + PUSHBUTTON "&Screenshot", IDC_SCREENSHOT, 5, 248, 45, 14 + PUSHBUTTON "&Donate...", IDC_DONATE, 5, 248, 45, 14 + PUSHBUTTON "", IDC_INSTALL, 286, 248, 120, 14 DEFPUSHBUTTON "&Close", IDOK, 409, 248, 45, 14 END diff --git a/src/tabbar.cpp b/src/tabbar.cpp @@ -21,8 +21,8 @@ #include <commctrl.h> #endif -TabBar::TabBar(const Tabs &tabs, HWND handle) - : Control(handle), m_size(0), m_lastPage(-1) +TabBar::TabBar(HWND handle, const Tabs &tabs) + : Control(handle), m_lastPage(-1) { for(const Tab &tab : tabs) addTab(tab); @@ -78,6 +78,17 @@ int TabBar::count() const { return TabCtrl_GetItemCount(handle()); } + +void TabBar::clear() +{ + m_pages.clear(); + +#ifdef TabCtrl_DeleteAllItems + TabCtrl_DeleteAllItems(handle()); +#else + for(int i = count(); i > 0; i--) + TabCtrl_DeleteItem(handle(), i - 1); +#endif } void TabBar::onNotify(LPNMHDR info, LPARAM) diff --git a/src/tabbar.hpp b/src/tabbar.hpp @@ -30,13 +30,14 @@ public: struct Tab { auto_string text; Page page; }; typedef std::vector<Tab> Tabs; - TabBar(const Tabs &tabs, HWND handle); + TabBar(HWND handle, const Tabs &tabs = {}); int addTab(const Tab &); int currentIndex() const; void setCurrentIndex(int); void removeTab(int); void setFocus(); int count() const; + void clear(); protected: void onNotify(LPNMHDR, LPARAM) override;