mirror of
https://github.com/pepaskopec-blip/Graduately.git
synced 2026-10-27 15:14:35 +00:00
fixed a bug with the second exercise in unit 1
This commit is contained in:
parent
2a447f4fd6
commit
f7cfd36b90
1 changed files with 215 additions and 53 deletions
266
sprechen.c
266
sprechen.c
|
|
@ -56,22 +56,23 @@ static const char *ex_names[NUM_EXERCISES + 1] = {
|
||||||
"Länder",
|
"Länder",
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Scattered bubble positions on the unit-1 map (centre of each bubble). */
|
/* Scattered bubble positions on the unit-1 map, as fractions of the
|
||||||
static const double ex_pos[NUM_EXERCISES + 1][2] = {
|
* available width/height so the map scales with the window. */
|
||||||
|
static const double scatter_pos[NUM_EXERCISES + 1][2] = {
|
||||||
{0.0, 0.0},
|
{0.0, 0.0},
|
||||||
{ 70.0, 100.0},
|
{0.100, 0.233},
|
||||||
{190.0, 45.0},
|
{0.271, 0.105},
|
||||||
{320.0, 90.0},
|
{0.457, 0.209},
|
||||||
{450.0, 40.0},
|
{0.643, 0.093},
|
||||||
{590.0, 95.0},
|
{0.843, 0.221},
|
||||||
{130.0, 210.0},
|
{0.186, 0.488},
|
||||||
{280.0, 185.0},
|
{0.400, 0.430},
|
||||||
{410.0, 215.0},
|
{0.586, 0.500},
|
||||||
{540.0, 190.0},
|
{0.771, 0.442},
|
||||||
{ 70.0, 320.0},
|
{0.100, 0.744},
|
||||||
{215.0, 330.0},
|
{0.307, 0.767},
|
||||||
{360.0, 325.0},
|
{0.514, 0.756},
|
||||||
{500.0, 335.0},
|
{0.714, 0.779},
|
||||||
};
|
};
|
||||||
|
|
||||||
static double path_x_at(double t) {
|
static double path_x_at(double t) {
|
||||||
|
|
@ -301,6 +302,8 @@ static GtkWidget *top_bar(const char *back_target, const char *title,
|
||||||
GtkWidget *sub = gtk_label_new(subtitle);
|
GtkWidget *sub = gtk_label_new(subtitle);
|
||||||
gtk_widget_set_halign(sub, GTK_ALIGN_CENTER);
|
gtk_widget_set_halign(sub, GTK_ALIGN_CENTER);
|
||||||
gtk_widget_add_css_class(sub, "roadmap-sub");
|
gtk_widget_add_css_class(sub, "roadmap-sub");
|
||||||
|
gtk_label_set_wrap(GTK_LABEL(sub), TRUE);
|
||||||
|
gtk_label_set_max_width_chars(GTK_LABEL(sub), 60);
|
||||||
gtk_box_append(GTK_BOX(center), sub);
|
gtk_box_append(GTK_BOX(center), sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -636,6 +639,77 @@ static GtkWidget *build_roadmap_page(void) {
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
/* Scatter layout (scales bubble positions with the window) */
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
#define SCATTER_MIN_W 600
|
||||||
|
#define SCATTER_MIN_H 380
|
||||||
|
#define SCATTER_NAT_W 760
|
||||||
|
#define SCATTER_NAT_H 440
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GtkWidget parent_instance;
|
||||||
|
GtkWidget *children[NUM_EXERCISES + 1];
|
||||||
|
} ScatterBox;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GtkWidgetClass parent_class;
|
||||||
|
} ScatterBoxClass;
|
||||||
|
|
||||||
|
G_DEFINE_TYPE(ScatterBox, scatter_box, GTK_TYPE_WIDGET)
|
||||||
|
|
||||||
|
#define SCATTER_BOX(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST((obj), scatter_box_get_type(), ScatterBox))
|
||||||
|
|
||||||
|
static void scatter_box_measure(GtkWidget *widget, GtkOrientation orientation,
|
||||||
|
int for_size, int *minimum, int *natural,
|
||||||
|
int *minimum_baseline, int *natural_baseline) {
|
||||||
|
(void)widget;
|
||||||
|
(void)for_size;
|
||||||
|
if (orientation == GTK_ORIENTATION_HORIZONTAL) {
|
||||||
|
*minimum = SCATTER_MIN_W;
|
||||||
|
*natural = SCATTER_NAT_W;
|
||||||
|
} else {
|
||||||
|
*minimum = SCATTER_MIN_H;
|
||||||
|
*natural = SCATTER_NAT_H;
|
||||||
|
}
|
||||||
|
*minimum_baseline = -1;
|
||||||
|
*natural_baseline = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scatter_box_size_allocate(GtkWidget *widget, int width, int height,
|
||||||
|
int baseline) {
|
||||||
|
ScatterBox *self = SCATTER_BOX(widget);
|
||||||
|
|
||||||
|
for (int i = 1; i <= NUM_EXERCISES; i++) {
|
||||||
|
GtkWidget *child = self->children[i];
|
||||||
|
GtkRequisition req;
|
||||||
|
GtkAllocation alloc;
|
||||||
|
|
||||||
|
if (!child)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
gtk_widget_get_preferred_size(child, &req, NULL);
|
||||||
|
alloc.x = (int)(scatter_pos[i][0] * width) - req.width / 2;
|
||||||
|
alloc.y = (int)(scatter_pos[i][1] * height) - 32;
|
||||||
|
alloc.width = req.width;
|
||||||
|
alloc.height = req.height;
|
||||||
|
gtk_widget_size_allocate(child, &alloc, baseline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scatter_box_init(ScatterBox *self) {
|
||||||
|
for (int i = 0; i <= NUM_EXERCISES; i++)
|
||||||
|
self->children[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scatter_box_class_init(ScatterBoxClass *klass) {
|
||||||
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
|
||||||
|
widget_class->measure = scatter_box_measure;
|
||||||
|
widget_class->size_allocate = scatter_box_size_allocate;
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
/* Unit 1 bubble map (scattered) */
|
/* Unit 1 bubble map (scattered) */
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
@ -698,8 +772,7 @@ static GtkWidget *make_bubble(int n) {
|
||||||
|
|
||||||
static GtkWidget *build_unit1_page(void) {
|
static GtkWidget *build_unit1_page(void) {
|
||||||
GtkWidget *page;
|
GtkWidget *page;
|
||||||
GtkWidget *scroll;
|
GtkWidget *scatter;
|
||||||
GtkWidget *fixed;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
page = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
page = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||||
|
|
@ -712,23 +785,15 @@ static GtkWidget *build_unit1_page(void) {
|
||||||
top_bar("roadmap", "Neue Freunde",
|
top_bar("roadmap", "Neue Freunde",
|
||||||
"Vyberte cvičení a dokončete je."));
|
"Vyberte cvičení a dokončete je."));
|
||||||
|
|
||||||
scroll = gtk_scrolled_window_new();
|
scatter = g_object_new(scatter_box_get_type(), NULL);
|
||||||
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
|
gtk_widget_set_hexpand(scatter, TRUE);
|
||||||
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
gtk_widget_set_vexpand(scatter, TRUE);
|
||||||
gtk_widget_set_vexpand(scroll, TRUE);
|
gtk_box_append(GTK_BOX(page), scatter);
|
||||||
gtk_widget_set_margin_top(scroll, 14);
|
|
||||||
gtk_box_append(GTK_BOX(page), scroll);
|
|
||||||
|
|
||||||
fixed = gtk_fixed_new();
|
|
||||||
gtk_widget_set_halign(fixed, GTK_ALIGN_CENTER);
|
|
||||||
gtk_widget_set_size_request(fixed, 700, 430);
|
|
||||||
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(scroll), fixed);
|
|
||||||
|
|
||||||
for (i = 1; i <= NUM_EXERCISES; i++) {
|
for (i = 1; i <= NUM_EXERCISES; i++) {
|
||||||
GtkWidget *cell = make_bubble(i);
|
GtkWidget *cell = make_bubble(i);
|
||||||
gtk_fixed_put(GTK_FIXED(fixed), cell,
|
SCATTER_BOX(scatter)->children[i] = cell;
|
||||||
(int)(ex_pos[i][0] - 60.0),
|
gtk_widget_set_parent(cell, scatter);
|
||||||
(int)(ex_pos[i][1] - 32.0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return page;
|
return page;
|
||||||
|
|
@ -758,7 +823,7 @@ static GtkWidget *ex_page_shell(const char *title, const char *subtitle,
|
||||||
|
|
||||||
scroll = gtk_scrolled_window_new();
|
scroll = gtk_scrolled_window_new();
|
||||||
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
|
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
|
||||||
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
|
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
||||||
gtk_widget_set_vexpand(scroll, TRUE);
|
gtk_widget_set_vexpand(scroll, TRUE);
|
||||||
gtk_widget_set_margin_top(scroll, 14);
|
gtk_widget_set_margin_top(scroll, 14);
|
||||||
gtk_widget_set_margin_bottom(scroll, 14);
|
gtk_widget_set_margin_bottom(scroll, 14);
|
||||||
|
|
@ -829,6 +894,24 @@ static GtkWidget *make_word_combo(const char **words, int n) {
|
||||||
return combo;
|
return combo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean answer_accepts(const char *sel_norm, const char *ans) {
|
||||||
|
gchar **parts = g_strsplit(ans, "|", -1);
|
||||||
|
gboolean ok = FALSE;
|
||||||
|
|
||||||
|
for (int i = 0; parts[i] != NULL; i++) {
|
||||||
|
gchar *a = normalize_answer(parts[i]);
|
||||||
|
if (g_strcmp0(sel_norm, a) == 0) {
|
||||||
|
ok = TRUE;
|
||||||
|
g_free(a);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
g_free(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_strfreev(parts);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
static void combo_list_check(GtkButton *button, gpointer data) {
|
static void combo_list_check(GtkButton *button, gpointer data) {
|
||||||
ComboListCtx *ctx = data;
|
ComboListCtx *ctx = data;
|
||||||
guint total = ctx->combos->len;
|
guint total = ctx->combos->len;
|
||||||
|
|
@ -844,10 +927,8 @@ static void combo_list_check(GtkButton *button, gpointer data) {
|
||||||
|
|
||||||
if (sel) {
|
if (sel) {
|
||||||
gchar *t = normalize_answer(sel);
|
gchar *t = normalize_answer(sel);
|
||||||
gchar *a = normalize_answer(ans);
|
good = answer_accepts(t, ans);
|
||||||
good = (g_strcmp0(t, a) == 0);
|
|
||||||
g_free(t);
|
g_free(t);
|
||||||
g_free(a);
|
|
||||||
g_free(sel);
|
g_free(sel);
|
||||||
}
|
}
|
||||||
answer_mark(GTK_WIDGET(combo), good);
|
answer_mark(GTK_WIDGET(combo), good);
|
||||||
|
|
@ -883,12 +964,13 @@ typedef struct {
|
||||||
int n_words;
|
int n_words;
|
||||||
} SentBuilder;
|
} SentBuilder;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SentBuilder *sb;
|
|
||||||
int idx;
|
|
||||||
} ChipRef;
|
|
||||||
|
|
||||||
static void sent_rebuild(SentBuilder *sb) {
|
static void sent_rebuild(SentBuilder *sb) {
|
||||||
|
for (int i = 0; i < sb->n_words; i++) {
|
||||||
|
GtkWidget *parent = gtk_widget_get_parent(sb->chips[i]);
|
||||||
|
if (parent != NULL && GTK_IS_FLOW_BOX_CHILD(parent))
|
||||||
|
gtk_flow_box_child_set_child(GTK_FLOW_BOX_CHILD(parent), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
flow_clear(GTK_FLOW_BOX(sb->pool));
|
flow_clear(GTK_FLOW_BOX(sb->pool));
|
||||||
flow_clear(GTK_FLOW_BOX(sb->target));
|
flow_clear(GTK_FLOW_BOX(sb->target));
|
||||||
|
|
||||||
|
|
@ -909,30 +991,91 @@ static void sent_rebuild(SentBuilder *sb) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_chip_clicked(GtkButton *button, gpointer data) {
|
typedef struct {
|
||||||
|
SentBuilder *sb;
|
||||||
|
int idx;
|
||||||
|
} ChipRef;
|
||||||
|
|
||||||
|
static GdkContentProvider *asm_drag_prepare(GtkDragSource *source,
|
||||||
|
double x, double y,
|
||||||
|
gpointer data) {
|
||||||
ChipRef *ref = data;
|
ChipRef *ref = data;
|
||||||
SentBuilder *sb = ref->sb;
|
(void)source;
|
||||||
int idx = ref->idx;
|
(void)x;
|
||||||
|
(void)y;
|
||||||
|
return gdk_content_provider_new_typed(G_TYPE_INT, ref->idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean asm_rebuild_idle(gpointer data) {
|
||||||
|
sent_rebuild(data);
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void asm_drag_end(GtkDragSource *source, GdkDrag *drag,
|
||||||
|
gboolean delete_data, gpointer data) {
|
||||||
|
ChipRef *ref = data;
|
||||||
|
(void)source;
|
||||||
|
(void)drag;
|
||||||
|
(void)delete_data;
|
||||||
|
g_idle_add(asm_rebuild_idle, ref->sb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean asm_drop_to_sentence(GtkDropTarget *target, const GValue *value,
|
||||||
|
double x, double y, gpointer data) {
|
||||||
|
SentBuilder *sb = data;
|
||||||
|
int idx;
|
||||||
int pos = -1;
|
int pos = -1;
|
||||||
|
|
||||||
(void)button;
|
(void)target;
|
||||||
|
(void)x;
|
||||||
|
(void)y;
|
||||||
|
|
||||||
|
if (!G_VALUE_HOLDS_INT(value))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
idx = g_value_get_int(value);
|
||||||
for (int i = 0; i < sb->placed_count; i++) {
|
for (int i = 0; i < sb->placed_count; i++) {
|
||||||
if (sb->placed[i] == idx) {
|
if (sb->placed[i] == idx) {
|
||||||
pos = i;
|
pos = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pos >= 0) {
|
if (pos >= 0) {
|
||||||
for (int i = pos; i < sb->placed_count - 1; i++)
|
for (int i = pos; i < sb->placed_count - 1; i++)
|
||||||
sb->placed[i] = sb->placed[i + 1];
|
sb->placed[i] = sb->placed[i + 1];
|
||||||
sb->placed_count--;
|
sb->placed_count--;
|
||||||
} else {
|
}
|
||||||
sb->placed[sb->placed_count++] = idx;
|
sb->placed[sb->placed_count++] = idx;
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
sent_rebuild(sb);
|
static gboolean asm_drop_to_pool(GtkDropTarget *target, const GValue *value,
|
||||||
|
double x, double y, gpointer data) {
|
||||||
|
SentBuilder *sb = data;
|
||||||
|
int idx;
|
||||||
|
int pos = -1;
|
||||||
|
|
||||||
|
(void)target;
|
||||||
|
(void)x;
|
||||||
|
(void)y;
|
||||||
|
|
||||||
|
if (!G_VALUE_HOLDS_INT(value))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
idx = g_value_get_int(value);
|
||||||
|
for (int i = 0; i < sb->placed_count; i++) {
|
||||||
|
if (sb->placed[i] == idx) {
|
||||||
|
pos = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pos < 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
for (int i = pos; i < sb->placed_count - 1; i++)
|
||||||
|
sb->placed[i] = sb->placed[i + 1];
|
||||||
|
sb->placed_count--;
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
@ -1024,15 +1167,28 @@ static GtkWidget *build_assembly(const char *title, const char *subtitle,
|
||||||
sb->pool = pool;
|
sb->pool = pool;
|
||||||
gtk_box_append(GTK_BOX(group), pool);
|
gtk_box_append(GTK_BOX(group), pool);
|
||||||
|
|
||||||
|
{
|
||||||
|
GtkDropTarget *dt = gtk_drop_target_new(G_TYPE_INT, GDK_ACTION_COPY);
|
||||||
|
GtkDropTarget *dp = gtk_drop_target_new(G_TYPE_INT, GDK_ACTION_COPY);
|
||||||
|
g_signal_connect(dt, "drop", G_CALLBACK(asm_drop_to_sentence), sb);
|
||||||
|
gtk_widget_add_controller(target, GTK_EVENT_CONTROLLER(dt));
|
||||||
|
g_signal_connect(dp, "drop", G_CALLBACK(asm_drop_to_pool), sb);
|
||||||
|
gtk_widget_add_controller(pool, GTK_EVENT_CONTROLLER(dp));
|
||||||
|
}
|
||||||
|
|
||||||
for (int w = 0; w < item->n; w++) {
|
for (int w = 0; w < item->n; w++) {
|
||||||
GtkWidget *chip = gtk_button_new_with_label(item->words[w]);
|
GtkWidget *chip = gtk_button_new_with_label(item->words[w]);
|
||||||
|
GtkDragSource *src = gtk_drag_source_new();
|
||||||
ChipRef *ref = g_new(ChipRef, 1);
|
ChipRef *ref = g_new(ChipRef, 1);
|
||||||
gtk_widget_add_css_class(chip, "chip");
|
gtk_widget_add_css_class(chip, "chip");
|
||||||
g_object_ref(chip);
|
g_object_ref(chip);
|
||||||
sb->chips[w] = chip;
|
sb->chips[w] = chip;
|
||||||
ref->sb = sb;
|
ref->sb = sb;
|
||||||
ref->idx = w;
|
ref->idx = w;
|
||||||
g_signal_connect(chip, "clicked", G_CALLBACK(asm_chip_clicked), ref);
|
gtk_drag_source_set_actions(src, GDK_ACTION_COPY);
|
||||||
|
g_signal_connect(src, "prepare", G_CALLBACK(asm_drag_prepare), ref);
|
||||||
|
g_signal_connect(src, "drag-end", G_CALLBACK(asm_drag_end), ref);
|
||||||
|
gtk_widget_add_controller(chip, GTK_EVENT_CONTROLLER(src));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
@ -1069,8 +1225,8 @@ typedef struct {
|
||||||
} Dialogue;
|
} Dialogue;
|
||||||
|
|
||||||
static const DialogRow ex1_d1[] = {
|
static const DialogRow ex1_d1[] = {
|
||||||
{"A:", "Hallo! Ich ", "bin", " Anna."},
|
{"A:", "Hallo! Ich ", "bin|heiße", " Anna."},
|
||||||
{"B:", "Hallo! Ich ", "heiße", " Peter."},
|
{"B:", "Hallo! Ich ", "bin|heiße", " Peter."},
|
||||||
{"A:", "Woher ", "kommst", " du?"},
|
{"A:", "Woher ", "kommst", " du?"},
|
||||||
{"B:", "Ich komme ", "aus", " Tschechien."},
|
{"B:", "Ich komme ", "aus", " Tschechien."},
|
||||||
};
|
};
|
||||||
|
|
@ -1721,6 +1877,12 @@ typedef struct {
|
||||||
} AssignChipRef;
|
} AssignChipRef;
|
||||||
|
|
||||||
static void assign_rebuild(AssignCtx *ac) {
|
static void assign_rebuild(AssignCtx *ac) {
|
||||||
|
for (int i = 0; i < ac->n_items; i++) {
|
||||||
|
GtkWidget *parent = gtk_widget_get_parent(ac->chips[i]);
|
||||||
|
if (parent != NULL && GTK_IS_FLOW_BOX_CHILD(parent))
|
||||||
|
gtk_flow_box_child_set_child(GTK_FLOW_BOX_CHILD(parent), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
flow_clear(GTK_FLOW_BOX(ac->pool));
|
flow_clear(GTK_FLOW_BOX(ac->pool));
|
||||||
for (int g = 0; g < ac->n_groups; g++)
|
for (int g = 0; g < ac->n_groups; g++)
|
||||||
flow_clear(GTK_FLOW_BOX(ac->group_flow[g]));
|
flow_clear(GTK_FLOW_BOX(ac->group_flow[g]));
|
||||||
|
|
@ -1928,7 +2090,7 @@ static void activate(GtkApplication *app, gpointer user_data) {
|
||||||
|
|
||||||
ex_pages[1] = build_ex1();
|
ex_pages[1] = build_ex1();
|
||||||
ex_pages[2] = build_assembly("Sätze bilden",
|
ex_pages[2] = build_assembly("Sätze bilden",
|
||||||
"Seřaďte slova do správného pořadí.",
|
"Přetáhněte slova do správného pořadí.",
|
||||||
2, ex2_items, G_N_ELEMENTS(ex2_items));
|
2, ex2_items, G_N_ELEMENTS(ex2_items));
|
||||||
ex_pages[3] = build_choice("Was ist richtig?", "Vyberte správnou číslovku.",
|
ex_pages[3] = build_choice("Was ist richtig?", "Vyberte správnou číslovku.",
|
||||||
3, ex3_questions, G_N_ELEMENTS(ex3_questions));
|
3, ex3_questions, G_N_ELEMENTS(ex3_questions));
|
||||||
|
|
@ -1940,7 +2102,7 @@ static void activate(GtkApplication *app, gpointer user_data) {
|
||||||
ex_pages[9] = build_choice("Wer? Wie? Wo?", "Vyberte správné tázací slovo.",
|
ex_pages[9] = build_choice("Wer? Wie? Wo?", "Vyberte správné tázací slovo.",
|
||||||
9, ex9_questions, G_N_ELEMENTS(ex9_questions));
|
9, ex9_questions, G_N_ELEMENTS(ex9_questions));
|
||||||
ex_pages[10] = build_assembly("Wörter trennen",
|
ex_pages[10] = build_assembly("Wörter trennen",
|
||||||
"Poskládejte slova do správného pořadí.",
|
"Přetáhněte slova do správného pořadí.",
|
||||||
10, ex10_items, G_N_ELEMENTS(ex10_items));
|
10, ex10_items, G_N_ELEMENTS(ex10_items));
|
||||||
ex_pages[11] = build_assign("Grußformen", "Roztřiďte pozdravy na pozdravy a rozloučení.",
|
ex_pages[11] = build_assign("Grußformen", "Roztřiďte pozdravy na pozdravy a rozloučení.",
|
||||||
11, ex11_items, G_N_ELEMENTS(ex11_items),
|
11, ex11_items, G_N_ELEMENTS(ex11_items),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue