comparison foosdk/sdk/libPPUI/CListControlHeaderImpl.h @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
comparison
equal deleted inserted replaced
0:e9bb126753e7 1:20d02a178406
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 };