mirror of
https://github.com/pepaskopec-blip/Graduately.git
synced 2026-10-27 15:14:35 +00:00
281 lines
8.7 KiB
C
281 lines
8.7 KiB
C
#include "maturita.h"
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* Subjects page — icon grid, one tile per subject */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
/* Index 0 (Deutsch), NET_SUBJ (networks), HW_SUBJ (hardware) and CZ_SUBJ
|
|
* (Czech) are unlocked. */
|
|
const char *sub_keys[NUM_SUBJECTS] = {
|
|
"Deutsch",
|
|
"Správa počítačových sítí",
|
|
"Technické vybavení",
|
|
"Český jazyk a literatura",
|
|
"Občanská nauka",
|
|
"English",
|
|
"Matematika",
|
|
"Fyzika",
|
|
"Základy Přírodopisných věd",
|
|
"Technická grafika",
|
|
"Prezentační grafika",
|
|
"Programování",
|
|
"Programové vybavení",
|
|
};
|
|
|
|
/* Slice of the global `units[]` table that each subject owns. A start of -1
|
|
* (or a count of 0) means the subject has no content yet; such subjects show
|
|
* as locked on the statistics page until their units are added. */
|
|
const int sub_unit_start[NUM_SUBJECTS] = {
|
|
0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
};
|
|
const int sub_unit_count[NUM_SUBJECTS] = {
|
|
NUM_UNITS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
};
|
|
|
|
GtkWidget *sub_scroll;
|
|
GtkWidget *sub_fixed;
|
|
GtkWidget *sub_rail;
|
|
GtkWidget *sub_cells[NUM_SUBJECTS];
|
|
GtkWidget *sub_labels[NUM_SUBJECTS];
|
|
double sub_cx[NUM_SUBJECTS];
|
|
double sub_cy[NUM_SUBJECTS];
|
|
int sub_rows = 1;
|
|
int sub_cols = NUM_SUBJECTS;
|
|
int sub_cw;
|
|
int sub_ch;
|
|
guint sub_idle;
|
|
|
|
void sub_layout_geometry(double avail) {
|
|
(void)avail;
|
|
}
|
|
|
|
void draw_sub_rail(GtkDrawingArea *area, cairo_t *cr,
|
|
int width, int height, gpointer user_data) {
|
|
(void)area;
|
|
(void)cr;
|
|
(void)width;
|
|
(void)height;
|
|
(void)user_data;
|
|
}
|
|
|
|
void sub_apply_layout(void) {
|
|
}
|
|
|
|
void sub_relayout(void) {
|
|
}
|
|
|
|
gboolean sub_relayout_idle(gpointer data) {
|
|
(void)data;
|
|
sub_idle = 0;
|
|
return G_SOURCE_REMOVE;
|
|
}
|
|
|
|
void sub_relayout_later(void) {
|
|
}
|
|
|
|
/* German flag (black / red / gold) drawn in a clipped circle. */
|
|
void draw_german_flag(GtkDrawingArea *area, cairo_t *cr,
|
|
int width, int height, gpointer data) {
|
|
double cx = width / 2.0;
|
|
double cy = height / 2.0;
|
|
double r = MIN(width, height) / 2.0 - 2.0;
|
|
double band = (double)height / 3.0;
|
|
|
|
(void)area;
|
|
(void)data;
|
|
|
|
cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
|
|
cairo_paint(cr);
|
|
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
|
|
|
|
cairo_save(cr);
|
|
cairo_new_path(cr);
|
|
cairo_arc(cr, cx, cy, r, 0.0, 2.0 * G_PI);
|
|
cairo_clip(cr);
|
|
|
|
cairo_new_path(cr);
|
|
cairo_rectangle(cr, 0.0, 0.0, (double)width, band);
|
|
cairo_set_source_rgb(cr, 0.18, 0.18, 0.19);
|
|
cairo_fill(cr);
|
|
|
|
cairo_new_path(cr);
|
|
cairo_rectangle(cr, 0.0, band, (double)width, band);
|
|
cairo_set_source_rgb(cr, 0.72, 0.27, 0.24);
|
|
cairo_fill(cr);
|
|
|
|
cairo_new_path(cr);
|
|
cairo_rectangle(cr, 0.0, 2.0 * band, (double)width, band);
|
|
cairo_set_source_rgb(cr, 0.84, 0.70, 0.32);
|
|
cairo_fill(cr);
|
|
|
|
cairo_restore(cr);
|
|
}
|
|
|
|
/* Czech flag (white / red with a blue triangle) drawn in a clipped circle. */
|
|
void draw_czech_flag(GtkDrawingArea *area, cairo_t *cr,
|
|
int width, int height, gpointer data) {
|
|
double cx = width / 2.0;
|
|
double cy = height / 2.0;
|
|
double r = MIN(width, height) / 2.0 - 2.0;
|
|
|
|
(void)area;
|
|
(void)data;
|
|
|
|
cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
|
|
cairo_paint(cr);
|
|
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
|
|
|
|
cairo_save(cr);
|
|
cairo_new_path(cr);
|
|
cairo_arc(cr, cx, cy, r, 0.0, 2.0 * G_PI);
|
|
cairo_clip(cr);
|
|
|
|
cairo_new_path(cr);
|
|
cairo_rectangle(cr, 0.0, 0.0, (double)width, (double)height);
|
|
cairo_set_source_rgb(cr, 0.98, 0.98, 0.98);
|
|
cairo_fill(cr);
|
|
|
|
cairo_new_path(cr);
|
|
cairo_rectangle(cr, 0.0, (double)height / 2.0,
|
|
(double)width, (double)height / 2.0);
|
|
cairo_set_source_rgb(cr, 0.83, 0.16, 0.18);
|
|
cairo_fill(cr);
|
|
|
|
cairo_new_path(cr);
|
|
cairo_move_to(cr, 0.0, 0.0);
|
|
cairo_line_to(cr, (double)width * 0.55, (double)height / 2.0);
|
|
cairo_line_to(cr, 0.0, (double)height);
|
|
cairo_close_path(cr);
|
|
cairo_set_source_rgb(cr, 0.07, 0.24, 0.55);
|
|
cairo_fill(cr);
|
|
|
|
cairo_restore(cr);
|
|
}
|
|
|
|
static gboolean subject_is_open(int i) {
|
|
return i == 0 || i == NET_SUBJ || i == HW_SUBJ || i == CZ_SUBJ;
|
|
}
|
|
|
|
static GtkWidget *subject_icon(int i) {
|
|
GtkWidget *area = gtk_drawing_area_new();
|
|
|
|
gtk_widget_set_size_request(area, 48, 48);
|
|
gtk_widget_set_halign(area, GTK_ALIGN_CENTER);
|
|
if (i == 0)
|
|
gtk_drawing_area_set_draw_func(GTK_DRAWING_AREA(area),
|
|
draw_german_flag, NULL, NULL);
|
|
else if (i == NET_SUBJ)
|
|
gtk_drawing_area_set_draw_func(GTK_DRAWING_AREA(area),
|
|
draw_wifi_icon, NULL, NULL);
|
|
else if (i == HW_SUBJ)
|
|
gtk_drawing_area_set_draw_func(GTK_DRAWING_AREA(area),
|
|
draw_chip_icon, NULL, NULL);
|
|
else if (i == CZ_SUBJ)
|
|
gtk_drawing_area_set_draw_func(GTK_DRAWING_AREA(area),
|
|
draw_czech_flag, NULL, NULL);
|
|
else
|
|
return icon_area_new(draw_lock_icon, 0.3451, 0.3569, 0.4392, 22);
|
|
return area;
|
|
}
|
|
|
|
static const char *subject_target(int i) {
|
|
if (i == 0)
|
|
return "roadmap";
|
|
if (i == NET_SUBJ)
|
|
return "netyears";
|
|
if (i == HW_SUBJ)
|
|
return "hwmap";
|
|
if (i == CZ_SUBJ)
|
|
return "czechmap";
|
|
return NULL;
|
|
}
|
|
|
|
GtkWidget *build_subjects_page(void) {
|
|
GtkWidget *page;
|
|
GtkWidget *scroll;
|
|
GtkWidget *grid;
|
|
int i;
|
|
|
|
page = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
|
gtk_widget_add_css_class(page, "subjects-page");
|
|
gtk_widget_set_hexpand(page, TRUE);
|
|
gtk_widget_set_vexpand(page, TRUE);
|
|
gtk_widget_set_margin_start(page, 40);
|
|
gtk_widget_set_margin_end(page, 40);
|
|
gtk_widget_set_margin_top(page, 16);
|
|
gtk_widget_set_margin_bottom(page, 28);
|
|
|
|
gtk_box_append(GTK_BOX(page),
|
|
top_bar("welcome", "subjects_title", "subjects_sub"));
|
|
|
|
scroll = gtk_scrolled_window_new();
|
|
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
|
|
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
|
|
gtk_widget_set_vexpand(scroll, TRUE);
|
|
gtk_widget_set_margin_top(scroll, 8);
|
|
gtk_box_append(GTK_BOX(page), scroll);
|
|
sub_scroll = scroll;
|
|
|
|
grid = gtk_flow_box_new();
|
|
gtk_flow_box_set_max_children_per_line(GTK_FLOW_BOX(grid), 5);
|
|
gtk_flow_box_set_min_children_per_line(GTK_FLOW_BOX(grid), 3);
|
|
gtk_flow_box_set_selection_mode(GTK_FLOW_BOX(grid), GTK_SELECTION_NONE);
|
|
gtk_flow_box_set_homogeneous(GTK_FLOW_BOX(grid), TRUE);
|
|
gtk_flow_box_set_column_spacing(GTK_FLOW_BOX(grid), 14);
|
|
gtk_flow_box_set_row_spacing(GTK_FLOW_BOX(grid), 14);
|
|
gtk_widget_set_halign(grid, GTK_ALIGN_CENTER);
|
|
gtk_widget_set_hexpand(grid, TRUE);
|
|
gtk_widget_add_css_class(grid, "subject-grid");
|
|
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(scroll), grid);
|
|
sub_fixed = grid;
|
|
|
|
for (i = 0; i < NUM_SUBJECTS; i++) {
|
|
GtkWidget *card;
|
|
GtkWidget *inner;
|
|
GtkWidget *icon;
|
|
GtkWidget *lbl;
|
|
const char *target;
|
|
gboolean open = subject_is_open(i);
|
|
|
|
card = gtk_button_new();
|
|
gtk_widget_add_css_class(card, "subject-tile");
|
|
gtk_widget_set_can_focus(card, open);
|
|
gtk_widget_set_hexpand(card, TRUE);
|
|
gtk_widget_set_size_request(card, 180, 132);
|
|
|
|
inner = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10);
|
|
gtk_widget_set_halign(inner, GTK_ALIGN_CENTER);
|
|
gtk_widget_set_valign(inner, GTK_ALIGN_CENTER);
|
|
gtk_button_set_child(GTK_BUTTON(card), inner);
|
|
|
|
icon = subject_icon(i);
|
|
gtk_box_append(GTK_BOX(inner), icon);
|
|
|
|
lbl = gtk_label_new(NULL);
|
|
i18n_bind(lbl, sub_keys[i], 0);
|
|
gtk_widget_set_halign(lbl, GTK_ALIGN_CENTER);
|
|
gtk_label_set_justify(GTK_LABEL(lbl), GTK_JUSTIFY_CENTER);
|
|
gtk_label_set_wrap(GTK_LABEL(lbl), TRUE);
|
|
gtk_label_set_max_width_chars(GTK_LABEL(lbl), 16);
|
|
gtk_widget_add_css_class(lbl, "subject-name");
|
|
gtk_box_append(GTK_BOX(inner), lbl);
|
|
|
|
if (open) {
|
|
gtk_widget_add_css_class(card, "open");
|
|
target = subject_target(i);
|
|
g_object_set_data_full(G_OBJECT(card), "target",
|
|
g_strdup(target), g_free);
|
|
g_signal_connect(card, "clicked", G_CALLBACK(on_nav_clicked), NULL);
|
|
} else {
|
|
gtk_widget_add_css_class(card, "locked");
|
|
gtk_widget_add_css_class(lbl, "unit-name-locked");
|
|
gtk_widget_set_sensitive(card, FALSE);
|
|
}
|
|
|
|
sub_cells[i] = card;
|
|
sub_labels[i] = lbl;
|
|
gtk_flow_box_insert(GTK_FLOW_BOX(grid), card, -1);
|
|
}
|
|
|
|
return page;
|
|
}
|