linuxdcpp-team team mailing list archive
-
linuxdcpp-team team
-
Mailing list archive
-
Message #04805
[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 2677: smarter sfinae in TypedTable to make text, image, sorting, custom draw optional
------------------------------------------------------------
revno: 2677
committer: poy <poy@xxxxxxxxxx>
branch nick: trunk
timestamp: Mon 2011-11-14 20:24:14 +0100
message:
smarter sfinae in TypedTable to make text, image, sorting, custom draw optional
modified:
dcpp/Util.h
dwt/include/dwt/widgets/Table.h
win32/FavHubGroupsDlg.cpp
win32/FavHubGroupsDlg.h
win32/HubFrame.h
win32/PublicHubsFrame.h
win32/TypedTable.h
win32/forward.h
--
lp:dcplusplus
https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk
Your team Dcplusplus-team is subscribed to branch lp:dcplusplus.
To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk/+edit-subscription
=== modified file 'dcpp/Util.h'
--- dcpp/Util.h 2011-10-08 15:21:54 +0000
+++ dcpp/Util.h 2011-11-14 19:24:14 +0000
@@ -110,6 +110,19 @@
template<typename T1> inline double fraction(T1 a, T1 b) { return static_cast<double>(a) / b; }
+/** Uses SFINAE to determine whether a type provides a function; stores the result in "value".
+Inspired by <http://stackoverflow.com/questions/257288#264088>. */
+/// @todo simplify when MSVC supports default template arguments on functions...
+#define HAS_FUNC(name, func, signature) \
+ template<typename T> struct name { \
+ typedef char yes[1]; \
+ typedef char no[2]; \
+ template<typename T, T> struct type_check; \
+ template<typename T> static yes& check(type_check<signature, &T::func>*); \
+ template<typename> static no& check(...); \
+ enum { value = sizeof(check<T>(0)) == sizeof(yes) }; \
+ }
+
class Util
{
public:
=== modified file 'dwt/include/dwt/widgets/Table.h'
--- dwt/include/dwt/widgets/Table.h 2011-11-07 22:11:39 +0000
+++ dwt/include/dwt/widgets/Table.h 2011-11-14 19:24:14 +0000
@@ -173,11 +173,9 @@
void setSort(int aColumn, SortType aType, bool aAscending = true);
- bool isAscending();
-
- int getSortColumn();
-
- SortType getSortType();
+ bool isAscending() const;
+ int getSortColumn() const;
+ SortType getSortType() const;
/// Returns the text of the given cell
/** The column is which column you wish to retrieve the text for. <br>
@@ -724,15 +722,15 @@
return Rectangle(r);
}
-inline bool Table::isAscending() {
+inline bool Table::isAscending() const {
return ascending;
}
-inline int Table::getSortColumn() {
+inline int Table::getSortColumn() const {
return sortColumn;
}
-inline Table::SortType Table::getSortType() {
+inline Table::SortType Table::getSortType() const {
return sortType;
}
=== modified file 'win32/FavHubGroupsDlg.cpp'
--- win32/FavHubGroupsDlg.cpp 2011-11-12 19:36:12 +0000
+++ win32/FavHubGroupsDlg.cpp 2011-11-14 19:24:14 +0000
@@ -74,10 +74,6 @@
return columns[col];
}
-int FavHubGroupsDlg::GroupInfo::getImage(int) const {
- return -1;
-}
-
int FavHubGroupsDlg::GroupInfo::compareItems(const GroupInfo* a, const GroupInfo* b, int col) {
return lstrcmpi(a->columns[col].c_str(), b->columns[col].c_str());
}
@@ -163,11 +159,11 @@
groups->setSort(COLUMN_NAME);
}
+ handleSelectionChanged();
+
groups->onKeyDown([this](int c) { return handleKeyDown(c); });
groups->onSelectionChanged([this] { handleSelectionChanged(); });
- handleSelectionChanged();
-
setText(T_("Favorite hub groups"));
layout();
=== modified file 'win32/FavHubGroupsDlg.h'
--- win32/FavHubGroupsDlg.h 2011-05-04 19:32:00 +0000
+++ win32/FavHubGroupsDlg.h 2011-11-14 19:24:14 +0000
@@ -45,12 +45,11 @@
COLUMN_LAST
};
- class GroupInfo : public FastAlloc<GroupInfo> {
+ class GroupInfo {
public:
GroupInfo(const FavHubGroup& group_);
const tstring& getText(int col) const;
- int getImage(int) const;
static int compareItems(const GroupInfo* a, const GroupInfo* b, int col);
=== modified file 'win32/HubFrame.h'
--- win32/HubFrame.h 2011-11-13 16:46:43 +0000
+++ win32/HubFrame.h 2011-11-14 19:24:14 +0000
@@ -161,7 +161,7 @@
GridPtr userGrid;
- typedef TypedTable<UserInfo, false, true> WidgetUsers;
+ typedef TypedTable<UserInfo, false> WidgetUsers;
typedef WidgetUsers* WidgetUsersPtr;
WidgetUsersPtr users;
=== modified file 'win32/PublicHubsFrame.h'
--- win32/PublicHubsFrame.h 2011-05-04 19:32:00 +0000
+++ win32/PublicHubsFrame.h 2011-11-14 19:24:14 +0000
@@ -80,7 +80,6 @@
static int compareItems(const HubInfo* a, const HubInfo* b, int col);
const tstring& getText(int column) const { return columns[column]; }
- int getImage(int) const { return 0; }
const HubEntry* entry;
=== modified file 'win32/TypedTable.h'
--- win32/TypedTable.h 2011-11-13 16:46:43 +0000
+++ win32/TypedTable.h 2011-11-14 19:24:14 +0000
@@ -29,18 +29,28 @@
@tparam managed Whether this class should handle deleting associated objects.
-@tparam customColors Custom colors per item (whole row) or per sub-item (each cell).
-The ContentType class must provide a int getColor(COLORREF& text, COLORREF& bg, int col) function.
-It is called a first time with col=-1 to set colors for the whole item. It can return:
+@note Support for texts:
+The ContentType class must provide a const tstring& getText(int col) const function.
+
+@note Support for images:
+The ContentType class must provide a int getImage(int col) const function.
+
+@note Support for item sorting:
+The ContentType class must provide a
+static int compareItems(ContentType* a, ContentType* b, int col) function.
+
+@note Support for custom colors per item (whole row) or per sub-item (each cell):
+The ContentType class must provide a int getColor(COLORREF& text, COLORREF& bg, int col) const
+function. It is called a first time with col=-1 to set colors for the whole item. It can return:
- CDRF_DODEFAULT to keep default colors for the item.
- CDRF_NEWFONT to change colors for the item.
- CDRF_NOTIFYSUBITEMDRAW to request custom colors for each sub-item (get Color will then be called
for each sub-item). */
-template<typename ContentType, bool managed, bool customColors>
+template<typename ContentType, bool managed>
class TypedTable : public Table
{
typedef Table BaseType;
- typedef TypedTable<ContentType, managed, customColors> ThisType;
+ typedef TypedTable<ContentType, managed> ThisType;
public:
typedef ThisType* ObjectType;
@@ -64,18 +74,14 @@
void create(const Seed& seed) {
BaseType::create(seed);
- this->onRaw([this](WPARAM, LPARAM lParam) -> LRESULT {
- auto& data = *reinterpret_cast<NMLVDISPINFO*>(lParam);
- this->handleDisplay(data);
- return 0;
- }, dwt::Message(WM_NOTIFY, LVN_GETDISPINFO));
- this->onColumnClick([this](int column) { this->handleColumnClick(column); });
- this->onSortItems([this](LPARAM lhs, LPARAM rhs) { return this->handleSort(lhs, rhs); });
- addColorEvent<void>();
+ addTextEvent<ContentType>();
+ addImageEvent<ContentType>();
+ addSortEvent<ContentType>();
+ addColorEvent<ContentType>();
}
int insert(ContentType* item) {
- return insert(getSortPos(item), item);
+ return insert(getSortPos<ContentType>(item), item);
}
int insert(int i, ContentType* item) {
@@ -147,7 +153,57 @@
void erase(ContentType* item) { int i = find(item); if(i != -1) this->erase(i); }
- int getSortPos(ContentType* a) {
+ void setSort(int col = -1, bool ascending = true) {
+ BaseType::setSort(col, BaseType::SORT_CALLBACK, ascending);
+ }
+
+private:
+ HAS_FUNC(HasText_, getText, const tstring& (ContentType::*)(int) const);
+#define HasText HasText_<ContentType>::value
+
+ HAS_FUNC(HasImage_, getImage, int (ContentType::*)(int) const);
+#define HasImage HasImage_<ContentType>::value
+
+ HAS_FUNC(HasSort_, compareItems, int (*)(const ContentType*, const ContentType*, int));
+#define HasSort HasSort_<ContentType>::value
+
+ HAS_FUNC(HasColor_, getColor, int (ContentType::*)(COLORREF&, COLORREF&, int) const);
+#define HasColor HasColor_<ContentType>::value
+
+ template<typename ContentType> typename std::enable_if<HasText, void>::type addTextEvent() {
+ this->onRaw([this](WPARAM, LPARAM lParam) -> LRESULT {
+ auto& data = *reinterpret_cast<NMLVDISPINFO*>(lParam);
+ if(data.item.mask & LVIF_TEXT) {
+ this->handleText<ContentType>(data);
+ }
+ return 0;
+ }, dwt::Message(WM_NOTIFY, LVN_GETDISPINFO));
+ }
+ template<typename ContentType> typename std::enable_if<!HasText, void>::type addTextEvent() { }
+
+ template<typename ContentType> typename std::enable_if<HasImage, void>::type addImageEvent() {
+ this->onRaw([this](WPARAM, LPARAM lParam) -> LRESULT {
+ auto& data = *reinterpret_cast<NMLVDISPINFO*>(lParam);
+ if(data.item.mask & LVIF_IMAGE) {
+ this->handleImage<ContentType>(data);
+ }
+ return 0;
+ }, dwt::Message(WM_NOTIFY, LVN_GETDISPINFO));
+ }
+ template<typename ContentType> typename std::enable_if<!HasImage, void>::type addImageEvent() { }
+
+ template<typename ContentType> typename std::enable_if<HasSort, void>::type addSortEvent() {
+ this->onSortItems([this](LPARAM lhs, LPARAM rhs) { return this->handleSort<ContentType>(lhs, rhs); });
+ this->onColumnClick([this](int column) { this->handleColumnClick<ContentType>(column); });
+ }
+ template<typename ContentType> typename std::enable_if<!HasSort, void>::type addSortEvent() { }
+
+ template<typename ContentType> typename std::enable_if<HasColor, void>::type addColorEvent() {
+ this->onCustomDraw([this](NMLVCUSTOMDRAW& data) { return this->handleCustomDraw<ContentType>(data); });
+ }
+ template<typename ContentType> typename std::enable_if<!HasColor, void>::type addColorEvent() { }
+
+ template<typename ContentType> typename std::enable_if<HasSort, int>::type getSortPos(ContentType* a) {
int high = this->size();
if((this->getSortColumn() == -1) || (high == 0))
return high;
@@ -183,33 +239,25 @@
return mid;
}
-
- void setSort(int col = -1, bool ascending = true) {
- BaseType::setSort(col, BaseType::SORT_CALLBACK, ascending);
- }
-
-private:
- template<typename Ret> typename std::enable_if<customColors, Ret>::type addColorEvent() {
- this->onCustomDraw([this](NMLVCUSTOMDRAW& data) { return this->handleCustomDraw<LRESULT>(data); });
- }
- template<typename Ret> typename std::enable_if<!customColors, Ret>::type addColorEvent() { }
-
- void handleDisplay(NMLVDISPINFO& data) {
- if(data.item.mask & LVIF_TEXT) {
- ContentType* content = reinterpret_cast<ContentType*>(data.item.lParam);
- const tstring& text = content->getText(data.item.iSubItem);
- _tcsncpy(data.item.pszText, text.data(), std::min(text.size(), static_cast<size_t>(data.item.cchTextMax)));
- if(text.size() < static_cast<size_t>(data.item.cchTextMax)) {
- data.item.pszText[text.size()] = 0;
- }
- }
- if(data.item.mask & LVIF_IMAGE) {
- ContentType* content = reinterpret_cast<ContentType*>(data.item.lParam);
- data.item.iImage = content->getImage(data.item.iSubItem);
- }
- }
-
- void handleColumnClick(int column) {
+ template<typename ContentType> typename std::enable_if<!HasSort, int>::type getSortPos(ContentType* a) {
+ return this->size();
+ }
+
+ template<typename ContentType> typename std::enable_if<HasText, void>::type handleText(NMLVDISPINFO& data) {
+ ContentType* content = reinterpret_cast<ContentType*>(data.item.lParam);
+ const tstring& text = content->getText(data.item.iSubItem);
+ _tcsncpy(data.item.pszText, text.data(), std::min(text.size(), static_cast<size_t>(data.item.cchTextMax)));
+ if(text.size() < static_cast<size_t>(data.item.cchTextMax)) {
+ data.item.pszText[text.size()] = 0;
+ }
+ }
+
+ template<typename ContentType> typename std::enable_if<HasImage, void>::type handleImage(NMLVDISPINFO& data) {
+ ContentType* content = reinterpret_cast<ContentType*>(data.item.lParam);
+ data.item.iImage = content->getImage(data.item.iSubItem);
+ }
+
+ template<typename ContentType> typename std::enable_if<HasSort, void>::type handleColumnClick(int column) {
if(column != this->getSortColumn()) {
this->setSort(column, true);
} else if(this->isAscending()) {
@@ -219,11 +267,11 @@
}
}
- int handleSort(LPARAM lhs, LPARAM rhs) {
+ template<typename ContentType> typename std::enable_if<HasSort, int>::type handleSort(LPARAM lhs, LPARAM rhs) {
return ContentType::compareItems(reinterpret_cast<ContentType*>(lhs), reinterpret_cast<ContentType*>(rhs), this->getSortColumn());
}
- template<typename Ret> typename std::enable_if<customColors, Ret>::type handleCustomDraw(NMLVCUSTOMDRAW& data) {
+ template<typename ContentType> typename std::enable_if<HasColor, LRESULT>::type handleCustomDraw(NMLVCUSTOMDRAW& data) {
switch(data.nmcd.dwDrawStage) {
case CDDS_PREPAINT:
return CDRF_NOTIFYITEMDRAW;
=== modified file 'win32/forward.h'
--- win32/forward.h 2011-11-13 16:46:43 +0000
+++ win32/forward.h 2011-11-14 19:24:14 +0000
@@ -57,7 +57,7 @@
class TransferView;
-template<typename ContentType, bool managed = true, bool customColors = false>
+template<typename ContentType, bool managed = true>
class TypedTable;
template<typename ContentType>