aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArslaan Pathan <[email protected]>2026-04-22 21:06:58 +1200
committerArslaan Pathan <[email protected]>2026-04-22 21:06:58 +1200
commit289ca3be66a5731fdcd8e2901514ddbb113c5076 (patch)
tree6ec66f374e042a57bcfaa288d0aa444517488d45
parent76516edf2c8c6ba36c0abb48871b5e69e9930dd2 (diff)
downloadsaffron-289ca3be66a5731fdcd8e2901514ddbb113c5076.tar.xz
saffron-289ca3be66a5731fdcd8e2901514ddbb113c5076.zip
Make the layout work roughly, make boxes have a size, update test code to work with boxes
-rw-r--r--include/saffron_api.h2
-rw-r--r--include/saffron_widget.h16
-rw-r--r--meson.build4
-rw-r--r--src/saffron_layout.c29
-rw-r--r--src/saffron_widget.c2
-rw-r--r--src/saffron_window.c12
-rw-r--r--tests/test_main.c30
7 files changed, 73 insertions, 22 deletions
diff --git a/include/saffron_api.h b/include/saffron_api.h
index 7b6fabb..64251e0 100644
--- a/include/saffron_api.h
+++ b/include/saffron_api.h
@@ -20,7 +20,7 @@ void saffron_window_show(SaffronWindow* window);
void saffron_window_main(SaffronWindow* window);
SaffronWidget* saffron_widget_hit_test(SaffronWidget* widget, int x, int y);
-SaffronBox* saffron_box_new(SaffronOrientation orientation, SaffronHorizontalAlignment halign, SaffronVerticalAlignment valign, int spacing, int padding, int margin);
+SaffronBox* saffron_box_new(SaffronOrientation orientation, SaffronHorizontalAlignment halign, SaffronVerticalAlignment valign, int spacing, int padding, int margin, int width, int height);
void saffron_box_layout(SaffronBox* box);
#endif
diff --git a/include/saffron_widget.h b/include/saffron_widget.h
index 4461555..7fc6bc8 100644
--- a/include/saffron_widget.h
+++ b/include/saffron_widget.h
@@ -3,12 +3,17 @@
#include <SDL3/SDL.h>
-typedef enum{
- SAFFRON_SIZE_FIXED,
- SAFFRON_SIZE_STRETCH,
- SAFFRON_SIZE_SCALE // scale but keep aspect ratio. this must be set on BOTH size modes (width AND height) to work
+typedef enum {
+ SAFFRON_SIZE_FIXED, // keep normal size
+ SAFFRON_SIZE_STRETCH, // stretch this axis to the maximum size
+ SAFFRON_SIZE_SCALE // scale but keep aspect ratio. this must be set on BOTH axes (width AND height) to work. if it's only set on one, then it will default back to fixed
} SaffronSizeMode;
+typedef enum {
+ SAFFRON_WIDGET_UNKNOWN,
+ SAFFRON_WIDGET_BOX,
+} SaffronWidgetType;
+
typedef struct SaffronWidget {
int x, y, w, h;
void (*draw)(struct SaffronWidget *self, SDL_Renderer *renderer);
@@ -18,7 +23,8 @@ typedef struct SaffronWidget {
int child_count;
SaffronSizeMode width_mode;
SaffronSizeMode height_mode;
- bool pixel_perfect; // Do we scale dynamically (SaffronSizeMode, etc) or use raw x, y, w, h values? If this is true, the SaffronSizeModes from earlier will be ignored
+ bool pixel_perfect; // Do we scale dynamically (SaffronSizeMode, etc) or use raw x, y, w, h values? If this is true, the SaffronSizeModes from earlier will be ignored. this pretty much tells the engine NOT to layout your widgets, don't expect it to allocate size for it. get better
+ SaffronWidgetType type;
} SaffronWidget;
#endif
diff --git a/meson.build b/meson.build
index 01f7716..c357bdd 100644
--- a/meson.build
+++ b/meson.build
@@ -16,11 +16,11 @@ sources = [
saffron_lib = static_library('saffron', sources, include_directories: inc, dependencies: deps)
test_deps = []
+
+# demonstrate how we can statically link SDL and saffron into an application easily
test_deps += dependency('sdl3', static: true)
test_deps += dependency('sdl3-ttf', static: true)
-
saffron_dep = declare_dependency(link_with: saffron_lib, include_directories: inc, dependencies: deps)
-
test_deps += saffron_dep
executable('saffron_test', 'tests/test_main.c', dependencies: test_deps)
diff --git a/src/saffron_layout.c b/src/saffron_layout.c
index c714bfa..62c7de2 100644
--- a/src/saffron_layout.c
+++ b/src/saffron_layout.c
@@ -1,5 +1,6 @@
#include "saffron_layout.h"
#include "saffron_api.h"
+#include "saffron_widget.h"
#include <SDL3/SDL_video.h>
#include <stdio.h>
#include <stdlib.h>
@@ -7,12 +8,14 @@
#include <SDL3_ttf/SDL_ttf.h>
#include <saffron.h>
-SaffronBox* saffron_box_new(SaffronOrientation orientation, SaffronHorizontalAlignment halign, SaffronVerticalAlignment valign, int spacing, int padding, int margin) {
+SaffronBox* saffron_box_new(SaffronOrientation orientation, SaffronHorizontalAlignment halign, SaffronVerticalAlignment valign, int spacing, int padding, int margin, int width, int height) {
SaffronBox* box = malloc(sizeof(SaffronBox));
if (!box) return NULL;
saffron_widget_init((SaffronWidget*)box);
+ ((SaffronWidget*)box)->type = SAFFRON_WIDGET_BOX;
+
box->orientation = orientation;
box->halign = halign;
box->valign = valign;
@@ -36,6 +39,28 @@ void saffron_box_layout(SaffronBox* box) {
int inner_w = content_w - (box->padding * 2);
int inner_h = content_h - (box->padding * 2);
- /* TODO actually make it layout */
+ int x_offset = inner_x;
+ int y_offset = inner_y;
+
+ /* TODO make it account for stretch and stuff */
+ for (int i = 0; i < ((SaffronWidget*)box)->child_count; i++) {
+ SaffronWidget* child = ((SaffronWidget*)box)->children[i];
+
+ if (child->pixel_perfect) continue;
+
+ if (box->orientation == SAFFRON_ORIENTATION_HORIZONTAL) {
+ child->x = x_offset;
+ child->y = y_offset;
+ x_offset += child->w + box->spacing;
+ } else {
+ child->x = x_offset;
+ child->y = y_offset;
+ y_offset += child->h + box->spacing;
+ }
+
+ if (child->type == SAFFRON_WIDGET_BOX) {
+ saffron_box_layout((SaffronBox*)child);
+ }
+ }
return;
}
diff --git a/src/saffron_widget.c b/src/saffron_widget.c
index 8612557..779253b 100644
--- a/src/saffron_widget.c
+++ b/src/saffron_widget.c
@@ -20,6 +20,8 @@ void saffron_widget_init(SaffronWidget* widget) {
widget->width_mode = SAFFRON_SIZE_FIXED;
widget->height_mode = SAFFRON_SIZE_FIXED;
widget->pixel_perfect = false;
+
+ widget->type = SAFFRON_WIDGET_UNKNOWN;
}
SaffronWidget* saffron_widget_new(void) {
diff --git a/src/saffron_window.c b/src/saffron_window.c
index 74742fa..5687f16 100644
--- a/src/saffron_window.c
+++ b/src/saffron_window.c
@@ -9,10 +9,10 @@
SaffronWindow* saffron_window_new(const char* title, int w, int h) {
SaffronWindow* window = malloc(sizeof(SaffronWindow));
- window->root = (SaffronWidget*)saffron_box_new(SAFFRON_ORIENTATION_VERTICAL, SAFFRON_HALIGN_CENTER, SAFFRON_VALIGN_CENTER, 10, 10, 0);
+ window->root = (SaffronWidget*)saffron_box_new(SAFFRON_ORIENTATION_VERTICAL, SAFFRON_HALIGN_CENTER, SAFFRON_VALIGN_CENTER, 10, 10, 0, w, h);
window->title = title;
- window->w = window->root->w = w;
- window->h = window->root->h = h;
+ window->w = w;
+ window->h = h;
Uint32 flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY;
window->sdl_window = SDL_CreateWindow(title, w, h, flags);
@@ -61,9 +61,13 @@ void saffron_window_main(SaffronWindow *window) {
if (!window) return;
bool running = true;
- printf("[Saffron] window running!\n");
+ printf("[Saffron] window starting!\n");
SDL_Event event;
+ printf("[Saffron] calculating layout on window->root\n");
+ saffron_box_layout((SaffronBox*)window->root);
+
+ printf("[Saffron] starting window mainloop\n");
while (running) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_EVENT_QUIT) {
diff --git a/tests/test_main.c b/tests/test_main.c
index 5bef6d5..c3ea050 100644
--- a/tests/test_main.c
+++ b/tests/test_main.c
@@ -1,3 +1,5 @@
+#include "saffron_api.h"
+#include "saffron_layout.h"
#include <stdio.h>
#include <saffron.h>
#include <SDL3/SDL.h>
@@ -26,28 +28,40 @@ void my_test_onclick(SaffronWidget* self) {
int main(void) {
saffron_init();
- SaffronWindow* window = saffron_window_new("saffron test", 800, 600);
+ SaffronWindow* window = saffron_window_new("Saffron Test", 800, 600);
+
+ /* replace the root with our own, because we want horizontal */
+ saffron_widget_free(window->root);
+ window->root = (SaffronWidget*)saffron_box_new(SAFFRON_ORIENTATION_HORIZONTAL, SAFFRON_HALIGN_LEFT, SAFFRON_VALIGN_TOP, 5, 5, 0, window->w, window->h);
/* i guess IM THE LUNATIC NOW
* DEAL WITH IT */
SaffronWidget* test = saffron_widget_new();
- test->x = 100;
- test->y = 100;
+ /* we don't need to set X and Y, the window will layout them automatically */
test->w = 200;
test->h = 150;
test->draw = my_test_draw;
test->on_click = my_test_onclick;
+ /* make a vertical box */
+ SaffronWidget* box = (SaffronWidget*)saffron_box_new(SAFFRON_ORIENTATION_VERTICAL, SAFFRON_HALIGN_LEFT, SAFFRON_VALIGN_TOP, 5, 0, 0, 200, 150);
+
/* lunatic method 2 */
SaffronWidget* test2 = saffron_widget_new();
- test2->x = 150;
- test2->y = 500;
- test2->w = 300;
- test2->h = 170;
+ test2->w = 200;
+ test2->h = 72;
test2->draw = my_test_draw;
+ /* lunatic method 3 */
+ SaffronWidget* test3 = saffron_widget_new();
+ test3->w = 200;
+ test3->h = 73;
+ test3->draw = my_test_draw;
+
saffron_widget_add_child(window->root, test);
- saffron_widget_add_child(window->root, test2);
+ saffron_widget_add_child(window->root, box);
+ saffron_widget_add_child(box, test2);
+ saffron_widget_add_child(box, test3);
saffron_window_main(window);