Adding New Screens
Section titled “Adding New Screens”Relevant source files
- main/display/cnc/fluidnc/screens/esp3d_screen_type.cpp
- main/display/cnc/fluidnc/screens/esp3d_screen_type.h
- main/display/cnc/fluidnc/screens/files_screen.cpp
- main/display/cnc/grblhal/screens/esp3d_screen_type.cpp
- main/display/esp3d_screen_transition.h
- main/display/esp3d_translations_init.cpp
- main/display/esp3d_translations_list.h
- main/display/screens/generic_screen.cpp
- main/display/screens/generic_screen.h
- tools/language_packs/template.lng
- tools/language_packs/ui_fr-fr.lng
This guide provides a step-by-step process for adding new application screens to the PiBot CNC Pendant firmware. It covers the technical requirements, code structure, and integration points needed to create a functional screen that integrates with the existing UI framework.
For information about screen lifecycle management and the base classes, see 7.2. Screen Lifecycle Management For details on reusable components that can be integrated into screens, see 8. Reusable UI Components
Overview
Section titled “Overview”The screen system is built on a hierarchical architecture where each screen:
- Is identified by an
ESP3DScreenTypeenum value main/display/cnc/fluidnc/screens/esp3d_screen_type.h#26-61 - Implements a
create()function within a dedicated namespace main/display/cnc/fluidnc/screens/esp3d_screen_type.cpp#25-115 - Is routed through a centralized
createScreen()dispatcher main/display/cnc/fluidnc/screens/esp3d_screen_type.cpp#122-232 - Extends
GenericScreenfor common functionality like orientation and styling main/display/screens/generic_screen.h#26-54 - Registers itself with
UIManagerfor lifecycle management main/display/screens/generic_screen.cpp#160-165
Screen Registration Layer Architecture
Sources:main/display/cnc/fluidnc/screens/esp3d_screen_type.h#26-103main/display/cnc/fluidnc/screens/esp3d_screen_type.cpp#122-232main/display/screens/generic_screen.h#26-54
Screen Creation Sequence
Section titled “Screen Creation Sequence”The following diagram shows the complete flow from screen creation request to active screen, using actual function and variable names from the codebase:
Screen Initialization Sequence
Sources:main/display/cnc/fluidnc/screens/esp3d_screen_type.cpp#122-232main/display/screens/generic_screen.cpp#35-177main/display/screens/generic_screen.h#52-54
Step-by-Step Implementation Guide
Section titled “Step-by-Step Implementation Guide”1. Add Screen Type to Enumeration
Section titled “1. Add Screen Type to Enumeration”Add your screen type to the ESP3DScreenType enum in main/display/cnc/fluidnc/screens/esp3d_screen_type.h#26-61 If ESP3D_LOG is enabled, also add the string name to the screen_type_names array at main/display/cnc/fluidnc/screens/esp3d_screen_type.h#81-103
2. Add Forward Declaration and Dispatcher Case
Section titled “2. Add Forward Declaration and Dispatcher Case”In main/display/cnc/fluidnc/screens/esp3d_screen_type.cpp#25-115 add a forward declaration for your screen’s create() function within its namespace. Then, add a case statement to the createScreen() function main/display/cnc/fluidnc/screens/esp3d_screen_type.cpp#125-231
3. Implement the create() Function
Section titled “3. Implement the create() Function”The create() function is the entry point for screen instantiation. It typically follows this pattern:
- Check for existing instance: Prevent duplicate creation using a static instance pointer (e.g.,
files_screen_obj_instance) main/display/cnc/fluidnc/screens/files_screen.cpp#105 - Define Button Configuration: Use the
virtual_button_conf_tstructure to define the bottom virtual buttons. - Instantiate GenericScreen: This handles base LVGL screen creation, background styling, and component registration main/display/screens/generic_screen.cpp#35-177
- Get Container: Access the rotatable container via
getContainer()main/display/screens/generic_screen.h#63 to place your UI elements. - Create UI Elements: Use standard LVGL functions (
lv_label_create, etc.) on the container. - Subscribe to Values: If the screen needs real-time data (like position), subscribe to
esp3dTftValuesusingonFileEntryUpdatestyle callbacks main/display/cnc/fluidnc/screens/files_screen.cpp#149-150 - Setup Cleanup: Add an
LV_EVENT_DELETEcallback to the screen object to handle destruction. UseESP3D_TRANSITION_STARTorESP3D_CLEANUP_TIMER_BODYmacros if using the standard transition pattern main/display/esp3d_screen_transition.h#73-130
Sources:main/display/screens/generic_screen.cpp#35-177main/display/cnc/fluidnc/screens/esp3d_screen_type.cpp#122-232main/display/esp3d_screen_transition.h#73-130main/display/cnc/fluidnc/screens/files_screen.cpp#105
Component Integration
Section titled “Component Integration”Screens often utilize specialized components. The GenericScreen constructor automatically registers itself as a ComponentType::generic_screenmain/display/screens/generic_screen.cpp#160-165
| Component | Class / Type | Purpose |
|---|---|---|
| Virtual Buttons | VirtualButtonsComponent | Manages the 3 bottom navigation/action buttons main/display/screens/generic_screen.h#31 |
| List Menus | ListMenuScreen | Base class for scrollable lists like file browsing main/display/cnc/fluidnc/screens/files_screen.cpp#42 |
| Status Indicators | ConnectionStatusComponent | Shows network/communication status main/display/cnc/fluidnc/screens/esp3d_screen_type.h#72 |
Configuring Virtual Buttons
Section titled “Configuring Virtual Buttons”Buttons are configured during GenericScreen initialization main/display/screens/generic_screen.cpp#147-157
configs: An array ofvirtual_button_conf_t.hardware_btn_id: Maps to physical buttons (0, 1, 2).updateButtonsStyles(): Updates button visuals when themes change main/display/screens/generic_screen.h#67-73
Sources:main/display/screens/generic_screen.cpp#147-157main/display/screens/generic_screen.h#31-73
Lifecycle and Cleanup
Section titled “Lifecycle and Cleanup”Every screen must implement a cleanup mechanism, typically triggered by LV_EVENT_DELETE.
Screen Cleanup Process
The prepareForDestruction() method in GenericScreen is responsible for unregistering the component from the UIManager and cleaning up virtual buttons main/display/screens/generic_screen.cpp#252-272 Specific screens like files_screen extend this to stop timers (e.g., watchdog_timer) and clear buffers main/display/cnc/fluidnc/screens/files_screen.cpp#139-142
Sources:main/display/screens/generic_screen.cpp#252-272main/display/screens/generic_screen.h#58main/display/cnc/fluidnc/screens/files_screen.cpp#139-142
Translation Integration
Section titled “Translation Integration”Text should never be hardcoded. Use the ESP3DTranslationService and the ESP3DLabel enum.
- Define Label: Add a label definition in the
.incdefinition files (e.g.,esp3d_translations_defs.inc). - Generate Enum: The
ESP3D_TR_DEFmacro generates the enum value inESP3DLabelmain/display/esp3d_translations_list.h#37-47 - Implement Fallback: Ensure the string is added to the English fallback table
kEnglishTextsmain/display/esp3d_translations_init.cpp#33-37 - Retrieve Text: In your screen, retrieve the text using
esp3d_translations_english(ESP3DLabel::label_name)main/display/esp3d_translations_init.cpp#45-51
Sources:main/display/esp3d_translations_init.cpp#33-51main/display/esp3d_translations_list.h#32-47tools/language_packs/template.lng#11-47