The Puzzle sample application demonstrates how to implement a complex view using recursive composition of the standard EFL components.
The following figure illustrates the main view of the Puzzle application in its normal state.
Figure: Puzzle main view
Implementation
To create the Puzzle:
- Create the layout for the Puzzle preview.
The puzzle_create() function creates the main layout of the Puzzle application.
void puzzle_create(appdata_s *data) { _D("Puzzle_create"); ret_if(!data); // Make a 6X6 image object for (i = 0; i < 37; i++) { ad->piece[i] = evas_object_image_filled_add(ad->e); ad->piece_pos[i] = i; evas_object_image_file_set(ad->piece[i], ad->smile_img_path, NULL); ret = evas_object_image_load_error_get(ad->piece[i]); if (ret != EVAS_LOAD_ERROR_NONE) { _E("Failed to load image"); } evas_object_data_set(ad->piece[i], "position", (void *)i); } evas_object_image_size_get(ad->piece[36], &ad->origin_image_width, &ad->origin_image_height); _D("The original image width: %d, height: %d", ad->origin_image_width, ad->origin_image_height); // Divide the size of a real image into a puzzle extract_region_width = ad->origin_image_width/PIECE; extract_region_height = ad->origin_image_height/PIECE; // Divide the size of the puzzle of the screen into a PIECE puzzle_width = ad->full_image_width/PIECE; puzzle_height = ad->full_image_height/PIECE; for (y = 0; y < PIECE; y++) { for (x = 0; x < PIECE; x++) { evas_object_move(ad->piece[y*PIECE + x], ad->puzzle_start_x + x*(2+puzzle_width), ad->puzzle_start_y + y*(2+puzzle_height)); evas_object_image_load_region_set(ad->piece[y*PIECE + x], x*extract_region_width, y*extract_region_height, extract_region_width, extract_region_height); evas_object_resize(ad->piece[y*PIECE + x], puzzle_width, puzzle_height); evas_object_event_callback_add(ad->piece[y*PIECE + x], EVAS_CALLBACK_MOUSE_DOWN, mouse_down_cb, ad); evas_object_event_callback_add(ad->piece[y*PIECE + x], EVAS_CALLBACK_MOUSE_UP, mouse_up_cb, ad); if (y == 3 && x == 3) { evas_object_color_get(ad->piece[y*PIECE + x], &ad->r, &ad->g, &ad->b, &ad->a); evas_object_color_set(ad->piece[y*PIECE + x], ad->r, ad->g, ad->b, 0); ad->white_piece = y*PIECE + x; } evas_object_show(ad->piece[y*PIECE + x]); } } ad->size = PIECE; ad->start = 0; }
- Move the piece and match the picture.
The move_***_cb() function moves the piece to ***. When moving the piece to ***, if there is a piece already, this function returns with no action.
int move_puzzle_to_right(void *data) { retv_if(!data, 0); appdata_s *ad = data; int x1, y1, w1, h1; int x2, y2, w2, h2; int white_piece = ad->white_piece; int size = ad->size; int temp; // There is a puzzle if (!(white_piece%size)) { return SAMPLE_APP_ERROR_OK; } evas_object_image_load_region_get(ad->piece[white_piece -1], &x1, &y1, &w1, &h1); evas_object_image_load_region_get(ad->piece[white_piece], &x2, &y2, &w2, &h2); // Exchange the position evas_object_image_load_region_set(ad->piece[white_piece - 1], x2, y2, w2, h2); evas_object_image_load_region_set(ad->piece[white_piece], x1, y1, w1, h1); evas_object_color_set(ad->piece[white_piece], ad->r, ad->g, ad->b, ad->a); evas_object_color_set(ad->piece[white_piece - 1], ad->r, ad->g, ad->b, 0); evas_object_show(ad->piece[white_piece]); evas_object_show(ad->piece[white_piece - 1]); temp = ad->piece_pos[white_piece]; ad->piece_pos[white_piece] = ad->piece_pos[white_piece - 1]; ad->piece_pos[white_piece - 1] = temp; ad->white_piece = white_piece - 1; if (ad->piece_pos[ad->white_piece] == size*size-1 && ad->start == 1) { puzzle_correct_cb(ad); } return 1; }
- Complete the puzzle.
If the image object is located in its original position, the puzzle_correct_cb() function is called to show the original picture of the puzzle.
void puzzle_correct_cb(appdata_s *data) { ret_if(!data); for (i = 0; i < ad->size * ad->size; i++) { if (ad->piece_pos[i]!=i) { return; } } // Make a popup for congratulations popup = elm_popup_add(win); elm_popup_align_set(popup, ELM_NOTIFY_ALIGN_FILL, 1.0); eext_object_event_callback_add(popup, EEXT_CALLBACK_BACK, eext_popup_back_cb, NULL); elm_object_part_text_set(popup, "title,text", "Correct!!"); evas_object_size_hint_weight_set(popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); layout = elm_layout_add(popup); elm_layout_file_set(layout, ad->puzzle_edj_path, "popup_image_list_layout"); evas_object_size_hint_weight_set(layout, 0, 0); evas_object_size_hint_align_set(layout, 0, EVAS_HINT_FILL); elm_object_content_set(popup, layout); // Show the original picture of the puzzle img = elm_image_add(layout); elm_image_file_set(img, ad->correct_img_path, NULL); elm_image_aspect_fixed_set(img, EINA_FALSE); evas_object_size_hint_min_set(img, 400, 400); evas_object_size_hint_max_set(img, 400, 400); elm_object_part_content_set(layout, "elm.swallow.content", img); // Make a popup delete button btn = elm_button_add(popup); elm_object_style_set(btn, "popup"); elm_object_text_set(btn, "OK"); elm_object_part_content_set(popup, "button1", btn); evas_object_smart_callback_add(btn, "clicked", con_button_clicked_cb, popup); evas_object_show(popup); ad->start = 0; }
- Select the level of the puzzle.
Figure: Puzzle levels
The user can select the level of the puzzle. Select a 4X4 puzzle or a 5X5 puzzle. To change the number of pieces, the puzzle_change() function is called. It works in the same way as the puzzle_create() function, but the value of PIECE is different.
void _level_button_cb(void *data, Evas_Object *obj, void *event_info) { ret_if(!data); appdata_s *ad = data; Evas_Object *popup = NULL; popup = evas_object_data_get(ad->win, "popup"); if (elm_check_state_get(ad->check1) == 1) { if (!puzzle_change(ad, 4)) { _E("Failed to change puzzle"); } } else if (elm_check_state_get(ad->check2) == 1) { if (!puzzle_change(ad, 5)) { _E("Failed to change puzzle"); } } evas_object_del(popup); }