From d4ea54a78a11563be9cc8f59d57a215d7120ccba Mon Sep 17 00:00:00 2001 From: Liu Date: Sun, 19 Mar 2023 22:27:01 +0800 Subject: [PATCH] refactor: remove some dependencies of libui --- examples/hello/src/main.c | 6 +- include/LCUI.h | 10 +- include/LCUI/ui.h | 979 ----------------- include/LCUI/ui/cursor.h | 21 - include/LCUI/ui/server.h | 20 - include/LCUI/ui/widgets/button.h | 44 - include/LCUI/ui/widgets/canvas.h | 80 -- include/LCUI/ui/widgets/scrollbar.h | 60 -- include/LCUI/ui/widgets/textedit.h | 82 -- include/LCUI/worker.h | 2 + lib/ctest/include/ctest.h | 2 +- lib/pandagl/xmake.lua | 6 +- lib/ui-builder/include/builder.h | 55 - .../ui-builder/include/ui_builder.h | 2 +- lib/ui-builder/src/builder.c | 6 +- .../include/{cursor.h => ui_cursor.h} | 2 +- lib/ui-cursor/src/cursor.c | 2 +- .../include/{server.h => ui_server.h} | 2 +- lib/ui-server/src/server.c | 4 +- lib/ui-widgets/include/anchor.h | 43 - lib/ui-widgets/include/textcaret.h | 46 - lib/ui-widgets/include/textview.h | 51 - lib/ui-widgets/include/ui_widgets.h | 8 + .../ui-widgets/include/ui_widgets}/anchor.h | 3 +- .../include/{ => ui_widgets}/button.h | 3 + .../include/{ => ui_widgets}/canvas.h | 2 + .../include/{ => ui_widgets}/scrollbar.h | 3 + .../include/ui_widgets}/textcaret.h | 2 +- .../include/{ => ui_widgets}/textedit.h | 2 +- .../ui-widgets/include/ui_widgets}/textview.h | 2 +- lib/ui-widgets/src/anchor.c | 6 +- lib/ui-widgets/src/button.c | 6 +- lib/ui-widgets/src/canvas.c | 4 +- lib/ui-widgets/src/scrollbar.c | 6 +- lib/ui-widgets/src/textcaret.c | 9 +- lib/ui-widgets/src/textedit.c | 6 +- lib/ui-widgets/src/textstyle.c | 2 +- .../src/{internal.h => textstyle.h} | 2 +- lib/ui-widgets/src/textview.c | 4 +- lib/ui/include/ui.h | 985 +----------------- lib/ui/include/ui/base.h | 141 +++ lib/ui/include/ui/common.h | 44 + lib/ui/include/ui/css.h | 12 + lib/ui/include/ui/events.h | 144 +++ lib/ui/include/ui/hash.h | 18 + lib/ui/include/ui/image.h | 48 + lib/ui/include/ui/logger.h | 16 + lib/ui/include/ui/metrics.h | 44 + lib/ui/include/ui/mutation_observer.h | 70 ++ lib/ui/include/ui/prototype.h | 23 + lib/ui/include/ui/rect.h | 45 + lib/ui/include/ui/style.h | 40 + lib/ui/include/ui/text_style.h | 42 + lib/ui/include/ui/types.h | 435 ++++++++ lib/ui/src/config.h.in | 5 + lib/ui/src/internal.h | 230 ---- lib/ui/src/ui.c | 12 +- lib/ui/src/ui_block_layout.c | 9 +- lib/ui/src/ui_block_layout.h | 1 + lib/ui/src/ui_css.c | 6 +- lib/ui/src/ui_css.h | 3 + lib/ui/src/ui_debug.c | 6 +- lib/ui/src/ui_diff.c | 22 +- lib/ui/src/ui_diff.h | 38 + lib/ui/src/ui_events.c | 110 +- lib/ui/src/ui_events.h | 8 + lib/ui/src/ui_flexbox_layout.c | 15 +- lib/ui/src/ui_flexbox_layout.h | 1 + lib/ui/src/{ui_image_loader.c => ui_image.c} | 82 +- lib/ui/src/ui_image.h | 2 + lib/ui/src/ui_logger.c | 2 +- lib/ui/src/ui_metrics.c | 3 +- lib/ui/src/ui_metrics.h | 2 + lib/ui/src/ui_mutation_oberver.c | 5 +- lib/ui/src/ui_mutation_observer.h | 7 + lib/ui/src/ui_rect.c | 30 +- lib/ui/src/ui_renderer.c | 74 +- lib/ui/src/ui_root.c | 5 +- lib/ui/src/ui_root.h | 3 + lib/ui/src/ui_text_style.c | 22 +- lib/ui/src/ui_trash.c | 6 +- lib/ui/src/ui_trash.h | 3 + lib/ui/src/ui_tree.c | 26 +- lib/ui/src/ui_updater.c | 71 +- lib/ui/src/ui_updater.h | 2 + lib/ui/src/ui_widget.c | 25 +- lib/ui/src/ui_widget.h | 2 + lib/ui/src/ui_widget_attributes.c | 12 +- lib/ui/src/ui_widget_attributes.h | 2 + lib/ui/src/ui_widget_background.c | 4 +- lib/ui/src/ui_widget_background.h | 3 + lib/ui/src/ui_widget_border.c | 4 +- lib/ui/src/ui_widget_border.h | 5 + lib/ui/src/ui_widget_box.c | 10 +- lib/ui/src/ui_widget_box.h | 5 + lib/ui/src/ui_widget_box_shadow.c | 4 +- lib/ui/src/ui_widget_box_shadow.h | 3 + lib/ui/src/ui_widget_classes.c | 12 +- lib/ui/src/ui_widget_classes.h | 2 + lib/ui/src/ui_widget_hash.c | 6 +- lib/ui/src/ui_widget_helper.c | 8 +- lib/ui/src/ui_widget_id.c | 16 +- lib/ui/src/ui_widget_id.h | 4 + lib/ui/src/ui_widget_layout.c | 13 +- lib/ui/src/ui_widget_observer.c | 15 +- lib/ui/src/ui_widget_observer.h | 5 + lib/ui/src/ui_widget_prototype.c | 22 +- lib/ui/src/ui_widget_prototype.h | 4 + lib/ui/src/ui_widget_status.c | 14 +- lib/ui/src/ui_widget_status.h | 2 + lib/ui/src/ui_widget_style.c | 18 +- lib/ui/src/ui_widget_style.h | 99 ++ lib/ui/xmake.lua | 12 +- src/config.h.in | 4 - src/lcui.c | 2 +- src/lcui_settings.c | 4 +- src/lcui_ui.c | 20 +- tests/cases/test_block_layout.c | 4 +- tests/cases/test_clipboard.c | 2 +- tests/cases/test_flex_layout.c | 4 +- tests/cases/test_font_load.c | 2 +- tests/cases/test_mainloop.c | 4 +- tests/cases/test_scrollbar.c | 8 +- tests/cases/test_textedit.c | 4 +- tests/cases/test_textview_resize.c | 2 +- tests/cases/test_widget_event.c | 2 +- tests/cases/test_widget_opacity.c | 5 - tests/cases/test_widget_rect.c | 2 +- tests/cases/test_xml_parser.c | 4 +- tests/helloworld_uwp/App.cpp | 8 +- tests/test_border.c | 2 +- tests/test_box_shadow.c | 2 +- tests/test_image_scaling_bench.c | 4 +- tests/test_render.c | 2 +- tests/test_scaling_support.c | 2 +- tests/test_widget.c | 4 +- tests/test_widget_render.c | 2 +- xmake.lua | 10 +- 138 files changed, 1869 insertions(+), 3084 deletions(-) delete mode 100644 include/LCUI/ui.h delete mode 100644 include/LCUI/ui/cursor.h delete mode 100644 include/LCUI/ui/server.h delete mode 100644 include/LCUI/ui/widgets/button.h delete mode 100644 include/LCUI/ui/widgets/canvas.h delete mode 100644 include/LCUI/ui/widgets/scrollbar.h delete mode 100644 include/LCUI/ui/widgets/textedit.h delete mode 100644 lib/ui-builder/include/builder.h rename include/LCUI/ui/builder.h => lib/ui-builder/include/ui_builder.h (99%) rename lib/ui-cursor/include/{cursor.h => ui_cursor.h} (96%) rename lib/ui-server/include/{server.h => ui_server.h} (97%) delete mode 100644 lib/ui-widgets/include/anchor.h delete mode 100644 lib/ui-widgets/include/textcaret.h delete mode 100644 lib/ui-widgets/include/textview.h create mode 100644 lib/ui-widgets/include/ui_widgets.h rename {include/LCUI/ui/widgets => lib/ui-widgets/include/ui_widgets}/anchor.h (98%) rename lib/ui-widgets/include/{ => ui_widgets}/button.h (98%) rename lib/ui-widgets/include/{ => ui_widgets}/canvas.h (98%) rename lib/ui-widgets/include/{ => ui_widgets}/scrollbar.h (98%) rename {include/LCUI/ui/widgets => lib/ui-widgets/include/ui_widgets}/textcaret.h (98%) rename lib/ui-widgets/include/{ => ui_widgets}/textedit.h (99%) rename {include/LCUI/ui/widgets => lib/ui-widgets/include/ui_widgets}/textview.h (99%) rename lib/ui-widgets/src/{internal.h => textstyle.h} (83%) create mode 100644 lib/ui/include/ui/base.h create mode 100644 lib/ui/include/ui/common.h create mode 100644 lib/ui/include/ui/css.h create mode 100644 lib/ui/include/ui/events.h create mode 100644 lib/ui/include/ui/hash.h create mode 100644 lib/ui/include/ui/image.h create mode 100644 lib/ui/include/ui/logger.h create mode 100644 lib/ui/include/ui/metrics.h create mode 100644 lib/ui/include/ui/mutation_observer.h create mode 100644 lib/ui/include/ui/prototype.h create mode 100644 lib/ui/include/ui/rect.h create mode 100644 lib/ui/include/ui/style.h create mode 100644 lib/ui/include/ui/text_style.h create mode 100644 lib/ui/include/ui/types.h create mode 100644 lib/ui/src/config.h.in delete mode 100644 lib/ui/src/internal.h create mode 100644 lib/ui/src/ui_block_layout.h create mode 100644 lib/ui/src/ui_css.h create mode 100644 lib/ui/src/ui_diff.h create mode 100644 lib/ui/src/ui_events.h create mode 100644 lib/ui/src/ui_flexbox_layout.h rename lib/ui/src/{ui_image_loader.c => ui_image.c} (70%) create mode 100644 lib/ui/src/ui_image.h create mode 100644 lib/ui/src/ui_metrics.h create mode 100644 lib/ui/src/ui_mutation_observer.h create mode 100644 lib/ui/src/ui_root.h create mode 100644 lib/ui/src/ui_trash.h create mode 100644 lib/ui/src/ui_updater.h create mode 100644 lib/ui/src/ui_widget.h create mode 100644 lib/ui/src/ui_widget_attributes.h create mode 100644 lib/ui/src/ui_widget_background.h create mode 100644 lib/ui/src/ui_widget_border.h create mode 100644 lib/ui/src/ui_widget_box.h create mode 100644 lib/ui/src/ui_widget_box_shadow.h create mode 100644 lib/ui/src/ui_widget_classes.h create mode 100644 lib/ui/src/ui_widget_id.h create mode 100644 lib/ui/src/ui_widget_observer.h create mode 100644 lib/ui/src/ui_widget_prototype.h create mode 100644 lib/ui/src/ui_widget_status.h create mode 100644 lib/ui/src/ui_widget_style.h diff --git a/examples/hello/src/main.c b/examples/hello/src/main.c index a21cabb61..7031243ab 100644 --- a/examples/hello/src/main.c +++ b/examples/hello/src/main.c @@ -1,8 +1,8 @@ #include #include -#include -#include -#include +#include +#include +#include static void on_btn_click(ui_widget_t* self, ui_event_t* e, void *arg) { diff --git a/include/LCUI.h b/include/LCUI.h index a92cd48a6..52d31b6d1 100644 --- a/include/LCUI.h +++ b/include/LCUI.h @@ -1,7 +1,11 @@ -#include #include #include -#include -#include +#include +#include +#include +#include +#include +#include #include +#include #include diff --git a/include/LCUI/ui.h b/include/LCUI/ui.h deleted file mode 100644 index 7411413aa..000000000 --- a/include/LCUI/ui.h +++ /dev/null @@ -1,979 +0,0 @@ -#ifndef LIB_UI_INCLUDE_UI_H -#define LIB_UI_INCLUDE_UI_H - -#include -#include -#include -#include -#include - -LCUI_BEGIN_HEADER - -// Types - -typedef struct ui_rect_t { - float x, y, width, height; -} ui_rect_t; - -typedef struct ui_area_t { - float left, top, right, bottom; -} ui_area_t; - -typedef css_metrics_t ui_metrics_t; - -typedef enum ui_density_Level_t { - UI_DENSITY_LEVEL_SMALL, - UI_DENSITY_LEVEL_NORMAL, - UI_DENSITY_LEVEL_LARGE, - UI_DENSITY_LEVEL_BIG -} ui_density_Level_t; - -typedef enum ui_sizing_rule_t { - UI_SIZING_RULE_NONE, - UI_SIZING_RULE_FIXED, - UI_SIZING_RULE_FILL, - UI_SIZING_RULE_PERCENT, - UI_SIZING_RULE_FIT_CONTENT -} ui_sizing_rule_t; - -typedef enum ui_layout_rule_t { - UI_LAYOUT_RULE_AUTO, - UI_LAYOUT_RULE_MAX_CONTENT, - UI_LAYOUT_RULE_FIXED_WIDTH = 0b11, - UI_LAYOUT_RULE_FIXED_HEIGHT = 0b101, - UI_LAYOUT_RULE_FIXED = 0b111 -} ui_layout_rule_t; - -typedef enum ui_widget_state_t { - UI_WIDGET_STATE_CREATED = 0, - UI_WIDGET_STATE_UPDATED, - UI_WIDGET_STATE_LAYOUTED, - UI_WIDGET_STATE_READY, - UI_WIDGET_STATE_NORMAL, - UI_WIDGET_STATE_DELETED, -} ui_widget_state_t; - -typedef enum ui_box_type_t { - UI_BOX_TYPE_CONTENT_BOX, - UI_BOX_TYPE_PADDING_BOX, - UI_BOX_TYPE_BORDER_BOX, - UI_BOX_TYPE_GRAPH_BOX -} ui_box_type_t; - -typedef enum ui_dirty_rect_type_t { - UI_DIRTY_RECT_TYPE_NONE, - UI_DIRTY_RECT_TYPE_CUSTOM, - UI_DIRTY_RECT_TYPE_PADDING_BOX, - UI_DIRTY_RECT_TYPE_BORDER_BOX, - UI_DIRTY_RECT_TYPE_CANVAS_BOX -} ui_dirty_rect_type_t; - -typedef struct ui_border_style_t_ { - struct { - int style; - float width; - pd_color_t color; - } top, right, bottom, left; - float top_left_radius; - float top_right_radius; - float bottom_left_radius; - float bottom_right_radius; -} ui_border_style_t; - -typedef struct ui_widget_attribute_t_ { - char *name; - struct { - int type; - void (*destructor)(void *); - union { - char *string; - void *data; - }; - } value; -} ui_widget_attribute_t; - -typedef struct ui_widget_actual_style_t_ { - float x, y; - pd_rect_t canvas_box; - pd_rect_t border_box; - pd_rect_t padding_box; - pd_rect_t content_box; -} ui_widget_actual_style_t; - -typedef enum ui_task_type_t { - UI_TASK_REFRESH_STYLE, - UI_TASK_UPDATE_STYLE, - UI_TASK_REFLOW, - UI_TASK_USER, - UI_TASK_TOTAL_NUM -} ui_task_type_t; - -typedef struct ui_event_listener_t ui_event_listener_t; -typedef struct ui_widget_t ui_widget_t; -typedef list_t ui_widget_listeners_t; - -typedef void (*ui_widget_function_t)(ui_widget_t *); -typedef void (*ui_widget_task_handler_t)(ui_widget_t *, int); -typedef void (*ui_widget_size_getter_t)(ui_widget_t *, float *, float *, - ui_layout_rule_t); -typedef void (*ui_widget_size_setter_t)(ui_widget_t *, float, float); -typedef void (*ui_widget_attr_setter_t)(ui_widget_t *, const char *, - const char *); -typedef void (*ui_widget_text_setter_t)(ui_widget_t *, const char *); -typedef void (*ui_widget_painter_t)(ui_widget_t *, pd_context_t *, - ui_widget_actual_style_t *); -typedef struct ui_widget_prototype_t ui_widget_prototype_t; - -typedef struct ui_widget_rules_t { - /** - * Suspend update if the current widget is not visible or is - * completely covered by other widgets - */ - LCUI_BOOL only_on_visible; - - /** - * First update the children in the visible area - * If your widget has a lot of children and you want to see the - * children who are currently seeing the priority update, we recommend - * enabling this rule. - */ - LCUI_BOOL first_update_visible_children; - - /** - * Cache the stylesheets of children to improve the query speed of - * the stylesheet. - * If this rule is enabled, we recommend that you manually call - * ui_widget_generate_hash() to generate a hash value for the children - * of the widget. - */ - LCUI_BOOL cache_children_style; - - /** Refresh the style of all child widgets if the status has changed */ - LCUI_BOOL ignore_status_change; - - /** Refresh the style of all child widgets if the classes has changed */ - LCUI_BOOL ignore_classes_change; - - /** - * Maximum number of children updated at each update - * values: - * 0 - Update all children at once - * -1 - Automatically calculates the appropriate maximum number - * N - Custom maximum number - */ - int max_update_children_count; - - /** Limit the number of children rendered */ - unsigned max_render_children_count; - - /** A callback function on update progress */ - void (*on_update_progress)(ui_widget_t *, size_t); -} ui_widget_rules_t; - -typedef struct ui_widget_update_t { - /** Should update for self? */ - LCUI_BOOL for_self; - - /** Should update for children? */ - LCUI_BOOL for_children; - - /** Should skip the property sync of bound surface? */ - LCUI_BOOL skip_surface_props_sync; - - /** States of tasks */ - LCUI_BOOL states[UI_TASK_TOTAL_NUM]; -} ui_widget_update_t; - -typedef struct ui_profile_t { - long time; - size_t update_count; - size_t refresh_count; - size_t layout_count; - size_t user_task_count; - size_t destroy_count; - size_t destroy_time; -} ui_profile_t; - -struct ui_widget_prototype_t { - char *name; - ui_widget_function_t init; - ui_widget_function_t refresh; - ui_widget_function_t destroy; - ui_widget_function_t update; - ui_widget_task_handler_t runtask; - ui_widget_attr_setter_t setattr; - ui_widget_text_setter_t settext; - ui_widget_size_getter_t autosize; - ui_widget_size_setter_t resize; - ui_widget_painter_t paint; - ui_widget_prototype_t *proto; -}; - -typedef struct ui_widget_data_entry_t { - void *data; - ui_widget_prototype_t *proto; -} ui_widget_data_entry_t; - -typedef struct ui_widget_data_t { - unsigned length; - ui_widget_data_entry_t *list; -} ui_widget_data_t; - -// Event begin - -typedef enum ui_event_type_t { - UI_EVENT_NONE, - UI_EVENT_LINK, - UI_EVENT_UNLINK, - UI_EVENT_READY, - UI_EVENT_DESTROY, - UI_EVENT_FOCUS, - UI_EVENT_BLUR, - UI_EVENT_AFTERLAYOUT, - UI_EVENT_KEYDOWN, - UI_EVENT_KEYUP, - UI_EVENT_KEYPRESS, - UI_EVENT_TEXTINPUT, - - UI_EVENT_MOUSEOVER, - UI_EVENT_MOUSEMOVE, - UI_EVENT_MOUSEOUT, - UI_EVENT_MOUSEDOWN, - UI_EVENT_MOUSEUP, - UI_EVENT_WHEEL, - UI_EVENT_CLICK, - UI_EVENT_DBLCLICK, - UI_EVENT_TOUCH, - UI_EVENT_TOUCHDOWN, - UI_EVENT_TOUCHUP, - UI_EVENT_TOUCHMOVE, - UI_EVENT_PASTE, - - UI_EVENT_FONT_FACE_LOAD, - UI_EVENT_USER -} ui_event_type_t; - -/** - * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent - */ -typedef struct ui_keyboard_event_t { - int code; - LCUI_BOOL alt_key; - LCUI_BOOL ctrl_key; - LCUI_BOOL shift_key; - LCUI_BOOL meta_key; - LCUI_BOOL is_composing; -} ui_keyboard_event_t; - -typedef struct ui_touch_point_t { - float x; - float y; - int id; - int state; - LCUI_BOOL is_primary; -} ui_touch_point_t; - -typedef struct ui_touch_event_t { - unsigned n_points; - ui_touch_point_t *points; -} ui_touch_event_t; - -typedef struct ui_paint_event_t { - pd_rect_t rect; -} ui_paint_event_t; - -typedef struct ui_textinput_event_t { - wchar_t *text; - size_t length; -} ui_textinput_event_t; - -/** - * @see https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent - */ -typedef struct ui_mouse_event_t { - float x; - float y; - int button; -} ui_mouse_event_t; - -typedef enum ui_wheel_delta_mode_t { - UI_WHEEL_DELTA_PIXEL = 0, - UI_WHEEL_DELTA_LINE, - UI_WHEEL_DELTA_PAGE -} ui_wheel_delta_mode_t; - -/** - * @see https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent - */ -typedef struct ui_wheel_event_t { - int delta_x; - int delta_y; - int delta_z; - int delta_mode; -} ui_wheel_event_t; - -typedef struct ui_event_t ui_event_t; -typedef void (*ui_event_handler_t)(ui_widget_t *, ui_event_t *, void *); -typedef void (*ui_event_arg_destructor_t)(void *); - -struct ui_event_t { - uint32_t type; /**< 事件类型标识号 */ - void *data; /**< 附加数据 */ - ui_widget_t *target; /**< 触发事件的部件 */ - LCUI_BOOL cancel_bubble; /**< 是否取消事件冒泡 */ - union { - ui_mouse_event_t mouse; - ui_wheel_event_t wheel; - ui_keyboard_event_t key; - ui_touch_event_t touch; - ui_textinput_event_t text; - }; -}; - -// Event end - -// MutationObserver begin - -typedef list_t ui_mutation_list_t; -typedef struct ui_mutation_observer_t ui_mutation_observer_t; - -typedef enum ui_mutation_record_type_t { - UI_MUTATION_RECORD_TYPE_NONE, - UI_MUTATION_RECORD_TYPE_ATTRIBUTES, - UI_MUTATION_RECORD_TYPE_PROPERTIES, - UI_MUTATION_RECORD_TYPE_CHILD_LIST, -} ui_mutation_record_type_t; - -typedef struct ui_mutation_record_t { - ui_mutation_record_type_t type; - ui_widget_t *target; - list_t added_widgets; - list_t removed_widgets; - char *attribute_name; - char *property_name; -} ui_mutation_record_t; - -typedef void (*ui_mutation_observer_callback_t)(ui_mutation_list_t *, - ui_mutation_observer_t *, - void *); - -/** - * @see https://developer.mozilla.org/en-US/docs/Web/API/MutationObserverInit - */ -typedef struct ui_mutation_observer_init_t { - LCUI_BOOL child_list; - LCUI_BOOL subtree; - LCUI_BOOL properties; - LCUI_BOOL attributes; -} ui_mutation_observer_init_t; - -LCUI_API ui_mutation_record_t *ui_mutation_record_create( - ui_widget_t *widget, ui_mutation_record_type_t type); - -LCUI_API ui_mutation_record_t *ui_mutation_record_duplicate( - ui_mutation_record_t *source); - -LCUI_API void ui_mutation_record_destroy(ui_mutation_record_t *mutation); - -/** - * @see https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver - */ -LCUI_API ui_mutation_observer_t *ui_mutation_observer_create( - ui_mutation_observer_callback_t callback, void *callback_arg); - -LCUI_API int ui_mutation_observer_observe(ui_mutation_observer_t *observer, - ui_widget_t *w, - ui_mutation_observer_init_t options); - -LCUI_API void ui_mutation_observer_disconnect(ui_mutation_observer_t *observer); -LCUI_API void ui_mutation_observer_destroy(ui_mutation_observer_t *observer); -LCUI_API void ui_process_mutation_observers(void); -LCUI_API void ui_mutation_observer_add_record(ui_mutation_observer_t *observer, - ui_mutation_record_t *record); - -// MutationObserver end - -typedef struct ui_widget_extra_data_t { - ui_widget_listeners_t listeners; - list_t observer_connections; - ui_widget_rules_t rules; - size_t default_max_update_count; - size_t update_progress; - dict_t *style_cache; -} ui_widget_extra_data_t; - -struct ui_widget_t { - unsigned hash; - ui_widget_state_t state; - - char *id; - char *type; - int tab_index; - strlist_t classes; - strlist_t status; - wchar_t *title; - dict_t *attributes; - LCUI_BOOL disabled; - LCUI_BOOL event_blocked; - - /** - * Coordinates calculated by the layout system - * The position of the rectangular boxes is calculated based on it - */ - float layout_x, layout_y; - - /** - * A box’s “ideal” size in a given axis when given infinite available - * space. See more: https://drafts.csswg.org/css-sizing-3/#max-content - */ - float max_content_width, max_content_height; - - /** See more: - * https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model */ - ui_rect_t content_box; - ui_rect_t padding_box; - ui_rect_t border_box; - ui_rect_t canvas_box; - ui_rect_t outer_box; - - css_style_decl_t *custom_style; - const css_style_decl_t *matched_style; - css_computed_style_t specified_style; - css_computed_style_t computed_style; - - /** Some data bound to the prototype */ - ui_widget_data_t data; - ui_widget_extra_data_t *extra; - - /** - * Prototype chain - * It is used to implement the inheritance of widgets, - * Just like prototype chain in JavaScript - */ - const ui_widget_prototype_t *proto; - - ui_widget_update_t update; - - ui_rect_t dirty_rect; - ui_dirty_rect_type_t dirty_rect_type; - LCUI_BOOL has_child_dirty_rect; - - /** Parent widget */ - ui_widget_t *parent; - - /** List of child widgets */ - list_t children; - - /** - * List of child widgets in descending order by z-index - * @see - *https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context - **/ - list_t stacking_context; - - /** - * Position in the parent->children - * this == list_get(&this->parent->children, this.index) - */ - size_t index; - - /** - * Node in the parent->children - * &this->node == list_get_node(&this->parent->children, this.index) - */ - list_node_t node; - - /** Node in the parent->children_shoa */ - list_node_t node_show; -}; - -// Base - -LCUI_API void ui_init(void); -LCUI_API void ui_destroy(void); -LCUI_API int ui_dispatch_event(ui_event_t *e); -LCUI_API void ui_process_events(void); - -// Metrics - -LCUI_API ui_metrics_t ui_metrics; - -INLINE int ui_compute(float value) -{ - return (int)(ui_metrics.scale * value); -} - -INLINE void ui_compute_rect(pd_rect_t *actual_rect, const ui_rect_t *rect) -{ - actual_rect->x = ui_compute(rect->x); - actual_rect->y = ui_compute(rect->y); - actual_rect->width = ui_compute(rect->width); - actual_rect->height = ui_compute(rect->height); -} - -/** 设置密度 */ -LCUI_API void ui_set_density(float density); - -/** 设置缩放密度 */ -LCUI_API void ui_set_scaled_density(float density); - -/** 设置密度等级 */ -LCUI_API void ui_set_density_level(ui_density_Level_t level); - -/** 设置缩放密度等级 */ -LCUI_API void ui_set_scaled_density_level(ui_density_Level_t level); - -/** 设置 DPI */ -LCUI_API void ui_set_dpi(float dpi); - -/** 设置全局缩放比例 */ -LCUI_API void ui_set_scale(float scale); - -// Base - -LCUI_API ui_widget_t *ui_create_widget(const char *type); -LCUI_API ui_widget_t *ui_create_widget_with_prototype( - const ui_widget_prototype_t *proto); -LCUI_API void ui_widget_destroy(ui_widget_t *w); -LCUI_API void ui_widget_set_title(ui_widget_t *w, const wchar_t *title); -LCUI_API void ui_widget_set_text(ui_widget_t *w, const char *text); -LCUI_API void ui_widget_get_offset(ui_widget_t *w, ui_widget_t *parent, - float *offset_x, float *offset_y); -LCUI_API LCUI_BOOL ui_widget_in_viewport(ui_widget_t *w); - -// Root - -LCUI_API ui_widget_t *ui_root(void); -LCUI_API int ui_root_append(ui_widget_t *w); - -// Id - -LCUI_API ui_widget_t *ui_get_widget(const char *id); -LCUI_API int ui_widget_set_id(ui_widget_t *w, const char *idstr); - -// Prototype - -LCUI_API ui_widget_prototype_t *ui_create_widget_prototype( - const char *name, const char *parent_name); -LCUI_API ui_widget_prototype_t *ui_get_widget_prototype(const char *name); -LCUI_API LCUI_BOOL ui_check_widget_type(ui_widget_t *w, const char *type); -LCUI_API LCUI_BOOL -ui_check_widget_prototype(ui_widget_t *w, const ui_widget_prototype_t *proto); -LCUI_API void *ui_widget_get_data(ui_widget_t *widget, - ui_widget_prototype_t *proto); -LCUI_API void *ui_widget_add_data(ui_widget_t *widget, - ui_widget_prototype_t *proto, - size_t data_size); - -// Extra Data - -LCUI_API ui_widget_extra_data_t *ui_create_extra_data(ui_widget_t *widget); - -INLINE ui_widget_extra_data_t *ui_widget_use_extra_data(ui_widget_t *widget) -{ - return widget->extra ? widget->extra : ui_create_extra_data(widget); -} - -// Attributes - -LCUI_API int ui_widget_set_attribute_ex(ui_widget_t *w, const char *name, - void *value, int value_type, - void (*value_destructor)(void *)); -LCUI_API int ui_widget_set_attribute(ui_widget_t *w, const char *name, - const char *value); -LCUI_API const char *ui_widget_get_attribute_value(ui_widget_t *w, - const char *name); - -// Classes - -LCUI_API int ui_widget_add_class(ui_widget_t *w, const char *class_name); -LCUI_API LCUI_BOOL ui_widget_has_class(ui_widget_t *w, const char *class_name); -LCUI_API int ui_widget_remove_class(ui_widget_t *w, const char *class_name); - -// Status - -LCUI_API int ui_widget_add_status(ui_widget_t *w, const char *status_name); -LCUI_API LCUI_BOOL ui_widget_has_status(ui_widget_t *w, - const char *status_name); -LCUI_API int ui_widget_remove_status(ui_widget_t *w, const char *status_name); -LCUI_API void ui_widget_update_status(ui_widget_t *widget); -LCUI_API void ui_widget_set_disabled(ui_widget_t *w, LCUI_BOOL disabled); - -// Tree - -LCUI_API void ui_widget_remove(ui_widget_t *w); -LCUI_API void ui_widget_empty(ui_widget_t *w); -LCUI_API int ui_widget_append(ui_widget_t *parent, ui_widget_t *widget); -LCUI_API int ui_widget_prepend(ui_widget_t *parent, ui_widget_t *widget); -LCUI_API int ui_widget_unwrap(ui_widget_t *widget); -LCUI_API int ui_widget_unlink(ui_widget_t *w); -LCUI_API ui_widget_t *ui_widget_prev(ui_widget_t *w); -LCUI_API ui_widget_t *ui_widget_next(ui_widget_t *w); -LCUI_API ui_widget_t *ui_widget_get_child(ui_widget_t *w, size_t index); -LCUI_API size_t ui_widget_each(ui_widget_t *w, - void (*callback)(ui_widget_t *, void *), - void *arg); -LCUI_API ui_widget_t *ui_widget_at(ui_widget_t *widget, int ix, int iy); -LCUI_API void ui_print_tree(ui_widget_t *w); - -// Style -LCUI_API void ui_widget_get_style(ui_widget_t *w, int key, - css_style_value_t *value); -LCUI_API void ui_widget_set_style(ui_widget_t *w, int key, - const css_style_value_t *value); -LCUI_API int ui_widget_unset_style(ui_widget_t *w, int key); -LCUI_API css_selector_node_t *ui_widget_create_selector_node(ui_widget_t *w); -LCUI_API css_selector_t *ui_widget_create_selector(ui_widget_t *w); -LCUI_API size_t ui_widget_get_children_style_changes(ui_widget_t *w, int type, - const char *name); -LCUI_API void ui_widget_print_stylesheet(ui_widget_t *w); -LCUI_API size_t ui_widget_get_children_style_changes(ui_widget_t *w, int type, - const char *name); -LCUI_API void ui_widget_update_children_style(ui_widget_t *w); -LCUI_API void ui_widget_refresh_children_style(ui_widget_t *w); -LCUI_API int ui_widget_set_style_string(ui_widget_t *w, const char *property, - const char *css_text); -LCUI_API void ui_widget_set_style_unit_value(ui_widget_t *w, int key, - css_numeric_value_t value, - css_unit_t unit); -LCUI_API void ui_widget_set_style_keyword_value(ui_widget_t *w, int key, - css_keyword_value_t value); -LCUI_API void ui_widget_set_style_color_value(ui_widget_t *w, int key, - css_color_value_t value); -LCUI_API void ui_widget_set_style_numeric_value(ui_widget_t *w, int key, - css_numeric_value_t value); -LCUI_API void ui_widget_compute_style(ui_widget_t *w); -LCUI_API void ui_widget_force_update_style(ui_widget_t *w); -LCUI_API void ui_widget_force_refresh_style(ui_widget_t *w); - -// Updater - -LCUI_API size_t ui_widget_update(ui_widget_t *w); -LCUI_API size_t ui_update(void); -LCUI_API void ui_refresh_style(void); - -// Helper - -LCUI_API LCUI_BOOL ui_widget_is_visible(ui_widget_t *w); -LCUI_API void ui_widget_move(ui_widget_t *w, float left, float top); -LCUI_API void ui_widget_resize(ui_widget_t *w, float width, float height); -LCUI_API void ui_widget_show(ui_widget_t *w); -LCUI_API void ui_widget_hide(ui_widget_t *w); -LCUI_API ui_widget_t *ui_widget_get_closest(ui_widget_t *w, const char *type); -LCUI_API dict_t *ui_widget_collect_references(ui_widget_t *w); - -// Hash - -LCUI_API void ui_widget_generate_self_hash(ui_widget_t *widget); -LCUI_API void ui_widget_generate_hash(ui_widget_t *w); -LCUI_API size_t ui_widget_export_hash(ui_widget_t *w, unsigned *hash_list, - size_t len); -LCUI_API size_t ui_widget_import_hash(ui_widget_t *w, unsigned *hash_list, - size_t maxlen); - -// Layout - -/** - * 执行布局前的准备操作 - * 重置布局相关属性,以让它们在布局时被重新计算 - * @param rule 父级组件所使用的布局规则 - */ -LCUI_API void ui_widget_prepare_reflow(ui_widget_t *w, ui_layout_rule_t rule); - -LCUI_API void ui_widget_reset_size(ui_widget_t *w); - -LCUI_API void ui_widget_reflow(ui_widget_t *w); - -// Renderer - -LCUI_API LCUI_BOOL ui_widget_mark_dirty_rect(ui_widget_t *w, ui_rect_t *in_rect, - ui_box_type_t box_type); -LCUI_API size_t ui_widget_get_dirty_rects(ui_widget_t *w, list_t *rects); -LCUI_API size_t ui_widget_render(ui_widget_t *w, pd_context_t *paint); - -// Updater - -LCUI_API void ui_widget_set_rules(ui_widget_t *w, - const ui_widget_rules_t *rules); -LCUI_API void ui_widget_add_task_for_children(ui_widget_t *widget, - ui_task_type_t task); -LCUI_API void ui_widget_add_task(ui_widget_t *widget, int task); - -INLINE void ui_widget_refresh_style(ui_widget_t *w) -{ - ui_widget_add_task(w, UI_TASK_REFRESH_STYLE); -} - -INLINE void ui_widget_update_style(ui_widget_t *w) -{ - ui_widget_add_task(w, UI_TASK_UPDATE_STYLE); -} - -// Observer -LCUI_API LCUI_BOOL ui_widget_has_observer(ui_widget_t *widget, - ui_mutation_record_type_t type); - -LCUI_API int ui_widget_add_mutation_recrod(ui_widget_t *widget, - ui_mutation_record_t *record); - -// Logger - -LCUI_API int ui_logger_log(logger_level_e level, ui_widget_t *w, - const char *fmt, ...); - -#define ui_debug(W, ...) ui_logger_log(LOGGER_LEVEL_DEBUG, W, ##__VA_ARGS__) - -// Events - -/** 设置阻止部件及其子级部件的事件 */ -INLINE void ui_widget_block_event(ui_widget_t *w, LCUI_BOOL block) -{ - w->event_blocked = block; -} - -/** 触发事件,让事件处理器在主循环中调用 */ -LCUI_API int ui_widget_post_event(ui_widget_t *w, const ui_event_t *e, - void *arg, - ui_event_arg_destructor_t destroy_arg); - -/** 触发事件,直接调用事件处理器 */ -LCUI_API int ui_widget_emit_event(ui_widget_t *w, ui_event_t e, void *arg); - -/** 自动分配一个可用的事件标识号 */ -LCUI_API int ui_alloc_event_id(void); - -/** 设置与事件标识号对应的名称 */ -LCUI_API int ui_set_event_id(int event_id, const char *event_name); - -/** 获取与事件标识号对应的名称 */ -LCUI_API const char *ui_get_event_name(int event_id); - -/** 获取与事件名称对应的标识号 */ -LCUI_API int ui_get_event_id(const char *event_name); - -LCUI_API void ui_event_init(ui_event_t *e, const char *name); - -LCUI_API void ui_event_destroy(ui_event_t *e); - -/** - * 添加部件事件绑定 - * @param[in] widget 目标部件 - * @param[in] event_id 事件标识号 - * @param[in] handler 事件处理函数 - * @param[in] data 事件处理函数的附加数据 - * @param[in] destroy_arg 数据的销毁函数 - * @return 成功则返回 0,失败返回负数 - */ -LCUI_API ui_event_listener_t *ui_widget_add_event_listener( - ui_widget_t *widget, int event_id, ui_event_handler_t handler, void *data, - void (*destroy_arg)(void *)); - -/** - * 解除部件事件绑定 - * @param[in] widget 目标部件 - * @param[in] event_name 事件名称 - * @param[in] handler 与事件绑定的函数 - * @return 成功则返回 0,失败返回负数 - */ -LCUI_API int ui_widget_remove_event_listener(ui_widget_t *w, int event_id, - ui_event_handler_t handler, - void *data); - -/** - * 添加部件事件绑定 - * @param[in] widget 目标部件 - * @param[in] event_name 事件名称 - * @param[in] handler 事件处理函数 - * @param[in] data 事件处理函数的附加数据 - * @param[in] destroy_arg 数据的销毁函数 - * @return 返回已移除的事件监听器数量 - */ -LCUI_API ui_event_listener_t *ui_widget_on(ui_widget_t *widget, - const char *event_name, - ui_event_handler_t handler, - void *data, - void (*destroy_arg)(void *)); - -/** - * 解除部件事件绑定 - * @param[in] widget 目标部件 - * @param[in] event_name 事件名称 - * @param[in] handler 与事件绑定的函数 - * @return 成功则返回 0,失败返回负数 - */ -LCUI_API int ui_widget_off(ui_widget_t *widget, const char *event_name, - ui_event_handler_t handler, void *data); - -INLINE int ui_emit_event(ui_event_t e, void *arg) -{ - return ui_widget_emit_event(ui_root(), e, arg); -} - -INLINE int ui_post_event(const ui_event_t *e, void *arg, - ui_event_arg_destructor_t destroy_arg) -{ - return ui_widget_post_event(ui_root(), e, arg, destroy_arg); -} - -INLINE ui_event_listener_t *ui_add_event_listener( - ui_widget_t *widget, int event_id, ui_event_handler_t handler, void *arg, - ui_event_arg_destructor_t destroy_arg) -{ - return ui_widget_add_event_listener(ui_root(), event_id, handler, arg, - destroy_arg); -} - -INLINE int ui_remove_event_listener(ui_widget_t *w, int event_id, - ui_event_handler_t handler, void *data) -{ - return ui_widget_remove_event_listener(ui_root(), event_id, handler, - data); -} - -INLINE ui_event_listener_t *ui_on_event(const char *event_name, - ui_event_handler_t handler, void *data, - void (*destroy_arg)(void *)) -{ - return ui_widget_on(ui_root(), event_name, handler, data, destroy_arg); -} - -INLINE int ui_off_event(const char *event_name, ui_event_handler_t handler, - void *data) -{ - return ui_widget_off(ui_root(), event_name, handler, data); -} - -/** 清除事件对象,通常在部件销毁时调用该函数,以避免部件销毁后还有事件发送给它 - */ -LCUI_API void ui_clear_event_target(ui_widget_t *widget); - -/** get current focused widget */ -LCUI_API ui_widget_t *ui_get_focus(void); - -/** 将一个部件设置为焦点 */ -LCUI_API int ui_set_focus(ui_widget_t *widget); - -/** 停止部件的事件传播 */ -LCUI_API int ui_widget_stop_event_propagation(ui_widget_t *widget); - -/** 为部件设置鼠标捕获,设置后将捕获全局范围内的鼠标事件 */ -LCUI_API void ui_widget_set_mouse_capture(ui_widget_t *w); - -/** 为部件解除鼠标捕获 */ -LCUI_API void ui_widget_release_mouse_capture(ui_widget_t *w); - -/** - * 为部件设置触点捕获,设置后将捕获全局范围内的触点事件 - * @param[in] w 部件 - * @param[in] point_id 触点ID,当值为 -1 时则捕获全部触点 - * @returns 设置成功返回 0,如果其它部件已经捕获该触点则返回 -1 - */ -LCUI_API int ui_widget_set_touch_capture(ui_widget_t *w, int point_id); - -/** - * 为部件解除触点捕获 - * @param[in] w 部件 - * @param[in] point_id 触点ID,当值为 -1 时则解除全部触点的捕获 - */ -LCUI_API int ui_widget_release_touch_capture(ui_widget_t *w, int point_id); - -LCUI_API void ui_widget_destroy_listeners(ui_widget_t *w); - -// CSS - -LCUI_API int ui_load_css_file(const char *filepath); -LCUI_API size_t ui_load_css_string(const char *str, const char *space); - -// Image Loader - -#define ui_image_on_event ui_image_add_event_listener -#define ui_image_off_event ui_image_remove_event_listener - -typedef struct ui_image_t ui_image_t; -typedef void (*ui_image_event_handler_t)(ui_image_t *, void *); - -LCUI_API void ui_init_image_loader(void); -LCUI_API void ui_destroy_image_loader(void); -LCUI_API void ui_process_image_events(void); -LCUI_API ui_image_t *ui_load_image(const char *path); -LCUI_API pd_canvas_t *ui_image_get_data(ui_image_t *image); -LCUI_API const char *ui_image_get_path(ui_image_t *image); -LCUI_API void ui_image_add_ref(ui_image_t *image); -LCUI_API void ui_image_remove_ref(ui_image_t *image); -LCUI_API int ui_image_add_event_listener(ui_image_t *image, - ui_image_event_handler_t handler, - void *data); -LCUI_API int ui_image_remove_event_listener(ui_image_t *image, - ui_image_event_handler_t handler, - void *data); - -// CSS Font Style - -#define UI_DEFAULT_FONT_SIZE 14 -#define UI_DEFAULT_FONT_COLOR 0xff333333 -#define UI_MIN_FONT_SIZE 12 -#define UI_LINE_HEIGHT_SCALE 1.42857143 - -typedef struct ui_text_style_t { - int font_size; - int line_height; - int *font_ids; - char *font_family; - wchar_t *content; - pd_color_t color; - uint8_t font_style; - uint8_t font_weight; - uint8_t text_align; - uint8_t white_space; - uint8_t word_break; -} ui_text_style_t; - -LCUI_API void ui_text_style_init(ui_text_style_t *fs); - -LCUI_API void ui_text_style_destroy(ui_text_style_t *fs); - -LCUI_API LCUI_BOOL ui_text_style_is_equal(const ui_text_style_t *a, - const ui_text_style_t *b); - -LCUI_API void ui_compute_text_style(ui_text_style_t *fs, - const css_computed_style_t *ss); - -// Rect - -LCUI_API void ui_convert_rect(const pd_rect_t *rect, ui_rect_t *rectf, - float scale); - -LCUI_API LCUI_BOOL ui_rect_correct(ui_rect_t *rect, float container_width, - float container_height); - -INLINE LCUI_BOOL ui_rect_has_point(ui_rect_t *rect, float x, float y) -{ - return x >= rect->x && y >= rect->y && x < rect->x + rect->width && - y < rect->y + rect->height; -} - -INLINE LCUI_BOOL ui_rect_is_equal(const ui_rect_t *a, const ui_rect_t *b) -{ - return (int)(100 * (a->x - b->x)) == 0 && - (int)(100 * (a->y - b->y)) == 0 && - (int)(100 * (a->width - b->width)) == 0 && - (int)(100 * (a->height - b->height)) == 0; -} - -LCUI_API LCUI_BOOL ui_rect_is_cover(const ui_rect_t *a, const ui_rect_t *b); - -INLINE LCUI_BOOL ui_rect_is_include(ui_rect_t *a, ui_rect_t *b) -{ - return (b->x >= a->x && b->x + b->width <= a->x + a->width && - b->y >= a->y && b->y + b->height <= a->y + a->height); -} - -LCUI_API LCUI_BOOL ui_rect_overlap(const ui_rect_t *a, const ui_rect_t *b, - ui_rect_t *overlapping_rect); - -LCUI_API void ui_rect_merge(ui_rect_t *merged_rect, const ui_rect_t *a, - const ui_rect_t *b); - -LCUI_END_HEADER - -#endif diff --git a/include/LCUI/ui/cursor.h b/include/LCUI/ui/cursor.h deleted file mode 100644 index 7938cf0f6..000000000 --- a/include/LCUI/ui/cursor.h +++ /dev/null @@ -1,21 +0,0 @@ -// TODO: Reduce dependence on lcui header files - -#include -#include -#include -#include - -LCUI_BEGIN_HEADER - -LCUI_API void ui_cursor_refresh(void); -LCUI_API LCUI_BOOL ui_cursor_is_visible(void); -LCUI_API void ui_cursor_show(void); -LCUI_API void ui_cursor_hide(void); -LCUI_API void ui_cursor_set_position(int x, int y); -LCUI_API int ui_cursor_set_image(pd_canvas_t *image); -LCUI_API void ui_cursor_get_position(int *x, int *y); -LCUI_API int ui_cursor_paint(app_window_t *w, app_window_paint_t* paint); -LCUI_API void ui_cursor_init(void); -LCUI_API void ui_cursor_destroy(void); - -LCUI_END_HEADER diff --git a/include/LCUI/ui/server.h b/include/LCUI/ui/server.h deleted file mode 100644 index 26cecb43f..000000000 --- a/include/LCUI/ui/server.h +++ /dev/null @@ -1,20 +0,0 @@ -// TODO: Reduce dependence on lcui header files - -#include -#include -#include - -LCUI_BEGIN_HEADER - -LCUI_API ui_widget_t *ui_server_get_widget(app_window_t *window); -LCUI_API app_window_t *ui_server_get_window(ui_widget_t *widget); -LCUI_API int ui_server_disconnect(ui_widget_t *widget, app_window_t *window); -LCUI_API void ui_server_connect(ui_widget_t *widget, app_window_t *window); -LCUI_API size_t ui_server_render(void); -LCUI_API void ui_server_present(void); -LCUI_API void ui_server_init(void); -LCUI_API void ui_server_set_threads(int threads); -LCUI_API void ui_server_set_paint_flashing_enabled(LCUI_BOOL enabled); -LCUI_API void ui_server_destroy(void); - -LCUI_END_HEADER diff --git a/include/LCUI/ui/widgets/button.h b/include/LCUI/ui/widgets/button.h deleted file mode 100644 index d802761c7..000000000 --- a/include/LCUI/ui/widgets/button.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * button.h -- LCUI‘s Button widget - * - * Copyright (c) 2018, Liu chao All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of LCUI nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef LIB_UI_WIDGETS_INCLUDE_BUTTON_H -#define LIB_UI_WIDGETS_INCLUDE_BUTTON_H - -LCUI_BEGIN_HEADER - -LCUI_API void ui_button_set_text_w(ui_widget_t* w, const wchar_t *wstr); - -LCUI_API void ui_button_set_text(ui_widget_t* w, const char *str); - -LCUI_API void ui_register_button(void); - -LCUI_END_HEADER - -#endif diff --git a/include/LCUI/ui/widgets/canvas.h b/include/LCUI/ui/widgets/canvas.h deleted file mode 100644 index afd506f3e..000000000 --- a/include/LCUI/ui/widgets/canvas.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * canvas.h -- canvas, used to draw custom graphics - * - * Copyright (c) 2019-2022, Liu chao All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of LCUI nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef LIB_UI_WIDGETS_INCLUDE_CANVAS_H -#define LIB_UI_WIDGETS_INCLUDE_CANVAS_H - -LCUI_BEGIN_HEADER - -/** @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas#attributes */ - -#define UI_CANVAS_DEFAULT_WIDTH 300 -#define UI_CANVAS_DEFAULT_HEIGHT 150 - -typedef struct ui_canvas_rendering_context_t ui_canvas_context_t; - -typedef struct ui_canvas_rendering_context_t { - LCUI_BOOL available; - pd_color_t fill_color; - pd_canvas_t buffer; - ui_widget_t* canvas; - list_node_t node; - - float scale; - int width; - int height; - - /** - * Draws a rectangle that is filled according to the current `fill_color`. - * Reference: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillRect - */ - void (*fill_rect)(ui_canvas_context_t*, int, int, int, int); - - /** - * Erases the pixels in a rectangular area by setting them to transparent black. - * Reference: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clearRect - */ - void (*clear_rect)(ui_canvas_context_t*, int, int, int, int); - - - void (*release)(ui_canvas_context_t*); -} ui_canvas_rendering_context_t; - -/** - * Get a drawing context on the canvas - * Reference: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/getContext -*/ -LCUI_API ui_canvas_context_t *ui_canvas_get_context(ui_widget_t* w); - -void ui_register_canvas(void); - -LCUI_END_HEADER - -#endif diff --git a/include/LCUI/ui/widgets/scrollbar.h b/include/LCUI/ui/widgets/scrollbar.h deleted file mode 100644 index 184ef31c3..000000000 --- a/include/LCUI/ui/widgets/scrollbar.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * scrollbar.c -- LCUI's scrollbar widget - * - * Copyright (c) 2018, Liu chao All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of LCUI nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef LIB_UI_WIDGETS_INCLUDE_SCROLLBAR_H -#define LIB_UI_WIDGETS_INCLUDE_SCROLLBAR_H - -LCUI_BEGIN_HEADER - -typedef enum ui_scrollbar_direction_t { - UI_SCROLLBAR_HORIZONTAL, - UI_SCROLLBAR_VERTICAL -} ui_scrollbar_direction_t; - -LCUI_API void ui_scrollbar_bind_container(ui_widget_t* w, - ui_widget_t* container); - -LCUI_API void ui_scrollbar_bind_target(ui_widget_t* w, ui_widget_t* target); - -/** 获取滚动条的位置 */ -LCUI_API float ui_scrollbar_get_position(ui_widget_t* w); - -/** 将与滚动条绑定的内容滚动至指定位置 */ -LCUI_API float ui_scrollbar_set_position(ui_widget_t* w, float pos); - -/** 设置滚动条的方向 */ -LCUI_API void ui_scrollbar_set_direction(ui_widget_t* w, - ui_scrollbar_direction_t direction); - -LCUI_API void ui_register_scrollbar(void); - -LCUI_END_HEADER - -#endif diff --git a/include/LCUI/ui/widgets/textedit.h b/include/LCUI/ui/widgets/textedit.h deleted file mode 100644 index 0b586390f..000000000 --- a/include/LCUI/ui/widgets/textedit.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * textedit.c -- textedit widget, used to allow user edit text. - * - * Copyright (c) 2018-22, Liu chao All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of LCUI nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef LIB_UI_WIDGETS_INCLUDE_TEXTEDIT_H -#define LIB_UI_WIDGETS_INCLUDE_TEXTEDIT_H - -#include -#include - -LCUI_BEGIN_HEADER - -/** Enable style tag parser */ -LCUI_API void ui_textedit_enable_style_tag(ui_widget_t* widget, LCUI_BOOL enable); - -LCUI_API void ui_textedit_enable_multiline(ui_widget_t* widget, LCUI_BOOL enable); - -LCUI_API void ui_textedit_move_caret(ui_widget_t* widget, int row, int col); - -/** 清空文本内容 */ -LCUI_API void ui_textedit_clear_text(ui_widget_t* widget); - -/** 获取文本内容 */ -LCUI_API size_t ui_textedit_get_text_w(ui_widget_t* w, size_t start, - size_t max_len, wchar_t *buf); - -/** 获取文本长度 */ -LCUI_API size_t ui_textedit_get_text_length(ui_widget_t* w); - -/** 设置文本编辑框内的光标,指定是否闪烁、闪烁时间间隔 */ -LCUI_API void ui_textedit_set_caret_blink(ui_widget_t* w, LCUI_BOOL visible, int time); - - /** 为文本框设置文本(宽字符版) */ -LCUI_API int ui_textedit_set_text_w(ui_widget_t* widget, const wchar_t *wstr); - -LCUI_API int ui_textedit_set_text(ui_widget_t* widget, const char *utf8_str); - -/** 为文本框追加文本(宽字符版) */ -LCUI_API int ui_textedit_append_text_w(ui_widget_t* widget, const wchar_t *wstr); - -/** 为文本框插入文本(宽字符版) */ -LCUI_API int ui_textedit_insert_text_w(ui_widget_t* widget, const wchar_t *wstr); - -/** 设置占位符,当文本编辑框内容为空时显示占位符 */ -LCUI_API int ui_textedit_set_placeholder_w(ui_widget_t* w, const wchar_t *wstr); - -LCUI_API int ui_textedit_set_placeholder(ui_widget_t* w, const char *str); - -/** 设置密码屏蔽符 */ -LCUI_API void ui_textedit_set_passworld_char(ui_widget_t* w, wchar_t ch); - -LCUI_API void ui_register_textedit(void); - -LCUI_END_HEADER - -#endif diff --git a/include/LCUI/worker.h b/include/LCUI/worker.h index b87e64aa4..f683e8237 100644 --- a/include/LCUI/worker.h +++ b/include/LCUI/worker.h @@ -45,6 +45,8 @@ typedef struct LCUI_WorkerRec_ *LCUI_Worker; LCUI_API LCUI_Worker LCUIWorker_New(void); +LCUI_API void LCUIWorker_setFrameRateCap(LCUI_Worker worker, unsigned rate_cap); + LCUI_API void LCUIWorker_PostTask(LCUI_Worker worker, LCUI_Task task); LCUI_API LCUI_BOOL LCUIWorker_RunTask(LCUI_Worker worker); diff --git a/lib/ctest/include/ctest.h b/lib/ctest/include/ctest.h index dc11f3579..8424d2ea6 100644 --- a/lib/ctest/include/ctest.h +++ b/lib/ctest/include/ctest.h @@ -3,7 +3,7 @@ #include #include -#include +#include void describe(const char *name, void (*func)()); diff --git a/lib/pandagl/xmake.lua b/lib/pandagl/xmake.lua index 029700589..65a2b68a1 100644 --- a/lib/pandagl/xmake.lua +++ b/lib/pandagl/xmake.lua @@ -2,9 +2,6 @@ set_project("pandagl") set_version("0.1.0-a") add_requires("libpng", "libjpeg", {optional = true}) add_requires("freetype", {optional = true, configs = {shared = false}}) -add_includedirs("include") -set_configdir("include/pandagl") -add_configfiles("src/config.h.in") if is_plat("linux") then add_requires("fontconfig", {optional = true}) @@ -29,6 +26,9 @@ target("pandagl") set_kind("$(kind)") add_files("src/*.c") add_deps("yutil") + add_includedirs("include") + set_configdir("include/pandagl") + add_configfiles("src/config.h.in") if is_kind("static") then set_configvar("PANDAGL_STATIC_BUILD", 1) elseif is_plat("windows") then diff --git a/lib/ui-builder/include/builder.h b/lib/ui-builder/include/builder.h deleted file mode 100644 index e52eb8e22..000000000 --- a/lib/ui-builder/include/builder.h +++ /dev/null @@ -1,55 +0,0 @@ -/* *************************************************************************** - * builder.h -- The GUI build module, parse UI config code and build UI. - * - * Copyright (c) 2018-2022, Liu chao All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of LCUI nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef LIB_UI_BUILDER_INCLUDE_BUILDER_H -#define LIB_UI_BUILDER_INCLUDE_BUILDER_H - -#include -#include - -LCUI_BEGIN_HEADER - -/** - * 从字符串中载入界面配置代码,解析并生成相应的图形界面(元素) - * @param[in] str 包含界面配置代码的字符串 - * @return 正常解析会返回一个部件,出现错误则返回 NULL - */ -LCUI_API ui_widget_t* ui_load_xml_string(const char *str, int size); - -/** - * 从文件中载入界面配置代码,解析并生成相应的图形界面(元素) - * @param[in] filepath 文件路径 - * @return 正常解析会返回一个部件,出现错误则返回 NULL - */ -LCUI_API ui_widget_t* ui_load_xml_file(const char *filepath); - -LCUI_END_HEADER - -#endif diff --git a/include/LCUI/ui/builder.h b/lib/ui-builder/include/ui_builder.h similarity index 99% rename from include/LCUI/ui/builder.h rename to lib/ui-builder/include/ui_builder.h index e52eb8e22..d2b548ed5 100644 --- a/include/LCUI/ui/builder.h +++ b/lib/ui-builder/include/ui_builder.h @@ -32,7 +32,7 @@ #define LIB_UI_BUILDER_INCLUDE_BUILDER_H #include -#include +#include LCUI_BEGIN_HEADER diff --git a/lib/ui-builder/src/builder.c b/lib/ui-builder/src/builder.c index bacbf0808..5cf31d6b9 100644 --- a/lib/ui-builder/src/builder.c +++ b/lib/ui-builder/src/builder.c @@ -31,11 +31,11 @@ #include #include #include -#include -#include +#include #include #include -#include "../include/builder.h" +#include +#include #define WARN_TXT "[builder] warning: this module is not enabled before build.\n" diff --git a/lib/ui-cursor/include/cursor.h b/lib/ui-cursor/include/ui_cursor.h similarity index 96% rename from lib/ui-cursor/include/cursor.h rename to lib/ui-cursor/include/ui_cursor.h index 7938cf0f6..2ac474297 100644 --- a/lib/ui-cursor/include/cursor.h +++ b/lib/ui-cursor/include/ui_cursor.h @@ -3,7 +3,7 @@ #include #include #include -#include +#include LCUI_BEGIN_HEADER diff --git a/lib/ui-cursor/src/cursor.c b/lib/ui-cursor/src/cursor.c index c27c424b9..65338beab 100644 --- a/lib/ui-cursor/src/cursor.c +++ b/lib/ui-cursor/src/cursor.c @@ -1,4 +1,4 @@ -#include "../include/cursor.h" +#include static struct ui_cursor_t { int x, y; diff --git a/lib/ui-server/include/server.h b/lib/ui-server/include/ui_server.h similarity index 97% rename from lib/ui-server/include/server.h rename to lib/ui-server/include/ui_server.h index 26cecb43f..a173c8709 100644 --- a/lib/ui-server/include/server.h +++ b/lib/ui-server/include/ui_server.h @@ -2,7 +2,7 @@ #include #include -#include +#include LCUI_BEGIN_HEADER diff --git a/lib/ui-server/src/server.c b/lib/ui-server/src/server.c index 877cad35e..a60f969f4 100644 --- a/lib/ui-server/src/server.c +++ b/lib/ui-server/src/server.c @@ -4,10 +4,10 @@ #include #include #include -#include +#include +#include #include #include -#include "../include/server.h" #ifdef ENABLE_OPENMP #include diff --git a/lib/ui-widgets/include/anchor.h b/lib/ui-widgets/include/anchor.h deleted file mode 100644 index 8e8eb5b77..000000000 --- a/lib/ui-widgets/include/anchor.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * anchor.c -- The anchor widget, used to link view resource, its function is - * similar to element in HTML. - * - * Copyright (c) 2018, Liu chao All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of LCUI nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef LIB_UI_WIDGETS_INCLUDE_ANCHOR_H -#define LIB_UI_WIDGETS_INCLUDE_ANCHOR_H - -#include - -LCUI_API void ui_anchor_open(ui_widget_t* w); - -LCUI_API void ui_register_anchor(void); - -LCUI_API void ui_unregister_anchor(void); - -#endif diff --git a/lib/ui-widgets/include/textcaret.h b/lib/ui-widgets/include/textcaret.h deleted file mode 100644 index eb8707907..000000000 --- a/lib/ui-widgets/include/textcaret.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * textcaret.h -- textcaret widget, used in textedit. - * - * Copyright (c) 2018, Liu chao All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of LCUI nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef LIB_UI_WIDGETS_INCLUDE_TEXTCARET_H -#define LIB_UI_WIDGETS_INCLUDE_TEXTCARET_H - -#include -#include - -LCUI_API void ui_textcaret_refresh(ui_widget_t* widget); - -LCUI_API void ui_textcaret_set_visible(ui_widget_t* widget, LCUI_BOOL visible); - -/** 设置闪烁的时间间隔 */ -LCUI_API void ui_textcaret_set_blink_time(ui_widget_t* widget, unsigned int n_ms); - -LCUI_API void ui_register_textcaret(void); - -#endif diff --git a/lib/ui-widgets/include/textview.h b/lib/ui-widgets/include/textview.h deleted file mode 100644 index dcf5b130b..000000000 --- a/lib/ui-widgets/include/textview.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * textview.h -- TextView widget for display text. - * - * Copyright (c) 2018-2022, Liu chao All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of LCUI nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef LIB_UI_WIDGETS_INCLUDE_TEXTVIEW_H -#define LIB_UI_WIDGETS_INCLUDE_TEXTVIEW_H - -#include -#include - -LCUI_BEGIN_HEADER - -LCUI_API int ui_textview_set_text_w(ui_widget_t* w, const wchar_t *text); - -LCUI_API int ui_textview_set_text(ui_widget_t* w, const char *utf8_text); - -LCUI_API void ui_textview_set_multiline(ui_widget_t* w, LCUI_BOOL enable); - -LCUI_API void ui_register_textview(void); - -LCUI_API void ui_unregister_textview(void); - -LCUI_END_HEADER - -#endif diff --git a/lib/ui-widgets/include/ui_widgets.h b/lib/ui-widgets/include/ui_widgets.h new file mode 100644 index 000000000..45be04be2 --- /dev/null +++ b/lib/ui-widgets/include/ui_widgets.h @@ -0,0 +1,8 @@ + +#include +#include +#include +#include +#include +#include +#include diff --git a/include/LCUI/ui/widgets/anchor.h b/lib/ui-widgets/include/ui_widgets/anchor.h similarity index 98% rename from include/LCUI/ui/widgets/anchor.h rename to lib/ui-widgets/include/ui_widgets/anchor.h index 8e8eb5b77..20dd5a595 100644 --- a/include/LCUI/ui/widgets/anchor.h +++ b/lib/ui-widgets/include/ui_widgets/anchor.h @@ -32,7 +32,8 @@ #ifndef LIB_UI_WIDGETS_INCLUDE_ANCHOR_H #define LIB_UI_WIDGETS_INCLUDE_ANCHOR_H -#include +#include +#include LCUI_API void ui_anchor_open(ui_widget_t* w); diff --git a/lib/ui-widgets/include/button.h b/lib/ui-widgets/include/ui_widgets/button.h similarity index 98% rename from lib/ui-widgets/include/button.h rename to lib/ui-widgets/include/ui_widgets/button.h index d802761c7..8fc932a6b 100644 --- a/lib/ui-widgets/include/button.h +++ b/lib/ui-widgets/include/ui_widgets/button.h @@ -31,6 +31,9 @@ #ifndef LIB_UI_WIDGETS_INCLUDE_BUTTON_H #define LIB_UI_WIDGETS_INCLUDE_BUTTON_H +#include +#include + LCUI_BEGIN_HEADER LCUI_API void ui_button_set_text_w(ui_widget_t* w, const wchar_t *wstr); diff --git a/lib/ui-widgets/include/canvas.h b/lib/ui-widgets/include/ui_widgets/canvas.h similarity index 98% rename from lib/ui-widgets/include/canvas.h rename to lib/ui-widgets/include/ui_widgets/canvas.h index afd506f3e..278b5bde9 100644 --- a/lib/ui-widgets/include/canvas.h +++ b/lib/ui-widgets/include/ui_widgets/canvas.h @@ -31,6 +31,8 @@ #ifndef LIB_UI_WIDGETS_INCLUDE_CANVAS_H #define LIB_UI_WIDGETS_INCLUDE_CANVAS_H +#include +#include LCUI_BEGIN_HEADER /** @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas#attributes */ diff --git a/lib/ui-widgets/include/scrollbar.h b/lib/ui-widgets/include/ui_widgets/scrollbar.h similarity index 98% rename from lib/ui-widgets/include/scrollbar.h rename to lib/ui-widgets/include/ui_widgets/scrollbar.h index 184ef31c3..872f38564 100644 --- a/lib/ui-widgets/include/scrollbar.h +++ b/lib/ui-widgets/include/ui_widgets/scrollbar.h @@ -31,6 +31,9 @@ #ifndef LIB_UI_WIDGETS_INCLUDE_SCROLLBAR_H #define LIB_UI_WIDGETS_INCLUDE_SCROLLBAR_H +#include +#include + LCUI_BEGIN_HEADER typedef enum ui_scrollbar_direction_t { diff --git a/include/LCUI/ui/widgets/textcaret.h b/lib/ui-widgets/include/ui_widgets/textcaret.h similarity index 98% rename from include/LCUI/ui/widgets/textcaret.h rename to lib/ui-widgets/include/ui_widgets/textcaret.h index eb8707907..2b18a9d2f 100644 --- a/include/LCUI/ui/widgets/textcaret.h +++ b/lib/ui-widgets/include/ui_widgets/textcaret.h @@ -32,7 +32,7 @@ #define LIB_UI_WIDGETS_INCLUDE_TEXTCARET_H #include -#include +#include LCUI_API void ui_textcaret_refresh(ui_widget_t* widget); diff --git a/lib/ui-widgets/include/textedit.h b/lib/ui-widgets/include/ui_widgets/textedit.h similarity index 99% rename from lib/ui-widgets/include/textedit.h rename to lib/ui-widgets/include/ui_widgets/textedit.h index 0b586390f..5b6f513a2 100644 --- a/lib/ui-widgets/include/textedit.h +++ b/lib/ui-widgets/include/ui_widgets/textedit.h @@ -32,7 +32,7 @@ #define LIB_UI_WIDGETS_INCLUDE_TEXTEDIT_H #include -#include +#include LCUI_BEGIN_HEADER diff --git a/include/LCUI/ui/widgets/textview.h b/lib/ui-widgets/include/ui_widgets/textview.h similarity index 99% rename from include/LCUI/ui/widgets/textview.h rename to lib/ui-widgets/include/ui_widgets/textview.h index dcf5b130b..f07f52100 100644 --- a/include/LCUI/ui/widgets/textview.h +++ b/lib/ui-widgets/include/ui_widgets/textview.h @@ -32,7 +32,7 @@ #define LIB_UI_WIDGETS_INCLUDE_TEXTVIEW_H #include -#include +#include LCUI_BEGIN_HEADER diff --git a/lib/ui-widgets/src/anchor.c b/lib/ui-widgets/src/anchor.c index a89fc8a4b..014b9d051 100644 --- a/lib/ui-widgets/src/anchor.c +++ b/lib/ui-widgets/src/anchor.c @@ -32,11 +32,11 @@ #include #include #include -#include +#include +#include +#include #include #include -#include -#include "../include/anchor.h" typedef struct xml_loader_t { char* key; /**< 键,作为在视图加载完后传给事件处理器的额外参数 */ diff --git a/lib/ui-widgets/src/button.c b/lib/ui-widgets/src/button.c index e4f0bcce9..aeb313438 100644 --- a/lib/ui-widgets/src/button.c +++ b/lib/ui-widgets/src/button.c @@ -30,10 +30,10 @@ #include #include -#include +#include #include -#include "../include/button.h" -#include "../include/textview.h" +#include +#include static ui_widget_prototype_t *ui_button_prototype = NULL; diff --git a/lib/ui-widgets/src/canvas.c b/lib/ui-widgets/src/canvas.c index e9751e84b..1ae5dd60b 100644 --- a/lib/ui-widgets/src/canvas.c +++ b/lib/ui-widgets/src/canvas.c @@ -30,8 +30,8 @@ #include #include -#include -#include "../include/canvas.h" +#include +#include typedef struct ui_canvas_t { pd_canvas_t buffer; diff --git a/lib/ui-widgets/src/scrollbar.c b/lib/ui-widgets/src/scrollbar.c index ac866ec76..666f31931 100644 --- a/lib/ui-widgets/src/scrollbar.c +++ b/lib/ui-widgets/src/scrollbar.c @@ -31,10 +31,10 @@ #include #include #include -#include -#include #include -#include "../include/scrollbar.h" +#include +#include +#include /* clang-format off */ diff --git a/lib/ui-widgets/src/textcaret.c b/lib/ui-widgets/src/textcaret.c index ffcde6c95..d90fa30a1 100644 --- a/lib/ui-widgets/src/textcaret.c +++ b/lib/ui-widgets/src/textcaret.c @@ -29,11 +29,12 @@ */ #include -#include -#include -#include +#include #include -#include "../include/textedit.h" +#include +#include +#include +#include typedef struct ui_textcaret_task_t { LCUI_BOOL active; diff --git a/lib/ui-widgets/src/textedit.c b/lib/ui-widgets/src/textedit.c index 022280468..2f9a6e48c 100644 --- a/lib/ui-widgets/src/textedit.c +++ b/lib/ui-widgets/src/textedit.c @@ -35,9 +35,9 @@ #include #include #include -#include "./internal.h" -#include "../include/textedit.h" -#include "../include/textcaret.h" +#include +#include +#include "textstyle.h" #define TEXTBLOCK_SIZE 512 #define DEFAULT_WIDTH 176.0f diff --git a/lib/ui-widgets/src/textstyle.c b/lib/ui-widgets/src/textstyle.c index ad7be5fb0..fd49a8d4a 100644 --- a/lib/ui-widgets/src/textstyle.c +++ b/lib/ui-widgets/src/textstyle.c @@ -1,4 +1,4 @@ -#include "./internal.h" +#include "textstyle.h" void convert_font_style_to_text_style(ui_text_style_t *fs, pd_text_style_t *ts) { diff --git a/lib/ui-widgets/src/internal.h b/lib/ui-widgets/src/textstyle.h similarity index 83% rename from lib/ui-widgets/src/internal.h rename to lib/ui-widgets/src/textstyle.h index 8f894e27f..8f94b98ae 100644 --- a/lib/ui-widgets/src/internal.h +++ b/lib/ui-widgets/src/textstyle.h @@ -1,4 +1,4 @@ #include -#include +#include void convert_font_style_to_text_style(ui_text_style_t *fs, pd_text_style_t *ts); diff --git a/lib/ui-widgets/src/textview.c b/lib/ui-widgets/src/textview.c index c79bc31be..35662b70a 100644 --- a/lib/ui-widgets/src/textview.c +++ b/lib/ui-widgets/src/textview.c @@ -34,8 +34,8 @@ #include #include #include -#include "./internal.h" -#include "../include/textview.h" +#include +#include "textstyle.h" typedef struct ui_textview_task_t { wchar_t *content; diff --git a/lib/ui/include/ui.h b/lib/ui/include/ui.h index 7411413aa..669c30d79 100644 --- a/lib/ui/include/ui.h +++ b/lib/ui/include/ui.h @@ -1,979 +1,16 @@ #ifndef LIB_UI_INCLUDE_UI_H #define LIB_UI_INCLUDE_UI_H -#include -#include -#include -#include -#include - -LCUI_BEGIN_HEADER - -// Types - -typedef struct ui_rect_t { - float x, y, width, height; -} ui_rect_t; - -typedef struct ui_area_t { - float left, top, right, bottom; -} ui_area_t; - -typedef css_metrics_t ui_metrics_t; - -typedef enum ui_density_Level_t { - UI_DENSITY_LEVEL_SMALL, - UI_DENSITY_LEVEL_NORMAL, - UI_DENSITY_LEVEL_LARGE, - UI_DENSITY_LEVEL_BIG -} ui_density_Level_t; - -typedef enum ui_sizing_rule_t { - UI_SIZING_RULE_NONE, - UI_SIZING_RULE_FIXED, - UI_SIZING_RULE_FILL, - UI_SIZING_RULE_PERCENT, - UI_SIZING_RULE_FIT_CONTENT -} ui_sizing_rule_t; - -typedef enum ui_layout_rule_t { - UI_LAYOUT_RULE_AUTO, - UI_LAYOUT_RULE_MAX_CONTENT, - UI_LAYOUT_RULE_FIXED_WIDTH = 0b11, - UI_LAYOUT_RULE_FIXED_HEIGHT = 0b101, - UI_LAYOUT_RULE_FIXED = 0b111 -} ui_layout_rule_t; - -typedef enum ui_widget_state_t { - UI_WIDGET_STATE_CREATED = 0, - UI_WIDGET_STATE_UPDATED, - UI_WIDGET_STATE_LAYOUTED, - UI_WIDGET_STATE_READY, - UI_WIDGET_STATE_NORMAL, - UI_WIDGET_STATE_DELETED, -} ui_widget_state_t; - -typedef enum ui_box_type_t { - UI_BOX_TYPE_CONTENT_BOX, - UI_BOX_TYPE_PADDING_BOX, - UI_BOX_TYPE_BORDER_BOX, - UI_BOX_TYPE_GRAPH_BOX -} ui_box_type_t; - -typedef enum ui_dirty_rect_type_t { - UI_DIRTY_RECT_TYPE_NONE, - UI_DIRTY_RECT_TYPE_CUSTOM, - UI_DIRTY_RECT_TYPE_PADDING_BOX, - UI_DIRTY_RECT_TYPE_BORDER_BOX, - UI_DIRTY_RECT_TYPE_CANVAS_BOX -} ui_dirty_rect_type_t; - -typedef struct ui_border_style_t_ { - struct { - int style; - float width; - pd_color_t color; - } top, right, bottom, left; - float top_left_radius; - float top_right_radius; - float bottom_left_radius; - float bottom_right_radius; -} ui_border_style_t; - -typedef struct ui_widget_attribute_t_ { - char *name; - struct { - int type; - void (*destructor)(void *); - union { - char *string; - void *data; - }; - } value; -} ui_widget_attribute_t; - -typedef struct ui_widget_actual_style_t_ { - float x, y; - pd_rect_t canvas_box; - pd_rect_t border_box; - pd_rect_t padding_box; - pd_rect_t content_box; -} ui_widget_actual_style_t; - -typedef enum ui_task_type_t { - UI_TASK_REFRESH_STYLE, - UI_TASK_UPDATE_STYLE, - UI_TASK_REFLOW, - UI_TASK_USER, - UI_TASK_TOTAL_NUM -} ui_task_type_t; - -typedef struct ui_event_listener_t ui_event_listener_t; -typedef struct ui_widget_t ui_widget_t; -typedef list_t ui_widget_listeners_t; - -typedef void (*ui_widget_function_t)(ui_widget_t *); -typedef void (*ui_widget_task_handler_t)(ui_widget_t *, int); -typedef void (*ui_widget_size_getter_t)(ui_widget_t *, float *, float *, - ui_layout_rule_t); -typedef void (*ui_widget_size_setter_t)(ui_widget_t *, float, float); -typedef void (*ui_widget_attr_setter_t)(ui_widget_t *, const char *, - const char *); -typedef void (*ui_widget_text_setter_t)(ui_widget_t *, const char *); -typedef void (*ui_widget_painter_t)(ui_widget_t *, pd_context_t *, - ui_widget_actual_style_t *); -typedef struct ui_widget_prototype_t ui_widget_prototype_t; - -typedef struct ui_widget_rules_t { - /** - * Suspend update if the current widget is not visible or is - * completely covered by other widgets - */ - LCUI_BOOL only_on_visible; - - /** - * First update the children in the visible area - * If your widget has a lot of children and you want to see the - * children who are currently seeing the priority update, we recommend - * enabling this rule. - */ - LCUI_BOOL first_update_visible_children; - - /** - * Cache the stylesheets of children to improve the query speed of - * the stylesheet. - * If this rule is enabled, we recommend that you manually call - * ui_widget_generate_hash() to generate a hash value for the children - * of the widget. - */ - LCUI_BOOL cache_children_style; - - /** Refresh the style of all child widgets if the status has changed */ - LCUI_BOOL ignore_status_change; - - /** Refresh the style of all child widgets if the classes has changed */ - LCUI_BOOL ignore_classes_change; - - /** - * Maximum number of children updated at each update - * values: - * 0 - Update all children at once - * -1 - Automatically calculates the appropriate maximum number - * N - Custom maximum number - */ - int max_update_children_count; - - /** Limit the number of children rendered */ - unsigned max_render_children_count; - - /** A callback function on update progress */ - void (*on_update_progress)(ui_widget_t *, size_t); -} ui_widget_rules_t; - -typedef struct ui_widget_update_t { - /** Should update for self? */ - LCUI_BOOL for_self; - - /** Should update for children? */ - LCUI_BOOL for_children; - - /** Should skip the property sync of bound surface? */ - LCUI_BOOL skip_surface_props_sync; - - /** States of tasks */ - LCUI_BOOL states[UI_TASK_TOTAL_NUM]; -} ui_widget_update_t; - -typedef struct ui_profile_t { - long time; - size_t update_count; - size_t refresh_count; - size_t layout_count; - size_t user_task_count; - size_t destroy_count; - size_t destroy_time; -} ui_profile_t; - -struct ui_widget_prototype_t { - char *name; - ui_widget_function_t init; - ui_widget_function_t refresh; - ui_widget_function_t destroy; - ui_widget_function_t update; - ui_widget_task_handler_t runtask; - ui_widget_attr_setter_t setattr; - ui_widget_text_setter_t settext; - ui_widget_size_getter_t autosize; - ui_widget_size_setter_t resize; - ui_widget_painter_t paint; - ui_widget_prototype_t *proto; -}; - -typedef struct ui_widget_data_entry_t { - void *data; - ui_widget_prototype_t *proto; -} ui_widget_data_entry_t; - -typedef struct ui_widget_data_t { - unsigned length; - ui_widget_data_entry_t *list; -} ui_widget_data_t; - -// Event begin - -typedef enum ui_event_type_t { - UI_EVENT_NONE, - UI_EVENT_LINK, - UI_EVENT_UNLINK, - UI_EVENT_READY, - UI_EVENT_DESTROY, - UI_EVENT_FOCUS, - UI_EVENT_BLUR, - UI_EVENT_AFTERLAYOUT, - UI_EVENT_KEYDOWN, - UI_EVENT_KEYUP, - UI_EVENT_KEYPRESS, - UI_EVENT_TEXTINPUT, - - UI_EVENT_MOUSEOVER, - UI_EVENT_MOUSEMOVE, - UI_EVENT_MOUSEOUT, - UI_EVENT_MOUSEDOWN, - UI_EVENT_MOUSEUP, - UI_EVENT_WHEEL, - UI_EVENT_CLICK, - UI_EVENT_DBLCLICK, - UI_EVENT_TOUCH, - UI_EVENT_TOUCHDOWN, - UI_EVENT_TOUCHUP, - UI_EVENT_TOUCHMOVE, - UI_EVENT_PASTE, - - UI_EVENT_FONT_FACE_LOAD, - UI_EVENT_USER -} ui_event_type_t; - -/** - * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent - */ -typedef struct ui_keyboard_event_t { - int code; - LCUI_BOOL alt_key; - LCUI_BOOL ctrl_key; - LCUI_BOOL shift_key; - LCUI_BOOL meta_key; - LCUI_BOOL is_composing; -} ui_keyboard_event_t; - -typedef struct ui_touch_point_t { - float x; - float y; - int id; - int state; - LCUI_BOOL is_primary; -} ui_touch_point_t; - -typedef struct ui_touch_event_t { - unsigned n_points; - ui_touch_point_t *points; -} ui_touch_event_t; - -typedef struct ui_paint_event_t { - pd_rect_t rect; -} ui_paint_event_t; - -typedef struct ui_textinput_event_t { - wchar_t *text; - size_t length; -} ui_textinput_event_t; - -/** - * @see https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent - */ -typedef struct ui_mouse_event_t { - float x; - float y; - int button; -} ui_mouse_event_t; - -typedef enum ui_wheel_delta_mode_t { - UI_WHEEL_DELTA_PIXEL = 0, - UI_WHEEL_DELTA_LINE, - UI_WHEEL_DELTA_PAGE -} ui_wheel_delta_mode_t; - -/** - * @see https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent - */ -typedef struct ui_wheel_event_t { - int delta_x; - int delta_y; - int delta_z; - int delta_mode; -} ui_wheel_event_t; - -typedef struct ui_event_t ui_event_t; -typedef void (*ui_event_handler_t)(ui_widget_t *, ui_event_t *, void *); -typedef void (*ui_event_arg_destructor_t)(void *); - -struct ui_event_t { - uint32_t type; /**< 事件类型标识号 */ - void *data; /**< 附加数据 */ - ui_widget_t *target; /**< 触发事件的部件 */ - LCUI_BOOL cancel_bubble; /**< 是否取消事件冒泡 */ - union { - ui_mouse_event_t mouse; - ui_wheel_event_t wheel; - ui_keyboard_event_t key; - ui_touch_event_t touch; - ui_textinput_event_t text; - }; -}; - -// Event end - -// MutationObserver begin - -typedef list_t ui_mutation_list_t; -typedef struct ui_mutation_observer_t ui_mutation_observer_t; - -typedef enum ui_mutation_record_type_t { - UI_MUTATION_RECORD_TYPE_NONE, - UI_MUTATION_RECORD_TYPE_ATTRIBUTES, - UI_MUTATION_RECORD_TYPE_PROPERTIES, - UI_MUTATION_RECORD_TYPE_CHILD_LIST, -} ui_mutation_record_type_t; - -typedef struct ui_mutation_record_t { - ui_mutation_record_type_t type; - ui_widget_t *target; - list_t added_widgets; - list_t removed_widgets; - char *attribute_name; - char *property_name; -} ui_mutation_record_t; - -typedef void (*ui_mutation_observer_callback_t)(ui_mutation_list_t *, - ui_mutation_observer_t *, - void *); - -/** - * @see https://developer.mozilla.org/en-US/docs/Web/API/MutationObserverInit - */ -typedef struct ui_mutation_observer_init_t { - LCUI_BOOL child_list; - LCUI_BOOL subtree; - LCUI_BOOL properties; - LCUI_BOOL attributes; -} ui_mutation_observer_init_t; - -LCUI_API ui_mutation_record_t *ui_mutation_record_create( - ui_widget_t *widget, ui_mutation_record_type_t type); - -LCUI_API ui_mutation_record_t *ui_mutation_record_duplicate( - ui_mutation_record_t *source); - -LCUI_API void ui_mutation_record_destroy(ui_mutation_record_t *mutation); - -/** - * @see https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver - */ -LCUI_API ui_mutation_observer_t *ui_mutation_observer_create( - ui_mutation_observer_callback_t callback, void *callback_arg); - -LCUI_API int ui_mutation_observer_observe(ui_mutation_observer_t *observer, - ui_widget_t *w, - ui_mutation_observer_init_t options); - -LCUI_API void ui_mutation_observer_disconnect(ui_mutation_observer_t *observer); -LCUI_API void ui_mutation_observer_destroy(ui_mutation_observer_t *observer); -LCUI_API void ui_process_mutation_observers(void); -LCUI_API void ui_mutation_observer_add_record(ui_mutation_observer_t *observer, - ui_mutation_record_t *record); - -// MutationObserver end - -typedef struct ui_widget_extra_data_t { - ui_widget_listeners_t listeners; - list_t observer_connections; - ui_widget_rules_t rules; - size_t default_max_update_count; - size_t update_progress; - dict_t *style_cache; -} ui_widget_extra_data_t; - -struct ui_widget_t { - unsigned hash; - ui_widget_state_t state; - - char *id; - char *type; - int tab_index; - strlist_t classes; - strlist_t status; - wchar_t *title; - dict_t *attributes; - LCUI_BOOL disabled; - LCUI_BOOL event_blocked; - - /** - * Coordinates calculated by the layout system - * The position of the rectangular boxes is calculated based on it - */ - float layout_x, layout_y; - - /** - * A box’s “ideal” size in a given axis when given infinite available - * space. See more: https://drafts.csswg.org/css-sizing-3/#max-content - */ - float max_content_width, max_content_height; - - /** See more: - * https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model */ - ui_rect_t content_box; - ui_rect_t padding_box; - ui_rect_t border_box; - ui_rect_t canvas_box; - ui_rect_t outer_box; - - css_style_decl_t *custom_style; - const css_style_decl_t *matched_style; - css_computed_style_t specified_style; - css_computed_style_t computed_style; - - /** Some data bound to the prototype */ - ui_widget_data_t data; - ui_widget_extra_data_t *extra; - - /** - * Prototype chain - * It is used to implement the inheritance of widgets, - * Just like prototype chain in JavaScript - */ - const ui_widget_prototype_t *proto; - - ui_widget_update_t update; - - ui_rect_t dirty_rect; - ui_dirty_rect_type_t dirty_rect_type; - LCUI_BOOL has_child_dirty_rect; - - /** Parent widget */ - ui_widget_t *parent; - - /** List of child widgets */ - list_t children; - - /** - * List of child widgets in descending order by z-index - * @see - *https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context - **/ - list_t stacking_context; - - /** - * Position in the parent->children - * this == list_get(&this->parent->children, this.index) - */ - size_t index; - - /** - * Node in the parent->children - * &this->node == list_get_node(&this->parent->children, this.index) - */ - list_node_t node; - - /** Node in the parent->children_shoa */ - list_node_t node_show; -}; - -// Base - -LCUI_API void ui_init(void); -LCUI_API void ui_destroy(void); -LCUI_API int ui_dispatch_event(ui_event_t *e); -LCUI_API void ui_process_events(void); - -// Metrics - -LCUI_API ui_metrics_t ui_metrics; - -INLINE int ui_compute(float value) -{ - return (int)(ui_metrics.scale * value); -} - -INLINE void ui_compute_rect(pd_rect_t *actual_rect, const ui_rect_t *rect) -{ - actual_rect->x = ui_compute(rect->x); - actual_rect->y = ui_compute(rect->y); - actual_rect->width = ui_compute(rect->width); - actual_rect->height = ui_compute(rect->height); -} - -/** 设置密度 */ -LCUI_API void ui_set_density(float density); - -/** 设置缩放密度 */ -LCUI_API void ui_set_scaled_density(float density); - -/** 设置密度等级 */ -LCUI_API void ui_set_density_level(ui_density_Level_t level); - -/** 设置缩放密度等级 */ -LCUI_API void ui_set_scaled_density_level(ui_density_Level_t level); - -/** 设置 DPI */ -LCUI_API void ui_set_dpi(float dpi); - -/** 设置全局缩放比例 */ -LCUI_API void ui_set_scale(float scale); - -// Base - -LCUI_API ui_widget_t *ui_create_widget(const char *type); -LCUI_API ui_widget_t *ui_create_widget_with_prototype( - const ui_widget_prototype_t *proto); -LCUI_API void ui_widget_destroy(ui_widget_t *w); -LCUI_API void ui_widget_set_title(ui_widget_t *w, const wchar_t *title); -LCUI_API void ui_widget_set_text(ui_widget_t *w, const char *text); -LCUI_API void ui_widget_get_offset(ui_widget_t *w, ui_widget_t *parent, - float *offset_x, float *offset_y); -LCUI_API LCUI_BOOL ui_widget_in_viewport(ui_widget_t *w); - -// Root - -LCUI_API ui_widget_t *ui_root(void); -LCUI_API int ui_root_append(ui_widget_t *w); - -// Id - -LCUI_API ui_widget_t *ui_get_widget(const char *id); -LCUI_API int ui_widget_set_id(ui_widget_t *w, const char *idstr); - -// Prototype - -LCUI_API ui_widget_prototype_t *ui_create_widget_prototype( - const char *name, const char *parent_name); -LCUI_API ui_widget_prototype_t *ui_get_widget_prototype(const char *name); -LCUI_API LCUI_BOOL ui_check_widget_type(ui_widget_t *w, const char *type); -LCUI_API LCUI_BOOL -ui_check_widget_prototype(ui_widget_t *w, const ui_widget_prototype_t *proto); -LCUI_API void *ui_widget_get_data(ui_widget_t *widget, - ui_widget_prototype_t *proto); -LCUI_API void *ui_widget_add_data(ui_widget_t *widget, - ui_widget_prototype_t *proto, - size_t data_size); - -// Extra Data - -LCUI_API ui_widget_extra_data_t *ui_create_extra_data(ui_widget_t *widget); - -INLINE ui_widget_extra_data_t *ui_widget_use_extra_data(ui_widget_t *widget) -{ - return widget->extra ? widget->extra : ui_create_extra_data(widget); -} - -// Attributes - -LCUI_API int ui_widget_set_attribute_ex(ui_widget_t *w, const char *name, - void *value, int value_type, - void (*value_destructor)(void *)); -LCUI_API int ui_widget_set_attribute(ui_widget_t *w, const char *name, - const char *value); -LCUI_API const char *ui_widget_get_attribute_value(ui_widget_t *w, - const char *name); - -// Classes - -LCUI_API int ui_widget_add_class(ui_widget_t *w, const char *class_name); -LCUI_API LCUI_BOOL ui_widget_has_class(ui_widget_t *w, const char *class_name); -LCUI_API int ui_widget_remove_class(ui_widget_t *w, const char *class_name); - -// Status - -LCUI_API int ui_widget_add_status(ui_widget_t *w, const char *status_name); -LCUI_API LCUI_BOOL ui_widget_has_status(ui_widget_t *w, - const char *status_name); -LCUI_API int ui_widget_remove_status(ui_widget_t *w, const char *status_name); -LCUI_API void ui_widget_update_status(ui_widget_t *widget); -LCUI_API void ui_widget_set_disabled(ui_widget_t *w, LCUI_BOOL disabled); - -// Tree - -LCUI_API void ui_widget_remove(ui_widget_t *w); -LCUI_API void ui_widget_empty(ui_widget_t *w); -LCUI_API int ui_widget_append(ui_widget_t *parent, ui_widget_t *widget); -LCUI_API int ui_widget_prepend(ui_widget_t *parent, ui_widget_t *widget); -LCUI_API int ui_widget_unwrap(ui_widget_t *widget); -LCUI_API int ui_widget_unlink(ui_widget_t *w); -LCUI_API ui_widget_t *ui_widget_prev(ui_widget_t *w); -LCUI_API ui_widget_t *ui_widget_next(ui_widget_t *w); -LCUI_API ui_widget_t *ui_widget_get_child(ui_widget_t *w, size_t index); -LCUI_API size_t ui_widget_each(ui_widget_t *w, - void (*callback)(ui_widget_t *, void *), - void *arg); -LCUI_API ui_widget_t *ui_widget_at(ui_widget_t *widget, int ix, int iy); -LCUI_API void ui_print_tree(ui_widget_t *w); - -// Style -LCUI_API void ui_widget_get_style(ui_widget_t *w, int key, - css_style_value_t *value); -LCUI_API void ui_widget_set_style(ui_widget_t *w, int key, - const css_style_value_t *value); -LCUI_API int ui_widget_unset_style(ui_widget_t *w, int key); -LCUI_API css_selector_node_t *ui_widget_create_selector_node(ui_widget_t *w); -LCUI_API css_selector_t *ui_widget_create_selector(ui_widget_t *w); -LCUI_API size_t ui_widget_get_children_style_changes(ui_widget_t *w, int type, - const char *name); -LCUI_API void ui_widget_print_stylesheet(ui_widget_t *w); -LCUI_API size_t ui_widget_get_children_style_changes(ui_widget_t *w, int type, - const char *name); -LCUI_API void ui_widget_update_children_style(ui_widget_t *w); -LCUI_API void ui_widget_refresh_children_style(ui_widget_t *w); -LCUI_API int ui_widget_set_style_string(ui_widget_t *w, const char *property, - const char *css_text); -LCUI_API void ui_widget_set_style_unit_value(ui_widget_t *w, int key, - css_numeric_value_t value, - css_unit_t unit); -LCUI_API void ui_widget_set_style_keyword_value(ui_widget_t *w, int key, - css_keyword_value_t value); -LCUI_API void ui_widget_set_style_color_value(ui_widget_t *w, int key, - css_color_value_t value); -LCUI_API void ui_widget_set_style_numeric_value(ui_widget_t *w, int key, - css_numeric_value_t value); -LCUI_API void ui_widget_compute_style(ui_widget_t *w); -LCUI_API void ui_widget_force_update_style(ui_widget_t *w); -LCUI_API void ui_widget_force_refresh_style(ui_widget_t *w); - -// Updater - -LCUI_API size_t ui_widget_update(ui_widget_t *w); -LCUI_API size_t ui_update(void); -LCUI_API void ui_refresh_style(void); - -// Helper - -LCUI_API LCUI_BOOL ui_widget_is_visible(ui_widget_t *w); -LCUI_API void ui_widget_move(ui_widget_t *w, float left, float top); -LCUI_API void ui_widget_resize(ui_widget_t *w, float width, float height); -LCUI_API void ui_widget_show(ui_widget_t *w); -LCUI_API void ui_widget_hide(ui_widget_t *w); -LCUI_API ui_widget_t *ui_widget_get_closest(ui_widget_t *w, const char *type); -LCUI_API dict_t *ui_widget_collect_references(ui_widget_t *w); - -// Hash - -LCUI_API void ui_widget_generate_self_hash(ui_widget_t *widget); -LCUI_API void ui_widget_generate_hash(ui_widget_t *w); -LCUI_API size_t ui_widget_export_hash(ui_widget_t *w, unsigned *hash_list, - size_t len); -LCUI_API size_t ui_widget_import_hash(ui_widget_t *w, unsigned *hash_list, - size_t maxlen); - -// Layout - -/** - * 执行布局前的准备操作 - * 重置布局相关属性,以让它们在布局时被重新计算 - * @param rule 父级组件所使用的布局规则 - */ -LCUI_API void ui_widget_prepare_reflow(ui_widget_t *w, ui_layout_rule_t rule); - -LCUI_API void ui_widget_reset_size(ui_widget_t *w); - -LCUI_API void ui_widget_reflow(ui_widget_t *w); - -// Renderer - -LCUI_API LCUI_BOOL ui_widget_mark_dirty_rect(ui_widget_t *w, ui_rect_t *in_rect, - ui_box_type_t box_type); -LCUI_API size_t ui_widget_get_dirty_rects(ui_widget_t *w, list_t *rects); -LCUI_API size_t ui_widget_render(ui_widget_t *w, pd_context_t *paint); - -// Updater - -LCUI_API void ui_widget_set_rules(ui_widget_t *w, - const ui_widget_rules_t *rules); -LCUI_API void ui_widget_add_task_for_children(ui_widget_t *widget, - ui_task_type_t task); -LCUI_API void ui_widget_add_task(ui_widget_t *widget, int task); - -INLINE void ui_widget_refresh_style(ui_widget_t *w) -{ - ui_widget_add_task(w, UI_TASK_REFRESH_STYLE); -} - -INLINE void ui_widget_update_style(ui_widget_t *w) -{ - ui_widget_add_task(w, UI_TASK_UPDATE_STYLE); -} - -// Observer -LCUI_API LCUI_BOOL ui_widget_has_observer(ui_widget_t *widget, - ui_mutation_record_type_t type); - -LCUI_API int ui_widget_add_mutation_recrod(ui_widget_t *widget, - ui_mutation_record_t *record); - -// Logger - -LCUI_API int ui_logger_log(logger_level_e level, ui_widget_t *w, - const char *fmt, ...); - -#define ui_debug(W, ...) ui_logger_log(LOGGER_LEVEL_DEBUG, W, ##__VA_ARGS__) - -// Events - -/** 设置阻止部件及其子级部件的事件 */ -INLINE void ui_widget_block_event(ui_widget_t *w, LCUI_BOOL block) -{ - w->event_blocked = block; -} - -/** 触发事件,让事件处理器在主循环中调用 */ -LCUI_API int ui_widget_post_event(ui_widget_t *w, const ui_event_t *e, - void *arg, - ui_event_arg_destructor_t destroy_arg); - -/** 触发事件,直接调用事件处理器 */ -LCUI_API int ui_widget_emit_event(ui_widget_t *w, ui_event_t e, void *arg); - -/** 自动分配一个可用的事件标识号 */ -LCUI_API int ui_alloc_event_id(void); - -/** 设置与事件标识号对应的名称 */ -LCUI_API int ui_set_event_id(int event_id, const char *event_name); - -/** 获取与事件标识号对应的名称 */ -LCUI_API const char *ui_get_event_name(int event_id); - -/** 获取与事件名称对应的标识号 */ -LCUI_API int ui_get_event_id(const char *event_name); - -LCUI_API void ui_event_init(ui_event_t *e, const char *name); - -LCUI_API void ui_event_destroy(ui_event_t *e); - -/** - * 添加部件事件绑定 - * @param[in] widget 目标部件 - * @param[in] event_id 事件标识号 - * @param[in] handler 事件处理函数 - * @param[in] data 事件处理函数的附加数据 - * @param[in] destroy_arg 数据的销毁函数 - * @return 成功则返回 0,失败返回负数 - */ -LCUI_API ui_event_listener_t *ui_widget_add_event_listener( - ui_widget_t *widget, int event_id, ui_event_handler_t handler, void *data, - void (*destroy_arg)(void *)); - -/** - * 解除部件事件绑定 - * @param[in] widget 目标部件 - * @param[in] event_name 事件名称 - * @param[in] handler 与事件绑定的函数 - * @return 成功则返回 0,失败返回负数 - */ -LCUI_API int ui_widget_remove_event_listener(ui_widget_t *w, int event_id, - ui_event_handler_t handler, - void *data); - -/** - * 添加部件事件绑定 - * @param[in] widget 目标部件 - * @param[in] event_name 事件名称 - * @param[in] handler 事件处理函数 - * @param[in] data 事件处理函数的附加数据 - * @param[in] destroy_arg 数据的销毁函数 - * @return 返回已移除的事件监听器数量 - */ -LCUI_API ui_event_listener_t *ui_widget_on(ui_widget_t *widget, - const char *event_name, - ui_event_handler_t handler, - void *data, - void (*destroy_arg)(void *)); - -/** - * 解除部件事件绑定 - * @param[in] widget 目标部件 - * @param[in] event_name 事件名称 - * @param[in] handler 与事件绑定的函数 - * @return 成功则返回 0,失败返回负数 - */ -LCUI_API int ui_widget_off(ui_widget_t *widget, const char *event_name, - ui_event_handler_t handler, void *data); - -INLINE int ui_emit_event(ui_event_t e, void *arg) -{ - return ui_widget_emit_event(ui_root(), e, arg); -} - -INLINE int ui_post_event(const ui_event_t *e, void *arg, - ui_event_arg_destructor_t destroy_arg) -{ - return ui_widget_post_event(ui_root(), e, arg, destroy_arg); -} - -INLINE ui_event_listener_t *ui_add_event_listener( - ui_widget_t *widget, int event_id, ui_event_handler_t handler, void *arg, - ui_event_arg_destructor_t destroy_arg) -{ - return ui_widget_add_event_listener(ui_root(), event_id, handler, arg, - destroy_arg); -} - -INLINE int ui_remove_event_listener(ui_widget_t *w, int event_id, - ui_event_handler_t handler, void *data) -{ - return ui_widget_remove_event_listener(ui_root(), event_id, handler, - data); -} - -INLINE ui_event_listener_t *ui_on_event(const char *event_name, - ui_event_handler_t handler, void *data, - void (*destroy_arg)(void *)) -{ - return ui_widget_on(ui_root(), event_name, handler, data, destroy_arg); -} - -INLINE int ui_off_event(const char *event_name, ui_event_handler_t handler, - void *data) -{ - return ui_widget_off(ui_root(), event_name, handler, data); -} - -/** 清除事件对象,通常在部件销毁时调用该函数,以避免部件销毁后还有事件发送给它 - */ -LCUI_API void ui_clear_event_target(ui_widget_t *widget); - -/** get current focused widget */ -LCUI_API ui_widget_t *ui_get_focus(void); - -/** 将一个部件设置为焦点 */ -LCUI_API int ui_set_focus(ui_widget_t *widget); - -/** 停止部件的事件传播 */ -LCUI_API int ui_widget_stop_event_propagation(ui_widget_t *widget); - -/** 为部件设置鼠标捕获,设置后将捕获全局范围内的鼠标事件 */ -LCUI_API void ui_widget_set_mouse_capture(ui_widget_t *w); - -/** 为部件解除鼠标捕获 */ -LCUI_API void ui_widget_release_mouse_capture(ui_widget_t *w); - -/** - * 为部件设置触点捕获,设置后将捕获全局范围内的触点事件 - * @param[in] w 部件 - * @param[in] point_id 触点ID,当值为 -1 时则捕获全部触点 - * @returns 设置成功返回 0,如果其它部件已经捕获该触点则返回 -1 - */ -LCUI_API int ui_widget_set_touch_capture(ui_widget_t *w, int point_id); - -/** - * 为部件解除触点捕获 - * @param[in] w 部件 - * @param[in] point_id 触点ID,当值为 -1 时则解除全部触点的捕获 - */ -LCUI_API int ui_widget_release_touch_capture(ui_widget_t *w, int point_id); - -LCUI_API void ui_widget_destroy_listeners(ui_widget_t *w); - -// CSS - -LCUI_API int ui_load_css_file(const char *filepath); -LCUI_API size_t ui_load_css_string(const char *str, const char *space); - -// Image Loader - -#define ui_image_on_event ui_image_add_event_listener -#define ui_image_off_event ui_image_remove_event_listener - -typedef struct ui_image_t ui_image_t; -typedef void (*ui_image_event_handler_t)(ui_image_t *, void *); - -LCUI_API void ui_init_image_loader(void); -LCUI_API void ui_destroy_image_loader(void); -LCUI_API void ui_process_image_events(void); -LCUI_API ui_image_t *ui_load_image(const char *path); -LCUI_API pd_canvas_t *ui_image_get_data(ui_image_t *image); -LCUI_API const char *ui_image_get_path(ui_image_t *image); -LCUI_API void ui_image_add_ref(ui_image_t *image); -LCUI_API void ui_image_remove_ref(ui_image_t *image); -LCUI_API int ui_image_add_event_listener(ui_image_t *image, - ui_image_event_handler_t handler, - void *data); -LCUI_API int ui_image_remove_event_listener(ui_image_t *image, - ui_image_event_handler_t handler, - void *data); - -// CSS Font Style - -#define UI_DEFAULT_FONT_SIZE 14 -#define UI_DEFAULT_FONT_COLOR 0xff333333 -#define UI_MIN_FONT_SIZE 12 -#define UI_LINE_HEIGHT_SCALE 1.42857143 - -typedef struct ui_text_style_t { - int font_size; - int line_height; - int *font_ids; - char *font_family; - wchar_t *content; - pd_color_t color; - uint8_t font_style; - uint8_t font_weight; - uint8_t text_align; - uint8_t white_space; - uint8_t word_break; -} ui_text_style_t; - -LCUI_API void ui_text_style_init(ui_text_style_t *fs); - -LCUI_API void ui_text_style_destroy(ui_text_style_t *fs); - -LCUI_API LCUI_BOOL ui_text_style_is_equal(const ui_text_style_t *a, - const ui_text_style_t *b); - -LCUI_API void ui_compute_text_style(ui_text_style_t *fs, - const css_computed_style_t *ss); - -// Rect - -LCUI_API void ui_convert_rect(const pd_rect_t *rect, ui_rect_t *rectf, - float scale); - -LCUI_API LCUI_BOOL ui_rect_correct(ui_rect_t *rect, float container_width, - float container_height); - -INLINE LCUI_BOOL ui_rect_has_point(ui_rect_t *rect, float x, float y) -{ - return x >= rect->x && y >= rect->y && x < rect->x + rect->width && - y < rect->y + rect->height; -} - -INLINE LCUI_BOOL ui_rect_is_equal(const ui_rect_t *a, const ui_rect_t *b) -{ - return (int)(100 * (a->x - b->x)) == 0 && - (int)(100 * (a->y - b->y)) == 0 && - (int)(100 * (a->width - b->width)) == 0 && - (int)(100 * (a->height - b->height)) == 0; -} - -LCUI_API LCUI_BOOL ui_rect_is_cover(const ui_rect_t *a, const ui_rect_t *b); - -INLINE LCUI_BOOL ui_rect_is_include(ui_rect_t *a, ui_rect_t *b) -{ - return (b->x >= a->x && b->x + b->width <= a->x + a->width && - b->y >= a->y && b->y + b->height <= a->y + a->height); -} - -LCUI_API LCUI_BOOL ui_rect_overlap(const ui_rect_t *a, const ui_rect_t *b, - ui_rect_t *overlapping_rect); - -LCUI_API void ui_rect_merge(ui_rect_t *merged_rect, const ui_rect_t *a, - const ui_rect_t *b); - -LCUI_END_HEADER +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #endif diff --git a/lib/ui/include/ui/base.h b/lib/ui/include/ui/base.h new file mode 100644 index 000000000..e42f646a8 --- /dev/null +++ b/lib/ui/include/ui/base.h @@ -0,0 +1,141 @@ +#ifndef LIB_UI_INCLUDE_UI_BASE_H +#define LIB_UI_INCLUDE_UI_BASE_H + +#include "common.h" +#include "types.h" + +LIBUI_BEGIN_DECLS + +LIBUI_PUBLIC void ui_init(void); +LIBUI_PUBLIC void ui_destroy(void); +LIBUI_PUBLIC int ui_dispatch_event(ui_event_t *e); +LIBUI_PUBLIC void ui_process_events(void); + +LIBUI_PUBLIC ui_widget_t *ui_create_widget(const char *type); +LIBUI_PUBLIC ui_widget_t *ui_create_widget_with_prototype( + const ui_widget_prototype_t *proto); +LIBUI_PUBLIC void ui_widget_destroy(ui_widget_t *w); +LIBUI_PUBLIC void ui_widget_set_title(ui_widget_t *w, const wchar_t *title); +LIBUI_PUBLIC void ui_widget_set_text(ui_widget_t *w, const char *text); +LIBUI_PUBLIC void ui_widget_get_offset(ui_widget_t *w, ui_widget_t *parent, + float *offset_x, float *offset_y); +LIBUI_PUBLIC bool ui_widget_in_viewport(ui_widget_t *w); + +// Root + +LIBUI_PUBLIC ui_widget_t *ui_root(void); +LIBUI_PUBLIC int ui_root_append(ui_widget_t *w); + +// Id + +LIBUI_PUBLIC ui_widget_t *ui_get_widget(const char *id); +LIBUI_PUBLIC int ui_widget_set_id(ui_widget_t *w, const char *idstr); + +// Extra Data + +LIBUI_PUBLIC ui_widget_extra_data_t *ui_create_extra_data(ui_widget_t *widget); + +LIBUI_INLINE ui_widget_extra_data_t *ui_widget_use_extra_data(ui_widget_t *widget) +{ + return widget->extra ? widget->extra : ui_create_extra_data(widget); +} + +// Attributes + +LIBUI_PUBLIC int ui_widget_set_attribute_ex(ui_widget_t *w, const char *name, + void *value, int value_type, + void (*value_destructor)(void *)); +LIBUI_PUBLIC int ui_widget_set_attribute(ui_widget_t *w, const char *name, + const char *value); +LIBUI_PUBLIC const char *ui_widget_get_attribute_value(ui_widget_t *w, + const char *name); + +// Classes + +LIBUI_PUBLIC int ui_widget_add_class(ui_widget_t *w, const char *class_name); +LIBUI_PUBLIC bool ui_widget_has_class(ui_widget_t *w, const char *class_name); +LIBUI_PUBLIC int ui_widget_remove_class(ui_widget_t *w, const char *class_name); + +// Status + +LIBUI_PUBLIC int ui_widget_add_status(ui_widget_t *w, const char *status_name); +LIBUI_PUBLIC bool ui_widget_has_status(ui_widget_t *w, const char *status_name); +LIBUI_PUBLIC int ui_widget_remove_status(ui_widget_t *w, + const char *status_name); +LIBUI_PUBLIC void ui_widget_update_status(ui_widget_t *widget); +LIBUI_PUBLIC void ui_widget_set_disabled(ui_widget_t *w, bool disabled); + +// Tree + +LIBUI_PUBLIC void ui_widget_remove(ui_widget_t *w); +LIBUI_PUBLIC void ui_widget_empty(ui_widget_t *w); +LIBUI_PUBLIC int ui_widget_append(ui_widget_t *parent, ui_widget_t *widget); +LIBUI_PUBLIC int ui_widget_prepend(ui_widget_t *parent, ui_widget_t *widget); +LIBUI_PUBLIC int ui_widget_unwrap(ui_widget_t *widget); +LIBUI_PUBLIC int ui_widget_unlink(ui_widget_t *w); +LIBUI_PUBLIC ui_widget_t *ui_widget_prev(ui_widget_t *w); +LIBUI_PUBLIC ui_widget_t *ui_widget_next(ui_widget_t *w); +LIBUI_PUBLIC ui_widget_t *ui_widget_get_child(ui_widget_t *w, size_t index); +LIBUI_PUBLIC size_t ui_widget_each(ui_widget_t *w, + void (*callback)(ui_widget_t *, void *), + void *arg); +LIBUI_PUBLIC ui_widget_t *ui_widget_at(ui_widget_t *widget, int ix, int iy); +LIBUI_PUBLIC void ui_print_tree(ui_widget_t *w); + +// Helper + +LIBUI_PUBLIC bool ui_widget_is_visible(ui_widget_t *w); +LIBUI_PUBLIC void ui_widget_move(ui_widget_t *w, float left, float top); +LIBUI_PUBLIC void ui_widget_resize(ui_widget_t *w, float width, float height); +LIBUI_PUBLIC void ui_widget_show(ui_widget_t *w); +LIBUI_PUBLIC void ui_widget_hide(ui_widget_t *w); +LIBUI_PUBLIC ui_widget_t *ui_widget_get_closest(ui_widget_t *w, + const char *type); +LIBUI_PUBLIC dict_t *ui_widget_collect_references(ui_widget_t *w); + +// Layout + +/** + * 执行布局前的准备操作 + * 重置布局相关属性,以让它们在布局时被重新计算 + * @param rule 父级组件所使用的布局规则 + */ +LIBUI_PUBLIC void ui_widget_prepare_reflow(ui_widget_t *w, + ui_layout_rule_t rule); + +LIBUI_PUBLIC void ui_widget_reset_size(ui_widget_t *w); + +LIBUI_PUBLIC void ui_widget_reflow(ui_widget_t *w); + +// Renderer + +LIBUI_PUBLIC bool ui_widget_mark_dirty_rect(ui_widget_t *w, ui_rect_t *in_rect, + ui_box_type_t box_type); +LIBUI_PUBLIC size_t ui_widget_get_dirty_rects(ui_widget_t *w, list_t *rects); +LIBUI_PUBLIC size_t ui_widget_render(ui_widget_t *w, pd_context_t *paint); + +// Updater + +LIBUI_PUBLIC size_t ui_widget_update(ui_widget_t *w); +LIBUI_PUBLIC size_t ui_update(void); +LIBUI_PUBLIC void ui_refresh_style(void); + +LIBUI_PUBLIC void ui_widget_set_rules(ui_widget_t *w, + const ui_widget_rules_t *rules); +LIBUI_PUBLIC void ui_widget_add_task_for_children(ui_widget_t *widget, + ui_task_type_t task); +LIBUI_PUBLIC void ui_widget_add_task(ui_widget_t *widget, int task); + +LIBUI_INLINE void ui_widget_refresh_style(ui_widget_t *w) +{ + ui_widget_add_task(w, UI_TASK_REFRESH_STYLE); +} + +LIBUI_INLINE void ui_widget_update_style(ui_widget_t *w) +{ + ui_widget_add_task(w, UI_TASK_UPDATE_STYLE); +} + +LIBUI_END_DECLS + +#endif diff --git a/lib/ui/include/ui/common.h b/lib/ui/include/ui/common.h new file mode 100644 index 000000000..37c331193 --- /dev/null +++ b/lib/ui/include/ui/common.h @@ -0,0 +1,44 @@ +#ifndef LIB_UI_INCLUDE_UI_COMMON_H +#define LIB_UI_INCLUDE_UI_COMMON_H + +#include "config.h" + +#ifdef __cplusplus +#define LIBUI_BEGIN_DECLS extern "C" { +#define LIBUI_END_DECLS } +#else +#define LIBUI_BEGIN_DECLS +#define LIBUI_END_DECLS +#endif + +#ifndef LIBUI_PUBLIC +#if defined(_MSC_VER) && !defined(LIBUI_STATIC_BUILD) +#ifdef LIBUI_DLL_EXPORT +#define LIBUI_PUBLIC __declspec(dllexport) +#else +#define LIBUI_PUBLIC __declspec(dllimport) +#endif +#elif __GNUC__ >= 4 +#define LIBUI_PUBLIC extern __attribute__((visibility("default"))) +#else +#define LIBUI_PUBLIC extern +#endif +#endif + +#if defined(_WIN32) && !defined(__cplusplus) +#define LIBUI_INLINE __inline +#else +#define LIBUI_INLINE static inline +#endif + +#ifdef DEBUG +#define DEBUG_MSG _DEBUG_MSG +#else +#define DEBUG_MSG(format, ...) +#endif + +#define _DEBUG_MSG(format, ...) \ + logger_log(LOGGER_LEVEL_DEBUG, __FILE__ ":%d: %s(): " format, \ + __LINE__, __FUNCTION__, ##__VA_ARGS__) + +#endif diff --git a/lib/ui/include/ui/css.h b/lib/ui/include/ui/css.h new file mode 100644 index 000000000..1f91b28b3 --- /dev/null +++ b/lib/ui/include/ui/css.h @@ -0,0 +1,12 @@ +#ifndef LIB_UI_INCLUDE_UI_CSS_H +#define LIB_UI_INCLUDE_UI_CSS_H + +#include "common.h" + +LIBUI_END_DECLS + +LIBUI_PUBLIC int ui_load_css_file(const char *filepath); +LIBUI_PUBLIC size_t ui_load_css_string(const char *str, const char *space); + +LIBUI_END_DECLS +#endif diff --git a/lib/ui/include/ui/events.h b/lib/ui/include/ui/events.h new file mode 100644 index 000000000..88538d9e2 --- /dev/null +++ b/lib/ui/include/ui/events.h @@ -0,0 +1,144 @@ +#ifndef LIB_UI_INCLUDE_UI_EVENTS_H +#define LIB_UI_INCLUDE_UI_EVENTS_H + +#include "common.h" +#include "types.h" + +LIBUI_BEGIN_DECLS + +/** 设置阻止部件及其子级部件的事件 */ +LIBUI_INLINE void ui_widget_block_event(ui_widget_t *w, bool block) +{ + w->event_blocked = block; +} + +/** 触发事件,让事件处理器在主循环中调用 */ +LIBUI_PUBLIC int ui_widget_post_event(ui_widget_t *w, const ui_event_t *e, + void *arg, + ui_event_arg_destructor_t destroy_arg); + +/** 触发事件,直接调用事件处理器 */ +LIBUI_PUBLIC int ui_widget_emit_event(ui_widget_t *w, ui_event_t e, void *arg); + +/** 自动分配一个可用的事件标识号 */ +LIBUI_PUBLIC int ui_alloc_event_id(void); + +/** 设置与事件标识号对应的名称 */ +LIBUI_PUBLIC int ui_set_event_id(int event_id, const char *event_name); + +/** 获取与事件标识号对应的名称 */ +LIBUI_PUBLIC const char *ui_get_event_name(int event_id); + +/** 获取与事件名称对应的标识号 */ +LIBUI_PUBLIC int ui_get_event_id(const char *event_name); + +LIBUI_PUBLIC void ui_event_init(ui_event_t *e, const char *name); + +LIBUI_PUBLIC void ui_event_destroy(ui_event_t *e); + +/** + * 添加部件事件绑定 + * @param[in] widget 目标部件 + * @param[in] event_id 事件标识号 + * @param[in] handler 事件处理函数 + * @param[in] data 事件处理函数的附加数据 + * @param[in] destroy_arg 数据的销毁函数 + * @return 成功则返回 0,失败返回负数 + */ +LIBUI_PUBLIC ui_event_listener_t *ui_widget_add_event_listener( + ui_widget_t *widget, int event_id, ui_event_handler_t handler, void *data, + void (*destroy_arg)(void *)); + +/** + * 解除部件事件绑定 + * @param[in] widget 目标部件 + * @param[in] event_name 事件名称 + * @param[in] handler 与事件绑定的函数 + * @return 成功则返回 0,失败返回负数 + */ +LIBUI_PUBLIC int ui_widget_remove_event_listener(ui_widget_t *w, int event_id, + ui_event_handler_t handler, + void *data); + +/** + * 添加部件事件绑定 + * @param[in] widget 目标部件 + * @param[in] event_name 事件名称 + * @param[in] handler 事件处理函数 + * @param[in] data 事件处理函数的附加数据 + * @param[in] destroy_arg 数据的销毁函数 + * @return 返回已移除的事件监听器数量 + */ +LIBUI_PUBLIC ui_event_listener_t *ui_widget_on(ui_widget_t *widget, + const char *event_name, + ui_event_handler_t handler, + void *data, + void (*destroy_arg)(void *)); + +/** + * 解除部件事件绑定 + * @param[in] widget 目标部件 + * @param[in] event_name 事件名称 + * @param[in] handler 与事件绑定的函数 + * @return 成功则返回 0,失败返回负数 + */ +LIBUI_PUBLIC int ui_widget_off(ui_widget_t *widget, const char *event_name, + ui_event_handler_t handler, void *data); + +LIBUI_PUBLIC int ui_emit_event(ui_event_t e, void *arg); + +LIBUI_PUBLIC int ui_post_event(const ui_event_t *e, void *arg, + ui_event_arg_destructor_t destroy_arg); + +LIBUI_PUBLIC ui_event_listener_t *ui_add_event_listener( + ui_widget_t *widget, int event_id, ui_event_handler_t handler, void *arg, + ui_event_arg_destructor_t destroy_arg); + +LIBUI_PUBLIC int ui_remove_event_listener(ui_widget_t *w, int event_id, + ui_event_handler_t handler, + void *data); + +LIBUI_PUBLIC ui_event_listener_t *ui_on_event(const char *event_name, + ui_event_handler_t handler, + void *data, + void (*destroy_arg)(void *)); +LIBUI_PUBLIC int ui_off_event(const char *event_name, + ui_event_handler_t handler, void *data); + +/** 清除事件对象,通常在部件销毁时调用该函数,以避免部件销毁后还有事件发送给它 + */ +LIBUI_PUBLIC void ui_clear_event_target(ui_widget_t *widget); + +/** get current focused widget */ +LIBUI_PUBLIC ui_widget_t *ui_get_focus(void); + +/** 将一个部件设置为焦点 */ +LIBUI_PUBLIC int ui_set_focus(ui_widget_t *widget); + +/** 停止部件的事件传播 */ +LIBUI_PUBLIC int ui_widget_stop_event_propagation(ui_widget_t *widget); + +/** 为部件设置鼠标捕获,设置后将捕获全局范围内的鼠标事件 */ +LIBUI_PUBLIC void ui_widget_set_mouse_capture(ui_widget_t *w); + +/** 为部件解除鼠标捕获 */ +LIBUI_PUBLIC void ui_widget_release_mouse_capture(ui_widget_t *w); + +/** + * 为部件设置触点捕获,设置后将捕获全局范围内的触点事件 + * @param[in] w 部件 + * @param[in] point_id 触点ID,当值为 -1 时则捕获全部触点 + * @returns 设置成功返回 0,如果其它部件已经捕获该触点则返回 -1 + */ +LIBUI_PUBLIC int ui_widget_set_touch_capture(ui_widget_t *w, int point_id); + +/** + * 为部件解除触点捕获 + * @param[in] w 部件 + * @param[in] point_id 触点ID,当值为 -1 时则解除全部触点的捕获 + */ +LIBUI_PUBLIC int ui_widget_release_touch_capture(ui_widget_t *w, int point_id); + +LIBUI_END_DECLS + +#endif diff --git a/lib/ui/include/ui/hash.h b/lib/ui/include/ui/hash.h new file mode 100644 index 000000000..5500c6e70 --- /dev/null +++ b/lib/ui/include/ui/hash.h @@ -0,0 +1,18 @@ +#ifndef LIB_UI_INCLUDE_UI_HASH_H +#define LIB_UI_INCLUDE_UI_HASH_H + +#include "common.h" +#include "types.h" + +LIBUI_BEGIN_DECLS + +LIBUI_PUBLIC void ui_widget_generate_self_hash(ui_widget_t *widget); +LIBUI_PUBLIC void ui_widget_generate_hash(ui_widget_t *w); +LIBUI_PUBLIC size_t ui_widget_export_hash(ui_widget_t *w, unsigned *hash_list, + size_t len); +LIBUI_PUBLIC size_t ui_widget_import_hash(ui_widget_t *w, unsigned *hash_list, + size_t maxlen); + +LIBUI_END_DECLS + +#endif diff --git a/lib/ui/include/ui/image.h b/lib/ui/include/ui/image.h new file mode 100644 index 000000000..58dbc1dd3 --- /dev/null +++ b/lib/ui/include/ui/image.h @@ -0,0 +1,48 @@ +#ifndef LIB_UI_INCLUDE_UI_IMAGE_H +#define LIB_UI_INCLUDE_UI_IMAGE_H + +#include "common.h" +#include "types.h" + +#define ui_image_on_event ui_image_add_event_listener +#define ui_image_off_event ui_image_remove_event_listener + +typedef struct ui_image_t ui_image_t; +typedef void (*ui_image_event_handler_t)(ui_image_t *, void *); + +LIBUI_BEGIN_DECLS + +/** + * 创建 UIImage 对象,从指定路径加载数据 + * 注意:UIImage 对象的数据不会被立刻加载 + **/ +LIBUI_PUBLIC ui_image_t *ui_image_create(const char *path); + +/** + * 获取已加载的图像数据 + */ +LIBUI_PUBLIC pd_canvas_t *ui_image_get_data(ui_image_t *image); + +LIBUI_PUBLIC const char *ui_image_get_path(ui_image_t *image); +LIBUI_PUBLIC void ui_image_destroy(ui_image_t *image); +LIBUI_PUBLIC int ui_image_add_event_listener(ui_image_t *image, + ui_image_event_handler_t handler, + void *data); +LIBUI_PUBLIC int ui_image_remove_event_listener( + ui_image_t *image, ui_image_event_handler_t handler, void *data); + +/** + * 为所有 UIImage 对象加载数据 + * 注意:该函数应在 UI 线程外调用 + **/ +LIBUI_PUBLIC void ui_load_images(void); + +/** + * 处理 UIImage 的事件 + * 注意:该函数应在 UI 线程内调用 + */ +LIBUI_PUBLIC void ui_process_image_events(void); + +LIBUI_END_DECLS + +#endif diff --git a/lib/ui/include/ui/logger.h b/lib/ui/include/ui/logger.h new file mode 100644 index 000000000..bacaeea06 --- /dev/null +++ b/lib/ui/include/ui/logger.h @@ -0,0 +1,16 @@ +#ifndef LIB_UI_INCLUDE_UI_LOGGER_H +#define LIB_UI_INCLUDE_UI_LOGGER_H + +#include "common.h" +#include "types.h" + +LIBUI_BEGIN_DECLS + +LIBUI_PUBLIC int ui_logger_log(logger_level_e level, ui_widget_t *w, + const char *fmt, ...); + +#define ui_debug(W, ...) ui_logger_log(LOGGER_LEVEL_DEBUG, W, ##__VA_ARGS__) + +LIBUI_END_DECLS + +#endif diff --git a/lib/ui/include/ui/metrics.h b/lib/ui/include/ui/metrics.h new file mode 100644 index 000000000..fd5d07dfd --- /dev/null +++ b/lib/ui/include/ui/metrics.h @@ -0,0 +1,44 @@ +#ifndef LIB_UI_INCLUDE_UI_METRICS_H +#define LIB_UI_INCLUDE_UI_METRICS_H + +#include "common.h" +#include "types.h" + +LIBUI_BEGIN_DECLS + +LIBUI_PUBLIC ui_metrics_t ui_metrics; + +LIBUI_INLINE int ui_compute(float value) +{ + return (int)(ui_metrics.scale * value); +} + +LIBUI_INLINE void ui_compute_rect(pd_rect_t *actual_rect, const ui_rect_t *rect) +{ + actual_rect->x = ui_compute(rect->x); + actual_rect->y = ui_compute(rect->y); + actual_rect->width = ui_compute(rect->width); + actual_rect->height = ui_compute(rect->height); +} + +/** 设置密度 */ +LIBUI_PUBLIC void ui_set_density(float density); + +/** 设置缩放密度 */ +LIBUI_PUBLIC void ui_set_scaled_density(float density); + +/** 设置密度等级 */ +LIBUI_PUBLIC void ui_set_density_level(ui_density_Level_t level); + +/** 设置缩放密度等级 */ +LIBUI_PUBLIC void ui_set_scaled_density_level(ui_density_Level_t level); + +/** 设置 DPI */ +LIBUI_PUBLIC void ui_set_dpi(float dpi); + +/** 设置全局缩放比例 */ +LIBUI_PUBLIC void ui_set_scale(float scale); + +LIBUI_END_DECLS + +#endif diff --git a/lib/ui/include/ui/mutation_observer.h b/lib/ui/include/ui/mutation_observer.h new file mode 100644 index 000000000..1e39c186e --- /dev/null +++ b/lib/ui/include/ui/mutation_observer.h @@ -0,0 +1,70 @@ +#ifndef LIB_UI_INCLUDE_UI_MUTATION_OBSERVER_H +#define LIB_UI_INCLUDE_UI_MUTATION_OBSERVER_H + +#include "common.h" +#include "types.h" + +LIBUI_BEGIN_DECLS + +typedef list_t ui_mutation_list_t; +typedef struct ui_mutation_observer_t ui_mutation_observer_t; + +typedef enum ui_mutation_record_type_t { + UI_MUTATION_RECORD_TYPE_NONE, + UI_MUTATION_RECORD_TYPE_ATTRIBUTES, + UI_MUTATION_RECORD_TYPE_PROPERTIES, + UI_MUTATION_RECORD_TYPE_CHILD_LIST, +} ui_mutation_record_type_t; + +typedef struct ui_mutation_record_t { + ui_mutation_record_type_t type; + ui_widget_t *target; + list_t added_widgets; + list_t removed_widgets; + char *attribute_name; + char *property_name; +} ui_mutation_record_t; + +typedef void (*ui_mutation_observer_callback_t)(ui_mutation_list_t *, + ui_mutation_observer_t *, + void *); + +/** + * @see https://developer.mozilla.org/en-US/docs/Web/API/MutationObserverInit + */ +typedef struct ui_mutation_observer_init_t { + bool child_list; + bool subtree; + bool properties; + bool attributes; +} ui_mutation_observer_init_t; + +LIBUI_PUBLIC ui_mutation_record_t *ui_mutation_record_create( + ui_widget_t *widget, ui_mutation_record_type_t type); + +LIBUI_PUBLIC ui_mutation_record_t *ui_mutation_record_duplicate( + ui_mutation_record_t *source); + +LIBUI_PUBLIC void ui_mutation_record_destroy(ui_mutation_record_t *mutation); + +/** + * @see https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver + */ +LIBUI_PUBLIC ui_mutation_observer_t *ui_mutation_observer_create( + ui_mutation_observer_callback_t callback, void *callback_arg); + +LIBUI_PUBLIC int ui_mutation_observer_observe( + ui_mutation_observer_t *observer, ui_widget_t *w, + ui_mutation_observer_init_t options); + +LIBUI_PUBLIC void ui_mutation_observer_disconnect( + ui_mutation_observer_t *observer); +LIBUI_PUBLIC void ui_mutation_observer_destroy( + ui_mutation_observer_t *observer); +LIBUI_PUBLIC void ui_process_mutation_observers(void); +LIBUI_PUBLIC void ui_mutation_observer_add_record( + ui_mutation_observer_t *observer, ui_mutation_record_t *record); + +LIBUI_END_DECLS + +#endif diff --git a/lib/ui/include/ui/prototype.h b/lib/ui/include/ui/prototype.h new file mode 100644 index 000000000..ece9afa66 --- /dev/null +++ b/lib/ui/include/ui/prototype.h @@ -0,0 +1,23 @@ +#ifndef LIB_UI_INCLUDE_UI_PROTOTYPE_H +#define LIB_UI_INCLUDE_UI_PROTOTYPE_H + +#include "common.h" +#include "types.h" + +LIBUI_BEGIN_DECLS + +LIBUI_PUBLIC ui_widget_prototype_t *ui_create_widget_prototype( + const char *name, const char *parent_name); +LIBUI_PUBLIC ui_widget_prototype_t *ui_get_widget_prototype(const char *name); +LIBUI_PUBLIC bool ui_check_widget_type(ui_widget_t *w, const char *type); +LIBUI_PUBLIC bool ui_check_widget_prototype(ui_widget_t *w, + const ui_widget_prototype_t *proto); +LIBUI_PUBLIC void *ui_widget_get_data(ui_widget_t *widget, + ui_widget_prototype_t *proto); +LIBUI_PUBLIC void *ui_widget_add_data(ui_widget_t *widget, + ui_widget_prototype_t *proto, + size_t data_size); + +LIBUI_END_DECLS + +#endif diff --git a/lib/ui/include/ui/rect.h b/lib/ui/include/ui/rect.h new file mode 100644 index 000000000..f94a2ffa1 --- /dev/null +++ b/lib/ui/include/ui/rect.h @@ -0,0 +1,45 @@ +#ifndef LIB_UI_INCLUDE_UI_RECT_H +#define LIB_UI_INCLUDE_UI_RECT_H + +#include "common.h" +#include "types.h" + +LIBUI_BEGIN_DECLS + +LIBUI_PUBLIC void ui_convert_rect(const pd_rect_t *rect, ui_rect_t *rectf, + float scale); + +LIBUI_PUBLIC bool ui_rect_correct(ui_rect_t *rect, float container_width, + float container_height); + +LIBUI_INLINE bool ui_rect_has_point(ui_rect_t *rect, float x, float y) +{ + return x >= rect->x && y >= rect->y && x < rect->x + rect->width && + y < rect->y + rect->height; +} + +LIBUI_INLINE bool ui_rect_is_equal(const ui_rect_t *a, const ui_rect_t *b) +{ + return (int)(100 * (a->x - b->x)) == 0 && + (int)(100 * (a->y - b->y)) == 0 && + (int)(100 * (a->width - b->width)) == 0 && + (int)(100 * (a->height - b->height)) == 0; +} + +LIBUI_PUBLIC bool ui_rect_is_cover(const ui_rect_t *a, const ui_rect_t *b); + +LIBUI_INLINE bool ui_rect_is_include(ui_rect_t *a, ui_rect_t *b) +{ + return (b->x >= a->x && b->x + b->width <= a->x + a->width && + b->y >= a->y && b->y + b->height <= a->y + a->height); +} + +LIBUI_PUBLIC bool ui_rect_overlap(const ui_rect_t *a, const ui_rect_t *b, + ui_rect_t *overlapping_rect); + +LIBUI_PUBLIC void ui_rect_merge(ui_rect_t *merged_rect, const ui_rect_t *a, + const ui_rect_t *b); + +LIBUI_END_DECLS + +#endif diff --git a/lib/ui/include/ui/style.h b/lib/ui/include/ui/style.h new file mode 100644 index 000000000..65404a5dd --- /dev/null +++ b/lib/ui/include/ui/style.h @@ -0,0 +1,40 @@ +#ifndef LIB_UI_INCLUDE_UI_STYLE_H +#define LIB_UI_INCLUDE_UI_STYLE_H + +#include "common.h" +#include "types.h" + +#include + +LIBUI_BEGIN_DECLS + +LIBUI_PUBLIC void ui_widget_get_style(ui_widget_t *w, int key, + css_style_value_t *value); +LIBUI_PUBLIC void ui_widget_set_style(ui_widget_t *w, int key, + const css_style_value_t *value); +LIBUI_PUBLIC int ui_widget_unset_style(ui_widget_t *w, int key); +LIBUI_PUBLIC css_selector_node_t *ui_widget_create_selector_node( + ui_widget_t *w); +LIBUI_PUBLIC css_selector_t *ui_widget_create_selector(ui_widget_t *w); +LIBUI_PUBLIC void ui_widget_print_stylesheet(ui_widget_t *w); +LIBUI_PUBLIC void ui_widget_update_children_style(ui_widget_t *w); +LIBUI_PUBLIC void ui_widget_refresh_children_style(ui_widget_t *w); +LIBUI_PUBLIC int ui_widget_set_style_string(ui_widget_t *w, + const char *property, + const char *css_text); +LIBUI_PUBLIC void ui_widget_set_style_unit_value(ui_widget_t *w, int key, + css_numeric_value_t value, + css_unit_t unit); +LIBUI_PUBLIC void ui_widget_set_style_keyword_value(ui_widget_t *w, int key, + css_keyword_value_t value); +LIBUI_PUBLIC void ui_widget_set_style_color_value(ui_widget_t *w, int key, + css_color_value_t value); +LIBUI_PUBLIC void ui_widget_set_style_numeric_value(ui_widget_t *w, int key, + css_numeric_value_t value); +LIBUI_PUBLIC void ui_widget_compute_style(ui_widget_t *w); +LIBUI_PUBLIC void ui_widget_force_update_style(ui_widget_t *w); +LIBUI_PUBLIC void ui_widget_force_refresh_style(ui_widget_t *w); + +LIBUI_END_DECLS + +#endif diff --git a/lib/ui/include/ui/text_style.h b/lib/ui/include/ui/text_style.h new file mode 100644 index 000000000..0cd988bfd --- /dev/null +++ b/lib/ui/include/ui/text_style.h @@ -0,0 +1,42 @@ +#ifndef LIB_UI_INCLUDE_UI_TEXT_STYLE_H +#define LIB_UI_INCLUDE_UI_TEXT_STYLE_H + +#include "common.h" +#include "types.h" + +#include + +LIBUI_BEGIN_DECLS + +#define UI_DEFAULT_FONT_SIZE 14 +#define UI_DEFAULT_FONT_COLOR 0xff333333 +#define UI_MIN_FONT_SIZE 12 +#define UI_LINE_HEIGHT_SCALE 1.42857143 + +typedef struct ui_text_style_t { + int font_size; + int line_height; + int *font_ids; + char *font_family; + wchar_t *content; + pd_color_t color; + uint8_t font_style; + uint8_t font_weight; + uint8_t text_align; + uint8_t white_space; + uint8_t word_break; +} ui_text_style_t; + +LIBUI_PUBLIC void ui_text_style_init(ui_text_style_t *fs); + +LIBUI_PUBLIC void ui_text_style_destroy(ui_text_style_t *fs); + +LIBUI_PUBLIC bool ui_text_style_is_equal(const ui_text_style_t *a, + const ui_text_style_t *b); + +LIBUI_PUBLIC void ui_compute_text_style(ui_text_style_t *fs, + const css_computed_style_t *ss); + +LIBUI_END_DECLS + +#endif diff --git a/lib/ui/include/ui/types.h b/lib/ui/include/ui/types.h new file mode 100644 index 000000000..d7835220d --- /dev/null +++ b/lib/ui/include/ui/types.h @@ -0,0 +1,435 @@ +#ifndef LIB_UI_INCLUDE_UI_TPYES_H +#define LIB_UI_INCLUDE_UI_TPYES_H + +#include +#include +#include +#include + +typedef struct ui_rect_t { + float x, y, width, height; +} ui_rect_t; + +typedef struct ui_area_t { + float left, top, right, bottom; +} ui_area_t; + +typedef css_metrics_t ui_metrics_t; + +typedef enum ui_density_Level_t { + UI_DENSITY_LEVEL_SMALL, + UI_DENSITY_LEVEL_NORMAL, + UI_DENSITY_LEVEL_LARGE, + UI_DENSITY_LEVEL_BIG +} ui_density_Level_t; + +typedef enum ui_sizing_rule_t { + UI_SIZING_RULE_NONE, + UI_SIZING_RULE_FIXED, + UI_SIZING_RULE_FILL, + UI_SIZING_RULE_PERCENT, + UI_SIZING_RULE_FIT_CONTENT +} ui_sizing_rule_t; + +typedef enum ui_layout_rule_t { + UI_LAYOUT_RULE_AUTO, + UI_LAYOUT_RULE_MAX_CONTENT, + UI_LAYOUT_RULE_FIXED_WIDTH = 0b11, + UI_LAYOUT_RULE_FIXED_HEIGHT = 0b101, + UI_LAYOUT_RULE_FIXED = 0b111 +} ui_layout_rule_t; + +typedef enum ui_widget_state_t { + UI_WIDGET_STATE_CREATED = 0, + UI_WIDGET_STATE_UPDATED, + UI_WIDGET_STATE_LAYOUTED, + UI_WIDGET_STATE_READY, + UI_WIDGET_STATE_NORMAL, + UI_WIDGET_STATE_DELETED, +} ui_widget_state_t; + +typedef enum ui_box_type_t { + UI_BOX_TYPE_CONTENT_BOX, + UI_BOX_TYPE_PADDING_BOX, + UI_BOX_TYPE_BORDER_BOX, + UI_BOX_TYPE_GRAPH_BOX +} ui_box_type_t; + +typedef enum ui_dirty_rect_type_t { + UI_DIRTY_RECT_TYPE_NONE, + UI_DIRTY_RECT_TYPE_CUSTOM, + UI_DIRTY_RECT_TYPE_PADDING_BOX, + UI_DIRTY_RECT_TYPE_BORDER_BOX, + UI_DIRTY_RECT_TYPE_CANVAS_BOX +} ui_dirty_rect_type_t; + +typedef struct ui_border_style_t_ { + struct { + int style; + float width; + pd_color_t color; + } top, right, bottom, left; + float top_left_radius; + float top_right_radius; + float bottom_left_radius; + float bottom_right_radius; +} ui_border_style_t; + +typedef struct ui_widget_attribute_t_ { + char *name; + struct { + int type; + void (*destructor)(void *); + union { + char *string; + void *data; + }; + } value; +} ui_widget_attribute_t; + +typedef struct ui_widget_actual_style_t_ { + float x, y; + pd_rect_t canvas_box; + pd_rect_t border_box; + pd_rect_t padding_box; + pd_rect_t content_box; +} ui_widget_actual_style_t; + +typedef enum ui_task_type_t { + UI_TASK_REFRESH_STYLE, + UI_TASK_UPDATE_STYLE, + UI_TASK_REFLOW, + UI_TASK_USER, + UI_TASK_TOTAL_NUM +} ui_task_type_t; + +typedef struct ui_event_listener_t ui_event_listener_t; +typedef struct ui_widget_t ui_widget_t; +typedef list_t ui_widget_listeners_t; + +typedef void (*ui_widget_function_t)(ui_widget_t *); +typedef void (*ui_widget_task_handler_t)(ui_widget_t *, int); +typedef void (*ui_widget_size_getter_t)(ui_widget_t *, float *, float *, + ui_layout_rule_t); +typedef void (*ui_widget_size_setter_t)(ui_widget_t *, float, float); +typedef void (*ui_widget_attr_setter_t)(ui_widget_t *, const char *, + const char *); +typedef void (*ui_widget_text_setter_t)(ui_widget_t *, const char *); +typedef void (*ui_widget_painter_t)(ui_widget_t *, pd_context_t *, + ui_widget_actual_style_t *); +typedef struct ui_widget_prototype_t ui_widget_prototype_t; + +typedef struct ui_widget_rules_t { + /** + * Suspend update if the current widget is not visible or is + * completely covered by other widgets + */ + bool only_on_visible; + + /** + * First update the children in the visible area + * If your widget has a lot of children and you want to see the + * children who are currently seeing the priority update, we recommend + * enabling this rule. + */ + bool first_update_visible_children; + + /** + * Cache the stylesheets of children to improve the query speed of + * the stylesheet. + * If this rule is enabled, we recommend that you manually call + * ui_widget_generate_hash() to generate a hash value for the children + * of the widget. + */ + bool cache_children_style; + + /** Refresh the style of all child widgets if the status has changed */ + bool ignore_status_change; + + /** Refresh the style of all child widgets if the classes has changed */ + bool ignore_classes_change; + + /** + * Maximum number of children updated at each update + * values: + * 0 - Update all children at once + * -1 - Automatically calculates the appropriate maximum number + * N - Custom maximum number + */ + int max_update_children_count; + + /** Limit the number of children rendered */ + unsigned max_render_children_count; + + /** A callback function on update progress */ + void (*on_update_progress)(ui_widget_t *, size_t); +} ui_widget_rules_t; + +typedef struct ui_widget_update_t { + /** Should update for self? */ + bool for_self; + + /** Should update for children? */ + bool for_children; + + /** Should skip the property sync of bound surface? */ + bool skip_surface_props_sync; + + /** States of tasks */ + bool states[UI_TASK_TOTAL_NUM]; +} ui_widget_update_t; + +typedef struct ui_profile_t { + long time; + size_t update_count; + size_t refresh_count; + size_t layout_count; + size_t user_task_count; + size_t destroy_count; + size_t destroy_time; +} ui_profile_t; + +struct ui_widget_prototype_t { + char *name; + ui_widget_function_t init; + ui_widget_function_t refresh; + ui_widget_function_t destroy; + ui_widget_function_t update; + ui_widget_task_handler_t runtask; + ui_widget_attr_setter_t setattr; + ui_widget_text_setter_t settext; + ui_widget_size_getter_t autosize; + ui_widget_size_setter_t resize; + ui_widget_painter_t paint; + ui_widget_prototype_t *proto; +}; + +typedef struct ui_widget_data_entry_t { + void *data; + ui_widget_prototype_t *proto; +} ui_widget_data_entry_t; + +typedef struct ui_widget_data_t { + unsigned length; + ui_widget_data_entry_t *list; +} ui_widget_data_t; + +// Event begin + +typedef enum ui_event_type_t { + UI_EVENT_NONE, + UI_EVENT_LINK, + UI_EVENT_UNLINK, + UI_EVENT_READY, + UI_EVENT_DESTROY, + UI_EVENT_FOCUS, + UI_EVENT_BLUR, + UI_EVENT_AFTERLAYOUT, + UI_EVENT_KEYDOWN, + UI_EVENT_KEYUP, + UI_EVENT_KEYPRESS, + UI_EVENT_TEXTINPUT, + + UI_EVENT_MOUSEOVER, + UI_EVENT_MOUSEMOVE, + UI_EVENT_MOUSEOUT, + UI_EVENT_MOUSEDOWN, + UI_EVENT_MOUSEUP, + UI_EVENT_WHEEL, + UI_EVENT_CLICK, + UI_EVENT_DBLCLICK, + UI_EVENT_TOUCH, + UI_EVENT_TOUCHDOWN, + UI_EVENT_TOUCHUP, + UI_EVENT_TOUCHMOVE, + UI_EVENT_PASTE, + + UI_EVENT_FONT_FACE_LOAD, + UI_EVENT_USER +} ui_event_type_t; + +typedef enum ui_mouse_button_code_t { + UI_MOUSE_BUTTON_MAIN, + UI_MOUSE_BUTTON_AUXILIARY, + UI_MOUSE_BUTTON_SECNODARY, + UI_MOUSE_BUTTON_FORTH_BUTTON, + UI_MOUSE_BUTTON_FIFTH_BUTTON +} ui_mouse_button_code_t; + +#define UI_MOUSE_BUTTON_LEFT UI_MOUSE_BUTTON_MAIN +#define UI_MOUSE_BUTTON_MIDDLE UI_MOUSE_BUTTON_AUXILIARY +#define UI_MOUSE_BUTTON_WHEEL UI_MOUSE_BUTTON_AUXILIARY +#define UI_MOUSE_BUTTON_RIGHT UI_MOUSE_BUTTON_SECNODARY + +/** + * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent + */ +typedef struct ui_keyboard_event_t { + int code; + bool alt_key; + bool ctrl_key; + bool shift_key; + bool meta_key; + bool is_composing; +} ui_keyboard_event_t; + +typedef struct ui_touch_point_t { + float x; + float y; + int id; + int state; + bool is_primary; +} ui_touch_point_t; + +typedef struct ui_touch_event_t { + unsigned n_points; + ui_touch_point_t *points; +} ui_touch_event_t; + +typedef struct ui_paint_event_t { + pd_rect_t rect; +} ui_paint_event_t; + +typedef struct ui_textinput_event_t { + wchar_t *text; + size_t length; +} ui_textinput_event_t; + +/** + * @see https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent + */ +typedef struct ui_mouse_event_t { + float x; + float y; + int button; +} ui_mouse_event_t; + +typedef enum ui_wheel_delta_mode_t { + UI_WHEEL_DELTA_PIXEL = 0, + UI_WHEEL_DELTA_LINE, + UI_WHEEL_DELTA_PAGE +} ui_wheel_delta_mode_t; + +/** + * @see https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent + */ +typedef struct ui_wheel_event_t { + int delta_x; + int delta_y; + int delta_z; + int delta_mode; +} ui_wheel_event_t; + +typedef struct ui_event_t ui_event_t; +typedef void (*ui_event_handler_t)(ui_widget_t *, ui_event_t *, void *); +typedef void (*ui_event_arg_destructor_t)(void *); + +struct ui_event_t { + uint32_t type; /**< 事件类型标识号 */ + void *data; /**< 附加数据 */ + ui_widget_t *target; /**< 触发事件的部件 */ + bool cancel_bubble; /**< 是否取消事件冒泡 */ + union { + ui_mouse_event_t mouse; + ui_wheel_event_t wheel; + ui_keyboard_event_t key; + ui_touch_event_t touch; + ui_textinput_event_t text; + }; +}; + +typedef struct ui_widget_extra_data_t { + ui_widget_listeners_t listeners; + list_t observer_connections; + ui_widget_rules_t rules; + size_t default_max_update_count; + size_t update_progress; + dict_t *style_cache; +} ui_widget_extra_data_t; + +struct ui_widget_t { + unsigned hash; + ui_widget_state_t state; + + char *id; + char *type; + int tab_index; + strlist_t classes; + strlist_t status; + wchar_t *title; + dict_t *attributes; + bool disabled; + bool event_blocked; + + /** + * Coordinates calculated by the layout system + * The position of the rectangular boxes is calculated based on it + */ + float layout_x, layout_y; + + /** + * A box’s “ideal” size in a given axis when given infinite available + * space. See more: https://drafts.csswg.org/css-sizing-3/#max-content + */ + float max_content_width, max_content_height; + + /** See more: + * https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model */ + ui_rect_t content_box; + ui_rect_t padding_box; + ui_rect_t border_box; + ui_rect_t canvas_box; + ui_rect_t outer_box; + + css_style_decl_t *custom_style; + const css_style_decl_t *matched_style; + css_computed_style_t specified_style; + css_computed_style_t computed_style; + + /** Some data bound to the prototype */ + ui_widget_data_t data; + ui_widget_extra_data_t *extra; + + /** + * Prototype chain + * It is used to implement the inheritance of widgets, + * Just like prototype chain in JavaScript + */ + const ui_widget_prototype_t *proto; + + ui_widget_update_t update; + + ui_rect_t dirty_rect; + ui_dirty_rect_type_t dirty_rect_type; + bool has_child_dirty_rect; + + /** Parent widget */ + ui_widget_t *parent; + + /** List of child widgets */ + list_t children; + + /** + * List of child widgets in descending order by z-index + * @see + *https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context + **/ + list_t stacking_context; + + /** + * Position in the parent->children + * this == list_get(&this->parent->children, this.index) + */ + size_t index; + + /** + * Node in the parent->children + * &this->node == list_get_node(&this->parent->children, this.index) + */ + list_node_t node; + + /** Node in the parent->children_shoa */ + list_node_t node_show; +}; + +#endif diff --git a/lib/ui/src/config.h.in b/lib/ui/src/config.h.in new file mode 100644 index 000000000..8948e1bba --- /dev/null +++ b/lib/ui/src/config.h.in @@ -0,0 +1,5 @@ +#define LIBUI_VERSION "${VERSION}" +#define LIBUI_VERSION_MAJOR ${VERSION_MAJOR} +#define LIBUI_VERSION_MINOR ${VERSION_MINOR} +#define LIBUI_VERSION_ALTER ${VERSION_ALTER} +${define LIBUI_STATIC_BUILD} diff --git a/lib/ui/src/internal.h b/lib/ui/src/internal.h deleted file mode 100644 index 3b9bba47b..000000000 --- a/lib/ui/src/internal.h +++ /dev/null @@ -1,230 +0,0 @@ -#include -#include "../include/ui.h" -#include "./ui_debug.h" - -typedef struct ui_mutation_connection_t { - ui_widget_t *widget; - ui_mutation_observer_t *observer; - ui_mutation_observer_init_t options; - list_node_t node; -} ui_mutation_connection_t; - -// Metrics - -void ui_init_metrics(void); - -// Prototype - -void ui_init_widget_prototype(void); -void ui_destroy_widget_prototype(void); -void ui_widget_destroy_prototype(ui_widget_t *widget); - -// Root - -void ui_init_root(void); -void ui_destroy_root(void); - -// Base - -void ui_widget_add_state(ui_widget_t *w, ui_widget_state_t state); - -// Trash - -size_t ui_trash_clear(void); -void ui_trash_add(ui_widget_t *w); - -// Id - -int ui_widget_destroy_id(ui_widget_t *w); -void ui_init_widget_id(void); -void ui_destroy_widget_id(void); - -// Attributes - -void ui_widget_destroy_attributes(ui_widget_t *w); - -// Classes - -void ui_widget_destroy_classes(ui_widget_t *w); - -// Status - -void ui_widget_destroy_status(ui_widget_t *w); - -// Background - -void ui_widget_paint_background(ui_widget_t *w, pd_context_t *paint, - ui_widget_actual_style_t *style); - -// Border - -void ui_widget_paint_border(ui_widget_t *w, pd_context_t *paint, - ui_widget_actual_style_t *style); -void ui_widget_crop_content(ui_widget_t *w, pd_context_t *paint, - ui_widget_actual_style_t *style); - -// Box Shadow - -void ui_widget_paint_box_shadow(ui_widget_t *w, pd_context_t *paint, - ui_widget_actual_style_t *style); - -// Box - -void ui_widget_update_box_position(ui_widget_t *w); -void ui_widget_update_canvas_box(ui_widget_t *w); -void ui_widget_update_box_size(ui_widget_t *w); -void ui_widget_set_content_box_size(ui_widget_t *w, float width, float height); - -// Diff - -/** for check widget difference */ -typedef struct ui_widget_style_diff_t_ { - css_computed_style_t style; - ui_rect_t content_box; - ui_rect_t padding_box; - ui_rect_t border_box; - ui_rect_t canvas_box; - ui_rect_t outer_box; - LCUI_BOOL visible; - LCUI_BOOL should_add_dirty_rect; -} ui_style_diff_t; - -typedef struct ui_layout_diff_t_ { - LCUI_BOOL should_add_dirty_rect; - ui_rect_t content_box; - ui_rect_t padding_box; - ui_rect_t border_box; - ui_rect_t canvas_box; - ui_rect_t outer_box; -} ui_layout_diff_t; - -typedef struct ui_layout_item_t { - ui_widget_t *widget; - ui_layout_diff_t diff; -} ui_layout_item_t; - -void ui_style_diff_init(ui_style_diff_t *diff, ui_widget_t *w); -void ui_style_diff_begin(ui_style_diff_t *diff, ui_widget_t *w); -void ui_style_diff_end(ui_style_diff_t *diff, ui_widget_t *w); -void ui_layout_diff_begin(ui_layout_diff_t *diff, ui_widget_t *w); -void ui_layout_diff_auto_reflow(ui_layout_diff_t *diff, ui_widget_t *w); -void ui_layout_diff_end(ui_layout_diff_t *diff, ui_widget_t *w); - -// Layout - -void ui_block_layout_reflow(ui_widget_t *w, ui_layout_rule_t rule); -void ui_flexbox_layout_reflow(ui_widget_t *w, ui_layout_rule_t rule); - -// Updater - -void ui_init_updater(void); - -// Events - -/** 初始化 LCUI 部件的事件系统 */ -void ui_init_events(void); - -/** 销毁(释放) LCUI 部件的事件系统的相关资源 */ -void ui_destroy_events(void); - -// Style - -INLINE float padding_x(ui_widget_t *w) -{ - return w->computed_style.padding_left + w->computed_style.padding_right; -} - -INLINE float padding_y(ui_widget_t *w) -{ - return w->computed_style.padding_top + w->computed_style.padding_bottom; -} - -INLINE float border_x(ui_widget_t *w) -{ - return w->computed_style.border_left_width + - w->computed_style.border_right_width; -} - -INLINE float border_y(ui_widget_t *w) -{ - return w->computed_style.border_top_width + - w->computed_style.border_bottom_width; -} - -INLINE float margin_x(ui_widget_t *w) -{ - return w->computed_style.margin_left + w->computed_style.margin_right; -} - -INLINE float margin_y(ui_widget_t *w) -{ - return w->computed_style.margin_top + w->computed_style.margin_bottom; -} - -INLINE float to_border_box_width(ui_widget_t *w, float content_width) -{ - return content_width + padding_x(w) + border_x(w); -} - -INLINE float to_border_box_height(ui_widget_t *w, float content_height) -{ - return content_height + padding_y(w) + border_y(w); -} - -INLINE LCUI_BOOL ui_widget_is_inline(ui_widget_t *w) -{ - return w->computed_style.type_bits.display == - CSS_DISPLAY_INLINE_BLOCK || - w->computed_style.type_bits.display == CSS_DISPLAY_INLINE_FLEX; -} - -INLINE LCUI_BOOL ui_widget_has_absolute_position(ui_widget_t *w) -{ - return css_computed_position(&w->computed_style) == - CSS_POSITION_ABSOLUTE; -} - -INLINE LCUI_BOOL ui_widget_in_layout_flow(ui_widget_t *w) -{ - return css_computed_display(&w->computed_style) != CSS_DISPLAY_NONE && - !ui_widget_has_absolute_position(w); -} - -INLINE LCUI_BOOL ui_widget_has_block_display(ui_widget_t *w) -{ - return css_computed_display(&w->computed_style) == CSS_DISPLAY_BLOCK; -} - -INLINE LCUI_BOOL ui_widget_has_flex_display(ui_widget_t *w) -{ - return css_computed_display(&w->computed_style) == CSS_DISPLAY_FLEX || - css_computed_display(&w->computed_style) == - CSS_DISPLAY_INLINE_FLEX; -} - -INLINE LCUI_BOOL ui_widget_has_inline_block_display(ui_widget_t *w) -{ - return css_computed_display(&w->computed_style) == - CSS_DISPLAY_INLINE_BLOCK; -} - -INLINE LCUI_BOOL ui_widget_is_flex_item(ui_widget_t *w) -{ - return ui_widget_has_flex_display(w) || - (!ui_widget_has_absolute_position(w) && w->parent && - ui_widget_has_flex_display(w->parent)); -} - -INLINE LCUI_BOOL ui_widget_has_fill_available_width(ui_widget_t *w) -{ - return (ui_widget_has_block_display(w) || - ui_widget_has_flex_display(w)) && - !ui_widget_has_absolute_position(w); -} - -void ui_widget_destroy_style(ui_widget_t *w); - -// CSS - -void ui_init_css(void); -void ui_destroy_css(void); diff --git a/lib/ui/src/ui.c b/lib/ui/src/ui.c index 692137c0a..d07f28ffb 100644 --- a/lib/ui/src/ui.c +++ b/lib/ui/src/ui.c @@ -1,6 +1,14 @@ #include -#include "../include/ui.h" -#include "internal.h" +#include +#include "ui_trash.h" +#include "ui_root.h" +#include "ui_events.h" +#include "ui_image.h" +#include "ui_widget_id.h" +#include "ui_widget_prototype.h" +#include "ui_css.h" +#include "ui_updater.h" +#include "ui_metrics.h" void ui_init(void) { diff --git a/lib/ui/src/ui_block_layout.c b/lib/ui/src/ui_block_layout.c index 19893d7ae..41016b0f0 100644 --- a/lib/ui/src/ui_block_layout.c +++ b/lib/ui/src/ui_block_layout.c @@ -1,5 +1,10 @@ // #define UI_DEBUG_ENABLED -#include "internal.h" +#include +#include +#include +#include "ui_diff.h" +#include "ui_widget_style.h" +#include "ui_widget_box.h" typedef struct ui_block_layout_row_t { float width; @@ -12,7 +17,7 @@ typedef struct ui_block_layout_row_t { typedef struct ui_block_layout_context_t { ui_widget_t *widget; ui_layout_rule_t rule; - LCUI_BOOL is_initiative; + bool is_initiative; float x, y; float content_width; diff --git a/lib/ui/src/ui_block_layout.h b/lib/ui/src/ui_block_layout.h new file mode 100644 index 000000000..5009c6ceb --- /dev/null +++ b/lib/ui/src/ui_block_layout.h @@ -0,0 +1 @@ +void ui_block_layout_reflow(ui_widget_t *w, ui_layout_rule_t rule); diff --git a/lib/ui/src/ui_css.c b/lib/ui/src/ui_css.c index e160eb92b..507659f68 100644 --- a/lib/ui/src/ui_css.c +++ b/lib/ui/src/ui_css.c @@ -1,9 +1,9 @@ #include -#include #include #include -#include "../include/ui.h" -#include "internal.h" +#include +#include +#include "ui_css.h" const char *ui_default_css = css_string( diff --git a/lib/ui/src/ui_css.h b/lib/ui/src/ui_css.h new file mode 100644 index 000000000..c22ac2746 --- /dev/null +++ b/lib/ui/src/ui_css.h @@ -0,0 +1,3 @@ + +void ui_init_css(void); +void ui_destroy_css(void); diff --git a/lib/ui/src/ui_debug.c b/lib/ui/src/ui_debug.c index 649da619e..24ae57b98 100644 --- a/lib/ui/src/ui_debug.c +++ b/lib/ui/src/ui_debug.c @@ -1,10 +1,10 @@ -#include "./internal.h" -#include #include +#include +#include int ui_debug_msg_indent = 0; -INLINE const char *get_css_unit_str(css_unit_t unit) +LIBUI_INLINE const char *get_css_unit_str(css_unit_t unit) { switch (unit) { case CSS_UNIT_PERCENT: diff --git a/lib/ui/src/ui_diff.c b/lib/ui/src/ui_diff.c index f0dbf17e4..67d3e529c 100644 --- a/lib/ui/src/ui_diff.c +++ b/lib/ui/src/ui_diff.c @@ -1,5 +1,13 @@ #include -#include "internal.h" +#include +#include +#include +#include +#include "ui_widget.h" +#include "ui_widget_box.h" +#include "ui_widget_style.h" +#include "ui_widget_observer.h" +#include "ui_diff.h" #define IS_PROP_TYPE_CHANGED(PROP_KEY) \ diff->style.type_bits.PROP_KEY != w->computed_style.type_bits.PROP_KEY @@ -17,7 +25,7 @@ void ui_style_diff_init(ui_style_diff_t *diff, ui_widget_t *w) diff->border_box = w->border_box; diff->canvas_box = w->canvas_box; diff->outer_box = w->outer_box; - diff->should_add_dirty_rect = FALSE; + diff->should_add_dirty_rect = false; if (w->parent) { if (!ui_widget_is_visible(w->parent)) { return; @@ -31,7 +39,7 @@ void ui_style_diff_init(ui_style_diff_t *diff, ui_widget_t *w) if (w->state < UI_WIDGET_STATE_LAYOUTED) { w->dirty_rect_type = UI_DIRTY_RECT_TYPE_CANVAS_BOX; } - diff->should_add_dirty_rect = TRUE; + diff->should_add_dirty_rect = true; } void ui_style_diff_begin(ui_style_diff_t *diff, ui_widget_t *w) @@ -40,7 +48,7 @@ void ui_style_diff_begin(ui_style_diff_t *diff, ui_widget_t *w) diff->visible = ui_widget_is_visible(w); } -INLINE void ui_widget_add_reflow_task(ui_widget_t *w) +LIBUI_INLINE void ui_widget_add_reflow_task(ui_widget_t *w) { if (w) { if (w->parent && !ui_widget_has_absolute_position(w) && @@ -51,7 +59,7 @@ INLINE void ui_widget_add_reflow_task(ui_widget_t *w) } } -INLINE void ui_widget_add_reflow_task_to_parent(ui_widget_t *w) +LIBUI_INLINE void ui_widget_add_reflow_task_to_parent(ui_widget_t *w) { switch (css_computed_position(&w->computed_style)) { case CSS_POSITION_ABSOLUTE: @@ -66,7 +74,7 @@ INLINE void ui_widget_add_reflow_task_to_parent(ui_widget_t *w) void ui_style_diff_end(ui_style_diff_t *diff, ui_widget_t *w) { ui_mutation_record_t *record; - const LCUI_BOOL is_flex_item = ui_widget_is_flex_item(w); + const bool is_flex_item = ui_widget_is_flex_item(w); if (ui_widget_is_visible(w) != diff->visible) { w->dirty_rect_type = UI_DIRTY_RECT_TYPE_CANVAS_BOX; @@ -209,7 +217,7 @@ void ui_layout_diff_end(ui_layout_diff_t *diff, ui_widget_t *w) } } for (parent = w->parent; parent; parent = parent->parent) { - parent->has_child_dirty_rect = TRUE; + parent->has_child_dirty_rect = true; } } else { w->dirty_rect_type = UI_DIRTY_RECT_TYPE_NONE; diff --git a/lib/ui/src/ui_diff.h b/lib/ui/src/ui_diff.h new file mode 100644 index 000000000..dc696add6 --- /dev/null +++ b/lib/ui/src/ui_diff.h @@ -0,0 +1,38 @@ + +/** for check widget difference */ +typedef struct ui_widget_style_diff_t_ { + css_computed_style_t style; + ui_rect_t content_box; + ui_rect_t padding_box; + ui_rect_t border_box; + ui_rect_t canvas_box; + ui_rect_t outer_box; + bool visible; + bool should_add_dirty_rect; +} ui_style_diff_t; + +typedef struct ui_layout_diff_t_ { + bool should_add_dirty_rect; + ui_rect_t content_box; + ui_rect_t padding_box; + ui_rect_t border_box; + ui_rect_t canvas_box; + ui_rect_t outer_box; +} ui_layout_diff_t; + +typedef struct ui_layout_item_t { + ui_widget_t *widget; + ui_layout_diff_t diff; +} ui_layout_item_t; + +void ui_style_diff_init(ui_style_diff_t *diff, ui_widget_t *w); +void ui_style_diff_begin(ui_style_diff_t *diff, ui_widget_t *w); +void ui_style_diff_end(ui_style_diff_t *diff, ui_widget_t *w); +void ui_layout_diff_begin(ui_layout_diff_t *diff, ui_widget_t *w); +void ui_layout_diff_auto_reflow(ui_layout_diff_t *diff, ui_widget_t *w); +void ui_layout_diff_end(ui_layout_diff_t *diff, ui_widget_t *w); + +// Layout + +void ui_block_layout_reflow(ui_widget_t *w, ui_layout_rule_t rule); +void ui_flexbox_layout_reflow(ui_widget_t *w, ui_layout_rule_t rule); diff --git a/lib/ui/src/ui_events.c b/lib/ui/src/ui_events.c index 9b3d19242..0607a5777 100644 --- a/lib/ui/src/ui_events.c +++ b/lib/ui/src/ui_events.c @@ -1,10 +1,13 @@ #include #include #include -#include +#include #include -#include "../include/ui.h" -#include "internal.h" +#include +#include +#include +#include +#include "ui_events.h" /* clang-format off */ @@ -19,7 +22,7 @@ typedef struct ui_touch_capturer_t { struct ui_event_listener_t { list_node_t node; size_t ref_count; - LCUI_BOOL active; + bool active; int event_id; ui_event_handler_t handler; void *data; @@ -75,7 +78,6 @@ static struct ui_events_t { int base_event_id; ui_widget_click_record_t click; - thread_mutex_t mutex; } ui_events; /* clang-format on */ @@ -94,9 +96,8 @@ int ui_set_event_id(int event_id, const char *event_name) { int ret; ui_event_mapping_t *mapping; - thread_mutex_lock(&ui_events.mutex); + if (dict_fetch_value(ui_events.event_ids, event_name)) { - thread_mutex_unlock(&ui_events.mutex); return -1; } mapping = malloc(sizeof(ui_event_mapping_t)); @@ -108,7 +109,6 @@ int ui_set_event_id(int event_id, const char *event_name) list_append(&ui_events.event_mappings, mapping); rbtree_insert_by_key(&ui_events.event_names, event_id, mapping); ret = dict_add(ui_events.event_ids, mapping->name, mapping); - thread_mutex_unlock(&ui_events.mutex); return ret; } @@ -120,18 +120,14 @@ int ui_alloc_event_id(void) const char *ui_get_event_name(int event_id) { ui_event_mapping_t *mapping; - thread_mutex_lock(&ui_events.mutex); mapping = rbtree_get_data_by_key(&ui_events.event_names, event_id); - thread_mutex_unlock(&ui_events.mutex); return mapping ? mapping->name : NULL; } int ui_get_event_id(const char *event_name) { ui_event_mapping_t *mapping; - thread_mutex_lock(&ui_events.mutex); mapping = dict_fetch_value(ui_events.event_ids, event_name); - thread_mutex_unlock(&ui_events.mutex); return mapping ? mapping->id : -1; } @@ -139,7 +135,7 @@ void ui_event_init(ui_event_t *e, const char *name) { e->target = NULL; e->type = ui_use_widget_event_id(name); - e->cancel_bubble = FALSE; + e->cancel_bubble = false; e->data = NULL; } @@ -236,7 +232,7 @@ static void ui_touch_capturer_destroy(void *arg) free(tc); } -INLINE void ui_clear_touch_capturers(list_t *list) +LIBUI_INLINE void ui_clear_touch_capturers(list_t *list) { list_destroy_without_node(list, ui_touch_capturer_destroy); } @@ -330,7 +326,7 @@ ui_event_listener_t *ui_widget_add_event_listener( return NULL; } listener->ref_count = 0; - listener->active = TRUE; + listener->active = true; listener->handler = handler; listener->data = data; listener->event_id = event_id; @@ -366,7 +362,7 @@ int ui_widget_remove_event_listener(ui_widget_t *w, int event_id, data != listener->data) { continue; } - listener->active = FALSE; + listener->active = false; if (listener->ref_count == 0) { prev = node->prev; list_unlink(&w->extra->listeners, node); @@ -385,6 +381,44 @@ int ui_widget_off(ui_widget_t *w, const char *event_name, return ui_widget_remove_event_listener(w, id, handler, data); } +int ui_emit_event(ui_event_t e, void *arg) +{ + return ui_widget_emit_event(ui_root(), e, arg); +} + +int ui_post_event(const ui_event_t *e, void *arg, + ui_event_arg_destructor_t destroy_arg) +{ + return ui_widget_post_event(ui_root(), e, arg, destroy_arg); +} + +ui_event_listener_t *ui_add_event_listener( + ui_widget_t *widget, int event_id, ui_event_handler_t handler, void *arg, + ui_event_arg_destructor_t destroy_arg) +{ + return ui_widget_add_event_listener(ui_root(), event_id, handler, arg, + destroy_arg); +} + +int ui_remove_event_listener(ui_widget_t *w, int event_id, + ui_event_handler_t handler, void *data) +{ + return ui_widget_remove_event_listener(ui_root(), event_id, handler, + data); +} + +ui_event_listener_t *ui_on_event(const char *event_name, + ui_event_handler_t handler, void *data, + void (*destroy_arg)(void *)) +{ + return ui_widget_on(ui_root(), event_name, handler, data, destroy_arg); +} + +int ui_off_event(const char *event_name, ui_event_handler_t handler, void *data) +{ + return ui_widget_off(ui_root(), event_name, handler, data); +} + static ui_widget_t *ui_widget_get_next_at(ui_widget_t *widget, float x, float y) { ui_widget_t *w; @@ -472,7 +506,7 @@ int ui_widget_emit_event(ui_widget_t *w, ui_event_t e, void *arg) float pointer_x, pointer_y; ui_widget_t *sibling; - LCUI_BOOL is_pointer_event = FALSE; + bool is_pointer_event = false; if (!e.target) { e.target = w; @@ -487,7 +521,7 @@ int ui_widget_emit_event(ui_widget_t *w, ui_event_t e, void *arg) case UI_EVENT_WHEEL: pointer_x = e.mouse.x; pointer_y = e.mouse.y; - is_pointer_event = TRUE; + is_pointer_event = true; if (w->computed_style.type_bits.pointer_events == CSS_POINTER_EVENTS_NONE) { break; @@ -588,7 +622,7 @@ static void ui_widget_trigger_mouseover_event(ui_widget_t *widget, ui_widget_t *w; ui_event_t e = { 0 }; - e.cancel_bubble = FALSE; + e.cancel_bubble = false; e.type = UI_EVENT_MOUSEOVER; for (w = widget; w && w != parent; w = w->parent) { e.target = w; @@ -603,7 +637,7 @@ static void ui_widget_trigger_mouseout_event(ui_widget_t *widget, ui_widget_t *w; ui_event_t e = { 0 }; - e.cancel_bubble = FALSE; + e.cancel_bubble = false; e.type = UI_EVENT_MOUSEOUT; for (w = widget; w && w != parent; w = w->parent) { e.target = w; @@ -702,7 +736,6 @@ void ui_clear_event_target(ui_widget_t *w) list_node_t *node, *prev; ui_event_pack_t *pack; - thread_mutex_lock(&ui_events.mutex); for (list_each(node, &ui_events.queue)) { prev = node->prev; pack = node->data; @@ -712,13 +745,12 @@ void ui_clear_event_target(ui_widget_t *w) node = prev; } } - thread_mutex_unlock(&ui_events.mutex); ui_clear_mouseover_target(w); ui_clear_mousedown_target(w); ui_clear_focus_target(w); } -INLINE LCUI_BOOL ui_widget_is_focusable(ui_widget_t *w) +LIBUI_INLINE bool ui_widget_is_focusable(ui_widget_t *w) { return w && w->computed_style.type_bits.pointer_events != @@ -756,7 +788,7 @@ int ui_set_focus(ui_widget_t *widget) } e.target = w; e.type = UI_EVENT_FOCUS; - e.cancel_bubble = FALSE; + e.cancel_bubble = false; ui_events.targets[UI_WIDGET_STATUS_FOCUS] = w; ui_widget_add_status(e.target, "focus"); ui_widget_post_event(e.target, &e, NULL, NULL); @@ -773,8 +805,8 @@ static ui_widget_t *ui_resolve_event_target(float x, float y) if (ui_events.mouse_capturer) { target = ui_events.mouse_capturer; } else { - target = - ui_widget_get_event_target(root, x, y, CSS_POINTER_EVENTS_AUTO); + target = ui_widget_get_event_target(root, x, y, + CSS_POINTER_EVENTS_AUTO); } for (w = target; w; w = w->parent) { if (w->event_blocked) { @@ -791,7 +823,7 @@ static int ui_on_wheel_event(ui_event_t *origin_event) { ui_event_t e = *origin_event; - e.cancel_bubble = FALSE; + e.cancel_bubble = false; e.target = ui_events.targets[UI_WIDGET_STATUS_HOVER]; if (!e.target) { return -1; @@ -804,7 +836,7 @@ static int ui_on_mouse_event(ui_event_t *origin_event) { ui_event_t e = *origin_event; - e.cancel_bubble = FALSE; + e.cancel_bubble = false; switch (e.type) { case UI_EVENT_MOUSEDOWN: e.target = ui_resolve_event_target(e.mouse.x, e.mouse.y); @@ -813,12 +845,12 @@ static int ui_on_mouse_event(ui_event_t *origin_event) } ui_widget_emit_event(e.target, e, NULL); ui_events.click.interval = DBLCLICK_INTERVAL; - if (e.mouse.button == MOUSE_BUTTON_LEFT && + if (e.mouse.button == UI_MOUSE_BUTTON_LEFT && ui_events.click.widget == e.target) { int delta; delta = (int)get_time_delta(ui_events.click.time); ui_events.click.interval = delta; - } else if (e.mouse.button == MOUSE_BUTTON_RIGHT && + } else if (e.mouse.button == UI_MOUSE_BUTTON_RIGHT && ui_events.click.widget != e.target) { ui_events.click.x = e.mouse.x; ui_events.click.y = e.mouse.y; @@ -835,7 +867,7 @@ static int ui_on_mouse_event(ui_event_t *origin_event) } ui_widget_emit_event(e.target, e, NULL); if (ui_events.targets[UI_WIDGET_STATUS_ACTIVE] != e.target || - e.mouse.button != MOUSE_BUTTON_LEFT) { + e.mouse.button != UI_MOUSE_BUTTON_LEFT) { ui_events.click.x = 0; ui_events.click.y = 0; ui_events.click.time = 0; @@ -890,7 +922,7 @@ static int ui_on_keyboard_event(ui_event_t *origin_event) if (!e.target) { return -1; } - e.cancel_bubble = FALSE; + e.cancel_bubble = false; ui_widget_emit_event(e.target, e, NULL); return 0; } @@ -903,7 +935,7 @@ static int ui_on_text_input(ui_event_t *origin_event) if (!e.target) { return -1; } - e.cancel_bubble = FALSE; + e.cancel_bubble = false; ui_widget_emit_event(e.target, e, NULL); return 0; } @@ -922,7 +954,7 @@ static int ui_dispatch_touch_event(list_t *capturers, ui_touch_point_t *points, root = ui_root(); scale = ui_metrics.scale; e.type = UI_EVENT_TOUCH; - e.cancel_bubble = FALSE; + e.cancel_bubble = false; e.touch.points = malloc(sizeof(ui_touch_point_t) * n_points); /* 先将各个触点按命中的部件进行分组 */ for (i = 0; i < n_points; ++i) { @@ -976,7 +1008,6 @@ static int ui_on_touch_event(ui_event_t *e) n = e->touch.n_points; points = e->touch.points; list_create(&capturers); - thread_mutex_lock(&ui_events.mutex); /* 合并现有的触点捕捉记录 */ for (list_each(node, &ui_events.touch_capturers)) { ui_touch_capturer_t *tc = node->data; @@ -998,7 +1029,6 @@ static int ui_on_touch_event(ui_event_t *e) } ui_dispatch_touch_event(&capturers, points, n); ui_clear_touch_capturers(&capturers); - thread_mutex_unlock(&ui_events.mutex); return 0; } @@ -1015,9 +1045,7 @@ void ui_widget_release_mouse_capture(ui_widget_t *w) int ui_widget_set_touch_capture(ui_widget_t *w, int point_id) { int ret; - thread_mutex_lock(&ui_events.mutex); ret = ui_add_touch_capturer(&ui_events.touch_capturers, w, point_id); - thread_mutex_unlock(&ui_events.mutex); return ret; } @@ -1028,9 +1056,7 @@ int ui_widget_release_touch_capture(ui_widget_t *w, int point_id) if (ui_events.touch_capturers.length <= 1) { return 0; } - thread_mutex_lock(&ui_events.mutex); ret = ui_remove_touch_capturer(&ui_events.touch_capturers, w, point_id); - thread_mutex_unlock(&ui_events.mutex); return ret; } @@ -1085,7 +1111,6 @@ void ui_init_events(void) { UI_EVENT_PASTE, "paste" }, { UI_EVENT_FONT_FACE_LOAD, "font_face_load" } }; - thread_mutex_init(&ui_events.mutex); rbtree_init(&ui_events.event_names); list_create(&ui_events.event_mappings); list_create(&ui_events.touch_capturers); @@ -1156,13 +1181,10 @@ void ui_process_events(void) void ui_destroy_events(void) { - thread_mutex_lock(&ui_events.mutex); rbtree_destroy(&ui_events.event_names); dict_destroy(ui_events.event_ids); ui_clear_touch_capturers(&ui_events.touch_capturers); list_destroy_without_node(&ui_events.queue, ui_on_destroy_event_pack); list_destroy(&ui_events.event_mappings, ui_event_mapping_destroy); - thread_mutex_unlock(&ui_events.mutex); - thread_mutex_destroy(&ui_events.mutex); ui_events.event_ids = NULL; } diff --git a/lib/ui/src/ui_events.h b/lib/ui/src/ui_events.h new file mode 100644 index 000000000..d4ae811b7 --- /dev/null +++ b/lib/ui/src/ui_events.h @@ -0,0 +1,8 @@ + +void ui_widget_destroy_listeners(ui_widget_t *w); + +/** 初始化 LCUI 部件的事件系统 */ +void ui_init_events(void); + +/** 销毁(释放) LCUI 部件的事件系统的相关资源 */ +void ui_destroy_events(void); diff --git a/lib/ui/src/ui_flexbox_layout.c b/lib/ui/src/ui_flexbox_layout.c index 2e84648a7..6ca259c64 100644 --- a/lib/ui/src/ui_flexbox_layout.c +++ b/lib/ui/src/ui_flexbox_layout.c @@ -5,7 +5,12 @@ */ // #define UI_DEBUG_ENABLED -#include "internal.h" +#include +#include +#include +#include "ui_diff.h" +#include "ui_widget_style.h" +#include "ui_widget_box.h" typedef struct ui_flexbox_line_t { float main_size; @@ -25,8 +30,8 @@ typedef struct ui_flexbox_line_t { typedef struct ui_flexbox_layout_context_t { ui_widget_t *widget; ui_layout_rule_t rule; - LCUI_BOOL is_initiative; - LCUI_BOOL direction_is_column; + bool is_initiative; + bool direction_is_column; float main_size; float cross_size; @@ -83,7 +88,7 @@ static void ui_flexbox_layout_next_line(ui_flexbox_layout_context_t *ctx) list_append(&ctx->lines, ctx->line); } -INLINE float ui_compute_row_item_main_size(css_computed_style_t *s) +LIBUI_INLINE float ui_compute_row_item_main_size(css_computed_style_t *s) { if (css_computed_box_sizing(s) == CSS_BOX_SIZING_BORDER_BOX) { if (s->flex_basis < css_padding_x(s) + css_border_x(s)) { @@ -94,7 +99,7 @@ INLINE float ui_compute_row_item_main_size(css_computed_style_t *s) return s->flex_basis; } -INLINE float ui_compute_column_item_main_size(css_computed_style_t *s) +LIBUI_INLINE float ui_compute_column_item_main_size(css_computed_style_t *s) { if (css_computed_box_sizing(s) == CSS_BOX_SIZING_BORDER_BOX) { if (s->flex_basis < css_padding_y(s) + css_border_y(s)) { diff --git a/lib/ui/src/ui_flexbox_layout.h b/lib/ui/src/ui_flexbox_layout.h new file mode 100644 index 000000000..8fd2be56f --- /dev/null +++ b/lib/ui/src/ui_flexbox_layout.h @@ -0,0 +1 @@ +void ui_flexbox_layout_reflow(ui_widget_t *w, ui_layout_rule_t rule); diff --git a/lib/ui/src/ui_image_loader.c b/lib/ui/src/ui_image.c similarity index 70% rename from lib/ui/src/ui_image_loader.c rename to lib/ui/src/ui_image.c index d7f411430..1507f29a7 100644 --- a/lib/ui/src/ui_image_loader.c +++ b/lib/ui/src/ui_image.c @@ -1,21 +1,19 @@ #include #include -#include -#include +#include #include -#include "../include/ui.h" -#include "internal.h" +#include typedef struct ui_image_event_listener_t { list_node_t node; void *data; - LCUI_BOOL is_fresh; + bool is_fresh; ui_image_event_handler_t handler; } ui_image_event_listener_t; struct ui_image_t { pd_canvas_t data; - LCUI_BOOL loaded; + bool loaded; char *path; size_t refs_count; /** list_t */ @@ -36,12 +34,14 @@ typedef struct ui_image_loader_t { /** list_t */ list_t events; - LCUI_Worker worker; + + /** list_t */ + list_t images; } ui_image_loader_t; static ui_image_loader_t ui_image_loader; -static void ui_image_destroy(void *privdata, void *data) +static void ui_image_force_destroy(void *privdata, void *data) { ui_image_t *image = data; pd_canvas_destroy(&image->data); @@ -52,18 +52,19 @@ static void ui_image_destroy(void *privdata, void *data) free(image); } -static void ui_image_loader_load(void *arg1, void *arg2) +static void ui_image_load(ui_image_t *image) { + list_t events; list_node_t *node; - ui_image_t *image = arg1; - ui_image_event_listener_t *listener; ui_image_event_t *e; + ui_image_event_listener_t *listener; + list_create(&events); if (!image->loaded) { if (pd_read_image_from_file(image->path, &image->data) != 0) { return; } - image->loaded = TRUE; + image->loaded = true; } for (list_each(node, &image->listeners)) { listener = node->data; @@ -77,38 +78,31 @@ static void ui_image_loader_load(void *arg1, void *arg2) e->image = image; e->data = listener->data; e->handler = listener->handler; - list_append_node(&ui_image_loader.events, &e->node); - listener->is_fresh = FALSE; + list_append_node(&events, &e->node); + listener->is_fresh = false; } + list_concat(&ui_image_loader.events, &events); } -static void ui_post_image_task(ui_image_t *image) -{ - LCUI_TaskRec task = { 0 }; - - task.arg[0] = image; - task.func = ui_image_loader_load; - LCUIWorker_PostTask(ui_image_loader.worker, &task); -} - -ui_image_t *ui_load_image(const char *path) +ui_image_t *ui_image_create(const char *path) { ui_image_t *image; image = dict_fetch_value(ui_image_loader.dict, path); if (image) { + image->refs_count++; return image; } image = malloc(sizeof(ui_image_t)); if (!image) { return NULL; } - image->loaded = FALSE; - image->refs_count = 0; + image->loaded = false; + image->refs_count = 1; image->path = strdup2(path); pd_canvas_init(&image->data); list_create(&image->listeners); - ui_post_image_task(image); + list_append(&ui_image_loader.images, image); return image; } @@ -122,18 +116,14 @@ const char *ui_image_get_path(ui_image_t *image) return image->path; } -void ui_image_add_ref(ui_image_t *image) -{ - image->refs_count++; -} - -void ui_image_remove_ref(ui_image_t *image) +void ui_image_destroy(ui_image_t *image) { assert(image->refs_count > 0); image->refs_count--; } -int ui_image_add_event_listener(ui_image_t *image, ui_image_event_handler_t handler, void *data) +int ui_image_add_event_listener(ui_image_t *image, + ui_image_event_handler_t handler, void *data) { ui_image_event_listener_t *listener; @@ -143,12 +133,13 @@ int ui_image_add_event_listener(ui_image_t *image, ui_image_event_handler_t hand } listener->handler = handler; listener->data = data; - listener->is_fresh = TRUE; + listener->is_fresh = true; list_append_node(&image->listeners, &listener->node); return 0; } -int ui_image_remove_event_listener(ui_image_t *image, ui_image_event_handler_t handler, void *data) +int ui_image_remove_event_listener(ui_image_t *image, + ui_image_event_handler_t handler, void *data) { list_node_t *node; ui_image_event_listener_t *listener; @@ -164,6 +155,18 @@ int ui_image_remove_event_listener(ui_image_t *image, ui_image_event_handler_t h return -1; } +void ui_load_images(void) +{ + list_t list; + list_node_t *node; + + list_create(&list); + list_concat(&list, &ui_image_loader.images); + for (list_each(node, &list)) { + ui_image_load(node->data); + } +} + void ui_process_image_events(void) { list_node_t *node; @@ -180,15 +183,14 @@ void ui_process_image_events(void) void ui_init_image_loader(void) { - ui_image_loader.dict_type.val_destructor = ui_image_destroy; + ui_image_loader.dict_type.val_destructor = ui_image_force_destroy; ui_image_loader.dict = dict_create(&ui_image_loader.dict_type, NULL); - ui_image_loader.worker = LCUIWorker_New(); - LCUIWorker_RunAsync(ui_image_loader.worker); + list_create(&ui_image_loader.images); } void ui_destroy_image_loader(void) { - LCUIWorker_Destroy(ui_image_loader.worker); + list_destroy(&ui_image_loader.images, NULL); dict_destroy(ui_image_loader.dict); ui_image_loader.dict = NULL; } diff --git a/lib/ui/src/ui_image.h b/lib/ui/src/ui_image.h new file mode 100644 index 000000000..3620961a1 --- /dev/null +++ b/lib/ui/src/ui_image.h @@ -0,0 +1,2 @@ +void ui_init_image_loader(void); +void ui_destroy_image_loader(void); diff --git a/lib/ui/src/ui_logger.c b/lib/ui/src/ui_logger.c index 57d158d0c..5ec216c97 100644 --- a/lib/ui/src/ui_logger.c +++ b/lib/ui/src/ui_logger.c @@ -2,7 +2,7 @@ #include #include #include -#include "internal.h" +#include #define LOG_BUFFER_SIZE 1024 #define WIDGET_STR_SIZE 256 diff --git a/lib/ui/src/ui_metrics.c b/lib/ui/src/ui_metrics.c index e4b7275f8..1b8947223 100644 --- a/lib/ui/src/ui_metrics.c +++ b/lib/ui/src/ui_metrics.c @@ -1,4 +1,5 @@ -#include "internal.h" +#include +#include "ui_metrics.h" ui_metrics_t ui_metrics; diff --git a/lib/ui/src/ui_metrics.h b/lib/ui/src/ui_metrics.h new file mode 100644 index 000000000..db91997f1 --- /dev/null +++ b/lib/ui/src/ui_metrics.h @@ -0,0 +1,2 @@ + +void ui_init_metrics(void); diff --git a/lib/ui/src/ui_mutation_oberver.c b/lib/ui/src/ui_mutation_oberver.c index e48088d9a..2cdf1d308 100644 --- a/lib/ui/src/ui_mutation_oberver.c +++ b/lib/ui/src/ui_mutation_oberver.c @@ -1,5 +1,8 @@ #include -#include "./internal.h" +#include +#include +#include +#include "ui_mutation_observer.h" static list_t ui_observers = { 0 }; diff --git a/lib/ui/src/ui_mutation_observer.h b/lib/ui/src/ui_mutation_observer.h new file mode 100644 index 000000000..b93ce9e8d --- /dev/null +++ b/lib/ui/src/ui_mutation_observer.h @@ -0,0 +1,7 @@ + +typedef struct ui_mutation_connection_t { + ui_widget_t *widget; + ui_mutation_observer_t *observer; + ui_mutation_observer_init_t options; + list_node_t node; +} ui_mutation_connection_t; diff --git a/lib/ui/src/ui_rect.c b/lib/ui/src/ui_rect.c index 4614ede8f..a8bfb29b1 100644 --- a/lib/ui/src/ui_rect.c +++ b/lib/ui/src/ui_rect.c @@ -9,24 +9,24 @@ void ui_convert_rect(const pd_rect_t *rect, ui_rect_t *ui_rect, float scale) ui_rect->height = rect->height * scale; } -LCUI_BOOL ui_rect_correct(ui_rect_t *rect, float container_width, +bool ui_rect_correct(ui_rect_t *rect, float container_width, float container_height) { - LCUI_BOOL overflow = FALSE; + bool overflow = false; if (rect->x < 0) { - overflow = TRUE; + overflow = true; rect->width += rect->x; rect->x = 0; } if (rect->y < 0) { - overflow = TRUE; + overflow = true; rect->height += rect->y; rect->y = 0; } if (rect->x + rect->width - container_width > 0) { - overflow = TRUE; + overflow = true; if (rect->x - container_width < 0) { rect->width = container_width - rect->x; } else { @@ -34,7 +34,7 @@ LCUI_BOOL ui_rect_correct(ui_rect_t *rect, float container_width, } } if (rect->y + rect->height - container_height > 0) { - overflow = TRUE; + overflow = true; if (rect->y - container_height < 0) { rect->height = container_height - rect->y; } else { @@ -44,30 +44,30 @@ LCUI_BOOL ui_rect_correct(ui_rect_t *rect, float container_width, return overflow; } -LCUI_BOOL ui_rect_is_cover(const ui_rect_t *a, const ui_rect_t *b) +bool ui_rect_is_cover(const ui_rect_t *a, const ui_rect_t *b) { if (a->x > b->x) { if (b->x + b->width <= a->x) { - return FALSE; + return false; } } else { if (a->x + a->width <= b->x) { - return FALSE; + return false; } } if (a->y > b->y) { if (b->y + b->height <= a->y) { - return FALSE; + return false; } } else { if (a->y + a->height <= b->y) { - return FALSE; + return false; } } - return TRUE; + return true; } -LCUI_BOOL ui_rect_overlap(const ui_rect_t *a, const ui_rect_t *b, +bool ui_rect_overlap(const ui_rect_t *a, const ui_rect_t *b, ui_rect_t *overlapping_rect) { if (a->x > b->x) { @@ -101,9 +101,9 @@ LCUI_BOOL ui_rect_overlap(const ui_rect_t *a, const ui_rect_t *b, overlapping_rect->y = b->y; } if (overlapping_rect->width <= 0 || overlapping_rect->height <= 0) { - return FALSE; + return false; } - return TRUE; + return true; } void ui_rect_merge(ui_rect_t *merged_rect, const ui_rect_t *a, const ui_rect_t *b) diff --git a/lib/ui/src/ui_renderer.c b/lib/ui/src/ui_renderer.c index 596b415fb..4c58fdac2 100644 --- a/lib/ui/src/ui_renderer.c +++ b/lib/ui/src/ui_renderer.c @@ -1,8 +1,16 @@ #include -#include +#include #include #include -#include "internal.h" +#include +#include +#include +#include +#include "ui_widget_box.h" +#include "ui_widget_border.h" +#include "ui_widget_background.h" +#include "ui_widget_box_shadow.h" +#include "ui_widget_prototype.h" //#define DEBUG_FRAME_RENDER #define MAX_VISIBLE_WIDTH 20000 @@ -55,15 +63,15 @@ typedef struct ui_renderer_t { * root canvas */ ui_rect_t content_rect; - LCUI_BOOL has_content_graph; - LCUI_BOOL has_self_graph; - LCUI_BOOL has_layer_graph; - LCUI_BOOL can_render_self; - LCUI_BOOL can_render_centent; + bool has_content_graph; + bool has_self_graph; + bool has_layer_graph; + bool can_render_self; + bool can_render_centent; } ui_renderer_t; /** 判断部件是否有可绘制内容 */ -static LCUI_BOOL ui_widget_is_paintable(ui_widget_t *w) +static bool ui_widget_is_paintable(ui_widget_t *w) { const css_computed_style_t *s = &w->computed_style; @@ -71,12 +79,12 @@ static LCUI_BOOL ui_widget_is_paintable(ui_widget_t *w) s->border_top_width > 0 || s->border_right_width > 0 || s->border_bottom_width > 0 || s->border_left_width > 0 || s->type_bits.box_shadow == CSS_BOX_SHADOW_SET) { - return TRUE; + return true; } return w->proto != ui_get_widget_prototype(NULL); } -static LCUI_BOOL ui_widget_has_round_border(ui_widget_t *w) +static bool ui_widget_has_round_border(ui_widget_t *w) { const css_computed_style_t *s = &w->computed_style; @@ -84,14 +92,14 @@ static LCUI_BOOL ui_widget_has_round_border(ui_widget_t *w) s->border_bottom_left_radius || s->border_bottom_right_radius; } -LCUI_BOOL ui_widget_mark_dirty_rect(ui_widget_t *w, ui_rect_t *in_rect, +bool ui_widget_mark_dirty_rect(ui_widget_t *w, ui_rect_t *in_rect, ui_box_type_t box_type) { ui_rect_t rect; ui_dirty_rect_type_t type; if (!ui_widget_is_visible(w)) { - return FALSE; + return false; } if (!in_rect) { switch (box_type) { @@ -108,28 +116,28 @@ LCUI_BOOL ui_widget_mark_dirty_rect(ui_widget_t *w, ui_rect_t *in_rect, break; } if (w->dirty_rect_type >= type) { - return FALSE; + return false; } w->dirty_rect_type = type; while (w->parent) { - w->parent->has_child_dirty_rect = TRUE; + w->parent->has_child_dirty_rect = true; w = w->parent; } - return TRUE; + return true; } rect = *in_rect; switch (box_type) { case UI_BOX_TYPE_GRAPH_BOX: if (w->dirty_rect_type == UI_DIRTY_RECT_TYPE_CANVAS_BOX) { - return FALSE; + return false; } ui_rect_correct(&rect, w->canvas_box.width, w->canvas_box.height); break; case UI_BOX_TYPE_BORDER_BOX: if (w->dirty_rect_type == UI_DIRTY_RECT_TYPE_BORDER_BOX) { - return FALSE; + return false; } ui_rect_correct(&rect, w->border_box.width, w->border_box.height); @@ -138,7 +146,7 @@ LCUI_BOOL ui_widget_mark_dirty_rect(ui_widget_t *w, ui_rect_t *in_rect, break; case UI_BOX_TYPE_PADDING_BOX: if (w->dirty_rect_type == UI_DIRTY_RECT_TYPE_PADDING_BOX) { - return FALSE; + return false; } ui_rect_correct(&rect, w->padding_box.width, w->padding_box.height); @@ -161,11 +169,11 @@ LCUI_BOOL ui_widget_mark_dirty_rect(ui_widget_t *w, ui_rect_t *in_rect, w->dirty_rect = rect; w->dirty_rect_type = UI_DIRTY_RECT_TYPE_CUSTOM; while (w->parent) { - w->parent->has_child_dirty_rect = TRUE; + w->parent->has_child_dirty_rect = true; w = w->parent; } } - return TRUE; + return true; } #define add_dirty_rect() \ @@ -227,7 +235,7 @@ static void ui_widget_collect_dirty_rect(ui_widget_t *w, list_t *rects, float x, } } w->dirty_rect_type = UI_DIRTY_RECT_TYPE_NONE; - w->has_child_dirty_rect = FALSE; + w->has_child_dirty_rect = false; } size_t ui_widget_get_dirty_rects(ui_widget_t *w, list_t *rects) @@ -272,9 +280,9 @@ static ui_renderer_t *ui_renderer_create(ui_widget_t *w, pd_context_t *paint, that->target = w; that->style = style; that->paint = paint; - that->has_self_graph = FALSE; - that->has_layer_graph = FALSE; - that->has_content_graph = FALSE; + that->has_self_graph = false; + that->has_layer_graph = false; + that->has_content_graph = false; if (parent) { that->root_paint = parent->root_paint; that->x = parent->x + parent->content_left + w->canvas_box.x; @@ -284,11 +292,11 @@ static ui_renderer_t *ui_renderer_create(ui_widget_t *w, pd_context_t *paint, that->root_paint = that->paint; } if (w->computed_style.opacity < 1.0) { - that->has_self_graph = TRUE; - that->has_content_graph = TRUE; - that->has_layer_graph = TRUE; + that->has_self_graph = true; + that->has_content_graph = true; + that->has_layer_graph = true; } else if (ui_widget_has_round_border(w)) { - that->has_content_graph = TRUE; + that->has_content_graph = true; } pd_canvas_init(&that->self_graph); pd_canvas_init(&that->layer_graph); @@ -359,7 +367,7 @@ static void ui_renderer_destroy(ui_renderer_t *renderer) free(renderer); } -INLINE void ui_widget_compute_box(ui_widget_t *w, ui_widget_actual_style_t *s) +LIBUI_INLINE void ui_widget_compute_box(ui_widget_t *w, ui_widget_actual_style_t *s) { s->content_box.x = ui_compute(s->x + w->content_box.x); s->content_box.y = ui_compute(s->y + w->content_box.y); @@ -443,7 +451,7 @@ static size_t ui_renderer_render_children(ui_renderer_t *that) child_paint.rect.x -= style.canvas_box.x; child_paint.rect.y -= style.canvas_box.y; if (that->has_content_graph) { - child_paint.with_alpha = TRUE; + child_paint.with_alpha = true; paint_rect.x -= that->actual_content_rect.x; paint_rect.y -= that->actual_content_rect.y; pd_canvas_quote(&child_paint.canvas, @@ -484,7 +492,7 @@ static size_t ui_renderer_render(ui_renderer_t *renderer) if (that->can_render_self) { count += 1; self_paint = *that->paint; - self_paint.with_alpha = TRUE; + self_paint.with_alpha = true; self_paint.canvas = that->self_graph; ui_widget_on_paint(that->target, &self_paint, that->style); #ifdef DEBUG_FRAME_RENDER @@ -521,7 +529,7 @@ static size_t ui_renderer_render(ui_renderer_t *renderer) if (that->has_content_graph) { pd_canvas_mix(&that->paint->canvas, &that->content_graph, content_x, - content_y, TRUE); + content_y, true); } #ifdef DEBUG_FRAME_RENDER sprintf(filename, "frame-%zd-L%d-%s-canvas.png", frame++, @@ -541,7 +549,7 @@ static size_t ui_renderer_render(ui_renderer_t *renderer) if (that->can_render_self) { pd_canvas_copy(&that->layer_graph, &that->self_graph); pd_canvas_mix(&that->layer_graph, &that->content_graph, - content_x, content_y, TRUE); + content_x, content_y, true); #ifdef DEBUG_FRAME_RENDER sprintf(filename, "frame-%zd-L%d-%s-content-graph-%d-%d.png", frame++, __LINE__, renderer->target->id, content_x, diff --git a/lib/ui/src/ui_root.c b/lib/ui/src/ui_root.c index f8b3182eb..5f2e9e1e7 100644 --- a/lib/ui/src/ui_root.c +++ b/lib/ui/src/ui_root.c @@ -1,6 +1,5 @@ -#include -#include "../include/ui.h" -#include "internal.h" +#include +#include "ui_root.h" static ui_widget_t *ui_root_widget; diff --git a/lib/ui/src/ui_root.h b/lib/ui/src/ui_root.h new file mode 100644 index 000000000..9cf0440e0 --- /dev/null +++ b/lib/ui/src/ui_root.h @@ -0,0 +1,3 @@ + +void ui_init_root(void); +void ui_destroy_root(void); diff --git a/lib/ui/src/ui_text_style.c b/lib/ui/src/ui_text_style.c index 8b205d199..14884c85c 100644 --- a/lib/ui/src/ui_text_style.c +++ b/lib/ui/src/ui_text_style.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include static size_t unescape(const wchar_t *instr, wchar_t *outstr) @@ -120,8 +120,7 @@ void ui_text_style_destroy(ui_text_style_t *fs) } } -LCUI_BOOL ui_text_style_is_equal(const ui_text_style_t *a, - const ui_text_style_t *b) +bool ui_text_style_is_equal(const ui_text_style_t *a, const ui_text_style_t *b) { int i; @@ -131,25 +130,25 @@ LCUI_BOOL ui_text_style_is_equal(const ui_text_style_t *a, a->white_space != b->white_space || a->font_style != b->font_style || a->font_weight != b->font_weight || a->font_size != b->font_size) { - return FALSE; + return false; } if (a->content && b->content) { if (wcscmp(a->content, b->content) != 0) { - return FALSE; + return false; } } else if (a->content != b->content) { - return FALSE; + return false; } if (a->font_ids && b->font_ids) { for (i = 0; a->font_ids[i] && b->font_ids[i]; ++i) { if (a->font_ids[i] != b->font_ids[i]) { - return FALSE; + return false; } } } else if (a->font_ids != b->font_ids) { - return FALSE; + return false; } - return TRUE; + return true; } void ui_compute_text_style(ui_text_style_t *fs, @@ -244,7 +243,8 @@ void ui_compute_text_style(ui_text_style_t *fs, fs->font_ids = NULL; } if (style->font_family) { - pd_font_library_query(&fs->font_ids, fs->font_style, fs->font_weight, - (const char *const *)style->font_family); + pd_font_library_query(&fs->font_ids, fs->font_style, + fs->font_weight, + (const char *const *)style->font_family); } } diff --git a/lib/ui/src/ui_trash.c b/lib/ui/src/ui_trash.c index bf5b16994..60f6893c2 100644 --- a/lib/ui/src/ui_trash.c +++ b/lib/ui/src/ui_trash.c @@ -1,6 +1,6 @@ -#include -#include "../include/ui.h" -#include "internal.h" +#include +#include +#include "ui_trash.h" static list_t ui_trash = { 0 }; diff --git a/lib/ui/src/ui_trash.h b/lib/ui/src/ui_trash.h new file mode 100644 index 000000000..c99894bfc --- /dev/null +++ b/lib/ui/src/ui_trash.h @@ -0,0 +1,3 @@ + +size_t ui_trash_clear(void); +void ui_trash_add(ui_widget_t *w); diff --git a/lib/ui/src/ui_tree.c b/lib/ui/src/ui_tree.c index a50c0cb1a..33b435a7c 100644 --- a/lib/ui/src/ui_tree.c +++ b/lib/ui/src/ui_tree.c @@ -1,7 +1,13 @@ #include #include #include -#include "internal.h" +#include +#include +#include +#include +#include +#include "ui_widget_observer.h" +#include "ui_trash.h" #define TYPE_CHILD_LIST UI_MUTATION_RECORD_TYPE_CHILD_LIST @@ -20,9 +26,9 @@ int ui_widget_append(ui_widget_t* parent, ui_widget_t* widget) widget->parent = parent; widget->state = UI_WIDGET_STATE_CREATED; widget->index = parent->children.length; - widget->parent->update.for_children = TRUE; + widget->parent->update.for_children = true; list_append_node(&parent->children, &widget->node); - ev.cancel_bubble = TRUE; + ev.cancel_bubble = true; ev.type = UI_EVENT_LINK; ui_widget_refresh_style(widget); ui_widget_refresh_children_style(widget); @@ -56,7 +62,7 @@ int ui_widget_prepend(ui_widget_t* parent, ui_widget_t* widget) widget->index = 0; widget->parent = parent; widget->state = UI_WIDGET_STATE_CREATED; - widget->parent->update.for_children = TRUE; + widget->parent->update.for_children = true; node = &widget->node; list_insert_node(&parent->children, 0, node); /** 修改它后面的部件的 index 值 */ @@ -66,7 +72,7 @@ int ui_widget_prepend(ui_widget_t* parent, ui_widget_t* widget) child->index += 1; node = node->next; } - ev.cancel_bubble = TRUE; + ev.cancel_bubble = true; ev.type = UI_EVENT_LINK; ui_widget_emit_event(widget, ev, NULL); ui_widget_add_task_for_children(widget, UI_TASK_REFRESH_STYLE); @@ -120,7 +126,7 @@ int ui_widget_unwrap(ui_widget_t* w) node = &w->node; target = node->prev; node = w->children.tail.prev; - ev.cancel_bubble = TRUE; + ev.cancel_bubble = true; while (len > 0) { assert(node != NULL); assert(node->data != NULL); @@ -181,7 +187,7 @@ int ui_widget_unlink(ui_widget_t* w) node = node->next; } node = &w->node; - ev.cancel_bubble = TRUE; + ev.cancel_bubble = true; ev.type = UI_EVENT_UNLINK; ui_widget_emit_event(w, ev, NULL); list_unlink(&w->parent->children, node); @@ -301,7 +307,7 @@ size_t ui_widget_each(ui_widget_t* w, void (*callback)(ui_widget_t*, void*), ui_widget_t* ui_widget_at(ui_widget_t* widget, int ix, int iy) { float x, y; - LCUI_BOOL is_hit; + bool is_hit; list_node_t* node; ui_widget_t *target = widget, *c = NULL; @@ -311,7 +317,7 @@ ui_widget_t* ui_widget_at(ui_widget_t* widget, int ix, int iy) x = 1.0f * ix; y = 1.0f * iy; do { - is_hit = FALSE; + is_hit = false; for (list_each(node, &target->stacking_context)) { c = node->data; if (!ui_widget_is_visible(c)) { @@ -321,7 +327,7 @@ ui_widget_t* ui_widget_at(ui_widget_t* widget, int ix, int iy) target = c; x -= c->padding_box.x; y -= c->padding_box.y; - is_hit = TRUE; + is_hit = true; break; } } diff --git a/lib/ui/src/ui_updater.c b/lib/ui/src/ui_updater.c index 2762b8bcb..81cc1ec69 100644 --- a/lib/ui/src/ui_updater.c +++ b/lib/ui/src/ui_updater.c @@ -1,10 +1,21 @@ // #define UI_DEBUG_ENABLED #include #include -#include -#include -#include "internal.h" +#include +#include +#include +#include +#include +#include +#include #include "ui_debug.h" +#include "ui_diff.h" +#include "ui_trash.h" +#include "ui_updater.h" +#include "ui_mutation_observer.h" +#include "ui_widget_style.h" +#include "ui_widget_box.h" +#include "ui_widget.h" // TODO: 考虑将 style_cache 移动到 ui_updater 内 @@ -22,7 +33,7 @@ struct ui_updater_profile_t { static struct ui_updater_t { dict_type_t style_cache_dict; ui_metrics_t metrics; - LCUI_BOOL refresh_all; + bool refresh_all; ui_widget_function_t handlers[UI_TASK_TOTAL_NUM]; } ui_updater; @@ -61,7 +72,7 @@ static void ui_widget_on_refresh_style(ui_widget_t* w) { // TODO:是否有必要将样式计算功能分为 refresh 和 update? ui_widget_force_refresh_style(w); - w->update.states[UI_TASK_UPDATE_STYLE] = FALSE; + w->update.states[UI_TASK_UPDATE_STYLE] = false; } static void ui_widget_on_update_style(ui_widget_t* w) @@ -74,7 +85,7 @@ void ui_widget_add_task_for_children(ui_widget_t* widget, ui_task_type_t task) ui_widget_t* child; list_node_t* node; - widget->update.for_children = TRUE; + widget->update.for_children = true; for (list_each(node, &widget->children)) { child = node->data; ui_widget_add_task(child, task); @@ -88,12 +99,12 @@ void ui_widget_add_task(ui_widget_t* widget, int task) return; } DEBUG_MSG("[%lu] %s, %d\n", widget->index, widget->type, task); - widget->update.for_self = TRUE; - widget->update.states[task] = TRUE; + widget->update.for_self = true; + widget->update.states[task] = true; widget = widget->parent; /* 向没有标记的父级部件添加标记 */ while (widget && !widget->update.for_children) { - widget->update.for_children = TRUE; + widget->update.for_children = true; widget = widget->parent; } } @@ -170,7 +181,7 @@ void ui_init_updater(void) set_task_handler(UPDATE_STYLE, ui_widget_on_update_style); set_task_handler(REFRESH_STYLE, ui_widget_on_refresh_style); set_task_handler(REFLOW, NULL); - ui_updater.refresh_all = TRUE; + ui_updater.refresh_all = true; } static ui_updater_profile_t* ui_widget_begin_update(ui_widget_t* w, @@ -248,7 +259,7 @@ static size_t ui_widget_update_visible_children(ui_widget_t* w, ui_updater_profile_t* ctx) { size_t total = 0, count; - LCUI_BOOL found = FALSE; + bool found = false; ui_rect_t rect, visible_rect; ui_widget_t *child, *parent; list_node_t *node, *next; @@ -290,10 +301,10 @@ static size_t ui_widget_update_visible_children(ui_widget_t* w, } continue; } - found = TRUE; + found = true; count = ui_widget_update_with_context(child, ctx); if (child->update.for_self || child->update.for_children) { - w->update.for_children = TRUE; + w->update.for_children = true; } total += count; node = next; @@ -336,13 +347,13 @@ static size_t ui_widget_update_children(ui_widget_t* w, } } - w->update.for_children = FALSE; + w->update.for_children = false; while (node) { child = node->data; next = node->next; count = ui_widget_update_with_context(child, ctx); if (child->update.for_self || child->update.for_children) { - w->update.for_children = TRUE; + w->update.for_children = true; } total += count; node = next; @@ -361,14 +372,14 @@ static size_t ui_widget_update_children(ui_widget_t* w, if (rules->max_update_children_count > 0) { if (update_count >= (size_t)rules->max_update_children_count) { - w->update.for_children = TRUE; + w->update.for_children = true; break; } } if (update_count < w->extra->default_max_update_count) { continue; } - w->update.for_children = TRUE; + w->update.for_children = true; msec = (clock() - msec); if (msec < 1) { w->extra->default_max_update_count += 128; @@ -395,7 +406,7 @@ static size_t ui_widget_update_children(ui_widget_t* w, static void ui_widget_update_self(ui_widget_t* w, ui_updater_profile_t* ctx) { int i; - LCUI_BOOL* states; + bool* states; ui_style_diff_t style_diff = { 0 }; if (!w->update.for_self) { @@ -406,20 +417,20 @@ static void ui_widget_update_self(ui_widget_t* w, ui_updater_profile_t* ctx) ui_style_diff_begin(&style_diff, w); } states = w->update.states; - w->update.for_self = FALSE; + w->update.for_self = false; for (i = 0; i < UI_TASK_REFLOW; ++i) { if (states[i]) { if (w->proto && w->proto->runtask) { w->proto->runtask(w, i); } - states[i] = FALSE; + states[i] = false; if (ui_updater.handlers[i]) { ui_updater.handlers[i](w); } } } if (states[UI_TASK_USER] && w->proto && w->proto->runtask) { - states[UI_TASK_USER] = FALSE; + states[UI_TASK_USER] = false; w->proto->runtask(w, UI_TASK_USER); } ui_widget_add_state(w, UI_WIDGET_STATE_UPDATED); @@ -434,10 +445,10 @@ static size_t ui_widget_update_with_context(ui_widget_t* w, ui_layout_diff_t diff; if (ui_updater.refresh_all) { - w->update.for_self = TRUE; - w->update.for_children = TRUE; - w->update.states[UI_TASK_REFRESH_STYLE] = TRUE; - w->update.states[UI_TASK_REFLOW] = TRUE; + w->update.for_self = true; + w->update.for_children = true; + w->update.states[UI_TASK_REFRESH_STYLE] = true; + w->update.states[UI_TASK_REFLOW] = true; w->dirty_rect_type = UI_DIRTY_RECT_TYPE_CANVAS_BOX; } if (!w->update.for_self && !w->update.for_children) { @@ -476,7 +487,7 @@ static size_t ui_widget_update_with_context(ui_widget_t* w, if (!w->parent || !ui_widget_in_layout_flow(w)) { ui_widget_update_box_position(w); } - w->update.states[UI_TASK_REFLOW] = FALSE; + w->update.states[UI_TASK_REFLOW] = false; #ifdef UI_DEBUG_ENABLED { UI_WIDGET_STR(w, str); @@ -503,7 +514,7 @@ size_t ui_widget_update(ui_widget_t* w) void ui_refresh_style(void) { - ui_updater.refresh_all = TRUE; + ui_updater.refresh_all = true; } size_t ui_update(void) @@ -513,7 +524,7 @@ size_t ui_update(void) ui_layout_diff_t diff; if (memcmp(&ui_metrics, &ui_updater.metrics, sizeof(ui_metrics_t))) { - ui_updater.refresh_all = TRUE; + ui_updater.refresh_all = true; } if (ui_updater.refresh_all) { ui_refresh_style(); @@ -522,7 +533,7 @@ size_t ui_update(void) ui_layout_diff_begin(&diff, root); count = ui_widget_update(root); ui_updater.metrics = ui_metrics; - ui_updater.refresh_all = FALSE; + ui_updater.refresh_all = false; ui_layout_diff_end(&diff, root); ui_process_mutation_observers(); ui_trash_clear(); @@ -546,7 +557,7 @@ void ui_update_with_profile(ui_profile_t* profile) profile->time = clock(); if (memcmp(&ui_metrics, &ui_updater.metrics, sizeof(ui_metrics_t))) { - ui_updater.refresh_all = TRUE; + ui_updater.refresh_all = true; } if (ui_updater.refresh_all) { ui_refresh_style(); diff --git a/lib/ui/src/ui_updater.h b/lib/ui/src/ui_updater.h new file mode 100644 index 000000000..b8f38276c --- /dev/null +++ b/lib/ui/src/ui_updater.h @@ -0,0 +1,2 @@ + +void ui_init_updater(void); diff --git a/lib/ui/src/ui_widget.c b/lib/ui/src/ui_widget.c index a97b169c2..830484869 100644 --- a/lib/ui/src/ui_widget.c +++ b/lib/ui/src/ui_widget.c @@ -1,7 +1,18 @@ #include #include #include -#include "internal.h" +#include +#include +#include +#include "ui_widget.h" +#include "ui_widget_id.h" +#include "ui_widget_attributes.h" +#include "ui_widget_classes.h" +#include "ui_widget_prototype.h" +#include "ui_widget_status.h" +#include "ui_widget_observer.h" +#include "ui_widget_style.h" +#include "ui_events.h" static void ui_widget_destroy_children(ui_widget_t* w); @@ -90,7 +101,7 @@ void ui_widget_add_state(ui_widget_t* w, ui_widget_state_t state) if (w->state == UI_WIDGET_STATE_READY) { ui_event_t e = { 0 }; e.type = UI_EVENT_READY; - e.cancel_bubble = TRUE; + e.cancel_bubble = true; ui_widget_emit_event(w, e, NULL); w->state = UI_WIDGET_STATE_NORMAL; } @@ -158,7 +169,7 @@ void ui_widget_get_offset(ui_widget_t* w, ui_widget_t* parent, float* offset_x, *offset_y = y; } -LCUI_BOOL ui_widget_in_viewport(ui_widget_t* w) +bool ui_widget_in_viewport(ui_widget_t* w) { list_node_t* node; ui_rect_t rect; @@ -177,7 +188,7 @@ LCUI_BOOL ui_widget_in_viewport(ui_widget_t* w) for (self = w, parent = w->parent; parent; self = parent, parent = parent->parent) { if (!ui_widget_is_visible(parent)) { - return FALSE; + return false; } for (node = self->node_show.prev; node && node->prev; node = node->prev) { @@ -199,7 +210,7 @@ LCUI_BOOL ui_widget_in_viewport(ui_widget_t* w) } if (style->opacity == 1.0f && css_color_alpha(style->background_color) == 255) { - return FALSE; + return false; } } rect.x += parent->padding_box.x; @@ -207,8 +218,8 @@ LCUI_BOOL ui_widget_in_viewport(ui_widget_t* w) ui_rect_correct(&rect, parent->padding_box.width, parent->padding_box.height); if (rect.width < 1 || rect.height < 1) { - return FALSE; + return false; } } - return TRUE; + return true; } diff --git a/lib/ui/src/ui_widget.h b/lib/ui/src/ui_widget.h new file mode 100644 index 000000000..9c8bad306 --- /dev/null +++ b/lib/ui/src/ui_widget.h @@ -0,0 +1,2 @@ + +void ui_widget_add_state(ui_widget_t *w, ui_widget_state_t state); diff --git a/lib/ui/src/ui_widget_attributes.c b/lib/ui/src/ui_widget_attributes.c index 1fe1c8c77..ef4186d3b 100644 --- a/lib/ui/src/ui_widget_attributes.c +++ b/lib/ui/src/ui_widget_attributes.c @@ -1,8 +1,8 @@ #include #include #include -#include "../include/ui.h" -#include "internal.h" +#include +#include "ui_widget_attributes.h" static void ui_widget_attribute_destructor(void *privdata, void *data) { @@ -22,12 +22,12 @@ int ui_widget_set_attribute_ex(ui_widget_t *w, const char *name, void *value, { ui_widget_attribute_t *attr; static dict_type_t dict_type; - static LCUI_BOOL dict_type_available = FALSE; + static bool dict_type_available = false; if (!dict_type_available) { dict_init_string_key_type(&dict_type); dict_type.val_destructor = ui_widget_attribute_destructor; - dict_type_available = TRUE; + dict_type_available = true; } if (!w->attributes) { w->attributes = dict_create(&dict_type, NULL); @@ -60,9 +60,9 @@ int ui_widget_set_attribute(ui_widget_t *w, const char *name, const char *value) } if (strcmp(name, "disabled") == 0) { if (!value || strcmp(value, "false") != 0) { - ui_widget_set_disabled(w, TRUE); + ui_widget_set_disabled(w, true); } else { - ui_widget_set_disabled(w, FALSE); + ui_widget_set_disabled(w, false); } } else if (strcmp(name, "tabindex") == 0) { if (value) { diff --git a/lib/ui/src/ui_widget_attributes.h b/lib/ui/src/ui_widget_attributes.h new file mode 100644 index 000000000..eb7cdea0c --- /dev/null +++ b/lib/ui/src/ui_widget_attributes.h @@ -0,0 +1,2 @@ + +void ui_widget_destroy_attributes(ui_widget_t *w); diff --git a/lib/ui/src/ui_widget_background.c b/lib/ui/src/ui_widget_background.c index 8fb36dcc2..e45f3e111 100644 --- a/lib/ui/src/ui_widget_background.c +++ b/lib/ui/src/ui_widget_background.c @@ -1,6 +1,8 @@ #include #include -#include "internal.h" +#include +#include +#include "ui_widget_background.h" void ui_widget_paint_background(ui_widget_t *w, pd_context_t *ctx, ui_widget_actual_style_t *style) diff --git a/lib/ui/src/ui_widget_background.h b/lib/ui/src/ui_widget_background.h new file mode 100644 index 000000000..047c81771 --- /dev/null +++ b/lib/ui/src/ui_widget_background.h @@ -0,0 +1,3 @@ + +void ui_widget_paint_background(ui_widget_t *w, pd_context_t *paint, + ui_widget_actual_style_t *style); diff --git a/lib/ui/src/ui_widget_border.c b/lib/ui/src/ui_widget_border.c index 8f5eeb43a..0c1ad701a 100644 --- a/lib/ui/src/ui_widget_border.c +++ b/lib/ui/src/ui_widget_border.c @@ -1,5 +1,7 @@ #include -#include "internal.h" +#include +#include +#include "ui_widget_border.h" static void ui_widget_compute_border(ui_widget_t* w, pd_border_t* b) { diff --git a/lib/ui/src/ui_widget_border.h b/lib/ui/src/ui_widget_border.h new file mode 100644 index 000000000..66f1ce713 --- /dev/null +++ b/lib/ui/src/ui_widget_border.h @@ -0,0 +1,5 @@ + +void ui_widget_paint_border(ui_widget_t *w, pd_context_t *paint, + ui_widget_actual_style_t *style); +void ui_widget_crop_content(ui_widget_t *w, pd_context_t *paint, + ui_widget_actual_style_t *style); diff --git a/lib/ui/src/ui_widget_box.c b/lib/ui/src/ui_widget_box.c index 7c82b6170..3d661eefa 100644 --- a/lib/ui/src/ui_widget_box.c +++ b/lib/ui/src/ui_widget_box.c @@ -1,6 +1,8 @@ #include #include -#include "internal.h" +#include +#include +#include "ui_widget_box.h" #define SHADOW_WIDTH(s) (s->box_shadow_blur + s->box_shadow_spread) @@ -95,7 +97,7 @@ void ui_widget_update_box_position(ui_widget_t *w) w->dirty_rect = w->canvas_box; w->dirty_rect_type = UI_DIRTY_RECT_TYPE_CANVAS_BOX; while (parent) { - parent->has_child_dirty_rect = TRUE; + parent->has_child_dirty_rect = true; parent = parent->parent; } } @@ -148,7 +150,7 @@ void ui_widget_update_box_size(ui_widget_t *w) w->dirty_rect = w->canvas_box; w->dirty_rect_type = UI_DIRTY_RECT_TYPE_CANVAS_BOX; while (parent) { - parent->has_child_dirty_rect = TRUE; + parent->has_child_dirty_rect = true; parent = parent->parent; } } @@ -169,7 +171,7 @@ void ui_widget_update_box_size(ui_widget_t *w) w->dirty_rect = w->canvas_box; w->dirty_rect_type = UI_DIRTY_RECT_TYPE_CANVAS_BOX; while (parent) { - parent->has_child_dirty_rect = TRUE; + parent->has_child_dirty_rect = true; parent = parent->parent; } } diff --git a/lib/ui/src/ui_widget_box.h b/lib/ui/src/ui_widget_box.h new file mode 100644 index 000000000..c31b97c2c --- /dev/null +++ b/lib/ui/src/ui_widget_box.h @@ -0,0 +1,5 @@ + +void ui_widget_update_box_position(ui_widget_t *w); +void ui_widget_update_canvas_box(ui_widget_t *w); +void ui_widget_update_box_size(ui_widget_t *w); +void ui_widget_set_content_box_size(ui_widget_t *w, float width, float height); diff --git a/lib/ui/src/ui_widget_box_shadow.c b/lib/ui/src/ui_widget_box_shadow.c index 4049f562e..550cce819 100644 --- a/lib/ui/src/ui_widget_box_shadow.c +++ b/lib/ui/src/ui_widget_box_shadow.c @@ -1,5 +1,7 @@ #include -#include "internal.h" +#include +#include +#include "ui_widget_box_shadow.h" void ui_widget_paint_box_shadow(ui_widget_t* w, pd_context_t* ctx, ui_widget_actual_style_t* style) diff --git a/lib/ui/src/ui_widget_box_shadow.h b/lib/ui/src/ui_widget_box_shadow.h new file mode 100644 index 000000000..3590e72bf --- /dev/null +++ b/lib/ui/src/ui_widget_box_shadow.h @@ -0,0 +1,3 @@ + +void ui_widget_paint_box_shadow(ui_widget_t *w, pd_context_t *paint, + ui_widget_actual_style_t *style); diff --git a/lib/ui/src/ui_widget_classes.c b/lib/ui/src/ui_widget_classes.c index 7b0af56db..7af858b18 100644 --- a/lib/ui/src/ui_widget_classes.c +++ b/lib/ui/src/ui_widget_classes.c @@ -1,6 +1,6 @@ -#include -#include "../include/ui.h" -#include "internal.h" +#include +#include "ui_widget_classes.h" +#include "ui_widget_style.h" static void ui_widget_refresh_children_by_classes(ui_widget_t* w) { @@ -44,12 +44,12 @@ int ui_widget_add_class(ui_widget_t* w, const char *class_name) return ui_widget_handle_classes_change(w, class_name); } -LCUI_BOOL ui_widget_has_class(ui_widget_t* w, const char *class_name) +bool ui_widget_has_class(ui_widget_t* w, const char *class_name) { if (strlist_has(w->classes, class_name)) { - return TRUE; + return true; } - return FALSE; + return false; } int ui_widget_remove_class(ui_widget_t* w, const char *class_name) diff --git a/lib/ui/src/ui_widget_classes.h b/lib/ui/src/ui_widget_classes.h new file mode 100644 index 000000000..33686ff58 --- /dev/null +++ b/lib/ui/src/ui_widget_classes.h @@ -0,0 +1,2 @@ + +void ui_widget_destroy_classes(ui_widget_t *w); diff --git a/lib/ui/src/ui_widget_hash.c b/lib/ui/src/ui_widget_hash.c index 614170a14..87a848fe8 100644 --- a/lib/ui/src/ui_widget_hash.c +++ b/lib/ui/src/ui_widget_hash.c @@ -1,7 +1,5 @@ - -#include -#include "../include/ui.h" -#include "internal.h" +#include +#include void ui_widget_generate_self_hash(ui_widget_t* widget) { diff --git a/lib/ui/src/ui_widget_helper.c b/lib/ui/src/ui_widget_helper.c index 8bbf22fbd..cf6a56f81 100644 --- a/lib/ui/src/ui_widget_helper.c +++ b/lib/ui/src/ui_widget_helper.c @@ -1,9 +1,11 @@ #include #include -#include "../include/ui.h" -#include "internal.h" +#include +#include +#include +#include -LCUI_BOOL ui_widget_is_visible(ui_widget_t *w) +bool ui_widget_is_visible(ui_widget_t *w) { return css_computed_display(&w->computed_style) != CSS_DISPLAY_NONE && css_computed_visibility(&w->computed_style) != diff --git a/lib/ui/src/ui_widget_id.c b/lib/ui/src/ui_widget_id.c index 452518ed7..a775f8a15 100644 --- a/lib/ui/src/ui_widget_id.c +++ b/lib/ui/src/ui_widget_id.c @@ -1,11 +1,10 @@ #include #include -#include "../include/ui.h" -#include "internal.h" +#include +#include "ui_widget_id.h" static dict_t* ui_widget_id_dict; -static thread_mutex_t ui_widget_id_dict_mutex; int ui_widget_destroy_id(ui_widget_t* w) { @@ -15,10 +14,8 @@ int ui_widget_destroy_id(ui_widget_t* w) if (!w->id) { return -1; } - thread_mutex_lock(&ui_widget_id_dict_mutex); list = dict_fetch_value(ui_widget_id_dict, w->id); if (!list) { - thread_mutex_unlock(&ui_widget_id_dict_mutex); return -2; } for (list_each(node, list)) { @@ -27,11 +24,9 @@ int ui_widget_destroy_id(ui_widget_t* w) w->id = NULL; list_unlink(list, node); free(node); - thread_mutex_unlock(&ui_widget_id_dict_mutex); return 0; } } - thread_mutex_unlock(&ui_widget_id_dict_mutex); return -3; } @@ -43,7 +38,6 @@ int ui_widget_set_id(ui_widget_t* w, const char *idstr) if (!idstr) { return -1; } - thread_mutex_lock(&ui_widget_id_dict_mutex); w->id = strdup2(idstr); if (!w->id) { goto error_exit; @@ -63,11 +57,9 @@ int ui_widget_set_id(ui_widget_t* w, const char *idstr) if (!list_append(list, w)) { goto error_exit; } - thread_mutex_unlock(&ui_widget_id_dict_mutex); return 0; error_exit: - thread_mutex_unlock(&ui_widget_id_dict_mutex); if (w->id) { free(w->id); w->id = NULL; @@ -83,12 +75,10 @@ ui_widget_t* ui_get_widget(const char *id) if (!id) { return NULL; } - thread_mutex_lock(&ui_widget_id_dict_mutex); list = dict_fetch_value(ui_widget_id_dict, id); if (list) { w = list_get(list, 0); } - thread_mutex_unlock(&ui_widget_id_dict_mutex); return w; } @@ -103,7 +93,6 @@ static void ui_widget_id_dict_val_destructor(void *privdata, void *data) void ui_init_widget_id(void) { static dict_type_t type; - thread_mutex_init(&ui_widget_id_dict_mutex); dict_init_string_copy_key_type(&type); type.val_destructor = ui_widget_id_dict_val_destructor; ui_widget_id_dict = dict_create(&type, NULL); @@ -112,6 +101,5 @@ void ui_init_widget_id(void) void ui_destroy_widget_id(void) { dict_destroy(ui_widget_id_dict); - thread_mutex_destroy(&ui_widget_id_dict_mutex); ui_widget_id_dict = NULL; } diff --git a/lib/ui/src/ui_widget_id.h b/lib/ui/src/ui_widget_id.h new file mode 100644 index 000000000..be03f6d9c --- /dev/null +++ b/lib/ui/src/ui_widget_id.h @@ -0,0 +1,4 @@ + +int ui_widget_destroy_id(ui_widget_t *w); +void ui_init_widget_id(void); +void ui_destroy_widget_id(void); diff --git a/lib/ui/src/ui_widget_layout.c b/lib/ui/src/ui_widget_layout.c index 73e62362d..dfa67afeb 100644 --- a/lib/ui/src/ui_widget_layout.c +++ b/lib/ui/src/ui_widget_layout.c @@ -1,7 +1,14 @@ // #define UI_DEBUG_ENABLED -#include "internal.h" -#include +#include +#include +#include +#include #include "ui_debug.h" +#include "ui_block_layout.h" +#include "ui_flexbox_layout.h" +#include "ui_widget.h" +#include "ui_widget_style.h" +#include "ui_widget_box.h" static void ui_widget_reflow_with_rule(ui_widget_t *w, ui_layout_rule_t rule) { @@ -68,7 +75,7 @@ void ui_widget_reset_size(ui_widget_t *w) void ui_widget_reflow(ui_widget_t *w) { ui_layout_rule_t rule = UI_LAYOUT_RULE_MAX_CONTENT; - ui_event_t ev = { .type = UI_EVENT_AFTERLAYOUT, .cancel_bubble = TRUE }; + ui_event_t ev = { .type = UI_EVENT_AFTERLAYOUT, .cancel_bubble = true }; if (IS_CSS_FIXED_LENGTH(&w->computed_style, width)) { rule |= UI_LAYOUT_RULE_FIXED_WIDTH; diff --git a/lib/ui/src/ui_widget_observer.c b/lib/ui/src/ui_widget_observer.c index f68cf7b3b..c96c7cdd3 100644 --- a/lib/ui/src/ui_widget_observer.c +++ b/lib/ui/src/ui_widget_observer.c @@ -1,6 +1,9 @@ -#include "./internal.h" +#include +#include +#include "ui_mutation_observer.h" +#include "ui_widget_observer.h" -LCUI_BOOL ui_widget_has_observer(ui_widget_t *widget, +bool ui_widget_has_observer(ui_widget_t *widget, ui_mutation_record_type_t type) { ui_widget_t *parent; @@ -20,17 +23,17 @@ LCUI_BOOL ui_widget_has_observer(ui_widget_t *widget, switch (type) { case UI_MUTATION_RECORD_TYPE_CHILD_LIST: if (conn->options.child_list) { - return TRUE; + return true; } break; case UI_MUTATION_RECORD_TYPE_PROPERTIES: if (conn->options.properties) { - return TRUE; + return true; } break; case UI_MUTATION_RECORD_TYPE_ATTRIBUTES: if (conn->options.attributes) { - return TRUE; + return true; } break; default: @@ -38,7 +41,7 @@ LCUI_BOOL ui_widget_has_observer(ui_widget_t *widget, } } } - return FALSE; + return false; } int ui_widget_add_mutation_recrod(ui_widget_t *widget, diff --git a/lib/ui/src/ui_widget_observer.h b/lib/ui/src/ui_widget_observer.h new file mode 100644 index 000000000..25a7300fd --- /dev/null +++ b/lib/ui/src/ui_widget_observer.h @@ -0,0 +1,5 @@ +bool ui_widget_has_observer(ui_widget_t *widget, + ui_mutation_record_type_t type); + +int ui_widget_add_mutation_recrod(ui_widget_t *widget, + ui_mutation_record_t *record); diff --git a/lib/ui/src/ui_widget_prototype.c b/lib/ui/src/ui_widget_prototype.c index 6b7859d72..40ada573f 100644 --- a/lib/ui/src/ui_widget_prototype.c +++ b/lib/ui/src/ui_widget_prototype.c @@ -1,6 +1,8 @@ #include -#include "internal.h" +#include +#include +#include "ui_widget_prototype.h" static dict_t *ui_widget_prototype_dict; @@ -102,37 +104,37 @@ ui_widget_prototype_t *ui_get_widget_prototype(const char *name) return proto; } -LCUI_BOOL ui_check_widget_type(ui_widget_t *w, const char *type) +bool ui_check_widget_type(ui_widget_t *w, const char *type) { const ui_widget_prototype_t *proto; if (!w || !w->type) { - return FALSE; + return false; } if (strcmp(w->type, type) == 0) { - return TRUE; + return true; } if (!w->proto) { - return FALSE; + return false; } for (proto = w->proto->proto; proto; proto = proto->proto) { if (strcmp(proto->name, type) == 0) { - return TRUE; + return true; } } - return FALSE; + return false; } -LCUI_BOOL ui_check_widget_prototype(ui_widget_t *w, +bool ui_check_widget_prototype(ui_widget_t *w, const ui_widget_prototype_t *proto) { const ui_widget_prototype_t *p; for (p = w->proto; p; p = p->proto) { if (p == proto) { - return TRUE; + return true; } } - return FALSE; + return false; } void *ui_widget_get_data(ui_widget_t *widget, ui_widget_prototype_t *proto) diff --git a/lib/ui/src/ui_widget_prototype.h b/lib/ui/src/ui_widget_prototype.h new file mode 100644 index 000000000..9639576bb --- /dev/null +++ b/lib/ui/src/ui_widget_prototype.h @@ -0,0 +1,4 @@ + +void ui_init_widget_prototype(void); +void ui_destroy_widget_prototype(void); +void ui_widget_destroy_prototype(ui_widget_t *widget); diff --git a/lib/ui/src/ui_widget_status.c b/lib/ui/src/ui_widget_status.c index 722c66d19..e95a08dc5 100644 --- a/lib/ui/src/ui_widget_status.c +++ b/lib/ui/src/ui_widget_status.c @@ -1,6 +1,6 @@ -#include -#include "../include/ui.h" -#include "internal.h" +#include +#include "ui_widget_status.h" +#include "ui_widget_style.h" static void ui_widget_refresh_children_by_status(ui_widget_t* w) { @@ -42,12 +42,12 @@ int ui_widget_add_status(ui_widget_t* w, const char *status_name) return ui_wdiget_handle_status_change(w, status_name); } -LCUI_BOOL ui_widget_has_status(ui_widget_t* w, const char *status_name) +bool ui_widget_has_status(ui_widget_t* w, const char *status_name) { if (strlist_has(w->status, status_name)) { - return TRUE; + return true; } - return FALSE; + return false; } int ui_widget_remove_status(ui_widget_t* w, const char *status_name) @@ -83,7 +83,7 @@ void ui_widget_update_status(ui_widget_t* widget) } } -void ui_widget_set_disabled(ui_widget_t* w, LCUI_BOOL disabled) +void ui_widget_set_disabled(ui_widget_t* w, bool disabled) { w->disabled = disabled; if (w->disabled) { diff --git a/lib/ui/src/ui_widget_status.h b/lib/ui/src/ui_widget_status.h new file mode 100644 index 000000000..7506274c7 --- /dev/null +++ b/lib/ui/src/ui_widget_status.h @@ -0,0 +1,2 @@ + +void ui_widget_destroy_status(ui_widget_t *w); diff --git a/lib/ui/src/ui_widget_style.c b/lib/ui/src/ui_widget_style.c index 13eabbd25..b1e7c2f35 100644 --- a/lib/ui/src/ui_widget_style.c +++ b/lib/ui/src/ui_widget_style.c @@ -1,7 +1,10 @@ #include #include -#include "internal.h" - +#include +#include +#include +#include +#include "ui_widget_style.h" css_selector_node_t *ui_widget_create_selector_node(ui_widget_t *w) { @@ -129,7 +132,7 @@ size_t ui_widget_get_children_style_changes(ui_widget_t *w, int type, void ui_widget_update_children_style(ui_widget_t *w) { list_node_t *node; - w->update.for_children = TRUE; + w->update.for_children = true; for (list_each(node, &w->children)) { ui_widget_update_style(node->data); ui_widget_update_children_style(node->data); @@ -139,7 +142,7 @@ void ui_widget_update_children_style(ui_widget_t *w) void ui_widget_refresh_children_style(ui_widget_t *w) { list_node_t *node; - w->update.for_children = TRUE; + w->update.for_children = true; for (list_each(node, &w->children)) { ui_widget_refresh_style(node->data); ui_widget_refresh_children_style(node->data); @@ -327,7 +330,7 @@ void ui_widget_force_update_style(ui_widget_t *w) DEBUG_MSG("begin, %s\n", w->classes ? w->classes[0] : "null"); if (s->background_image && s->type_bits.background_image == CSS_BACKGROUND_IMAGE_DATA) { - ui_image_remove_ref((ui_image_t *)s->background_image); + ui_image_destroy((ui_image_t *)s->background_image); } css_computed_style_destroy(s); if (w->custom_style) { @@ -344,10 +347,9 @@ void ui_widget_force_update_style(ui_widget_t *w) if (s->background_image) { s->type_bits.background_image = CSS_BACKGROUND_IMAGE_DATA; s->background_image = - (css_image_value_t)ui_load_image(s->background_image); + (css_image_value_t)ui_image_create(s->background_image); ui_image_on_event((ui_image_t *)s->background_image, ui_widget_on_background_image_load, w); - ui_image_add_ref((ui_image_t *)s->background_image); } if (w->proto && w->proto->update) { /* 扩展部分的样式交给该部件自己处理 */ @@ -370,7 +372,7 @@ void ui_widget_destroy_style(ui_widget_t *w) w->matched_style = NULL; if (w->computed_style.type_bits.background_image == CSS_BACKGROUND_IMAGE_DATA) { - ui_image_remove_ref( + ui_image_destroy( (ui_image_t *)w->computed_style.background_image); } if (w->custom_style) { diff --git a/lib/ui/src/ui_widget_style.h b/lib/ui/src/ui_widget_style.h new file mode 100644 index 000000000..4f5ecfb21 --- /dev/null +++ b/lib/ui/src/ui_widget_style.h @@ -0,0 +1,99 @@ +#include + +LIBUI_INLINE float padding_x(ui_widget_t *w) +{ + return w->computed_style.padding_left + w->computed_style.padding_right; +} + +LIBUI_INLINE float padding_y(ui_widget_t *w) +{ + return w->computed_style.padding_top + w->computed_style.padding_bottom; +} + +LIBUI_INLINE float border_x(ui_widget_t *w) +{ + return w->computed_style.border_left_width + + w->computed_style.border_right_width; +} + +LIBUI_INLINE float border_y(ui_widget_t *w) +{ + return w->computed_style.border_top_width + + w->computed_style.border_bottom_width; +} + +LIBUI_INLINE float margin_x(ui_widget_t *w) +{ + return w->computed_style.margin_left + w->computed_style.margin_right; +} + +LIBUI_INLINE float margin_y(ui_widget_t *w) +{ + return w->computed_style.margin_top + w->computed_style.margin_bottom; +} + +LIBUI_INLINE float to_border_box_width(ui_widget_t *w, float content_width) +{ + return content_width + padding_x(w) + border_x(w); +} + +LIBUI_INLINE float to_border_box_height(ui_widget_t *w, float content_height) +{ + return content_height + padding_y(w) + border_y(w); +} + +LIBUI_INLINE bool ui_widget_is_inline(ui_widget_t *w) +{ + return w->computed_style.type_bits.display == + CSS_DISPLAY_INLINE_BLOCK || + w->computed_style.type_bits.display == CSS_DISPLAY_INLINE_FLEX; +} + +LIBUI_INLINE bool ui_widget_has_absolute_position(ui_widget_t *w) +{ + return css_computed_position(&w->computed_style) == + CSS_POSITION_ABSOLUTE; +} + +LIBUI_INLINE bool ui_widget_in_layout_flow(ui_widget_t *w) +{ + return css_computed_display(&w->computed_style) != CSS_DISPLAY_NONE && + !ui_widget_has_absolute_position(w); +} + +LIBUI_INLINE bool ui_widget_has_block_display(ui_widget_t *w) +{ + return css_computed_display(&w->computed_style) == CSS_DISPLAY_BLOCK; +} + +LIBUI_INLINE bool ui_widget_has_flex_display(ui_widget_t *w) +{ + return css_computed_display(&w->computed_style) == CSS_DISPLAY_FLEX || + css_computed_display(&w->computed_style) == + CSS_DISPLAY_INLINE_FLEX; +} + +LIBUI_INLINE bool ui_widget_has_inline_block_display(ui_widget_t *w) +{ + return css_computed_display(&w->computed_style) == + CSS_DISPLAY_INLINE_BLOCK; +} + +LIBUI_INLINE bool ui_widget_is_flex_item(ui_widget_t *w) +{ + return ui_widget_has_flex_display(w) || + (!ui_widget_has_absolute_position(w) && w->parent && + ui_widget_has_flex_display(w->parent)); +} + +LIBUI_INLINE bool ui_widget_has_fill_available_width(ui_widget_t *w) +{ + return (ui_widget_has_block_display(w) || + ui_widget_has_flex_display(w)) && + !ui_widget_has_absolute_position(w); +} + +size_t ui_widget_get_children_style_changes(ui_widget_t *w, int type, + const char *name); + +void ui_widget_destroy_style(ui_widget_t *w); diff --git a/lib/ui/xmake.lua b/lib/ui/xmake.lua index c3f4dbe89..32da0e053 100644 --- a/lib/ui/xmake.lua +++ b/lib/ui/xmake.lua @@ -1,5 +1,15 @@ +set_project("libui") +set_version("0.1.0-a") + target("libui") set_default(false) set_kind("$(kind)") add_files("src/**.c") - add_deps("yutil", "pandagl", "libcss", "libthread", "libworker") + add_deps("yutil", "pandagl", "libcss") + set_configdir("include/ui") + add_configfiles("src/config.h.in") + if is_kind("static") then + set_configvar("LIBUI_STATIC_BUILD", 1) + elseif is_plat("windows") then + add_defines("LIBUI_DLL_EXPORT") + end diff --git a/src/config.h.in b/src/config.h.in index bd9d45835..bcbd17306 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -1,8 +1,4 @@ #define PACKAGE_VERSION "${VERSION}-${GIT_COMMIT}" ${define WITH_LIBXML2} - -${define HAVE_LIBX11} -${define ENABLE_TOUCH} - ${define ENABLE_OPENMP} diff --git a/src/lcui.c b/src/lcui.c index 6c72833b8..5dcc7c821 100644 --- a/src/lcui.c +++ b/src/lcui.c @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/lcui_settings.c b/src/lcui_settings.c index e896ada4a..c11ae8bb2 100644 --- a/src/lcui_settings.c +++ b/src/lcui_settings.c @@ -27,9 +27,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include +#include #include -#include -#include static lcui_settings_t lcui_settings; diff --git a/src/lcui_ui.c b/src/lcui_ui.c index feaefcffd..2b8186510 100644 --- a/src/lcui_ui.c +++ b/src/lcui_ui.c @@ -1,20 +1,15 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include #define DEFAULT_WINDOW_WIDTH 800 #define DEFAULT_WINDOW_HEIGHT 600 static struct lcui_ui_t { + int image_loading_timer; lcui_display_mode_t mode; ui_mutation_observer_t *observer; @@ -374,6 +369,11 @@ static void lcui_load_default_fonts(void) #endif } +static void lcui_ui_image_loading_timer(void *arg) +{ + ui_load_images(); +} + void lcui_init_ui(void) { ui_init(); @@ -385,10 +385,12 @@ void lcui_init_ui(void) lcui_init_ui_preset_widgets(); lcui_load_default_fonts(); app_on_event(APP_EVENT_CLOSE, lcui_on_window_destroy, NULL); + lcui_ui.image_loading_timer = lcui_set_interval(100, lcui_ui_image_loading_timer, NULL); } void lcui_destroy_ui(void) { + lcui_destroy_timer(lcui_ui.image_loading_timer); lcui_destroy_ui_preset_widgets(); app_off_event(APP_EVENT_CLOSE, lcui_on_window_destroy); list_destroy(&lcui_ui.windows, lcui_close_window); diff --git a/tests/cases/test_block_layout.c b/tests/cases/test_block_layout.c index 2b9e30d27..a78799e14 100644 --- a/tests/cases/test_block_layout.c +++ b/tests/cases/test_block_layout.c @@ -1,7 +1,7 @@ #include "ctest.h" #include -#include -#include +#include +#include static void test_dropdown(void) { diff --git a/tests/cases/test_clipboard.c b/tests/cases/test_clipboard.c index 2666220ff..c18668b2f 100644 --- a/tests/cases/test_clipboard.c +++ b/tests/cases/test_clipboard.c @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include "ctest.h" diff --git a/tests/cases/test_flex_layout.c b/tests/cases/test_flex_layout.c index f282b0ff2..5838b4841 100644 --- a/tests/cases/test_flex_layout.c +++ b/tests/cases/test_flex_layout.c @@ -1,7 +1,7 @@ #include "ctest.h" #include -#include -#include +#include +#include static void test_flex_layout_with_content_width(float width) { diff --git a/tests/cases/test_font_load.c b/tests/cases/test_font_load.c index 3c85dc03f..a63b2fdda 100644 --- a/tests/cases/test_font_load.c +++ b/tests/cases/test_font_load.c @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include "ctest.h" diff --git a/tests/cases/test_mainloop.c b/tests/cases/test_mainloop.c index 69c481e62..01ed1a509 100644 --- a/tests/cases/test_mainloop.c +++ b/tests/cases/test_mainloop.c @@ -1,8 +1,8 @@ #include #include -#include +#include #include -#include +#include #include #include "ctest.h" diff --git a/tests/cases/test_scrollbar.c b/tests/cases/test_scrollbar.c index cf25c4b70..2d33cd375 100644 --- a/tests/cases/test_scrollbar.c +++ b/tests/cases/test_scrollbar.c @@ -1,9 +1,9 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include "ctest.h" /* clang-format off */ diff --git a/tests/cases/test_textedit.c b/tests/cases/test_textedit.c index 9ea6d44d8..6c0eaf21a 100644 --- a/tests/cases/test_textedit.c +++ b/tests/cases/test_textedit.c @@ -1,6 +1,6 @@ #include -#include -#include +#include +#include #include "ctest.h" void test_textedit(void) diff --git a/tests/cases/test_textview_resize.c b/tests/cases/test_textview_resize.c index 24f1410f8..a878f9b29 100644 --- a/tests/cases/test_textview_resize.c +++ b/tests/cases/test_textview_resize.c @@ -1,5 +1,5 @@ #include -#include +#include #include #include "ctest.h" diff --git a/tests/cases/test_widget_event.c b/tests/cases/test_widget_event.c index 394dec11a..c832bddba 100644 --- a/tests/cases/test_widget_event.c +++ b/tests/cases/test_widget_event.c @@ -1,6 +1,6 @@ #include #include -#include +#include #include "ctest.h" void test_widget_mouse_event(void) diff --git a/tests/cases/test_widget_opacity.c b/tests/cases/test_widget_opacity.c index df5a2c799..55b5e2570 100644 --- a/tests/cases/test_widget_opacity.c +++ b/tests/cases/test_widget_opacity.c @@ -1,11 +1,6 @@ #include #include #include -#include -#include -#include -#include -#include #include "ctest.h" #define PARENT_OPACITY 0.8f diff --git a/tests/cases/test_widget_rect.c b/tests/cases/test_widget_rect.c index 8da42a484..88e76f389 100644 --- a/tests/cases/test_widget_rect.c +++ b/tests/cases/test_widget_rect.c @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include "ctest.h" void test_widget_rect(void) diff --git a/tests/cases/test_xml_parser.c b/tests/cases/test_xml_parser.c index e92cfc5c7..c939395e8 100644 --- a/tests/cases/test_xml_parser.c +++ b/tests/cases/test_xml_parser.c @@ -1,6 +1,6 @@ #include -#include -#include +#include +#include #include "ctest.h" static void check_widget_attribute(void) diff --git a/tests/helloworld_uwp/App.cpp b/tests/helloworld_uwp/App.cpp index dde1cd21a..b7d1eacd8 100644 --- a/tests/helloworld_uwp/App.cpp +++ b/tests/helloworld_uwp/App.cpp @@ -1,10 +1,10 @@ #include "pch.h" #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include LCUI_APP_H class App : public LCUI::Application diff --git a/tests/test_border.c b/tests/test_border.c index 2f2c74ba3..14a8eafe6 100644 --- a/tests/test_border.c +++ b/tests/test_border.c @@ -1,6 +1,6 @@ #include #include -#include +#include #include int main(void) diff --git a/tests/test_box_shadow.c b/tests/test_box_shadow.c index bd734763d..764e9ab39 100644 --- a/tests/test_box_shadow.c +++ b/tests/test_box_shadow.c @@ -1,5 +1,5 @@ #include -#include +#include #include int main(void) diff --git a/tests/test_image_scaling_bench.c b/tests/test_image_scaling_bench.c index 221fdafec..da844b321 100644 --- a/tests/test_image_scaling_bench.c +++ b/tests/test_image_scaling_bench.c @@ -3,8 +3,8 @@ #include #include #include -#include -#include +#include +#include #include int main(int argc, char **argv) diff --git a/tests/test_render.c b/tests/test_render.c index 89b81d8b7..c4bd51d00 100644 --- a/tests/test_render.c +++ b/tests/test_render.c @@ -4,7 +4,7 @@ #include #include #include -#include +#include #define SCREEN_WIDTH 1600 #define SCREEN_HEIGHT 900 diff --git a/tests/test_scaling_support.c b/tests/test_scaling_support.c index afcce3260..b6d9fb163 100644 --- a/tests/test_scaling_support.c +++ b/tests/test_scaling_support.c @@ -1,6 +1,6 @@ #include #include -#include +#include #include enum { TYPE_DENSITY, TYPE_SCALED_DENSITY, TYPE_SCALE }; diff --git a/tests/test_widget.c b/tests/test_widget.c index 729d2d959..e84cc3238 100644 --- a/tests/test_widget.c +++ b/tests/test_widget.c @@ -1,7 +1,7 @@ #include #include -#include -#include +#include +#include int main(void) { diff --git a/tests/test_widget_render.c b/tests/test_widget_render.c index 17a95a0fe..848c8a87e 100644 --- a/tests/test_widget_render.c +++ b/tests/test_widget_render.c @@ -1,6 +1,6 @@ #include #include -#include +#include int main(void) { diff --git a/xmake.lua b/xmake.lua index 24754b72b..3ae2416cf 100644 --- a/xmake.lua +++ b/xmake.lua @@ -11,6 +11,11 @@ add_includedirs( "lib/pandagl/include", "lib/css/include", "lib/platform/include", + "lib/ui/include", + "lib/ui-server/include", + "lib/ui-widgets/include", + "lib/ui-cursor/include", + "lib/ui-builder/include", "include" ) includes("lib/*/xmake.lua") @@ -92,11 +97,6 @@ target("headers") before_build(function (target) -- Copy the header file of the internal library to the LCUI header file directory os.cp("$(projectdir)/lib/thread/include/*.h", "$(projectdir)/include/LCUI/") - os.cp("$(projectdir)/lib/ui/include/*.h", "$(projectdir)/include/LCUI/") - os.cp("$(projectdir)/lib/ui-widgets/include/*.h", "$(projectdir)/include/LCUI/ui/widgets/") - os.cp("$(projectdir)/lib/ui-cursor/include/*.h", "$(projectdir)/include/LCUI/ui/") - os.cp("$(projectdir)/lib/ui-builder/include/*.h", "$(projectdir)/include/LCUI/ui/") - os.cp("$(projectdir)/lib/ui-server/include/*.h", "$(projectdir)/include/LCUI/ui/") os.cp("$(projectdir)/lib/timer/include/*.h", "$(projectdir)/include/LCUI/") os.cp("$(projectdir)/lib/worker/include/*.h", "$(projectdir)/include/LCUI/") end)