reapack

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

commit 0b732463e07593ca651beae1fdcc95218dde34a0
parent 7738ba0fe5d3b6449f1df2b59919e4746c10f147
Author: cfillion <cfillion@users.noreply.github.com>
Date:   Sat, 28 Oct 2017 16:37:52 -0700

manager: display enabled status using REAPER's checkbox icons

Diffstat:
Asrc/iconlist.cpp | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/iconlist.hpp | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/listview.cpp | 53+++++++++++++++++++++++++++++++++++++----------------
Msrc/listview.hpp | 10++++++----
Msrc/manager.cpp | 15+++++----------
Msrc/manager.hpp | 1-
Msrc/resource.rc | 2+-
Mwin32.tup | 2+-
8 files changed, 152 insertions(+), 33 deletions(-)

diff --git a/src/iconlist.cpp b/src/iconlist.cpp @@ -0,0 +1,53 @@ +/* ReaPack: Package manager for REAPER + * Copyright (C) 2015-2017 Christian Fillion + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "iconlist.hpp" + +#ifdef _WIN32 +# define DEFINE_ICON(icon, rc, _) IconList::Icon IconList::icon = MAKEINTRESOURCE(rc) +#else +# define DEFINE_ICON(icon, _, name) IconList::Icon IconList::icon = name +#endif + +DEFINE_ICON(CheckedIcon, 141, "checked"); +DEFINE_ICON(UncheckedIcon, 142, "unchecke"); + +IconList::IconList(const std::initializer_list<const Win32::char_type *> &icons) +{ + m_list = ImageList_Create(16, 16, 1, (int)icons.size(), (int)icons.size()); + + for(const auto *icon : icons) + loadIcon(icon); +} + +void IconList::loadIcon(const Win32::char_type *name) +{ +#ifdef _WIN32 + HINSTANCE reaper = GetModuleHandle(nullptr); + HICON icon = LoadIcon(reaper, name); + ImageList_AddIcon(m_list, icon); +#else + HICON icon = LoadNamedImage(name, true); + ImageList_Add(m_list, icon, 0); +#endif + DestroyIcon(icon); +} + +IconList::~IconList() +{ + ImageList_Destroy(m_list); +} diff --git a/src/iconlist.hpp b/src/iconlist.hpp @@ -0,0 +1,49 @@ +/* ReaPack: Package manager for REAPER + * Copyright (C) 2015-2017 Christian Fillion + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef REAPACK_ICONLIST_HPP +#define REAPACK_ICONLIST_HPP + +#include "win32.hpp" + +#include <initializer_list> + +#ifdef _WIN32 +# include <windows.h> +# include <commctrl.h> +#else +# include <swell.h> +#endif + +class IconList { +public: + typedef const Win32::char_type *Icon; + + static Icon CheckedIcon; + static Icon UncheckedIcon; + + IconList(const std::initializer_list<Icon> &icons); + ~IconList(); + + void loadIcon(Icon icon); + HIMAGELIST handle() const { return m_list; } + +private: + HIMAGELIST m_list; +}; + +#endif diff --git a/src/listview.cpp b/src/listview.cpp @@ -17,6 +17,7 @@ #include "listview.hpp" +#include "iconlist.hpp" #include "menu.hpp" #include "time.hpp" #include "version.hpp" @@ -24,14 +25,22 @@ #include <boost/algorithm/string/case_conv.hpp> +using namespace std; + +static int adjustWidth(const int points) +{ #ifdef _WIN32 -# include <commctrl.h> + if(points < 1) + return points; + else + return (int)ceil(points * 0.863); // magic number to make pretty sizes... +#else + return points; #endif - -using namespace std; +} ListView::ListView(HWND handle, const Columns &columns) - : Control(handle), m_customizable(false), m_sort(), m_defaultSort(), m_dirty(0) + : Control(handle), m_dirty(0), m_customizable(false), m_sort(), m_defaultSort() { for(const Column &col : columns) addColumn(col); @@ -116,6 +125,25 @@ void ListView::updateCell(int row, int cell) m_dirty |= NeedFilterFlag; } +void ListView::enableIcons() +{ + static IconList list({IconList::UncheckedIcon, IconList::CheckedIcon}); + + // NOTE: the list must have the LVS_SHAREIMAGELISTS style to prevent + // it from taking ownership of the image list + ListView_SetImageList(handle(), list.handle(), LVSIL_SMALL); +} + +void ListView::setRowIcon(const int row, const int image) +{ + LVITEM item{}; + item.iItem = translate(row); + item.iImage = image; + item.mask |= LVIF_IMAGE; + + ListView_SetItem(handle(), &item); +} + void ListView::removeRow(const int userIndex) { // translate to view index before fixing lParams @@ -509,18 +537,6 @@ int ListView::translateBack(const int internalIndex) const return -1; } -int ListView::adjustWidth(const int points) -{ -#ifdef _WIN32 - if(points < 1) - return points; - else - return (int)ceil(points * 0.863); // magic number to make pretty sizes... -#else - return points; -#endif -} - void ListView::headerMenu(const int x, const int y) { enum { ACTION_RESTORE = 800 }; @@ -668,6 +684,11 @@ void ListView::Row::setCell(const int i, const string &val, void *data) m_list->updateCell(m_userIndex, i); } +void ListView::Row::setChecked(bool checked) +{ + m_list->setRowIcon(m_userIndex, checked); +} + vector<string> ListView::Row::filterValues() const { vector<string> values; diff --git a/src/listview.hpp b/src/listview.hpp @@ -66,6 +66,7 @@ public: const Cell &cell(const int i) const { return m_cells[i]; } void setCell(const int i, const std::string &, void *data = nullptr); + void setChecked(bool check = true); std::vector<std::string> filterValues() const; @@ -121,6 +122,7 @@ public: void clear(); void reset(); void autoSizeHeader(); + void enableIcons(); int currentIndex() const; int itemUnderMouse() const; @@ -158,6 +160,7 @@ protected: friend Row; friend BeginEdit; void updateCell(int row, int cell); + void setRowIcon(int row, int icon); void endEdit(); private: @@ -178,7 +181,6 @@ private: void onNotify(LPNMHDR, LPARAM) override; bool onContextMenu(HWND, int, int) override; - static int adjustWidth(int); void setExStyle(int style, bool enable = true); void setSortArrow(bool); void handleDoubleClick(); @@ -191,15 +193,15 @@ private: void reindexVisible(); void filter(); + int m_dirty; + Filter m_filter; + bool m_customizable; std::vector<Column> m_cols; std::vector<RowPtr> m_rows; boost::optional<Sort> m_sort; boost::optional<Sort> m_defaultSort; - Filter m_filter; - int m_dirty; - VoidSignal m_onSelect; VoidSignal m_onActivate; MenuSignal m_onContextMenu; diff --git a/src/manager.cpp b/src/manager.cpp @@ -65,11 +65,11 @@ void Manager::onInit() disable(m_apply); m_list = createControl<ListView>(IDC_LIST, ListView::Columns{ - {"Name", 115}, - {"Index URL", 415}, - {"State", 60}, + {"Name", 145}, + {"Index URL", 445}, }); + m_list->enableIcons(); m_list->onActivate(bind(&Manager::aboutRepo, this, true)); m_list->onSelect(bind(&Dialog::startTimer, this, 100, 0, true)); m_list->onContextMenu(bind(&Manager::fillContextMenu, this, _1, _2)); @@ -327,20 +327,15 @@ void Manager::refresh() int c = 0; auto row = m_list->createRow(); + row->setChecked(isRemoteEnabled(remote)); row->setCell(c++, remote.name()); row->setCell(c++, remote.url()); - updateEnabledCell(row->index(), remote); if(find(selected.begin(), selected.end(), remote.name()) != selected.end()) m_list->select(row->index()); } } -void Manager::updateEnabledCell(int index, const Remote &remote) -{ - m_list->row(index)->setCell(2, isRemoteEnabled(remote) ? "Enabled" : "Disabled"); -} - void Manager::setMods(const ModsCallback &cb, const bool updateRow) { ListView::BeginEdit edit(m_list); @@ -371,7 +366,7 @@ void Manager::setMods(const ModsCallback &cb, const bool updateRow) } if(updateRow) - updateEnabledCell(index, remote); + m_list->row(index)->setChecked(isRemoteEnabled(remote)); // TODO: move into cb } } diff --git a/src/manager.hpp b/src/manager.hpp @@ -56,7 +56,6 @@ private: Remote getRemote(int index) const; bool fillContextMenu(Menu &, int index) const; - void updateEnabledCell(int index, const Remote &); void setMods(const ModsCallback &, bool updateRow); void setRemoteEnabled(bool); bool isRemoteEnabled(const Remote &) const; diff --git a/src/resource.rc b/src/resource.rc @@ -33,7 +33,7 @@ BEGIN LTEXT "The repositories enabled in this list are used to populate the package list:", IDC_LABEL, 5, 5, 360, 10 CONTROL "", IDC_LIST, WC_LISTVIEW, LVS_REPORT | LVS_SHOWSELALWAYS | - WS_BORDER | WS_TABSTOP, 5, 18, 360, 200 + LVS_SHAREIMAGELISTS | WS_BORDER | WS_TABSTOP, 5, 18, 360, 200 PUSHBUTTON "&Browse packages", IDC_BROWSE, 5, 221, 75, 14 PUSHBUTTON "&Import/export...", IDC_IMPORT, 83, 221, 65, 14 PUSHBUTTON "&Options...", IDC_OPTIONS, 151, 221, 45, 14 diff --git a/win32.tup b/win32.tup @@ -25,7 +25,7 @@ SQLFLAGS += /DSQLITE_OMIT_COMPILEOPTION_DIAGS /DSQLITE_OMIT_CAST SQLFLAGS += /DSQLITE_OMIT_CHECK /DSQLITE_OMIT_DECLTYPE /DSQLITE_OMIT_DEPRECATED LD := $(WRAP) link -LDFLAGS := /nologo User32.lib Shell32.lib Gdi32.lib Comdlg32.lib +LDFLAGS := /nologo User32.lib Shell32.lib Gdi32.lib Comdlg32.lib Comctl32.lib LDFLAGS += vendor/libcurl@(SUFFIX)/lib/libcurl_a.lib LDFLAGS += $(TUP_VARIANTDIR)/src/resource.res LDFLAGS += $(TUP_VARIANTDIR)/build/vendor/sqlite3.o