From cccb0b704f9508e65630ddad5056f944a05d23ab Mon Sep 17 00:00:00 2001 From: "yu.dongliang" <18588496441@163.com> Date: Fri, 13 Jun 2025 00:12:32 +0800 Subject: [PATCH] support 'open', 'save', 'save as', 'quit' of 'file' menu --- ses_ui.c | 385 +++++++++++++++++++++++++++++++++++++++++---------- ses_ui.glade | 2 +- ses_ui.h | 3 + 3 files changed, 314 insertions(+), 76 deletions(-) diff --git a/ses_ui.c b/ses_ui.c index 54b3bc4..fa8ae6a 100644 --- a/ses_ui.c +++ b/ses_ui.c @@ -209,46 +209,22 @@ static void ui_print_logs(ses_ui_t* ui) } } -static void ui_add_log(ses_ui_t* ui, ui_log_t* log) +static void ui_free_log(ui_log_t* log, int unused) { - scf_list_t* l; - - scf_list_add_front(ui->current, &log->list); - ui->current = &log->list; - - fprintf(stderr, "\n-----\n"); - for (l = scf_list_next(ui->current); l != scf_list_sentinel(&ui->log); ) { - log = scf_list_data(l, ui_log_t, list); - l = scf_list_next(l); - - if (UI_ADD_LINE == log->type && !log->l->el) { - scf_list_del(&log->list); - - scf_logw("free: add line %p, (%d,%d)-->(%d,%d)\n", log->l, log->l->x0, log->l->y0, log->l->x1, log->l->y1); - - ScfLine_free(log->l); - free(log); - log = NULL; - } - } - - for (l = scf_list_next(ui->current); l != scf_list_sentinel(&ui->log); ) { - log = scf_list_data(l, ui_log_t, list); - l = scf_list_next(l); - - scf_list_del(&log->list); - + if (log) { switch (log->type) { case UI_ADD_COMPONENT: scf_logw("free: add %p, c%ld\n", log->c, log->c->id); - ScfEcomponent_free(log->c); + if (unused) + ScfEcomponent_free(log->c); break; case UI_ADD_ELINE: scf_logw("free: add %p, el%ld\n", log->el, log->el->id); - ScfEline_free(log->el); + if (unused) + ScfEline_free(log->el); break; case UI_MOV_COMPONENT: @@ -279,8 +255,69 @@ static void ui_add_log(ses_ui_t* ui, ui_log_t* log) }; free(log); + } +} + +static void ui_free_unused_logs(ses_ui_t* ui) +{ + scf_list_t* l; + ui_log_t* log; + + for (l = scf_list_next(ui->current); l != scf_list_sentinel(&ui->log); ) { + log = scf_list_data(l, ui_log_t, list); + l = scf_list_next(l); + + if (UI_ADD_LINE == log->type && !log->l->el) { + scf_list_del(&log->list); + + scf_logw("free: add line %p, (%d,%d)-->(%d,%d)\n", log->l, log->l->x0, log->l->y0, log->l->x1, log->l->y1); + + ScfLine_free(log->l); + free(log); + log = NULL; + } + } + + for (l = scf_list_next(ui->current); l != scf_list_sentinel(&ui->log); ) { + log = scf_list_data(l, ui_log_t, list); + l = scf_list_next(l); + + scf_list_del(&log->list); + + ui_free_log(log, 1); log = NULL; } +} + +static void ui_free_logs(ses_ui_t* ui) +{ + scf_list_t* l; + ui_log_t* log; + + ui_free_unused_logs(ui); + + for (l = scf_list_head(&ui->log); l != scf_list_sentinel(&ui->log); ) { + log = scf_list_data(l, ui_log_t, list); + l = scf_list_next(l); + + scf_list_del(&log->list); + + ui_free_log(log, 0); + log = NULL; + } + + ui->current = &ui->log; +} + +static void ui_add_log(ses_ui_t* ui, ui_log_t* log) +{ + scf_list_t* l; + + scf_list_add_front(ui->current, &log->list); + ui->current = &log->list; + + fprintf(stderr, "\n-----\n"); + ui_free_unused_logs(ui); if (scf_list_sentinel(&ui->log) == scf_list_next(ui->current)) gtk_widget_set_sensitive(ui->redo, FALSE); @@ -861,6 +898,8 @@ static gboolean button_press_event(GtkWidget* self, GdkEventButton* event, gpoin scf_logi("x: %f, y: %f\n", event->x, event->y); + gtk_window_set_focus(ui->window, GTK_WIDGET(ui->gl_area)); + if (ui->f) { ui->c = NULL; ui->p = NULL; @@ -889,8 +928,8 @@ static gboolean button_press_event(GtkWidget* self, GdkEventButton* event, gpoin if (ui->p) fprintf(stderr, "p%ld", ui->p->id); } + fprintf(stderr, "\n"); } - fprintf(stderr, "\n"); } return TRUE; @@ -905,47 +944,52 @@ static gboolean button_release_event(GtkWidget* self, GdkEventButton* event, gpo ui->status = SES_UI_EDIT; scf_logw("x: %f, y: %f\n", event->x, event->y); + if (ui->f) { + if (ui->c && !ui->p) { + int dx = ui->c->x - ui->cx; + int dy = ui->c->y - ui->cy; + + if (dx * dx + dy * dy > 25) { + log = calloc(1, sizeof(ui_log_t)); + if (!log) { + gtk_gl_area_queue_render(ui->gl_area); + return TRUE; + } - if (ui->c && !ui->p) { - int dx = ui->c->x - ui->cx; - int dy = ui->c->y - ui->cy; + log->c = ui->c; + log->old_x = ui->cx; + log->old_y = ui->cy; + log->new_x = ui->c->x; + log->new_y = ui->c->y; + log->type = UI_MOV_COMPONENT; - if (dx * dx + dy * dy > 25) { - log = calloc(1, sizeof(ui_log_t)); - if (!log) { - gtk_gl_area_queue_render(ui->gl_area); - return TRUE; + ui_add_log(ui, log); } - log->c = ui->c; - log->old_x = ui->cx; - log->old_y = ui->cy; - log->new_x = ui->c->x; - log->new_y = ui->c->y; - log->type = UI_MOV_COMPONENT; + button_connect_pins(ui); + } else { + int dx = event->x - ui->press_x; + int dy = event->y - ui->press_y; - ui_add_log(ui, log); + if (dx * dx + dy * dy > 25) + button_line_to(ui, ui->press_x, ui->press_y, event->x, event->y); } - button_connect_pins(ui); - } else { - button_line_to(ui, ui->press_x, ui->press_y, event->x, event->y); - } - - if (!scf_list_empty(&ui->log)) { - log = scf_list_data(scf_list_tail(&ui->log), ui_log_t, list); - log->ok_flag = 1; - } + if (!scf_list_empty(&ui->log)) { + log = scf_list_data(scf_list_tail(&ui->log), ui_log_t, list); + log->ok_flag = 1; + } - ui->c = NULL; - ui->p = NULL; - ui->cx = 0; - ui->cy = 0; + ui->c = NULL; + ui->p = NULL; + ui->cx = 0; + ui->cy = 0; - ui->press_x = 0; - ui->press_y = 0; - ui->move_x = 0; - ui->move_y = 0; + ui->press_x = 0; + ui->press_y = 0; + ui->move_x = 0; + ui->move_y = 0; + } } return TRUE; @@ -996,17 +1040,19 @@ static gboolean button_move_event(GtkWidget* self, GdkEventMotion* event, gpoint return TRUE; } -static void apply_clicked(GtkButton* self, gpointer user_data) +static int ui_save_file(ses_ui_t* ui) { - ses_ui_t* ui = user_data; + if (!ui->f || !ui->save_path) + return -EINVAL; ScfEboard* b = scf_eboard__alloc(); if (!b) - return; + return -ENOMEM; - if (scf_eboard__add_function(b, ui->f) < 0) { + long ret = scf_eboard__add_function(b, ui->f); + if (ret < 0) { ScfEboard_free(b); - return; + return ret; } ui->f->x = 0; @@ -1016,18 +1062,19 @@ static void apply_clicked(GtkButton* self, gpointer user_data) uint8_t* buf = NULL; long len = 0; - long ret = ScfEboard_pack(b, &buf, &len); + + ret = ScfEboard_pack(b, &buf, &len); assert(0 == scf_eboard__del_function(b, ui->f)); ScfEboard_free(b); b = NULL; if (ret < 0) - return; + return ret; - FILE* fp = fopen("./tmp.cpk", "wb"); + FILE* fp = fopen(ui->save_path, "wb"); if (!fp) - return; + return -1; fwrite(buf, len, 1, fp); fclose(fp); @@ -1035,11 +1082,21 @@ static void apply_clicked(GtkButton* self, gpointer user_data) free(buf); buf = NULL; + return 0; +} + +static void apply_clicked(GtkButton* self, gpointer user_data) +{ + ses_ui_t* ui = user_data; + + int ret = ui_save_file(ui); + if (ret < 0) + return; float ns = atof(gtk_entry_get_text(ui->entry_ns)); int count = atoi(gtk_entry_get_text(ui->entry_count)); - printf("./ses ./tmp.cpk -l 0 -t %fns -c %d\n", ns, count); + printf("./ses %s -l 0 -t %fns -c %d\n", ui->save_path, ns, count); fflush(stdout); gtk_widget_set_sensitive(ui->back, FALSE); @@ -1051,6 +1108,164 @@ static void apply_clicked(GtkButton* self, gpointer user_data) ui->status = SES_UI_RUN; } +static int load_file(ses_ui_t* ui, const char* cpk) +{ + ScfEfunction* f = NULL; + ScfEboard* b = NULL; + + uint8_t* buf = NULL; + + long len = scf_pack_read(&buf, cpk); + if (len < 0) { + scf_loge("scf_pack_read '%s' error: %ld\n", cpk, len); + return len; + } + + long ret = ScfEboard_unpack(&b, buf, len); + free(buf); + buf = NULL; + + if (ret < 0) { + scf_loge("ScfEboard__unpack error: %ld\n", ret); + ScfEboard_free(b); + return ret; + } + + if (b->n_functions <= 0) { + scf_loge("NO electronic function found in '%s'\n", cpk); + ScfEboard_free(b); + return -EINVAL; + } + + f = b->functions[0]; + assert(0 == scf_eboard__del_function(b, f)); + ScfEboard_free(b); + b = NULL; + + char* path = ui->save_path; + + ui->save_path = strdup(cpk); + if (ui->save_path) { + free(path); + path = NULL; + } else { + ui->save_path = path; + ScfEfunction_free(f); + return -ENOMEM; + } + + ui_free_logs(ui); + gtk_widget_set_sensitive(ui->undo, FALSE); + gtk_widget_set_sensitive(ui->redo, FALSE); + + if (ui->f) + ScfEfunction_free(ui->f); + + ui->f = f; + if (f->w > 0 && f->h > 0) { + ui->width = f->w; + ui->height = f->h; + } + + ui->c = NULL; + ui->p = NULL; + ui->cx = 0; + ui->cy = 0; + + ui->press_us = 0; + ui->press_x = 0; + ui->press_y = 0; + ui->move_x = 0; + ui->move_y = 0; + return 0; +} + +static void open_activate(GtkMenuItem* self, gpointer user_data) +{ + scf_logi("\n"); + + ses_ui_t* ui = user_data; + GtkWidget* dialog; + gint res; + + dialog = gtk_file_chooser_dialog_new("Open File", + ui->window, + GTK_FILE_CHOOSER_ACTION_OPEN, + "_Cancel", + GTK_RESPONSE_CANCEL, + "_Open", + GTK_RESPONSE_ACCEPT, + NULL); + + res = gtk_dialog_run(GTK_DIALOG(dialog)); + if (res == GTK_RESPONSE_ACCEPT) { + GtkFileChooser* chooser = GTK_FILE_CHOOSER(dialog); + + char* file = gtk_file_chooser_get_filename(chooser); + + int ret = load_file(ui, file); + if (ret < 0) + scf_loge("load '%s' failed\n", file); + + g_free(file); + } + + gtk_widget_destroy(dialog); +} + +static void save_activate(GtkMenuItem* self, gpointer user_data) +{ + ses_ui_t* ui = user_data; + + scf_logi("\n"); + + ui_save_file(ui); +} + +static void save_as_activate(GtkMenuItem* self, gpointer user_data) +{ + ses_ui_t* ui = user_data; + + scf_logi("\n"); + + GtkWidget* dialog; + GtkFileChooser* chooser; + + dialog = gtk_file_chooser_dialog_new("Save File", + ui->window, + GTK_FILE_CHOOSER_ACTION_SAVE, + "_Cancel", + GTK_RESPONSE_CANCEL, + "_Save", + GTK_RESPONSE_ACCEPT, + NULL); + + chooser = GTK_FILE_CHOOSER(dialog); + + gtk_file_chooser_set_do_overwrite_confirmation(chooser, TRUE); + gtk_file_chooser_set_filename(chooser, ui->save_path); + + gint res = gtk_dialog_run(GTK_DIALOG(dialog)); + if (res == GTK_RESPONSE_ACCEPT) + { + char* file = gtk_file_chooser_get_filename(chooser); + char* path = ui->save_path; + + ui->save_path = strdup(file); + if (ui->save_path) { + free(path); + path = NULL; + } else + ui->save_path = path; + + ui_save_file(ui); + + g_free(file); + } + + gtk_widget_destroy(dialog); +} + static gboolean key_press_event(GtkWidget* self, GdkEventKey* event, gpointer user_data) { ses_ui_t* ui = user_data; @@ -1061,6 +1276,10 @@ static gboolean key_press_event(GtkWidget* self, GdkEventKey* event, gpointer us case GDK_KEY_BackSpace: case GDK_KEY_Delete: break; + + case 's': + save_activate(NULL, user_data); + break; default: break; }; @@ -1417,7 +1636,13 @@ int main(int argc, char* argv[]) if (gtk_builder_add_from_file(builder, "ses_ui.glade", &error) == 0) { g_printerr("Error loading file: %s\n", error->message); g_clear_error(&error); - return 1; + return -1; + } + + ui.save_path = strdup("./tmp.cpk"); + if (!ui.save_path) { + scf_loge("no memory for 'default save path'\n"); + goto exit; } window = gtk_builder_get_object(builder, "main_window"); @@ -1444,6 +1669,16 @@ int main(int argc, char* argv[]) g_signal_connect(window, "button-release-event", G_CALLBACK(button_release_event), &ui); g_signal_connect(window, "motion-notify-event", G_CALLBACK(button_move_event), &ui); + GObject* open = gtk_builder_get_object(builder, "file_open"); + GObject* save = gtk_builder_get_object(builder, "file_save"); + GObject* save_as = gtk_builder_get_object(builder, "file_save_as"); + GObject* quit = gtk_builder_get_object(builder, "file_quit"); + + g_signal_connect(open, "activate", G_CALLBACK(open_activate), &ui); + g_signal_connect(save, "activate", G_CALLBACK(save_activate), &ui); + g_signal_connect(save_as, "activate", G_CALLBACK(save_as_activate), &ui); + g_signal_connect(quit, "activate", G_CALLBACK(gtk_main_quit), NULL); + GObject* back = gtk_builder_get_object(builder, "button_back"); GObject* forward = gtk_builder_get_object(builder, "button_forward"); GObject* undo = gtk_builder_get_object(builder, "button_undo"); @@ -1486,7 +1721,7 @@ int main(int argc, char* argv[]) gtk_widget_show_all(GTK_WIDGET(window)); gtk_main(); - +exit: printf("q\n"); fflush(stdout); diff --git a/ses_ui.glade b/ses_ui.glade index a5374bb..33ee01d 100644 --- a/ses_ui.glade +++ b/ses_ui.glade @@ -565,7 +565,7 @@ True True - False + True False diff --git a/ses_ui.h b/ses_ui.h index 827d449..1bddc66 100644 --- a/ses_ui.h +++ b/ses_ui.h @@ -70,6 +70,8 @@ struct ses_ui_s cairo_t* cr; uint8_t* bgra; + uint8_t* save_path; + ScfEfunction* f; ScfEcomponent* c; ScfEpin* p; @@ -103,6 +105,7 @@ struct ses_ui_s NULL,NULL, \ NULL,NULL, \ NULL,NULL,NULL, \ + NULL, \ NULL,NULL,NULL,0,0, \ 0,0,0,0,0, 0,0, 0,0,0,0, -1,-1, 0} -- 2.25.1