How handle buttons on a resize able window?

blackwindow

How can I maintain a static appearance for the three buttons at the top of the window while adjusting the window size? Is there a way to achieve this effect using LVGL’s layout features?

This is what i have done so far


#define MIN_HEIGHT 100
#define MIN_WIDTH  150

const char* region = NULL;
bool MovingFlag = false;
bool ResizeFlag = false;

bool chartWindow = false; bool chartMinimized = false;
bool timerWindow = false; bool timerMinimized = false;
bool tempWindow  = false; bool tempMinimized  = false;

uint32_t WINDOW_LAYOUT;

void handle_resize(lv_obj_t *obj, const char *region) {
    if (region != NULL) {
        if (strcmp(region, "LEFT_MID") == 0 || strcmp(region, "RIGHT_MID") == 0 ) {
            MovingFlag = true;
        } else {
            MovingFlag = false;
        }
    }
}

void handle_drag(lv_obj_t *obj, const char *region) {
    if (region != NULL) {
        handle_resize(&obj, &region);
        // Handle the drag behavior only for TOP_MID region
        if (strcmp(region, "TOP_MID") == 0) {
            MovingFlag = true;
        } else {
            MovingFlag = false;
        }
    }
}

 const char *determine_region(int touched_vertical_region, int touched_horizontal_region) {     
    if ((touched_vertical_region == 0 && touched_horizontal_region == 1) ||
        (touched_vertical_region == 0 && touched_horizontal_region == 0) ||
        (touched_vertical_region == 0 && touched_horizontal_region == 2)) {

        return "TOP_MID";
    } else if ((touched_vertical_region == 2 && touched_horizontal_region == 1) ||
               (touched_vertical_region == 2 && touched_horizontal_region == 0) ||
               (touched_vertical_region == 2 && touched_horizontal_region == 2)) {
        return "BOTTOM_MID";
    } else if (touched_vertical_region == 1 && touched_horizontal_region == 0) {
        return "LEFT_MID";
    } else if (touched_vertical_region == 1 && touched_horizontal_region == 2) {
        return "RIGHT_MID";
    } else {
        return NULL;
    }
}

static void resize_event_handler(lv_event_t *event) {
    lv_obj_t *obj = lv_event_get_target(event);
    lv_indev_t *indev = lv_indev_get_act();
    
    if (indev == NULL) return;

    lv_point_t vect;
    lv_indev_get_vect(indev, &vect);

    lv_coord_t obj_width = lv_obj_get_width(obj);
    lv_coord_t obj_height = lv_obj_get_height(obj);

    if (region && strcmp(region, "BOTTOM_MID") == 0) {
        lv_coord_t new_height = obj_height + vect.y;
        lv_coord_t new_width = obj_width - vect.x;

        // Ensure the object height doesn't become too small
        if (new_height < MIN_HEIGHT) {
            new_height = MIN_HEIGHT;
        }

        // Ensure the object stays within the top and bottom boundaries of the screen
        lv_coord_t screen_height = lv_obj_get_height(lv_scr_act());
        if (lv_obj_get_y(obj) + new_height > screen_height) {
            new_height = screen_height - lv_obj_get_y(obj);
        }

        lv_obj_set_height(obj, new_height);

        // Adjust button and title frame positions and sizes
        lv_obj_align(windowTopbarCloseButton, LV_ALIGN_CENTER, new_width * 25 / 100, -new_height * 43 / 100);

        lv_obj_align_to(windowTopbarMinimizeButton, windowTopbarCloseButton, LV_ALIGN_CENTER, new_width * 10 / 100,  0);

        lv_obj_align_to(windowTopbarFullScreenButton, windowTopbarMinimizeButton, LV_ALIGN_CENTER, new_width * 10 / 100,  0);

        lv_obj_align(windowTitleFrame, LV_ALIGN_LEFT_MID, (new_width * 5 / 100) - 90*LV_HOR_RES_MAX/1000, -new_height * 44 / 100);
    } 
    else if (region && strcmp(region, "LEFT_MID") == 0) {
        lv_coord_t new_width = obj_width - vect.x;
        lv_coord_t new_x = lv_obj_get_x(obj) + vect.x;

        // Ensure the object width doesn't become too small
        if (new_width < MIN_WIDTH) {
            new_width = MIN_WIDTH;
            new_x = lv_obj_get_x(obj) + obj_width - MIN_WIDTH;
        }

        // Ensure the object stays within the left and right boundaries of the screen
        if (new_x < 0) {
            new_x = 0;
        }
        lv_coord_t screen_width = lv_obj_get_width(lv_scr_act());
        if (new_x + new_width > screen_width) {
            new_width = screen_width - new_x;
        }

        lv_obj_set_width(obj, new_width);
        lv_obj_set_x(obj, new_x);

        // Adjust button and title frame positions and sizes
        lv_obj_align(windowTopbarCloseButton, LV_ALIGN_CENTER, new_width * 25 / 100, -obj_height * 43 / 100);

        lv_obj_align_to(windowTopbarMinimizeButton, windowTopbarCloseButton, LV_ALIGN_CENTER, new_width * 10 / 100,  0);

        lv_obj_align_to(windowTopbarFullScreenButton, windowTopbarMinimizeButton, LV_ALIGN_CENTER, new_width * 10 / 100,  0);

        lv_obj_align(windowTitleFrame, LV_ALIGN_LEFT_MID, (new_width * 5 / 100) - 90*LV_HOR_RES_MAX/1000, -obj_height * 44 / 100);
    } 
    else if (region && strcmp(region, "RIGHT_MID") == 0) {
        lv_coord_t new_width = obj_width + vect.x;

        // Ensure the object width doesn't become too small
        if (new_width < MIN_WIDTH) {
            new_width = MIN_WIDTH;
        }

        // Ensure the object stays within the left and right boundaries of the screen
        lv_coord_t screen_width = lv_obj_get_width(lv_scr_act());
        if (lv_obj_get_x(obj) + new_width > screen_width) {
            new_width = screen_width - lv_obj_get_x(obj);
        }

        lv_obj_set_width(obj, new_width);

        // Adjust button and title frame positions and sizes
        lv_obj_align(windowTopbarCloseButton, LV_ALIGN_CENTER, new_width * 25 / 100, -obj_height * 43 / 100);

        lv_obj_align_to(windowTopbarMinimizeButton, windowTopbarCloseButton, LV_ALIGN_CENTER, new_width * 10 / 100,  0);

        lv_obj_align_to(windowTopbarFullScreenButton, windowTopbarMinimizeButton, LV_ALIGN_CENTER, new_width * 10 / 100,  0);

        lv_obj_align(windowTitleFrame, LV_ALIGN_LEFT_MID, (new_width * 5 / 100) - 90*LV_HOR_RES_MAX/1000, -obj_height * 44 / 100);
    }
}

static void drag_event_handler(lv_event_t * event) {
    if ((region && strcmp(region, "TOP_MID") == 0)) {
        lv_obj_t * obj = lv_event_get_target(event);
        lv_indev_t * indev = lv_indev_get_act();
        if (indev == NULL) return;

        lv_point_t vect;
        lv_indev_get_vect(indev, &vect);

        lv_coord_t obj_height = lv_obj_get_height(obj);

        lv_coord_t new_x = lv_obj_get_x(obj) + vect.x;
        lv_coord_t new_y = lv_obj_get_y(obj) + vect.y;

        // Ensure the object stays within the left and right boundaries of the screen
        if (new_x < 0) {
            new_x = 0;
        }
        lv_coord_t screen_width = lv_obj_get_width(lv_scr_act());
        if (new_x + lv_obj_get_width(obj) > screen_width) {
            new_x = screen_width - lv_obj_get_width(obj);
        }

        // Ensure the object stays within the top and bottom boundaries of the screen
        if (new_y < 0) {
            new_y = 0;
        }
        lv_coord_t screen_height = lv_obj_get_height(lv_scr_act());
        if (new_y + obj_height > screen_height) {
            new_y = screen_height - obj_height;
        }

        lv_obj_set_pos(obj, new_x, new_y);
    }
}

 void window_control_event_handler(lv_event_t *event) {
    lv_obj_t *obj = lv_event_get_target(event);
    lv_event_code_t event_code = lv_event_get_code(event);

    if (event_code == LV_EVENT_LONG_PRESSED_REPEAT || event_code == LV_EVENT_LONG_PRESSED) {
        lv_point_t point;
        lv_indev_get_point(lv_indev_get_act(), &point);  // Get touch coordinates

        lv_coord_t obj_x = lv_obj_get_x(obj);
        lv_coord_t obj_y = lv_obj_get_y(obj);
        lv_coord_t obj_width = lv_obj_get_width(obj);
        lv_coord_t obj_height = lv_obj_get_height(obj);

        // Calculate touch position relative to the object
        lv_coord_t touch_x = point.x - obj_x;
        lv_coord_t touch_y = point.y - obj_y;

        lv_coord_t third_width = obj_width / 3;
        lv_coord_t third_height = obj_height / 3;

        int touched_horizontal_region = touch_x / third_width;
        int touched_vertical_region = touch_y / third_height;

        // Determine the current region based on touch coordinates
        region = determine_region(touched_vertical_region, touched_horizontal_region);

        // Update label and handle drag behavior
        handle_drag(obj, region);
    }
}

void window_generator(int type,int sizeX, int sizeY) {

    switch (type){

        case 1: {// temperature window
            
                windowMainFrame[1] = lv_obj_create(Screen);
                lv_obj_set_pos(windowMainFrame[1], LV_HOR_RES_MAX/2 - sizeX/2, LV_VER_RES_MAX/2 - sizeY/2);
                lv_obj_set_size(windowMainFrame[1], sizeX,  sizeY);
                lv_obj_add_style(windowMainFrame[1],&style_WindowMainFrame,0);
                lv_obj_clear_flag(windowMainFrame[1], LV_OBJ_FLAG_SCROLLABLE);
                lv_obj_add_event_cb(windowMainFrame[1], window_control_event_handler, LV_EVENT_LONG_PRESSED, NULL);
                lv_obj_add_event_cb(windowMainFrame[1], drag_event_handler, LV_EVENT_PRESSING, NULL);
                lv_obj_add_event_cb(windowMainFrame[1], resize_event_handler, LV_EVENT_PRESSING, NULL);

                windowTopbarCloseButton = lv_btn_create(windowMainFrame[1]);
                lv_obj_set_size(windowTopbarCloseButton, 12 ,   12 );
                lv_obj_align(windowTopbarCloseButton, LV_ALIGN_CENTER, 180*LV_HOR_RES_MAX/1000, -320*LV_VER_RES_MAX/1000);
                lv_obj_add_style(windowTopbarCloseButton,&style_windowTopbarCloseButton,0);
                lv_obj_clear_flag(windowTopbarCloseButton, LV_OBJ_FLAG_SCROLLABLE);

                windowTopbarMinimizeButton = lv_btn_create(windowMainFrame[1]);
                lv_obj_set_size(windowTopbarMinimizeButton, 12 ,   12 );
                lv_obj_align_to(windowTopbarMinimizeButton, windowTopbarCloseButton, LV_ALIGN_CENTER, -30*LV_HOR_RES_MAX/1000, 0);
                lv_obj_add_style(windowTopbarMinimizeButton,&style_windowTopbarMinimizeButton,0);
                lv_obj_clear_flag(windowTopbarMinimizeButton, LV_OBJ_FLAG_SCROLLABLE);

                windowTopbarFullScreenButton = lv_btn_create(windowMainFrame[1]);
                lv_obj_set_size(windowTopbarFullScreenButton, 12 ,   12 );
                lv_obj_align_to(windowTopbarFullScreenButton, windowTopbarMinimizeButton, LV_ALIGN_CENTER, -30*LV_HOR_RES_MAX/1000, 0);
                lv_obj_add_style(windowTopbarFullScreenButton,&style_windowTopbarFullScreenButton,0);
                lv_obj_clear_flag(windowTopbarFullScreenButton, LV_OBJ_FLAG_SCROLLABLE);

                windowTitleFrame = lv_obj_create(windowMainFrame[1]);
                lv_obj_align(windowTitleFrame, LV_ALIGN_LEFT_MID, - 70*LV_HOR_RES_MAX/1000, -320*LV_VER_RES_MAX/1000);
                lv_obj_set_size(windowTitleFrame, 200*LV_HOR_RES_MAX/1000, 80*LV_VER_RES_MAX/1000 );
                lv_obj_add_style(windowTitleFrame,&style_windowTitleFrame,0);
                lv_obj_clear_flag(windowTitleFrame, LV_OBJ_FLAG_SCROLLABLE);
                lv_obj_set_align(windowTitleFrame, LV_ALIGN_LEFT_MID);
        
        break;
        case 2:  // chart window
            
        
        break;
        case 3:  // timer window
            
        
        break;
        }
    }
}

Idea? Why not Flex — LVGL documentation