linuxdcpp-team team mailing list archive
-
linuxdcpp-team team
-
Mailing list archive
-
Message #04947
[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 2717: add icons next to list-view group headers
------------------------------------------------------------
revno: 2717
committer: poy <poy@xxxxxxxxxx>
branch nick: trunk
timestamp: Tue 2011-12-13 22:15:23 +0100
message:
add icons next to list-view group headers
modified:
dwt/include/dwt/widgets/Table.h
dwt/src/widgets/Table.cpp
win32/FavHubsFrame.cpp
win32/StylesPage.cpp
--
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 'dwt/include/dwt/widgets/Table.h'
--- dwt/include/dwt/widgets/Table.h 2011-11-19 00:10:54 +0000
+++ dwt/include/dwt/widgets/Table.h 2011-12-13 21:15:23 +0000
@@ -281,17 +281,13 @@
*/
void setColumnWidth( unsigned columnNo, int width );
- /** Enable group support (only for ComCtrl 6), and insert each given group. The group id used
- will be the position of the group in the vector. */
+ /** Enable group support, and insert each given group. The group id used as the "index" param
+ of the insert function will be the position of the group in the vector given here.
+ Once a table has been set into grouped mode, it cannot be switched back to non-grouped mode. */
void setGroups(const std::vector<tstring>& groups);
- tstring getGroup(unsigned id) const;
bool isGrouped() const { return grouped; }
- /** tell dwt to take over painting of group headers in order to allow custom colors that match
- the background. the theme will be respected. */
- void handleGroupDraw();
-
/// Returns the checked state of the given row
/** A list view can have checkboxes in each row, if the checkbox for the given
* row is CHECKED this funtion returns true.
@@ -397,19 +393,22 @@
/** normalImageList is the image list that contains the images
* for the data grid icons in Icon View (big icons).
*/
- void setNormalImageList( ImageListPtr normalImageList );
+ void setNormalImageList(ImageListPtr imageList);
/// Set the small image list for the Data Grid.
/** smallImageList is the image list that contains the images
* for the data grid icons in Report, List & Small Icon Views.
*/
- void setSmallImageList( ImageListPtr smallImageList );
+ void setSmallImageList(ImageListPtr imageList);
/// Set the state image list for the Data Grid.
/** stateImageList is the image list that contains the images
* for the data grid icons states.
*/
- void setStateImageList( ImageListPtr stateImageList );
+ void setStateImageList(ImageListPtr imageList);
+
+ /** Set the image list to find icons from when adding groups. Only available on >= Visa. */
+ void setGroupImageList(ImageListPtr imageList);
/// Change the view for the Data Grid.
/** The view parameter can be one of LVS_ICON, LVS_SMALLICON, LVS_LIST or
@@ -486,6 +485,7 @@
ImageListPtr itsNormalImageList;
ImageListPtr itsSmallImageList;
ImageListPtr itsStateImageList;
+ ImageListPtr groupImageList;
// If true the grid is in "read only mode" meaning that cell values cannot be edited.
// A simpler version of defining a beenValidate always returning false
@@ -501,6 +501,7 @@
static int CALLBACK compareFuncCallback( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort );
void setIndex(LVITEM& item, int index) const;
+ void initGroupSupport();
void updateArrow();
#ifdef PORT_ME
// Private validate function, this ones returns the "read only" property of the list
=== modified file 'dwt/src/widgets/Table.cpp'
--- dwt/src/widgets/Table.cpp 2011-11-16 18:12:07 +0000
+++ dwt/src/widgets/Table.cpp 2011-12-13 21:15:23 +0000
@@ -45,6 +45,38 @@
const TCHAR Table::windowClass[] = WC_LISTVIEW;
+/* the following dance adds Vista members to LVGROUP (notably iTitleImage to have group icons)
+without requiring a global switch of WINVER / _WIN32_WINNT / etc to Vista values. */
+typedef LVGROUP legacyLVGROUP;
+#if(_WIN32_WINNT < 0x600)
+struct LVGROUP_ : LVGROUP {
+ LPWSTR pszSubtitle;
+ UINT cchSubtitle;
+ LPWSTR pszTask;
+ UINT cchTask;
+ LPWSTR pszDescriptionTop;
+ UINT cchDescriptionTop;
+ LPWSTR pszDescriptionBottom;
+ UINT cchDescriptionBottom;
+ int iTitleImage;
+ int iExtendedImage;
+ int iFirstItem;
+ UINT cItems;
+ LPWSTR pszSubsetTitle;
+ UINT cchSubsetTitle;
+ LVGROUP_(const LVGROUP& lvg) : LVGROUP(lvg) { }
+};
+#define LVGROUP LVGROUP_
+#define LVGF_TITLEIMAGE 0x00001000
+#define ListView_SetGroupHeaderImageList(hwnd, himl) \
+ (HIMAGELIST)SNDMSG((hwnd), LVM_SETIMAGELIST, (WPARAM)LVSIL_GROUPHEADER, (LPARAM)(HIMAGELIST)(himl))
+#endif
+
+namespace { legacyLVGROUP makeLVGROUP() {
+ legacyLVGROUP lvg = { util::win32::ensureVersion(util::win32::VISTA) ? sizeof(LVGROUP) : sizeof(legacyLVGROUP) };
+ return lvg;
+} }
+
Table::Seed::Seed() :
BaseType::Seed(WS_CHILD | WS_TABSTOP | LVS_REPORT),
font(0),
@@ -294,12 +326,16 @@
}
void Table::setGroups(const std::vector<tstring>& groups) {
- grouped = ListView_EnableGroupView(handle(), TRUE) >= 0;
- if(!grouped)
- return;
-
- LVGROUP group = { sizeof(LVGROUP) };
- for(std::vector<tstring>::const_iterator i = groups.begin(), iend = groups.end(); i != iend; ++i) {
+ if(!grouped) {
+ grouped = ListView_EnableGroupView(handle(), TRUE) >= 0;
+ if(!grouped)
+ return;
+
+ initGroupSupport();
+ }
+
+ LVGROUP group = makeLVGROUP();
+ for(auto i = groups.cbegin(), iend = groups.cend(); i != iend; ++i) {
if(i->empty()) {
group.mask = LVGF_GROUPID;
group.pszHeader = 0;
@@ -307,6 +343,10 @@
group.mask = LVGF_GROUPID | LVGF_HEADER;
group.pszHeader = const_cast<LPWSTR>(i->c_str());
}
+ if(groupImageList) {
+ group.mask |= LVGF_TITLEIMAGE;
+ group.iTitleImage = group.iGroupId;
+ }
if(ListView_InsertGroup(handle(), -1, &group) == -1) {
throw DWTException("Group insertion failed in Table::setGroups");
}
@@ -316,22 +356,16 @@
grouped = true;
}
-tstring Table::getGroup(unsigned id) const {
- if(grouped) {
- LVGROUP group = { sizeof(LVGROUP), LVGF_HEADER };
- if(ListView_GetGroupInfo(handle(), id, &group) == static_cast<int>(id)) {
- return tstring(group.pszHeader, group.cchHeader);
- }
- }
- return tstring();
-}
+void Table::initGroupSupport() {
+ /* fiddle with the painting of group headers to allow custom colors that match the background (the
+ theme will be respected). */
-void Table::handleGroupDraw() {
theme.load(VSCLASS_LISTVIEW, this);
onCustomDraw([this](NMLVCUSTOMDRAW& data) -> LRESULT {
- if(!grouped || data.dwItemType != LVCDI_GROUP)
+ if(data.dwItemType != LVCDI_GROUP)
return CDRF_DODEFAULT;
+
switch(data.nmcd.dwDrawStage) {
case CDDS_PREPAINT:
{
@@ -346,20 +380,57 @@
/* the theme color and the bg color are too close to each other; start by
filling the canvas with an invert of the bg, then invert the whole canvas after
everything has been drawn (after CDDS_POSTPAINT). */
+ FreeCanvas canvas(data.nmcd.hdc);
+ Brush brush(0xFFFFFF - bgColor);
+
Rectangle rect(data.rcText);
if(!theme && util::win32::ensureVersion(util::win32::VISTA))
rect.size.y += 6;
- FreeCanvas(data.nmcd.hdc).fill(rect, Brush(0xFFFFFF - bgColor));
+
+ LONG iconPos = 0;
+
+ if(groupImageList) {
+ // don't invert the icon. let's find out where it is placed...
+ if(theme) {
+ auto temp = rect;
+ theme.formatRect(canvas, LVP_GROUPHEADER, LVGH_OPEN, temp);
+ iconPos = temp.left() - rect.left();
+ }
+ if(iconPos <= 0)
+ iconPos = 10; // assume a 10px margin for unthemed visual styles
+
+ rect.size.x = iconPos;
+ canvas.fill(rect, brush);
+
+ rect.pos.x = rect.right() + 16;
+ rect.size.x = data.rcText.right - rect.pos.x;
+ }
+
+ canvas.fill(rect, brush);
// set a flag so we don't have to re-compare colors on CDDS_POSTPAINT.
- data.nmcd.lItemlParam = 1;
+ data.nmcd.lItemlParam = std::max(iconPos, 0L) + 1;
}
break;
}
+
case CDDS_POSTPAINT:
{
if(data.nmcd.lItemlParam) {
- FreeCanvas(data.nmcd.hdc).invert(Region(Rectangle(data.rcText)));
+ LONG iconPos = data.nmcd.lItemlParam - 1;
+
+ FreeCanvas canvas(data.nmcd.hdc);
+ Rectangle rect(data.rcText);
+
+ if(iconPos > 0) {
+ rect.size.x = iconPos;
+ canvas.invert(Region(rect));
+
+ rect.pos.x = rect.right() + 16;
+ rect.size.x = data.rcText.right - rect.pos.x;
+ }
+
+ canvas.invert(Region(rect));
}
break;
}
@@ -415,6 +486,13 @@
ListView_SetImageList( handle(), imageList->getImageList(), LVSIL_STATE );
}
+void Table::setGroupImageList(ImageListPtr imageList) {
+ if(util::win32::ensureVersion(util::win32::VISTA)) {
+ groupImageList = imageList;
+ ListView_SetGroupHeaderImageList(handle(), groupImageList->handle());
+ }
+}
+
void Table::setView( int view ) {
if ( ( view & LVS_TYPEMASK ) != view )
{
=== modified file 'win32/FavHubsFrame.cpp'
--- win32/FavHubsFrame.cpp 2011-11-16 18:12:07 +0000
+++ win32/FavHubsFrame.cpp 2011-12-13 21:15:23 +0000
@@ -80,7 +80,6 @@
hubs->onDblClicked([this] { handleDoubleClick(); });
hubs->onKeyDown([this](int c) { return handleKeyDown(c); });
hubs->onContextMenu([this](const dwt::ScreenCoordinate &sc) { return handleContextMenu(sc); });
- hubs->handleGroupDraw();
}
{
=== modified file 'win32/StylesPage.cpp'
--- win32/StylesPage.cpp 2011-12-13 17:16:36 +0000
+++ win32/StylesPage.cpp 2011-12-13 21:15:23 +0000
@@ -92,7 +92,12 @@
seed.style &= ~LVS_SHOWSELALWAYS;
seed.style |= LVS_SINGLESEL | LVS_NOCOLUMNHEADER;
table = cur->addChild(Table::Seed(seed));
- table->handleGroupDraw();
+
+ dwt::ImageListPtr images(new dwt::ImageList(dwt::Point(16, 16)));
+ images->add(*WinUtil::createIcon(IDI_DCPP, 16));
+ images->add(*WinUtil::createIcon(IDI_NET_STATS, 16)); /// @todo better icon for the "transfers" group?
+ images->add(*WinUtil::createIcon(IDI_USERS, 16));
+ table->setGroupImageList(images);
}
{
@@ -418,7 +423,9 @@
void StylesPage::handleCustomTextColor() {
auto data = table->getSelectedData();
data->customTextColor = customTextColor->getChecked();
- data->textColor = getTextColor(data);
+ if(data->customTextColor) {
+ data->textColor = getTextColor(data);
+ }
update(data);
handleSelectionChanged();
}
@@ -435,7 +442,9 @@
void StylesPage::handleCustomBgColor() {
auto data = table->getSelectedData();
data->customBgColor = customBgColor->getChecked();
- data->bgColor = getBgColor(data);
+ if(data->customBgColor) {
+ data->bgColor = getBgColor(data);
+ }
update(data);
handleSelectionChanged();
}