Add standalone test apps and Playwright specs for wxWidgets WASM
- Add 10 standalone test apps for isolated component testing: - menu, toolbar, layout, aui, clipboard, filedialog, grid - dialog, timer, tree (3 new) - Add 12 Playwright e2e test specs for automated testing - Update Makefile with GL/non-GL build configurations - Update build script to list all standalone tests - Add WHATWORKS.md documenting KiCad wxWidgets coverage - Update .gitignore for build artifacts Test results: - 79 Playwright tests pass - wxGrid crashes (memory access out of bounds) - wxTreeCtrl crashes (similar issue) - wxDialog/wxMessageBox events fire but no visual popup 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
5918557545
commit
53e4603a41
26 changed files with 5070 additions and 30 deletions
|
|
@ -1,45 +1,143 @@
|
|||
# Makefile for wxWidgets WASM test app with OpenGL support
|
||||
# Uses the local wxWidgets build with legacy GL emulation
|
||||
# Makefile for wxWidgets WASM test apps
|
||||
# Uses the local wxWidgets build
|
||||
|
||||
WXCONFIG = ../../build-wasm/wxwidgets-universal/wx-config
|
||||
TOOLS_ROOT = ../../wxwidgets/build/wasm
|
||||
|
||||
CXX = em++
|
||||
WX_CXXFLAGS := $(shell $(WXCONFIG) --cxxflags)
|
||||
# Include GL library for OpenGL tests
|
||||
WX_LDFLAGS := $(shell $(WXCONFIG) --libs base,core,gl)
|
||||
|
||||
TARGET = minimal_test
|
||||
SOURCES = minimal_test.cpp
|
||||
# Libraries for GL apps (minimal_test uses OpenGL)
|
||||
WX_LDFLAGS_GL := $(shell $(WXCONFIG) --libs base,core,gl,aui)
|
||||
|
||||
# Libraries for non-GL apps (standalone tests don't need GL)
|
||||
WX_LDFLAGS_NOGL := $(shell $(WXCONFIG) --libs base,core,aui)
|
||||
|
||||
CXXFLAGS = -O2 $(WX_CXXFLAGS)
|
||||
|
||||
# Emscripten flags:
|
||||
# -sLEGACY_GL_EMULATION: Enable legacy OpenGL (glBegin/glEnd, etc.) emulation on WebGL
|
||||
# -sMAX_WEBGL_VERSION=2: Enable WebGL 2.0 support (required since wxGLCanvas requests WebGL 2)
|
||||
# Note: Cannot combine LEGACY_GL_EMULATION with FULL_ES2 - they are mutually exclusive
|
||||
EM_GL_FLAGS = -sLEGACY_GL_EMULATION -sMAX_WEBGL_VERSION=2
|
||||
# Base Emscripten flags (for all apps)
|
||||
BASE_LDFLAGS = -sALLOW_MEMORY_GROWTH -sERROR_ON_UNDEFINED_SYMBOLS=0 \
|
||||
-s "EXPORTED_RUNTIME_METHODS=['HEAPU8','HEAP8','HEAP32']"
|
||||
|
||||
# GL immediate mode shim - fixes Emscripten's color-per-vertex requirement
|
||||
# and provides missing glVertex2d/glColor4d implementations
|
||||
# GL-specific flags
|
||||
EM_GL_FLAGS = -sLEGACY_GL_EMULATION -sMAX_WEBGL_VERSION=2
|
||||
GL_SHIM = ../../lib/gl_immediate_shim.js
|
||||
|
||||
LDFLAGS = -sALLOW_MEMORY_GROWTH -sERROR_ON_UNDEFINED_SYMBOLS=0 \
|
||||
-s "EXPORTED_RUNTIME_METHODS=['HEAPU8','HEAP8','HEAP32']" \
|
||||
$(EM_GL_FLAGS) --js-library=$(GL_SHIM) $(WX_LDFLAGS)
|
||||
# LDFLAGS for GL apps (minimal_test)
|
||||
LDFLAGS_GL = $(BASE_LDFLAGS) $(EM_GL_FLAGS) --js-library=$(GL_SHIM) $(WX_LDFLAGS_GL)
|
||||
|
||||
# LDFLAGS for non-GL apps (standalone tests)
|
||||
LDFLAGS_NOGL = $(BASE_LDFLAGS) $(WX_LDFLAGS_NOGL)
|
||||
|
||||
JS = $(TOOLS_ROOT)/wx.js
|
||||
HTML = $(TOOLS_ROOT)/template.html
|
||||
|
||||
all: $(TARGET).html
|
||||
# Standalone directories
|
||||
S = standalone
|
||||
|
||||
$(TARGET).o: $(SOURCES)
|
||||
all: minimal_test.html \
|
||||
$(S)/menu/menu_test.html \
|
||||
$(S)/clipboard/clipboard_test.html \
|
||||
$(S)/filedialog/filedialog_test.html \
|
||||
$(S)/layout/layout_test.html \
|
||||
$(S)/aui/aui_test.html \
|
||||
$(S)/toolbar/toolbar_test.html \
|
||||
$(S)/grid/grid_test.html \
|
||||
$(S)/dialog/dialog_test.html \
|
||||
$(S)/timer/timer_test.html \
|
||||
$(S)/tree/tree_test.html
|
||||
|
||||
# Main test app (uses GL)
|
||||
minimal_test.o: minimal_test.cpp
|
||||
$(CXX) -c $(CXXFLAGS) $< -o $@
|
||||
|
||||
$(TARGET).html: $(TARGET).o
|
||||
$(CXX) $(TARGET).o $(LDFLAGS) --pre-js $(JS) --shell-file $(HTML) -o $@
|
||||
minimal_test.html: minimal_test.o
|
||||
$(CXX) $< $(LDFLAGS_GL) --pre-js $(JS) --shell-file $(HTML) -o $@
|
||||
|
||||
# Menu test (no GL)
|
||||
$(S)/menu/menu_test.o: $(S)/menu/menu_test.cpp
|
||||
$(CXX) -c $(CXXFLAGS) $< -o $@
|
||||
|
||||
$(S)/menu/menu_test.html: $(S)/menu/menu_test.o
|
||||
$(CXX) $< $(LDFLAGS_NOGL) --pre-js $(JS) --shell-file $(HTML) -o $@
|
||||
|
||||
# Clipboard test (no GL)
|
||||
$(S)/clipboard/clipboard_test.o: $(S)/clipboard/clipboard_test.cpp
|
||||
$(CXX) -c $(CXXFLAGS) $< -o $@
|
||||
|
||||
$(S)/clipboard/clipboard_test.html: $(S)/clipboard/clipboard_test.o
|
||||
$(CXX) $< $(LDFLAGS_NOGL) --pre-js $(JS) --shell-file $(HTML) -o $@
|
||||
|
||||
# FileDialog test (no GL)
|
||||
$(S)/filedialog/filedialog_test.o: $(S)/filedialog/filedialog_test.cpp
|
||||
$(CXX) -c $(CXXFLAGS) $< -o $@
|
||||
|
||||
$(S)/filedialog/filedialog_test.html: $(S)/filedialog/filedialog_test.o
|
||||
$(CXX) $< $(LDFLAGS_NOGL) --pre-js $(JS) --shell-file $(HTML) -o $@
|
||||
|
||||
# Layout test (no GL)
|
||||
$(S)/layout/layout_test.o: $(S)/layout/layout_test.cpp
|
||||
$(CXX) -c $(CXXFLAGS) $< -o $@
|
||||
|
||||
$(S)/layout/layout_test.html: $(S)/layout/layout_test.o
|
||||
$(CXX) $< $(LDFLAGS_NOGL) --pre-js $(JS) --shell-file $(HTML) -o $@
|
||||
|
||||
# AUI test (no GL)
|
||||
$(S)/aui/aui_test.o: $(S)/aui/aui_test.cpp
|
||||
$(CXX) -c $(CXXFLAGS) $< -o $@
|
||||
|
||||
$(S)/aui/aui_test.html: $(S)/aui/aui_test.o
|
||||
$(CXX) $< $(LDFLAGS_NOGL) --pre-js $(JS) --shell-file $(HTML) -o $@
|
||||
|
||||
# Toolbar test (no GL)
|
||||
$(S)/toolbar/toolbar_test.o: $(S)/toolbar/toolbar_test.cpp
|
||||
$(CXX) -c $(CXXFLAGS) $< -o $@
|
||||
|
||||
$(S)/toolbar/toolbar_test.html: $(S)/toolbar/toolbar_test.o
|
||||
$(CXX) $< $(LDFLAGS_NOGL) --pre-js $(JS) --shell-file $(HTML) -o $@
|
||||
|
||||
# Grid test (no GL)
|
||||
$(S)/grid/grid_test.o: $(S)/grid/grid_test.cpp
|
||||
$(CXX) -c $(CXXFLAGS) $< -o $@
|
||||
|
||||
$(S)/grid/grid_test.html: $(S)/grid/grid_test.o
|
||||
$(CXX) $< $(LDFLAGS_NOGL) --pre-js $(JS) --shell-file $(HTML) -o $@
|
||||
|
||||
# Dialog test (no GL)
|
||||
$(S)/dialog/dialog_test.o: $(S)/dialog/dialog_test.cpp
|
||||
$(CXX) -c $(CXXFLAGS) $< -o $@
|
||||
|
||||
$(S)/dialog/dialog_test.html: $(S)/dialog/dialog_test.o
|
||||
$(CXX) $< $(LDFLAGS_NOGL) --pre-js $(JS) --shell-file $(HTML) -o $@
|
||||
|
||||
# Timer test (no GL)
|
||||
$(S)/timer/timer_test.o: $(S)/timer/timer_test.cpp
|
||||
$(CXX) -c $(CXXFLAGS) $< -o $@
|
||||
|
||||
$(S)/timer/timer_test.html: $(S)/timer/timer_test.o
|
||||
$(CXX) $< $(LDFLAGS_NOGL) --pre-js $(JS) --shell-file $(HTML) -o $@
|
||||
|
||||
# Tree test (no GL)
|
||||
$(S)/tree/tree_test.o: $(S)/tree/tree_test.cpp
|
||||
$(CXX) -c $(CXXFLAGS) $< -o $@
|
||||
|
||||
$(S)/tree/tree_test.html: $(S)/tree/tree_test.o
|
||||
$(CXX) $< $(LDFLAGS_NOGL) --pre-js $(JS) --shell-file $(HTML) -o $@
|
||||
|
||||
# Convenience targets
|
||||
menu: $(S)/menu/menu_test.html
|
||||
clipboard: $(S)/clipboard/clipboard_test.html
|
||||
filedialog: $(S)/filedialog/filedialog_test.html
|
||||
layout: $(S)/layout/layout_test.html
|
||||
aui: $(S)/aui/aui_test.html
|
||||
toolbar: $(S)/toolbar/toolbar_test.html
|
||||
grid: $(S)/grid/grid_test.html
|
||||
dialog: $(S)/dialog/dialog_test.html
|
||||
timer: $(S)/timer/timer_test.html
|
||||
tree: $(S)/tree/tree_test.html
|
||||
|
||||
clean:
|
||||
rm -f $(TARGET).o $(TARGET).html $(TARGET).js $(TARGET).wasm
|
||||
rm -f minimal_test.o minimal_test.html minimal_test.js minimal_test.wasm
|
||||
rm -f $(S)/*/*.o $(S)/*/*.html $(S)/*/*.js $(S)/*/*.wasm
|
||||
|
||||
.PHONY: all clean
|
||||
.PHONY: all clean menu clipboard filedialog layout aui toolbar grid dialog timer tree
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@
|
|||
#include "wx/dcbuffer.h"
|
||||
#include "wx/datetime.h"
|
||||
#include "wx/glcanvas.h"
|
||||
#include "wx/grid.h"
|
||||
#include "wx/spinctrl.h"
|
||||
#include "wx/srchctrl.h"
|
||||
|
||||
// OpenGL headers - using legacy GL with Emscripten's emulation
|
||||
#ifdef __EMSCRIPTEN__
|
||||
|
|
@ -61,7 +64,19 @@ enum {
|
|||
ID_BTN_GL_TEST_MATRIX,
|
||||
ID_BTN_GL_TEST_VERTEX_ARRAY,
|
||||
ID_BTN_GL_RUN_ALL,
|
||||
ID_GL_TEST_SELECT
|
||||
ID_GL_TEST_SELECT,
|
||||
// Grid tab IDs
|
||||
ID_GRID,
|
||||
ID_SPIN_CTRL,
|
||||
ID_SEARCH_CTRL,
|
||||
// Dialogs tab IDs
|
||||
ID_BTN_MSGBOX_INFO,
|
||||
ID_BTN_MSGBOX_YESNO,
|
||||
ID_BTN_MSGBOX_ERROR,
|
||||
ID_BTN_CUSTOM_DIALOG,
|
||||
ID_BTN_TIMER_START,
|
||||
ID_BTN_TIMER_STOP,
|
||||
ID_TIMER
|
||||
};
|
||||
|
||||
// Forward declarations
|
||||
|
|
@ -638,6 +653,14 @@ private:
|
|||
wxListBox* m_listBox;
|
||||
GLTestCanvas* m_glCanvas;
|
||||
wxChoice* m_glTestChoice;
|
||||
// Grid tab controls
|
||||
wxGrid* m_grid;
|
||||
wxSpinCtrl* m_spinCtrl;
|
||||
wxSearchCtrl* m_searchCtrl;
|
||||
// Dialogs tab controls
|
||||
wxTimer* m_timer;
|
||||
wxStaticText* m_timerLabel;
|
||||
int m_timerCount;
|
||||
|
||||
// Create tab pages
|
||||
wxPanel* CreateControlsPage(wxNotebook* parent);
|
||||
|
|
@ -645,6 +668,8 @@ private:
|
|||
wxPanel* CreateDrawingPage(wxNotebook* parent);
|
||||
wxPanel* CreateListsPage(wxNotebook* parent);
|
||||
wxPanel* CreateOpenGLPage(wxNotebook* parent);
|
||||
wxPanel* CreateGridPage(wxNotebook* parent);
|
||||
wxPanel* CreateDialogsPage(wxNotebook* parent);
|
||||
|
||||
// Event handlers
|
||||
void OnQuit(wxCommandEvent& evt);
|
||||
|
|
@ -665,6 +690,20 @@ private:
|
|||
void OnNotebookPageChanged(wxBookCtrlEvent& evt);
|
||||
void OnGLTestSelect(wxCommandEvent& evt);
|
||||
void OnGLRunAll(wxCommandEvent& evt);
|
||||
// Grid tab event handlers
|
||||
void OnGridCellChange(wxGridEvent& evt);
|
||||
void OnGridCellSelect(wxGridEvent& evt);
|
||||
void OnSpinCtrl(wxSpinEvent& evt);
|
||||
void OnSearchCtrl(wxCommandEvent& evt);
|
||||
void OnSearchCtrlEnter(wxCommandEvent& evt);
|
||||
// Dialogs tab event handlers
|
||||
void OnMsgBoxInfo(wxCommandEvent& evt);
|
||||
void OnMsgBoxYesNo(wxCommandEvent& evt);
|
||||
void OnMsgBoxError(wxCommandEvent& evt);
|
||||
void OnCustomDialog(wxCommandEvent& evt);
|
||||
void OnTimerStart(wxCommandEvent& evt);
|
||||
void OnTimerStop(wxCommandEvent& evt);
|
||||
void OnTimer(wxTimerEvent& evt);
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
|
@ -688,6 +727,20 @@ wxBEGIN_EVENT_TABLE(TestFrame, wxFrame)
|
|||
EVT_NOTEBOOK_PAGE_CHANGED(wxID_ANY, TestFrame::OnNotebookPageChanged)
|
||||
EVT_CHOICE(ID_GL_TEST_SELECT, TestFrame::OnGLTestSelect)
|
||||
EVT_BUTTON(ID_BTN_GL_RUN_ALL, TestFrame::OnGLRunAll)
|
||||
// Grid tab events
|
||||
EVT_GRID_CELL_CHANGED(TestFrame::OnGridCellChange)
|
||||
EVT_GRID_SELECT_CELL(TestFrame::OnGridCellSelect)
|
||||
EVT_SPINCTRL(ID_SPIN_CTRL, TestFrame::OnSpinCtrl)
|
||||
EVT_SEARCHCTRL_SEARCH_BTN(ID_SEARCH_CTRL, TestFrame::OnSearchCtrl)
|
||||
EVT_TEXT_ENTER(ID_SEARCH_CTRL, TestFrame::OnSearchCtrlEnter)
|
||||
// Dialogs tab events
|
||||
EVT_BUTTON(ID_BTN_MSGBOX_INFO, TestFrame::OnMsgBoxInfo)
|
||||
EVT_BUTTON(ID_BTN_MSGBOX_YESNO, TestFrame::OnMsgBoxYesNo)
|
||||
EVT_BUTTON(ID_BTN_MSGBOX_ERROR, TestFrame::OnMsgBoxError)
|
||||
EVT_BUTTON(ID_BTN_CUSTOM_DIALOG, TestFrame::OnCustomDialog)
|
||||
EVT_BUTTON(ID_BTN_TIMER_START, TestFrame::OnTimerStart)
|
||||
EVT_BUTTON(ID_BTN_TIMER_STOP, TestFrame::OnTimerStop)
|
||||
EVT_TIMER(ID_TIMER, TestFrame::OnTimer)
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
TestFrame::TestFrame(const wxString& title)
|
||||
|
|
@ -721,6 +774,8 @@ TestFrame::TestFrame(const wxString& title)
|
|||
m_notebook->AddPage(CreateDrawingPage(m_notebook), "Drawing");
|
||||
m_notebook->AddPage(CreateListsPage(m_notebook), "Lists");
|
||||
m_notebook->AddPage(CreateOpenGLPage(m_notebook), "OpenGL");
|
||||
m_notebook->AddPage(CreateGridPage(m_notebook), "Grid");
|
||||
m_notebook->AddPage(CreateDialogsPage(m_notebook), "Dialogs");
|
||||
|
||||
mainSizer->Add(m_notebook, 1, wxEXPAND | wxALL, 5);
|
||||
|
||||
|
|
@ -979,6 +1034,65 @@ wxPanel* TestFrame::CreateOpenGLPage(wxNotebook* parent)
|
|||
return panel;
|
||||
}
|
||||
|
||||
wxPanel* TestFrame::CreateGridPage(wxNotebook* parent)
|
||||
{
|
||||
wxPanel* panel = new wxPanel(parent);
|
||||
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
// Description
|
||||
wxStaticText* desc = new wxStaticText(panel, wxID_ANY,
|
||||
"Advanced Controls Test\n"
|
||||
"Tests wxSpinCtrl and wxSearchCtrl which KiCad uses extensively.\n"
|
||||
"NOTE: wxGrid is NOT YET SUPPORTED in WASM (causes function signature mismatch crash).");
|
||||
mainSizer->Add(desc, 0, wxALL, 10);
|
||||
|
||||
// wxGrid - DISABLED: causes "function signature mismatch" crash in WASM
|
||||
// This needs to be fixed in wxWidgets WASM port before we can test it
|
||||
/*
|
||||
wxStaticBox* gridBox = new wxStaticBox(panel, wxID_ANY, "wxGrid (editable cells)");
|
||||
wxStaticBoxSizer* gridSizer = new wxStaticBoxSizer(gridBox, wxVERTICAL);
|
||||
m_grid = new wxGrid(panel, ID_GRID, wxDefaultPosition, wxSize(400, 150));
|
||||
m_grid->CreateGrid(5, 4);
|
||||
// ... grid setup ...
|
||||
gridSizer->Add(m_grid, 1, wxEXPAND | wxALL, 5);
|
||||
mainSizer->Add(gridSizer, 1, wxEXPAND | wxALL, 5);
|
||||
*/
|
||||
m_grid = nullptr; // wxGrid not supported in WASM yet
|
||||
|
||||
// Row with wxSpinCtrl and wxSearchCtrl
|
||||
wxBoxSizer* controlRow = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
// wxSpinCtrl
|
||||
wxStaticBox* spinBox = new wxStaticBox(panel, wxID_ANY, "wxSpinCtrl");
|
||||
wxStaticBoxSizer* spinSizer = new wxStaticBoxSizer(spinBox, wxHORIZONTAL);
|
||||
|
||||
spinSizer->Add(new wxStaticText(panel, wxID_ANY, "Value (0-100):"), 0,
|
||||
wxALL | wxALIGN_CENTER_VERTICAL, 5);
|
||||
m_spinCtrl = new wxSpinCtrl(panel, ID_SPIN_CTRL, "50",
|
||||
wxDefaultPosition, wxSize(80, -1), wxSP_ARROW_KEYS, 0, 100, 50);
|
||||
spinSizer->Add(m_spinCtrl, 0, wxALL, 5);
|
||||
|
||||
controlRow->Add(spinSizer, 0, wxALL, 5);
|
||||
|
||||
// wxSearchCtrl
|
||||
wxStaticBox* searchBox = new wxStaticBox(panel, wxID_ANY, "wxSearchCtrl");
|
||||
wxStaticBoxSizer* searchSizer = new wxStaticBoxSizer(searchBox, wxHORIZONTAL);
|
||||
|
||||
m_searchCtrl = new wxSearchCtrl(panel, ID_SEARCH_CTRL, "",
|
||||
wxDefaultPosition, wxSize(200, -1), wxTE_PROCESS_ENTER);
|
||||
m_searchCtrl->ShowSearchButton(true);
|
||||
m_searchCtrl->ShowCancelButton(true);
|
||||
m_searchCtrl->SetDescriptiveText("Search...");
|
||||
searchSizer->Add(m_searchCtrl, 1, wxALL | wxEXPAND, 5);
|
||||
|
||||
controlRow->Add(searchSizer, 1, wxALL | wxEXPAND, 5);
|
||||
|
||||
mainSizer->Add(controlRow, 0, wxEXPAND);
|
||||
|
||||
panel->SetSizer(mainSizer);
|
||||
return panel;
|
||||
}
|
||||
|
||||
// Event handlers
|
||||
void TestFrame::OnQuit(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
|
|
@ -1111,6 +1225,45 @@ void TestFrame::OnGLRunAll(wxCommandEvent& WXUNUSED(evt))
|
|||
LogEvent("All GL tests completed - check console for detailed results");
|
||||
}
|
||||
|
||||
// Grid tab event handlers
|
||||
void TestFrame::OnGridCellChange(wxGridEvent& evt)
|
||||
{
|
||||
if (!m_grid) { evt.Skip(); return; } // wxGrid not supported in WASM
|
||||
int row = evt.GetRow();
|
||||
int col = evt.GetCol();
|
||||
wxString value = m_grid->GetCellValue(row, col);
|
||||
LogEvent(wxString::Format("Grid cell changed: [%d,%d] = \"%s\"", row, col, value));
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
void TestFrame::OnGridCellSelect(wxGridEvent& evt)
|
||||
{
|
||||
if (!m_grid) { evt.Skip(); return; } // wxGrid not supported in WASM
|
||||
int row = evt.GetRow();
|
||||
int col = evt.GetCol();
|
||||
wxString value = m_grid->GetCellValue(row, col);
|
||||
LogEvent(wxString::Format("Grid cell selected: [%d,%d] \"%s\"", row, col, value));
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
void TestFrame::OnSpinCtrl(wxSpinEvent& evt)
|
||||
{
|
||||
int value = evt.GetValue();
|
||||
LogEvent(wxString::Format("SpinCtrl value: %d", value));
|
||||
}
|
||||
|
||||
void TestFrame::OnSearchCtrl(wxCommandEvent& evt)
|
||||
{
|
||||
wxString text = m_searchCtrl->GetValue();
|
||||
LogEvent(wxString::Format("Search button clicked: \"%s\"", text));
|
||||
}
|
||||
|
||||
void TestFrame::OnSearchCtrlEnter(wxCommandEvent& evt)
|
||||
{
|
||||
wxString text = evt.GetString();
|
||||
LogEvent(wxString::Format("Search Enter pressed: \"%s\"", text));
|
||||
}
|
||||
|
||||
// DrawingPanel event handlers (defined after TestFrame for g_frame access)
|
||||
void DrawingPanel::OnMouseDown(wxMouseEvent& evt)
|
||||
{
|
||||
|
|
@ -1169,6 +1322,151 @@ void DrawingPanel::OnMouseLeave(wxMouseEvent& WXUNUSED(evt))
|
|||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CreateDialogsPage - Dialogs tab with message boxes and timer
|
||||
//-----------------------------------------------------------------------------
|
||||
wxPanel* TestFrame::CreateDialogsPage(wxNotebook* parent)
|
||||
{
|
||||
wxPanel* panel = new wxPanel(parent);
|
||||
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
// Description
|
||||
wxStaticText* desc = new wxStaticText(panel, wxID_ANY,
|
||||
"Dialog and Timer Tests\n"
|
||||
"Tests wxMessageBox, wxDialog, and wxTimer which KiCad uses for alerts and animations.");
|
||||
mainSizer->Add(desc, 0, wxALL, 10);
|
||||
|
||||
// Message Box section
|
||||
wxStaticBox* msgBox = new wxStaticBox(panel, wxID_ANY, "wxMessageBox");
|
||||
wxStaticBoxSizer* msgSizer = new wxStaticBoxSizer(msgBox, wxHORIZONTAL);
|
||||
|
||||
wxButton* btnInfo = new wxButton(panel, ID_BTN_MSGBOX_INFO, "Info Dialog");
|
||||
wxButton* btnYesNo = new wxButton(panel, ID_BTN_MSGBOX_YESNO, "Yes/No Dialog");
|
||||
wxButton* btnError = new wxButton(panel, ID_BTN_MSGBOX_ERROR, "Error Dialog");
|
||||
|
||||
msgSizer->Add(btnInfo, 0, wxALL, 5);
|
||||
msgSizer->Add(btnYesNo, 0, wxALL, 5);
|
||||
msgSizer->Add(btnError, 0, wxALL, 5);
|
||||
|
||||
mainSizer->Add(msgSizer, 0, wxEXPAND | wxALL, 10);
|
||||
|
||||
// Custom Dialog section
|
||||
wxStaticBox* dlgBox = new wxStaticBox(panel, wxID_ANY, "wxDialog");
|
||||
wxStaticBoxSizer* dlgSizer = new wxStaticBoxSizer(dlgBox, wxHORIZONTAL);
|
||||
|
||||
wxButton* btnCustom = new wxButton(panel, ID_BTN_CUSTOM_DIALOG, "Open Custom Dialog");
|
||||
dlgSizer->Add(btnCustom, 0, wxALL, 5);
|
||||
dlgSizer->Add(new wxStaticText(panel, wxID_ANY,
|
||||
"Opens a modal dialog with OK/Cancel buttons"), 0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
|
||||
|
||||
mainSizer->Add(dlgSizer, 0, wxEXPAND | wxALL, 10);
|
||||
|
||||
// Timer section
|
||||
wxStaticBox* timerBox = new wxStaticBox(panel, wxID_ANY, "wxTimer");
|
||||
wxStaticBoxSizer* timerSizer = new wxStaticBoxSizer(timerBox, wxVERTICAL);
|
||||
|
||||
wxBoxSizer* timerBtnSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxButton* btnStart = new wxButton(panel, ID_BTN_TIMER_START, "Start Timer");
|
||||
wxButton* btnStop = new wxButton(panel, ID_BTN_TIMER_STOP, "Stop Timer");
|
||||
timerBtnSizer->Add(btnStart, 0, wxALL, 5);
|
||||
timerBtnSizer->Add(btnStop, 0, wxALL, 5);
|
||||
timerSizer->Add(timerBtnSizer, 0, wxALIGN_CENTER);
|
||||
|
||||
m_timerLabel = new wxStaticText(panel, wxID_ANY, "Timer: 0");
|
||||
wxFont font = m_timerLabel->GetFont();
|
||||
font.SetPointSize(16);
|
||||
m_timerLabel->SetFont(font);
|
||||
timerSizer->Add(m_timerLabel, 0, wxALL | wxALIGN_CENTER, 10);
|
||||
|
||||
mainSizer->Add(timerSizer, 0, wxEXPAND | wxALL, 10);
|
||||
|
||||
// Initialize timer
|
||||
m_timer = new wxTimer(this, ID_TIMER);
|
||||
m_timerCount = 0;
|
||||
|
||||
panel->SetSizer(mainSizer);
|
||||
return panel;
|
||||
}
|
||||
|
||||
// Dialogs tab event handlers
|
||||
void TestFrame::OnMsgBoxInfo(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Showing Info message box");
|
||||
wxMessageBox("This is an information message.\n\nwxMessageBox is used throughout KiCad for notifications.",
|
||||
"Information",
|
||||
wxOK | wxICON_INFORMATION, this);
|
||||
LogEvent("Info message box closed");
|
||||
}
|
||||
|
||||
void TestFrame::OnMsgBoxYesNo(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Showing Yes/No message box");
|
||||
int result = wxMessageBox("Do you want to proceed?\n\nThis tests wxYES_NO style dialogs.",
|
||||
"Confirm Action",
|
||||
wxYES_NO | wxICON_QUESTION, this);
|
||||
LogEvent(wxString::Format("User clicked: %s", result == wxYES ? "Yes" : "No"));
|
||||
}
|
||||
|
||||
void TestFrame::OnMsgBoxError(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Showing Error message box");
|
||||
wxMessageBox("An error has occurred!\n\nThis tests wxICON_ERROR style dialogs.",
|
||||
"Error",
|
||||
wxOK | wxICON_ERROR, this);
|
||||
LogEvent("Error message box closed");
|
||||
}
|
||||
|
||||
void TestFrame::OnCustomDialog(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Opening custom dialog");
|
||||
|
||||
// Create a simple custom dialog
|
||||
wxDialog dlg(this, wxID_ANY, "Custom Dialog",
|
||||
wxDefaultPosition, wxSize(300, 200));
|
||||
|
||||
wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
sizer->Add(new wxStaticText(&dlg, wxID_ANY,
|
||||
"This is a custom wxDialog.\n\n"
|
||||
"KiCad uses wxDialog extensively for\n"
|
||||
"property editors, settings panels, etc."),
|
||||
1, wxALL | wxEXPAND, 20);
|
||||
|
||||
wxBoxSizer* btnSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
btnSizer->Add(new wxButton(&dlg, wxID_OK, "OK"), 0, wxALL, 5);
|
||||
btnSizer->Add(new wxButton(&dlg, wxID_CANCEL, "Cancel"), 0, wxALL, 5);
|
||||
sizer->Add(btnSizer, 0, wxALIGN_CENTER | wxBOTTOM, 10);
|
||||
|
||||
dlg.SetSizer(sizer);
|
||||
|
||||
int result = dlg.ShowModal();
|
||||
LogEvent(wxString::Format("Custom dialog closed with: %s",
|
||||
result == wxID_OK ? "OK" : "Cancel"));
|
||||
}
|
||||
|
||||
void TestFrame::OnTimerStart(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
if (!m_timer->IsRunning()) {
|
||||
m_timer->Start(1000); // 1 second interval
|
||||
LogEvent("Timer started (1 second interval)");
|
||||
}
|
||||
}
|
||||
|
||||
void TestFrame::OnTimerStop(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
if (m_timer->IsRunning()) {
|
||||
m_timer->Stop();
|
||||
LogEvent("Timer stopped");
|
||||
}
|
||||
}
|
||||
|
||||
void TestFrame::OnTimer(wxTimerEvent& WXUNUSED(evt))
|
||||
{
|
||||
m_timerCount++;
|
||||
m_timerLabel->SetLabel(wxString::Format("Timer: %d", m_timerCount));
|
||||
LogEvent(wxString::Format("Timer tick: %d", m_timerCount));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TestApp - Application class
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
143
tests/wasm-app/standalone/aui/aui_test.cpp
Normal file
143
tests/wasm-app/standalone/aui/aui_test.cpp
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
// wxAuiManager Test - Tests AUI docking functionality in WASM
|
||||
// KiCad uses AUI extensively for dockable panels
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/wx.h"
|
||||
#endif
|
||||
|
||||
#include "wx/aui/aui.h"
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten/emscripten.h>
|
||||
#endif
|
||||
|
||||
class AuiTestApp : public wxApp
|
||||
{
|
||||
public:
|
||||
virtual bool OnInit() override;
|
||||
};
|
||||
|
||||
class AuiTestFrame : public wxFrame
|
||||
{
|
||||
public:
|
||||
AuiTestFrame();
|
||||
~AuiTestFrame();
|
||||
|
||||
private:
|
||||
wxAuiManager m_mgr;
|
||||
wxTextCtrl* m_log;
|
||||
|
||||
void LogEvent(const wxString& msg);
|
||||
void OnPaneClose(wxAuiManagerEvent& evt);
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
wxBEGIN_EVENT_TABLE(AuiTestFrame, wxFrame)
|
||||
EVT_AUI_PANE_CLOSE(AuiTestFrame::OnPaneClose)
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
wxIMPLEMENT_APP(AuiTestApp);
|
||||
|
||||
bool AuiTestApp::OnInit()
|
||||
{
|
||||
if (!wxApp::OnInit())
|
||||
return false;
|
||||
|
||||
AuiTestFrame* frame = new AuiTestFrame();
|
||||
frame->Show(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
AuiTestFrame::AuiTestFrame()
|
||||
: wxFrame(nullptr, wxID_ANY, "wxAuiManager WASM Test",
|
||||
wxDefaultPosition, wxSize(800, 600))
|
||||
{
|
||||
m_mgr.SetManagedWindow(this);
|
||||
|
||||
// Create center pane with event log
|
||||
m_log = new wxTextCtrl(this, wxID_ANY, "",
|
||||
wxDefaultPosition, wxDefaultSize,
|
||||
wxTE_MULTILINE | wxTE_READONLY);
|
||||
m_mgr.AddPane(m_log, wxAuiPaneInfo().Name("log").Caption("Event Log")
|
||||
.Center().CloseButton(false));
|
||||
|
||||
// Create left panel (like KiCad's properties panel)
|
||||
wxPanel* leftPanel = new wxPanel(this);
|
||||
leftPanel->SetBackgroundColour(*wxLIGHT_GREY);
|
||||
wxBoxSizer* leftSizer = new wxBoxSizer(wxVERTICAL);
|
||||
leftSizer->Add(new wxStaticText(leftPanel, wxID_ANY, "Properties Panel"), 0, wxALL, 10);
|
||||
leftSizer->Add(new wxStaticText(leftPanel, wxID_ANY, "Like KiCad's"), 0, wxALL, 5);
|
||||
leftSizer->Add(new wxStaticText(leftPanel, wxID_ANY, "property editor"), 0, wxALL, 5);
|
||||
leftPanel->SetSizer(leftSizer);
|
||||
|
||||
m_mgr.AddPane(leftPanel, wxAuiPaneInfo().Name("properties").Caption("Properties")
|
||||
.Left().Layer(1).Position(1).CloseButton(true).MaximizeButton(true)
|
||||
.MinSize(150, 200));
|
||||
|
||||
// Create right panel (like KiCad's layer manager)
|
||||
wxPanel* rightPanel = new wxPanel(this);
|
||||
rightPanel->SetBackgroundColour(wxColour(240, 240, 255));
|
||||
wxBoxSizer* rightSizer = new wxBoxSizer(wxVERTICAL);
|
||||
rightSizer->Add(new wxStaticText(rightPanel, wxID_ANY, "Layers Panel"), 0, wxALL, 10);
|
||||
rightSizer->Add(new wxStaticText(rightPanel, wxID_ANY, "Like KiCad's"), 0, wxALL, 5);
|
||||
rightSizer->Add(new wxStaticText(rightPanel, wxID_ANY, "layer manager"), 0, wxALL, 5);
|
||||
rightPanel->SetSizer(rightSizer);
|
||||
|
||||
m_mgr.AddPane(rightPanel, wxAuiPaneInfo().Name("layers").Caption("Layers")
|
||||
.Right().Layer(1).Position(1).CloseButton(true).MaximizeButton(true)
|
||||
.MinSize(150, 200));
|
||||
|
||||
// Create bottom panel (like KiCad's message panel)
|
||||
wxPanel* bottomPanel = new wxPanel(this);
|
||||
bottomPanel->SetBackgroundColour(wxColour(255, 255, 240));
|
||||
wxBoxSizer* bottomSizer = new wxBoxSizer(wxVERTICAL);
|
||||
bottomSizer->Add(new wxStaticText(bottomPanel, wxID_ANY,
|
||||
"Message Panel - Like KiCad's message area"), 0, wxALL, 5);
|
||||
bottomPanel->SetSizer(bottomSizer);
|
||||
|
||||
m_mgr.AddPane(bottomPanel, wxAuiPaneInfo().Name("messages").Caption("Messages")
|
||||
.Bottom().Layer(0).Position(1).CloseButton(true)
|
||||
.MinSize(-1, 80));
|
||||
|
||||
m_mgr.Update();
|
||||
|
||||
CreateStatusBar();
|
||||
SetStatusText("AUI Manager ready - try dragging and docking panels");
|
||||
|
||||
LogEvent("AUI test app started");
|
||||
LogEvent("Created dockable panels: Properties, Layers, Messages");
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM({
|
||||
console.log('[AUI_TEST] wxAuiManager test app started successfully');
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
AuiTestFrame::~AuiTestFrame()
|
||||
{
|
||||
m_mgr.UnInit();
|
||||
}
|
||||
|
||||
void AuiTestFrame::LogEvent(const wxString& msg)
|
||||
{
|
||||
m_log->AppendText(msg + "\n");
|
||||
SetStatusText(msg);
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM({
|
||||
console.log('[AUI_EVENT] ' + UTF8ToString($0));
|
||||
}, msg.c_str().AsChar());
|
||||
#endif
|
||||
}
|
||||
|
||||
void AuiTestFrame::OnPaneClose(wxAuiManagerEvent& evt)
|
||||
{
|
||||
wxAuiPaneInfo* pane = evt.GetPane();
|
||||
if (pane) {
|
||||
LogEvent(wxString::Format("Pane closing: %s", pane->name));
|
||||
}
|
||||
}
|
||||
213
tests/wasm-app/standalone/clipboard/clipboard_test.cpp
Normal file
213
tests/wasm-app/standalone/clipboard/clipboard_test.cpp
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
// wxClipboard Test - Tests clipboard functionality in WASM
|
||||
// KiCad uses clipboard for copy/paste of schematic symbols, PCB components, text
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/wx.h"
|
||||
#endif
|
||||
|
||||
#include "wx/clipbrd.h"
|
||||
#include "wx/dataobj.h"
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten/emscripten.h>
|
||||
#endif
|
||||
|
||||
class ClipboardTestApp : public wxApp
|
||||
{
|
||||
public:
|
||||
virtual bool OnInit() override;
|
||||
};
|
||||
|
||||
class ClipboardTestFrame : public wxFrame
|
||||
{
|
||||
public:
|
||||
ClipboardTestFrame();
|
||||
|
||||
private:
|
||||
wxTextCtrl* m_input;
|
||||
wxTextCtrl* m_output;
|
||||
wxTextCtrl* m_log;
|
||||
|
||||
void LogEvent(const wxString& msg);
|
||||
|
||||
void OnCopyText(wxCommandEvent& evt);
|
||||
void OnPasteText(wxCommandEvent& evt);
|
||||
void OnClearClipboard(wxCommandEvent& evt);
|
||||
void OnCheckClipboard(wxCommandEvent& evt);
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
enum {
|
||||
ID_COPY_TEXT = wxID_HIGHEST + 1,
|
||||
ID_PASTE_TEXT,
|
||||
ID_CLEAR_CLIPBOARD,
|
||||
ID_CHECK_CLIPBOARD
|
||||
};
|
||||
|
||||
wxBEGIN_EVENT_TABLE(ClipboardTestFrame, wxFrame)
|
||||
EVT_BUTTON(ID_COPY_TEXT, ClipboardTestFrame::OnCopyText)
|
||||
EVT_BUTTON(ID_PASTE_TEXT, ClipboardTestFrame::OnPasteText)
|
||||
EVT_BUTTON(ID_CLEAR_CLIPBOARD, ClipboardTestFrame::OnClearClipboard)
|
||||
EVT_BUTTON(ID_CHECK_CLIPBOARD, ClipboardTestFrame::OnCheckClipboard)
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
wxIMPLEMENT_APP(ClipboardTestApp);
|
||||
|
||||
bool ClipboardTestApp::OnInit()
|
||||
{
|
||||
if (!wxApp::OnInit())
|
||||
return false;
|
||||
|
||||
ClipboardTestFrame* frame = new ClipboardTestFrame();
|
||||
frame->Show(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
ClipboardTestFrame::ClipboardTestFrame()
|
||||
: wxFrame(nullptr, wxID_ANY, "wxClipboard WASM Test",
|
||||
wxDefaultPosition, wxSize(600, 500))
|
||||
{
|
||||
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
// Description
|
||||
wxStaticText* desc = new wxStaticText(this, wxID_ANY,
|
||||
"wxClipboard Test\n\n"
|
||||
"Tests clipboard operations that KiCad uses for copy/paste.\n"
|
||||
"Note: Browser clipboard access may be restricted.");
|
||||
mainSizer->Add(desc, 0, wxALL, 10);
|
||||
|
||||
// Input section
|
||||
wxStaticBoxSizer* inputBox = new wxStaticBoxSizer(wxVERTICAL, this, "Text to Copy");
|
||||
m_input = new wxTextCtrl(this, wxID_ANY, "Sample text for clipboard test",
|
||||
wxDefaultPosition, wxSize(-1, 60), wxTE_MULTILINE);
|
||||
inputBox->Add(m_input, 1, wxEXPAND | wxALL, 5);
|
||||
mainSizer->Add(inputBox, 0, wxEXPAND | wxLEFT | wxRIGHT, 10);
|
||||
|
||||
// Buttons
|
||||
wxBoxSizer* buttonSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
buttonSizer->Add(new wxButton(this, ID_COPY_TEXT, "Copy to Clipboard"), 0, wxALL, 5);
|
||||
buttonSizer->Add(new wxButton(this, ID_PASTE_TEXT, "Paste from Clipboard"), 0, wxALL, 5);
|
||||
buttonSizer->Add(new wxButton(this, ID_CHECK_CLIPBOARD, "Check Clipboard"), 0, wxALL, 5);
|
||||
buttonSizer->Add(new wxButton(this, ID_CLEAR_CLIPBOARD, "Clear Clipboard"), 0, wxALL, 5);
|
||||
mainSizer->Add(buttonSizer, 0, wxALIGN_CENTER | wxALL, 10);
|
||||
|
||||
// Output section
|
||||
wxStaticBoxSizer* outputBox = new wxStaticBoxSizer(wxVERTICAL, this, "Pasted Text");
|
||||
m_output = new wxTextCtrl(this, wxID_ANY, "",
|
||||
wxDefaultPosition, wxSize(-1, 60), wxTE_MULTILINE | wxTE_READONLY);
|
||||
outputBox->Add(m_output, 1, wxEXPAND | wxALL, 5);
|
||||
mainSizer->Add(outputBox, 0, wxEXPAND | wxLEFT | wxRIGHT, 10);
|
||||
|
||||
// Log section
|
||||
wxStaticBoxSizer* logBox = new wxStaticBoxSizer(wxVERTICAL, this, "Event Log");
|
||||
m_log = new wxTextCtrl(this, wxID_ANY, "",
|
||||
wxDefaultPosition, wxSize(-1, 100), wxTE_MULTILINE | wxTE_READONLY);
|
||||
logBox->Add(m_log, 1, wxEXPAND | wxALL, 5);
|
||||
mainSizer->Add(logBox, 1, wxEXPAND | wxALL, 10);
|
||||
|
||||
SetSizer(mainSizer);
|
||||
|
||||
// Status bar
|
||||
CreateStatusBar();
|
||||
SetStatusText("Ready - Test clipboard operations");
|
||||
|
||||
LogEvent("Clipboard test app started");
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM({
|
||||
console.log('[CLIPBOARD_TEST] wxClipboard test app started successfully');
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void ClipboardTestFrame::LogEvent(const wxString& msg)
|
||||
{
|
||||
m_log->AppendText(msg + "\n");
|
||||
SetStatusText(msg);
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM({
|
||||
console.log('[CLIPBOARD_EVENT] ' + UTF8ToString($0));
|
||||
}, msg.c_str().AsChar());
|
||||
#endif
|
||||
}
|
||||
|
||||
void ClipboardTestFrame::OnCopyText(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Attempting to copy text to clipboard...");
|
||||
|
||||
wxString text = m_input->GetValue();
|
||||
if (text.IsEmpty()) {
|
||||
LogEvent("ERROR: No text to copy");
|
||||
return;
|
||||
}
|
||||
|
||||
if (wxTheClipboard->Open()) {
|
||||
wxTheClipboard->SetData(new wxTextDataObject(text));
|
||||
wxTheClipboard->Close();
|
||||
LogEvent(wxString::Format("SUCCESS: Copied %d characters to clipboard", (int)text.Length()));
|
||||
} else {
|
||||
LogEvent("ERROR: Could not open clipboard");
|
||||
}
|
||||
}
|
||||
|
||||
void ClipboardTestFrame::OnPasteText(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Attempting to paste from clipboard...");
|
||||
|
||||
if (wxTheClipboard->Open()) {
|
||||
if (wxTheClipboard->IsSupported(wxDF_TEXT) ||
|
||||
wxTheClipboard->IsSupported(wxDF_UNICODETEXT)) {
|
||||
wxTextDataObject data;
|
||||
wxTheClipboard->GetData(data);
|
||||
wxString text = data.GetText();
|
||||
m_output->SetValue(text);
|
||||
LogEvent(wxString::Format("SUCCESS: Pasted %d characters from clipboard", (int)text.Length()));
|
||||
} else {
|
||||
LogEvent("WARNING: No text data in clipboard");
|
||||
m_output->SetValue("");
|
||||
}
|
||||
wxTheClipboard->Close();
|
||||
} else {
|
||||
LogEvent("ERROR: Could not open clipboard");
|
||||
}
|
||||
}
|
||||
|
||||
void ClipboardTestFrame::OnClearClipboard(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Attempting to clear clipboard...");
|
||||
|
||||
if (wxTheClipboard->Open()) {
|
||||
wxTheClipboard->Clear();
|
||||
wxTheClipboard->Close();
|
||||
LogEvent("SUCCESS: Clipboard cleared");
|
||||
} else {
|
||||
LogEvent("ERROR: Could not open clipboard");
|
||||
}
|
||||
}
|
||||
|
||||
void ClipboardTestFrame::OnCheckClipboard(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Checking clipboard contents...");
|
||||
|
||||
if (wxTheClipboard->Open()) {
|
||||
bool hasText = wxTheClipboard->IsSupported(wxDF_TEXT) ||
|
||||
wxTheClipboard->IsSupported(wxDF_UNICODETEXT);
|
||||
bool hasBitmap = wxTheClipboard->IsSupported(wxDF_BITMAP);
|
||||
bool hasFiles = wxTheClipboard->IsSupported(wxDF_FILENAME);
|
||||
|
||||
wxString status = "Clipboard contains: ";
|
||||
if (hasText) status += "TEXT ";
|
||||
if (hasBitmap) status += "BITMAP ";
|
||||
if (hasFiles) status += "FILES ";
|
||||
if (!hasText && !hasBitmap && !hasFiles) status += "(empty or unsupported format)";
|
||||
|
||||
LogEvent(status);
|
||||
wxTheClipboard->Close();
|
||||
} else {
|
||||
LogEvent("ERROR: Could not open clipboard");
|
||||
}
|
||||
}
|
||||
225
tests/wasm-app/standalone/dialog/dialog_test.cpp
Normal file
225
tests/wasm-app/standalone/dialog/dialog_test.cpp
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
// wxDialog/wxMessageBox Test - Tests modal dialogs in WASM
|
||||
// KiCad uses dialogs for alerts, confirmations, and custom dialogs
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/wx.h"
|
||||
#endif
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten/emscripten.h>
|
||||
#endif
|
||||
|
||||
class DialogTestApp : public wxApp
|
||||
{
|
||||
public:
|
||||
virtual bool OnInit() override;
|
||||
};
|
||||
|
||||
class DialogTestFrame : public wxFrame
|
||||
{
|
||||
public:
|
||||
DialogTestFrame();
|
||||
|
||||
private:
|
||||
wxTextCtrl* m_log;
|
||||
|
||||
void LogEvent(const wxString& msg);
|
||||
|
||||
void OnInfoDialog(wxCommandEvent& evt);
|
||||
void OnYesNoDialog(wxCommandEvent& evt);
|
||||
void OnErrorDialog(wxCommandEvent& evt);
|
||||
void OnCustomDialog(wxCommandEvent& evt);
|
||||
void OnInputDialog(wxCommandEvent& evt);
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
// Custom dialog class (like KiCad's property dialogs)
|
||||
class CustomTestDialog : public wxDialog
|
||||
{
|
||||
public:
|
||||
CustomTestDialog(wxWindow* parent);
|
||||
|
||||
wxString GetValue() const { return m_textCtrl->GetValue(); }
|
||||
|
||||
private:
|
||||
wxTextCtrl* m_textCtrl;
|
||||
};
|
||||
|
||||
enum {
|
||||
ID_INFO_DIALOG = wxID_HIGHEST + 1,
|
||||
ID_YESNO_DIALOG,
|
||||
ID_ERROR_DIALOG,
|
||||
ID_CUSTOM_DIALOG,
|
||||
ID_INPUT_DIALOG
|
||||
};
|
||||
|
||||
wxBEGIN_EVENT_TABLE(DialogTestFrame, wxFrame)
|
||||
EVT_BUTTON(ID_INFO_DIALOG, DialogTestFrame::OnInfoDialog)
|
||||
EVT_BUTTON(ID_YESNO_DIALOG, DialogTestFrame::OnYesNoDialog)
|
||||
EVT_BUTTON(ID_ERROR_DIALOG, DialogTestFrame::OnErrorDialog)
|
||||
EVT_BUTTON(ID_CUSTOM_DIALOG, DialogTestFrame::OnCustomDialog)
|
||||
EVT_BUTTON(ID_INPUT_DIALOG, DialogTestFrame::OnInputDialog)
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
wxIMPLEMENT_APP(DialogTestApp);
|
||||
|
||||
bool DialogTestApp::OnInit()
|
||||
{
|
||||
if (!wxApp::OnInit())
|
||||
return false;
|
||||
|
||||
DialogTestFrame* frame = new DialogTestFrame();
|
||||
frame->Show(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
DialogTestFrame::DialogTestFrame()
|
||||
: wxFrame(nullptr, wxID_ANY, "wxDialog/wxMessageBox WASM Test",
|
||||
wxDefaultPosition, wxSize(600, 500))
|
||||
{
|
||||
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
wxStaticText* desc = new wxStaticText(this, wxID_ANY,
|
||||
"wxDialog and wxMessageBox Test\n\n"
|
||||
"KiCad uses dialogs for alerts, confirmations, and custom property dialogs.\n"
|
||||
"Click buttons to test different dialog types.");
|
||||
mainSizer->Add(desc, 0, wxALL, 10);
|
||||
|
||||
// wxMessageBox section
|
||||
wxStaticBoxSizer* msgBoxSizer = new wxStaticBoxSizer(wxVERTICAL, this, "wxMessageBox");
|
||||
wxBoxSizer* msgBtnSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
msgBtnSizer->Add(new wxButton(this, ID_INFO_DIALOG, "Info Dialog"), 0, wxALL, 5);
|
||||
msgBtnSizer->Add(new wxButton(this, ID_YESNO_DIALOG, "Yes/No Dialog"), 0, wxALL, 5);
|
||||
msgBtnSizer->Add(new wxButton(this, ID_ERROR_DIALOG, "Error Dialog"), 0, wxALL, 5);
|
||||
msgBoxSizer->Add(msgBtnSizer, 0, wxALIGN_CENTER);
|
||||
mainSizer->Add(msgBoxSizer, 0, wxEXPAND | wxALL, 10);
|
||||
|
||||
// wxDialog section
|
||||
wxStaticBoxSizer* dlgSizer = new wxStaticBoxSizer(wxVERTICAL, this, "wxDialog");
|
||||
wxBoxSizer* dlgBtnSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
dlgBtnSizer->Add(new wxButton(this, ID_CUSTOM_DIALOG, "Custom Dialog"), 0, wxALL, 5);
|
||||
dlgBtnSizer->Add(new wxButton(this, ID_INPUT_DIALOG, "Input Dialog"), 0, wxALL, 5);
|
||||
dlgSizer->Add(dlgBtnSizer, 0, wxALIGN_CENTER);
|
||||
mainSizer->Add(dlgSizer, 0, wxEXPAND | wxALL, 10);
|
||||
|
||||
// Event log
|
||||
wxStaticBoxSizer* logBox = new wxStaticBoxSizer(wxVERTICAL, this, "Event Log");
|
||||
m_log = new wxTextCtrl(this, wxID_ANY, "",
|
||||
wxDefaultPosition, wxSize(-1, 200), wxTE_MULTILINE | wxTE_READONLY);
|
||||
logBox->Add(m_log, 1, wxEXPAND | wxALL, 5);
|
||||
mainSizer->Add(logBox, 1, wxEXPAND | wxALL, 10);
|
||||
|
||||
SetSizer(mainSizer);
|
||||
CreateStatusBar();
|
||||
SetStatusText("Ready");
|
||||
|
||||
LogEvent("Dialog test app started");
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM({
|
||||
console.log('[DIALOG_TEST] wxDialog test app started successfully');
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void DialogTestFrame::LogEvent(const wxString& msg)
|
||||
{
|
||||
m_log->AppendText(msg + "\n");
|
||||
SetStatusText(msg);
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM({
|
||||
console.log('[DIALOG_EVENT] ' + UTF8ToString($0));
|
||||
}, msg.c_str().AsChar());
|
||||
#endif
|
||||
}
|
||||
|
||||
void DialogTestFrame::OnInfoDialog(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Opening Info dialog...");
|
||||
|
||||
int result = wxMessageBox("This is an informational message.\n\nKiCad uses these for status updates.",
|
||||
"Information", wxOK | wxICON_INFORMATION, this);
|
||||
|
||||
LogEvent(wxString::Format("Info dialog closed with result: %d", result));
|
||||
}
|
||||
|
||||
void DialogTestFrame::OnYesNoDialog(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Opening Yes/No dialog...");
|
||||
|
||||
int result = wxMessageBox("Do you want to save changes?\n\nKiCad uses these for confirmations.",
|
||||
"Confirm", wxYES_NO | wxCANCEL | wxICON_QUESTION, this);
|
||||
|
||||
wxString resultStr;
|
||||
switch (result) {
|
||||
case wxYES: resultStr = "YES"; break;
|
||||
case wxNO: resultStr = "NO"; break;
|
||||
case wxCANCEL: resultStr = "CANCEL"; break;
|
||||
default: resultStr = wxString::Format("Unknown (%d)", result);
|
||||
}
|
||||
LogEvent(wxString::Format("Yes/No dialog closed with: %s", resultStr));
|
||||
}
|
||||
|
||||
void DialogTestFrame::OnErrorDialog(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Opening Error dialog...");
|
||||
|
||||
int result = wxMessageBox("An error has occurred!\n\nKiCad uses these for error messages.",
|
||||
"Error", wxOK | wxICON_ERROR, this);
|
||||
|
||||
LogEvent(wxString::Format("Error dialog closed with result: %d", result));
|
||||
}
|
||||
|
||||
void DialogTestFrame::OnCustomDialog(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Opening Custom dialog...");
|
||||
|
||||
CustomTestDialog dlg(this);
|
||||
int result = dlg.ShowModal();
|
||||
|
||||
if (result == wxID_OK) {
|
||||
LogEvent(wxString::Format("Custom dialog OK - value: '%s'", dlg.GetValue()));
|
||||
} else {
|
||||
LogEvent("Custom dialog cancelled");
|
||||
}
|
||||
}
|
||||
|
||||
void DialogTestFrame::OnInputDialog(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Opening Input dialog...");
|
||||
|
||||
wxTextEntryDialog dlg(this, "Enter a component reference:",
|
||||
"Input Dialog", "R1");
|
||||
|
||||
if (dlg.ShowModal() == wxID_OK) {
|
||||
LogEvent(wxString::Format("Input dialog OK - value: '%s'", dlg.GetValue()));
|
||||
} else {
|
||||
LogEvent("Input dialog cancelled");
|
||||
}
|
||||
}
|
||||
|
||||
// Custom dialog implementation
|
||||
CustomTestDialog::CustomTestDialog(wxWindow* parent)
|
||||
: wxDialog(parent, wxID_ANY, "Custom Test Dialog",
|
||||
wxDefaultPosition, wxSize(300, 200))
|
||||
{
|
||||
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
wxStaticText* label = new wxStaticText(this, wxID_ANY,
|
||||
"This is a custom wxDialog\nlike KiCad's property dialogs:");
|
||||
mainSizer->Add(label, 0, wxALL, 10);
|
||||
|
||||
m_textCtrl = new wxTextCtrl(this, wxID_ANY, "Sample value");
|
||||
mainSizer->Add(m_textCtrl, 0, wxEXPAND | wxLEFT | wxRIGHT, 10);
|
||||
|
||||
wxBoxSizer* btnSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
btnSizer->Add(new wxButton(this, wxID_OK, "OK"), 0, wxALL, 5);
|
||||
btnSizer->Add(new wxButton(this, wxID_CANCEL, "Cancel"), 0, wxALL, 5);
|
||||
mainSizer->Add(btnSizer, 0, wxALIGN_CENTER | wxALL, 10);
|
||||
|
||||
SetSizer(mainSizer);
|
||||
}
|
||||
162
tests/wasm-app/standalone/filedialog/filedialog_test.cpp
Normal file
162
tests/wasm-app/standalone/filedialog/filedialog_test.cpp
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
// wxFileDialog Test - Tests file dialog functionality in WASM
|
||||
// KiCad uses file dialogs for opening/saving schematics, PCBs, footprints
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/wx.h"
|
||||
#endif
|
||||
|
||||
#include "wx/filedlg.h"
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten/emscripten.h>
|
||||
#endif
|
||||
|
||||
class FileDialogTestApp : public wxApp
|
||||
{
|
||||
public:
|
||||
virtual bool OnInit() override;
|
||||
};
|
||||
|
||||
class FileDialogTestFrame : public wxFrame
|
||||
{
|
||||
public:
|
||||
FileDialogTestFrame();
|
||||
|
||||
private:
|
||||
wxTextCtrl* m_log;
|
||||
|
||||
void LogEvent(const wxString& msg);
|
||||
|
||||
void OnOpenFile(wxCommandEvent& evt);
|
||||
void OnSaveFile(wxCommandEvent& evt);
|
||||
void OnOpenMultiple(wxCommandEvent& evt);
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
enum {
|
||||
ID_OPEN_FILE = wxID_HIGHEST + 1,
|
||||
ID_SAVE_FILE,
|
||||
ID_OPEN_MULTIPLE
|
||||
};
|
||||
|
||||
wxBEGIN_EVENT_TABLE(FileDialogTestFrame, wxFrame)
|
||||
EVT_BUTTON(ID_OPEN_FILE, FileDialogTestFrame::OnOpenFile)
|
||||
EVT_BUTTON(ID_SAVE_FILE, FileDialogTestFrame::OnSaveFile)
|
||||
EVT_BUTTON(ID_OPEN_MULTIPLE, FileDialogTestFrame::OnOpenMultiple)
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
wxIMPLEMENT_APP(FileDialogTestApp);
|
||||
|
||||
bool FileDialogTestApp::OnInit()
|
||||
{
|
||||
if (!wxApp::OnInit())
|
||||
return false;
|
||||
|
||||
FileDialogTestFrame* frame = new FileDialogTestFrame();
|
||||
frame->Show(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
FileDialogTestFrame::FileDialogTestFrame()
|
||||
: wxFrame(nullptr, wxID_ANY, "wxFileDialog WASM Test",
|
||||
wxDefaultPosition, wxSize(600, 400))
|
||||
{
|
||||
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
wxStaticText* desc = new wxStaticText(this, wxID_ANY,
|
||||
"wxFileDialog Test\n\n"
|
||||
"Tests file dialog operations that KiCad uses for open/save.\n"
|
||||
"Note: Browser file access is typically restricted.");
|
||||
mainSizer->Add(desc, 0, wxALL, 10);
|
||||
|
||||
wxBoxSizer* buttonSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
buttonSizer->Add(new wxButton(this, ID_OPEN_FILE, "Open File..."), 0, wxALL, 5);
|
||||
buttonSizer->Add(new wxButton(this, ID_SAVE_FILE, "Save File..."), 0, wxALL, 5);
|
||||
buttonSizer->Add(new wxButton(this, ID_OPEN_MULTIPLE, "Open Multiple..."), 0, wxALL, 5);
|
||||
mainSizer->Add(buttonSizer, 0, wxALIGN_CENTER | wxALL, 10);
|
||||
|
||||
wxStaticBoxSizer* logBox = new wxStaticBoxSizer(wxVERTICAL, this, "Event Log");
|
||||
m_log = new wxTextCtrl(this, wxID_ANY, "",
|
||||
wxDefaultPosition, wxSize(-1, 200), wxTE_MULTILINE | wxTE_READONLY);
|
||||
logBox->Add(m_log, 1, wxEXPAND | wxALL, 5);
|
||||
mainSizer->Add(logBox, 1, wxEXPAND | wxALL, 10);
|
||||
|
||||
SetSizer(mainSizer);
|
||||
CreateStatusBar();
|
||||
SetStatusText("Ready");
|
||||
|
||||
LogEvent("FileDialog test app started");
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM({
|
||||
console.log('[FILEDIALOG_TEST] wxFileDialog test app started successfully');
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void FileDialogTestFrame::LogEvent(const wxString& msg)
|
||||
{
|
||||
m_log->AppendText(msg + "\n");
|
||||
SetStatusText(msg);
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM({
|
||||
console.log('[FILEDIALOG_EVENT] ' + UTF8ToString($0));
|
||||
}, msg.c_str().AsChar());
|
||||
#endif
|
||||
}
|
||||
|
||||
void FileDialogTestFrame::OnOpenFile(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Opening file dialog...");
|
||||
|
||||
wxFileDialog openDialog(this, "Open File", "", "",
|
||||
"All files (*.*)|*.*|KiCad files (*.kicad_*)|*.kicad_*",
|
||||
wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
|
||||
if (openDialog.ShowModal() == wxID_OK) {
|
||||
wxString path = openDialog.GetPath();
|
||||
LogEvent(wxString::Format("Selected file: %s", path));
|
||||
} else {
|
||||
LogEvent("Open dialog cancelled");
|
||||
}
|
||||
}
|
||||
|
||||
void FileDialogTestFrame::OnSaveFile(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Opening save dialog...");
|
||||
|
||||
wxFileDialog saveDialog(this, "Save File", "", "untitled.txt",
|
||||
"Text files (*.txt)|*.txt|All files (*.*)|*.*",
|
||||
wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||
|
||||
if (saveDialog.ShowModal() == wxID_OK) {
|
||||
wxString path = saveDialog.GetPath();
|
||||
LogEvent(wxString::Format("Save to: %s", path));
|
||||
} else {
|
||||
LogEvent("Save dialog cancelled");
|
||||
}
|
||||
}
|
||||
|
||||
void FileDialogTestFrame::OnOpenMultiple(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Opening multiple file dialog...");
|
||||
|
||||
wxFileDialog openDialog(this, "Open Multiple Files", "", "",
|
||||
"All files (*.*)|*.*",
|
||||
wxFD_OPEN | wxFD_MULTIPLE);
|
||||
|
||||
if (openDialog.ShowModal() == wxID_OK) {
|
||||
wxArrayString paths;
|
||||
openDialog.GetPaths(paths);
|
||||
LogEvent(wxString::Format("Selected %zu files:", paths.GetCount()));
|
||||
for (size_t i = 0; i < paths.GetCount(); i++) {
|
||||
LogEvent(wxString::Format(" %s", paths[i]));
|
||||
}
|
||||
} else {
|
||||
LogEvent("Multiple file dialog cancelled");
|
||||
}
|
||||
}
|
||||
190
tests/wasm-app/standalone/grid/grid_test.cpp
Normal file
190
tests/wasm-app/standalone/grid/grid_test.cpp
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
// Minimal wxGrid Test - Tests if wxGrid works in WASM
|
||||
// This is a SEPARATE test app because wxGrid may crash the app at startup
|
||||
// If this page loads successfully, wxGrid is working!
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/wx.h"
|
||||
#endif
|
||||
|
||||
#include "wx/grid.h"
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten/emscripten.h>
|
||||
#endif
|
||||
|
||||
class GridTestApp : public wxApp
|
||||
{
|
||||
public:
|
||||
virtual bool OnInit() override;
|
||||
};
|
||||
|
||||
class GridTestFrame : public wxFrame
|
||||
{
|
||||
public:
|
||||
GridTestFrame();
|
||||
|
||||
private:
|
||||
wxGrid* m_grid;
|
||||
wxTextCtrl* m_log;
|
||||
|
||||
void LogEvent(const wxString& msg);
|
||||
|
||||
// Grid event handlers
|
||||
void OnGridCellSelect(wxGridEvent& evt);
|
||||
void OnGridCellChange(wxGridEvent& evt);
|
||||
void OnGridLabelClick(wxGridEvent& evt);
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
enum {
|
||||
ID_GRID = wxID_HIGHEST + 1,
|
||||
ID_LOG
|
||||
};
|
||||
|
||||
wxBEGIN_EVENT_TABLE(GridTestFrame, wxFrame)
|
||||
EVT_GRID_SELECT_CELL(GridTestFrame::OnGridCellSelect)
|
||||
EVT_GRID_CELL_CHANGED(GridTestFrame::OnGridCellChange)
|
||||
EVT_GRID_LABEL_LEFT_CLICK(GridTestFrame::OnGridLabelClick)
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
wxIMPLEMENT_APP(GridTestApp);
|
||||
|
||||
bool GridTestApp::OnInit()
|
||||
{
|
||||
if (!wxApp::OnInit())
|
||||
return false;
|
||||
|
||||
GridTestFrame* frame = new GridTestFrame();
|
||||
frame->Show(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
GridTestFrame::GridTestFrame()
|
||||
: wxFrame(nullptr, wxID_ANY, "wxGrid WASM Test",
|
||||
wxDefaultPosition, wxSize(600, 500))
|
||||
{
|
||||
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
// Status message
|
||||
wxStaticText* status = new wxStaticText(this, wxID_ANY,
|
||||
"SUCCESS: wxGrid initialized! If you see this, wxGrid is working in WASM.");
|
||||
status->SetForegroundColour(*wxGREEN);
|
||||
mainSizer->Add(status, 0, wxALL, 10);
|
||||
|
||||
// Create wxGrid - THIS IS THE CRITICAL TEST
|
||||
// If wxGrid doesn't work in WASM, the app will crash HERE
|
||||
m_grid = new wxGrid(this, ID_GRID, wxDefaultPosition, wxSize(500, 200));
|
||||
|
||||
// Setup grid with sample data (like KiCad's property grids)
|
||||
m_grid->CreateGrid(5, 4);
|
||||
|
||||
// Set column labels (similar to KiCad's property dialogs)
|
||||
m_grid->SetColLabelValue(0, "Property");
|
||||
m_grid->SetColLabelValue(1, "Value");
|
||||
m_grid->SetColLabelValue(2, "Units");
|
||||
m_grid->SetColLabelValue(3, "Description");
|
||||
|
||||
// Set column widths
|
||||
m_grid->SetColSize(0, 100);
|
||||
m_grid->SetColSize(1, 80);
|
||||
m_grid->SetColSize(2, 50);
|
||||
m_grid->SetColSize(3, 150);
|
||||
|
||||
// Fill with sample data (like KiCad track/via properties)
|
||||
m_grid->SetCellValue(0, 0, "Track Width");
|
||||
m_grid->SetCellValue(0, 1, "0.25");
|
||||
m_grid->SetCellValue(0, 2, "mm");
|
||||
m_grid->SetCellValue(0, 3, "Default track width");
|
||||
|
||||
m_grid->SetCellValue(1, 0, "Via Size");
|
||||
m_grid->SetCellValue(1, 1, "0.80");
|
||||
m_grid->SetCellValue(1, 2, "mm");
|
||||
m_grid->SetCellValue(1, 3, "Via outer diameter");
|
||||
|
||||
m_grid->SetCellValue(2, 0, "Via Drill");
|
||||
m_grid->SetCellValue(2, 1, "0.40");
|
||||
m_grid->SetCellValue(2, 2, "mm");
|
||||
m_grid->SetCellValue(2, 3, "Via drill diameter");
|
||||
|
||||
m_grid->SetCellValue(3, 0, "Clearance");
|
||||
m_grid->SetCellValue(3, 1, "0.20");
|
||||
m_grid->SetCellValue(3, 2, "mm");
|
||||
m_grid->SetCellValue(3, 3, "Min clearance");
|
||||
|
||||
m_grid->SetCellValue(4, 0, "Net Class");
|
||||
m_grid->SetCellValue(4, 1, "Default");
|
||||
m_grid->SetCellValue(4, 2, "-");
|
||||
m_grid->SetCellValue(4, 3, "Net class name");
|
||||
|
||||
// Make first column read-only (like property names in KiCad)
|
||||
for (int row = 0; row < 5; row++) {
|
||||
m_grid->SetReadOnly(row, 0);
|
||||
m_grid->SetReadOnly(row, 2);
|
||||
m_grid->SetReadOnly(row, 3);
|
||||
}
|
||||
|
||||
mainSizer->Add(m_grid, 1, wxEXPAND | wxALL, 10);
|
||||
|
||||
// Event log
|
||||
wxStaticBox* logBox = new wxStaticBox(this, wxID_ANY, "Event Log");
|
||||
wxStaticBoxSizer* logSizer = new wxStaticBoxSizer(logBox, wxVERTICAL);
|
||||
|
||||
m_log = new wxTextCtrl(this, ID_LOG, "", wxDefaultPosition, wxSize(-1, 100),
|
||||
wxTE_MULTILINE | wxTE_READONLY);
|
||||
logSizer->Add(m_log, 1, wxEXPAND | wxALL, 5);
|
||||
|
||||
mainSizer->Add(logSizer, 0, wxEXPAND | wxALL, 10);
|
||||
|
||||
SetSizer(mainSizer);
|
||||
|
||||
LogEvent("wxGrid initialized successfully!");
|
||||
LogEvent("Try clicking cells, editing values, etc.");
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM({
|
||||
console.log('[GRID_TEST] wxGrid test app started successfully!');
|
||||
console.log('[GRID_TEST] If you see this message, wxGrid is working in WASM!');
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void GridTestFrame::LogEvent(const wxString& msg)
|
||||
{
|
||||
m_log->AppendText(msg + "\n");
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM({
|
||||
console.log('[GRID_EVENT] ' + UTF8ToString($0));
|
||||
}, msg.c_str().AsChar());
|
||||
#endif
|
||||
}
|
||||
|
||||
void GridTestFrame::OnGridCellSelect(wxGridEvent& evt)
|
||||
{
|
||||
LogEvent(wxString::Format("Cell selected: row=%d, col=%d, value='%s'",
|
||||
evt.GetRow(), evt.GetCol(),
|
||||
m_grid->GetCellValue(evt.GetRow(), evt.GetCol())));
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
void GridTestFrame::OnGridCellChange(wxGridEvent& evt)
|
||||
{
|
||||
LogEvent(wxString::Format("Cell changed: row=%d, col=%d, new value='%s'",
|
||||
evt.GetRow(), evt.GetCol(),
|
||||
m_grid->GetCellValue(evt.GetRow(), evt.GetCol())));
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
void GridTestFrame::OnGridLabelClick(wxGridEvent& evt)
|
||||
{
|
||||
if (evt.GetRow() >= 0) {
|
||||
LogEvent(wxString::Format("Row label clicked: row=%d", evt.GetRow()));
|
||||
} else if (evt.GetCol() >= 0) {
|
||||
LogEvent(wxString::Format("Column label clicked: col=%d ('%s')",
|
||||
evt.GetCol(), m_grid->GetColLabelValue(evt.GetCol())));
|
||||
}
|
||||
evt.Skip();
|
||||
}
|
||||
142
tests/wasm-app/standalone/layout/layout_test.cpp
Normal file
142
tests/wasm-app/standalone/layout/layout_test.cpp
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
// Layout Test - Tests wxSplitterWindow and wxScrolledWindow in WASM
|
||||
// KiCad uses splitters and scrolled windows extensively
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/wx.h"
|
||||
#endif
|
||||
|
||||
#include "wx/splitter.h"
|
||||
#include "wx/scrolwin.h"
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten/emscripten.h>
|
||||
#endif
|
||||
|
||||
class LayoutTestApp : public wxApp
|
||||
{
|
||||
public:
|
||||
virtual bool OnInit() override;
|
||||
};
|
||||
|
||||
class LayoutTestFrame : public wxFrame
|
||||
{
|
||||
public:
|
||||
LayoutTestFrame();
|
||||
|
||||
private:
|
||||
wxSplitterWindow* m_splitter;
|
||||
wxScrolledWindow* m_scrollLeft;
|
||||
wxScrolledWindow* m_scrollRight;
|
||||
wxTextCtrl* m_log;
|
||||
|
||||
void LogEvent(const wxString& msg);
|
||||
void OnSplitterSashPosChanged(wxSplitterEvent& evt);
|
||||
void OnScrollWin(wxScrollWinEvent& evt);
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
wxBEGIN_EVENT_TABLE(LayoutTestFrame, wxFrame)
|
||||
EVT_SPLITTER_SASH_POS_CHANGED(wxID_ANY, LayoutTestFrame::OnSplitterSashPosChanged)
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
wxIMPLEMENT_APP(LayoutTestApp);
|
||||
|
||||
bool LayoutTestApp::OnInit()
|
||||
{
|
||||
if (!wxApp::OnInit())
|
||||
return false;
|
||||
|
||||
LayoutTestFrame* frame = new LayoutTestFrame();
|
||||
frame->Show(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
LayoutTestFrame::LayoutTestFrame()
|
||||
: wxFrame(nullptr, wxID_ANY, "wxSplitter/wxScrolled WASM Test",
|
||||
wxDefaultPosition, wxSize(800, 600))
|
||||
{
|
||||
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
wxStaticText* desc = new wxStaticText(this, wxID_ANY,
|
||||
"wxSplitterWindow and wxScrolledWindow Test - KiCad layout controls");
|
||||
mainSizer->Add(desc, 0, wxALL, 5);
|
||||
|
||||
// Create splitter
|
||||
m_splitter = new wxSplitterWindow(this, wxID_ANY, wxDefaultPosition,
|
||||
wxDefaultSize, wxSP_3D | wxSP_LIVE_UPDATE);
|
||||
|
||||
// Left scrolled window
|
||||
m_scrollLeft = new wxScrolledWindow(m_splitter, wxID_ANY);
|
||||
m_scrollLeft->SetBackgroundColour(*wxLIGHT_GREY);
|
||||
m_scrollLeft->SetScrollbars(10, 10, 100, 100);
|
||||
|
||||
wxBoxSizer* leftSizer = new wxBoxSizer(wxVERTICAL);
|
||||
for (int i = 0; i < 20; i++) {
|
||||
leftSizer->Add(new wxStaticText(m_scrollLeft, wxID_ANY,
|
||||
wxString::Format("Left Item %d", i+1)), 0, wxALL, 5);
|
||||
}
|
||||
m_scrollLeft->SetSizer(leftSizer);
|
||||
|
||||
// Right scrolled window
|
||||
m_scrollRight = new wxScrolledWindow(m_splitter, wxID_ANY);
|
||||
m_scrollRight->SetBackgroundColour(*wxWHITE);
|
||||
m_scrollRight->SetScrollbars(10, 10, 100, 100);
|
||||
|
||||
wxBoxSizer* rightSizer = new wxBoxSizer(wxVERTICAL);
|
||||
for (int i = 0; i < 20; i++) {
|
||||
rightSizer->Add(new wxStaticText(m_scrollRight, wxID_ANY,
|
||||
wxString::Format("Right Item %d", i+1)), 0, wxALL, 5);
|
||||
}
|
||||
m_scrollRight->SetSizer(rightSizer);
|
||||
|
||||
m_splitter->SplitVertically(m_scrollLeft, m_scrollRight, 300);
|
||||
m_splitter->SetMinimumPaneSize(100);
|
||||
|
||||
mainSizer->Add(m_splitter, 1, wxEXPAND | wxALL, 5);
|
||||
|
||||
// Event log
|
||||
wxStaticBoxSizer* logBox = new wxStaticBoxSizer(wxVERTICAL, this, "Event Log");
|
||||
m_log = new wxTextCtrl(this, wxID_ANY, "",
|
||||
wxDefaultPosition, wxSize(-1, 100), wxTE_MULTILINE | wxTE_READONLY);
|
||||
logBox->Add(m_log, 1, wxEXPAND | wxALL, 5);
|
||||
mainSizer->Add(logBox, 0, wxEXPAND | wxALL, 5);
|
||||
|
||||
SetSizer(mainSizer);
|
||||
CreateStatusBar();
|
||||
SetStatusText("Drag splitter sash or scroll the panes");
|
||||
|
||||
LogEvent("Layout test app started");
|
||||
LogEvent("Splitter position: 300");
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM({
|
||||
console.log('[LAYOUT_TEST] wxSplitter/wxScrolled test app started successfully');
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void LayoutTestFrame::LogEvent(const wxString& msg)
|
||||
{
|
||||
m_log->AppendText(msg + "\n");
|
||||
SetStatusText(msg);
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM({
|
||||
console.log('[LAYOUT_EVENT] ' + UTF8ToString($0));
|
||||
}, msg.c_str().AsChar());
|
||||
#endif
|
||||
}
|
||||
|
||||
void LayoutTestFrame::OnSplitterSashPosChanged(wxSplitterEvent& evt)
|
||||
{
|
||||
LogEvent(wxString::Format("Splitter sash moved to: %d", evt.GetSashPosition()));
|
||||
}
|
||||
|
||||
void LayoutTestFrame::OnScrollWin(wxScrollWinEvent& evt)
|
||||
{
|
||||
LogEvent("Scroll event");
|
||||
evt.Skip();
|
||||
}
|
||||
300
tests/wasm-app/standalone/menu/menu_test.cpp
Normal file
300
tests/wasm-app/standalone/menu/menu_test.cpp
Normal file
|
|
@ -0,0 +1,300 @@
|
|||
// wxMenuBar Test - Tests menu functionality in WASM
|
||||
// KiCad uses extensive menus for File, Edit, View, Place, Route, etc.
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/wx.h"
|
||||
#endif
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten/emscripten.h>
|
||||
#endif
|
||||
|
||||
class MenuTestApp : public wxApp
|
||||
{
|
||||
public:
|
||||
virtual bool OnInit() override;
|
||||
};
|
||||
|
||||
class MenuTestFrame : public wxFrame
|
||||
{
|
||||
public:
|
||||
MenuTestFrame();
|
||||
|
||||
private:
|
||||
wxTextCtrl* m_log;
|
||||
|
||||
void LogEvent(const wxString& msg);
|
||||
|
||||
// Menu event handlers
|
||||
void OnMenuNew(wxCommandEvent& evt);
|
||||
void OnMenuOpen(wxCommandEvent& evt);
|
||||
void OnMenuSave(wxCommandEvent& evt);
|
||||
void OnMenuSaveAs(wxCommandEvent& evt);
|
||||
void OnMenuExit(wxCommandEvent& evt);
|
||||
|
||||
void OnMenuUndo(wxCommandEvent& evt);
|
||||
void OnMenuRedo(wxCommandEvent& evt);
|
||||
void OnMenuCut(wxCommandEvent& evt);
|
||||
void OnMenuCopy(wxCommandEvent& evt);
|
||||
void OnMenuPaste(wxCommandEvent& evt);
|
||||
void OnMenuSelectAll(wxCommandEvent& evt);
|
||||
|
||||
void OnMenuZoomIn(wxCommandEvent& evt);
|
||||
void OnMenuZoomOut(wxCommandEvent& evt);
|
||||
void OnMenuZoomFit(wxCommandEvent& evt);
|
||||
void OnMenuFullScreen(wxCommandEvent& evt);
|
||||
|
||||
void OnMenuPreferences(wxCommandEvent& evt);
|
||||
void OnMenuAbout(wxCommandEvent& evt);
|
||||
void OnMenuHelp(wxCommandEvent& evt);
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
enum {
|
||||
ID_NEW = wxID_HIGHEST + 1,
|
||||
ID_OPEN,
|
||||
ID_SAVE,
|
||||
ID_SAVE_AS,
|
||||
ID_UNDO,
|
||||
ID_REDO,
|
||||
ID_CUT,
|
||||
ID_COPY,
|
||||
ID_PASTE,
|
||||
ID_SELECT_ALL,
|
||||
ID_ZOOM_IN,
|
||||
ID_ZOOM_OUT,
|
||||
ID_ZOOM_FIT,
|
||||
ID_FULLSCREEN,
|
||||
ID_PREFERENCES,
|
||||
ID_HELP_CONTENTS
|
||||
};
|
||||
|
||||
wxBEGIN_EVENT_TABLE(MenuTestFrame, wxFrame)
|
||||
EVT_MENU(ID_NEW, MenuTestFrame::OnMenuNew)
|
||||
EVT_MENU(ID_OPEN, MenuTestFrame::OnMenuOpen)
|
||||
EVT_MENU(ID_SAVE, MenuTestFrame::OnMenuSave)
|
||||
EVT_MENU(ID_SAVE_AS, MenuTestFrame::OnMenuSaveAs)
|
||||
EVT_MENU(wxID_EXIT, MenuTestFrame::OnMenuExit)
|
||||
EVT_MENU(ID_UNDO, MenuTestFrame::OnMenuUndo)
|
||||
EVT_MENU(ID_REDO, MenuTestFrame::OnMenuRedo)
|
||||
EVT_MENU(ID_CUT, MenuTestFrame::OnMenuCut)
|
||||
EVT_MENU(ID_COPY, MenuTestFrame::OnMenuCopy)
|
||||
EVT_MENU(ID_PASTE, MenuTestFrame::OnMenuPaste)
|
||||
EVT_MENU(ID_SELECT_ALL, MenuTestFrame::OnMenuSelectAll)
|
||||
EVT_MENU(ID_ZOOM_IN, MenuTestFrame::OnMenuZoomIn)
|
||||
EVT_MENU(ID_ZOOM_OUT, MenuTestFrame::OnMenuZoomOut)
|
||||
EVT_MENU(ID_ZOOM_FIT, MenuTestFrame::OnMenuZoomFit)
|
||||
EVT_MENU(ID_FULLSCREEN, MenuTestFrame::OnMenuFullScreen)
|
||||
EVT_MENU(ID_PREFERENCES, MenuTestFrame::OnMenuPreferences)
|
||||
EVT_MENU(wxID_ABOUT, MenuTestFrame::OnMenuAbout)
|
||||
EVT_MENU(ID_HELP_CONTENTS, MenuTestFrame::OnMenuHelp)
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
wxIMPLEMENT_APP(MenuTestApp);
|
||||
|
||||
bool MenuTestApp::OnInit()
|
||||
{
|
||||
if (!wxApp::OnInit())
|
||||
return false;
|
||||
|
||||
MenuTestFrame* frame = new MenuTestFrame();
|
||||
frame->Show(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
MenuTestFrame::MenuTestFrame()
|
||||
: wxFrame(nullptr, wxID_ANY, "wxMenuBar WASM Test",
|
||||
wxDefaultPosition, wxSize(600, 400))
|
||||
{
|
||||
// Create File menu
|
||||
wxMenu* menuFile = new wxMenu;
|
||||
menuFile->Append(ID_NEW, "&New\tCtrl+N", "Create a new file");
|
||||
menuFile->Append(ID_OPEN, "&Open...\tCtrl+O", "Open an existing file");
|
||||
menuFile->AppendSeparator();
|
||||
menuFile->Append(ID_SAVE, "&Save\tCtrl+S", "Save the current file");
|
||||
menuFile->Append(ID_SAVE_AS, "Save &As...\tCtrl+Shift+S", "Save with a new name");
|
||||
menuFile->AppendSeparator();
|
||||
menuFile->Append(wxID_EXIT, "E&xit\tAlt+F4", "Exit the application");
|
||||
|
||||
// Create Edit menu
|
||||
wxMenu* menuEdit = new wxMenu;
|
||||
menuEdit->Append(ID_UNDO, "&Undo\tCtrl+Z", "Undo the last action");
|
||||
menuEdit->Append(ID_REDO, "&Redo\tCtrl+Y", "Redo the last undone action");
|
||||
menuEdit->AppendSeparator();
|
||||
menuEdit->Append(ID_CUT, "Cu&t\tCtrl+X", "Cut selection to clipboard");
|
||||
menuEdit->Append(ID_COPY, "&Copy\tCtrl+C", "Copy selection to clipboard");
|
||||
menuEdit->Append(ID_PASTE, "&Paste\tCtrl+V", "Paste from clipboard");
|
||||
menuEdit->AppendSeparator();
|
||||
menuEdit->Append(ID_SELECT_ALL, "Select &All\tCtrl+A", "Select all");
|
||||
|
||||
// Create View menu
|
||||
wxMenu* menuView = new wxMenu;
|
||||
menuView->Append(ID_ZOOM_IN, "Zoom &In\tCtrl++", "Zoom in");
|
||||
menuView->Append(ID_ZOOM_OUT, "Zoom &Out\tCtrl+-", "Zoom out");
|
||||
menuView->Append(ID_ZOOM_FIT, "Zoom to &Fit\tCtrl+0", "Fit view to window");
|
||||
menuView->AppendSeparator();
|
||||
menuView->AppendCheckItem(ID_FULLSCREEN, "&Full Screen\tF11", "Toggle full screen mode");
|
||||
|
||||
// Create Tools menu (like KiCad's preferences)
|
||||
wxMenu* menuTools = new wxMenu;
|
||||
menuTools->Append(ID_PREFERENCES, "&Preferences...", "Open preferences dialog");
|
||||
|
||||
// Create Help menu
|
||||
wxMenu* menuHelp = new wxMenu;
|
||||
menuHelp->Append(ID_HELP_CONTENTS, "&Help Contents\tF1", "Show help");
|
||||
menuHelp->AppendSeparator();
|
||||
menuHelp->Append(wxID_ABOUT, "&About...", "About this application");
|
||||
|
||||
// Create menu bar
|
||||
wxMenuBar* menuBar = new wxMenuBar;
|
||||
menuBar->Append(menuFile, "&File");
|
||||
menuBar->Append(menuEdit, "&Edit");
|
||||
menuBar->Append(menuView, "&View");
|
||||
menuBar->Append(menuTools, "&Tools");
|
||||
menuBar->Append(menuHelp, "&Help");
|
||||
|
||||
SetMenuBar(menuBar);
|
||||
|
||||
// Create main content - NO GL canvas
|
||||
wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
wxStaticText* desc = new wxStaticText(this, wxID_ANY,
|
||||
"wxMenuBar Test\n\n"
|
||||
"This tests the menu system which KiCad uses extensively.\n"
|
||||
"Click menu items to see events logged below.");
|
||||
sizer->Add(desc, 0, wxALL, 10);
|
||||
|
||||
m_log = new wxTextCtrl(this, wxID_ANY, "", wxDefaultPosition, wxSize(-1, 200),
|
||||
wxTE_MULTILINE | wxTE_READONLY);
|
||||
sizer->Add(m_log, 1, wxEXPAND | wxALL, 10);
|
||||
|
||||
SetSizer(sizer);
|
||||
|
||||
// Create status bar
|
||||
CreateStatusBar(2);
|
||||
SetStatusText("Ready");
|
||||
SetStatusText("Menu test", 1);
|
||||
|
||||
LogEvent("Menu test app started");
|
||||
LogEvent("Menu bar created with File, Edit, View, Tools, Help menus");
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM({
|
||||
console.log('[MENU_TEST] wxMenuBar test app started successfully');
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void MenuTestFrame::LogEvent(const wxString& msg)
|
||||
{
|
||||
m_log->AppendText(msg + "\n");
|
||||
SetStatusText(msg);
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM({
|
||||
console.log('[MENU_EVENT] ' + UTF8ToString($0));
|
||||
}, msg.c_str().AsChar());
|
||||
#endif
|
||||
}
|
||||
|
||||
// File menu handlers
|
||||
void MenuTestFrame::OnMenuNew(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("File > New clicked");
|
||||
}
|
||||
|
||||
void MenuTestFrame::OnMenuOpen(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("File > Open clicked");
|
||||
}
|
||||
|
||||
void MenuTestFrame::OnMenuSave(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("File > Save clicked");
|
||||
}
|
||||
|
||||
void MenuTestFrame::OnMenuSaveAs(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("File > Save As clicked");
|
||||
}
|
||||
|
||||
void MenuTestFrame::OnMenuExit(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("File > Exit clicked");
|
||||
Close(true);
|
||||
}
|
||||
|
||||
// Edit menu handlers
|
||||
void MenuTestFrame::OnMenuUndo(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Edit > Undo clicked");
|
||||
}
|
||||
|
||||
void MenuTestFrame::OnMenuRedo(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Edit > Redo clicked");
|
||||
}
|
||||
|
||||
void MenuTestFrame::OnMenuCut(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Edit > Cut clicked");
|
||||
}
|
||||
|
||||
void MenuTestFrame::OnMenuCopy(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Edit > Copy clicked");
|
||||
}
|
||||
|
||||
void MenuTestFrame::OnMenuPaste(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Edit > Paste clicked");
|
||||
}
|
||||
|
||||
void MenuTestFrame::OnMenuSelectAll(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Edit > Select All clicked");
|
||||
}
|
||||
|
||||
// View menu handlers
|
||||
void MenuTestFrame::OnMenuZoomIn(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("View > Zoom In clicked");
|
||||
}
|
||||
|
||||
void MenuTestFrame::OnMenuZoomOut(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("View > Zoom Out clicked");
|
||||
}
|
||||
|
||||
void MenuTestFrame::OnMenuZoomFit(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("View > Zoom to Fit clicked");
|
||||
}
|
||||
|
||||
void MenuTestFrame::OnMenuFullScreen(wxCommandEvent& evt)
|
||||
{
|
||||
bool isFullScreen = evt.IsChecked();
|
||||
LogEvent(wxString::Format("View > Full Screen toggled: %s",
|
||||
isFullScreen ? "ON" : "OFF"));
|
||||
ShowFullScreen(isFullScreen);
|
||||
}
|
||||
|
||||
// Tools menu handlers
|
||||
void MenuTestFrame::OnMenuPreferences(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Tools > Preferences clicked");
|
||||
}
|
||||
|
||||
// Help menu handlers
|
||||
void MenuTestFrame::OnMenuAbout(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Help > About clicked");
|
||||
}
|
||||
|
||||
void MenuTestFrame::OnMenuHelp(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Help > Help Contents clicked");
|
||||
}
|
||||
235
tests/wasm-app/standalone/timer/timer_test.cpp
Normal file
235
tests/wasm-app/standalone/timer/timer_test.cpp
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
// wxTimer Test - Tests timer functionality in WASM
|
||||
// KiCad uses timers for animations, auto-save, and periodic updates
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/wx.h"
|
||||
#endif
|
||||
|
||||
#include "wx/timer.h"
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten/emscripten.h>
|
||||
#endif
|
||||
|
||||
class TimerTestApp : public wxApp
|
||||
{
|
||||
public:
|
||||
virtual bool OnInit() override;
|
||||
};
|
||||
|
||||
class TimerTestFrame : public wxFrame
|
||||
{
|
||||
public:
|
||||
TimerTestFrame();
|
||||
~TimerTestFrame();
|
||||
|
||||
private:
|
||||
wxTimer* m_timer;
|
||||
wxTimer* m_fastTimer;
|
||||
int m_counter;
|
||||
int m_fastCounter;
|
||||
wxStaticText* m_counterDisplay;
|
||||
wxStaticText* m_fastCounterDisplay;
|
||||
wxGauge* m_progressGauge;
|
||||
wxTextCtrl* m_log;
|
||||
|
||||
void LogEvent(const wxString& msg);
|
||||
|
||||
void OnStartTimer(wxCommandEvent& evt);
|
||||
void OnStopTimer(wxCommandEvent& evt);
|
||||
void OnStartFastTimer(wxCommandEvent& evt);
|
||||
void OnStopFastTimer(wxCommandEvent& evt);
|
||||
void OnResetCounters(wxCommandEvent& evt);
|
||||
void OnTimer(wxTimerEvent& evt);
|
||||
void OnFastTimer(wxTimerEvent& evt);
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
enum {
|
||||
ID_START_TIMER = wxID_HIGHEST + 1,
|
||||
ID_STOP_TIMER,
|
||||
ID_START_FAST_TIMER,
|
||||
ID_STOP_FAST_TIMER,
|
||||
ID_RESET_COUNTERS,
|
||||
ID_TIMER,
|
||||
ID_FAST_TIMER
|
||||
};
|
||||
|
||||
wxBEGIN_EVENT_TABLE(TimerTestFrame, wxFrame)
|
||||
EVT_BUTTON(ID_START_TIMER, TimerTestFrame::OnStartTimer)
|
||||
EVT_BUTTON(ID_STOP_TIMER, TimerTestFrame::OnStopTimer)
|
||||
EVT_BUTTON(ID_START_FAST_TIMER, TimerTestFrame::OnStartFastTimer)
|
||||
EVT_BUTTON(ID_STOP_FAST_TIMER, TimerTestFrame::OnStopFastTimer)
|
||||
EVT_BUTTON(ID_RESET_COUNTERS, TimerTestFrame::OnResetCounters)
|
||||
EVT_TIMER(ID_TIMER, TimerTestFrame::OnTimer)
|
||||
EVT_TIMER(ID_FAST_TIMER, TimerTestFrame::OnFastTimer)
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
wxIMPLEMENT_APP(TimerTestApp);
|
||||
|
||||
bool TimerTestApp::OnInit()
|
||||
{
|
||||
if (!wxApp::OnInit())
|
||||
return false;
|
||||
|
||||
TimerTestFrame* frame = new TimerTestFrame();
|
||||
frame->Show(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
TimerTestFrame::TimerTestFrame()
|
||||
: wxFrame(nullptr, wxID_ANY, "wxTimer WASM Test",
|
||||
wxDefaultPosition, wxSize(600, 550))
|
||||
, m_counter(0)
|
||||
, m_fastCounter(0)
|
||||
{
|
||||
m_timer = new wxTimer(this, ID_TIMER);
|
||||
m_fastTimer = new wxTimer(this, ID_FAST_TIMER);
|
||||
|
||||
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
wxStaticText* desc = new wxStaticText(this, wxID_ANY,
|
||||
"wxTimer Test\n\n"
|
||||
"KiCad uses timers for auto-save, animations, and periodic updates.\n"
|
||||
"Test both slow (1 sec) and fast (100ms) timers.");
|
||||
mainSizer->Add(desc, 0, wxALL, 10);
|
||||
|
||||
// Slow timer section (1 second interval)
|
||||
wxStaticBoxSizer* timerBox = new wxStaticBoxSizer(wxVERTICAL, this, "Slow Timer (1 second)");
|
||||
|
||||
wxBoxSizer* timerBtnSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
timerBtnSizer->Add(new wxButton(this, ID_START_TIMER, "Start"), 0, wxALL, 5);
|
||||
timerBtnSizer->Add(new wxButton(this, ID_STOP_TIMER, "Stop"), 0, wxALL, 5);
|
||||
timerBox->Add(timerBtnSizer, 0, wxALIGN_CENTER);
|
||||
|
||||
m_counterDisplay = new wxStaticText(this, wxID_ANY, "Counter: 0",
|
||||
wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER);
|
||||
m_counterDisplay->SetFont(m_counterDisplay->GetFont().Scale(2.0));
|
||||
timerBox->Add(m_counterDisplay, 0, wxALIGN_CENTER | wxALL, 10);
|
||||
|
||||
mainSizer->Add(timerBox, 0, wxEXPAND | wxALL, 10);
|
||||
|
||||
// Fast timer section (100ms interval)
|
||||
wxStaticBoxSizer* fastTimerBox = new wxStaticBoxSizer(wxVERTICAL, this, "Fast Timer (100ms)");
|
||||
|
||||
wxBoxSizer* fastBtnSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
fastBtnSizer->Add(new wxButton(this, ID_START_FAST_TIMER, "Start Fast"), 0, wxALL, 5);
|
||||
fastBtnSizer->Add(new wxButton(this, ID_STOP_FAST_TIMER, "Stop Fast"), 0, wxALL, 5);
|
||||
fastTimerBox->Add(fastBtnSizer, 0, wxALIGN_CENTER);
|
||||
|
||||
m_fastCounterDisplay = new wxStaticText(this, wxID_ANY, "Fast Counter: 0");
|
||||
fastTimerBox->Add(m_fastCounterDisplay, 0, wxALIGN_CENTER | wxALL, 5);
|
||||
|
||||
m_progressGauge = new wxGauge(this, wxID_ANY, 100);
|
||||
fastTimerBox->Add(m_progressGauge, 0, wxEXPAND | wxALL, 5);
|
||||
|
||||
mainSizer->Add(fastTimerBox, 0, wxEXPAND | wxALL, 10);
|
||||
|
||||
// Reset button
|
||||
mainSizer->Add(new wxButton(this, ID_RESET_COUNTERS, "Reset All Counters"),
|
||||
0, wxALIGN_CENTER | wxALL, 5);
|
||||
|
||||
// Event log
|
||||
wxStaticBoxSizer* logBox = new wxStaticBoxSizer(wxVERTICAL, this, "Event Log");
|
||||
m_log = new wxTextCtrl(this, wxID_ANY, "",
|
||||
wxDefaultPosition, wxSize(-1, 120), wxTE_MULTILINE | wxTE_READONLY);
|
||||
logBox->Add(m_log, 1, wxEXPAND | wxALL, 5);
|
||||
mainSizer->Add(logBox, 1, wxEXPAND | wxALL, 10);
|
||||
|
||||
SetSizer(mainSizer);
|
||||
CreateStatusBar();
|
||||
SetStatusText("Ready");
|
||||
|
||||
LogEvent("Timer test app started");
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM({
|
||||
console.log('[TIMER_TEST] wxTimer test app started successfully');
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
TimerTestFrame::~TimerTestFrame()
|
||||
{
|
||||
m_timer->Stop();
|
||||
m_fastTimer->Stop();
|
||||
delete m_timer;
|
||||
delete m_fastTimer;
|
||||
}
|
||||
|
||||
void TimerTestFrame::LogEvent(const wxString& msg)
|
||||
{
|
||||
m_log->AppendText(msg + "\n");
|
||||
SetStatusText(msg);
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM({
|
||||
console.log('[TIMER_EVENT] ' + UTF8ToString($0));
|
||||
}, msg.c_str().AsChar());
|
||||
#endif
|
||||
}
|
||||
|
||||
void TimerTestFrame::OnStartTimer(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
m_timer->Start(1000); // 1 second
|
||||
LogEvent("Slow timer started (1 second interval)");
|
||||
}
|
||||
|
||||
void TimerTestFrame::OnStopTimer(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
m_timer->Stop();
|
||||
LogEvent("Slow timer stopped");
|
||||
}
|
||||
|
||||
void TimerTestFrame::OnStartFastTimer(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
m_fastTimer->Start(100); // 100ms
|
||||
LogEvent("Fast timer started (100ms interval)");
|
||||
}
|
||||
|
||||
void TimerTestFrame::OnStopFastTimer(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
m_fastTimer->Stop();
|
||||
LogEvent("Fast timer stopped");
|
||||
}
|
||||
|
||||
void TimerTestFrame::OnResetCounters(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
m_counter = 0;
|
||||
m_fastCounter = 0;
|
||||
m_counterDisplay->SetLabel("Counter: 0");
|
||||
m_fastCounterDisplay->SetLabel("Fast Counter: 0");
|
||||
m_progressGauge->SetValue(0);
|
||||
LogEvent("Counters reset");
|
||||
}
|
||||
|
||||
void TimerTestFrame::OnTimer(wxTimerEvent& WXUNUSED(evt))
|
||||
{
|
||||
m_counter++;
|
||||
m_counterDisplay->SetLabel(wxString::Format("Counter: %d", m_counter));
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM({
|
||||
console.log('[TIMER_TICK] Slow timer tick: ' + $0);
|
||||
}, m_counter);
|
||||
#endif
|
||||
}
|
||||
|
||||
void TimerTestFrame::OnFastTimer(wxTimerEvent& WXUNUSED(evt))
|
||||
{
|
||||
m_fastCounter++;
|
||||
m_fastCounterDisplay->SetLabel(wxString::Format("Fast Counter: %d", m_fastCounter));
|
||||
m_progressGauge->SetValue(m_fastCounter % 101);
|
||||
|
||||
// Log every 10 ticks to avoid flooding
|
||||
if (m_fastCounter % 10 == 0) {
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM({
|
||||
console.log('[TIMER_TICK] Fast timer tick: ' + $0);
|
||||
}, m_fastCounter);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
188
tests/wasm-app/standalone/toolbar/toolbar_test.cpp
Normal file
188
tests/wasm-app/standalone/toolbar/toolbar_test.cpp
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
// wxToolBar/wxStatusBar Test - Tests toolbar and statusbar in WASM
|
||||
// KiCad uses toolbars extensively for actions
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/wx.h"
|
||||
#endif
|
||||
|
||||
#include "wx/artprov.h"
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten/emscripten.h>
|
||||
#endif
|
||||
|
||||
class ToolbarTestApp : public wxApp
|
||||
{
|
||||
public:
|
||||
virtual bool OnInit() override;
|
||||
};
|
||||
|
||||
class ToolbarTestFrame : public wxFrame
|
||||
{
|
||||
public:
|
||||
ToolbarTestFrame();
|
||||
|
||||
private:
|
||||
wxTextCtrl* m_log;
|
||||
|
||||
void LogEvent(const wxString& msg);
|
||||
|
||||
void OnToolNew(wxCommandEvent& evt);
|
||||
void OnToolOpen(wxCommandEvent& evt);
|
||||
void OnToolSave(wxCommandEvent& evt);
|
||||
void OnToolZoomIn(wxCommandEvent& evt);
|
||||
void OnToolZoomOut(wxCommandEvent& evt);
|
||||
void OnToolToggle(wxCommandEvent& evt);
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
enum {
|
||||
ID_TOOL_NEW = wxID_HIGHEST + 1,
|
||||
ID_TOOL_OPEN,
|
||||
ID_TOOL_SAVE,
|
||||
ID_TOOL_ZOOM_IN,
|
||||
ID_TOOL_ZOOM_OUT,
|
||||
ID_TOOL_TOGGLE
|
||||
};
|
||||
|
||||
wxBEGIN_EVENT_TABLE(ToolbarTestFrame, wxFrame)
|
||||
EVT_TOOL(ID_TOOL_NEW, ToolbarTestFrame::OnToolNew)
|
||||
EVT_TOOL(ID_TOOL_OPEN, ToolbarTestFrame::OnToolOpen)
|
||||
EVT_TOOL(ID_TOOL_SAVE, ToolbarTestFrame::OnToolSave)
|
||||
EVT_TOOL(ID_TOOL_ZOOM_IN, ToolbarTestFrame::OnToolZoomIn)
|
||||
EVT_TOOL(ID_TOOL_ZOOM_OUT, ToolbarTestFrame::OnToolZoomOut)
|
||||
EVT_TOOL(ID_TOOL_TOGGLE, ToolbarTestFrame::OnToolToggle)
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
wxIMPLEMENT_APP(ToolbarTestApp);
|
||||
|
||||
bool ToolbarTestApp::OnInit()
|
||||
{
|
||||
if (!wxApp::OnInit())
|
||||
return false;
|
||||
|
||||
ToolbarTestFrame* frame = new ToolbarTestFrame();
|
||||
frame->Show(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
ToolbarTestFrame::ToolbarTestFrame()
|
||||
: wxFrame(nullptr, wxID_ANY, "wxToolBar/wxStatusBar WASM Test",
|
||||
wxDefaultPosition, wxSize(700, 500))
|
||||
{
|
||||
// Create toolbar
|
||||
wxToolBar* toolbar = CreateToolBar(wxTB_HORIZONTAL | wxTB_TEXT);
|
||||
|
||||
toolbar->AddTool(ID_TOOL_NEW, "New",
|
||||
wxArtProvider::GetBitmap(wxART_NEW, wxART_TOOLBAR),
|
||||
"Create new file");
|
||||
toolbar->AddTool(ID_TOOL_OPEN, "Open",
|
||||
wxArtProvider::GetBitmap(wxART_FILE_OPEN, wxART_TOOLBAR),
|
||||
"Open existing file");
|
||||
toolbar->AddTool(ID_TOOL_SAVE, "Save",
|
||||
wxArtProvider::GetBitmap(wxART_FILE_SAVE, wxART_TOOLBAR),
|
||||
"Save current file");
|
||||
|
||||
toolbar->AddSeparator();
|
||||
|
||||
toolbar->AddTool(ID_TOOL_ZOOM_IN, "Zoom In",
|
||||
wxArtProvider::GetBitmap(wxART_PLUS, wxART_TOOLBAR),
|
||||
"Zoom in");
|
||||
toolbar->AddTool(ID_TOOL_ZOOM_OUT, "Zoom Out",
|
||||
wxArtProvider::GetBitmap(wxART_MINUS, wxART_TOOLBAR),
|
||||
"Zoom out");
|
||||
|
||||
toolbar->AddSeparator();
|
||||
|
||||
toolbar->AddCheckTool(ID_TOOL_TOGGLE, "Toggle",
|
||||
wxArtProvider::GetBitmap(wxART_TICK_MARK, wxART_TOOLBAR),
|
||||
wxNullBitmap,
|
||||
"Toggle tool example");
|
||||
|
||||
toolbar->Realize();
|
||||
|
||||
// Create status bar with multiple fields
|
||||
CreateStatusBar(3);
|
||||
SetStatusText("Ready", 0);
|
||||
SetStatusText("X: 0, Y: 0", 1);
|
||||
SetStatusText("Zoom: 100%", 2);
|
||||
|
||||
// Set status bar field widths
|
||||
int widths[] = {-1, 150, 100};
|
||||
GetStatusBar()->SetStatusWidths(3, widths);
|
||||
|
||||
// Main content
|
||||
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
wxStaticText* desc = new wxStaticText(this, wxID_ANY,
|
||||
"wxToolBar and wxStatusBar Test\n\n"
|
||||
"KiCad uses toolbars for quick access to tools.\n"
|
||||
"Click toolbar buttons to see events.");
|
||||
mainSizer->Add(desc, 0, wxALL, 10);
|
||||
|
||||
wxStaticBoxSizer* logBox = new wxStaticBoxSizer(wxVERTICAL, this, "Event Log");
|
||||
m_log = new wxTextCtrl(this, wxID_ANY, "",
|
||||
wxDefaultPosition, wxSize(-1, 200), wxTE_MULTILINE | wxTE_READONLY);
|
||||
logBox->Add(m_log, 1, wxEXPAND | wxALL, 5);
|
||||
mainSizer->Add(logBox, 1, wxEXPAND | wxALL, 10);
|
||||
|
||||
SetSizer(mainSizer);
|
||||
|
||||
LogEvent("Toolbar test app started");
|
||||
LogEvent("Toolbar created with 6 tools");
|
||||
LogEvent("Status bar created with 3 fields");
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM({
|
||||
console.log('[TOOLBAR_TEST] wxToolBar test app started successfully');
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void ToolbarTestFrame::LogEvent(const wxString& msg)
|
||||
{
|
||||
m_log->AppendText(msg + "\n");
|
||||
SetStatusText(msg, 0);
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM({
|
||||
console.log('[TOOLBAR_EVENT] ' + UTF8ToString($0));
|
||||
}, msg.c_str().AsChar());
|
||||
#endif
|
||||
}
|
||||
|
||||
void ToolbarTestFrame::OnToolNew(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Toolbar: New clicked");
|
||||
}
|
||||
|
||||
void ToolbarTestFrame::OnToolOpen(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Toolbar: Open clicked");
|
||||
}
|
||||
|
||||
void ToolbarTestFrame::OnToolSave(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Toolbar: Save clicked");
|
||||
}
|
||||
|
||||
void ToolbarTestFrame::OnToolZoomIn(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Toolbar: Zoom In clicked");
|
||||
SetStatusText("Zoom: 150%", 2);
|
||||
}
|
||||
|
||||
void ToolbarTestFrame::OnToolZoomOut(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
LogEvent("Toolbar: Zoom Out clicked");
|
||||
SetStatusText("Zoom: 75%", 2);
|
||||
}
|
||||
|
||||
void ToolbarTestFrame::OnToolToggle(wxCommandEvent& evt)
|
||||
{
|
||||
bool checked = evt.IsChecked();
|
||||
LogEvent(wxString::Format("Toolbar: Toggle %s", checked ? "ON" : "OFF"));
|
||||
}
|
||||
252
tests/wasm-app/standalone/tree/tree_test.cpp
Normal file
252
tests/wasm-app/standalone/tree/tree_test.cpp
Normal file
|
|
@ -0,0 +1,252 @@
|
|||
// wxTreeCtrl Test - Tests tree control in WASM
|
||||
// KiCad uses tree controls for hierarchy browsers (components, nets, etc.)
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/wx.h"
|
||||
#endif
|
||||
|
||||
#include "wx/treectrl.h"
|
||||
#include "wx/imaglist.h"
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten/emscripten.h>
|
||||
#endif
|
||||
|
||||
class TreeTestApp : public wxApp
|
||||
{
|
||||
public:
|
||||
virtual bool OnInit() override;
|
||||
};
|
||||
|
||||
class TreeTestFrame : public wxFrame
|
||||
{
|
||||
public:
|
||||
TreeTestFrame();
|
||||
|
||||
private:
|
||||
wxTreeCtrl* m_tree;
|
||||
wxTextCtrl* m_log;
|
||||
|
||||
void LogEvent(const wxString& msg);
|
||||
void PopulateTree();
|
||||
|
||||
void OnSelChanged(wxTreeEvent& evt);
|
||||
void OnItemExpanding(wxTreeEvent& evt);
|
||||
void OnItemCollapsing(wxTreeEvent& evt);
|
||||
void OnItemActivated(wxTreeEvent& evt);
|
||||
void OnExpandAll(wxCommandEvent& evt);
|
||||
void OnCollapseAll(wxCommandEvent& evt);
|
||||
void OnAddItem(wxCommandEvent& evt);
|
||||
void OnDeleteItem(wxCommandEvent& evt);
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
enum {
|
||||
ID_TREE = wxID_HIGHEST + 1,
|
||||
ID_EXPAND_ALL,
|
||||
ID_COLLAPSE_ALL,
|
||||
ID_ADD_ITEM,
|
||||
ID_DELETE_ITEM
|
||||
};
|
||||
|
||||
wxBEGIN_EVENT_TABLE(TreeTestFrame, wxFrame)
|
||||
EVT_TREE_SEL_CHANGED(ID_TREE, TreeTestFrame::OnSelChanged)
|
||||
EVT_TREE_ITEM_EXPANDING(ID_TREE, TreeTestFrame::OnItemExpanding)
|
||||
EVT_TREE_ITEM_COLLAPSING(ID_TREE, TreeTestFrame::OnItemCollapsing)
|
||||
EVT_TREE_ITEM_ACTIVATED(ID_TREE, TreeTestFrame::OnItemActivated)
|
||||
EVT_BUTTON(ID_EXPAND_ALL, TreeTestFrame::OnExpandAll)
|
||||
EVT_BUTTON(ID_COLLAPSE_ALL, TreeTestFrame::OnCollapseAll)
|
||||
EVT_BUTTON(ID_ADD_ITEM, TreeTestFrame::OnAddItem)
|
||||
EVT_BUTTON(ID_DELETE_ITEM, TreeTestFrame::OnDeleteItem)
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
wxIMPLEMENT_APP(TreeTestApp);
|
||||
|
||||
bool TreeTestApp::OnInit()
|
||||
{
|
||||
if (!wxApp::OnInit())
|
||||
return false;
|
||||
|
||||
TreeTestFrame* frame = new TreeTestFrame();
|
||||
frame->Show(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
TreeTestFrame::TreeTestFrame()
|
||||
: wxFrame(nullptr, wxID_ANY, "wxTreeCtrl WASM Test",
|
||||
wxDefaultPosition, wxSize(600, 600))
|
||||
{
|
||||
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
wxStaticText* desc = new wxStaticText(this, wxID_ANY,
|
||||
"wxTreeCtrl Test\n\n"
|
||||
"KiCad uses tree controls for hierarchy browsers, component trees, and net lists.\n"
|
||||
"Click items to select, double-click to activate, +/- to expand/collapse.");
|
||||
mainSizer->Add(desc, 0, wxALL, 10);
|
||||
|
||||
// Button bar
|
||||
wxBoxSizer* btnSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
btnSizer->Add(new wxButton(this, ID_EXPAND_ALL, "Expand All"), 0, wxALL, 5);
|
||||
btnSizer->Add(new wxButton(this, ID_COLLAPSE_ALL, "Collapse All"), 0, wxALL, 5);
|
||||
btnSizer->Add(new wxButton(this, ID_ADD_ITEM, "Add Item"), 0, wxALL, 5);
|
||||
btnSizer->Add(new wxButton(this, ID_DELETE_ITEM, "Delete Selected"), 0, wxALL, 5);
|
||||
mainSizer->Add(btnSizer, 0, wxALIGN_CENTER);
|
||||
|
||||
// Tree control
|
||||
m_tree = new wxTreeCtrl(this, ID_TREE, wxDefaultPosition, wxSize(-1, 250),
|
||||
wxTR_DEFAULT_STYLE | wxTR_EDIT_LABELS);
|
||||
mainSizer->Add(m_tree, 1, wxEXPAND | wxALL, 10);
|
||||
|
||||
PopulateTree();
|
||||
|
||||
// Event log
|
||||
wxStaticBoxSizer* logBox = new wxStaticBoxSizer(wxVERTICAL, this, "Event Log");
|
||||
m_log = new wxTextCtrl(this, wxID_ANY, "",
|
||||
wxDefaultPosition, wxSize(-1, 150), wxTE_MULTILINE | wxTE_READONLY);
|
||||
logBox->Add(m_log, 1, wxEXPAND | wxALL, 5);
|
||||
mainSizer->Add(logBox, 0, wxEXPAND | wxALL, 10);
|
||||
|
||||
SetSizer(mainSizer);
|
||||
CreateStatusBar();
|
||||
SetStatusText("Ready");
|
||||
|
||||
LogEvent("Tree test app started");
|
||||
LogEvent("Tree populated with KiCad-like hierarchy");
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM({
|
||||
console.log('[TREE_TEST] wxTreeCtrl test app started successfully');
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void TreeTestFrame::PopulateTree()
|
||||
{
|
||||
// Create a KiCad-like component hierarchy
|
||||
wxTreeItemId root = m_tree->AddRoot("Project: MyBoard");
|
||||
|
||||
// Schematic hierarchy
|
||||
wxTreeItemId schematic = m_tree->AppendItem(root, "Schematic");
|
||||
wxTreeItemId sheet1 = m_tree->AppendItem(schematic, "Sheet 1 - Main");
|
||||
m_tree->AppendItem(sheet1, "U1 - MCU");
|
||||
m_tree->AppendItem(sheet1, "U2 - Power Regulator");
|
||||
m_tree->AppendItem(sheet1, "C1-C10 - Capacitors");
|
||||
m_tree->AppendItem(sheet1, "R1-R20 - Resistors");
|
||||
|
||||
wxTreeItemId sheet2 = m_tree->AppendItem(schematic, "Sheet 2 - IO");
|
||||
m_tree->AppendItem(sheet2, "J1 - USB Connector");
|
||||
m_tree->AppendItem(sheet2, "J2 - GPIO Header");
|
||||
m_tree->AppendItem(sheet2, "LED1-LED4 - Status LEDs");
|
||||
|
||||
// PCB hierarchy
|
||||
wxTreeItemId pcb = m_tree->AppendItem(root, "PCB");
|
||||
wxTreeItemId layers = m_tree->AppendItem(pcb, "Layers");
|
||||
m_tree->AppendItem(layers, "F.Cu - Front Copper");
|
||||
m_tree->AppendItem(layers, "B.Cu - Back Copper");
|
||||
m_tree->AppendItem(layers, "F.SilkS - Front Silkscreen");
|
||||
m_tree->AppendItem(layers, "B.SilkS - Back Silkscreen");
|
||||
m_tree->AppendItem(layers, "Edge.Cuts - Board Outline");
|
||||
|
||||
wxTreeItemId nets = m_tree->AppendItem(pcb, "Nets");
|
||||
m_tree->AppendItem(nets, "GND (45 pads)");
|
||||
m_tree->AppendItem(nets, "VCC (12 pads)");
|
||||
m_tree->AppendItem(nets, "3V3 (8 pads)");
|
||||
m_tree->AppendItem(nets, "SDA (4 pads)");
|
||||
m_tree->AppendItem(nets, "SCL (4 pads)");
|
||||
|
||||
// Libraries
|
||||
wxTreeItemId libraries = m_tree->AppendItem(root, "Libraries");
|
||||
m_tree->AppendItem(libraries, "Device.lib");
|
||||
m_tree->AppendItem(libraries, "Connector.lib");
|
||||
m_tree->AppendItem(libraries, "MCU_ST.lib");
|
||||
|
||||
m_tree->Expand(root);
|
||||
m_tree->Expand(schematic);
|
||||
m_tree->Expand(pcb);
|
||||
}
|
||||
|
||||
void TreeTestFrame::LogEvent(const wxString& msg)
|
||||
{
|
||||
m_log->AppendText(msg + "\n");
|
||||
SetStatusText(msg);
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EM_ASM({
|
||||
console.log('[TREE_EVENT] ' + UTF8ToString($0));
|
||||
}, msg.c_str().AsChar());
|
||||
#endif
|
||||
}
|
||||
|
||||
void TreeTestFrame::OnSelChanged(wxTreeEvent& evt)
|
||||
{
|
||||
wxTreeItemId item = evt.GetItem();
|
||||
if (item.IsOk()) {
|
||||
LogEvent(wxString::Format("Selection changed: '%s'", m_tree->GetItemText(item)));
|
||||
}
|
||||
}
|
||||
|
||||
void TreeTestFrame::OnItemExpanding(wxTreeEvent& evt)
|
||||
{
|
||||
wxTreeItemId item = evt.GetItem();
|
||||
if (item.IsOk()) {
|
||||
LogEvent(wxString::Format("Expanding: '%s'", m_tree->GetItemText(item)));
|
||||
}
|
||||
}
|
||||
|
||||
void TreeTestFrame::OnItemCollapsing(wxTreeEvent& evt)
|
||||
{
|
||||
wxTreeItemId item = evt.GetItem();
|
||||
if (item.IsOk()) {
|
||||
LogEvent(wxString::Format("Collapsing: '%s'", m_tree->GetItemText(item)));
|
||||
}
|
||||
}
|
||||
|
||||
void TreeTestFrame::OnItemActivated(wxTreeEvent& evt)
|
||||
{
|
||||
wxTreeItemId item = evt.GetItem();
|
||||
if (item.IsOk()) {
|
||||
LogEvent(wxString::Format("Activated (double-click): '%s'", m_tree->GetItemText(item)));
|
||||
}
|
||||
}
|
||||
|
||||
void TreeTestFrame::OnExpandAll(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
m_tree->ExpandAll();
|
||||
LogEvent("All items expanded");
|
||||
}
|
||||
|
||||
void TreeTestFrame::OnCollapseAll(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
m_tree->CollapseAll();
|
||||
LogEvent("All items collapsed");
|
||||
}
|
||||
|
||||
void TreeTestFrame::OnAddItem(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
wxTreeItemId sel = m_tree->GetSelection();
|
||||
if (sel.IsOk()) {
|
||||
static int itemNum = 1;
|
||||
wxTreeItemId newItem = m_tree->AppendItem(sel,
|
||||
wxString::Format("New Item %d", itemNum++));
|
||||
m_tree->Expand(sel);
|
||||
m_tree->SelectItem(newItem);
|
||||
LogEvent(wxString::Format("Added new item under '%s'", m_tree->GetItemText(sel)));
|
||||
} else {
|
||||
LogEvent("No item selected - select a parent first");
|
||||
}
|
||||
}
|
||||
|
||||
void TreeTestFrame::OnDeleteItem(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
wxTreeItemId sel = m_tree->GetSelection();
|
||||
if (sel.IsOk() && sel != m_tree->GetRootItem()) {
|
||||
wxString itemText = m_tree->GetItemText(sel);
|
||||
m_tree->Delete(sel);
|
||||
LogEvent(wxString::Format("Deleted item: '%s'", itemText));
|
||||
} else {
|
||||
LogEvent("Cannot delete root or no item selected");
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue