payredu

[WIP] Cross-platform ledger GUI written in c99

commit 87a2d134c0a6b6f1f3972b324c5726092ae04f01
parent 2d1f499256f33813f93bf99c2a4c85a93e8ccdf9
Author: Bharatvaj Hemanth <bharatvaj@yahoo.com>
Date: Sat, 21 Oct 2023 15:28:09 +0530

Basic UI added

In the midst querying the ledger .txt file
8 files changed, 167 insertions(+), 110 deletions(-)
M
.gitignore
|
1
+
M
Makefile
|
18
++++++++++++------
M
balance.c
|
130
+++++++++++++++++++++++++-------------------------------------------------------
A
common.h
|
5
+++++
D
hot-reload.c
|
6
------
M
hot.c
|
77
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
A
ledger.h
|
33
+++++++++++++++++++++++++++++++++
A
october-2023.txt
|
7
+++++++
diff --git a/.gitignore b/.gitignore
@@ -2,3 +2,4 @@ balance
 hot
 *.so
 *.o
+tags
diff --git a/Makefile b/Makefile
@@ -1,9 +1,11 @@
 GENERAL_FLAGS=-fPIC
-LDFLAGS=$(GENERAL_FLAGS) -lglfw -lGL -lm -lGLEW
-CFLAGS=$(GENERAL_FLAGS) -I. -g -Werror #-Wpedantic
+LDFLAGS=$(GENERAL_FLAGS) -lglfw -lGL -lm
+CFLAGS=$(GENERAL_FLAGS) -O0 -I. -g -Werror #-Wpedantic
 
 .DEFAULT_GOAL=hot
 
+CC=tcc
+
 %: %.c
 	$(CC) -o $@ $(CFLAGS) $(LDFLAGS) $<
 

@@ -13,11 +15,15 @@ CFLAGS=$(GENERAL_FLAGS) -I. -g -Werror #-Wpedantic
 lib%.so: %.o
 	$(CC) -shared -Wl,-soname,$@ -o $@ $<
 
-balance: balance.c
+balance: balance.c ledger.h
+
+hot: hot.c libbalance.so
 
-libhot-reload.so: hot-reload.c
+refresh:
+	git ls-files | entr make libbalance.so
 
-hot: hot.c libhot-reload.so libbalance.so
+autorefresh:
+	ls libbalance.so | entr kill -3 $$(pgrep hot)
 
 clean:
-	-rm $(cat .gitignore)
+	-rm $$(cat .gitignore)
diff --git a/balance.c b/balance.c
@@ -1,6 +1,8 @@
 #include <stdio.h>
 #include <stddef.h>
 #include <stdlib.h>
+#include <time.h>
+#include "common.h"
 
 #include <GLFW/glfw3.h>
 #define NK_INCLUDE_FIXED_TYPES

@@ -16,105 +18,53 @@
 #include <nuklear.h>
 #include <nuklear_glfw_gl2.h>
 
-#define MAX_MEMORY 4064
-#define WINDOW_WIDTH 512
-#define WINDOW_HEIGHT 512
+#include "ledger.h"
 
 float your_text_width_calculation(nk_handle handle, float height, const char *text, int len) {
 	return 10.0f;
 }
 
-static void error_callback(int e, const char *d)
-{printf("Error %d: %s\n", e, d);}
 
-void* module_main(void* data) {
-	int width,height;
-	struct nk_context* ctx;
-	struct nk_colorf bg;
-	glfwSetErrorCallback(error_callback);
-    if (!glfwInit()) {
-        fprintf(stdout, "[GFLW] failed to init!\n");
-        exit(1);
-    }
-	/***********************/
-    GLFWwindow* win = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Balance", NULL, NULL);
-    glfwMakeContextCurrent(win);
-    glfwGetWindowSize(win, &width, &height);
+void edit_entry(int i) {
+	printf("ledger_edit_entry(%d)\n", i);
+}
 
-    /* GUI */
-    ctx = nk_glfw3_init(win, NK_GLFW3_INSTALL_CALLBACKS);
-	/***********************/
-	//nk_init_fixed(ctx, calloc(1, MAX_MEMORY), MAX_MEMORY, &font);
-	{struct nk_font_atlas *atlas;
-    nk_glfw3_font_stash_begin(&atlas);
-    struct nk_font *droid = nk_font_atlas_add_from_file(atlas, "./Ubuntu-Medium.ttf", 14, 0);
-    nk_glfw3_font_stash_end();
-	nk_style_set_font(ctx, &droid->handle);
-	}
-    bg.r = 0.10f, bg.g = 0.18f, bg.b = 1.00f, bg.a = 1.0f;
-    while (!glfwWindowShouldClose(win))
-    {
-		glfwPollEvents();
-		nk_glfw3_new_frame();
-		//struct nk_context* ctx = (struct nk_context*)_ctx;
-		/* Input */
-		if (nk_begin(ctx, "balance", nk_rect(0, 0, width, height),
-					NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE)) {
-			nk_layout_space_begin(ctx, NK_DYNAMIC, height, 3);
-			// fixed widget pixel width
-			//nk_layout_row_static(ctx, 30, 80, 1);
-			nk_layout_space_push(ctx, nk_rect(0,0,width, height*0.1));
-			if (nk_button_label(ctx, "Refresh")) {
-				// event handling
-				goto end;
-				//printf("ledger_add_entry\n");
+void* module_main(struct nk_context* ctx, int width, int height) {
+	// main render loop
+	// handle file loading
+	// handle rendering clicks etc
+	Entry** new_list = ledger_read_file("october-2023.txt", time(NULL), time(NULL));
+	if (nk_begin(ctx, "balance", nk_rect(0, 0, width, height), 0)) {
+		float size[] = {0.10, 0.70, 0.30};
+		nk_layout_row(ctx, NK_DYNAMIC, 0, 3, size);
+		nk_layout_row_begin(ctx, NK_STATIC, 25, 1);
+		nk_layout_row_push(ctx, 40);
+		nk_label(ctx, "500", NK_TEXT_LEFT);
+		nk_layout_row_end(ctx);
+
+		int len = 12;
+		for(int i = 0; i < len; i++) {
+			nk_layout_row_begin(ctx, NK_DYNAMIC, 0, 2);
+			nk_layout_row_push(ctx, 0.7f);
+			char* name = (char*)malloc(sizeof(char) * 50);
+			sprintf(name, "%s: %d", new_list[i]->to->name, 500);
+			if(nk_button_label(ctx, name)) {
+				printf("%s\n", name);
+				edit_entry(i);
 			}
+			nk_layout_row_push(ctx, 0.3f);
 			nk_label(ctx, "500", NK_TEXT_LEFT);
-			static const char *list[12] = {
-				"Salary Deposited - Stonks +",
-				"New Stonks",
-				"New Stonks",
-				"New Stonks",
-				"New Stonks",
-				"New Stonks",
-				"New Stonks",
-				"New Stonks",
-				"New Stonks",
-				"New Stonks",
-				"New Stonks",
-				"New Stonks",
-			};
-			nk_layout_space_push(ctx, nk_rect(0,0,width, height*0.7));
-			nk_layout_row_dynamic(ctx, 40, 12);
-			for(int i = 0; i < 12; i++) {
-				nk_layout_row_begin(ctx, NK_DYNAMIC, 0, 2);
-				nk_layout_row_push(ctx, 50);
-				nk_label(ctx, list[i], NK_TEXT_CENTERED);
-				nk_layout_row_push(ctx, 50);
-				nk_label(ctx, "500", NK_TEXT_CENTERED);
-				nk_layout_row_end(ctx);
-			}
-			nk_layout_space_push(ctx, nk_rect(0,0,width, height*0.2));
-			if (nk_button_label(ctx, " + Add Entry")) {
-				// event handling
-				printf("ledger_add_entry\n");
-			}
-			nk_layout_space_end(ctx);
+			nk_layout_row_end(ctx);
+		}
+
+		nk_layout_row_begin(ctx, NK_STATIC, 25, 1);
+		nk_layout_row_push(ctx, 100);
+		if (nk_button_label(ctx, " + Add Entry")) {
+			// event handling
+			printf("ledger_add_entry\n");
 		}
-		nk_end(ctx);
-		glfwGetWindowSize(win, &width, &height);
-		glViewport(0, 0, width, height);
-		glClear(GL_COLOR_BUFFER_BIT);
-		glClearColor(bg.r, bg.g, bg.b, bg.a);
-		/* IMPORTANT: `nk_glfw_render` modifies some global OpenGL state
-		 * with blending, scissor, face culling and depth test and defaults everything
-		 * back into a default state. Make sure to either save and restore or
-		 * reset your own state after drawing rendering the UI. */
-		nk_glfw3_render(NK_ANTI_ALIASING_ON);
-		glfwSwapBuffers(win);
+		nk_layout_row_end(ctx);
 	}
-	nk_glfw3_shutdown();
-	glfwTerminate();
-end:
-	printf("End\n");
+	nk_end(ctx);
+	return NULL;
 }
diff --git a/common.h b/common.h
@@ -0,0 +1,5 @@
+#ifndef __COMMON_H
+#define __COMMON_H
+
+
+#endif
diff --git a/hot-reload.c b/hot-reload.c
@@ -1,6 +0,0 @@
-#include <stdio.h>
-
-void* module_main(void* data) {
-	printf("this is\n");
-	return 0;
-}
diff --git a/hot.c b/hot.c
@@ -1,21 +1,67 @@
 #include <stdio.h>
 #include <stdlib.h>
-#include <signal.h>
 #include <dlfcn.h>
+#include <signal.h>
 
-typedef void* module_main_func(void* data);
+#include <GLFW/glfw3.h>
+#define NK_INCLUDE_FIXED_TYPES
+#define NK_INCLUDE_STANDARD_IO
+#define NK_INCLUDE_STANDARD_VARARGS
+#define NK_INCLUDE_DEFAULT_ALLOCATOR
+#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
+#define NK_INCLUDE_FONT_BAKING
+#define NK_INCLUDE_DEFAULT_FONT
+#define NK_IMPLEMENTATION
+#define NK_GLFW_GL2_IMPLEMENTATION
+#define NK_KEYSTATE_BASED_INPUT
+#include <nuklear.h>
+#include <nuklear_glfw_gl2.h>
+#include "common.h"
 
-int should_exit = 0;
+#define MAX_MEMORY 4064
+#define WINDOW_WIDTH 512
+#define WINDOW_HEIGHT 512
 
+void* state = NULL;
+int should_exit = 0;
+// init gui state
+int width,height;
+struct nk_context* ctx;
+GLFWwindow* win;
 
 void sig_handle() {
+	printf("Reloaded\n");
+	system("date");
 	should_exit = 1;
 }
 
+typedef void* (*module_main_func)(void*, int, int);
+
+static void error_callback(int e, const char *d)
+{printf("Error %d: %s\n", e, d);}
+
 int main(int argc, char* argv[]) {
-	void* state = NULL;
-	// init gui state
-	//signal(SIGINT, sig_handle);
+	signal(SIGQUIT, sig_handle);
+	glfwSetErrorCallback(error_callback);
+	if (!glfwInit()) {
+		fprintf(stdout, "[GFLW] failed to init!\n");
+		exit(1);
+	}
+	/***********************/
+	win = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Balance", NULL, NULL);
+	glfwMakeContextCurrent(win);
+	glfwGetWindowSize(win, &width, &height);
+
+	/* GUI */
+	ctx = nk_glfw3_init(win, NK_GLFW3_INSTALL_CALLBACKS);
+	/***********************/
+	//nk_init_fixed(ctx, calloc(1, MAX_MEMORY), MAX_MEMORY, &font);
+	{struct nk_font_atlas *atlas;
+		nk_glfw3_font_stash_begin(&atlas);
+		struct nk_font *droid = nk_font_atlas_add_from_file(atlas, "./Ubuntu-Medium.ttf", 14, 0);
+		nk_glfw3_font_stash_end();
+		nk_style_set_font(ctx, &droid->handle);
+	}
 	while(1) {
 		void* module = dlopen("./libbalance.so", RTLD_NOW);
 		while(module == NULL){

@@ -24,9 +70,24 @@ int main(int argc, char* argv[]) {
 			getchar();
 			module = dlopen("./libbalance.so", RTLD_NOW);
 		}
-		module_main_func* module_main = (module_main_func*)dlsym(module, "module_main");
-		state = module_main(state);
+		module_main_func module_main = dlsym(module, "module_main");
+		while (!glfwWindowShouldClose(win) && !should_exit) {
+			glfwPollEvents();
+			nk_glfw3_new_frame();
+			state = module_main((void*)ctx, width, height);
+			glfwGetWindowSize(win, &width, &height);
+			glViewport(0, 0, width, height);
+			glClearColor(0.10f, 0.18f, 1.0f, 1.0f);
+			glClear(GL_COLOR_BUFFER_BIT);
+			/* IMPORTANT: `nk_glfw_render` modifies some global OpenGL state
+			 * with blending, scissor, face culling and depth test and defaults everything
+			 * back into a default state. Make sure to either save and restore or
+			 * reset your own state after drawing rendering the UI. */
+			nk_glfw3_render(NK_ANTI_ALIASING_ON);
+			glfwSwapBuffers(win);
+		}
 		dlclose(module);
+		should_exit = 0;
 	}
 
 	return 0;
diff --git a/ledger.h b/ledger.h
@@ -0,0 +1,33 @@
+#include <string.h>
+#include <stdlib.h>
+
+typedef struct {
+	char* name;
+} Entity;
+
+typedef struct {
+	Entity* from;
+	Entity* to;
+	long long amt;
+} Entry;
+
+Entity me = {"Account:Income"};
+
+Entry** ledger_read_file(const char* filename, time_t date_start, time_t date_end) {
+	// list population, read from
+	FILE* file = fopen(filename, "r");
+	if (file == NULL) {
+		printf("Failed to open file %s\n", filename);
+	}
+	Entry** new_list = (Entry**)malloc(sizeof(Entry*) * 12);
+	for(int i = 0; i < 12; i++) {
+		Entry* entry = (Entry*)malloc(sizeof(Entry));
+		new_list[i] = entry;
+		entry->from = &me;
+		entry->to = (Entity*)malloc(sizeof(Entity));
+		entry->to->name = (char*)malloc(sizeof(char*) * 20);
+		strcpy(entry->to->name, "Woman");
+	}
+	return new_list;
+}
+
diff --git a/october-2023.txt b/october-2023.txt
@@ -0,0 +1,7 @@
+2015/10/12 Exxon
+    Expenses:Auto:Gas
+    Liabilities:MasterCard   $-10.00
+
+2015/10/12 Exide
+    Expenses:Auto:Gas
+    Assets:Credit  $-5.00