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 @@
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