rust_widgets 2.8.2

Pure Rust cross-platform native GUI library with hardware-adaptive rendering, 180 widgets, touch/gesture support, i18n, and SVG-pipeline-accurate output
// SPDX-FileCopyrightText: Copyright (c) 2026 Mike Li/Mikewolfli/Wei Li(mikewolfli@163.com)
// SPDX-License-Identifier: MIT

//! Core widget registration — registers every built-in widget kind in the factory.
//!
//! This module defines `register_core_widgets` which is called from
//! [`WidgetFactory::new_with_defaults`] to populate the factory with every
//! built-in widget kind.
//!
//! The count is deliberately not written down here: it is the number of
//! `self.register(..)` calls below, which a comment cannot keep true as kinds are
//! added. `every_widgetkind_variant_is_registered_or_declared_child_only` in the
//! tests is the thing that keeps this file complete, and it reads the real counts.

// Bring constructors, capability functions, and WidgetFactory into scope.
use super::*;

impl WidgetFactory {
    /// Registers every core widget kind with its constructor and capability.
    pub(crate) fn register_core_widgets(&mut self) {
        // ── Core widgets (always available) ─────────────────────────
        self.register(button_capability(), create_button);
        self.register(label_capability(), create_label);
        self.register(check_box_capability(), create_check_box);
        self.register(radio_button_capability(), create_radio_button);
        self.register(slider_capability(), create_slider);
        self.register(progress_bar_capability(), create_progress_bar);
        self.register(scroll_bar_capability(), create_scroll_bar);
        self.register(list_box_capability(), create_list_box);
        self.register(spin_box_capability(), create_spin_box);
        self.register(combo_box_capability(), create_combo_box);
        self.register(window_capability(), create_window);
        self.register(group_box_capability(), create_group_box);
        self.register(line_edit_capability(), create_line_edit);
        self.register(arc_capability(), create_arc);
        self.register(spinner_capability(), create_spinner);
        self.register(roller_capability(), create_roller);
        self.register(dropdown_capability(), create_dropdown);
        self.register(text_area_capability(), create_textarea);
        self.register(keyboard_capability(), create_keyboard);
        self.register(switch_capability(), create_switch);
        self.register(cupertino_switch_capability(), create_cupertino_switch);
        self.register(line_capability(), create_line);
        self.register(meter_capability(), create_meter);
        self.register(radar_chart_capability(), create_radar_chart);
        self.register(heatmap_capability(), create_heatmap);
        self.register(kanban_board_capability(), create_kanban_board);
        self.register(cascader_capability(), create_cascader);
        self.register(query_builder_capability(), create_query_builder);
        self.register(emoji_picker_capability(), create_emoji_picker);
        self.register(mention_capability(), create_mention);
        self.register(mini_chart_capability(), create_mini_chart);
        self.register(image_view_capability(), create_image_view);
        self.register(mini_canvas_capability(), create_mini_canvas);

        // ── Non-core widgets ────────────────────────────────────────
        //
        // Gated on `full_widgets`, not `not(mini)`: every constructor in this
        // block lives in a module that is itself profile-gated, so an
        // embedded build must skip the whole block. Gating it on `not(mini)`
        // alone left `embedded` referring to constructors that do not exist.
        #[cfg(full_widgets)]
        {
            self.register(toggle_button_capability(), create_toggle_button);
            self.register(menu_capability(), create_menu);
            self.register(freeform_shape_capability(), create_freeform_shape);
            self.register(splitter_capability(), create_splitter);
            self.register(frame_capability(), create_frame);
            self.register(lcd_number_capability(), create_lcd_number);
            self.register(command_link_capability(), create_command_link);
            self.register(font_combo_box_capability(), create_font_combo_box);
            self.register(action_capability(), create_action);
            self.register(panel_capability(), create_panel);
            self.register(tool_box_capability(), create_tool_box);
            self.register(table_capability(), create_table);
            self.register(list_view_capability(), create_list_view);
            self.register(tree_view_capability(), create_tree_view);
            self.register(table_widget_capability(), create_table_widget);
            self.register(data_grid_capability(), create_data_grid);
            self.register(tree_table_capability(), create_tree_table);
            self.register(virtual_table_capability(), create_virtual_table);
            self.register(virtual_list_capability(), create_virtual_list);
            self.register(data_view_capability(), create_data_view);
            self.register(menu_bar_capability(), create_menu_bar);
            self.register(tool_bar_capability(), create_tool_bar);

            // ── Dialog widgets ────────────────────────────────────────
            self.register(message_box_capability(), create_message_box);
            self.register(file_dialog_capability(), create_file_dialog);
            self.register(font_dialog_capability(), create_font_dialog);
            self.register(input_dialog_capability(), create_input_dialog);
        }

        // ── Advanced widgets (not available in embedded or mini) ────
        #[cfg(full_widgets)]
        {
            self.register(dial_capability(), create_dial);
            self.register(tab_bar_capability(), create_tab_bar);
            self.register(calendar_capability(), create_calendar);
            self.register(date_edit_capability(), create_date_edit);
            self.register(time_edit_capability(), create_time_edit);
            self.register(ribbon_bar_capability(), create_ribbon_bar);
            self.register(color_picker_capability(), create_color_picker);
            self.register(color_dialog_capability(), create_color_dialog);
            self.register(code_editor_capability(), create_code_editor);
            self.register(gantt_widget_capability(), create_gantt_widget);
            self.register(terminal_view_capability(), create_terminal_view);
            self.register(snackbar_capability(), create_snackbar);
            self.register(map_view_capability(), create_map_view);
            self.register(media_player_capability(), create_media_player);
            self.register(breadcrumb_capability(), create_breadcrumb);
            self.register(signature_pad_capability(), create_signature_pad);
            self.register(drop_zone_capability(), create_drop_zone);
            self.register(split_button_capability(), create_split_button);
            self.register(segmented_control_capability(), create_segmented_control);
            self.register(chip_capability(), create_chip);
            self.register(grid_capability(), create_grid);
            // Controls that existed with a complete implementation but were never
            // registered. Without these rows the factory could not construct them by
            // name, so they were unreachable from declarative JSON and invisible to
            // CSS selectors even though a Rust caller could build them directly.
            self.register(timeline_widget_capability(), create_timeline_widget);
            self.register(command_palette_capability(), create_command_palette);
            self.register(notification_center_capability(), create_notification_center);
            self.register(diff_viewer_capability(), create_diff_viewer);
            self.register(markdown_editor_capability(), create_markdown_editor);
            self.register(toast_stack_capability(), create_toast_stack);
            // `grid_table` was found by the registration-fidelity gate rather than by
            // hand: `GridTableWidget` is a complete virtualised table that had no
            // capability at all.
            self.register(grid_table_capability(), create_grid_table);
            self.register(number_picker_capability(), create_number_picker);
            self.register(otp_input_capability(), create_otp_input);
            self.register(banner_capability(), create_banner);
            self.register(pagination_capability(), create_pagination);
            self.register(toast_capability(), create_toast);
            self.register(splash_screen_capability(), create_splash_screen);
            self.register(progress_dialog_capability(), create_progress_dialog);
            self.register(popup_window_capability(), create_popup_window);
            self.register(dialog_capability(), create_dialog);

            // ── Container widgets ─────────────────────────────────────
            self.register(scroll_area_capability(), create_scroll_area);
            self.register(tab_widget_capability(), create_tab_widget);
            self.register(stacked_widget_capability(), create_stacked_widget);
            self.register(collapsible_pane_capability(), create_collapsible_pane);
            self.register(dock_widget_capability(), create_dock_widget);
            self.register(mdi_area_capability(), create_mdi_area);

            // ── Text widget ───────────────────────────────────────────
            self.register(text_edit_capability(), create_text_edit);

            // ── Web widget ────────────────────────────────────────────
            self.register(web_view_capability(), create_web_view);

            // ── Advanced widgets ──────────────────────────────────────
            self.register(pie_menu_capability(), create_pie_menu);
            self.register(date_time_edit_capability(), create_date_time_edit);

            // ── Group A widgets (non-mini) ──────────────────────────────
            self.register(canvas_capability(), create_canvas);
            self.register(chart_capability(), create_chart);
            self.register(search_box_capability(), create_search_box);
            self.register(badge_capability(), create_badge);
            self.register(skeleton_loader_capability(), create_skeleton_loader);
            self.register(fab_capability(), create_fab);
            self.register(bottom_sheet_capability(), create_bottom_sheet);
            self.register(bottom_navigation_bar_capability(), create_bottom_navigation_bar);
            self.register(navigation_drawer_capability(), create_navigation_drawer);
            self.register(app_bar_capability(), create_app_bar);
            self.register(mobile_date_picker_capability(), create_mobile_date_picker);
            self.register(divider_capability(), create_divider);
            self.register(stepper_capability(), create_stepper);
            self.register(rating_capability(), create_rating);
            self.register(avatar_capability(), create_avatar);
            self.register(empty_state_capability(), create_empty_state);
            self.register(color_history_capability(), create_color_history);
            self.register(color_well_capability(), create_color_well);
            self.register(tag_input_capability(), create_tag_input);
            self.register(ime_preedit_capability(), create_ime_preedit);
            self.register(inplace_editor_capability(), create_inplace_editor);
            self.register(qr_code_capability(), create_qr_code);
            self.register(masonry_layout_capability(), create_masonry_layout);
            self.register(material_snackbar_capability(), create_material_snackbar);
            self.register(adaptive_scaffold_capability(), create_adaptive_scaffold);
            self.register(wizard_dialog_capability(), create_wizard_dialog);
            self.register(safe_area_capability(), create_safe_area);
            self.register(cupertino_alert_dialog_capability(), create_cupertino_alert_dialog);
            self.register(cupertino_slider_capability(), create_cupertino_slider);
            self.register(tooltip_capability(), create_tooltip);
            self.register(segmented_button_capability(), create_segmented_button);
            self.register(navigation_stack_capability(), create_navigation_stack);
            self.register(progress_circle_capability(), create_progress_circle);
            self.register(icon_capability(), create_icon);
            self.register(dropdown_menu_capability(), create_dropdown_menu);
            self.register(masked_edit_capability(), create_masked_edit);
            self.register(menu_button_capability(), create_menu_button);
            self.register(popover_capability(), create_popover);
            self.register(auto_complete_edit_capability(), create_auto_complete_edit);
            self.register(multi_select_combo_box_capability(), create_multi_select_combo_box);
            self.register(range_slider_capability(), create_range_slider);
            self.register(floating_label_capability(), create_floating_label);
            self.register(font_preview_capability(), create_font_preview);
            self.register(cupertino_navigation_bar_capability(), create_cupertino_navigation_bar);
            self.register(
                cupertino_segmented_control_capability(),
                create_cupertino_segmented_control,
            );
            self.register(refresh_control_capability(), create_refresh_control);
            self.register(modal_bottom_sheet_capability(), create_modal_bottom_sheet);
            self.register(find_replace_dialog_capability(), create_find_replace_dialog);
            self.register(properties_panel_capability(), create_properties_panel);
            self.register(cupertino_date_picker_capability(), create_cupertino_date_picker);
            self.register(editable_combo_box_capability(), create_editable_combo_box);
            self.register(date_range_picker_capability(), create_date_range_picker);

            // ── New widgets ────────────────────────────────────────────
            self.register(rich_edit_capability(), create_rich_edit);
            self.register(carousel_capability(), create_carousel);
            self.register(material_navigation_rail_capability(), create_material_navigation_rail);
            self.register(tab_view_capability(), create_tab_view);
            self.register(search_bar_capability(), create_search_bar);
            self.register(shortcut_editor_capability(), create_shortcut_editor);
            self.register(swipe_to_dismiss_capability(), create_swipe_to_dismiss);
            self.register(line_chart_capability(), create_line_chart);
            self.register(sparkline_capability(), create_sparkline);
            self.register(bar_chart_capability(), create_bar_chart);
            self.register(candlestick_chart_capability(), create_candlestick_chart);
            self.register(volume_chart_capability(), create_volume_chart);
            self.register(depth_chart_capability(), create_depth_chart);
            self.register(order_book_capability(), create_order_book);
            self.register(quote_board_capability(), create_quote_board);
            self.register(indicator_chart_capability(), create_indicator_chart);
            self.register(pie_chart_capability(), create_pie_chart);
            self.register(animated_image_capability(), create_animated_image);
            self.register(hero_animation_capability(), create_hero_animation);
            self.register(bezier_curve_editor_capability(), create_bezier_curve_editor);
            self.register(lottie_widget_capability(), create_lottie_widget);
            self.register(rive_widget_capability(), create_rive_widget);
            self.register(video_player_capability(), create_video_player);
            self.register(image_gallery_capability(), create_image_gallery);
            self.register(audio_visualizer_capability(), create_audio_visualizer);
            self.register(camera_preview_capability(), create_camera_preview);
            self.register(barcode_scanner_capability(), create_barcode_scanner);
            self.register(tool_button_capability(), create_tool_button);
            self.register(status_bar_capability(), create_status_bar);
            self.register(property_grid_capability(), create_property_grid);
        }
    }
}

#[cfg(all(test, full_widgets))]
mod tests {
    use crate::widget::kind::WidgetKind;
    use crate::widget::WidgetFactory;

    /// Every `WidgetKind` variant is either registered or declared child-only (rule #27).
    ///
    /// # Why this test exists
    ///
    /// The module documentation above promises exactly this test by name and describes its
    /// criterion — but the test did not exist, so `WidgetKind`→module auditability had **no
    /// mechanical gate at all**. A variant added to the enum with neither a `self.register(..)` here
    /// nor an alias row in `capability::alias_factory_name` would fall through to an empty name and
    /// lose its theme role silently, which is the class of defect the aliases below were added to
    /// fix.
    ///
    /// # How it checks without an `ALL` array
    ///
    /// `WidgetKind` has no enumerable `ALL` (the variants are `cfg`-gated per profile), so this
    /// does not iterate the enum. It checks the two halves the promise names:
    ///
    /// 1. **Registered** — every capability the factory holds has a canonical name that a variant
    ///    can resolve to, so the registry and the name table agree.
    /// 2. **Declared child-only** — the variants that legitimately have no capability row are
    ///    exactly the ones the alias table covers, and each resolves to a name the factory knows.
    #[test]
    fn every_widgetkind_variant_is_registered_or_declared_child_only() {
        let factory = WidgetFactory::new_with_defaults();

        // 1. Each registered capability's kind resolves to a name the factory knows. This is the
        //    registry -> name direction: a kind the lookup cannot name would be themed as nothing.
        //    The resolution need not be the capability's *own* canonical name — several
        //    capabilities share one kind (`panel` is kinded `GroupBox`), and the lookup answers with
        //    the one whose kind matches first — but it must be a spelling the factory answers to.
        let mut registered = 0usize;
        for capability in factory.capabilities() {
            let resolved = crate::widget::capability::factory_name_for_kind(capability.kind);
            let name = resolved.unwrap_or_else(|| {
                panic!(
                    "`{}` is registered for {:?}, but the name lookup answers None, so its theme \
                     role would be unresolvable",
                    capability.canonical_name, capability.kind
                )
            });
            assert!(
                factory.capability(name).is_some(),
                "{:?} resolves to `{name}`, which is not a name the factory knows",
                capability.kind
            );
            registered += 1;
        }
        assert!(
            registered > 100,
            "only {registered} capabilities are registered, so this test is not covering the \
             widget set it exists to audit"
        );

        // 2. The declared child-only variants. Each has a real constructor or is created only as
        //    a child, publishes no capability row of its own, and is named through the alias table
        //    so the theme layer can still classify it. `factory_name` is whether the *alias* is
        //    itself a registered factory name: `panel` and `dock_widget` are, while `menu_item` is
        //    a theme-classification name only (a row is built by its owning `Menu`, never by a
        //    factory call on its own name).
        let child_only = [
            (WidgetKind::Panel, "panel", true),
            (WidgetKind::DockPanel, "dock_widget", true),
            (WidgetKind::MenuItem, "menu_item", false),
            (WidgetKind::ContextMenu, "menu", true),
            (WidgetKind::CheckListBox, "list_box", true),
            (WidgetKind::DoubleSpinBox, "spin_box", true),
            (WidgetKind::Wizard, "wizard_dialog", true),
            (WidgetKind::DirectoryDialog, "file_dialog", true),
            (WidgetKind::ActivityIndicator, "progress_bar", true),
            (WidgetKind::ColumnView, "tree_view", true),
            (WidgetKind::UndoView, "list_view", true),
        ];
        for (kind, expected, is_factory_name) in child_only {
            assert_eq!(
                crate::widget::capability::factory_name_for_kind(kind),
                Some(expected),
                "{kind:?} is declared child-only, so it must resolve through the alias table"
            );
            if is_factory_name {
                // A name the factory would reject is as broken as no name, so the resolution has to
                // be a spelling the registry actually answers to.
                assert!(
                    factory.capability(expected).is_some(),
                    "the alias `{expected}` for {kind:?} is not a name the factory knows"
                );
            }
        }
    }
}