Mercurial > foo_out_sdl
comparison foosdk/sdk/libPPUI/CListControlWithSelection.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 #include "CListControl.h" | |
| 4 | |
| 5 //! Implementation of focus/selection handling. Leaves maintaining focus/selection info to the derived class. \n | |
| 6 //! Most classes should derive from CListControlWithSelectionImpl instead. | |
| 7 class CListControlWithSelectionBase : public CListControl { | |
| 8 public: | |
| 9 typedef CListControl TParent; | |
| 10 CListControlWithSelectionBase() {} | |
| 11 BEGIN_MSG_MAP_EX(CListControlWithSelectionBase) | |
| 12 MSG_WM_CREATE(OnCreatePassThru); | |
| 13 MSG_WM_DESTROY(OnDestroyPassThru); | |
| 14 CHAIN_MSG_MAP(TParent) | |
| 15 MESSAGE_HANDLER(WM_LBUTTONDBLCLK,OnLButtonDblClk) | |
| 16 MESSAGE_HANDLER(WM_LBUTTONDOWN,OnButtonDown) | |
| 17 MESSAGE_HANDLER(WM_RBUTTONDOWN,OnButtonDown) | |
| 18 MESSAGE_HANDLER(WM_RBUTTONDBLCLK,OnButtonDown) | |
| 19 MESSAGE_HANDLER(WM_RBUTTONUP,OnRButtonUp) | |
| 20 MESSAGE_HANDLER(WM_MOUSEMOVE,OnMouseMove) | |
| 21 MESSAGE_HANDLER(WM_LBUTTONUP,OnLButtonUp) | |
| 22 MESSAGE_HANDLER(WM_KEYDOWN,OnKeyDown); | |
| 23 MESSAGE_HANDLER(WM_SYSKEYDOWN,OnKeyDown); | |
| 24 MESSAGE_HANDLER(WM_SETFOCUS,OnFocus); | |
| 25 MESSAGE_HANDLER(WM_KILLFOCUS,OnFocus); | |
| 26 MESSAGE_HANDLER(WM_TIMER,OnTimer); | |
| 27 MESSAGE_HANDLER(WM_CAPTURECHANGED,OnCaptureChanged); | |
| 28 MESSAGE_HANDLER(WM_GETDLGCODE,OnGetDlgCode); | |
| 29 MSG_WM_CHAR(OnChar) | |
| 30 END_MSG_MAP() | |
| 31 | |
| 32 virtual void SetFocusItem(t_size index) = 0; | |
| 33 virtual t_size GetFocusItem() const = 0; | |
| 34 virtual void SetGroupFocusByItem(t_size item) = 0; | |
| 35 virtual size_t GetGroupFocus2() const = 0; | |
| 36 virtual bool IsItemSelected(t_size index) const = 0; | |
| 37 virtual void SetSelection(pfc::bit_array const & affected,pfc::bit_array const & status) = 0; | |
| 38 void SelectSingle(size_t which); | |
| 39 void SetSelectionAt(size_t idx, bool bSel); | |
| 40 virtual bool SelectAll(); | |
| 41 void SelectNone(); | |
| 42 virtual void RequestMoveSelection(int delta); | |
| 43 bool MoveSelectionProbe(int delta); | |
| 44 virtual void RequestReorder( size_t const * order, size_t count ) = 0; | |
| 45 virtual void RequestRemoveSelection() = 0; | |
| 46 virtual void ExecuteDefaultAction(t_size index) = 0; | |
| 47 virtual void ExecuteDefaultActionGroup(t_size base, t_size count) { (void)base; (void)count; } | |
| 48 virtual bool ExecuteCanvasDefaultAction(CPoint pt) { (void)pt; return false; } | |
| 49 | |
| 50 virtual t_size GetSelectionStart() const = 0; | |
| 51 virtual void SetSelectionStart(t_size val) = 0; | |
| 52 //! Full hook for drag-drop loop | |
| 53 virtual void RunDragDrop(const CPoint & p_origin,bool p_isRightClick); | |
| 54 | |
| 55 //! Should RunDragDrop() be called at all? | |
| 56 virtual bool IsDragDropSupported() {return QueryDragDropTypes() != 0;} | |
| 57 | |
| 58 //! Notification, mandatory to call by SetFocusItem() implementation. \n | |
| 59 //! If overridden by subclass, must call parent. | |
| 60 virtual void OnFocusChanged(size_t oldFocus, size_t newFocus) { (void)oldFocus; (void)newFocus; } | |
| 61 virtual void OnFocusChangedGroup2(size_t baseItem) { (void)baseItem; } | |
| 62 //! Notification, mandatory to call by SetSelection() implementation. \n | |
| 63 //! If overridden by subclass, must call parent. \n | |
| 64 //! Affected: Mask indicating what items ACTUALLY CHANGED, old state to be assumed opposite of new. \n | |
| 65 //! During this call, IsSelected() already returns new state. | |
| 66 virtual void OnSelectionChanged(pfc::bit_array const& affected, pfc::bit_array const& status) { (void)affected; (void)status; } | |
| 67 | |
| 68 enum { | |
| 69 dragDrop_reorder = 1 << 0, | |
| 70 dragDrop_external = 1 << 1, | |
| 71 }; | |
| 72 | |
| 73 virtual uint32_t QueryDragDropTypes() const { return 0; } | |
| 74 struct dragDropAccept_t { | |
| 75 DWORD dwEFfect = DROPEFFECT_NONE; | |
| 76 //! Show drop mark or not? | |
| 77 bool showDropMark = false; | |
| 78 //! Drop on item or insert into list? | |
| 79 bool dropOnItem = false; | |
| 80 }; | |
| 81 //! Deprecated, use DragDropAccept2() | |
| 82 virtual DWORD DragDropAccept(IDataObject* obj, bool& showDropMark); | |
| 83 //! Return info on what you can do with this IDataObject. | |
| 84 virtual dragDropAccept_t DragDropAccept2(IDataObject*); | |
| 85 virtual pfc::com_ptr_t<IDataObject> MakeDataObject(); | |
| 86 //! Called upon drop | |
| 87 //! @param pt Drop point in screen coordinates. | |
| 88 virtual void OnDrop(IDataObject* obj, CPoint pt) { (void)obj; (void)pt; } | |
| 89 virtual DWORD DragDropSourceEffects() { return DROPEFFECT_MOVE | DROPEFFECT_COPY;} | |
| 90 virtual void DragDropSourceSucceeded(DWORD effect) { (void)effect; } | |
| 91 | |
| 92 virtual void AdjustSelectionRect(size_t item, CRect& rc) { (void)item; (void)rc; } | |
| 93 | |
| 94 bool GroupFocusActive() const {return GetGroupFocus2() != SIZE_MAX;} | |
| 95 | |
| 96 void RenderOverlay2(const CRect & p_updaterect,CDCHandle p_dc) override; | |
| 97 | |
| 98 bool IsItemFocused(t_size index) const {return GetFocusItem() == index;} | |
| 99 bool IsGroupHeaderFocused2(size_t atItem) const {return GetGroupFocus2() == atItem;} | |
| 100 void ToggleSelection(pfc::bit_array const & mask); | |
| 101 | |
| 102 size_t GetSelectedCount(pfc::bit_array const & mask,size_t max = SIZE_MAX) const; | |
| 103 size_t GetSelectedCount() const {return GetSelectedCount(pfc::bit_array_true());} | |
| 104 size_t GetSingleSel() const; | |
| 105 size_t GetFirstSelected() const; | |
| 106 size_t GetLastSelected() const; | |
| 107 | |
| 108 //! Execute default action per focus or selection depending on what's focused/selected | |
| 109 virtual void ExecuteDefaultActionByFocus(); | |
| 110 | |
| 111 void FocusToUpdateRgn(HRGN rgn); | |
| 112 | |
| 113 | |
| 114 //! Self-contained minimal drag and drop implementation for reordering list items only; dummy IDataObject presented. \n | |
| 115 //! Call from your override of RunDragDrop(), if p_isRightClick is false / left button clicked, never with right button clicked. \n | |
| 116 //! On success, use MakeDropReorderPermutation() to fetch the permutation to apply to your content. | |
| 117 bool RunReorderDragDrop(CPoint ptOrigin, CPoint & ptDrop); | |
| 118 | |
| 119 bool MakeDropReorderPermutation(pfc::array_t<t_size> & out, CPoint ptDrop) const; | |
| 120 | |
| 121 size_t GetPasteTarget( const CPoint * ptPaste = nullptr ) const; | |
| 122 | |
| 123 //! Fix coordinates of context menu point handed by WM_CONTEXTMENU, turn (-1,-1) into something that makes sense. \n | |
| 124 //! Input & output in screen coordinates, per WM_CONTEXTMENU conventions. | |
| 125 CPoint GetContextMenuPoint(LPARAM lp); | |
| 126 CPoint GetContextMenuPoint(CPoint ptGot); | |
| 127 //! Import context menu point coordinates: turn (-1,-1) to something that makes sense; \n | |
| 128 //! Returns false if clicked point was outside client area so WM_CONTEXTMENU should be left unhandled. | |
| 129 bool GetContextMenuPoint2(CPoint & ptInOut); | |
| 130 //! Returns center-of-focused-item point for context menu, in screen coordinates. | |
| 131 CPoint GetContextMenuPointDefault(); | |
| 132 | |
| 133 protected: | |
| 134 void ToggleDDScroll(bool p_state); | |
| 135 void AbortSelectDragMode() {AbortSelectDragMode(false);} | |
| 136 void RenderDropMarkerByOffset2(int offset,CDCHandle p_dc); | |
| 137 void RenderDropMarker2(CDCHandle dc, t_size item, bool bInside); | |
| 138 bool RenderDropMarkerClipped2(CDCHandle dc, const CRect & update, t_size item, bool bInside); | |
| 139 CRect DropMarkerRect(int offset) const; | |
| 140 int DropMarkerOffset(t_size marker) const; | |
| 141 void AddDropMarkToUpdateRgn(HRGN p_rgn, t_size p_index, bool bInside = false) const; | |
| 142 CRect DropMarkerUpdateRect(t_size index,bool bInside) const; | |
| 143 bool GetFocusRect(CRect & p_rect); | |
| 144 bool GetFocusRectAbs(CRect & p_rect); | |
| 145 bool IsOwnDDActive() const {return m_ownDDActive;} | |
| 146 | |
| 147 SIZE DropMarkerMargin() const; | |
| 148 void MakeDropMarkerPen(CPen & out) const; | |
| 149 | |
| 150 void EnsureVisibleRectAbs(const CRect & p_rect) override; | |
| 151 virtual size_t EvalTypeFind(); | |
| 152 | |
| 153 virtual bool AllowRangeSelect() const { return true; } | |
| 154 | |
| 155 size_t GetDropMark( ) const { return m_dropMark; } | |
| 156 bool IsDropMarkInside( ) const { return m_dropMarkInside; } | |
| 157 void SetDropMark( size_t idx, bool bInside ); | |
| 158 void ClearDropMark() { SetDropMark(SIZE_MAX, false); } | |
| 159 private: | |
| 160 int OnCreatePassThru(LPCREATESTRUCT lpCreateStruct); | |
| 161 void OnDestroyPassThru(); | |
| 162 | |
| 163 struct TDDScrollControl { | |
| 164 bool m_timerActive = false; | |
| 165 | |
| 166 enum {KTimerID = 0x35bb25af,KTimerPeriod = 25}; | |
| 167 }; | |
| 168 | |
| 169 static constexpr unsigned | |
| 170 KSelectionTimerID = 0xad8abd04, | |
| 171 KSelectionTimerPeriod = 50; | |
| 172 | |
| 173 LRESULT OnFocus(UINT,WPARAM,LPARAM,BOOL&); | |
| 174 LRESULT OnKeyDown(UINT,WPARAM,LPARAM,BOOL&); | |
| 175 LRESULT OnLButtonDblClk(UINT,WPARAM,LPARAM,BOOL&); | |
| 176 LRESULT OnButtonDown(UINT,WPARAM,LPARAM,BOOL&); | |
| 177 LRESULT OnRButtonUp(UINT,WPARAM,LPARAM,BOOL&); | |
| 178 LRESULT OnMouseMove(UINT,WPARAM,LPARAM,BOOL&); | |
| 179 LRESULT OnLButtonUp(UINT,WPARAM,LPARAM,BOOL&); | |
| 180 LRESULT OnTimer(UINT,WPARAM,LPARAM,BOOL&); | |
| 181 LRESULT OnCaptureChanged(UINT,WPARAM,LPARAM,BOOL&); | |
| 182 LRESULT OnGetDlgCode(UINT,WPARAM,LPARAM,BOOL&); | |
| 183 void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags); | |
| 184 void RunTypeFind(); | |
| 185 | |
| 186 void OnKeyDown_HomeEndHelper(bool isEnd, int p_keys); | |
| 187 void OnKeyDown_SetIndexHelper(int p_index, int p_keys); | |
| 188 void OnKeyDown_SetIndexDeltaHelper(int p_delta, int p_keys); | |
| 189 void OnKeyDown_SetIndexDeltaLineHelper(int p_delta, int p_keys); | |
| 190 void OnKeyDown_SetIndexDeltaPageHelper(int p_delta, int p_keys); | |
| 191 void SelectGroupHelper2(size_t p_groupBase,int p_keys); | |
| 192 void HandleDragSel(const CPoint & p_pt); | |
| 193 void AbortSelectDragMode(bool p_lostCapture); | |
| 194 void InitSelectDragMode(const CPoint & p_pt,bool p_rightClick = false); | |
| 195 | |
| 196 void ToggleRangeSelection(pfc::bit_array const & mask); | |
| 197 void ToggleGroupSelection2(size_t p_item); | |
| 198 | |
| 199 void HandleDDScroll(); | |
| 200 | |
| 201 void PrepareDragDrop(const CPoint & p_point,bool p_isRightClick); | |
| 202 void AbortPrepareDragDropMode(bool p_lostCapture = false); | |
| 203 | |
| 204 bool TypeFindCheck(DWORD ts = GetTickCount()) const; | |
| 205 | |
| 206 | |
| 207 protected: | |
| 208 // Spacebar handler | |
| 209 void ToggleSelectedItems(); | |
| 210 | |
| 211 void RenderItem(t_size p_item,const CRect & p_itemRect,const CRect & p_updateRect,CDCHandle p_dc) override; | |
| 212 void RenderGroupHeader2(size_t baseItem,const CRect & p_headerRect,const CRect & p_updateRect,CDCHandle p_dc) override; | |
| 213 void RenderSubItemText(t_size item, t_size subItem,const CRect & subItemRect,const CRect & updateRect,CDCHandle dc, bool allowColors) override; | |
| 214 private: | |
| 215 bool m_selectDragMode = false; | |
| 216 CPoint m_selectDragOriginAbs, m_selectDragCurrentAbs; | |
| 217 bool m_selectDragChanged, m_selectDragMoved; | |
| 218 TDDScrollControl m_ddScroll; | |
| 219 | |
| 220 bool m_prepareDragDropMode = false, m_prepareDragDropModeRightClick = false; | |
| 221 bool m_noEnsureVisible = false; | |
| 222 CPoint m_prepareDragDropOrigin; | |
| 223 bool ShouldBeginDrag(CPoint ptRef, CPoint ptNow) const; | |
| 224 | |
| 225 bool m_ownDDActive = false; | |
| 226 bool m_drawThemeText = false; | |
| 227 pfc::string8 m_typeFind; DWORD m_typeFindTS = 0; | |
| 228 | |
| 229 size_t m_dropMark = SIZE_MAX; bool m_dropMarkInside = false; | |
| 230 }; | |
| 231 | |
| 232 //! CListControlWithSelectionImpl implements virtual methods of CListControlWithSelectionBase, | |
| 233 //! maintaining focus/selection info for you. | |
| 234 class CListControlWithSelectionImpl : public CListControlWithSelectionBase { | |
| 235 public: | |
| 236 | |
| 237 enum { selectionSupportNone = 0, selectionSupportSingle, selectionSupportMulti }; | |
| 238 unsigned m_selectionSupport = selectionSupportMulti; | |
| 239 | |
| 240 void SetSelectionModeNone() { m_selectionSupport = selectionSupportNone; } | |
| 241 void SetSelectionModeSingle() { m_selectionSupport = selectionSupportSingle; } | |
| 242 void SetSelectionModeMulti() { m_selectionSupport = selectionSupportMulti; } | |
| 243 bool IsSingleSelect() const { return m_selectionSupport == selectionSupportSingle; } | |
| 244 | |
| 245 CListControlWithSelectionImpl() {} | |
| 246 void SetFocusItem(t_size index); | |
| 247 t_size GetFocusItem() const {return m_groupFocus ? SIZE_MAX : m_focus;} | |
| 248 void SetGroupFocusByItem(t_size item) override; | |
| 249 size_t GetGroupFocus2() const override; | |
| 250 bool IsItemSelected(t_size index) const {return index < m_selection.get_size() ? m_selection[index] : false;} | |
| 251 void SetSelection(pfc::bit_array const & affected,pfc::bit_array const & status); | |
| 252 virtual bool CanSelectItem(size_t index) const { (void)index; return true; } | |
| 253 t_size GetSelectionStart() const {return m_selectionStart;} | |
| 254 void SetSelectionStart(t_size val) {m_selectionStart = val;} | |
| 255 | |
| 256 void SelHandleReorder(const t_size * order, t_size count); | |
| 257 void SelHandleRemoval(const pfc::bit_array & mask, t_size oldCount); | |
| 258 void SelHandleInsertion(t_size base, t_size count, bool select); | |
| 259 void SelHandleInsertion(pfc::bit_array const & mask, size_t oldCount, size_t newCount, bool select); | |
| 260 void SelHandleReset(); | |
| 261 | |
| 262 void ReloadData() override; | |
| 263 size_t _DebugGetItemCountSel() const { return m_selection.get_size(); } | |
| 264 | |
| 265 virtual void OnItemsReordered( const size_t* order, size_t count ) override; | |
| 266 virtual void OnItemsRemoved( pfc::bit_array const & mask, size_t oldCount ) override; | |
| 267 virtual void OnItemsInsertedEx(pfc::bit_array const& mask, size_t oldCount, size_t newCount, bool bSelect) override; | |
| 268 | |
| 269 pfc::bit_array_bittable GetSelectionMask() const; // returns a standalone object holding a copy of the state | |
| 270 pfc::bit_array_table GetSelectionMaskRef() const; // returns a TEMPORARY object referencing this list's internal data | |
| 271 | |
| 272 bool SelectAll() override; | |
| 273 | |
| 274 const bool* GetSelectionArray() { RefreshSelectionSize(); return m_selection.get_ptr(); } | |
| 275 | |
| 276 protected: | |
| 277 | |
| 278 bool AllowRangeSelect() const override { return m_selectionSupport == selectionSupportMulti; } | |
| 279 private: | |
| 280 void SetSelectionImpl(pfc::bit_array const & affected,pfc::bit_array const & status); | |
| 281 void RefreshSelectionSize(); | |
| 282 void RefreshSelectionSize(t_size size); | |
| 283 pfc::array_t<bool> m_selection; | |
| 284 size_t m_focus = SIZE_MAX, m_selectionStart = SIZE_MAX; | |
| 285 bool m_groupFocus = false; | |
| 286 }; |
