diff --git a/demos/render/lv_demo_render.c b/demos/render/lv_demo_render.c index 6a3a3e02b..0c0f61836 100644 --- a/demos/render/lv_demo_render.c +++ b/demos/render/lv_demo_render.c @@ -214,6 +214,7 @@ static lv_obj_t * box_shadow_obj_create(lv_obj_t * parent, int32_t col, int32_t lv_obj_t * obj = lv_obj_create(parent); lv_obj_remove_style_all(obj); lv_obj_set_style_bg_opa(obj, LV_OPA_20, 0); + lv_obj_set_style_bg_color(obj, lv_color_black(), 0); lv_obj_set_style_shadow_color(obj, lv_color_hex3(0xf00), 0); lv_obj_set_style_opa(obj, opa_saved, 0); lv_obj_set_size(obj, DEF_WIDTH - 20, DEF_HEIGHT - 5); @@ -452,6 +453,7 @@ static lv_obj_t * arc_obj_create(lv_obj_t * parent, int32_t col, int32_t row, in lv_obj_t * obj = lv_arc_create(parent); lv_obj_remove_style_all(obj); lv_obj_set_style_arc_width(obj, w, 0); + lv_obj_set_style_arc_color(obj, lv_color_white(), 0); lv_obj_set_style_opa(obj, opa_saved, 0); lv_arc_set_bg_angles(obj, start, end); lv_obj_set_size(obj, DEF_HEIGHT, DEF_HEIGHT); diff --git a/docs/overview/style-props.md b/docs/overview/style-props.md new file mode 100644 index 000000000..89d494be4 --- /dev/null +++ b/docs/overview/style-props.md @@ -0,0 +1,1033 @@ +# Style properties + +## Size and position +Properties related to size, position, alignment and layout of the objects. + +### width +Sets the width of object. Pixel, percentage and `LV_SIZE_CONTENT` values can be used. Percentage values are relative to the width of the parent's content area. + + +### min_width +Sets a minimal width. Pixel and percentage values can be used. Percentage values are relative to the width of the parent's content area. + + +### max_width +Sets a maximal width. Pixel and percentage values can be used. Percentage values are relative to the width of the parent's content area. + + +### height +Sets the height of object. Pixel, percentage and `LV_SIZE_CONTENT` can be used. Percentage values are relative to the height of the parent's content area. + + +### min_height +Sets a minimal height. Pixel and percentage values can be used. Percentage values are relative to the width of the parent's content area. + + +### max_height +Sets a maximal height. Pixel and percentage values can be used. Percentage values are relative to the height of the parent's content area. + + +### length +Its meaning depends on the type of the widget. For example in case of lv_scale it means the length of the ticks. + + +### x +Set the X coordinate of the object considering the set `align`. Pixel and percentage values can be used. Percentage values are relative to the width of the parent's content area. + + +### y +Set the Y coordinate of the object considering the set `align`. Pixel and percentage values can be used. Percentage values are relative to the height of the parent's content area. + + +### align +Set the alignment which tells from which point of the parent the X and Y coordinates should be interpreted. The possible values are: `LV_ALIGN_DEFAULT`, `LV_ALIGN_TOP_LEFT/MID/RIGHT`, `LV_ALIGN_BOTTOM_LEFT/MID/RIGHT`, `LV_ALIGN_LEFT/RIGHT_MID`, `LV_ALIGN_CENTER`. `LV_ALIGN_DEFAULT` means `LV_ALIGN_TOP_LEFT` with LTR base direction and `LV_ALIGN_TOP_RIGHT` with RTL base direction. + + +### transform_width +Make the object wider on both sides with this value. Pixel and percentage (with `lv_pct(x)`) values can be used. Percentage values are relative to the object's width. + + +### transform_height +Make the object higher on both sides with this value. Pixel and percentage (with `lv_pct(x)`) values can be used. Percentage values are relative to the object's height. + + +### translate_x +Move the object with this value in X direction. Applied after layouts, aligns and other positioning. Pixel and percentage (with `lv_pct(x)`) values can be used. Percentage values are relative to the object's width. + + +### translate_y +Move the object with this value in Y direction. Applied after layouts, aligns and other positioning. Pixel and percentage (with `lv_pct(x)`) values can be used. Percentage values are relative to the object's height. + + +### transform_scale_x +Zoom an objects horizontally. The value 256 (or `LV_SCALE_NONE`) means normal size, 128 half size, 512 double size, and so on + + +### transform_scale_y +Zoom an objects vertically. The value 256 (or `LV_SCALE_NONE`) means normal size, 128 half size, 512 double size, and so on + + +### transform_rotation +Rotate an objects. The value is interpreted in 0.1 degree units. E.g. 450 means 45 deg. + + +### transform_pivot_x +Set the pivot point's X coordinate for transformations. Relative to the object's top left corner' + + +### transform_pivot_y +Set the pivot point's Y coordinate for transformations. Relative to the object's top left corner' + + +### transform_skew_x +Skew an object horizontally. The value is interpreted in 0.1 degree units. E.g. 450 means 45 deg. + + +### transform_skew_y +Skew an object vertically. The value is interpreted in 0.1 degree units. E.g. 450 means 45 deg. + + +## Padding +Properties to describe spacing between the parent's sides and the children and among the children. Very similar to the padding properties in HTML. + +### pad_top +Sets the padding on the top. It makes the content area smaller in this direction. + + +### pad_bottom +Sets the padding on the bottom. It makes the content area smaller in this direction. + + +### pad_left +Sets the padding on the left. It makes the content area smaller in this direction. + + +### pad_right +Sets the padding on the right. It makes the content area smaller in this direction. + + +### pad_row +Sets the padding between the rows. Used by the layouts. + + +### pad_column +Sets the padding between the columns. Used by the layouts. + + +## Margin +Properties to describe spacing around an object. Very similar to the margin properties in HTML. + +### margin_top +Sets the margin on the top. The object will keep this space from its siblings in layouts. + + +### margin_bottom +Sets the margin on the bottom. The object will keep this space from its siblings in layouts. + + +### margin_left +Sets the margin on the left. The object will keep this space from its siblings in layouts. + + +### margin_right +Sets the margin on the right. The object will keep this space from its siblings in layouts. + + +## Background +Properties to describe the background color and image of the objects. + +### bg_color +Set the background color of the object. + + +### bg_opa +Set the opacity of the background. Value 0, `LV_OPA_0` or `LV_OPA_TRANSP` means fully transparent, 255, `LV_OPA_100` or `LV_OPA_COVER` means fully covering, other values or LV_OPA_10, LV_OPA_20, etc means semi transparency. + + +### bg_grad_color +Set the gradient color of the background. Used only if `grad_dir` is not `LV_GRAD_DIR_NONE` + + +### bg_grad_dir +Set the direction of the gradient of the background. The possible values are `LV_GRAD_DIR_NONE/HOR/VER`. + + +### bg_main_stop +Set the point from which the background color should start for gradients. 0 means to top/left side, 255 the bottom/right side, 128 the center, and so on + + +### bg_grad_stop +Set the point from which the background's gradient color should start. 0 means to top/left side, 255 the bottom/right side, 128 the center, and so on + + +### bg_main_opa +Set the opacity of the first gradient color + + +### bg_grad_opa +Set the opacity of the second gradient color + + +### bg_grad +Set the gradient definition. The pointed instance must exist while the object is alive. NULL to disable. It wraps `BG_GRAD_COLOR`, `BG_GRAD_DIR`, `BG_MAIN_STOP` and `BG_GRAD_STOP` into one descriptor and allows creating gradients with more colors too. If it's set other gradient related properties will be ignored' + + +### bg_image_src +Set a background image. Can be a pointer to `lv_image_dsc_t`, a path to a file or an `LV_SYMBOL_...` + + +### bg_image_opa +Set the opacity of the background image. Value 0, `LV_OPA_0` or `LV_OPA_TRANSP` means fully transparent, 255, `LV_OPA_100` or `LV_OPA_COVER` means fully covering, other values or LV_OPA_10, LV_OPA_20, etc means semi transparency. + + +### bg_image_recolor +Set a color to mix to the background image. + + +### bg_image_recolor_opa +Set the intensity of background image recoloring. Value 0, `LV_OPA_0` or `LV_OPA_TRANSP` means no mixing, 255, `LV_OPA_100` or `LV_OPA_COVER` means full recoloring, other values or LV_OPA_10, LV_OPA_20, etc are interpreted proportionally. + + +### bg_image_tiled +If enabled the background image will be tiled. The possible values are `true` or `false`. + + +## Border +Properties to describe the borders + +### border_color +Set the color of the border + + +### border_opa +Set the opacity of the border. Value 0, `LV_OPA_0` or `LV_OPA_TRANSP` means fully transparent, 255, `LV_OPA_100` or `LV_OPA_COVER` means fully covering, other values or LV_OPA_10, LV_OPA_20, etc means semi transparency. + + +### border_width +Set the width of the border. Only pixel values can be used. + + +### border_side +Set only which side(s) the border should be drawn. The possible values are `LV_BORDER_SIDE_NONE/TOP/BOTTOM/LEFT/RIGHT/INTERNAL`. OR-ed values can be used as well, e.g. `LV_BORDER_SIDE_TOP | LV_BORDER_SIDE_LEFT`. + + +### border_post +Sets whether the border should be drawn before or after the children are drawn. `true`: after children, `false`: before children + + +## Outline +Properties to describe the outline. It's like a border but drawn outside of the rectangles. + +### outline_width +Set the width of the outline in pixels. + + +### outline_color +Set the color of the outline. + + +### outline_opa +Set the opacity of the outline. Value 0, `LV_OPA_0` or `LV_OPA_TRANSP` means fully transparent, 255, `LV_OPA_100` or `LV_OPA_COVER` means fully covering, other values or LV_OPA_10, LV_OPA_20, etc means semi transparency. + + +### outline_pad +Set the padding of the outline, i.e. the gap between object and the outline. + + +## Shadow +Properties to describe the shadow drawn under the rectangles. + +### shadow_width +Set the width of the shadow in pixels. The value should be >= 0. + + +### shadow_offset_x +Set an offset on the shadow in pixels in X direction. + + +### shadow_offset_y +Set an offset on the shadow in pixels in Y direction. + + +### shadow_spread +Make the shadow calculation to use a larger or smaller rectangle as base. The value can be in pixel to make the area larger/smaller + + +### shadow_color +Set the color of the shadow + + +### shadow_opa +Set the opacity of the shadow. Value 0, `LV_OPA_0` or `LV_OPA_TRANSP` means fully transparent, 255, `LV_OPA_100` or `LV_OPA_COVER` means fully covering, other values or LV_OPA_10, LV_OPA_20, etc means semi transparency. + + +## Image +Properties to describe the images + +### image_opa +Set the opacity of an image. Value 0, `LV_OPA_0` or `LV_OPA_TRANSP` means fully transparent, 255, `LV_OPA_100` or `LV_OPA_COVER` means fully covering, other values or LV_OPA_10, LV_OPA_20, etc means semi transparency. + + +### image_recolor +Set color to mixt to the image. + + +### image_recolor_opa +Set the intensity of the color mixing. Value 0, `LV_OPA_0` or `LV_OPA_TRANSP` means fully transparent, 255, `LV_OPA_100` or `LV_OPA_COVER` means fully covering, other values or LV_OPA_10, LV_OPA_20, etc means semi transparency. + + +## Line +Properties to describe line-like objects + +### line_width +Set the width of the lines in pixel. + + +### line_dash_width +Set the width of dashes in pixel. Note that dash works only on horizontal and vertical lines + + +### line_dash_gap +Set the gap between dashes in pixel. Note that dash works only on horizontal and vertical lines + + +### line_rounded +Make the end points of the lines rounded. `true`: rounded, `false`: perpendicular line ending + + +### line_color +Set the color of the lines. + + +### line_opa +Set the opacity of the lines. + + +## Arc +TODO + +### arc_width +Set the width (thickness) of the arcs in pixel. + + +### arc_rounded +Make the end points of the arcs rounded. `true`: rounded, `false`: perpendicular line ending + + +### arc_color +Set the color of the arc. + + +### arc_opa +Set the opacity of the arcs. + + +### arc_image_src +Set an image from which the arc will be masked out. It's useful to display complex effects on the arcs. Can be a pointer to `lv_image_dsc_t` or a path to a file + + +## Text +Properties to describe the properties of text. All these properties are inherited. + +### text_color +Sets the color of the text. + + +### text_opa +Set the opacity of the text. Value 0, `LV_OPA_0` or `LV_OPA_TRANSP` means fully transparent, 255, `LV_OPA_100` or `LV_OPA_COVER` means fully covering, other values or LV_OPA_10, LV_OPA_20, etc means semi transparency. + + +### text_font +Set the font of the text (a pointer `lv_font_t *`). + + +### text_letter_space +Set the letter space in pixels + + +### text_line_space +Set the line space in pixels. + + +### text_decor +Set decoration for the text. The possible values are `LV_TEXT_DECOR_NONE/UNDERLINE/STRIKETHROUGH`. OR-ed values can be used as well. + + +### text_align +Set how to align the lines of the text. Note that it doesn't align the object itself, only the lines inside the object. The possible values are `LV_TEXT_ALIGN_LEFT/CENTER/RIGHT/AUTO`. `LV_TEXT_ALIGN_AUTO` detect the text base direction and uses left or right alignment accordingly + + +## Miscellaneous +Mixed properties for various purposes. + +### radius +Set the radius on every corner. The value is interpreted in pixel (>= 0) or `LV_RADIUS_CIRCLE` for max. radius + + +### clip_corner +Enable to clip the overflowed content on the rounded corner. Can be `true` or `false`. + + +### opa +Scale down all opacity values of the object by this factor. Value 0, `LV_OPA_0` or `LV_OPA_TRANSP` means fully transparent, 255, `LV_OPA_100` or `LV_OPA_COVER` means fully covering, other values or LV_OPA_10, LV_OPA_20, etc means semi transparency. + + +### opa_layered +First draw the object on the layer, then scale down layer opacity factor. Value 0, `LV_OPA_0` or `LV_OPA_TRANSP` means fully transparent, 255, `LV_OPA_100` or `LV_OPA_COVER` means fully covering, other values or LV_OPA_10, LV_OPA_20, etc means semi transparency. + + +### color_filter_dsc +Mix a color to all colors of the object. + + +### color_filter_opa +The intensity of mixing of color filter. + + +### anim +The animation template for the object's animation. Should be a pointer to `lv_anim_t`. The animation parameters are widget specific, e.g. animation time could be the E.g. blink time of the cursor on the text area or scroll time of a roller. See the widgets' documentation to learn more. + + +### anim_duration +The animation duration in milliseconds. Its meaning is widget specific. E.g. blink time of the cursor on the text area or scroll time of a roller. See the widgets' documentation to learn more. + + +### transition +An initialized `lv_style_transition_dsc_t` to describe a transition. + + +### blend_mode +Describes how to blend the colors to the background. The possible values are `LV_BLEND_MODE_NORMAL/ADDITIVE/SUBTRACTIVE/MULTIPLY` + + +### layout +Set the layout if the object. The children will be repositioned and resized according to the policies set for the layout. For the possible values see the documentation of the layouts. + + +### base_dir +Set the base direction of the object. The possible values are `LV_BIDI_DIR_LTR/RTL/AUTO`. + + +### bitmap_mask_src +If set a layer will be created for the widget and the layer will be masked with this A8 bitmap mask. + + +### rotary_sensitivity +Adjust the sensitivity for rotary encoders in 1/256 unit. It means, 128: slow down the rotary to half, 512: speeds up to double, 256: no change + + +## Flex +Flex layout properties. + +### flex_flow +Defines in which direct the flex layout should arrange the children + + +### flex_main_place +Defines how to align the children in the direction of flex flow + + +### flex_cross_place +Defines how to align the children perpendicular to the direction of flex flow + + +### flex_track_place +Defines how to align the tracks of the flow + + +### flex_grow +Defines how mayn space to take proprtionally the free space of the object's trach + + +## Grid +Grid layout properties. + +### grid_column_dsc_array +An array to describe the columns of the grid. Should be LV_GRID_TEMPLATE_LAST terminated + + +### grid_column_align +Defines how to distribute the columns + + +### grid_row_dsc_array +An array to describe the rows of the grid. Should be LV_GRID_TEMPLATE_LAST terminated + + +### grid_row_align +Defines how to distribute the rows. + + +### grid_cell_column_pos +Set the column in which the object should be placed + + +### grid_cell_x_align +Set how to align the object horizontally. + + +### grid_cell_column_span +Set how many columns the object should span. Needs to be >= 1 + + +### grid_cell_row_pos +Set the row in which the object should be placed + + +### grid_cell_y_align +Set how to align the object vertically. + + +### grid_cell_row_span +Set how many rows the object should span. Needs to be >= 1 + diff --git a/docs/overview/style-props.rst b/docs/overview/style-props.rst index 31f127397..8cbbd8977 100644 --- a/docs/overview/style-props.rst +++ b/docs/overview/style-props.rst @@ -1378,6 +1378,20 @@ If set a layer will be created for the widget and the layer will be masked with
  • Ext. draw No
  • +rotary_sensitivity +~~~~~~~~~~~~~~~~~~ + +Adjust the sensitivity for rotary encoders in 1/256 unit. It means, 128: slow down the rotary to half, 512: speeds up to double, 256: no change + +.. raw:: html + + + Flex ---- diff --git a/docs/porting/indev.rst b/docs/porting/indev.rst index 2bab65e43..d18ca4efb 100644 --- a/docs/porting/indev.rst +++ b/docs/porting/indev.rst @@ -51,8 +51,41 @@ category. } } + +Mouse cursor +~~~~~~~~~~~~ + To set a mouse cursor use :cpp:expr:`lv_indev_set_cursor(indev, &img_cursor)`. +Crown behavior +~~~~~~~~~~~~~~ + +The "Crown" is a rotary device typically found on smart watches. + +When the user clicks somewhere and after that turns the rotary +the last clicked widget will be either scrolled or it's value will be incremented/decremented +(e.g. in case of a slider). + +As this behavior is tightly related to the last clicked widget, the crown support is +an extension of the pointer input device. Just set ``data->diff`` to the number of +turned steps and LVGL will automatically send :cpp:enum:`LV_EVENT_ROTARY` or scroll the widget based on the +``editable`` flag in the widget's class. Non-editable widgets are scrolled and for editable widgets the event is sent. + +To get the steps in an event callback use :cpp:func:`int32_t diff = lv_event_get_rotary_diff(e)` + +The rotary sensitivity can be adjusted on 2 levels: + +1. In the input device by the `indev->rotary_sensitvity` element (1/256 unit) +2. By the `rotary_sensitivity` style property in the widget (1/256 unit) + +The final diff is calculated like this: + +``diff_final = diff_in * (indev_sensitivity / 256) + (widget_sensitivity / 256); `` + +For example, if both the indev and widget sensitivity is set to 128 (0.5), the input diff. will be +multiplied by 0.25 (divided by 4). The value of the widget will be incremented by this value or +the widget will be scrolled this amount of pixels. + Keypad or keyboard ------------------ diff --git a/lv_conf_template.h b/lv_conf_template.h index 6b6b9212e..4ab3155da 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -848,11 +848,12 @@ /*Use SDL to open window on PC and handle mouse and keyboard*/ #define LV_USE_SDL 0 #if LV_USE_SDL - #define LV_SDL_INCLUDE_PATH - #define LV_SDL_RENDER_MODE LV_DISPLAY_RENDER_MODE_DIRECT /*LV_DISPLAY_RENDER_MODE_DIRECT is recommended for best performance*/ - #define LV_SDL_BUF_COUNT 1 /*1 or 2*/ - #define LV_SDL_FULLSCREEN 0 /*1: Make the window full screen by default*/ - #define LV_SDL_DIRECT_EXIT 1 /*1: Exit the application when all SDL windows are closed*/ + #define LV_SDL_INCLUDE_PATH + #define LV_SDL_RENDER_MODE LV_DISPLAY_RENDER_MODE_DIRECT /*LV_DISPLAY_RENDER_MODE_DIRECT is recommended for best performance*/ + #define LV_SDL_BUF_COUNT 1 /*1 or 2*/ + #define LV_SDL_FULLSCREEN 0 /*1: Make the window full screen by default*/ + #define LV_SDL_DIRECT_EXIT 1 /*1: Exit the application when all SDL windows are closed*/ + #define LV_SDL_MOUSEWHEEL_MODE LV_SDL_MOUSEWHEEL_MODE_ENCODER /*LV_SDL_MOUSEWHEEL_MODE_ENCODER/CROWN*/ #endif /*Use X11 to open window on Linux desktop and handle mouse and keyboard*/ diff --git a/scripts/style_api_gen.py b/scripts/style_api_gen.py index f08d550af..fdf11a83f 100755 --- a/scripts/style_api_gen.py +++ b/scripts/style_api_gen.py @@ -393,6 +393,10 @@ props = [ 'style_type': 'ptr', 'var_type': 'const lv_image_dsc_t *', 'default':'`NULL`', 'inherited': 0, 'layout': 0, 'ext_draw': 0, 'dsc': "If set a layer will be created for the widget and the layer will be masked with this A8 bitmap mask."}, +{'name': 'ROTARY_SENSITIVITY', + 'style_type': 'num', 'var_type': 'uint32_t', 'default':'`256`', 'inherited': 1, 'layout': 0, 'ext_draw': 0, + 'dsc': "Adjust the sensitivity for rotary encoders in 1/256 unit. It means, 128: slow down the rotary to half, 512: speeds up to double, 256: no change"}, + {'section': 'Flex', 'dsc':'Flex layout properties.', 'guard':'LV_USE_FLEX'}, diff --git a/src/core/lv_obj_event.c b/src/core/lv_obj_event.c index f88128adf..0553f3d77 100644 --- a/src/core/lv_obj_event.c +++ b/src/core/lv_obj_event.c @@ -242,6 +242,19 @@ uint32_t lv_event_get_key(lv_event_t * e) } } +int32_t lv_event_get_rotary_diff(lv_event_t * e) +{ + if(e->code == LV_EVENT_ROTARY) { + int32_t * r = lv_event_get_param(e); + if(r) return *r; + else return 0; + } + else { + LV_LOG_WARN("Not interpreted with this event code"); + return 0; + } +} + lv_anim_t * lv_event_get_scroll_anim(lv_event_t * e) { if(e->code == LV_EVENT_SCROLL_BEGIN) { diff --git a/src/core/lv_obj_event.h b/src/core/lv_obj_event.h index 769b5fd2e..40a002d8a 100644 --- a/src/core/lv_obj_event.h +++ b/src/core/lv_obj_event.h @@ -151,6 +151,13 @@ const lv_area_t * lv_event_get_old_size(lv_event_t * e); */ uint32_t lv_event_get_key(lv_event_t * e); +/** + * Get the signed rotary encoder diff. passed as parameter to an event. Can be used in `LV_EVENT_ROTARY` + * @param e pointer to an event + * @return the triggering key or NULL if called on an unrelated event + */ +int32_t lv_event_get_rotary_diff(lv_event_t * e); + /** * Get the animation descriptor of a scrolling. Can be used in `LV_EVENT_SCROLL_BEGIN` * @param e pointer to an event diff --git a/src/core/lv_obj_style.c b/src/core/lv_obj_style.c index 020cf3ba1..2273c0e41 100644 --- a/src/core/lv_obj_style.c +++ b/src/core/lv_obj_style.c @@ -320,70 +320,6 @@ void lv_obj_enable_style_refresh(bool en) style_refr = en; } -static inline lv_style_value_t lv_style_prop_get_default_inlined(lv_style_prop_t prop) -{ - const lv_color_t black = LV_COLOR_MAKE(0x00, 0x00, 0x00); - const lv_color_t white = LV_COLOR_MAKE(0xff, 0xff, 0xff); - switch(prop) { - case LV_STYLE_TRANSFORM_SCALE_X: - case LV_STYLE_TRANSFORM_SCALE_Y: - return (lv_style_value_t) { - .num = LV_SCALE_NONE - }; - case LV_STYLE_BG_COLOR: - return (lv_style_value_t) { - .color = black - }; - case LV_STYLE_BG_GRAD_COLOR: - case LV_STYLE_BORDER_COLOR: - case LV_STYLE_SHADOW_COLOR: - case LV_STYLE_OUTLINE_COLOR: - case LV_STYLE_ARC_COLOR: - case LV_STYLE_LINE_COLOR: - case LV_STYLE_TEXT_COLOR: - case LV_STYLE_IMAGE_RECOLOR: - return (lv_style_value_t) { - .color = white - }; - case LV_STYLE_OPA: - case LV_STYLE_OPA_LAYERED: - case LV_STYLE_BORDER_OPA: - case LV_STYLE_TEXT_OPA: - case LV_STYLE_IMAGE_OPA: - case LV_STYLE_BG_GRAD_OPA: - case LV_STYLE_BG_MAIN_OPA: - case LV_STYLE_BG_IMAGE_OPA: - case LV_STYLE_OUTLINE_OPA: - case LV_STYLE_SHADOW_OPA: - case LV_STYLE_LINE_OPA: - case LV_STYLE_ARC_OPA: - return (lv_style_value_t) { - .num = LV_OPA_COVER - }; - case LV_STYLE_BG_GRAD_STOP: - return (lv_style_value_t) { - .num = 255 - }; - case LV_STYLE_BORDER_SIDE: - return (lv_style_value_t) { - .num = LV_BORDER_SIDE_FULL - }; - case LV_STYLE_TEXT_FONT: - return (lv_style_value_t) { - .ptr = LV_FONT_DEFAULT - }; - case LV_STYLE_MAX_WIDTH: - case LV_STYLE_MAX_HEIGHT: - return (lv_style_value_t) { - .num = LV_COORD_MAX - }; - default: - return (lv_style_value_t) { - .ptr = 0 - }; - } -} - lv_style_value_t lv_obj_get_style_prop(const lv_obj_t * obj, lv_part_t part, lv_style_prop_t prop) { LV_ASSERT_NULL(obj) @@ -395,7 +331,7 @@ lv_style_value_t lv_obj_get_style_prop(const lv_obj_t * obj, lv_part_t part, lv_ found = get_selector_style_prop(obj, selector, prop, &value_act); if(found == LV_STYLE_RES_FOUND) return value_act; - return lv_style_prop_get_default_inlined(prop); + return lv_style_prop_get_default(prop); } bool lv_obj_has_style_prop(const lv_obj_t * obj, lv_style_selector_t selector, lv_style_prop_t prop) diff --git a/src/core/lv_obj_style_gen.c b/src/core/lv_obj_style_gen.c index cee767287..f9b21e807 100644 --- a/src/core/lv_obj_style_gen.c +++ b/src/core/lv_obj_style_gen.c @@ -761,6 +761,14 @@ void lv_obj_set_style_bitmap_mask_src(lv_obj_t * obj, const lv_image_dsc_t * val }; lv_obj_set_local_style_prop(obj, LV_STYLE_BITMAP_MASK_SRC, v, selector); } + +void lv_obj_set_style_rotary_sensitivity(lv_obj_t * obj, uint32_t value, lv_style_selector_t selector) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_obj_set_local_style_prop(obj, LV_STYLE_ROTARY_SENSITIVITY, v, selector); +} #if LV_USE_FLEX void lv_obj_set_style_flex_flow(lv_obj_t * obj, lv_flex_flow_t value, lv_style_selector_t selector) diff --git a/src/core/lv_obj_style_gen.h b/src/core/lv_obj_style_gen.h index c3895287e..c3bd10761 100644 --- a/src/core/lv_obj_style_gen.h +++ b/src/core/lv_obj_style_gen.h @@ -642,6 +642,12 @@ static inline const lv_image_dsc_t * lv_obj_get_style_bitmap_mask_src(const lv_o return (const lv_image_dsc_t *)v.ptr; } +static inline uint32_t lv_obj_get_style_rotary_sensitivity(const lv_obj_t * obj, uint32_t part) +{ + lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ROTARY_SENSITIVITY); + return (uint32_t)v.num; +} + #if LV_USE_FLEX static inline lv_flex_flow_t lv_obj_get_style_flex_flow(const lv_obj_t * obj, uint32_t part) { @@ -832,6 +838,7 @@ void lv_obj_set_style_blend_mode(lv_obj_t * obj, lv_blend_mode_t value, lv_style void lv_obj_set_style_layout(lv_obj_t * obj, uint16_t value, lv_style_selector_t selector); void lv_obj_set_style_base_dir(lv_obj_t * obj, lv_base_dir_t value, lv_style_selector_t selector); void lv_obj_set_style_bitmap_mask_src(lv_obj_t * obj, const lv_image_dsc_t * value, lv_style_selector_t selector); +void lv_obj_set_style_rotary_sensitivity(lv_obj_t * obj, uint32_t value, lv_style_selector_t selector); #if LV_USE_FLEX void lv_obj_set_style_flex_flow(lv_obj_t * obj, lv_flex_flow_t value, lv_style_selector_t selector); void lv_obj_set_style_flex_main_place(lv_obj_t * obj, lv_flex_align_t value, lv_style_selector_t selector); diff --git a/src/drivers/sdl/lv_sdl_mouse.c b/src/drivers/sdl/lv_sdl_mouse.c index 124cd1740..a6c1c692a 100644 --- a/src/drivers/sdl/lv_sdl_mouse.c +++ b/src/drivers/sdl/lv_sdl_mouse.c @@ -35,6 +35,9 @@ typedef struct { int16_t last_x; int16_t last_y; bool left_button_down; +#if LV_SDL_MOUSEWHEEL_MODE == LV_SDL_MOUSEWHEEL_MODE_CROWN + int32_t diff; +#endif } lv_sdl_mouse_t; /********************** @@ -76,6 +79,10 @@ static void sdl_mouse_read(lv_indev_t * indev, lv_indev_data_t * data) data->point.x = dsc->last_x; data->point.y = dsc->last_y; data->state = dsc->left_button_down ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED; +#if LV_SDL_MOUSEWHEEL_MODE == LV_SDL_MOUSEWHEEL_MODE_CROWN + data->enc_diff = dsc->diff; + dsc->diff = 0; +#endif } static void release_indev_cb(lv_event_t * e) @@ -101,7 +108,11 @@ void _lv_sdl_mouse_handler(SDL_Event * event) case SDL_MOUSEMOTION: win_id = event->motion.windowID; break; - +#if LV_SDL_MOUSEWHEEL_MODE == LV_SDL_MOUSEWHEEL_MODE_CROWN + case SDL_MOUSEWHEEL: + win_id = event->wheel.windowID; + break; +#endif case SDL_FINGERUP: case SDL_FINGERDOWN: case SDL_FINGERMOTION: @@ -174,6 +185,17 @@ void _lv_sdl_mouse_handler(SDL_Event * event) indev_dev->last_x = (int16_t)((float)hor_res * event->tfinger.x / zoom); indev_dev->last_y = (int16_t)((float)ver_res * event->tfinger.y / zoom); break; + case SDL_MOUSEWHEEL: +#if LV_SDL_MOUSEWHEEL_MODE == LV_SDL_MOUSEWHEEL_MODE_CROWN +#ifdef __EMSCRIPTEN__ + /*Escripten scales it wrong*/ + if(event->wheel.y < 0) dsc->diff++; + if(event->wheel.y > 0) dsc->diff--; +#else + indev_dev->diff = -event->wheel.y; +#endif /*__EMSCRIPTEN__*/ +#endif /*LV_SDL_MOUSEWHEEL_MODE == LV_SDL_MOUSEWHEEL_MODE_CROWN*/ + break; } lv_indev_read(indev); } diff --git a/src/drivers/sdl/lv_sdl_mousewheel.c b/src/drivers/sdl/lv_sdl_mousewheel.c index c75fbc4ee..f331e3788 100644 --- a/src/drivers/sdl/lv_sdl_mousewheel.c +++ b/src/drivers/sdl/lv_sdl_mousewheel.c @@ -7,7 +7,7 @@ * INCLUDES *********************/ #include "lv_sdl_mousewheel.h" -#if LV_USE_SDL +#if LV_USE_SDL && LV_SDL_MOUSEWHEEL_MODE == LV_SDL_MOUSEWHEEL_MODE_ENCODER #include "../../core/lv_group.h" #include "../../indev/lv_indev_private.h" diff --git a/src/drivers/sdl/lv_sdl_mousewheel.h b/src/drivers/sdl/lv_sdl_mousewheel.h index 6adf6ee02..7ca34bdbb 100644 --- a/src/drivers/sdl/lv_sdl_mousewheel.h +++ b/src/drivers/sdl/lv_sdl_mousewheel.h @@ -14,7 +14,7 @@ extern "C" { * INCLUDES *********************/ #include "lv_sdl_window.h" -#if LV_USE_SDL +#if LV_USE_SDL && LV_SDL_MOUSEWHEEL_MODE == LV_SDL_MOUSEWHEEL_MODE_ENCODER /********************* * DEFINES diff --git a/src/drivers/sdl/lv_sdl_window.c b/src/drivers/sdl/lv_sdl_window.c index 76addcc53..b4300666f 100644 --- a/src/drivers/sdl/lv_sdl_window.c +++ b/src/drivers/sdl/lv_sdl_window.c @@ -253,7 +253,9 @@ static void sdl_event_handler(lv_timer_t * t) SDL_Event event; while(SDL_PollEvent(&event)) { _lv_sdl_mouse_handler(&event); +#if LV_SDL_MOUSEWHEEL_MODE == LV_SDL_MOUSEWHEEL_MODE_ENCODER _lv_sdl_mousewheel_handler(&event); +#endif _lv_sdl_keyboard_handler(&event); if(event.type == SDL_WINDOWEVENT) { diff --git a/src/drivers/sdl/lv_sdl_window.h b/src/drivers/sdl/lv_sdl_window.h index 53c7b194b..4a3901fdc 100644 --- a/src/drivers/sdl/lv_sdl_window.h +++ b/src/drivers/sdl/lv_sdl_window.h @@ -23,6 +23,10 @@ extern "C" { * DEFINES *********************/ +/* Possible values of LV_SDL_MOUSEWHEEL_MODE */ +#define LV_SDL_MOUSEWHEEL_MODE_ENCODER 0 /* The mousewheel emulates an encoder input device*/ +#define LV_SDL_MOUSEWHEEL_MODE_CROWN 1 /* The mousewheel emulates a smart watch crown*/ + /********************** * TYPEDEFS **********************/ diff --git a/src/indev/lv_indev.c b/src/indev/lv_indev.c index 3169dd0ec..66624922c 100644 --- a/src/indev/lv_indev.c +++ b/src/indev/lv_indev.c @@ -43,6 +43,9 @@ /*Gesture min velocity at release before swipe (pixels)*/ #define LV_INDEV_DEF_GESTURE_MIN_VELOCITY 3 +/**< Rotary diff count will be multiplied by this and divided by 256 */ +#define LV_INDEV_DEF_ROTARY_SENSITIVITY 256 + #if LV_INDEV_DEF_SCROLL_THROW <= 0 #warning "LV_INDEV_DEF_SCROLL_THROW must be greater than 0" #endif @@ -64,6 +67,7 @@ static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data); static void indev_button_proc(lv_indev_t * i, lv_indev_data_t * data); static void indev_proc_press(lv_indev_t * indev); static void indev_proc_release(lv_indev_t * indev); +static void indev_proc_pointer_diff(lv_indev_t * indev); static lv_obj_t * pointer_search_obj(lv_display_t * disp, lv_point_t * p); static void indev_proc_reset_query_handler(lv_indev_t * indev); static void indev_click_focus(lv_indev_t * indev); @@ -130,6 +134,7 @@ lv_indev_t * lv_indev_create(void) indev->long_press_repeat_time = LV_INDEV_DEF_LONG_PRESS_REP_TIME; indev->gesture_limit = LV_INDEV_DEF_GESTURE_LIMIT; indev->gesture_min_velocity = LV_INDEV_DEF_GESTURE_MIN_VELOCITY; + indev->rotary_sensitvity = LV_INDEV_DEF_ROTARY_SENSITIVITY; return indev; } @@ -660,6 +665,10 @@ static void indev_pointer_proc(lv_indev_t * i, lv_indev_data_t * data) i->pointer.act_point.x = data->point.x; i->pointer.act_point.y = data->point.y; + i->pointer.diff = data->enc_diff; + + /*Process the diff first as scrolling will be processed in indev_proc_release*/ + indev_proc_pointer_diff(i); if(i->state == LV_INDEV_STATE_PRESSED) { indev_proc_press(i); @@ -670,6 +679,7 @@ static void indev_pointer_proc(lv_indev_t * i, lv_indev_data_t * data) i->pointer.last_point.x = i->pointer.act_point.x; i->pointer.last_point.y = i->pointer.act_point.y; + } /** @@ -1117,8 +1127,9 @@ static void indev_proc_press(lv_indev_t * indev) if(new_obj_searched && indev->pointer.scroll_obj) { /*Attempt to stop scroll throw animation firstly*/ - if(!indev->scroll_throw_anim || !lv_anim_delete(indev, indev_scroll_throw_anim_cb)) { - indev_scroll_throw_anim_reset(indev); + if(indev->scroll_throw_anim) { + lv_anim_delete(indev, indev_scroll_throw_anim_cb); + indev->scroll_throw_anim = NULL; } _lv_indev_scroll_throw_handler(indev); @@ -1301,7 +1312,6 @@ static void indev_proc_release(lv_indev_t * indev) lv_point_transform(&indev->pointer.scroll_throw_vect_ori, angle, scale_x, scale_y, &pivot, false); } } - } if(scroll_obj) { @@ -1313,6 +1323,40 @@ static void indev_proc_release(lv_indev_t * indev) } } +static void indev_proc_pointer_diff(lv_indev_t * indev) +{ + lv_obj_t * obj = indev->pointer.last_pressed; + if(obj == NULL) return; + if(indev->pointer.diff == 0) return; + + indev_obj_act = obj; + + bool editable = lv_obj_is_editable(obj); + + if(editable) { + uint32_t indev_sensitivity = indev->rotary_sensitvity; + uint32_t obj_sensitivity = lv_obj_get_style_rotary_sensitivity(indev_obj_act, 0); + int32_t diff = (int32_t)((int32_t)indev->pointer.diff * indev_sensitivity * obj_sensitivity + 32768) >> 16; + send_event(LV_EVENT_ROTARY, &diff); + } + else { + + int32_t vect = indev->pointer.diff > 0 ? indev->scroll_limit : -indev->scroll_limit; + indev->pointer.vect.y = vect; + indev->pointer.act_obj = obj; + lv_obj_t * scroll_obj = lv_indev_find_scroll_obj(indev); + if(scroll_obj == NULL) return; + uint32_t indev_sensitivity = indev->rotary_sensitvity; + uint32_t obj_sensitivity = lv_obj_get_style_rotary_sensitivity(scroll_obj, 0); + int32_t diff = (int32_t)((int32_t)indev->pointer.diff * indev_sensitivity * obj_sensitivity + 32768) >> 16; + + indev->pointer.scroll_throw_vect.y = diff; + indev->pointer.scroll_throw_vect_ori.y = diff; + _lv_indev_scroll_handler(indev); + } + +} + static lv_obj_t * pointer_search_obj(lv_display_t * disp, lv_point_t * p) { indev_obj_act = lv_indev_search_obj(lv_display_get_layer_sys(disp), p); @@ -1545,7 +1589,8 @@ static lv_result_t send_event(lv_event_code_t code, void * param) code == LV_EVENT_CLICKED || code == LV_EVENT_RELEASED || code == LV_EVENT_LONG_PRESSED || - code == LV_EVENT_LONG_PRESSED_REPEAT) { + code == LV_EVENT_LONG_PRESSED_REPEAT || + code == LV_EVENT_ROTARY) { lv_indev_send_event(indev_act, code, indev_obj_act); if(indev_reset_check(indev_act)) return LV_RESULT_INVALID; } diff --git a/src/indev/lv_indev_private.h b/src/indev/lv_indev_private.h index e2a00ff4a..96ba4739a 100644 --- a/src/indev/lv_indev_private.h +++ b/src/indev/lv_indev_private.h @@ -69,6 +69,9 @@ struct _lv_indev_t { /**< Repeated trigger period in long press [ms]*/ uint16_t long_press_repeat_time; + /**< Rotary diff count will be multiplied by this value and divided by 256*/ + int32_t rotary_sensitvity; + struct { /*Pointer and button data*/ lv_point_t act_point; /**< Current point of input device.*/ @@ -84,6 +87,7 @@ struct _lv_indev_t { lv_obj_t * last_pressed; /*The lastly pressed object*/ lv_area_t scroll_area; lv_point_t gesture_sum; /*Count the gesture pixels to check LV_INDEV_DEF_GESTURE_LIMIT*/ + int32_t diff; /*Flags*/ lv_dir_t scroll_dir : 4; @@ -100,14 +104,22 @@ struct _lv_indev_t { lv_group_t * group; /**< Keypad destination group*/ const lv_point_t * btn_points; /**< Array points assigned to the button ()screen will be pressed here by the buttons*/ - lv_event_list_t event_list; lv_anim_t * scroll_throw_anim; }; + /********************** * GLOBAL PROTOTYPES **********************/ +/** + * Find a scrollable object based on the current scroll vector in the indev. + * In handles scroll propagation to the parent if needed, and scroll directions too. + * @param indev pointer to an indev + * @return the found scrollable object or NULL if not found. + */ +lv_obj_t * lv_indev_find_scroll_obj(lv_indev_t * indev); + /********************** * MACROS **********************/ diff --git a/src/indev/lv_indev_scroll.c b/src/indev/lv_indev_scroll.c index e6d98c83e..947bda5e6 100644 --- a/src/indev/lv_indev_scroll.c +++ b/src/indev/lv_indev_scroll.c @@ -22,7 +22,6 @@ /********************** * STATIC PROTOTYPES **********************/ -static lv_obj_t * find_scroll_obj(lv_indev_t * indev); static void init_scroll_limits(lv_indev_t * indev); static int32_t find_snap_point_x(const lv_obj_t * obj, int32_t min, int32_t max, int32_t ofs); static int32_t find_snap_point_y(const lv_obj_t * obj, int32_t min, int32_t max, int32_t ofs); @@ -51,7 +50,7 @@ void _lv_indev_scroll_handler(lv_indev_t * indev) lv_obj_t * scroll_obj = indev->pointer.scroll_obj; /*If there is no scroll object yet try to find one*/ if(scroll_obj == NULL) { - scroll_obj = find_scroll_obj(indev); + scroll_obj = lv_indev_find_scroll_obj(indev); if(scroll_obj == NULL) return; init_scroll_limits(indev); @@ -254,11 +253,7 @@ void lv_indev_scroll_get_snap_dist(lv_obj_t * obj, lv_point_t * p) p->y = find_snap_point_y(obj, obj->coords.y1, obj->coords.y2, 0); } -/********************** - * STATIC FUNCTIONS - **********************/ - -static lv_obj_t * find_scroll_obj(lv_indev_t * indev) +lv_obj_t * lv_indev_find_scroll_obj(lv_indev_t * indev) { lv_obj_t * obj_candidate = NULL; lv_dir_t dir_candidate = LV_DIR_NONE; @@ -389,6 +384,10 @@ static lv_obj_t * find_scroll_obj(lv_indev_t * indev) return obj_candidate; } +/********************** + * STATIC FUNCTIONS + **********************/ + static void init_scroll_limits(lv_indev_t * indev) { lv_obj_t * obj = indev->pointer.scroll_obj; diff --git a/src/lv_conf_internal.h b/src/lv_conf_internal.h index 80141a1ad..672d3a77a 100644 --- a/src/lv_conf_internal.h +++ b/src/lv_conf_internal.h @@ -2712,14 +2712,14 @@ #ifdef CONFIG_LV_SDL_INCLUDE_PATH #define LV_SDL_INCLUDE_PATH CONFIG_LV_SDL_INCLUDE_PATH #else - #define LV_SDL_INCLUDE_PATH + #define LV_SDL_INCLUDE_PATH #endif #endif #ifndef LV_SDL_RENDER_MODE #ifdef CONFIG_LV_SDL_RENDER_MODE #define LV_SDL_RENDER_MODE CONFIG_LV_SDL_RENDER_MODE #else - #define LV_SDL_RENDER_MODE LV_DISPLAY_RENDER_MODE_DIRECT /*LV_DISPLAY_RENDER_MODE_DIRECT is recommended for best performance*/ + #define LV_SDL_RENDER_MODE LV_DISPLAY_RENDER_MODE_DIRECT /*LV_DISPLAY_RENDER_MODE_DIRECT is recommended for best performance*/ #endif #endif #ifndef LV_SDL_BUF_COUNT @@ -2730,14 +2730,14 @@ #define LV_SDL_BUF_COUNT 0 #endif #else - #define LV_SDL_BUF_COUNT 1 /*1 or 2*/ + #define LV_SDL_BUF_COUNT 1 /*1 or 2*/ #endif #endif #ifndef LV_SDL_FULLSCREEN #ifdef CONFIG_LV_SDL_FULLSCREEN #define LV_SDL_FULLSCREEN CONFIG_LV_SDL_FULLSCREEN #else - #define LV_SDL_FULLSCREEN 0 /*1: Make the window full screen by default*/ + #define LV_SDL_FULLSCREEN 0 /*1: Make the window full screen by default*/ #endif #endif #ifndef LV_SDL_DIRECT_EXIT @@ -2748,7 +2748,14 @@ #define LV_SDL_DIRECT_EXIT 0 #endif #else - #define LV_SDL_DIRECT_EXIT 1 /*1: Exit the application when all SDL windows are closed*/ + #define LV_SDL_DIRECT_EXIT 1 /*1: Exit the application when all SDL windows are closed*/ + #endif + #endif + #ifndef LV_SDL_MOUSEWHEEL_MODE + #ifdef CONFIG_LV_SDL_MOUSEWHEEL_MODE + #define LV_SDL_MOUSEWHEEL_MODE CONFIG_LV_SDL_MOUSEWHEEL_MODE + #else + #define LV_SDL_MOUSEWHEEL_MODE LV_SDL_MOUSEWHEEL_MODE_ENCODER /*LV_SDL_MOUSEWHEEL_MODE_ENCODER/CROWN*/ #endif #endif #endif diff --git a/src/misc/lv_event.h b/src/misc/lv_event.h index 1e807819b..2eeb5cdf5 100644 --- a/src/misc/lv_event.h +++ b/src/misc/lv_event.h @@ -57,6 +57,7 @@ typedef enum { LV_EVENT_SCROLL, /**< Scrolling*/ LV_EVENT_GESTURE, /**< A gesture is detected. Get the gesture with `lv_indev_get_gesture_dir(lv_indev_active());` */ LV_EVENT_KEY, /**< A key is sent to the object. Get the key with `lv_indev_get_key(lv_indev_active());`*/ + LV_EVENT_ROTARY, /**< An encoder or wheel was rotated. Get the rotation count with `lv_event_get_rotary_diff(e);`*/ LV_EVENT_FOCUSED, /**< The object is focused*/ LV_EVENT_DEFOCUSED, /**< The object is defocused*/ LV_EVENT_LEAVE, /**< The object is defocused but still selected*/ diff --git a/src/misc/lv_style.c b/src/misc/lv_style.c index adfb2521c..e7278434e 100644 --- a/src/misc/lv_style.c +++ b/src/misc/lv_style.c @@ -406,9 +406,13 @@ lv_style_value_t lv_style_prop_get_default(lv_style_prop_t prop) return (lv_style_value_t) { .num = LV_COORD_MAX }; + case LV_STYLE_ROTARY_SENSITIVITY: + return (lv_style_value_t) { + .num = 256 + }; default: return (lv_style_value_t) { - .ptr = 0 + .ptr = NULL }; } } diff --git a/src/misc/lv_style.h b/src/misc/lv_style.h index 86077987c..5c69e5989 100644 --- a/src/misc/lv_style.h +++ b/src/misc/lv_style.h @@ -298,8 +298,8 @@ enum _lv_style_prop_t { LV_STYLE_TRANSFORM_PIVOT_Y = 112, LV_STYLE_TRANSFORM_SKEW_X = 113, LV_STYLE_TRANSFORM_SKEW_Y = 114, - LV_STYLE_BITMAP_MASK_SRC = 115, + LV_STYLE_ROTARY_SENSITIVITY = 116, #if LV_USE_FLEX LV_STYLE_FLEX_FLOW = 125, diff --git a/src/misc/lv_style_gen.c b/src/misc/lv_style_gen.c index 3fce9532f..297087534 100644 --- a/src/misc/lv_style_gen.c +++ b/src/misc/lv_style_gen.c @@ -949,6 +949,16 @@ void lv_style_set_bitmap_mask_src(lv_style_t * style, const lv_image_dsc_t * val } const lv_style_prop_t _lv_style_const_prop_id_BITMAP_MASK_SRC = LV_STYLE_BITMAP_MASK_SRC; + +void lv_style_set_rotary_sensitivity(lv_style_t * style, uint32_t value) +{ + lv_style_value_t v = { + .num = (int32_t)value + }; + lv_style_set_prop(style, LV_STYLE_ROTARY_SENSITIVITY, v); +} + +const lv_style_prop_t _lv_style_const_prop_id_ROTARY_SENSITIVITY = LV_STYLE_ROTARY_SENSITIVITY; #if LV_USE_FLEX void lv_style_set_flex_flow(lv_style_t * style, lv_flex_flow_t value) diff --git a/src/misc/lv_style_gen.h b/src/misc/lv_style_gen.h index 6ce838e1c..7aed6b7e9 100644 --- a/src/misc/lv_style_gen.h +++ b/src/misc/lv_style_gen.h @@ -202,6 +202,8 @@ void lv_style_set_base_dir(lv_style_t * style, lv_base_dir_t value); LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_BASE_DIR; void lv_style_set_bitmap_mask_src(lv_style_t * style, const lv_image_dsc_t * value); LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_BITMAP_MASK_SRC; +void lv_style_set_rotary_sensitivity(lv_style_t * style, uint32_t value); +LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_ROTARY_SENSITIVITY; #if LV_USE_FLEX void lv_style_set_flex_flow(lv_style_t * style, lv_flex_flow_t value); LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_FLEX_FLOW; @@ -708,6 +710,11 @@ LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_GR { \ .prop_ptr = &_lv_style_const_prop_id_BITMAP_MASK_SRC, .value = { .ptr = val } \ } + +#define LV_STYLE_CONST_ROTARY_SENSITIVITY(val) \ + { \ + .prop_ptr = &_lv_style_const_prop_id_ROTARY_SENSITIVITY, .value = { .num = (int32_t)val } \ + } #if LV_USE_FLEX #define LV_STYLE_CONST_FLEX_FLOW(val) \ diff --git a/src/themes/default/lv_theme_default.c b/src/themes/default/lv_theme_default.c index a6a5eb242..66494ba92 100644 --- a/src/themes/default/lv_theme_default.c +++ b/src/themes/default/lv_theme_default.c @@ -75,6 +75,7 @@ typedef struct { lv_style_t circle; lv_style_t no_radius; lv_style_t clip_corner; + lv_style_t rotary_scroll; #if LV_THEME_DEFAULT_GROW lv_style_t grow; #endif @@ -263,6 +264,7 @@ static void style_init(my_theme_t * theme) lv_style_set_text_font(&theme->styles.scr, theme->base.font_normal); lv_style_set_pad_row(&theme->styles.scr, PAD_SMALL); lv_style_set_pad_column(&theme->styles.scr, PAD_SMALL); + lv_style_set_rotary_sensitivity(&theme->styles.scr, theme->disp_dpi / 4 * 256); style_init_reset(&theme->styles.card); lv_style_set_radius(&theme->styles.card, RADIUS_DEFAULT); @@ -386,6 +388,9 @@ static void style_init(my_theme_t * theme) style_init_reset(&theme->styles.no_radius); lv_style_set_radius(&theme->styles.no_radius, 0); + style_init_reset(&theme->styles.rotary_scroll); + lv_style_set_rotary_sensitivity(&theme->styles.rotary_scroll, theme->disp_dpi / 4 * 256); + #if LV_THEME_DEFAULT_GROW style_init_reset(&theme->styles.grow); lv_style_set_transform_width(&theme->styles.grow, _LV_DPX_CALC(theme->disp_dpi, 3)); @@ -747,6 +752,7 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj) /*Tabview pages*/ else if(parent && lv_obj_check_type(lv_obj_get_parent(parent), &lv_tabview_class)) { lv_obj_add_style(obj, &theme->styles.pad_normal, 0); + lv_obj_add_style(obj, &theme->styles.rotary_scroll, 0); lv_obj_add_style(obj, &theme->styles.scrollbar, LV_PART_SCROLLBAR); lv_obj_add_style(obj, &theme->styles.scrollbar_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED); return; diff --git a/src/widgets/arc/lv_arc.c b/src/widgets/arc/lv_arc.c index 994efa759..6d4383971 100644 --- a/src/widgets/arc/lv_arc.c +++ b/src/widgets/arc/lv_arc.c @@ -605,7 +605,7 @@ static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e) else if(code == LV_EVENT_KEY) { uint32_t c = lv_event_get_key(e); - int16_t old_value = arc->value; + int32_t old_value = arc->value; if(c == LV_KEY_RIGHT || c == LV_KEY_UP) { lv_arc_set_value(obj, lv_arc_get_value(obj) + 1); } @@ -618,6 +618,16 @@ static void lv_arc_event(const lv_obj_class_t * class_p, lv_event_t * e) if(res != LV_RESULT_OK) return; } } + else if(code == LV_EVENT_ROTARY) { + int32_t r = lv_event_get_rotary_diff(e); + + int32_t old_value = arc->value; + lv_arc_set_value(obj, lv_arc_get_value(obj) + r); + if(old_value != arc->value) { + res = lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RESULT_OK) return; + } + } else if(code == LV_EVENT_HIT_TEST) { lv_hit_test_info_t * info = lv_event_get_param(e); diff --git a/src/widgets/dropdown/lv_dropdown.c b/src/widgets/dropdown/lv_dropdown.c index e99fa6e1a..c5d1c0189 100644 --- a/src/widgets/dropdown/lv_dropdown.c +++ b/src/widgets/dropdown/lv_dropdown.c @@ -738,6 +738,19 @@ static void lv_dropdown_event(const lv_obj_class_t * class_p, lv_event_t * e) } } } + else if(code == LV_EVENT_ROTARY) { + if(!lv_dropdown_is_open(obj)) { + lv_dropdown_open(obj); + } + else { + int32_t r = lv_event_get_rotary_diff(e); + int32_t new_id = dropdown->sel_opt_id + r; + new_id = LV_CLAMP(0, new_id, (int32_t)dropdown->option_cnt - 1); + + dropdown->sel_opt_id = new_id; + position_to_selected(obj); + } + } else if(code == LV_EVENT_DRAW_MAIN) { draw_main(e); } diff --git a/src/widgets/roller/lv_roller.c b/src/widgets/roller/lv_roller.c index ae909c320..98ed0f3df 100644 --- a/src/widgets/roller/lv_roller.c +++ b/src/widgets/roller/lv_roller.c @@ -380,6 +380,16 @@ static void lv_roller_event(const lv_obj_class_t * class_p, lv_event_t * e) } } } + else if(code == LV_EVENT_ROTARY) { + int32_t r = lv_event_get_rotary_diff(e); + int32_t new_id = roller->sel_opt_id + r; + new_id = LV_CLAMP(0, new_id, (int32_t)roller->option_cnt - 1); + if((int32_t)roller->sel_opt_id != new_id) { + uint32_t ori_id = roller->sel_opt_id_ori; /*lv_roller_set_selected will overwrite this*/ + lv_roller_set_selected(obj, new_id, LV_ANIM_ON); + roller->sel_opt_id_ori = ori_id; + } + } else if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { lv_obj_t * label = get_label(obj); lv_obj_refresh_ext_draw_size(label); diff --git a/src/widgets/slider/lv_slider.c b/src/widgets/slider/lv_slider.c index 1bf7cca10..2cce03ab2 100644 --- a/src/widgets/slider/lv_slider.c +++ b/src/widgets/slider/lv_slider.c @@ -224,6 +224,15 @@ static void lv_slider_event(const lv_obj_class_t * class_p, lv_event_t * e) res = lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL); if(res != LV_RESULT_OK) return; } + else if(code == LV_EVENT_ROTARY) { + int32_t r = lv_event_get_rotary_diff(e); + + if(!slider->left_knob_focus) lv_slider_set_value(obj, lv_slider_get_value(obj) + r, LV_ANIM_ON); + else lv_slider_set_left_value(obj, lv_slider_get_left_value(obj) + 1, LV_ANIM_ON); + + res = lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RESULT_OK) return; + } else if(code == LV_EVENT_DRAW_MAIN) { draw_knob(e); } diff --git a/tests/src/test_cases/widgets/test_image.c b/tests/src/test_cases/widgets/test_image.c index 52069169d..17a4d8d32 100644 --- a/tests/src/test_cases/widgets/test_image.c +++ b/tests/src/test_cases/widgets/test_image.c @@ -21,6 +21,7 @@ static lv_obj_t * img_create(void) lv_obj_t * img = lv_image_create(lv_screen_active()); lv_image_set_src(img, &test_img_lvgl_logo_png); lv_obj_set_style_bg_opa(img, LV_OPA_20, 0); + lv_obj_set_style_bg_color(img, lv_color_hex(0x000000), 0); lv_obj_set_style_shadow_width(img, 10, 0); lv_obj_set_style_shadow_color(img, lv_color_hex(0xff0000), 0); return img;