// Retourne : une liste de points représentant un arc de cercle // A utiliser dans le dessin des boutons ei_linked_point_t* ei_draw_arc(ei_point_t centre, float R, float angledebut, float anglefin) { ei_linked_point_t* liste = NULL; float angle = angledebut; while (angle < anglefin) { ei_linked_point_t* new_point = malloc(sizeof(ei_linked_point_t)); new_point->point = ei_point( (int)(R*cos(angle)) + centre.x, (int)(R*sin(angle)) + centre.y); new_point->next = NULL; concat_lists(&liste, &new_point); // Pas de rotation = 0.1 angle = angle + 0.1; } ei_linked_point_t* last_point = malloc(sizeof(ei_linked_point_t)); last_point->point = ei_point( (int)(R*cos(anglefin)) + centre.x, (int)(R*sin(anglefin)) + centre.y); last_point->next = NULL; concat_lists(&liste, &last_point); return liste; }
void ei_geomnotify_button(ei_widget_t *widget, ei_rect_t rect) { *(widget->content_rect) = ei_rect( ei_point_add( rect.top_left, ei_point( *ei_button(widget)->border_width, *ei_button(widget)->border_width)), ei_size( rect.size.width - 2 * *ei_button(widget)->border_width, rect.size.height - 2 * *ei_button(widget)->border_width)); }
/* Modifie l'Etat du bouton*/ void set_button_press(ei_widget_t * button) { ei_geomnotify_button(button, ei_rect( ei_point_add( button->screen_location.top_left, ei_point( EI_BUTTON_SINK_LENGHT, EI_BUTTON_SINK_LENGHT)), button->screen_location.size)); *ei_button(button)->relief = ei_relief_sunken; ei_app_invalidate_rect(&button->screen_location); if(*ei_button(button)->callback) ei_bind(ei_ev_mouse_buttonup, button, NULL, *ei_button(button)->callback, ei_button(button)->user_param); }
// Requiert : - high, booléen qui vaut true ssi on souhaite le contour // de la partie supérieure // - low, booléen qui vaut true ssi on souhaite le contour // de la partie inférieure // - rect, rectangle contenant le bouton sur lequel dessiner // le contour // - R, rayon des arcs de cercles des coins du bouton // - border, la largeur de la bordure (relief) en pixels // Retourne : Une liste chaînée de points correspondant au contour // arrondi d'un bouton ei_linked_point_t* ei_curvy_contour_button(ei_bool_t high, ei_bool_t low, ei_rect_t rect, float R, int border) { // Pointeur "curve_button" sur la liste à retourner ei_linked_point_t* curve_button = NULL; // Calcul des 4 points intérieurs clés pour calculer les 4 bords ei_point_t centertopleft = ei_point( rect.top_left.x + R, rect.top_left.y + R ); ei_point_t centertopright = ei_point( rect.top_left.x + rect.size.width - R, rect.top_left.y + R ); ei_point_t centerbottomleft = ei_point( rect.top_left.x + R, rect.top_left.y + rect.size.height - R ); ei_point_t centerbottomright= ei_point(rect.top_left.x + rect.size.width - R -1.0, rect.top_left.y + rect.size.height - R); // Calcul des 2 listes représentant les 2 coins non coupés // (topleft et bottomright) ei_linked_point_t* curvetopleft = ei_draw_arc(centertopleft, R-(float)border, M_PI, 1.5*M_PI); ei_linked_point_t* curvebottomright = ei_draw_arc(centerbottomright, R-(float)border, 0.0, 0.5*M_PI); // Définition de h = demi-hauteur int h = rect.size.height/2; // Calcul des deux points de marquage de la ligne centrale ei_point_t markleft = ei_point(rect.top_left.x + h, rect.top_left.y + h); ei_point_t markright = ei_point(rect.top_left.x + rect.size.width - h, rect.top_left.y + h); // Calcul des 4 listes représentant les 2 coins coupés // (bottomleft et topright) ei_linked_point_t* curvebottomleft_low = ei_draw_arc(centerbottomleft, R-(float)border, 0.5 *M_PI, 0.75*M_PI); ei_linked_point_t* curvetopright_low = ei_draw_arc(centertopright, R-(float)border, 1.75*M_PI, 2*M_PI); ei_linked_point_t* curvebottomleft_high = ei_draw_arc(centerbottomleft, R-(float)border, 0.75*M_PI, M_PI); ei_linked_point_t* curvetopright_high = ei_draw_arc(centertopright, R-(float)border, 1.5 *M_PI, 1.75*M_PI); // Chaînage des points et listes de points suivants les différents cas // pour "high" et "low" // CAS 1 : on veut tout le contour if ( (high == EI_TRUE) && (low == EI_TRUE) ) { // Partie supérieure concat_lists(&curve_button, &curvebottomleft_high); concat_lists(&curve_button, &curvetopleft); concat_lists(&curve_button, &curvetopright_high); // Partie inférieure concat_lists(&curve_button, &curvetopright_low); concat_lists(&curve_button, &curvebottomright); concat_lists(&curve_button, &curvebottomleft_low); // CAS 2 : on ne veut que le contour supérieur } else if ( (high == EI_TRUE) && (low == EI_FALSE) ) { concat_lists(&curve_button, &curvebottomleft_high); concat_lists(&curve_button, &curvetopleft); concat_lists(&curve_button, &curvetopright_high); // Ligne de démarquation ei_linked_point_t* marquage_droit = malloc(sizeof(ei_linked_point_t)); marquage_droit->point = markright; marquage_droit->next = NULL; concat_lists(&curve_button, &marquage_droit); ei_linked_point_t* marquage_gauche = malloc(sizeof(ei_linked_point_t)); marquage_gauche->point = markleft; marquage_gauche->next = NULL; concat_lists(&curve_button, &marquage_gauche); // Libération des listes non utilisées ei_free_linked_points_list(curvebottomright); ei_free_linked_points_list(curvebottomleft_low); ei_free_linked_points_list(curvetopright_low); // CAS 3 : on ne veut que le contour inférieur } else if ( (high == EI_FALSE) && (low == EI_TRUE) ) { concat_lists(&curve_button, &curvetopright_low); concat_lists(&curve_button, &curvebottomright); concat_lists(&curve_button, &curvebottomleft_low); // Ligne de démarquation ei_linked_point_t* marquage_gauche = malloc(sizeof(ei_linked_point_t)); marquage_gauche->point = markleft; marquage_gauche->next = NULL; concat_lists(&curve_button, &marquage_gauche); ei_linked_point_t* marquage_droit = malloc(sizeof(ei_linked_point_t)); marquage_droit->point = markright; marquage_droit->next = NULL; concat_lists(&curve_button, &marquage_droit); // Libération des listes non utilisées ei_free_linked_points_list(curvetopleft); ei_free_linked_points_list(curvebottomleft_high); ei_free_linked_points_list(curvetopright_high); } return(curve_button); }
// Dessine l'image d'un widget void ei_draw_widget_img( ei_surface_t surface, ei_widget_t* widget, ei_surface_t img, ei_rect_t* img_rect, ei_anchor_t anchor, int button_border_width ) { // Paramètres du widget ei_point_t wtopleft = ei_point_add( widget->screen_location.top_left, ei_point(2*button_border_width, 2*button_border_width) ); ei_size_t wsize = ei_size_sub( widget->screen_location.size, ei_size(4*button_border_width, 4*button_border_width) ); // Variables à calculer ei_rect_t dst_widget_rect; ei_rect_t src_image_rect; /***********************************************/ /* ETAPE 1 : CALCUL DE LA TAILLE DE DST ET SRC */ /***********************************************/ ei_size_t img_size; if (img_rect != NULL) { img_size = img_rect->size; } else { img_size = hw_surface_get_size(img); } // Calcul de la largeur de la zone de copie if (img_size.width > wsize.width) { src_image_rect.size.width = wsize.width; dst_widget_rect.size.width = wsize.width; } else { src_image_rect.size.width = img_size.width; dst_widget_rect.size.width = img_size.width; } // Calcul de la hauteur de la zone de copie if (img_size.height > wsize.height) { src_image_rect.size.height = wsize.height; dst_widget_rect.size.height = wsize.height; } else { src_image_rect.size.height = img_size.height; dst_widget_rect.size.height = img_size.height; } /*************************************/ /* ETAPE 2 : CALCUL DES DEUX TOPLEFT */ /*************************************/ // Calcul du topleft de la destination ei_switch_anchor(anchor, &(dst_widget_rect.top_left), dst_widget_rect.size, wtopleft, wsize); // Calcul du topleft de la source if (img_rect != NULL) { src_image_rect.top_left = img_rect->top_left; // fprintf(stderr, "x %i\n", img_rect->top_left.x); // fprintf(stderr, "y %i\n", img_rect->top_left.y); } else { // Par défaut je prend le coin en haut à gauche de l'image ei_rect_t rect_total = hw_surface_get_rect(img); src_image_rect.top_left = rect_total.top_left; } /*************************************************************/ /* ETAPE 2bis : RECALCUL SI SORTIE DU CADRE PRINCIPAL (ROOT) */ /*************************************************************/ ei_surface_t display_surface = ei_app_root_surface(); ei_rect_t display_rect = hw_surface_get_rect(display_surface); int cut; // Cas 1 : sortie à gauche cut = display_rect.top_left.x - dst_widget_rect.top_left.x; if ( cut > 0 ) { // Changement de DST dst_widget_rect.top_left.x = display_rect.top_left.x; dst_widget_rect.size.width = dst_widget_rect.size.width - cut; // Changement de SRC src_image_rect.top_left.x = src_image_rect.top_left.x + cut; src_image_rect.size = dst_widget_rect.size; } // Cas 2 : sortie à droite cut = dst_widget_rect.top_left.x + dst_widget_rect.size.width - display_rect.top_left.x - display_rect.size.width; if ( cut > 0 ) { // Changement de DST dst_widget_rect.size.width = dst_widget_rect.size.width - cut; // Changement de SRC src_image_rect.size = dst_widget_rect.size; } // Cas 3 : sortie en haut cut = display_rect.top_left.y - dst_widget_rect.top_left.y; if ( cut > 0 ) { // Changement de DST dst_widget_rect.top_left.y = display_rect.top_left.y; dst_widget_rect.size.height = dst_widget_rect.size.height - cut; // Changement de SRC src_image_rect.top_left.y = src_image_rect.top_left.y + cut; src_image_rect.size = dst_widget_rect.size; } // Cas 4 : sortie en bas cut = dst_widget_rect.top_left.y + dst_widget_rect.size.height - display_rect.top_left.y - display_rect.size.height; if ( cut > 0 ) { // Changement de DST dst_widget_rect.size.height = dst_widget_rect.size.height - cut; // Changement de SRC src_image_rect.size = dst_widget_rect.size; } /*****************************************/ /* ETAPE 3 : COPIE DE L'IMAGE A AFFICHEE */ /*****************************************/ hw_surface_lock(img); ei_copy_surface(surface, &dst_widget_rect, img, &src_image_rect, EI_FALSE); hw_surface_unlock(img); }
void create_puzzle_window(char* image_filename) { /*ei_widget_t* toplevel; ei_surface_t image; ei_size_t image_size; int x, y; int border_width = 2; ei_point_t place_coords; ei_point_t current_position; ei_size_t n; ei_size_t toplevel_size; ei_size_t image_rect_size; ei_size_t tile_size = ei_size(k_tile_size, k_tile_size); char* title = "Puzzle"; ei_color_t toplevel_bg = {0xff, 0xff, 0xff, 0x60}; ei_axis_set_t resizable = ei_axis_none;*/ ei_widget_t* frame; ei_surface_t image; ei_size_t image_size; int x, y; int border_width = 2; ei_point_t place_coords; ei_point_t current_position; ei_size_t n; ei_size_t toplevel_size; ei_size_t image_rect_size; ei_size_t tile_size = ei_size(k_tile_size, k_tile_size); ei_color_t toplevel_bg = {0xff, 0xff, 0xff, 0x60}; ei_axis_set_t resizable = ei_axis_none; ei_widget_t* button; ei_color_t grey = {0x88, 0x88, 0x88, 0xff}; int corner_radius = 0; ei_relief_t relief = ei_relief_raised; ei_rect_t img_rect; ei_rect_t* img_rect_ptr = &img_rect; ei_callback_t callback = handle_tile_press; puzzle_t* puzzle; tile_t* tile; image = hw_image_load(image_filename, ei_app_root_surface()); image_size = hw_surface_get_size(image); n = ei_size(image_size.width / k_tile_size, image_size.height / k_tile_size); frame = ei_widget_create("frame", ei_app_root_widget()); toplevel_size = ei_size(n.width*k_tile_size, n.height*k_tile_size); border_width = 0; ei_frame_configure(frame, &toplevel_size, &toplevel_bg, &border_width, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); ei_place(frame, NULL, &(g_toplevel_position.x), &(g_toplevel_position.y), NULL, NULL, NULL, NULL, NULL, NULL); g_toplevel_position = ei_point_add(g_toplevel_position, ei_point(12, 12)); puzzle = (puzzle_t*)malloc(sizeof(*puzzle)); puzzle->n = n; puzzle->tiles = (tile_t*) malloc(n.width*n.height*sizeof(tile_t)); puzzle->current = (tile_t**)malloc(n.width*n.height*sizeof(tile_t*)); border_width = 2; image_rect_size = ei_size_sub(tile_size, ei_size(2*border_width, 2*border_width)); for (y = 0; y < n.height; y++) { for (x = 0; x < n.width; x++) { current_position = ei_point(x, y); if ((x == n.width - 1) && (y == n.height - 1)) { puzzle->current[index_at(puzzle, current_position)] = NULL; continue; } button = ei_widget_create("button", frame); img_rect = ei_rect(ei_point(x*k_tile_size+border_width, y*k_tile_size+border_width), image_rect_size); tile = tile_memory_at(puzzle, ei_point(x, y)); printf("puzzle.c WIDTH::%i\n",img_rect_ptr->size.width); ei_button_configure(button, &tile_size, &grey, &border_width, &corner_radius, &relief, NULL, NULL, NULL, NULL, &image, &img_rect_ptr, NULL, &callback, (void*)&tile); place_coords = place_coordinates(current_position); ei_place(button, NULL, &(place_coords.x), &(place_coords.y), NULL, NULL, NULL, NULL, NULL, NULL); tile->puzzle = puzzle; tile->button = button; tile->original_position = current_position; tile->current_position = current_position; puzzle->current[index_at(puzzle, current_position)] = tile; } } }
static inline ei_point_t place_coordinates(ei_point_t pos) { return ei_point(pos.x*k_tile_size, pos.y*k_tile_size); }
void ei_runfunc_placer(struct ei_widget_t* widget) { // we load the location of the father widget ei_rect_t* container = widget->parent->content_rect; ei_geometrymanager_param_placer_t* prm_placer = (ei_geometrymanager_param_placer_t*)widget->geom_params; float width, height ; assert(prm_placer); assert(prm_placer->rel_width); width = container->size.width * *(prm_placer->rel_width) + *(prm_placer->width); height = container->size.height * *(prm_placer->rel_height) + *(prm_placer->height); ei_point_t pos_rel; switch (*(prm_placer->anchor)) { case ei_anc_none: case ei_anc_northwest: pos_rel = ei_point_zero(); break; case ei_anc_center: pos_rel = ei_point(width / 2, height / 2); break; case ei_anc_north: pos_rel = ei_point(width / 2, 0); break; case ei_anc_northeast: pos_rel = ei_point(width , 0); break; case ei_anc_east: pos_rel = ei_point(width, height / 2); break; case ei_anc_southeast: pos_rel = ei_point(width, height ); break; case ei_anc_south: pos_rel = ei_point(width / 2, height); break; case ei_anc_southwest: pos_rel = ei_point(0 , height ); break; case ei_anc_west: pos_rel = ei_point(0 , height / 2 ); break; } ei_point_t pos_abs = ei_point( container->size.width * *(prm_placer->rel_x) + *(prm_placer->x), container->size.height * *(prm_placer->rel_y) + *(prm_placer->y)); // ei_app_invalidate_rect(&widget->screen_location); widget->screen_location = ei_rect( ei_point_add(ei_point_sub(pos_abs, pos_rel),container->top_left), ei_size(width, height)); ei_app_invalidate_rect(&widget->screen_location); widget->wclass->geomnotifyfunc(widget, widget->screen_location); ei_widget_t * current = widget->children_head; while(current) { if(current->geom_params) { current->geom_params->manager->runfunc(current); } current = current->next_sibling; } }