commit a2f4b389e88edd67b4640e9e97b43d9ab2e0f7e7
parent bc6a47a87654aaa416101353d0a5f7ed184c7249
Author: cfillion <cfillion@users.noreply.github.com>
Date: Sat, 20 Aug 2016 23:55:22 -0400
Merge branch 'modeless-about'
Diffstat:
13 files changed, 366 insertions(+), 269 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,55 +38,117 @@ 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)
{
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);
+ m_desc = createControl<RichEdit>(IDC_ABOUT);
- m_tabs = createControl<TabBar>(IDC_TABS, TabBar::Tabs{});
+ m_menu = createControl<ListView>(IDC_MENU);
+ m_menu->onSelect(bind(&About::updateList, this));
- 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);
+ 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);
+}
+
+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;
}
+}
- RichEdit *desc = createControl<RichEdit>(IDC_ABOUT);
- if(desc->setRichText(aboutText))
- tabs()->addTab({AUTO_STR("About"), {desc->handle()}});
+void About::setDelegate(const DelegatePtr &delegate)
+{
+#ifdef _WIN32
+ // preventing fast blinking on windows
+ SendMessage(handle(), WM_SETREDRAW, false, 0);
+#endif
- m_menu = createMenu();
+ m_tabs->clear();
+ m_menu->reset();
m_menu->sortByColumn(0);
- m_menu->onSelect(bind(&AboutDialog::callUpdateList, this));
-
- m_list = createList();
+ m_list->reset();
m_list->sortByColumn(0);
- m_report = getControl(IDC_REPORT);
+ 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,
+ };
- populate();
- populateLinks();
+ for(const int control : controls)
+ hide(getControl(control));
+
+ m_delegate = delegate;
+ m_delegate->init(this);
m_menu->sort();
- callUpdateList();
+
+ m_currentIndex = -255;
+ updateList();
#ifdef LVSCW_AUTOSIZE_USEHEADER
m_menu->resizeColumn(m_menu->columnCount() - 1, LVSCW_AUTOSIZE_USEHEADER);
m_list->resizeColumn(m_list->columnCount() - 1, LVSCW_AUTOSIZE_USEHEADER);
#endif
+
+#ifdef _WIN32
+ SendMessage(handle(), WM_SETREDRAW, true, 0);
+
+ // This is required on Windows to get the first tab to be fully draw,
+ // but I have no idea why...
+ InvalidateRect(handle(), nullptr, true);
+#endif
}
-void AboutDialog::populateLinks()
+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 +169,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 +211,76 @@ 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 != -255) || 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));
-}
-
-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());
+ dialog->list()->setSortCallback(1, [&] (const int a, const int b) {
+ const Version *l = m_packagesData->at(a)->lastVersion();
+ const Version *r = m_packagesData->at(b)->lastVersion();
+ return l->compare(*r);
+ });
- list()->addRow({name, version, author});
- }
+ initInstalledFiles();
}
-void AboutRemote::updateInstalledFiles()
+void AboutIndexDelegate::initInstalledFiles()
{
set<Registry::File> allFiles;
@@ -289,12 +299,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 +321,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 +444,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 +453,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 +465,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 +475,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,96 @@ 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 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/richedit.cpp b/src/richedit.cpp
@@ -95,14 +95,6 @@ bool RichEdit::setRichText(const string &rtf)
if(!length)
return false;
- // move caret to the end
- CHARRANGE cr{length, length};
- SendMessage(handle(), EM_EXSETSEL, 0, (LPARAM)&cr);
-
- // scroll back to top
- LONG lines = (LONG)SendMessage(handle(), EM_GETLINECOUNT, 0, 0);
- SendMessage(handle(), EM_LINESCROLL, 0, -lines);
-
// scale down a little bit, by default everything is way to big
SendMessage(handle(), EM_SETZOOM, 3, 4);
diff --git a/src/richedit.mm b/src/richedit.mm
@@ -52,6 +52,11 @@ bool RichEdit::setRichText(const string &rtf)
NSTextView *textView = (NSTextView *)handle();
+ // Manually clear the view so that invalid content will always result
+ // in this function to return false. Without this, the old text would be
+ // retained, length would stay the same and we would return true.
+ [textView setString: @""];
+
[textView
replaceCharactersInRange: NSMakeRange(0, [[textView string] length])
withRTF: [str dataUsingEncoding: NSUTF8StringEncoding]
@@ -59,10 +64,10 @@ bool RichEdit::setRichText(const string &rtf)
// auto-detect links, equivalent to Windows' EM_AUTOURLDETECT message
const BOOL isEditable = textView.isEditable;
- [textView setEditable:YES];
- [textView setEnabledTextCheckingTypes:NSTextCheckingTypeLink];
- [textView checkTextInDocument:nil];
- [textView setEditable:isEditable];
+ [textView setEditable: YES];
+ [textView setEnabledTextCheckingTypes: NSTextCheckingTypeLink];
+ [textView checkTextInDocument: nil];
+ [textView setEditable: isEditable];
return [[textView string] length];
}
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);
@@ -30,7 +30,7 @@ TabBar::TabBar(const Tabs &tabs, HWND handle)
int TabBar::addTab(const Tab &tab)
{
- int index = m_size++;
+ const int index = count();
m_pages.push_back(tab.page);
@@ -68,10 +68,27 @@ void TabBar::removeTab(const int index)
void TabBar::setFocus()
{
- if(m_lastPage < 0 || (size_t)m_lastPage >= m_pages.size())
- return;
+ const int index = currentIndex();
+
+ if(index > -1)
+ SetFocus(m_pages[index].front());
+}
+
+int TabBar::count() const
+{
+ return TabCtrl_GetItemCount(handle());
+}
- SetFocus(m_pages[m_lastPage].front());
+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,12 +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;
@@ -43,7 +45,6 @@ protected:
private:
void switchPage();
- int m_size;
int m_lastPage;
std::vector<Page> m_pages;
};