commit ae718b3c446f53282def59fef3749c289d520165
parent 6c57007c8d4ff1159d89aae432c03ed38f84adae
Author: cfillion <cfillion@users.noreply.github.com>
Date: Sun, 26 Jun 2016 17:27:36 -0400
browser: save and restore window size and position + refactoring
Diffstat:
16 files changed, 96 insertions(+), 41 deletions(-)
diff --git a/src/about.cpp b/src/about.cpp
@@ -45,6 +45,8 @@ About::About(IndexPtr index)
void About::onInit()
{
+ Dialog::onInit();
+
m_about = createControl<RichEdit>(IDC_ABOUT);
m_cats = createControl<ListView>(IDC_CATEGORIES, ListView::Columns{
diff --git a/src/browser.cpp b/src/browser.cpp
@@ -108,12 +108,6 @@ void Browser::onInit()
return a.latest->time().compare(b.latest->time());
});
- const auto config = m_reapack->config()->browser();
- m_list->restore(config->list, 1);
-
- updateDisplayLabel();
- refresh();
-
m_filterTimer = startTimer(200);
Dialog::onInit();
@@ -129,6 +123,14 @@ void Browser::onInit()
setAnchor(getControl(IDOK), AnchorAll);
setAnchor(getControl(IDCANCEL), AnchorAll);
setAnchor(m_applyBtn, AnchorAll);
+
+ auto data = m_serializer.read(m_reapack->config()->browser()->state, 1);
+ Dialog::restore(data);
+ m_list->restore(data);
+ assert(data.empty());
+
+ updateDisplayLabel();
+ refresh();
}
void Browser::onCommand(const int id, const int event)
@@ -250,8 +252,10 @@ bool Browser::onKeyDown(const int key, const int mods)
void Browser::onClose()
{
- auto config = m_reapack->config()->browser();
- config->list = m_list->save();
+ Serializer::Data data;
+ Dialog::save(data);
+ m_list->save(data);
+ m_reapack->config()->browser()->state = m_serializer.write(data);
}
void Browser::onTimer(const int id)
diff --git a/src/browser.hpp b/src/browser.hpp
@@ -154,6 +154,7 @@ private:
HWND m_actionsBtn;
ListView *m_list;
HWND m_applyBtn;
+ Serializer m_serializer;
};
#endif
diff --git a/src/config.cpp b/src/config.cpp
@@ -37,7 +37,7 @@ static const auto_char *PRERELEASES_KEY = AUTO_STR("prereleases");
static const auto_char *BROWSER_GRP = AUTO_STR("browser");
static const auto_char *TYPEFILTER_KEY = AUTO_STR("typefilter");
static const auto_char *SHOWDESCS_KEY = AUTO_STR("showdescs");
-static const auto_char *LIST_KEY = AUTO_STR("list");
+static const auto_char *STATE_KEY = AUTO_STR("state");
static const auto_char *NETWORK_GRP = AUTO_STR("network");
static const auto_char *PROXY_KEY = AUTO_STR("proxy");
@@ -139,7 +139,7 @@ void Config::read(const Path &path)
TYPEFILTER_KEY, m_browser.typeFilter);
m_browser.showDescs = getUInt(BROWSER_GRP,
SHOWDESCS_KEY, m_browser.showDescs) > 0;
- m_browser.list = getString(BROWSER_GRP, LIST_KEY, m_browser.list);
+ m_browser.state = getString(BROWSER_GRP, STATE_KEY, m_browser.state);
m_network.proxy = getString(NETWORK_GRP, PROXY_KEY, m_network.proxy);
m_network.verifyPeer = getUInt(NETWORK_GRP,
@@ -159,7 +159,7 @@ void Config::write()
setUInt(BROWSER_GRP, TYPEFILTER_KEY, m_browser.typeFilter);
setUInt(BROWSER_GRP, SHOWDESCS_KEY, m_browser.showDescs);
- setString(BROWSER_GRP, LIST_KEY, m_browser.list);
+ setString(BROWSER_GRP, STATE_KEY, m_browser.state);
setString(NETWORK_GRP, PROXY_KEY, m_network.proxy);
setUInt(NETWORK_GRP, VERIFYPEER_KEY, m_network.verifyPeer);
diff --git a/src/config.hpp b/src/config.hpp
@@ -33,7 +33,7 @@ struct InstallOpts {
struct BrowserOpts {
unsigned int typeFilter;
bool showDescs;
- std::string list;
+ std::string state;
};
struct NetworkOpts {
diff --git a/src/dialog.cpp b/src/dialog.cpp
@@ -235,7 +235,8 @@ void Dialog::center()
top += verticalBias; // according to SWELL, top means bottom.
#endif
- SetWindowPos(m_handle, HWND_TOP, max(0, left), max(0, top), 0, 0, SWP_NOSIZE);
+ SetWindowPos(m_handle, HWND_TOP, max(0, left), max(0, top),
+ 0, 0, SWP_NOZORDER | SWP_NOSIZE);
}
bool Dialog::hasFocus() const
@@ -327,18 +328,45 @@ void Dialog::setAnchor(HWND handle, const int flags)
m_resizer.init_itemhwnd(handle, left, top, right, bottom);
}
+void Dialog::restore(Serializer::Data &data)
+{
+ if(data.size() < 2)
+ return;
+
+ auto it = data.begin();
+
+ const auto &pos = *it++;
+ const auto &size = *it++;
+
+ SetWindowPos(m_handle, HWND_TOP, pos[0], pos[1],
+ size[0], size[1], SWP_NOZORDER);
+ onResize();
+
+ data.erase(data.begin(), it);
+}
+
+void Dialog::save(Serializer::Data &data) const
+{
+ RECT rect;
+ GetWindowRect(m_handle, &rect);
+
+ data.push_back({rect.left, rect.top});
+ data.push_back({rect.right - rect.left, rect.bottom - rect.top});
+}
+
void Dialog::onInit()
{
RECT rect;
GetWindowRect(m_handle, &rect);
m_initialSize = {rect.right - rect.left, rect.bottom - rect.top};
+ center();
+
m_resizer.init(m_handle);
}
void Dialog::onShow()
{
- center();
}
void Dialog::onHide()
diff --git a/src/dialog.hpp b/src/dialog.hpp
@@ -18,6 +18,8 @@
#ifndef REAPACK_DIALOG_HPP
#define REAPACK_DIALOG_HPP
+#include "serializer.hpp"
+
#include <functional>
#include <map>
#include <set>
@@ -107,6 +109,9 @@ public:
std::string getText(HWND);
void setAnchor(HWND, int flags);
+ void restore(Serializer::Data &);
+ void save(Serializer::Data &) const;
+
void setCloseHandler(const CloseHandler &cb) { m_closeHandler = cb; }
protected:
diff --git a/src/import.cpp b/src/import.cpp
@@ -38,6 +38,8 @@ Import::Import(ReaPack *reapack)
void Import::onInit()
{
+ Dialog::onInit();
+
SetWindowText(handle(), TITLE);
m_url = getControl(IDC_URL);
diff --git a/src/listview.cpp b/src/listview.cpp
@@ -28,7 +28,7 @@
using namespace std;
ListView::ListView(const Columns &columns, HWND handle)
- : Control(handle), m_sort(), m_defaultSort()
+ : Control(handle), m_customizable(false), m_sort(), m_defaultSort()
{
for(const Column &col : columns)
addColumn(col);
@@ -293,7 +293,7 @@ bool ListView::onContextMenu(HWND dialog, int x, int y)
#endif
if(point.y < headerHeight) {
- if(m_serializer) // show menu only if header is customizable
+ if(m_customizable) // show menu only if header is customizable
headerMenu(x, y);
return true;
}
@@ -444,18 +444,20 @@ void ListView::resetColumns()
}
}
-void ListView::restore(const string &input, const int userVersion)
+void ListView::restore(Serializer::Data &data)
{
+ m_customizable = true;
setExStyle(LVS_EX_HEADERDRAGDROP, true); // enable column reordering
- const Serializer::Vector &data = m_serializer.read(input, userVersion);
if(data.empty())
return;
int col = -1;
vector<int> order(columnCount());
- for(const auto &rec : data) {
+ while(!data.empty()) {
+ const auto &rec = data.front();
+
const int left = rec[0];
const int right = rec[1];
@@ -471,6 +473,8 @@ void ListView::restore(const string &input, const int userVersion)
break;
}
+ data.pop_front();
+
if(++col >= columnCount())
break;
}
@@ -482,17 +486,14 @@ void ListView::restore(const string &input, const int userVersion)
ListView_SetColumnOrderArray(handle(), columnCount(), &order[0]);
}
-string ListView::save() const
+void ListView::save(Serializer::Data &data) const
{
const Sort sort = m_sort.value_or(Sort());
vector<int> order(columnCount());
ListView_GetColumnOrderArray(handle(), columnCount(), &order[0]);
- Serializer::Vector data;
data.push_back({sort.column, sort.order});
for(int i = 0; i < columnCount(); i++)
data.push_back({order[i], columnWidth(i)});
-
- return m_serializer.write(data);
}
diff --git a/src/listview.hpp b/src/listview.hpp
@@ -84,8 +84,8 @@ public:
void sortByColumn(int index, SortOrder order = AscendingOrder, bool user = false);
void setSortCallback(int i, const SortCallback &cb) { m_sortFuncs[i] = cb; }
- void restore(const std::string &, int userVersion);
- std::string save() const;
+ void restore(Serializer::Data &);
+ void save(Serializer::Data &) const;
void resetColumns();
void onSelect(const VoidSignal::slot_type &slot) { m_onSelect.connect(slot); }
@@ -114,7 +114,7 @@ private:
int translateBack(int internalIndex) const;
void headerMenu(int x, int y);
- Serializer m_serializer;
+ bool m_customizable;
std::vector<Column> m_cols;
std::vector<Row> m_rows;
boost::optional<Sort> m_sort;
diff --git a/src/manager.cpp b/src/manager.cpp
@@ -42,6 +42,8 @@ Manager::Manager(ReaPack *reapack)
void Manager::onInit()
{
+ Dialog::onInit();
+
m_apply = getControl(IDAPPLY);
disable(m_apply);
@@ -489,6 +491,8 @@ NetworkConfig::NetworkConfig(NetworkOpts *opts)
void NetworkConfig::onInit()
{
+ Dialog::onInit();
+
m_proxy = getControl(IDC_PROXY);
SetWindowText(m_proxy, make_autostring(m_opts->proxy).c_str());
diff --git a/src/progress.cpp b/src/progress.cpp
@@ -32,6 +32,8 @@ Progress::Progress(DownloadQueue *queue)
void Progress::onInit()
{
+ Dialog::onInit();
+
m_label = getControl(IDC_LABEL);
m_progress = GetDlgItem(handle(), IDC_PROGRESS);
diff --git a/src/report.cpp b/src/report.cpp
@@ -40,6 +40,8 @@ ReportDialog::ReportDialog()
void ReportDialog::onInit()
{
+ Dialog::onInit();
+
fillReport();
const auto_string &str = make_autostring(m_stream.str());
diff --git a/src/serializer.cpp b/src/serializer.cpp
@@ -25,14 +25,14 @@ static const char RECORD_END = ',';
using namespace std;
-auto Serializer::read(const string &input, const int userVersion) -> Vector
+auto Serializer::read(const string &input, const int userVersion) -> Data
{
m_userVersion = userVersion;
bool first = true;
istringstream stream(input);
- Vector out;
+ Data out;
while(!stream.eof()) {
string line;
@@ -73,7 +73,7 @@ auto Serializer::read(const string &input, const int userVersion) -> Vector
return out;
}
-string Serializer::write(const Vector &data) const
+string Serializer::write(const Data &data) const
{
if(!m_userVersion)
return {};
@@ -84,9 +84,10 @@ string Serializer::write(const Vector &data) const
<< m_userVersion << FIELD_END
<< VERSION << RECORD_END;
- size_t i = 0;
+ auto it = data.begin();
+
while(true) {
- const Record &rec = data[i];
+ const Record &rec = *it;
size_t j = 0;
while(true) {
@@ -98,7 +99,9 @@ string Serializer::write(const Vector &data) const
break;
}
- if(++i < data.size())
+ it++;
+
+ if(it != data.end())
stream << RECORD_END;
else
break;
diff --git a/src/serializer.hpp b/src/serializer.hpp
@@ -20,19 +20,19 @@
#include <array>
#include <string>
-#include <vector>
+#include <list>
class Serializer {
public:
typedef std::array<int, 2> Record;
- typedef std::vector<Record> Vector;
+ typedef std::list<Record> Data;
Serializer() : m_userVersion(0) {}
int userVersion() const { return m_userVersion; }
operator bool() const { return m_userVersion > 0; }
- Vector read(const std::string &, int userVersion);
- std::string write(const Vector &in) const;
+ Data read(const std::string &, int userVersion);
+ std::string write(const Data &in) const;
private:
int m_userVersion;
diff --git a/test/serializer.cpp b/test/serializer.cpp
@@ -12,9 +12,10 @@ TEST_CASE("read from serialized data", M) {
SECTION("valid") {
const auto &out = s.read("1 1,1 2,3 4,5 6", 1);
REQUIRE(out.size() == 3);
- REQUIRE(out[0] == (Serializer::Record{1,2}));
- REQUIRE(out[1] == (Serializer::Record{3,4}));
- REQUIRE(out[2] == (Serializer::Record{5,6}));
+ auto it = out.begin();
+ REQUIRE(*it++ == (Serializer::Record{1,2}));
+ REQUIRE(*it++ == (Serializer::Record{3,4}));
+ REQUIRE(*it++ == (Serializer::Record{5,6}));
REQUIRE(s.userVersion() == 1);
REQUIRE(s);
@@ -37,13 +38,13 @@ TEST_CASE("read from serialized data", M) {
SECTION("not an integer") {
const auto &out = s.read("1 1,1 2,hello world,3 4", 1);
REQUIRE(out.size() == 1);
- REQUIRE(out[0] == (Serializer::Record{1,2}));
+ REQUIRE(out.front() == (Serializer::Record{1,2}));
}
SECTION("single field") {
const auto &out = s.read("1 1,1 2,3,4 5", 1);
REQUIRE(out.size() == 1);
- REQUIRE(out[0] == (Serializer::Record{1,2}));
+ REQUIRE(out.front() == (Serializer::Record{1,2}));
}
SECTION("empty string") {