repos/menu

A graphical menu within a window
Commits Files Refs
menu.c (162 lines)
   1 #include "menu.h"
   2 
   3 /* Finds the selected entry then selects next */
   4 void Set_select_next(Set *set) {
   5     for(int i = 0; i < set->size; i++) {
   6         if(set->elements[i]->selected == true) {
   7             set->elements[i]->selected = false;
   8             if((i + 1) == set->size) set->elements[0]->selected = true;
   9             else set->elements[i + 1]->selected = true;
  10             i++;
  11             continue;
  12         }
  13         set->elements[i]->selected = false;
  14     }
  15 }
  16 
  17 /* Finds the selected entry then selects previous */
  18 void Set_select_prev(Set *set) {
  19     for(int i = 0; i < set->size; i++) {
  20         if(set->elements[i]->selected == true) {
  21             set->elements[i]->selected = false;
  22             if(i == 0) {
  23                 set->elements[set->size - 1]->selected = true;
  24                 break;
  25             }
  26             else set->elements[i - 1]->selected = true;
  27         }
  28     }
  29 }
  30 
  31 void Set_select_index(Set *set, size_t index) {
  32     size_t i;
  33     for(i = 0; i < set->size; i++) {
  34         if(set->elements[i]->index == index) set->elements[i]->selected = true;
  35         else if(set->elements[i]->selected == true) set->elements[i]->selected = false;
  36     }
  37 }
  38 
  39 size_t Set_elem_at(Set *set, int x, int y) {
  40     size_t i;
  41 
  42     for(i = 0; i < set->size; i++)
  43         if((y < set->elements[i]->pos.y) && (y > (set->elements[i]->pos.y - BAR_H)))
  44             return i;
  45 
  46     return set->size;
  47 }
  48 
  49 void Set_compute_pos(Set *set, int win_w, int win_h) {
  50     int first_entry_pos_y, win_center_y;
  51     size_t i;
  52 
  53     win_center_y = (win_h / 2);
  54     first_entry_pos_y = win_center_y -
  55         ((((BAR_H + ELEMENTS_PADDING) * set->size) - ELEMENTS_PADDING) / 2) + BAR_H;
  56 
  57     for(i = 0; i < set->size; i++) {
  58         set->elements[i]->pos.x = BAR_BORDER;
  59         set->elements[i]->pos.y = (first_entry_pos_y + (set->elements[i]->index * (ELEMENTS_PADDING + BAR_H)));
  60     }
  61 }
  62 
  63 void Set_hover_elem(Set *set, size_t index) {
  64     size_t i;
  65 
  66     for(i = 0; i < set->size; i++)
  67         set->elements[i]->hover = ((i == index) ? true : false);
  68 }
  69 
  70 void Set_hover_at(Set *set, int x, int y) {
  71     size_t i;
  72 
  73     for(i = 0; i < set->size; i++) {
  74         if((y < set->elements[i]->pos.y) && (y > (set->elements[i]->pos.y - BAR_H)))
  75             set->elements[i]->hover = true;
  76         else set->elements[i]->hover = false;
  77     }
  78 }
  79 
  80 void Elem_draw(SDL_Renderer *rend, TTF_Font *font, int win_w, int win_h, const Elem *elem) {
  81     SDL_Surface *text_surface;
  82     SDL_Texture *text_texture;
  83     SDL_Rect text_rect, box;
  84     SDL_Color text_color, text_color_shadow;
  85     int text_w, text_h;
  86 
  87     text_color = mk_SDL_Color(UNHEX(FONT_COLOR));
  88     text_color_shadow = mk_SDL_Color(UNHEX(SHADOW_COLOR));
  89 
  90     box = (SDL_Rect) { BAR_BORDER, elem->pos.y, win_w - (BAR_BORDER * 2), -BAR_H };
  91 
  92     SDL_SetRenderDrawColor(rend, UNHEX(elem->selected ? SEL_COLOR : (elem->hover ? HOVER_COLOR : NORM_COLOR)));
  93     SDL_RenderFillRect(rend, &box);
  94 
  95     TTF_SizeText(font, elem->text, &text_w, &text_h);
  96 
  97     /* Draw shadow */
  98     if(elem->selected) {
  99         text_surface = TTF_RenderText_Blended(font, elem->text, text_color_shadow);
 100         text_texture = SDL_CreateTextureFromSurface(rend, text_surface);
 101 
 102         text_rect.x = (win_w / 2) - (text_w / 2) + 2;
 103         text_rect.y = elem->pos.y - (BAR_H + 1) + 2;
 104         text_rect.w = text_surface->w;
 105         text_rect.h = text_surface->h;
 106 
 107         SDL_RenderCopy(rend, text_texture, NULL, &text_rect);
 108         SDL_DestroyTexture(text_texture);
 109         SDL_FreeSurface(text_surface);
 110     }
 111 
 112     text_surface = TTF_RenderText_Blended(font, elem->text, text_color);
 113     text_texture = SDL_CreateTextureFromSurface(rend, text_surface);
 114     text_rect.x = (win_w / 2) - (text_w / 2);
 115     text_rect.y = elem->pos.y - (BAR_H + 1);
 116     text_rect.w = text_surface->w;
 117     text_rect.h = text_surface->h;
 118 
 119     SDL_RenderCopy(rend, text_texture, NULL, &text_rect);
 120     SDL_DestroyTexture(text_texture);
 121     SDL_FreeSurface(text_surface);
 122 }
 123 
 124 void Set_new(Set **set, size_t size) {
 125     if(size == 0) return;
 126 
 127     (*set) = malloc(sizeof(Set));
 128 
 129     if((*set) == NULL)
 130         return;
 131 
 132     if(((*set)->elements = malloc(sizeof(Elem) * size)) == NULL)
 133         return;
 134 
 135     for(size_t i = 0; i < size; i++)
 136         if(((*set)->elements[i] = malloc(sizeof(Elem))) == NULL)
 137             return;
 138 
 139     /* Initialize elements */
 140     (*set)->size = size;
 141     for(size_t i = 0; i < size; i++) {
 142         (*set)->elements[i]->text = NULL;
 143         (*set)->elements[i]->selected = false;
 144         (*set)->elements[i]->hover = false;
 145         (*set)->elements[i]->index = i;
 146     }
 147 
 148     (*set)->elements[0]->selected = true;
 149 }
 150 
 151 void Set_destroy(Set *set) {
 152     free(set->elements);
 153     free(set);
 154 }
 155 
 156 void Elem_set_text(Elem *el, const char *src) {
 157     size_t text_len = strlen(src);
 158 
 159     el->text = calloc(text_len + 1, sizeof(char));
 160 
 161     strcpy(el->text, src);
 162 }