Puzzle Sample Overview

Mobile native

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

Puzzle main view

Implementation

To create the Puzzle:

  1. 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;
    }
    
  2. 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;
    }
    
  3. 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;
    }
    
  4. Select the level of the puzzle.

    Figure: Puzzle levels

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