sav

Sorting Algorithms Visualized
Index Commits Files Refs README LICENSE
commit 6b0a1482cd53e253f55af83940232602472e8e31
parent 56f6a24f96bd857dc7e7e35f963cb4ce69ed7073
Author: klewer-martin <martin.cachari@gmail.com>
Date:   Wed, 30 Mar 2022 22:58:37 -0300

Added status bar

Now the window shows a statusbar in the bottom, still not finished yet
but the concept it's there.

Diffstat:
MMakefile | 6+++---
Mdrw.c | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Mdrw.h | 29++++++++++++++++++++++++-----
Msav.c | 72+++++++++++++++++++++++++++++++++++++++++++++---------------------------
Msav.h | 5+++++
Msdl_extra.c | 6++++++
Msdl_extra.h | 5+++--
Msort.c | 3++-
Msort.h | 3+++
Mutil.h | 5+++--
10 files changed, 158 insertions(+), 65 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,6 +1,6 @@
 CC := cc
 CLIBS := `sdl2-config --libs --cflags`
-CFLAGS := -lSDL2_image -lm -Werror -Wall -pedantic -ansi -std=c99 -g -pthread
+CFLAGS := -lSDL2_ttf -lm -Werror -Wall -pedantic -ansi -std=c99 -g -pthread
 SRCS := sav.c util.c sort.c drw.c sdl_extra.c
 OBJS := $(SRCS:.c=.o)
 
@@ -11,10 +11,10 @@ TARGET := sav
 all: $(TARGET) clean
 
 $(TARGET): $(OBJS)
-    $(CC) $(CFLAGS) $(CLIBS) -o $@ $^
+    $(CC) $(CLIBS) $(CFLAGS) -o $@ $^
 
 %.o: %.c
-    $(CC) $(CFLAGS) $(CLIBS) -c $< -o $@
+    $(CC) $(CLIBS) $(CFLAGS) -c $< -o $@
 
 clean:
     rm -f $(OBJS)
diff --git a/drw.c b/drw.c
@@ -1,23 +1,6 @@
 #include "drw.h"
 
 void
-drw_element(SDL_Renderer *rend, int x, int y, int h) {
-    SDL_Rect rect;
-
-    rect.x = x + X_BORDER; /* top left + x */
-    rect.y = y - Y_BORDER; /* top left + y, (y < 0) */
-    rect.w = RECT_WIDTH; /* fixed width */
-    rect.h = -h;
-
-    SDL_RenderDrawRect(rend, &rect);
-    SDL_SetRenderDrawColor(rend, 255, 0, 0, 0); /* RGBA */
-    SDL_RenderFillRect(rend, &rect);
-
-    SDL_SetRenderDrawColor(rend, 0, 0, 0, 0);
-    SDL_RenderDrawLine(rend, x + X_BORDER, y - Y_BORDER, x + X_BORDER, y - Y_BORDER - h);
-}
-
-void
 drw_element_color(SDL_Renderer *rend, int x, int y, int h, unsigned int col) {
     SDL_Rect rect;
     unsigned char r, g, b, a;
@@ -41,20 +24,76 @@ drw_element_color(SDL_Renderer *rend, int x, int y, int h, unsigned int col) {
 }
 
 void
-drw_array_graph(SDL_Renderer *rend, SDL_Window *win, SAV *sav) {
+drw_array_graph(Drw *drw, SAV *sav) {
     int x, w, h;
 
-    SDL_GetWindowSize(win, &w, &h);
+    SDL_GetWindowSize(drw->win, &w, &h);
 
-    SDL_SetRenderDrawColor(rend, 29, 28, 28, 0);
-    SDL_RenderClear(rend);
+    SDL_SetRenderDrawColor(drw->rend, 29, 28, 28, 0);
+    SDL_RenderClear(drw->rend);
 
     size_t i;
     for(i = x = 0; i < sav->arr->len; i++, x += RECT_WIDTH) {
-        if(i == sav->sel) drw_element_color(rend, x, h, sav->arr->v[i], SEL_COLOR);
-        else if(i == sav->cmp) drw_element_color(rend, x, h, sav->arr->v[i], CMP_COLOR);
-        else drw_element(rend, x, h, sav->arr->v[i]);
+        if(i == sav->sel) drw_element_color(drw->rend, x, h, sav->arr->v[i], SEL_COLOR);
+        else if(i == sav->cmp) drw_element_color(drw->rend, x, h, sav->arr->v[i], CMP_COLOR);
+        else drw_element_color(drw->rend, x, h, sav->arr->v[i], NORM_COLOR);
     }
+    drw_status_bar(drw, sav);
+}
+
+void
+drw_status_bar(Drw *drw, SAV *sav) {
+    SDL_Rect rect;
+    int bar_border = 2;
+
+    rect.x = bar_border; /* top left + x */
+    rect.y = drw->h - bar_border; /* top left + y, (y < 0) */
+    rect.w = drw->w - (2 * bar_border); /* fixed width */
+    rect.h = -BAR_HEIGHT;
+
+    SDL_RenderDrawRect(drw->rend, &rect);
+    SDL_SetRenderDrawColor(drw->rend, 0, 0, 0, 0); /* RGBA */
+    SDL_RenderFillRect(drw->rend, &rect);
+
+    if((sav->status == RUN) || (sav->status == UPDATE))
+        drw_text(drw, "SORTING -- insertion sort", 10, drw->h - drw->font_size - 5);
+    else if(sav->status == SORTED)
+        drw_text(drw, "SORTED -- insertion sort", 10, drw->h - drw->font_size - 5);
+
+    /* SDL_RenderCopy(drw->rend, drw->text_texture, NULL, &text_rect); */
+}
+
+void drw_text(Drw *drw, char *text, int x, int y) {
+    drw->text_surface = TTF_RenderText_Blended(drw->font, text, drw->text_color);
+    drw->text_texture = SDL_CreateTextureFromSurface(drw->rend, drw->text_surface);
+
+    SDL_Rect text_rect = { 10 + x, drw->h - drw->font_size - 5, drw->text_surface->w, drw->text_surface->h };
+
+    SDL_RenderCopy(drw->rend, drw->text_texture, NULL, &text_rect);
+}
+
+status_t DRW_New(SDL_Renderer *rend, SDL_Window *win, Drw **drw) {
+    if((*drw = (Drw *)malloc(sizeof(Drw))) == NULL)
+        return ERROR_MEMORY_ALLOC;
+
+    TTF_Font *font = TTF_OpenFont("/usr/share/fonts/TTF/DejaVuSansMono.ttf", FONT_SIZE);
+    if(!font) fprintf(stderr, "TTF_OpenFont: %s\n", TTF_GetError());
+
+    (*drw)->rend = rend;
+    (*drw)->win = win;
+    (*drw)->font = font;
+    (*drw)->font_size = FONT_SIZE;
+
+    (*drw)->text_color.r = 255;
+    (*drw)->text_color.g = 255;
+    (*drw)->text_color.b = 255;
+
+    SDL_GetWindowSize(win, &((*drw)->w), &((*drw)->h));
+
+    return 0;
+}
 
-    SDL_RenderPresent(rend);
+void DRW_Destroy(Drw *drw) {
+    TTF_CloseFont(drw->font);
+    free(drw);
 }
diff --git a/drw.h b/drw.h
@@ -2,19 +2,38 @@
 #define __DRAW_H__
 
 #include <SDL2/SDL.h>
-#include <SDL2/SDL_video.h>
-#include <SDL2/SDL_image.h>
+#include <SDL2/SDL_ttf.h>
 
-#include "util.h"
 #include "sav.h"
+#include "util.h"
+#include "sort.h"
 
 #define SEL_COLOR    0x00FF0000 // RGBA (A not used rn)
 #define CMP_COLOR    0x00FFFF00
+#define NORM_COLOR    0xFF000000
+
+#define FONT_SIZE    11
+#define BAR_HEIGHT    14
+
+typedef struct {
+    SDL_Renderer *rend;
+    SDL_Window *win;
+    SDL_Surface *text_surface;
+    SDL_Texture *text_texture;
+    SDL_Color text_color;
+    TTF_Font *font;
+    int w, h, font_size;
+} Drw;
+
+status_t DRW_New(SDL_Renderer *rend, SDL_Window *win, Drw **drw);
+void DRW_Destroy(Drw *drw);
 
 void drw_element(SDL_Renderer *rend, int x, int y, int h);
-/* void draw_array_graph(SDL_Renderer *rend, SDL_Window *win, Arr *arr); */
 void drw_element_color(SDL_Renderer *rend, int x, int y, int h, unsigned int col);
+void drw_array_graph(Drw *drw, SAV *sav);
+void drw_status_bar(Drw *drw, SAV *sav);
+void drw_text(Drw *drw, char *text, int x, int y);
 
-void drw_array_graph(SDL_Renderer *rend, SDL_Window *win, SAV *sav);
+void loading_animation(Drw *drw, SAV *sav);
 
 #endif // __DRAW_H__
diff --git a/sav.c b/sav.c
@@ -1,20 +1,46 @@
+#include <time.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <stdbool.h>
-#include <time.h>
-#include <SDL2/SDL.h>
-#include <SDL2/SDL_video.h>
-#include <SDL2/SDL_image.h>
-
 #include <unistd.h>
+#include <stdbool.h>
 #include <pthread.h>
 
+#include <SDL2/SDL.h>
+#include <SDL2/SDL_ttf.h>
+
 #include "sav.h"
 #include "drw.h"
 #include "util.h"
 #include "sort.h"
 #include "sdl_extra.h"
 
+status_t SAV_New(SAV **sav) {
+    if((*sav = (SAV *)malloc(sizeof(SAV))) == NULL)
+        return ERROR_MEMORY_ALLOC;
+
+    (*sav)->sel = (*sav)->cmp = 0;
+    (*sav)->status = RUN;
+
+    if(((*sav)->arr = (Arr *)malloc(sizeof(Arr))) == NULL)
+        return ERROR_MEMORY_ALLOC;
+
+    if(((*sav)->arr->v = (int *)malloc(sizeof(int) * ARR_LEN)) == NULL)
+        return ERROR_MEMORY_ALLOC;
+
+    (*sav)->arr->len = ARR_LEN;
+
+    if((*sav)->arr == NULL) {
+        return ERROR_MEMORY_ALLOC;
+    }
+    return 0;
+}
+
+void SAV_Destroy(SAV *sav) {
+    free(sav->arr->v);
+    free(sav->arr);
+    free(sav);
+}
+
 void *
 routine_wrapper(void *arg) {
     SAV *sav = (SAV *)arg;
@@ -26,30 +52,17 @@ routine_wrapper(void *arg) {
 
 int
 main (void) {
-    SAV *sav = NULL;
+    SAV *sav;
+    Drw *drw;
     SDL_Renderer *rend;
     SDL_Window *win;
+
     pthread_t p1;
 
     setup(&win, &rend);
 
-    if((sav = (SAV *)malloc(sizeof(SAV))) == NULL)
-        return ERROR_MEMORY_ALLOC;
-
-    sav->sel = sav->cmp = 0;
-    sav->status = RUN;
-
-    if((sav->arr = (Arr *)malloc(sizeof(Arr))) == NULL)
-        return ERROR_MEMORY_ALLOC;
-
-    if((sav->arr->v = (int *)malloc(sizeof(int) * ARR_LEN)) == NULL)
-        return ERROR_MEMORY_ALLOC;
-
-    sav->arr->len = ARR_LEN;
-
-    if(sav->arr == NULL) {
-        return ERROR_MEMORY_ALLOC;
-    }
+    SAV_New(&sav);
+    DRW_New(rend, win, &drw);
 
     /* assigns random values to array */
     srand((unsigned int)time(NULL));
@@ -62,15 +75,20 @@ main (void) {
     while(sav->status != STOP) {
         check_events(&(sav->status)); 
         if(sav->status == UPDATE) {
-            drw_array_graph(rend, win, sav);
+            drw_array_graph(drw, sav);
             sav->status = RUN;
+            SDL_RenderPresent(rend);
+        }
+        if(sav->status == SORTED) {
+            drw_array_graph(drw, sav);
+            SDL_RenderPresent(rend);
         }
     }
 
     pthread_join(p1, NULL);
 
-    free(sav->arr);
-    free(sav);
+    SAV_Destroy(sav);
+    DRW_Destroy(drw);
 
     cleanup(win, rend);
     return 0;
diff --git a/sav.h b/sav.h
@@ -3,10 +3,15 @@
 
 #include "util.h"
 
+#include <SDL2/SDL.h>
+
 typedef struct {
     Arr *arr;
     size_t sel, cmp;
     status_t status;
 } SAV;
 
+status_t SAV_New(SAV **sav);
+void SAV_Destroy(SAV *sav);
+
 #endif
diff --git a/sdl_extra.c b/sdl_extra.c
@@ -44,6 +44,11 @@ setup(SDL_Window **win, SDL_Renderer **rend) {
 
     *rend = SDL_CreateRenderer(*win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
 
+    if(TTF_Init()==-1) {
+        printf("TTF_Init: %s\n", TTF_GetError());
+        exit(2);
+    }
+
     if (*win == NULL) end("SDL: window cannot be created");
     else if (*rend == NULL) end("SDL: renderer cannot be created");
 
@@ -63,5 +68,6 @@ void
 cleanup(SDL_Window *win, SDL_Renderer *rend) {
     SDL_DestroyRenderer(rend);
     SDL_DestroyWindow(win);
+    TTF_Quit();
     SDL_Quit();
 }
diff --git a/sdl_extra.h b/sdl_extra.h
@@ -3,8 +3,9 @@
 
 #include <stdbool.h>
 #include <SDL2/SDL.h>
-#include <SDL2/SDL_video.h>
-#include <SDL2/SDL_image.h>
+#include <SDL2/SDL_ttf.h>
+/* #include <SDL2/SDL_video.h> */
+/* #include <SDL2/SDL_image.h> */
 
 /* typedef struct { */
 /*     status_t status; */
diff --git a/sort.c b/sort.c
@@ -13,7 +13,7 @@ insertion_sort(SAV *sav) {
         j = i - 1;
         while((j >= 0) && (sav->arr->v[j] > key)) {
             sav->arr->v[j + 1] = sav->arr->v[j];
-            j = j - 1;
+            j--;
 
             sav->sel = i;
             sav->cmp = j;
@@ -29,4 +29,5 @@ insertion_sort(SAV *sav) {
         wait_main_thread(&(sav->status));
         if(sav->status == STOP) break;
     }
+    if(sav->status != STOP) sav->status = SORTED;
 }
diff --git a/sort.h b/sort.h
@@ -1,6 +1,9 @@
 #ifndef __SORT_H__
 #define __SORT_H__
 
+#include <stdio.h>
+#include <stdbool.h>
+
 #include "sav.h"
 #include "util.h"
 
diff --git a/util.h b/util.h
@@ -4,8 +4,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#define ARR_LEN        120
-#define ARR_MAX        500
+#define ARR_LEN        100
+#define ARR_MAX        400
 
 #define X_BORDER    40
 #define Y_BORDER    40
@@ -18,6 +18,7 @@ typedef enum {
     PAUSE,
     UPDATE,
     ERROR_MEMORY_ALLOC,
+    SORTED,
     STOP
 } status_t;