[Update] Open Source Window Handler (Open,Minimize,Close,Drag,Resize)

#define MIN_HEIGHT 760*LV_VER_RES_MAX/1000
#define MIN_WIDTH  490*LV_HOR_RES_MAX/1000

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

typedef struct {
    bool isClosed;
    bool isMinimized;
    bool isFullScreen;
} WindowFlags;

WindowFlags objFlags[10]; 

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);
    }
    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 positions and sizes
        lv_obj_set_x(windowTopbarFullScreenButton, new_width -220*LV_VER_RES_MAX/1000);
        lv_obj_set_x(windowTopbarMinimizeButton, new_width -280*LV_VER_RES_MAX/1000);
        lv_obj_set_x(windowTopbarCloseButton, new_width -340*LV_VER_RES_MAX/1000);
    } 
    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 positions and sizes
        lv_obj_set_x(windowTopbarFullScreenButton, new_width -220*LV_VER_RES_MAX/1000);
        lv_obj_set_x(windowTopbarMinimizeButton, new_width -280*LV_VER_RES_MAX/1000);
        lv_obj_set_x(windowTopbarCloseButton, new_width -340*LV_VER_RES_MAX/1000);
    }
}

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);
        }

        lv_coord_t offset = -obj_height + 26; // fixed offset for window top bar

        // Ensure the object stays within the top and bottom boundaries of the screen with offset
        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 - offset) {
            new_y = screen_height - obj_height - offset;
        }

        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 handle_fullscreen(lv_event_t *event) {
    lv_event_code_t event_code = lv_event_get_code(event);

    if (event_code == LV_EVENT_CLICKED) {

    int type = lv_event_get_user_data(event);
    lv_obj_t *obj = lv_event_get_target(event);
    lv_obj_t *window = lv_obj_get_parent(obj);

    lv_indev_t *indev = lv_indev_get_act();
    lv_point_t vect;
    lv_indev_get_vect(indev, &vect);

    lv_coord_t screen_width = lv_obj_get_width(lv_scr_act());
    lv_coord_t screen_height = LV_VER_RES_MAX - 100*LV_VER_RES_MAX/1000;

        if (objFlags[type].isFullScreen == false)
        {
            objFlags[type].isFullScreen = true;

            // Resize the window to match the screen size
            lv_obj_set_size(window, screen_width, screen_height);

            // Center the window on the screen
            lv_obj_set_pos(window,0,100*LV_VER_RES_MAX/1000);

            // Adjust button positions and sizes
            lv_obj_set_x(windowTopbarFullScreenButton, screen_width -220*LV_VER_RES_MAX/1000);
            lv_obj_set_x(windowTopbarMinimizeButton, screen_width -280*LV_VER_RES_MAX/1000);
            lv_obj_set_x(windowTopbarCloseButton, screen_width -340*LV_VER_RES_MAX/1000);

        } else if (objFlags[type].isFullScreen == true) {
            objFlags[type].isFullScreen = false;

            lv_obj_set_size(window, MIN_WIDTH,MIN_HEIGHT);
            lv_obj_set_pos(window,LV_HOR_RES_MAX/4,LV_VER_RES_MAX/4);

            // Adjust button positions and sizes
            lv_obj_set_x(windowTopbarFullScreenButton, LV_HOR_RES_MAX/2 -220*LV_VER_RES_MAX/1000);
            lv_obj_set_x(windowTopbarMinimizeButton, LV_HOR_RES_MAX/2 -280*LV_VER_RES_MAX/1000);
            lv_obj_set_x(windowTopbarCloseButton, LV_HOR_RES_MAX/2 -340*LV_VER_RES_MAX/1000);
        }
    }
}

void handle_minimize(lv_event_t *event) {
    lv_event_code_t event_code = lv_event_get_code(event);

    if (event_code == LV_EVENT_CLICKED) {

    int type = lv_event_get_user_data(event);
    lv_obj_t *obj = lv_event_get_target(event);
    lv_obj_t *window = lv_obj_get_parent(obj);

    lv_indev_t *indev = lv_indev_get_act();
    lv_point_t vect;
    lv_indev_get_vect(indev, &vect);

    lv_coord_t screen_width = lv_obj_get_width(lv_scr_act());
    lv_coord_t screen_height = LV_VER_RES_MAX - 100*LV_VER_RES_MAX/1000;

        if (objFlags[type].isMinimized == false)
        {
            objFlags[type].isMinimized = true;

            lv_obj_set_size(window, LV_HOR_RES_MAX/2,LV_VER_RES_MAX/2);
            lv_obj_set_pos(window,LV_HOR_RES_MAX/4,LV_VER_RES_MAX/4);

            // Adjust button positions and sizes
            lv_obj_set_x(windowTopbarFullScreenButton, LV_HOR_RES_MAX/2 -220*LV_VER_RES_MAX/1000);
            lv_obj_set_x(windowTopbarMinimizeButton, LV_HOR_RES_MAX/2 -280*LV_VER_RES_MAX/1000);
            lv_obj_set_x(windowTopbarCloseButton, LV_HOR_RES_MAX/2 -340*LV_VER_RES_MAX/1000);

            lv_obj_add_flag(window, LV_OBJ_FLAG_HIDDEN);
            printf("minimized %d",type);
        }
    }
}

void handle_close(lv_event_t *event) {
    lv_event_code_t event_code = lv_event_get_code(event);

    if (event_code == LV_EVENT_CLICKED) {

    int type = lv_event_get_user_data(event);
    lv_obj_t *obj = lv_event_get_target(event);
    lv_obj_t *window = lv_obj_get_parent(obj);

    lv_indev_t *indev = lv_indev_get_act();
    lv_point_t vect;
    lv_indev_get_vect(indev, &vect);

    lv_coord_t screen_width = lv_obj_get_width(lv_scr_act());
    lv_coord_t screen_height = LV_VER_RES_MAX - 100*LV_VER_RES_MAX/1000;

        if (objFlags[type].isClosed == false)
        {
            objFlags[type].isClosed = true;

            lv_obj_del(window);

        }
    }
}

void windowUI_generator(int type,int sizeX, int sizeY) {
    // Creating the main frame window
    windowMainFrame[type] = lv_obj_create(Screen);
    lv_obj_set_pos(windowMainFrame[type], LV_HOR_RES_MAX/2 - sizeX/2, LV_VER_RES_MAX/2 - sizeY/2);
    lv_obj_set_size(windowMainFrame[type], sizeX, sizeY);
    lv_obj_add_style(windowMainFrame[type], &style_WindowMainFrame, 0);
    lv_obj_clear_flag(windowMainFrame[type], LV_OBJ_FLAG_SCROLLABLE);
    lv_obj_add_event_cb(windowMainFrame[type], window_control_event_handler, LV_EVENT_LONG_PRESSED, NULL);
    lv_obj_add_event_cb(windowMainFrame[type], drag_event_handler, LV_EVENT_PRESSING, NULL);
    lv_obj_add_event_cb(windowMainFrame[type], resize_event_handler, LV_EVENT_PRESSING, NULL);

    // Creating the full-screen button in the top bar
    windowTopbarFullScreenButton = lv_btn_create(windowMainFrame[type]);
    lv_obj_set_size(windowTopbarFullScreenButton, 12, 12);
    lv_obj_align_to(windowTopbarFullScreenButton, windowMainFrame[type], LV_ALIGN_RIGHT_MID, 80 * LV_HOR_RES_MAX / 1000, -332.5 * LV_VER_RES_MAX / 1000);
    lv_obj_add_style(windowTopbarFullScreenButton, &style_windowTopbarFullScreenButton, 0);
    lv_obj_clear_flag(windowTopbarFullScreenButton, LV_OBJ_FLAG_SCROLLABLE);

    // Creating the minimize button in the top bar
    windowTopbarMinimizeButton = lv_btn_create(windowMainFrame[type]);
    lv_obj_set_size(windowTopbarMinimizeButton, 12, 12);
    lv_obj_align_to(windowTopbarMinimizeButton, windowTopbarFullScreenButton, 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);

    // Creating the close button in the top bar
    windowTopbarCloseButton = lv_btn_create(windowMainFrame[type]);
    lv_obj_set_size(windowTopbarCloseButton, 12, 12);
    lv_obj_align_to(windowTopbarCloseButton, windowTopbarMinimizeButton, LV_ALIGN_CENTER, -30 * LV_HOR_RES_MAX / 1000, 0);
    lv_obj_add_style(windowTopbarCloseButton, &style_windowTopbarCloseButton, 0);
    lv_obj_clear_flag(windowTopbarCloseButton, LV_OBJ_FLAG_SCROLLABLE);

    // Creating the title frame
    windowTitleFrame = lv_btn_create(windowMainFrame[type]);
    lv_obj_set_size(windowTitleFrame, 220 * LV_HOR_RES_MAX / 1000, 80 * LV_VER_RES_MAX / 1000);
    lv_obj_align_to(windowTitleFrame, windowMainFrame[type], LV_ALIGN_RIGHT_MID, -100 * LV_HOR_RES_MAX / 1000, -332.5 * LV_VER_RES_MAX / 1000);
    lv_obj_add_style(windowTitleFrame, &style_windowTitleFrame, 0);
    lv_obj_clear_flag(windowTitleFrame, LV_OBJ_FLAG_SCROLLABLE);
    lv_obj_clear_flag(windowTitleFrame, LV_OBJ_FLAG_CLICKABLE);

    // Adding event callbacks for the buttons
    lv_obj_add_event_cb(windowTopbarFullScreenButton, handle_fullscreen, LV_EVENT_ALL, type);
    lv_obj_add_event_cb(windowTopbarMinimizeButton, handle_minimize, LV_EVENT_ALL, type);
    lv_obj_add_event_cb(windowTopbarCloseButton, handle_close, LV_EVENT_ALL, type);

    // Initializing object flags
    objFlags[type].isClosed = false;
    objFlags[type].isMinimized = false;
    objFlags[type].isFullScreen = false;
    printf("Generated");
}

void window_generator(int type, int sizeX, int sizeY) {
    switch (type) {
        case 1: // Simple window    
            windowUI_generator(type,sizeX,sizeY);
            break;
        case 2: // Chart window
            windowUI_generator(type,sizeX,sizeY);
            // Code for chart window
            break;
    }
}

void window_generatorCallback(lv_event_t * event){

    int type = lv_event_get_user_data(event);

    printf("Callback");

    window_generator(type, 490*LV_HOR_RES_MAX / 1000,  760*LV_VER_RES_MAX/1000);

    printf("%d",type);
}

void InitializeWindowsFlags(){
    for (int i = 0; i < 10; ++i) {
        objFlags[i].isClosed = true;
        objFlags[i].isMinimized = false;
        objFlags[i].isFullScreen = false;
    }
}
1 Like

The code have been updated and now also supports Open,Close,Minimize

1 Like