]>
cygwin.com Git - cygwin-apps/setup.git/blob - ListView.cc
2 * Copyright (c) 2016 Jon Turney
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * A copy of the GNU General Public License can be found at
15 #include "LogSingleton.h"
19 // ---------------------------------------------------------------------------
20 // implements class ListView
22 // ListView Common Control
23 // ---------------------------------------------------------------------------
26 ListView::init(HWND parent
, int id
, HeaderList headers
)
30 // locate the listview control
31 hWndListView
= ::GetDlgItem(parent
, id
);
33 // configure the listview control
34 SendMessage(hWndListView
, CCM_SETVERSION
, 6, 0);
36 ListView_SetExtendedListViewStyle(hWndListView
,
37 LVS_EX_COLUMNSNAPPOINTS
| // use cxMin
38 LVS_EX_FULLROWSELECT
|
40 LVS_EX_HEADERDRAGDROP
); // headers can be re-ordered
42 // give the header control a border
43 HWND hWndHeader
= ListView_GetHeader(hWndListView
);
44 SetWindowLongPtr(hWndHeader
, GWL_STYLE
,
45 GetWindowLongPtr(hWndHeader
, GWL_STYLE
) | WS_BORDER
);
47 // ensure an initial item exists for width calculations...
52 lvi
.pszText
= const_cast <char *> ("Working...");
53 ListView_InsertItem(hWndListView
, &lvi
);
55 // populate with columns
60 ListView::initColumns(HeaderList headers_
)
62 // store HeaderList for later use
67 lvc
.mask
= LVCF_FMT
| LVCF_WIDTH
| LVCF_TEXT
| LVCF_SUBITEM
;
70 for (i
= 0; headers
[i
].text
!= 0; i
++)
73 lvc
.pszText
= const_cast <char *> (headers
[i
].text
);
75 lvc
.fmt
= headers
[i
].fmt
;
77 ListView_InsertColumn(hWndListView
, i
, &lvc
);
80 // now do some width calculations
81 for (i
= 0; headers
[i
].text
!= 0; i
++)
85 ListView_SetColumnWidth(hWndListView
, i
, LVSCW_AUTOSIZE_USEHEADER
);
86 headers
[i
].hdr_width
= ListView_GetColumnWidth(hWndListView
, i
);
91 ListView::noteColumnWidthStart()
93 dc
= GetDC (hWndListView
);
95 // we must set the font of the DC here, otherwise the width calculations
96 // will be off because the system will use the wrong font metrics
97 HANDLE sysfont
= GetStockObject (DEFAULT_GUI_FONT
);
98 SelectObject (dc
, sysfont
);
101 for (i
= 0; headers
[i
].text
!= 0; i
++)
103 headers
[i
].width
= 0;
108 ListView::noteColumnWidth(int col_num
, const std::string
& string
)
112 // A margin of 3*GetSystemMetrics(SM_CXEDGE) is used at each side of the
114 int addend
= 2*3*GetSystemMetrics(SM_CXEDGE
);
117 GetTextExtentPoint32 (dc
, string
.c_str(), string
.size(), &s
);
119 int width
= addend
+ s
.cx
;
121 if (width
> headers
[col_num
].width
)
122 headers
[col_num
].width
= width
;
126 ListView::noteColumnWidthEnd()
128 ReleaseDC(hWndListView
, dc
);
132 ListView::resizeColumns(void)
134 // ensure the last column stretches all the way to the right-hand side of the
138 for (i
= 0; headers
[i
].text
!= 0; i
++)
139 total
= total
+ headers
[i
].width
;
142 GetClientRect(hWndListView
, &r
);
143 int width
= r
.right
- r
.left
;
146 headers
[i
-1].width
+= width
- total
;
150 lvc
.mask
= LVCF_WIDTH
| LVCF_MINWIDTH
;
151 for (i
= 0; headers
[i
].text
!= 0; i
++)
154 lvc
.cx
= (headers
[i
].width
< headers
[i
].hdr_width
) ? headers
[i
].hdr_width
: headers
[i
].width
;
155 lvc
.cxMin
= headers
[i
].hdr_width
;
157 Log (LOG_BABBLE
) << "resizeColumns: " << i
<< " cx " << lvc
.cx
<< " cxMin " << lvc
.cxMin
<<endLog
;
160 ListView_SetColumn(hWndListView
, i
, &lvc
);
165 ListView::setContents(ListViewContents
*_contents
)
167 contents
= _contents
;
169 // disable redrawing of ListView
170 // (otherwise it will redraw every time a row is added, which makes this very slow)
171 SendMessage(hWndListView
, WM_SETREDRAW
, FALSE
, 0);
173 // preserve focus/selection
174 int iRow
= ListView_GetSelectionMark(hWndListView
);
179 for (i
= 0; i
< contents
->size(); i
++)
182 lvi
.mask
= LVIF_TEXT
;
185 lvi
.pszText
= LPSTR_TEXTCALLBACK
;
187 ListView_InsertItem(hWndListView
, &lvi
);
192 ListView_SetItemState(hWndListView
, iRow
, LVNI_SELECTED
| LVNI_FOCUSED
, LVNI_SELECTED
| LVNI_FOCUSED
);
193 ListView_EnsureVisible(hWndListView
, iRow
, false);
196 // enable redrawing of ListView and redraw
197 SendMessage(hWndListView
, WM_SETREDRAW
, TRUE
, 0);
198 RedrawWindow(hWndListView
, NULL
, NULL
, RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
);
201 // Helper class: The char * pointer we hand back needs to remain valid for some
202 // time after OnNotify returns, when the std::string we have retrieved has gone
203 // out of scope, so a static instance of this class maintains a local cache.
207 StringCache() : cache(NULL
), cache_size(0) { }
208 StringCache
& operator = (const std::string
& s
)
210 if ((s
.length() + 1) > cache_size
)
212 cache_size
= s
.length() + 1;
213 cache
= (char *)realloc(cache
, cache_size
);
215 strcpy(cache
, s
.c_str());
218 operator char *() const
228 ListView::OnNotify (NMHDR
*pNmHdr
, LRESULT
*pResult
)
231 Log (LOG_BABBLE
) << "ListView::OnNotify id:" << pNmHdr
->idFrom
<< " hwnd:" << pNmHdr
->hwndFrom
<< " code:" << (int)pNmHdr
->code
<< endLog
;
234 switch (pNmHdr
->code
)
236 case LVN_GETDISPINFO
:
238 NMLVDISPINFO
*pNmLvDispInfo
= (NMLVDISPINFO
*)pNmHdr
;
240 Log (LOG_BABBLE
) << "LVN_GETDISPINFO " << pNmLvDispInfo
->item
.iItem
<< endLog
;
244 int iRow
= pNmLvDispInfo
->item
.iItem
;
245 int iCol
= pNmLvDispInfo
->item
.iSubItem
;
247 static StringCache s
;
248 s
= (*contents
)[iRow
]->get_text(iCol
);
249 pNmLvDispInfo
->item
.pszText
= s
;
256 case LVN_GETEMPTYMARKUP
:
258 NMLVEMPTYMARKUP
*pNmMarkup
= (NMLVEMPTYMARKUP
*) pNmHdr
;
260 MultiByteToWideChar(CP_UTF8
, 0,
262 pNmMarkup
->szMarkup
, L_MAX_URL_LENGTH
);
271 NMITEMACTIVATE
*pNmItemAct
= (NMITEMACTIVATE
*) pNmHdr
;
273 Log (LOG_BABBLE
) << "NM_CLICK: pnmitem->iItem " << pNmItemAct
->iItem
<< " pNmItemAct->iSubItem " << pNmItemAct
->iSubItem
<< endLog
;
275 int iRow
= pNmItemAct
->iItem
;
276 int iCol
= pNmItemAct
->iSubItem
;
280 // Inform the item of the click
281 int update
= (*contents
)[iRow
]->do_action(iCol
);
283 // Update items, if needed
286 ListView_RedrawItems(hWndListView
, iRow
, iRow
+ update
-1);
295 NMLVCUSTOMDRAW
*pNmLvCustomDraw
= (NMLVCUSTOMDRAW
*)pNmHdr
;
297 switch(pNmLvCustomDraw
->nmcd
.dwDrawStage
)
300 *pResult
= CDRF_NOTIFYITEMDRAW
;
302 case CDDS_ITEMPREPAINT
:
303 *pResult
= CDRF_NOTIFYSUBITEMDRAW
;
305 case CDDS_SUBITEM
| CDDS_ITEMPREPAINT
:
307 LRESULT result
= CDRF_DODEFAULT
;
308 int iCol
= pNmLvCustomDraw
->iSubItem
;
309 int iRow
= pNmLvCustomDraw
->nmcd
.dwItemSpec
;
311 switch (headers
[iCol
].type
)
314 case ListView::ControlType::text
:
315 result
= CDRF_DODEFAULT
;
318 case ListView::ControlType::checkbox
:
320 // get the subitem text
322 ListView_GetItemText(hWndListView
, iRow
, iCol
, buf
, _countof(buf
));
324 // map the subitem text to a checkbox state
325 UINT state
= DFCS_BUTTONCHECK
| DFCS_FLAT
;
326 if (buf
[0] == '\0') // empty
328 result
= CDRF_DODEFAULT
;
331 else if (buf
[0] == 'y') // yes
332 state
|= DFCS_CHECKED
;
333 else if ((buf
[0] == 'n') && (buf
[1] == 'o')) // no
336 state
|= DFCS_INACTIVE
;
338 // erase and draw a checkbox
340 ListView_GetSubItemRect(hWndListView
, iRow
, iCol
, LVIR_BOUNDS
, &r
);
341 HBRUSH hBrush
= CreateSolidBrush(ListView_GetBkColor(hWndListView
));
342 FillRect(pNmLvCustomDraw
->nmcd
.hdc
, &r
, hBrush
);
343 DeleteObject(hBrush
);
344 DrawFrameControl(pNmLvCustomDraw
->nmcd
.hdc
, &r
, DFC_BUTTON
, state
);
346 result
= CDRF_SKIPDEFAULT
;
362 ListView::empty(void)
364 ListView_DeleteAllItems(hWndListView
);
368 ListView::setEmptyText(const char *text
)
370 empty_list_text
= text
;
This page took 0.053228 seconds and 6 git commands to generate.