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