Reorganize project structure for clarity
- 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>
This commit is contained in:
parent
c4cd69f28d
commit
a26b40c063
78 changed files with 38 additions and 128055 deletions
330
tests/apps/standalone/ownerdrawn/ownerdrawn_test.cpp
Normal file
330
tests/apps/standalone/ownerdrawn/ownerdrawn_test.cpp
Normal file
|
|
@ -0,0 +1,330 @@
|
|||
// wxOwnerDrawnComboBox Test - Custom dropdown rendering like KiCad's layer/font selectors
|
||||
// Tests: wxOwnerDrawnComboBox, OnDrawItem, OnMeasureItem, custom rendering
|
||||
|
||||
#include "wx/wx.h"
|
||||
#include "wx/odcombo.h"
|
||||
#include "wx/dcmemory.h"
|
||||
|
||||
// Custom owner-drawn combo box for layer selection (like KiCad LAYER_BOX_SELECTOR)
|
||||
class LayerComboBox : public wxOwnerDrawnComboBox
|
||||
{
|
||||
public:
|
||||
LayerComboBox(wxWindow* parent, wxWindowID id = wxID_ANY)
|
||||
: wxOwnerDrawnComboBox(parent, id, wxEmptyString, wxDefaultPosition,
|
||||
wxSize(200, -1), 0, nullptr, wxCB_READONLY)
|
||||
{
|
||||
// Add layers with colors
|
||||
Append("F.Cu"); m_colors.push_back(*wxRED);
|
||||
Append("B.Cu"); m_colors.push_back(*wxBLUE);
|
||||
Append("F.SilkS"); m_colors.push_back(*wxYELLOW);
|
||||
Append("B.SilkS"); m_colors.push_back(wxColour(255, 0, 255));
|
||||
Append("F.Mask"); m_colors.push_back(wxColour(0, 128, 0));
|
||||
Append("B.Mask"); m_colors.push_back(wxColour(0, 128, 128));
|
||||
Append("Edge.Cuts"); m_colors.push_back(*wxWHITE);
|
||||
Append("Dwgs.User"); m_colors.push_back(wxColour(128, 128, 128));
|
||||
|
||||
SetSelection(0);
|
||||
}
|
||||
|
||||
virtual void OnDrawItem(wxDC& dc, const wxRect& rect, int item, int flags) const override
|
||||
{
|
||||
if (item == wxNOT_FOUND)
|
||||
return;
|
||||
|
||||
// Draw background
|
||||
if (flags & wxODCB_PAINTING_SELECTED)
|
||||
{
|
||||
dc.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT)));
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
dc.DrawRectangle(rect);
|
||||
dc.SetTextForeground(*wxWHITE);
|
||||
}
|
||||
else
|
||||
{
|
||||
dc.SetTextForeground(*wxBLACK);
|
||||
}
|
||||
|
||||
// Draw color swatch
|
||||
wxRect swatchRect(rect.x + 4, rect.y + 4, 20, rect.height - 8);
|
||||
dc.SetBrush(wxBrush(m_colors[item]));
|
||||
dc.SetPen(*wxBLACK_PEN);
|
||||
dc.DrawRectangle(swatchRect);
|
||||
|
||||
// Draw text
|
||||
wxString text = GetString(item);
|
||||
dc.DrawText(text, rect.x + 30, rect.y + (rect.height - dc.GetCharHeight()) / 2);
|
||||
}
|
||||
|
||||
virtual wxCoord OnMeasureItem(size_t item) const override
|
||||
{
|
||||
return 24; // Fixed item height
|
||||
}
|
||||
|
||||
virtual wxCoord OnMeasureItemWidth(size_t item) const override
|
||||
{
|
||||
return -1; // Use default width
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<wxColour> m_colors;
|
||||
};
|
||||
|
||||
// Custom owner-drawn combo box for fonts (like KiCad FONT_CHOICE)
|
||||
class FontComboBox : public wxOwnerDrawnComboBox
|
||||
{
|
||||
public:
|
||||
FontComboBox(wxWindow* parent, wxWindowID id = wxID_ANY)
|
||||
: wxOwnerDrawnComboBox(parent, id, wxEmptyString, wxDefaultPosition,
|
||||
wxSize(200, -1), 0, nullptr, wxCB_READONLY)
|
||||
{
|
||||
// Add sample fonts
|
||||
Append("Default");
|
||||
Append("Arial");
|
||||
Append("Times New Roman");
|
||||
Append("Courier New");
|
||||
Append("Verdana");
|
||||
Append("Georgia");
|
||||
Append("Comic Sans MS");
|
||||
Append("Impact");
|
||||
|
||||
SetSelection(0);
|
||||
}
|
||||
|
||||
virtual void OnDrawItem(wxDC& dc, const wxRect& rect, int item, int flags) const override
|
||||
{
|
||||
if (item == wxNOT_FOUND)
|
||||
return;
|
||||
|
||||
// Draw background
|
||||
if (flags & wxODCB_PAINTING_SELECTED)
|
||||
{
|
||||
dc.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT)));
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
dc.DrawRectangle(rect);
|
||||
dc.SetTextForeground(*wxWHITE);
|
||||
}
|
||||
else
|
||||
{
|
||||
dc.SetTextForeground(*wxBLACK);
|
||||
}
|
||||
|
||||
// Draw text in the font itself (if not Default)
|
||||
wxString fontName = GetString(item);
|
||||
wxFont font = dc.GetFont();
|
||||
if (fontName != "Default")
|
||||
{
|
||||
font.SetFaceName(fontName);
|
||||
}
|
||||
dc.SetFont(font);
|
||||
dc.DrawText(fontName, rect.x + 6, rect.y + (rect.height - dc.GetCharHeight()) / 2);
|
||||
}
|
||||
|
||||
virtual wxCoord OnMeasureItem(size_t item) const override
|
||||
{
|
||||
return 26; // Slightly taller for fonts
|
||||
}
|
||||
};
|
||||
|
||||
// Custom owner-drawn combo box with icons (for footprints)
|
||||
class IconComboBox : public wxOwnerDrawnComboBox
|
||||
{
|
||||
public:
|
||||
IconComboBox(wxWindow* parent, wxWindowID id = wxID_ANY)
|
||||
: wxOwnerDrawnComboBox(parent, id, wxEmptyString, wxDefaultPosition,
|
||||
wxSize(250, -1), 0, nullptr, wxCB_READONLY)
|
||||
{
|
||||
// Add items with different icon types
|
||||
Append("Resistor"); m_types.push_back(0); // Rectangle
|
||||
Append("Capacitor"); m_types.push_back(1); // Two lines
|
||||
Append("Inductor"); m_types.push_back(2); // Coil
|
||||
Append("Diode"); m_types.push_back(3); // Triangle
|
||||
Append("Transistor"); m_types.push_back(4); // Complex
|
||||
Append("IC Package"); m_types.push_back(5); // Square with pins
|
||||
Append("Connector"); m_types.push_back(6); // Dots
|
||||
|
||||
SetSelection(0);
|
||||
}
|
||||
|
||||
virtual void OnDrawItem(wxDC& dc, const wxRect& rect, int item, int flags) const override
|
||||
{
|
||||
if (item == wxNOT_FOUND)
|
||||
return;
|
||||
|
||||
// Draw background
|
||||
if (flags & wxODCB_PAINTING_SELECTED)
|
||||
{
|
||||
dc.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT)));
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
dc.DrawRectangle(rect);
|
||||
dc.SetTextForeground(*wxWHITE);
|
||||
}
|
||||
else
|
||||
{
|
||||
dc.SetTextForeground(*wxBLACK);
|
||||
}
|
||||
|
||||
// Draw icon based on type
|
||||
int iconX = rect.x + 4;
|
||||
int iconY = rect.y + 4;
|
||||
int iconSize = rect.height - 8;
|
||||
|
||||
dc.SetPen(wxPen(*wxBLACK, 2));
|
||||
dc.SetBrush(*wxWHITE_BRUSH);
|
||||
|
||||
int type = m_types[item];
|
||||
switch (type)
|
||||
{
|
||||
case 0: // Resistor - zigzag
|
||||
dc.DrawLine(iconX, iconY + iconSize/2, iconX + iconSize, iconY + iconSize/2);
|
||||
break;
|
||||
case 1: // Capacitor - two lines
|
||||
dc.DrawLine(iconX + iconSize/3, iconY + 2, iconX + iconSize/3, iconY + iconSize - 2);
|
||||
dc.DrawLine(iconX + 2*iconSize/3, iconY + 2, iconX + 2*iconSize/3, iconY + iconSize - 2);
|
||||
break;
|
||||
case 2: // Inductor - coil (3 bumps)
|
||||
dc.DrawArc(iconX + 4, iconY + iconSize/2, iconX + 10, iconY + iconSize/2, iconX + 7, iconY + iconSize/2 - 4);
|
||||
break;
|
||||
case 3: // Diode - triangle
|
||||
{
|
||||
wxPoint pts[3] = {
|
||||
wxPoint(iconX + 2, iconY + 2),
|
||||
wxPoint(iconX + 2, iconY + iconSize - 2),
|
||||
wxPoint(iconX + iconSize - 2, iconY + iconSize/2)
|
||||
};
|
||||
dc.DrawPolygon(3, pts);
|
||||
}
|
||||
break;
|
||||
case 4: // Transistor - circle with lines
|
||||
dc.DrawCircle(iconX + iconSize/2, iconY + iconSize/2, iconSize/3);
|
||||
break;
|
||||
case 5: // IC - square
|
||||
dc.DrawRectangle(iconX + 2, iconY + 2, iconSize - 4, iconSize - 4);
|
||||
break;
|
||||
case 6: // Connector - dots
|
||||
dc.SetBrush(*wxBLACK_BRUSH);
|
||||
dc.DrawCircle(iconX + iconSize/4, iconY + iconSize/2, 3);
|
||||
dc.DrawCircle(iconX + 3*iconSize/4, iconY + iconSize/2, 3);
|
||||
break;
|
||||
}
|
||||
|
||||
// Draw text
|
||||
wxString text = GetString(item);
|
||||
dc.DrawText(text, rect.x + iconSize + 10, rect.y + (rect.height - dc.GetCharHeight()) / 2);
|
||||
}
|
||||
|
||||
virtual wxCoord OnMeasureItem(size_t item) const override
|
||||
{
|
||||
return 28;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<int> m_types;
|
||||
};
|
||||
|
||||
class OwnerDrawnFrame : public wxFrame
|
||||
{
|
||||
public:
|
||||
OwnerDrawnFrame() : wxFrame(nullptr, wxID_ANY, "wxOwnerDrawnComboBox Test",
|
||||
wxDefaultPosition, wxSize(700, 600))
|
||||
{
|
||||
wxPanel* mainPanel = new wxPanel(this);
|
||||
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
// Description
|
||||
wxStaticText* desc = new wxStaticText(mainPanel, wxID_ANY,
|
||||
"KiCad uses wxOwnerDrawnComboBox for layer selectors and font choosers.\n"
|
||||
"Tests: Custom item drawing, variable heights, icons + text.");
|
||||
mainSizer->Add(desc, 0, wxALL, 5);
|
||||
|
||||
// Layer selector
|
||||
wxStaticBoxSizer* layerSizer = new wxStaticBoxSizer(wxVERTICAL, mainPanel, "Layer Selector (Color Swatches)");
|
||||
m_layerCombo = new LayerComboBox(mainPanel);
|
||||
m_layerCombo->Bind(wxEVT_COMBOBOX, &OwnerDrawnFrame::OnLayerChanged, this);
|
||||
layerSizer->Add(m_layerCombo, 0, wxALL, 5);
|
||||
m_layerLabel = new wxStaticText(mainPanel, wxID_ANY, "Selected: F.Cu");
|
||||
layerSizer->Add(m_layerLabel, 0, wxALL, 5);
|
||||
mainSizer->Add(layerSizer, 0, wxEXPAND | wxALL, 5);
|
||||
|
||||
// Font selector
|
||||
wxStaticBoxSizer* fontSizer = new wxStaticBoxSizer(wxVERTICAL, mainPanel, "Font Selector (Font Preview)");
|
||||
m_fontCombo = new FontComboBox(mainPanel);
|
||||
m_fontCombo->Bind(wxEVT_COMBOBOX, &OwnerDrawnFrame::OnFontChanged, this);
|
||||
fontSizer->Add(m_fontCombo, 0, wxALL, 5);
|
||||
m_fontLabel = new wxStaticText(mainPanel, wxID_ANY, "Selected: Default");
|
||||
fontSizer->Add(m_fontLabel, 0, wxALL, 5);
|
||||
mainSizer->Add(fontSizer, 0, wxEXPAND | wxALL, 5);
|
||||
|
||||
// Icon selector
|
||||
wxStaticBoxSizer* iconSizer = new wxStaticBoxSizer(wxVERTICAL, mainPanel, "Component Selector (Icons)");
|
||||
m_iconCombo = new IconComboBox(mainPanel);
|
||||
m_iconCombo->Bind(wxEVT_COMBOBOX, &OwnerDrawnFrame::OnIconChanged, this);
|
||||
iconSizer->Add(m_iconCombo, 0, wxALL, 5);
|
||||
m_iconLabel = new wxStaticText(mainPanel, wxID_ANY, "Selected: Resistor");
|
||||
iconSizer->Add(m_iconLabel, 0, wxALL, 5);
|
||||
mainSizer->Add(iconSizer, 0, 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, 150),
|
||||
wxTE_MULTILINE | wxTE_READONLY);
|
||||
mainSizer->Add(m_log, 1, wxEXPAND | wxALL, 5);
|
||||
|
||||
mainPanel->SetSizer(mainSizer);
|
||||
|
||||
CreateStatusBar();
|
||||
SetStatusText("Owner-drawn combo box test app started");
|
||||
Log("Owner-drawn combo box test app started");
|
||||
Log("Each dropdown shows custom-rendered items");
|
||||
}
|
||||
|
||||
private:
|
||||
void OnLayerChanged(wxCommandEvent& event)
|
||||
{
|
||||
int sel = m_layerCombo->GetSelection();
|
||||
wxString layer = sel != wxNOT_FOUND ? m_layerCombo->GetString(sel) : "";
|
||||
m_layerLabel->SetLabel("Selected: " + layer);
|
||||
Log("Layer changed to: " + layer);
|
||||
}
|
||||
|
||||
void OnFontChanged(wxCommandEvent& event)
|
||||
{
|
||||
int sel = m_fontCombo->GetSelection();
|
||||
wxString font = sel != wxNOT_FOUND ? m_fontCombo->GetString(sel) : "";
|
||||
m_fontLabel->SetLabel("Selected: " + font);
|
||||
Log("Font changed to: " + font);
|
||||
}
|
||||
|
||||
void OnIconChanged(wxCommandEvent& event)
|
||||
{
|
||||
int sel = m_iconCombo->GetSelection();
|
||||
wxString component = sel != wxNOT_FOUND ? m_iconCombo->GetString(sel) : "";
|
||||
m_iconLabel->SetLabel("Selected: " + component);
|
||||
Log("Component changed to: " + component);
|
||||
}
|
||||
|
||||
void Log(const wxString& msg)
|
||||
{
|
||||
m_log->AppendText(msg + "\n");
|
||||
}
|
||||
|
||||
LayerComboBox* m_layerCombo;
|
||||
FontComboBox* m_fontCombo;
|
||||
IconComboBox* m_iconCombo;
|
||||
wxStaticText* m_layerLabel;
|
||||
wxStaticText* m_fontLabel;
|
||||
wxStaticText* m_iconLabel;
|
||||
wxTextCtrl* m_log;
|
||||
};
|
||||
|
||||
class OwnerDrawnApp : public wxApp
|
||||
{
|
||||
public:
|
||||
virtual bool OnInit() override
|
||||
{
|
||||
OwnerDrawnFrame* frame = new OwnerDrawnFrame();
|
||||
frame->Show();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
wxIMPLEMENT_APP(OwnerDrawnApp);
|
||||
Loading…
Reference in a new issue