// Specialized wxWidgets Controls Test // Tests: wxTreebook, wxBitmapComboBox, wxSpinCtrl // These are used in KiCad for settings dialogs and layer management #include "wx/wx.h" #include "wx/treebook.h" #include "wx/bmpcbox.h" #include "wx/dcmemory.h" #include "wx/spinctrl.h" // Helper to create color swatch bitmaps for wxBitmapComboBox wxBitmap CreateColorSwatch(const wxColour& color, int width = 16, int height = 16) { wxBitmap bmp(width, height); wxMemoryDC dc(bmp); dc.SetPen(*wxBLACK_PEN); dc.SetBrush(wxBrush(color)); dc.DrawRectangle(0, 0, width, height); return bmp; } class SpecializedFrame : public wxFrame { public: SpecializedFrame() : wxFrame(nullptr, wxID_ANY, "Specialized wxWidgets Controls Test", wxDefaultPosition, wxSize(900, 700)) { wxPanel* mainPanel = new wxPanel(this); wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL); // Description wxStaticText* desc = new wxStaticText(mainPanel, wxID_ANY, "KiCad uses specialized controls for settings and layer management.\n" "Tests: wxTreebook (settings pages), wxBitmapComboBox (layer chooser), wxListBox (layer list)."); mainSizer->Add(desc, 0, wxALL, 5); // Split into left and right panels wxBoxSizer* contentSizer = new wxBoxSizer(wxHORIZONTAL); // Left: wxTreebook wxStaticBoxSizer* treebookSizer = new wxStaticBoxSizer(wxVERTICAL, mainPanel, "wxTreebook (Settings)"); CreateTreebook(mainPanel); treebookSizer->Add(m_treebook, 1, wxEXPAND | wxALL, 5); contentSizer->Add(treebookSizer, 1, wxEXPAND | wxALL, 5); // Right: wxBitmapComboBox and wxListBox for layer list wxBoxSizer* rightSizer = new wxBoxSizer(wxVERTICAL); // wxBitmapComboBox wxStaticBoxSizer* bmpComboSizer = new wxStaticBoxSizer(wxVERTICAL, mainPanel, "wxBitmapComboBox (Layer Chooser)"); CreateBitmapComboBox(mainPanel); bmpComboSizer->Add(m_layerCombo, 0, wxEXPAND | wxALL, 5); wxStaticText* comboLabel = new wxStaticText(mainPanel, wxID_ANY, "Selected: (none)"); m_comboLabel = comboLabel; bmpComboSizer->Add(comboLabel, 0, wxALL, 5); rightSizer->Add(bmpComboSizer, 0, wxEXPAND | wxALL, 5); // Layer List (simulating wxRearrangeCtrl with wxCheckListBox) wxStaticBoxSizer* listSizer = new wxStaticBoxSizer(wxVERTICAL, mainPanel, "Layer List (Visibility)"); CreateLayerList(mainPanel); listSizer->Add(m_layerList, 1, wxEXPAND | wxALL, 5); wxButton* btnGetOrder = new wxButton(mainPanel, wxID_ANY, "Get Layer Status"); btnGetOrder->Bind(wxEVT_BUTTON, &SpecializedFrame::OnGetOrder, this); listSizer->Add(btnGetOrder, 0, wxALL, 5); rightSizer->Add(listSizer, 1, wxEXPAND | wxALL, 5); contentSizer->Add(rightSizer, 1, wxEXPAND); mainSizer->Add(contentSizer, 1, wxEXPAND); // 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, 100), wxTE_MULTILINE | wxTE_READONLY); mainSizer->Add(m_log, 0, wxEXPAND | wxALL, 5); mainPanel->SetSizer(mainSizer); CreateStatusBar(); SetStatusText("Specialized controls test app started"); Log("Specialized controls test app started"); } private: void CreateTreebook(wxWindow* parent) { m_treebook = new wxTreebook(parent, wxID_ANY); // General settings page wxPanel* generalPage = new wxPanel(m_treebook); wxBoxSizer* generalSizer = new wxBoxSizer(wxVERTICAL); generalSizer->Add(new wxStaticText(generalPage, wxID_ANY, "General Settings"), 0, wxALL, 10); generalSizer->Add(new wxCheckBox(generalPage, wxID_ANY, "Show grid"), 0, wxALL, 5); generalSizer->Add(new wxCheckBox(generalPage, wxID_ANY, "Auto-save"), 0, wxALL, 5); generalSizer->Add(new wxCheckBox(generalPage, wxID_ANY, "Show welcome dialog"), 0, wxALL, 5); generalPage->SetSizer(generalSizer); m_treebook->AddPage(generalPage, "General"); // Display page with sub-pages wxPanel* displayPage = new wxPanel(m_treebook); wxBoxSizer* displaySizer = new wxBoxSizer(wxVERTICAL); displaySizer->Add(new wxStaticText(displayPage, wxID_ANY, "Display Settings"), 0, wxALL, 10); displaySizer->Add(new wxCheckBox(displayPage, wxID_ANY, "Anti-aliasing"), 0, wxALL, 5); displayPage->SetSizer(displaySizer); m_treebook->AddPage(displayPage, "Display"); // Display sub-page: Colors wxPanel* colorsPage = new wxPanel(m_treebook); wxBoxSizer* colorsSizer = new wxBoxSizer(wxVERTICAL); colorsSizer->Add(new wxStaticText(colorsPage, wxID_ANY, "Color Settings"), 0, wxALL, 10); colorsSizer->Add(new wxStaticText(colorsPage, wxID_ANY, "Background:"), 0, wxLEFT | wxTOP, 5); wxChoice* bgChoice = new wxChoice(colorsPage, wxID_ANY); bgChoice->Append("White"); bgChoice->Append("Black"); bgChoice->Append("Gray"); bgChoice->SetSelection(0); colorsSizer->Add(bgChoice, 0, wxALL, 5); colorsPage->SetSizer(colorsSizer); m_treebook->AddSubPage(colorsPage, "Colors"); // Display sub-page: Grid wxPanel* gridPage = new wxPanel(m_treebook); wxBoxSizer* gridSizer = new wxBoxSizer(wxVERTICAL); gridSizer->Add(new wxStaticText(gridPage, wxID_ANY, "Grid Settings"), 0, wxALL, 10); gridSizer->Add(new wxStaticText(gridPage, wxID_ANY, "Grid size (mm):"), 0, wxLEFT | wxTOP, 5); gridSizer->Add(new wxSpinCtrl(gridPage, wxID_ANY, "1", wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 1, 100, 1), 0, wxALL, 5); gridPage->SetSizer(gridSizer); m_treebook->AddSubPage(gridPage, "Grid"); // Editing page wxPanel* editPage = new wxPanel(m_treebook); wxBoxSizer* editSizer = new wxBoxSizer(wxVERTICAL); editSizer->Add(new wxStaticText(editPage, wxID_ANY, "Editing Settings"), 0, wxALL, 10); editSizer->Add(new wxCheckBox(editPage, wxID_ANY, "Magnetic pads"), 0, wxALL, 5); editSizer->Add(new wxCheckBox(editPage, wxID_ANY, "Magnetic graphics"), 0, wxALL, 5); editSizer->Add(new wxCheckBox(editPage, wxID_ANY, "Allow free pads"), 0, wxALL, 5); editPage->SetSizer(editSizer); m_treebook->AddPage(editPage, "Editing"); // Editing sub-page: Defaults wxPanel* defaultsPage = new wxPanel(m_treebook); wxBoxSizer* defaultsSizer = new wxBoxSizer(wxVERTICAL); defaultsSizer->Add(new wxStaticText(defaultsPage, wxID_ANY, "Default Values"), 0, wxALL, 10); defaultsSizer->Add(new wxStaticText(defaultsPage, wxID_ANY, "Track width (mm):"), 0, wxLEFT | wxTOP, 5); defaultsSizer->Add(new wxTextCtrl(defaultsPage, wxID_ANY, "0.25"), 0, wxALL, 5); defaultsSizer->Add(new wxStaticText(defaultsPage, wxID_ANY, "Via size (mm):"), 0, wxLEFT | wxTOP, 5); defaultsSizer->Add(new wxTextCtrl(defaultsPage, wxID_ANY, "0.8"), 0, wxALL, 5); defaultsPage->SetSizer(defaultsSizer); m_treebook->AddSubPage(defaultsPage, "Defaults"); // Printing page wxPanel* printPage = new wxPanel(m_treebook); wxBoxSizer* printSizer = new wxBoxSizer(wxVERTICAL); printSizer->Add(new wxStaticText(printPage, wxID_ANY, "Print Settings"), 0, wxALL, 10); printSizer->Add(new wxCheckBox(printPage, wxID_ANY, "Print mirrored"), 0, wxALL, 5); printSizer->Add(new wxCheckBox(printPage, wxID_ANY, "Print in black"), 0, wxALL, 5); printPage->SetSizer(printSizer); m_treebook->AddPage(printPage, "Printing"); m_treebook->Bind(wxEVT_TREEBOOK_PAGE_CHANGED, &SpecializedFrame::OnTreebookPageChanged, this); } void CreateBitmapComboBox(wxWindow* parent) { m_layerCombo = new wxBitmapComboBox(parent, wxID_ANY, "", wxDefaultPosition, wxSize(200, -1), 0, nullptr, wxCB_READONLY); // Add layers with color swatches m_layerCombo->Append("F.Cu (Top Copper)", CreateColorSwatch(*wxRED)); m_layerCombo->Append("B.Cu (Bottom Copper)", CreateColorSwatch(*wxBLUE)); m_layerCombo->Append("F.SilkS (Top Silk)", CreateColorSwatch(*wxYELLOW)); m_layerCombo->Append("B.SilkS (Bottom Silk)", CreateColorSwatch(wxColour(255, 0, 255))); m_layerCombo->Append("F.Mask (Top Mask)", CreateColorSwatch(wxColour(0, 128, 0))); m_layerCombo->Append("B.Mask (Bottom Mask)", CreateColorSwatch(wxColour(0, 128, 128))); m_layerCombo->Append("Edge.Cuts", CreateColorSwatch(*wxWHITE)); m_layerCombo->Append("Dwgs.User", CreateColorSwatch(wxColour(128, 128, 128))); m_layerCombo->SetSelection(0); m_layerCombo->Bind(wxEVT_COMBOBOX, &SpecializedFrame::OnLayerComboChanged, this); } void CreateLayerList(wxWindow* parent) { wxArrayString items; items.Add("F.Cu"); items.Add("In1.Cu"); items.Add("In2.Cu"); items.Add("B.Cu"); items.Add("F.SilkS"); items.Add("B.SilkS"); items.Add("F.Mask"); items.Add("B.Mask"); m_layerList = new wxCheckListBox(parent, wxID_ANY, wxDefaultPosition, wxSize(-1, 200), items); // Check all by default for (unsigned int i = 0; i < m_layerList->GetCount(); i++) { m_layerList->Check(i, true); } m_layerList->Bind(wxEVT_CHECKLISTBOX, &SpecializedFrame::OnLayerListCheck, this); } void OnTreebookPageChanged(wxBookCtrlEvent& event) { int page = event.GetSelection(); wxString pageName = m_treebook->GetPageText(page); Log(wxString::Format("Treebook page changed to: %s (page %d)", pageName, page)); } void OnLayerComboChanged(wxCommandEvent& event) { int sel = m_layerCombo->GetSelection(); if (sel != wxNOT_FOUND) { wxString layer = m_layerCombo->GetString(sel); m_comboLabel->SetLabel(wxString::Format("Selected: %s", layer)); Log(wxString::Format("Layer selected: %s", layer)); } } void OnLayerListCheck(wxCommandEvent& event) { int idx = event.GetInt(); bool checked = m_layerList->IsChecked(idx); wxString layer = m_layerList->GetString(idx); Log(wxString::Format("Layer %s visibility: %s", layer, checked ? "visible" : "hidden")); } void OnGetOrder(wxCommandEvent& event) { wxString orderStr = "Layer status:\n"; for (unsigned int i = 0; i < m_layerList->GetCount(); i++) { wxString layer = m_layerList->GetString(i); bool visible = m_layerList->IsChecked(i); orderStr += wxString::Format(" %d. %s [%s]\n", (int)(i + 1), layer, visible ? "visible" : "hidden"); } Log(orderStr); } void Log(const wxString& msg) { m_log->AppendText(msg + "\n"); } wxTreebook* m_treebook; wxBitmapComboBox* m_layerCombo; wxStaticText* m_comboLabel; wxCheckListBox* m_layerList; wxTextCtrl* m_log; }; class SpecializedApp : public wxApp { public: virtual bool OnInit() override { SpecializedFrame* frame = new SpecializedFrame(); frame->Show(); return true; } }; wxIMPLEMENT_APP(SpecializedApp);