- Rename tests/wasm-app/ to tests/apps/ for brevity - Move lib/gl_immediate_shim.js to wasm/shims/ (consolidates WASM files) - Delete docs/ directory (outdated Nov 2024 research docs) - Delete patches/ directory (already applied to fork submodules) - Delete wasm/patches/ and wasm/config/ (empty/unused) - Update all file references in scripts, configs, and documentation - Update .gitignore for new tests/apps/ paths Verified both build workflows pass: - wxWidgets tests: 255 passed - Docker KiCad build: completed successfully 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
330 lines
11 KiB
C++
330 lines
11 KiB
C++
// wxGrid Custom Cell Renderers Test - KiCad-style grid cells
|
|
// Tests custom cell rendering: color cells, icon+text, checkboxes, striped rows
|
|
|
|
#include "wx/wx.h"
|
|
#include "wx/grid.h"
|
|
#include "wx/dcmemory.h"
|
|
#include "wx/notebook.h"
|
|
|
|
// Custom Color Cell Renderer - like KiCad's layer color swatches
|
|
class ColorCellRenderer : public wxGridCellRenderer
|
|
{
|
|
public:
|
|
virtual void Draw(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc,
|
|
const wxRect& rect, int row, int col, bool isSelected) override
|
|
{
|
|
wxGridCellRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);
|
|
|
|
wxString value = grid.GetCellValue(row, col);
|
|
wxColour color;
|
|
if (color.Set(value))
|
|
{
|
|
// Draw color swatch
|
|
wxRect colorRect = rect;
|
|
colorRect.Deflate(4);
|
|
dc.SetBrush(wxBrush(color));
|
|
dc.SetPen(*wxBLACK_PEN);
|
|
dc.DrawRectangle(colorRect);
|
|
}
|
|
}
|
|
|
|
virtual wxSize GetBestSize(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc,
|
|
int row, int col) override
|
|
{
|
|
return wxSize(60, 20);
|
|
}
|
|
|
|
virtual wxGridCellRenderer* Clone() const override
|
|
{
|
|
return new ColorCellRenderer();
|
|
}
|
|
};
|
|
|
|
// Custom Icon+Text Renderer - like KiCad's footprint list with icons
|
|
class IconTextRenderer : public wxGridCellStringRenderer
|
|
{
|
|
public:
|
|
IconTextRenderer(const wxColour& iconColor = *wxBLUE) : m_iconColor(iconColor) {}
|
|
|
|
virtual void Draw(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc,
|
|
const wxRect& rect, int row, int col, bool isSelected) override
|
|
{
|
|
// Draw background
|
|
wxGridCellStringRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);
|
|
|
|
// Draw icon (small colored square)
|
|
wxRect iconRect(rect.x + 2, rect.y + 3, 14, 14);
|
|
dc.SetBrush(wxBrush(m_iconColor));
|
|
dc.SetPen(*wxBLACK_PEN);
|
|
dc.DrawRectangle(iconRect);
|
|
|
|
// Draw text offset by icon width
|
|
wxRect textRect = rect;
|
|
textRect.x += 20;
|
|
textRect.width -= 20;
|
|
|
|
dc.SetTextForeground(isSelected ? *wxWHITE : *wxBLACK);
|
|
dc.DrawLabel(grid.GetCellValue(row, col), textRect, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
|
|
}
|
|
|
|
virtual wxGridCellRenderer* Clone() const override
|
|
{
|
|
return new IconTextRenderer(m_iconColor);
|
|
}
|
|
|
|
private:
|
|
wxColour m_iconColor;
|
|
};
|
|
|
|
// Striped Row Renderer - alternating row colors like KiCad's symbol editor
|
|
class StripedRenderer : public wxGridCellStringRenderer
|
|
{
|
|
public:
|
|
virtual void Draw(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc,
|
|
const wxRect& rect, int row, int col, bool isSelected) override
|
|
{
|
|
// Alternating background colors
|
|
if (!isSelected)
|
|
{
|
|
wxColour bgColor = (row % 2 == 0) ? wxColour(255, 255, 255) : wxColour(240, 240, 245);
|
|
dc.SetBrush(wxBrush(bgColor));
|
|
dc.SetPen(*wxTRANSPARENT_PEN);
|
|
dc.DrawRectangle(rect);
|
|
}
|
|
|
|
// Draw text
|
|
wxGridCellStringRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);
|
|
}
|
|
|
|
virtual wxGridCellRenderer* Clone() const override
|
|
{
|
|
return new StripedRenderer();
|
|
}
|
|
};
|
|
|
|
class GridRenderersFrame : public wxFrame
|
|
{
|
|
public:
|
|
GridRenderersFrame() : wxFrame(nullptr, wxID_ANY, "wxGrid Custom Cell Renderers Test",
|
|
wxDefaultPosition, wxSize(1000, 600))
|
|
{
|
|
wxPanel* mainPanel = new wxPanel(this);
|
|
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
|
|
|
|
// Description
|
|
wxStaticText* desc = new wxStaticText(mainPanel, wxID_ANY,
|
|
"KiCad uses custom grid cell renderers for color swatches, icons, and striped rows.\n"
|
|
"Tests: Color cells, Icon+Text cells, Striped rows, Checkbox cells.");
|
|
mainSizer->Add(desc, 0, wxALL, 5);
|
|
|
|
// Create notebook with different grid examples
|
|
m_notebook = new wxNotebook(mainPanel, wxID_ANY);
|
|
|
|
// Tab 1: Color Cells (like KiCad layer manager)
|
|
CreateColorGrid();
|
|
|
|
// Tab 2: Icon + Text (like footprint browser)
|
|
CreateIconTextGrid();
|
|
|
|
// Tab 3: Striped rows with checkboxes
|
|
CreateStripedGrid();
|
|
|
|
mainSizer->Add(m_notebook, 1, wxEXPAND | wxALL, 5);
|
|
|
|
// Event log
|
|
mainSizer->Add(new wxStaticText(mainPanel, wxID_ANY, "Event Log"), 0, wxLEFT | wxTOP, 5);
|
|
m_log = new wxTextCtrl(mainPanel, wxID_ANY, "", wxDefaultPosition, wxSize(-1, 80),
|
|
wxTE_MULTILINE | wxTE_READONLY);
|
|
mainSizer->Add(m_log, 0, wxEXPAND | wxALL, 5);
|
|
|
|
mainPanel->SetSizer(mainSizer);
|
|
|
|
CreateStatusBar();
|
|
SetStatusText("Grid renderers test app started");
|
|
Log("Grid renderers test app started");
|
|
}
|
|
|
|
private:
|
|
void CreateColorGrid()
|
|
{
|
|
wxPanel* panel = new wxPanel(m_notebook);
|
|
wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
|
|
|
|
wxGrid* grid = new wxGrid(panel, wxID_ANY);
|
|
grid->CreateGrid(8, 3);
|
|
|
|
grid->SetColLabelValue(0, "Layer");
|
|
grid->SetColLabelValue(1, "Color");
|
|
grid->SetColLabelValue(2, "Visible");
|
|
|
|
grid->SetColSize(0, 150);
|
|
grid->SetColSize(1, 100);
|
|
grid->SetColSize(2, 80);
|
|
|
|
// Set up color renderer for column 1 (read-only display)
|
|
wxGridCellAttr* colorAttr = new wxGridCellAttr();
|
|
colorAttr->SetRenderer(new ColorCellRenderer());
|
|
colorAttr->SetReadOnly(true); // Display only - would need dialog to edit
|
|
grid->SetColAttr(1, colorAttr);
|
|
|
|
// Boolean column
|
|
grid->SetColFormatBool(2);
|
|
|
|
// Layer data
|
|
const char* layers[] = {"F.Cu", "B.Cu", "F.SilkS", "B.SilkS", "F.Mask", "B.Mask", "Edge.Cuts", "Dwgs.User"};
|
|
const char* colors[] = {"#FF0000", "#0000FF", "#FFFF00", "#FF00FF", "#00FF00", "#00FFFF", "#FFFFFF", "#808080"};
|
|
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
grid->SetCellValue(i, 0, layers[i]);
|
|
grid->SetCellValue(i, 1, colors[i]);
|
|
grid->SetCellValue(i, 2, "1");
|
|
}
|
|
|
|
grid->Bind(wxEVT_GRID_CELL_CHANGED, &GridRenderersFrame::OnCellChanged, this);
|
|
|
|
sizer->Add(grid, 1, wxEXPAND | wxALL, 5);
|
|
panel->SetSizer(sizer);
|
|
m_notebook->AddPage(panel, "Color Cells");
|
|
m_colorGrid = grid;
|
|
}
|
|
|
|
void CreateIconTextGrid()
|
|
{
|
|
wxPanel* panel = new wxPanel(m_notebook);
|
|
wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
|
|
|
|
wxGrid* grid = new wxGrid(panel, wxID_ANY);
|
|
grid->CreateGrid(10, 3);
|
|
|
|
grid->SetColLabelValue(0, "Component");
|
|
grid->SetColLabelValue(1, "Footprint");
|
|
grid->SetColLabelValue(2, "Library");
|
|
|
|
grid->SetColSize(0, 180);
|
|
grid->SetColSize(1, 250);
|
|
grid->SetColSize(2, 150);
|
|
|
|
// Set up icon+text renderer
|
|
wxGridCellAttr* iconAttr = new wxGridCellAttr();
|
|
iconAttr->SetRenderer(new IconTextRenderer(*wxRED));
|
|
grid->SetColAttr(0, iconAttr);
|
|
|
|
wxGridCellAttr* iconAttr2 = new wxGridCellAttr();
|
|
iconAttr2->SetRenderer(new IconTextRenderer(wxColour(0, 128, 0)));
|
|
grid->SetColAttr(1, iconAttr2);
|
|
|
|
// Data
|
|
const char* components[] = {"R_0402", "C_0603", "LED_0805", "STM32F4", "USB_C",
|
|
"MOSFET_SOT23", "LDO_SOT223", "Crystal_3225", "Header_2x5", "Connector_JST"};
|
|
const char* footprints[] = {"Resistor_SMD:R_0402", "Capacitor_SMD:C_0603", "LED_SMD:LED_0805",
|
|
"Package_QFP:LQFP-100", "Connector_USB:USB_C",
|
|
"Package_TO:SOT-23", "Package_TO:SOT-223", "Crystal:Crystal_3225",
|
|
"Connector_Pin:2x5", "Connector_JST:JST_PH_4"};
|
|
const char* libraries[] = {"Resistor_SMD", "Capacitor_SMD", "LED_SMD", "Package_QFP",
|
|
"Connector_USB", "Package_TO", "Package_TO", "Crystal",
|
|
"Connector_Pin", "Connector_JST"};
|
|
|
|
for (int i = 0; i < 10; i++)
|
|
{
|
|
grid->SetCellValue(i, 0, components[i]);
|
|
grid->SetCellValue(i, 1, footprints[i]);
|
|
grid->SetCellValue(i, 2, libraries[i]);
|
|
}
|
|
|
|
sizer->Add(grid, 1, wxEXPAND | wxALL, 5);
|
|
panel->SetSizer(sizer);
|
|
m_notebook->AddPage(panel, "Icon+Text");
|
|
m_iconGrid = grid;
|
|
}
|
|
|
|
void CreateStripedGrid()
|
|
{
|
|
wxPanel* panel = new wxPanel(m_notebook);
|
|
wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
|
|
|
|
wxGrid* grid = new wxGrid(panel, wxID_ANY);
|
|
grid->CreateGrid(12, 4);
|
|
|
|
grid->SetColLabelValue(0, "Reference");
|
|
grid->SetColLabelValue(1, "Value");
|
|
grid->SetColLabelValue(2, "DNP");
|
|
grid->SetColLabelValue(3, "Excluded");
|
|
|
|
grid->SetColSize(0, 100);
|
|
grid->SetColSize(1, 150);
|
|
grid->SetColSize(2, 80);
|
|
grid->SetColSize(3, 80);
|
|
|
|
// Apply striped renderer to text columns
|
|
wxGridCellAttr* stripedAttr = new wxGridCellAttr();
|
|
stripedAttr->SetRenderer(new StripedRenderer());
|
|
grid->SetColAttr(0, stripedAttr);
|
|
|
|
wxGridCellAttr* stripedAttr2 = new wxGridCellAttr();
|
|
stripedAttr2->SetRenderer(new StripedRenderer());
|
|
grid->SetColAttr(1, stripedAttr2);
|
|
|
|
// Boolean columns
|
|
grid->SetColFormatBool(2);
|
|
grid->SetColFormatBool(3);
|
|
|
|
// BOM-like data
|
|
const char* refs[] = {"R1", "R2", "R3", "R4", "C1", "C2", "C3", "U1", "U2", "J1", "D1", "Q1"};
|
|
const char* values[] = {"10k", "4.7k", "100", "1M", "100nF", "10uF", "22pF", "STM32F103",
|
|
"74HC595", "USB-C", "LED_Red", "2N7002"};
|
|
const char* dnp[] = {"0", "0", "1", "0", "0", "0", "0", "0", "1", "0", "0", "0"};
|
|
const char* excluded[] = {"0", "0", "0", "1", "0", "0", "0", "0", "0", "0", "0", "0"};
|
|
|
|
for (int i = 0; i < 12; i++)
|
|
{
|
|
grid->SetCellValue(i, 0, refs[i]);
|
|
grid->SetCellValue(i, 1, values[i]);
|
|
grid->SetCellValue(i, 2, dnp[i]);
|
|
grid->SetCellValue(i, 3, excluded[i]);
|
|
}
|
|
|
|
grid->Bind(wxEVT_GRID_CELL_CHANGED, &GridRenderersFrame::OnCellChanged, this);
|
|
|
|
sizer->Add(grid, 1, wxEXPAND | wxALL, 5);
|
|
panel->SetSizer(sizer);
|
|
m_notebook->AddPage(panel, "Striped+Checkboxes");
|
|
m_stripedGrid = grid;
|
|
}
|
|
|
|
void Log(const wxString& msg)
|
|
{
|
|
m_log->AppendText(msg + "\n");
|
|
}
|
|
|
|
void OnCellChanged(wxGridEvent& event)
|
|
{
|
|
wxGrid* grid = dynamic_cast<wxGrid*>(event.GetEventObject());
|
|
if (grid)
|
|
{
|
|
int row = event.GetRow();
|
|
int col = event.GetCol();
|
|
wxString value = grid->GetCellValue(row, col);
|
|
Log(wxString::Format("Cell [%d,%d] changed to: %s", row, col, value));
|
|
}
|
|
}
|
|
|
|
wxNotebook* m_notebook;
|
|
wxGrid* m_colorGrid;
|
|
wxGrid* m_iconGrid;
|
|
wxGrid* m_stripedGrid;
|
|
wxTextCtrl* m_log;
|
|
};
|
|
|
|
class GridRenderersApp : public wxApp
|
|
{
|
|
public:
|
|
virtual bool OnInit() override
|
|
{
|
|
GridRenderersFrame* frame = new GridRenderersFrame();
|
|
frame->Show();
|
|
return true;
|
|
}
|
|
};
|
|
|
|
wxIMPLEMENT_APP(GridRenderersApp);
|