1 /*******************************************************************
2  *
3  * @file lv_example_gestures.c
4  *
5  * This is a simple example program that demonstrates how to use
6  * the gesture recognition API, please refer to lv_indev_gesture.h or the documentation
7  * for more details
8  *
9  * The application starts with a single rectangle that is scaled when a pinch gesture
10  * is detected. A single finger moves the rectangle around,
11  *
12  * Copyright (c) 2024 EDGEMTech Ltd
13  *
14  * Author: EDGEMTech Ltd, Erik Tagirov (erik.tagirov@edgemtech.ch)
15  *
16  ******************************************************************/
17 
18 /*********************
19  *      INCLUDES
20  *********************/
21 #include "../../lv_examples.h"
22 
23 #if LV_USE_GESTURE_RECOGNITION && LV_BUILD_EXAMPLES
24 
25 /*********************
26  *      DEFINES
27  *********************/
28 
29 #define RECT_INIT_WIDTH 300.0
30 #define RECT_INIT_HEIGHT 300.0
31 #define RECT_COLOR 0xC1BCFF
32 
33 /**********************
34  *      TYPEDEFS
35  **********************/
36 
37 /**********************
38  *  STATIC PROTOTYPES
39  **********************/
40 
41 static void label_scale(lv_event_t * gesture_event);
42 static void label_move(lv_event_t * event);
43 
44 /**********************
45  *  STATIC VARIABLES
46  **********************/
47 
48 static lv_obj_t * label;
49 static lv_style_t label_style;
50 static float label_width;
51 static float label_height;
52 static float label_x;
53 static float label_y;
54 
55 /**********************
56  *      MACROS
57  **********************/
58 
59 /**********************
60  *   GLOBAL FUNCTIONS
61  **********************/
62 
63 /**
64  * Entry point it creates the screen, and the label
65  * Set event callbacks on the label
66  */
lv_example_gestures(void)67 void lv_example_gestures(void)
68 {
69     lv_obj_t * root_view;
70 
71     label_width = RECT_INIT_WIDTH;
72     label_height = RECT_INIT_HEIGHT;
73     label_y = label_x = 300;
74 
75     root_view = lv_screen_active();
76 
77     lv_obj_set_style_bg_color(root_view, lv_color_hex(0xFFFFFF), LV_PART_MAIN);
78     label = lv_label_create(root_view);
79     lv_obj_remove_flag(root_view, LV_OBJ_FLAG_SCROLLABLE);
80 
81     lv_label_set_text(label, "Zoom or move");
82     lv_obj_add_flag(label, LV_OBJ_FLAG_CLICKABLE);
83 
84     lv_style_init(&label_style);
85     lv_style_set_bg_color(&label_style, lv_color_hex(RECT_COLOR));
86     lv_style_set_bg_opa(&label_style, LV_OPA_COVER);
87 
88     lv_style_set_width(&label_style, (int)label_width);
89     lv_style_set_height(&label_style, (int)label_height);
90 
91     lv_style_set_x(&label_style, (int)label_x);
92     lv_style_set_y(&label_style, (int)label_y);
93 
94     lv_obj_add_style(label, &label_style, LV_STATE_DEFAULT);
95 
96     lv_obj_add_event_cb(label, label_scale, LV_EVENT_GESTURE, label);
97     lv_obj_add_event_cb(label, label_move, LV_EVENT_PRESSING, label);
98 
99 }
100 
101 /**********************
102  *   STATIC FUNCTIONS
103  **********************/
104 
105 /**
106  * Called when a pinch event occurs - scales the label
107  * @param gesture_event point to a LV_EVENT_PINCH event
108  */
label_scale(lv_event_t * gesture_event)109 static void label_scale(lv_event_t * gesture_event)
110 {
111 
112     static int initial_w = -1;
113     static int initial_h = -1;
114     lv_indev_gesture_state_t state;
115     lv_point_t center_pnt;
116     float scale;
117 
118     scale = lv_event_get_pinch_scale(gesture_event);
119     state = lv_event_get_gesture_state(gesture_event);
120 
121     lv_indev_get_point(lv_indev_active(), &center_pnt);
122 
123     if(state == LV_INDEV_GESTURE_STATE_ENDED) {
124         /* Pinch gesture has ended - reset the width/height for the next pinch gesture*/
125         initial_w = -1;
126         initial_h = -1;
127 
128         LV_LOG_USER("label end scale: %g, state: %d", scale, state);
129         return;
130     }
131 
132     if(initial_h == -1 || initial_w == -1) {
133 
134         LV_ASSERT(state == LV_INDEV_GESTURE_STATE_RECOGNIZED);
135 
136         /* Pinch gesture has been recognized - this is the first event in a series of recognized events */
137         /* The scaling is applied relative to the original width/height of the rectangle */
138         initial_w = (int)label_width;
139         initial_h = (int)label_height;
140 
141         LV_LOG_USER("label start scale: %g", scale);
142     }
143 
144     /* The gesture has started or is on-going */
145 
146     /* Avoids a situation where the rectangle becomes too small,
147      * do not perform the scaling - leave straight away */
148     if(scale < 0.4) {
149         return;
150     }
151 
152     label_width = initial_w * scale;
153     label_height = initial_h * scale;
154     label_x = center_pnt.x - label_width / 2;
155     label_y = center_pnt.y - label_height / 2;
156 
157     LV_LOG_USER("label scale: %g label x: %g label y: %g w: %g h: %g",
158                 scale, label_x, label_y, label_width, label_height);
159 
160     /* Update position and size */
161     lv_style_set_width(&label_style, (int)label_width);
162     lv_style_set_height(&label_style, (int)label_height);
163     lv_style_set_x(&label_style, (int)label_x);
164     lv_style_set_y(&label_style, (int)label_y);
165 
166     lv_obj_add_style(label, &label_style, LV_STATE_DEFAULT);
167 }
168 
169 /**
170  * Called when a LV_EVENT_PRESSING occurs on the rectangle - moves the label
171  * @param event pointer to the event
172  */
label_move(lv_event_t * event)173 static void label_move(lv_event_t * event)
174 {
175     lv_point_t pnt;
176     lv_indev_gesture_state_t state;
177 
178     state = lv_event_get_gesture_state(event);
179     lv_indev_get_point(lv_indev_active(), &pnt);
180 
181     /* Do not move and when a pinch gesture is ongoing */
182     if(state == LV_INDEV_GESTURE_STATE_RECOGNIZED) {
183         return;
184     }
185 
186     LV_LOG_USER("label move x: %d, y: %d", pnt.x, pnt.y);
187 
188     label_x = pnt.x - label_width / 2;
189     label_y = pnt.y - label_height / 2;
190 
191     /* Update position */
192     lv_style_set_x(&label_style, (int)label_x);
193     lv_style_set_y(&label_style, (int)label_y);
194 
195     lv_obj_add_style(label, &label_style, LV_STATE_DEFAULT);
196 }
197 
198 #endif /* LV_USE_GESTURE_RECOGNITION && LV_USE_FLOAT */
199