mirror of
https://github.com/sebastiandine/Card-Collection-Manager-3.git
synced 2026-08-28 23:01:09 +00:00
55ace147bc
* initial development * pipeline * pipeline * pipeline * pipeline * pipeline * pipeline * pipeline * pipeline * pipeline * pipeline * pipeline * pipeline * pipeline * pipeline * ci/cd * ci/cd * ci/cd * ci/cd * ci/cd * ci/cd * ci/cd * pokemon * pokemon * pokemon * pokemon * pokemon * pokemon * improvements * improvements * ci/cd * ci/cd * improvements * improvements * improvements * improvements * improvements * improvements * improvements * improvements * improvements --------- Co-authored-by: sdine <sdine@sdine.com>
93 lines
3.5 KiB
C++
93 lines
3.5 KiB
C++
#pragma once
|
|
|
|
// IconListCtrl
|
|
//
|
|
// `wxListCtrl` subclass that custom-draws icon sub-items so they are
|
|
// pixel-perfect centered within the cell, matching our themed-header icon
|
|
// centering exactly even after column resize.
|
|
//
|
|
// Why we need this:
|
|
// - Native MSW `LVS_REPORT` sub-item image rendering anchors the image at
|
|
// the cell's left edge with a small built-in inset. The header icons in
|
|
// this app are centered via wx sizers, so the two never line up.
|
|
// - We override `NM_CUSTOMDRAW` to paint icons ourselves at the exact
|
|
// center of each icon sub-item rect.
|
|
// - Default text cell rendering is left untouched.
|
|
//
|
|
// Rendering path (MSW):
|
|
// We keep one premultiplied 32 bpp BGRA DIB section per (iconIdx, selected)
|
|
// variant and composite it onto the listctrl's HDC with `AlphaBlend`
|
|
// (`AC_SRC_OVER` + `AC_SRC_ALPHA`) from `NM_CUSTOMDRAW`. We deliberately
|
|
// do **not** route through `ImageList_Draw` / `HIMAGELIST`: in our test
|
|
// environment `ImageList_Draw` on an `ILC_COLOR32` list ignored the alpha
|
|
// channel and the "transparent" canvas around each glyph painted as
|
|
// opaque black behind the icon — see `ui_wx/AGENTS.md` convention 11.
|
|
//
|
|
// Usage:
|
|
// 1) Construct with the same wxListCtrl flags as before.
|
|
// 2) Call `setIconColumns(firstIconCol, count)` so the subclass knows which
|
|
// sub-item indices it owns.
|
|
// 3) Call `setIconPredicate(...)` with a callback that decides if the icon
|
|
// should be drawn for a given (row, iconIdx).
|
|
// 4) Call `setIconBitmaps(normal, selected)` with two equally-sized vectors
|
|
// of pre-rendered icon bitmaps — one variant per selection state.
|
|
//
|
|
// This class is MSW-specific in behavior (NM_CUSTOMDRAW). On other platforms
|
|
// `MSWOnNotify` is a no-op override and the listctrl falls back to default
|
|
// rendering — which is fine because this app only ships on Windows.
|
|
|
|
#include <wx/bitmap.h>
|
|
#include <wx/listctrl.h>
|
|
|
|
#include <functional>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
namespace ccm::ui {
|
|
|
|
class IconListCtrl : public wxListCtrl {
|
|
public:
|
|
using wxListCtrl::wxListCtrl;
|
|
|
|
using IconPredicate = std::function<bool(long row, int iconIdx)>;
|
|
|
|
~IconListCtrl() override;
|
|
|
|
void setIconColumns(int firstIconCol, int iconCount) noexcept {
|
|
firstIconCol_ = firstIconCol;
|
|
iconColCount_ = iconCount;
|
|
}
|
|
void setIconPredicate(IconPredicate p) { predicate_ = std::move(p); }
|
|
|
|
// Replace the cached icon bitmaps. Both vectors must have the same size
|
|
// (one entry per icon column). Internal premultiplied DIB cache rebuilds.
|
|
void setIconBitmaps(std::vector<wxBitmap> normal,
|
|
std::vector<wxBitmap> selected);
|
|
|
|
protected:
|
|
#ifdef __WXMSW__
|
|
bool MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM* result) override;
|
|
#endif
|
|
|
|
private:
|
|
int firstIconCol_{-1};
|
|
int iconColCount_{0};
|
|
IconPredicate predicate_;
|
|
std::vector<wxBitmap> normalBmps_;
|
|
std::vector<wxBitmap> selectedBmps_;
|
|
|
|
// Premultiplied BGRA DIB sections used as the source for `AlphaBlend`.
|
|
// Stored as `void*` (HBITMAP) so the header stays free of `<windows.h>`.
|
|
// Index layout:
|
|
// [0 .. iconColCount_) -> normal variants
|
|
// [iconColCount_ .. 2 * iconColCount_) -> selected variants
|
|
std::vector<void*> dibBitmaps_;
|
|
int dibWidth_{0};
|
|
int dibHeight_{0};
|
|
|
|
void rebuildDibCache();
|
|
void destroyDibCache();
|
|
};
|
|
|
|
} // namespace ccm::ui
|