From 508be38c3f667c54b49360cc8e8388133f7d1137 Mon Sep 17 00:00:00 2001 From: dvorakmortonxd Date: Thu, 3 Sep 2026 11:50:05 +0200 Subject: [PATCH] First commit, introduction message added --- CLAUDE.md | 76 +++++++++++++++++++++++++++++ error.log | 0 sprechen | Bin 0 -> 36104 bytes sprechen.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 216 insertions(+) create mode 100644 CLAUDE.md create mode 100644 error.log create mode 100755 sprechen create mode 100644 sprechen.c diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..5cd8c8e --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,76 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Development Commands + +- **Build**: Compile the GTK application using the Makefile: + ```sh + make + ``` + Or manually with gcc: + ```sh + gcc -o sprechen sprechen.c `pkg-config --cflags --libs gtk4` + ``` + +- **Run**: Execute the built binary: + ```sh + make run + ``` + or + ```sh + ./sprechen + ``` + +- **Clean**: Remove compiled binaries: + ```sh + make clean + ``` + or + ```sh + rm -f sprechen + ``` + +- **Format**: If using clang-format, run: + ```sh + clang-format -i *.c *.h + ``` + +- **Lint**: Use `clang-tidy` or `cppcheck` for static analysis: + ```sh + clang-tidy sprechen.c -- `pkg-config --cflags gtk4` + ``` + or + ```sh + cppcheck --enable=all sprechen.c + ``` + +- **Test**: Currently no test framework is integrated. To add unit tests, consider using a lightweight framework like `check` or `cmocka`. Tests can be compiled and run similarly. + +## Project Structure + +- **Root**: Contains the CLAUDE.md, README.md, .gitignore, LICENSE, Makefile, and source files. +- **Source**: The main application resides in a single C file (`sprechen.c`) that uses GTK 4 for the graphical interface. +- **Build Artifacts**: Compiled binaries are placed in the project root by default; consider using a `build/` directory for out-of-source builds. +- **Dependencies**: Requires GTK 4 development libraries. On macOS, install via Homebrew: `brew install gtk4`. On Linux, use your package manager (e.g., `sudo apt install libgtk-4-dev`). + +## Architecture Overview + +The application is a simple GUI program written in C using GTK 4. It features: +- A main window with a title "Sprechen.c". +- A vertical box layout containing a centered label with welcome text. +- Custom CSS styling for a gradient background and styled label box. +- The text size scales dynamically with the window width to ensure readability on different screen sizes. +- The GTK application lifecycle is managed via `GtkApplication`, with activation callback setting up the UI. + +Future extensions may include: +- Additional widgets for language lessons (buttons, text entry, progress bars). +- Separation of UI code into multiple files (e.g., `ui.c`, `ui.h`). +- Lesson data structures and loading from external files (JSON or plain text). +- Internationalization support using gettext. + +## Notes + +- Ensure GTK 4 is installed and accessible via pkg-config. +- The code adheres to GTK 4 conventions and uses CSS for styling. +- When modifying the UI, consider keeping the CSS in a separate file for maintainability, though currently it is embedded for simplicity. diff --git a/error.log b/error.log new file mode 100644 index 0000000..e69de29 diff --git a/sprechen b/sprechen new file mode 100755 index 0000000000000000000000000000000000000000..d8bcafcaecacdccd945e3684e02789709b3d4855 GIT binary patch literal 36104 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 literal 0 HcmV?d00001 diff --git a/sprechen.c b/sprechen.c new file mode 100644 index 0000000..cbb037d --- /dev/null +++ b/sprechen.c @@ -0,0 +1,140 @@ +#include +#include +#include + +typedef struct { + GtkWidget *label; + GtkCssProvider *provider; +} ScaleData; + +static void +on_window_notify (GObject *object, + GParamSpec *pspec, + gpointer user_data) +{ + // We get the ScaleData from the window + ScaleData *scale_data = g_object_get_data(G_OBJECT(object), "scale-data"); + if (!scale_data || !scale_data->label || !scale_data->provider) + return; + + GtkWidget *window = GTK_WIDGET(object); + int width; + g_object_get(window, "width", &width, NULL); + + // Calculate font size in points based on width + // Base: 600px width -> 18 points + double points_per_pixel = 18.0 / 600.0; + double font_size_points = width * points_per_pixel; + // Clamp between 10 and 24 points + if (font_size_points < 10.0) font_size_points = 10.0; + if (font_size_points > 24.0) font_size_points = 24.0; + + // Update the CSS provider with the new font size + char *css_data = g_strdup_printf( + "window {" + " background-color: #2E3440;" + " background-image: linear-gradient(135deg, #2E3440 0%%, #3B4252 100%%);" + " color: #ECEFF4;" + " font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;" + "}" + "label {" + " margin: 30px;" + " padding: 30px;" + " background-color: rgba(59, 66, 82, 0.8);" + " border-radius: 16px;" + " box-shadow: 0 8px 16px rgba(0,0,0,0.4);" + " font-size: %dpt;" + "}", + (int)font_size_points); + + gtk_css_provider_load_from_string(scale_data->provider, css_data); + g_free(css_data); +} + +static void activate(GtkApplication *app, gpointer user_data) { + GtkWidget *window; + GtkWidget *box; + GtkWidget *label; + GtkCssProvider *provider; + ScaleData *scale_data; + + // Create a new application window + window = gtk_application_window_new(app); + gtk_window_set_title(GTK_WINDOW(window), "Sprechen.c"); + gtk_window_set_default_size(GTK_WINDOW(window), 600, 400); + + // Create a vertical box to hold contents + box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 20); + gtk_widget_set_halign(box, GTK_ALIGN_CENTER); + gtk_widget_set_valign(box, GTK_ALIGN_CENTER); + gtk_window_set_child(GTK_WINDOW(window), box); + + // Create a label with welcome message + label = gtk_label_new("Vítejte ve Sprechen.C!\n\nSprechen.C je vzdělávací program na procvičování Němčiny, určený pro studenty středních škol a gymnázií. Program je napsaný v Céčku studentama ze SSŠVT!"); + gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER); + gtk_label_set_lines(label, -1); // Allow multiple lines + gtk_label_set_xalign(label, 0.5); // Center horizontally + gtk_label_set_yalign(label, 0.5); // Center vertically + gtk_label_set_wrap(label, TRUE); // Enable line wrapping + gtk_label_set_max_width_chars(label, 40); + gtk_box_append(GTK_BOX(box), label); + + // Create and load CSS for beautiful background with initial font size + provider = gtk_css_provider_new(); + int initial_width = 600; // default width + double points_per_pixel = 18.0 / 600.0; + double initial_font_size_points = initial_width * points_per_pixel; + if (initial_font_size_points < 10.0) initial_font_size_points = 10.0; + if (initial_font_size_points > 24.0) initial_font_size_points = 24.0; + char *initial_css = g_strdup_printf( + "window {" + " background-color: #2E3440;" + " background-image: linear-gradient(135deg, #2E3440 0%%, #3B4252 100%%);" + " color: #ECEFF4;" + " font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;" + "}" + "label {" + " margin: 30px;" + " padding: 30px;" + " background-color: rgba(59, 66, 82, 0.8);" + " border-radius: 16px;" + " box-shadow: 0 8px 16px rgba(0,0,0,0.4);" + " font-size: %dpt;" + "}", + (int)initial_font_size_points); + gtk_css_provider_load_from_string(provider, initial_css); + g_free(initial_css); + + // Apply CSS to the window + gtk_style_context_add_provider_for_display( + gdk_display_get_default(), + GTK_STYLE_PROVIDER(provider), + GTK_STYLE_PROVIDER_PRIORITY_USER); + + // We keep the provider to update it later, so we don't unreference it yet + // g_object_unref(provider); // We will unreference it in the cleanup? We'll store it in ScaleData and unreference when the window is destroyed. + + // Set up scaling data + scale_data = g_new(ScaleData, 1); + scale_data->label = label; + scale_data->provider = provider; + g_object_set_data_full(G_OBJECT(window), "scale-data", scale_data, g_free); + + // Connect to the window's notify::width and notify::height signals + g_signal_connect(window, "notify::width", G_CALLBACK(on_window_notify), NULL); + g_signal_connect(window, "notify::height", G_CALLBACK(on_window_notify), NULL); + + gtk_window_present(window); +} + +int main(int argc, char **argv) { + GtkApplication *app; + int status; + + app = gtk_application_new("org.example.Sprechen", G_APPLICATION_DEFAULT_FLAGS); + g_signal_connect(app, "activate", G_CALLBACK(activate), NULL); + status = g_application_run(G_APPLICATION(app), argc, argv); + g_object_unref(app); + + return status; +} \ No newline at end of file