|
1
|
1 #pragma once
|
|
|
2
|
|
|
3 class CListCell;
|
|
|
4
|
|
|
5 class CListControlHeaderImpl : public CListControlFontOps {
|
|
|
6 private:
|
|
|
7 typedef CListControlFontOps TParent;
|
|
|
8 public:
|
|
|
9 CListControlHeaderImpl() {}
|
|
|
10
|
|
|
11 BEGIN_MSG_MAP_EX(CListControlHeaderImpl)
|
|
|
12 MSG_WM_THEMECHANGED(OnThemeChangedPT)
|
|
|
13 MSG_WM_LBUTTONDBLCLK(OnLButtonDblClk)
|
|
|
14 MESSAGE_RANGE_HANDLER_EX(WM_MOUSEFIRST, WM_MOUSELAST, MousePassThru);
|
|
|
15 MSG_WM_MOUSELEAVE(OnMouseLeave)
|
|
|
16 MSG_WM_CTLCOLORSTATIC(OnCtlColorStatic);
|
|
|
17 MESSAGE_HANDLER(WM_KEYDOWN,OnKeyDown);
|
|
|
18 MESSAGE_HANDLER(WM_SYSKEYDOWN,OnKeyDown);
|
|
|
19 MESSAGE_HANDLER_EX(WM_SIZE,OnSizePassThru);
|
|
|
20 NOTIFY_CODE_HANDLER(HDN_ITEMCHANGED,OnHeaderItemChanged);
|
|
|
21 NOTIFY_CODE_HANDLER(HDN_ENDDRAG,OnHeaderEndDrag);
|
|
|
22 NOTIFY_CODE_HANDLER(HDN_ITEMCLICK,OnHeaderItemClick);
|
|
|
23 NOTIFY_CODE_HANDLER(HDN_DIVIDERDBLCLICK,OnDividerDoubleClick);
|
|
|
24 NOTIFY_CODE_HANDLER_EX(NM_CUSTOMDRAW, OnHeaderCustomDraw);
|
|
|
25 MSG_WM_SETCURSOR(OnSetCursor);
|
|
|
26 MSG_WM_MOUSEMOVE(OnMouseMove)
|
|
|
27 MSG_WM_DESTROY(OnDestroy)
|
|
|
28 MSG_WM_ENABLE(OnEnable)
|
|
|
29 MSG_WM_KILLFOCUS(OnKillFocus)
|
|
|
30 MSG_WM_WINDOWPOSCHANGED(OnWindowPosChanged)
|
|
|
31 CHAIN_MSG_MAP(TParent)
|
|
|
32 END_MSG_MAP()
|
|
|
33
|
|
|
34 typedef uint32_t cellState_t;
|
|
|
35 typedef CListCell * cellType_t;
|
|
|
36
|
|
|
37 int GetHeaderItemWidth( int which );
|
|
|
38 void InitializeHeaderCtrl(DWORD flags = HDS_FULLDRAG);
|
|
|
39 void InitializeHeaderCtrlSortable() {InitializeHeaderCtrl(HDS_FULLDRAG | HDS_BUTTONS);}
|
|
|
40 CHeaderCtrl GetHeaderCtrl() const {return m_header;}
|
|
|
41 void SetSortIndicator( size_t whichColumn, bool isUp );
|
|
|
42 void ClearSortIndicator();
|
|
|
43
|
|
|
44 bool IsHeaderEnabled() const {return m_header.m_hWnd != NULL;}
|
|
|
45 void ResetColumns(bool update = true);
|
|
|
46
|
|
|
47 static constexpr uint32_t columnWidthMax = (uint32_t)INT32_MAX,
|
|
|
48 columnWidthAuto = UINT32_MAX,
|
|
|
49 columnWidthAutoUseContent = UINT32_MAX - 1;
|
|
|
50
|
|
|
51 void AddColumn(const char * label, uint32_t widthPixels, DWORD fmtFlags = HDF_LEFT,bool update = true);
|
|
|
52 //! Extended AddColumn, specifies width in pixels @ 96DPI instead of screen-specific pixels
|
|
|
53 void AddColumnEx( const char * label, uint32_t widthPixelsAt96DPI, DWORD fmtFlags = HDF_LEFT, bool update = true );
|
|
|
54 //! Extended AddColumn, specifies width in Dialog Length Units (DLU), assumes parent of this list to be a dialog window.
|
|
|
55 void AddColumnDLU( const char * label, uint32_t widthDLU, DWORD fmtFlags = HDF_LEFT, bool update = true );
|
|
|
56 //! Extended AddColumn, specifies width as floating-point value of pixels at 96DPI. \n
|
|
|
57 //! For DPI-safe storage of user's column widths.
|
|
|
58 void AddColumnF( const char * label, float widthF, DWORD fmtFlags = HDF_LEFT, bool update = true );
|
|
|
59 void AddColumnAutoWidth( const char * label, DWORD fmtFlags = HDF_LEFT, bool bUpdate = true) { AddColumn(label, columnWidthAuto, fmtFlags, bUpdate); }
|
|
|
60 bool DeleteColumn(size_t index, bool updateView = true);
|
|
|
61 void DeleteColumns( pfc::bit_array const & mask, bool updateView = true);
|
|
|
62 void ResizeColumn(t_size index, t_uint32 widthPixels, bool updateView = true);
|
|
|
63 void SetColumn( size_t which, const char * title, DWORD fmtFlags = HDF_LEFT, bool updateView = true);
|
|
|
64 void GetColumnText(size_t which, pfc::string_base & out) const;
|
|
|
65
|
|
|
66 uint32_t GetOptimalColumnWidth( size_t index ) const;
|
|
|
67 uint32_t GetOptimalColumnWidthFixed( const char * fixedText, bool pad = true) const;
|
|
|
68 uint32_t GetColumnsBlankWidth( size_t colExclude = SIZE_MAX ) const;
|
|
|
69 void SizeColumnToContent( size_t which, uint32_t minWidth );
|
|
|
70 void SizeColumnToContentFillBlank( size_t which );
|
|
|
71
|
|
|
72 //! If creating a custom headerless multi column scheme, override these to manipulate your columns
|
|
|
73 virtual size_t GetColumnCount() const;
|
|
|
74 virtual uint32_t GetSubItemWidth(size_t subItem) const;
|
|
|
75 //! Returns column width as a floating-point value of pixels at 96DPI. \n
|
|
|
76 //! For DPI-safe storage of user's column widths.
|
|
|
77 float GetColumnWidthF( size_t subItem ) const;
|
|
|
78 //! Indicate how many columns a specific row/column cell spans\n
|
|
|
79 //! This makes sense only if the columns can't be user-reordered
|
|
|
80 virtual size_t GetSubItemSpan(size_t row, size_t column) const;
|
|
|
81
|
|
|
82 t_size GetSubItemOrder(t_size subItem) const;
|
|
|
83 int GetItemWidth() const override;
|
|
|
84
|
|
|
85 void SetHeaderFont(HFONT font);
|
|
|
86 protected:
|
|
|
87 CRect GetClientRectHook() const override;
|
|
|
88 void RenderBackground(CDCHandle dc, CRect const& rc) override;
|
|
|
89
|
|
|
90 struct GetOptimalWidth_Cache {
|
|
|
91 //! For temporary use.
|
|
|
92 pfc::string8_fastalloc m_stringTemp, m_stringTempFixAmpersands;
|
|
|
93 //! For temporary use.
|
|
|
94 pfc::stringcvt::string_wide_from_utf8_t<pfc::alloc_fast_aggressive> m_convertTemp;
|
|
|
95 //! Our DC for measuring text. Correct font pre-selected.
|
|
|
96 CDCHandle m_dc;
|
|
|
97
|
|
|
98 t_uint32 GetStringTempWidth();
|
|
|
99 };
|
|
|
100
|
|
|
101 void UpdateHeaderLayout();
|
|
|
102 void OnViewOriginChange(CPoint p_delta) override;
|
|
|
103 void RenderItemText(t_size item,const CRect & itemRect,const CRect & updateRect,CDCHandle dc, bool allowColors) override;
|
|
|
104 void RenderGroupHeaderText2(size_t baseItem,const CRect & headerRect,const CRect & updateRect,CDCHandle dc) override;
|
|
|
105 void RenderGroupOverlay(size_t baseItem, const CRect& p_groupWhole, const CRect& p_updateRect, CDCHandle p_dc) override;
|
|
|
106 void UpdateGroupOverlayColumnByID(groupID_t groupID, size_t subItem);
|
|
|
107
|
|
|
108 //! Converts an item/subitem rect to a rect in which the text should be rendered, removing spacing to the left/right of the text.
|
|
|
109 virtual CRect GetItemTextRectHook(size_t item, size_t subItem, CRect const & itemRect) const;
|
|
|
110 CRect GetItemTextRect(CRect const & itemRect) const;
|
|
|
111 //! Override for custom spacing to the left/right of the text in each column.
|
|
|
112 virtual t_uint32 GetColumnSpacing() const {return MulDiv(4,m_dpi.cx,96);}
|
|
|
113 //! Override for column-header-click sorting.
|
|
|
114 virtual void OnColumnHeaderClick(t_size index) { (void)index; }
|
|
|
115 //! Override to supply item labels.
|
|
|
116 virtual bool GetSubItemText(t_size item, t_size subItem, pfc::string_base& out) const { (void)item; (void)subItem; (void)out; return false; }
|
|
|
117 //! Override if you support groups.
|
|
|
118 virtual bool GetGroupHeaderText2(size_t baseItem, pfc::string_base& out) const { (void)baseItem; (void)out; return false; }
|
|
|
119 //! Override optionally.
|
|
|
120 virtual void RenderSubItemText(t_size item, t_size subItem,const CRect & subItemRect,const CRect & updateRect,CDCHandle dc, bool allowColors);
|
|
|
121 virtual void RenderGroupOverlayColumn(size_t baseItem, size_t subItem, const CRect& p_groupWhole, const CRect& p_updateRect, CDCHandle p_dc) { (void)baseItem; (void)subItem; (void)p_groupWhole; (void)p_updateRect; (void)p_dc; }
|
|
|
122
|
|
|
123 virtual void OnColumnsChanged();
|
|
|
124
|
|
|
125 virtual t_uint32 GetOptimalSubItemWidth(t_size item, t_size subItem, GetOptimalWidth_Cache & cache) const;
|
|
|
126
|
|
|
127 virtual t_uint32 GetOptimalGroupHeaderWidth2(size_t baseItem) const;
|
|
|
128
|
|
|
129
|
|
|
130 bool GetItemAtPointAbsEx( CPoint pt, size_t & outItem, size_t & outSubItem ) const;
|
|
|
131 cellType_t GetCellTypeAtPointAbs( CPoint pt ) const;
|
|
|
132 virtual cellType_t GetCellType( size_t item, size_t subItem ) const;
|
|
|
133 virtual bool AllowTypeFindInCell( size_t item, size_t subItem ) const;
|
|
|
134 virtual bool GetCellTypeSupported() const { return false; } // optimization hint, some expensive checks can be suppressed if cell types are not used for this view
|
|
|
135 virtual bool GetCellCheckState(size_t item, size_t subItem) const { (void)item; (void)subItem; return false; }
|
|
|
136 virtual void SetCellCheckState(size_t item, size_t subItem, bool value);
|
|
|
137 virtual bool ToggleSelectedItemsHook(const pfc::bit_array & mask) override;
|
|
|
138
|
|
|
139 virtual bool RenderCellImageTest(size_t item, size_t subItem) const { (void)item; (void)subItem; return false; }
|
|
|
140 virtual void RenderCellImage(size_t item, size_t subItem, CDCHandle, const CRect&) const { (void)item; (void)subItem; }
|
|
|
141
|
|
|
142 t_uint32 GetOptimalColumnWidth(t_size which, GetOptimalWidth_Cache & cache) const;
|
|
|
143 t_uint32 GetOptimalSubItemWidthSimple(t_size item, t_size subItem) const;
|
|
|
144
|
|
|
145 void AutoColumnWidths(const pfc::bit_array & mask,bool expandLast = false);
|
|
|
146 void AutoColumnWidths() {AutoColumnWidths(pfc::bit_array_true());}
|
|
|
147 void AutoColumnWidth(t_size which) {AutoColumnWidths(pfc::bit_array_one(which));}
|
|
|
148
|
|
|
149 virtual bool OnColumnHeaderDrag(t_size index, t_size newOrder);
|
|
|
150
|
|
|
151 void OnItemClicked(t_size item, CPoint pt) override;
|
|
|
152 virtual void OnSubItemClicked(t_size item, t_size subItem,CPoint pt);
|
|
|
153 bool OnClickedSpecialHitTest(CPoint pt) override;
|
|
|
154 bool OnClickedSpecial(DWORD status, CPoint pt) override;
|
|
|
155 static bool CellTypeUsesSpecialHitTests( cellType_t ct );
|
|
|
156
|
|
|
157
|
|
|
158 CRect GetSubItemRectAbs(t_size item,t_size subItem) const;
|
|
|
159 CRect GetSubItemRect(t_size item,t_size subItem) const;
|
|
|
160
|
|
|
161 t_size SubItemFromPointAbs(CPoint pt) const;
|
|
|
162
|
|
|
163 static bool CellTypeReactsToMouseOver( cellType_t ct );
|
|
|
164 virtual CRect CellHotRect( size_t item, size_t subItem, cellType_t ct, CRect rcCell );
|
|
|
165 CRect CellHotRect( size_t item, size_t subItem, cellType_t ct );
|
|
|
166 virtual double CellTextScale(size_t item, size_t subItem) { (void)item; (void)subItem; return 1; }
|
|
|
167 virtual bool IsSubItemGrayed(size_t item, size_t subItem) { (void)item; (void)subItem; return !this->IsWindowEnabled(); }
|
|
|
168
|
|
|
169 virtual void CellTrackMouseMove(size_t item, size_t subItem, UINT msg, DWORD status, CPoint pt) { (void)item; (void)subItem; (void)msg; (void)status; (void)pt; }
|
|
|
170
|
|
|
171 // HDF_* constants for this column, override when not using list header control. Used to control text alignment.
|
|
|
172 virtual DWORD GetColumnFormat(t_size which) const;
|
|
|
173 void SetColumnFormat(t_size which,DWORD format);
|
|
|
174 void SetColumnSort(t_size which, bool isUp);
|
|
|
175
|
|
|
176 std::vector<int> GetColumnOrderArray() const;
|
|
|
177
|
|
|
178 bool AllowScrollbar(bool vertical) const override;
|
|
|
179
|
|
|
180 void RenderItemBackground(CDCHandle p_dc,const CRect & p_itemRect,size_t item, uint32_t bkColor) override;
|
|
|
181
|
|
|
182 void ColumnWidthFix(); // Call RecalcItemWidth() / ProcessAutoWidth()
|
|
|
183
|
|
|
184 void ReloadData() override;
|
|
|
185
|
|
|
186 size_t HotItem() const { return m_hotItem; }
|
|
|
187 size_t HotSubItem() const { return m_hotSubItem; }
|
|
|
188
|
|
|
189 virtual void RequestEditItem(size_t item, size_t subItem);
|
|
|
190 private:
|
|
|
191 void OnLButtonDblClk(UINT nFlags, CPoint point);
|
|
|
192 void OnThemeChangedPT();
|
|
|
193 void OnEnable(BOOL) { Invalidate(); }
|
|
|
194 HBRUSH OnCtlColorStatic(CDCHandle dc, CStatic wndStatic);
|
|
|
195 void ProcessColumnsChange() { OnColumnsChanged();}
|
|
|
196 LRESULT OnSizePassThru(UINT,WPARAM,LPARAM);
|
|
|
197 LRESULT OnHeaderItemClick(int,LPNMHDR,BOOL&);
|
|
|
198 LRESULT OnHeaderCustomDraw(LPNMHDR);
|
|
|
199 LRESULT OnDividerDoubleClick(int,LPNMHDR,BOOL&);
|
|
|
200 LRESULT OnHeaderItemChanged(int,LPNMHDR,BOOL&);
|
|
|
201 LRESULT OnHeaderEndDrag(int,LPNMHDR,BOOL&);
|
|
|
202 LRESULT OnKeyDown(UINT,WPARAM,LPARAM,BOOL&);
|
|
|
203 void OnDestroy();
|
|
|
204 BOOL OnSetCursor(CWindow wnd, UINT nHitTest, UINT message);
|
|
|
205 void OnMouseMove(UINT nFlags, CPoint point);
|
|
|
206
|
|
|
207 void RecalcItemWidth(); // FIXED width math
|
|
|
208 void ProcessAutoWidth(); // DYNAMIC width math
|
|
|
209
|
|
|
210 bool m_ownColumnsChange = false;
|
|
|
211
|
|
|
212 int m_itemWidth = 0;
|
|
|
213 int m_clientWidth = 0;
|
|
|
214 CHeaderCtrl m_header;
|
|
|
215 bool m_headerDark = false;
|
|
|
216 CStatic m_headerLine;
|
|
|
217
|
|
|
218 bool HaveAutoWidthColumns() const;
|
|
|
219 bool HaveAutoWidthContentColumns() const;
|
|
|
220
|
|
|
221 struct colRuntime_t {
|
|
|
222 bool m_autoWidth = false;
|
|
|
223 bool m_autoWidthContent = false;
|
|
|
224 int m_widthPixels = 0;
|
|
|
225 uint32_t m_userWidth = 0;
|
|
|
226 std::string m_text;
|
|
|
227
|
|
|
228 bool autoWidth() const { return m_userWidth > columnWidthMax; }
|
|
|
229 bool autoWidthContent() const { return m_userWidth == columnWidthAutoUseContent; }
|
|
|
230 bool autoWidthPlain() const { return m_userWidth == columnWidthAuto; }
|
|
|
231 };
|
|
|
232
|
|
|
233 std::vector<colRuntime_t> m_colRuntime;
|
|
|
234
|
|
|
235
|
|
|
236 //for group headers
|
|
|
237 GdiplusScope m_gdiPlusScope;
|
|
|
238
|
|
|
239 void SetPressedItem(size_t row, size_t column);
|
|
|
240 void ClearPressedItem() {SetPressedItem(SIZE_MAX, SIZE_MAX);}
|
|
|
241 void SetHotItem( size_t row, size_t column );
|
|
|
242 void ClearHotItem() { SetHotItem(SIZE_MAX, SIZE_MAX); }
|
|
|
243
|
|
|
244 virtual void HotItemChanged(size_t row, size_t column) { (void)row; (void)column; }
|
|
|
245 virtual void PressedItemChanged(size_t row, size_t column) { (void)row; (void)column; }
|
|
|
246
|
|
|
247 size_t m_pressedItem = SIZE_MAX, m_pressedSubItem = SIZE_MAX;
|
|
|
248 size_t m_hotItem = SIZE_MAX, m_hotSubItem = SIZE_MAX;
|
|
|
249
|
|
|
250 private:
|
|
|
251 // ==== mySetCapture stuff ====
|
|
|
252 // SetCapture()-like functionality used for tracking of hot fields.
|
|
|
253 // Not a part of the API, do not reuse in subclasses.
|
|
|
254 void mySetCapture(CaptureProc_t proc);
|
|
|
255 void myReleaseCapture();
|
|
|
256
|
|
|
257 void TrackMouseLeave();
|
|
|
258
|
|
|
259 void mySetCaptureMsgHandled(BOOL v) { this->SetMsgHandled(v); }
|
|
|
260 CaptureProc_t m_captureProc;
|
|
|
261
|
|
|
262 void OnMouseLeave();
|
|
|
263 void OnKillFocus(CWindow);
|
|
|
264 void OnWindowPosChanged(LPWINDOWPOS);
|
|
|
265 LRESULT MousePassThru(UINT, WPARAM, LPARAM);
|
|
|
266 };
|