Files
foobar2000-sdk/libPPUI/CListControlHeaderImpl.h
2021-12-14 00:28:25 -07:00

225 lines
9.8 KiB
C++

#pragma once
class CListCell;
class CListControlHeaderImpl : public CListControlFontOps {
private:
typedef CListControlFontOps TParent;
public:
CListControlHeaderImpl() {}
BEGIN_MSG_MAP_EX(CListControlHeaderImpl)
MSG_WM_CTLCOLORSTATIC(OnCtlColorStatic);
MESSAGE_HANDLER(WM_KEYDOWN,OnKeyDown);
MESSAGE_HANDLER(WM_SYSKEYDOWN,OnKeyDown);
MESSAGE_HANDLER_EX(WM_SIZE,OnSizePassThru);
NOTIFY_CODE_HANDLER(HDN_ITEMCHANGED,OnHeaderItemChanged);
NOTIFY_CODE_HANDLER(HDN_ENDDRAG,OnHeaderEndDrag);
NOTIFY_CODE_HANDLER(HDN_ITEMCLICK,OnHeaderItemClick);
NOTIFY_CODE_HANDLER(HDN_DIVIDERDBLCLICK,OnDividerDoubleClick);
MSG_WM_SETCURSOR(OnSetCursor);
MSG_WM_MOUSEMOVE(OnMouseMove)
MSG_WM_DESTROY(OnDestroy)
MSG_WM_ENABLE(OnEnable)
CHAIN_MSG_MAP(TParent)
END_MSG_MAP()
typedef uint32_t cellState_t;
typedef CListCell * cellType_t;
int GetHeaderItemWidth( int which );
void InitializeHeaderCtrl(DWORD flags = HDS_FULLDRAG);
void InitializeHeaderCtrlSortable() {InitializeHeaderCtrl(HDS_FULLDRAG | HDS_BUTTONS);}
CHeaderCtrl GetHeaderCtrl() const {return m_header;}
void SetSortIndicator( size_t whichColumn, bool isUp );
void ClearSortIndicator();
bool IsHeaderEnabled() const {return m_header.m_hWnd != NULL;}
void ResetColumns(bool update = true);
enum {
columnWidthMax = (uint32_t)INT32_MAX,
columnWidthAuto = UINT32_MAX,
columnWidthAutoUseContent = UINT32_MAX-1,
};
void AddColumn(const char * label, uint32_t widthPixels, DWORD fmtFlags = HDF_LEFT,bool update = true);
//! Extended AddColumn, specifies width in pixels @ 96DPI instead of screen-specific pixels
void AddColumnEx( const char * label, uint32_t widthPixelsAt96DPI, DWORD fmtFlags = HDF_LEFT, bool update = true );
//! Extended AddColumn, specifies width in Dialog Length Units (DLU), assumes parent of this list to be a dialog window.
void AddColumnDLU( const char * label, uint32_t widthDLU, DWORD fmtFlags = HDF_LEFT, bool update = true );
//! Extended AddColumn, specifies width as floating-point value of pixels at 96DPI. \n
//! For DPI-safe storage of user's column widths.
void AddColumnF( const char * label, float widthF, DWORD fmtFlags = HDF_LEFT, bool update = true );
void AddColumnAutoWidth( const char * label, DWORD fmtFlags = HDF_LEFT, bool bUpdate = true) { AddColumn(label, columnWidthAuto, fmtFlags, bUpdate); }
bool DeleteColumn(size_t index, bool updateView = true);
void DeleteColumns( pfc::bit_array const & mask, bool updateView = true);
void ResizeColumn(t_size index, t_uint32 widthPixels, bool updateView = true);
void SetColumn( size_t which, const char * title, DWORD fmtFlags = HDF_LEFT, bool updateView = true);
void GetColumnText(size_t which, pfc::string_base & out) const;
uint32_t GetOptimalColumnWidth( size_t index ) const;
uint32_t GetOptimalColumnWidthFixed( const char * fixedText) const;
uint32_t GetColumnsBlankWidth( size_t colExclude = SIZE_MAX ) const;
void SizeColumnToContent( size_t which, uint32_t minWidth );
void SizeColumnToContentFillBlank( size_t which );
//! If creating a custom headerless multi column scheme, override these to manipulate your columns
virtual size_t GetColumnCount() const;
virtual uint32_t GetSubItemWidth(size_t subItem) const;
//! Returns column width as a floating-point value of pixels at 96DPI. \n
//! For DPI-safe storage of user's column widths.
float GetColumnWidthF( size_t subItem ) const;
//! Indicate how many columns a specific row/column cell spans\n
//! This makes sense only if the columns can't be user-reordered
virtual size_t GetSubItemSpan(size_t row, size_t column) const;
t_size GetSubItemOrder(t_size subItem) const;
int GetItemWidth() const override;
protected:
CRect GetClientRectHook() const override;
void RenderBackground(CDCHandle dc, CRect const& rc) override;
struct GetOptimalWidth_Cache {
//! For temporary use.
pfc::string8_fastalloc m_stringTemp, m_stringTempUnfuckAmpersands;
//! For temporary use.
pfc::stringcvt::string_wide_from_utf8_t<pfc::alloc_fast_aggressive> m_convertTemp;
//! Our DC for measuring text. Correct font pre-selected.
CDCHandle m_dc;
t_uint32 GetStringTempWidth();
};
void UpdateHeaderLayout();
void OnViewOriginChange(CPoint p_delta);
void SetHeaderFont(HFONT font);
void RenderItemText(t_size item,const CRect & itemRect,const CRect & updateRect,CDCHandle dc, bool allowColors);
void RenderGroupHeaderText(int id,const CRect & headerRect,const CRect & updateRect,CDCHandle dc);
//! Converts an item/subitem rect to a rect in which the text should be rendered, removing spacing to the left/right of the text.
virtual CRect GetItemTextRectHook(size_t item, size_t subItem, CRect const & itemRect) const;
CRect GetItemTextRect(CRect const & itemRect) const;
//! Override for custom spacing to the left/right of the text in each column.
virtual t_uint32 GetColumnSpacing() const {return MulDiv(4,m_dpi.cx,96);}
//! Override for column-header-click sorting.
virtual void OnColumnHeaderClick(t_size index) {}
//! Override to supply item labels.
virtual bool GetSubItemText(t_size item, t_size subItem, pfc::string_base & out) const {return false;}
//! Override if you support groups.
virtual bool GetGroupHeaderText(int id, pfc::string_base & out) const {return false;}
//! Override optionally.
virtual void RenderSubItemText(t_size item, t_size subItem,const CRect & subItemRect,const CRect & updateRect,CDCHandle dc, bool allowColors);
virtual void OnColumnsChanged();
virtual t_uint32 GetOptimalSubItemWidth(t_size item, t_size subItem, GetOptimalWidth_Cache & cache) const;
virtual t_uint32 GetOptimalGroupHeaderWidth(int which) const;
bool GetItemAtPointAbsEx( CPoint pt, size_t & outItem, size_t & outSubItem ) const;
cellType_t GetCellTypeAtPointAbs( CPoint pt ) const;
virtual cellType_t GetCellType( size_t item, size_t subItem ) const;
virtual bool AllowTypeFindInCell( size_t item, size_t subItem ) const;
virtual bool GetCellTypeSupported() const { return false; } // optimization hint, some expensive checks can be suppressed if cell types are not used for this view
virtual bool GetCellCheckState( size_t item, size_t subItem ) const { return false; }
virtual void SetCellCheckState(size_t item, size_t subItem, bool value);
virtual bool ToggleSelectedItemsHook(const pfc::bit_array & mask);
void RenderSubItemTextInternal(size_t subItem, const CRect & subItemRect, CDCHandle dc, const char * text, bool allowColors);
t_uint32 GetOptimalColumnWidth(t_size which, GetOptimalWidth_Cache & cache) const;
t_uint32 GetOptimalSubItemWidthSimple(t_size item, t_size subItem) const;
void AutoColumnWidths(const pfc::bit_array & mask,bool expandLast = false);
void AutoColumnWidths() {AutoColumnWidths(pfc::bit_array_true());}
void AutoColumnWidth(t_size which) {AutoColumnWidths(pfc::bit_array_one(which));}
virtual bool OnColumnHeaderDrag(t_size index, t_size newOrder);
void OnItemClicked(t_size item, CPoint pt) override;
virtual void OnSubItemClicked(t_size item, t_size subItem,CPoint pt);
bool OnClickedSpecialHitTest(CPoint pt) override;
bool OnClickedSpecial(DWORD status, CPoint pt) override;
static bool CellTypeUsesSpecialHitTests( cellType_t ct );
CRect GetSubItemRectAbs(t_size item,t_size subItem) const;
CRect GetSubItemRect(t_size item,t_size subItem) const;
t_size SubItemFromPointAbs(CPoint pt) const;
static bool CellTypeReactsToMouseOver( cellType_t ct );
virtual CRect CellHotRect( size_t item, size_t subItem, cellType_t ct, CRect rcCell );
CRect CellHotRect( size_t item, size_t subItem, cellType_t ct );
virtual double CellTextScale(size_t item, size_t subItem) { return 1; }
virtual bool IsSubItemGrayed(size_t item, size_t subItem) { return !this->IsWindowEnabled(); }
// HDF_* constants for this column, override when not using list header control. Used to control text alignment.
virtual DWORD GetColumnFormat(t_size which) const;
void SetColumnFormat(t_size which,DWORD format);
void SetColumnSort(t_size which, bool isUp);
std::vector<int> GetColumnOrderArray() const;
bool AllowScrollbar(bool vertical) const override;
void RenderItemBackground(CDCHandle p_dc,const CRect & p_itemRect,size_t item, uint32_t bkColor) override;
void ColumnWidthFix(); // Call RecalcItemWidth() / ProcessAutoWidth()
void ReloadData() override;
private:
void OnEnable(BOOL) { Invalidate(); }
HBRUSH OnCtlColorStatic(CDCHandle dc, CStatic wndStatic);
void ProcessColumnsChange() { OnColumnsChanged();}
LRESULT OnSizePassThru(UINT,WPARAM,LPARAM);
LRESULT OnHeaderItemClick(int,LPNMHDR,BOOL&);
LRESULT OnDividerDoubleClick(int,LPNMHDR,BOOL&);
LRESULT OnHeaderItemChanged(int,LPNMHDR,BOOL&);
LRESULT OnHeaderEndDrag(int,LPNMHDR,BOOL&);
LRESULT OnKeyDown(UINT,WPARAM,LPARAM,BOOL&);
void OnDestroy();
BOOL OnSetCursor(CWindow wnd, UINT nHitTest, UINT message);
void OnMouseMove(UINT nFlags, CPoint point);
void RecalcItemWidth(); // FIXED width math
void ProcessAutoWidth(); // DYNAMIC width math
bool m_ownColumnsChange = false;
int m_itemWidth = 0;
int m_clientWidth = 0;
CHeaderCtrl m_header;
CStatic m_headerLine;
bool HaveAutoWidthColumns() const;
bool HaveAutoWidthContentColumns() const;
struct colRuntime_t {
bool m_autoWidth = false;
bool m_autoWidthContent = false;
int m_widthPixels = 0;
uint32_t m_userWidth = 0;
std::string m_text;
bool autoWidth() const { return m_userWidth > columnWidthMax; }
bool autoWidthContent() const { return m_userWidth == columnWidthAutoUseContent; }
bool autoWidthPlain() const { return m_userWidth == columnWidthAuto; }
};
std::vector<colRuntime_t> m_colRuntime;
//for group headers
GdiplusScope m_gdiPlusScope;
void SetPressedItem(size_t row, size_t column);
void ClearPressedItem() {SetPressedItem(SIZE_MAX, SIZE_MAX);}
void SetHotItem( size_t row, size_t column );
void ClearHotItem() { SetHotItem(SIZE_MAX, SIZE_MAX); }
size_t m_pressedItem = SIZE_MAX, m_pressedSubItem = SIZE_MAX;
size_t m_hotItem = SIZE_MAX, m_hotSubItem = SIZE_MAX;
};