From 6ebea9612c496ee0800e56779373f830cc37f761 Mon Sep 17 00:00:00 2001 From: "yu.dongliang" <18588496441@163.com> Date: Tue, 10 Jun 2025 23:48:19 +0800 Subject: [PATCH] UI: support buttons of 'undo', 'redo', 'back', 'forward' --- scf_eda_pack.h | 35 +-- scf_list.h | 102 ++++++++ ses_ui.c | 693 ++++++++++++++++++++++++++++++++++++++++++++----- ses_ui.glade | 22 +- ses_ui.h | 53 +++- udiv.cpk | Bin 1080 -> 0 bytes 6 files changed, 821 insertions(+), 84 deletions(-) create mode 100644 scf_list.h delete mode 100644 udiv.cpk diff --git a/scf_eda_pack.h b/scf_eda_pack.h index eb0866b..1d1f871 100644 --- a/scf_eda_pack.h +++ b/scf_eda_pack.h @@ -297,20 +297,6 @@ typedef struct { char* va_curve; } ScfEdata; -typedef struct { - SCF_PACK_DEF_VAR(int, x0); - SCF_PACK_DEF_VAR(int, y0); - SCF_PACK_DEF_VAR(int, x1); - SCF_PACK_DEF_VAR(int, y1); -} ScfLine; - -SCF_PACK_TYPE(ScfLine) -SCF_PACK_INFO_VAR(ScfLine, x0), -SCF_PACK_INFO_VAR(ScfLine, y0), -SCF_PACK_INFO_VAR(ScfLine, x1), -SCF_PACK_INFO_VAR(ScfLine, y1), -SCF_PACK_END(ScfLine) - typedef struct { SCF_PACK_DEF_VAR(double, Vb); SCF_PACK_DEF_VAR(double, Ib); @@ -325,6 +311,7 @@ SCF_PACK_END(ScfEcurve) typedef struct scf_eops_s ScfEops; typedef struct scf_epin_s ScfEpin; +typedef struct scf_eline_s ScfEline; typedef struct scf_ecomponent_s ScfEcomponent; typedef struct scf_efunction_s ScfEfunction; typedef struct scf_eboard_s ScfEboard; @@ -336,6 +323,21 @@ struct scf_eops_s int (*shared)(ScfEpin* p, int flags); }; +typedef struct { + SCF_PACK_DEF_VAR(int, x0); + SCF_PACK_DEF_VAR(int, y0); + SCF_PACK_DEF_VAR(int, x1); + SCF_PACK_DEF_VAR(int, y1); + SCF_PACK_DEF_OBJ(ScfEline, el); +} ScfLine; + +SCF_PACK_TYPE(ScfLine) +SCF_PACK_INFO_VAR(ScfLine, x0), +SCF_PACK_INFO_VAR(ScfLine, y0), +SCF_PACK_INFO_VAR(ScfLine, x1), +SCF_PACK_INFO_VAR(ScfLine, y1), +SCF_PACK_END(ScfLine) + struct scf_epin_s { SCF_PACK_DEF_VAR(uint64_t, id); @@ -420,7 +422,8 @@ SCF_PACK_INFO_VAR(ScfEconn, lid), SCF_PACK_INFO_VARS(ScfEconn, cids, uint64_t), SCF_PACK_END(ScfEconn) -typedef struct { +struct scf_eline_s +{ SCF_PACK_DEF_VAR(uint64_t, id); SCF_PACK_DEF_VARS(uint64_t, pins); SCF_PACK_DEF_VAR(uint64_t, c_pins); @@ -440,7 +443,7 @@ typedef struct { SCF_PACK_DEF_VAR(uint8_t, aconst); SCF_PACK_DEF_VAR(uint8_t, vflag); SCF_PACK_DEF_VAR(uint8_t, open_flag); -} ScfEline; +}; SCF_PACK_TYPE(ScfEline) SCF_PACK_INFO_VAR(ScfEline, id), diff --git a/scf_list.h b/scf_list.h new file mode 100644 index 0000000..e08644f --- /dev/null +++ b/scf_list.h @@ -0,0 +1,102 @@ +#ifndef SCF_LIST_H +#define SCF_LIST_H + +#include"scf_def.h" + +typedef struct scf_list_s scf_list_t; + +struct scf_list_s { + struct scf_list_s* prev; + struct scf_list_s* next; +}; + +static inline void scf_list_init(scf_list_t* h) +{ + h->prev = h; + h->next = h; +} + +static inline void scf_list_del(scf_list_t* n) +{ + n->prev->next = n->next; + n->next->prev = n->prev; + + // only to avoid some wrong operations for these 2 invalid pointers + n->prev = NULL; + n->next = NULL; +} + +static inline void scf_list_add_tail(scf_list_t* h, scf_list_t* n) +{ + h->prev->next = n; + n->prev = h->prev; + n->next = h; + h->prev = n; +} + +static inline void scf_list_add_front(scf_list_t* h, scf_list_t* n) +{ + h->next->prev = n; + n->next = h->next; + n->prev = h; + h->next = n; +} + +static inline void scf_list_mov2(scf_list_t* h0, scf_list_t* h1) +{ + if (h1->next == h1) + return; + + h0->prev->next = h1->next; + h1->next->prev = h0->prev; + h1->prev->next = h0; + h0->prev = h1->prev; +} + +#define SCF_LIST_INIT(h) {&h, &h} + +#define scf_list_data(l, type, member) ((type*)((char*)l - offsetof(type, member))) + +#define scf_list_head(h) ((h)->next) +#define scf_list_tail(h) ((h)->prev) +#define scf_list_sentinel(h) (h) +#define scf_list_next(l) ((l)->next) +#define scf_list_prev(l) ((l)->prev) +#define scf_list_empty(h) ((h)->next == (h)) + +#define scf_list_clear(h, type, member, type_free) \ + do {\ + scf_list_t* l;\ + type* t;\ + for (l = scf_list_head(h); l != scf_list_sentinel(h);) {\ + t = scf_list_data(l, type, member);\ + l = scf_list_next(l);\ + scf_list_del(&t->member);\ + type_free(t);\ + t = NULL;\ + }\ + } while(0) + +#define scf_slist_clear(h, type, next, type_free) \ + do { \ + while (h) { \ + type* p = h; \ + h = p->next; \ + type_free(p); \ + p = NULL; \ + } \ + } while (0) + +#define scf_list_mov(dst, src, type, member) \ + do {\ + scf_list_t* l;\ + type* t;\ + for (l = scf_list_head(src); l != scf_list_sentinel(src);) {\ + t = scf_list_data(l, type, member);\ + l = scf_list_next(l);\ + scf_list_del(&t->member);\ + scf_list_add_tail(dst, &t->member);\ + }\ + } while(0) + +#endif diff --git a/ses_ui.c b/ses_ui.c index c641e73..5f87dcd 100644 --- a/ses_ui.c +++ b/ses_ui.c @@ -1,5 +1,37 @@ #include"ses_ui.h" +static void ui_add_eline(ses_ui_t* ui, ScfEline* el) +{ + ScfEcomponent* c; + ScfEpin* p; + long i; + + for (i = 0; i + 1 < el->n_pins; i += 2) { + c = ui->f->components[el->pins[i]]; + p = c->pins [el->pins[i + 1]]; + + p->lid = el->id; + + scf_logi("\033[32m el%ld add c%ldp%ld\033[0m\n", el->id, p->cid, p->id); + } +} + +static void ui_del_eline(ses_ui_t* ui, ScfEline* el) +{ + ScfEcomponent* c; + ScfEpin* p; + long i; + + for (i = 0; i + 1 < el->n_pins; i += 2) { + c = ui->f->components[el->pins[i]]; + p = c->pins [el->pins[i + 1]]; + + p->lid = -1; + + scf_logi("\033[31m el%ld del c%ldp%ld\033[0m\n", el->id, p->cid, p->id); + } +} + static void resize(GtkGLArea* self, gint width, gint height, gpointer user_data) { GdkGLContext *context; @@ -90,6 +122,132 @@ static gboolean render(GtkGLArea* self, GdkGLContext* context, gpointer user_dat return TRUE; } +static void ui_print_log(ui_log_t* log) +{ + switch (log->type) { + case UI_ADD_COMPONENT: + fprintf(stderr, "log: add %p c%ld\n", log->c, log->c->id); + break; + + case UI_MOV_COMPONENT: + fprintf(stderr, "log: mov %p c%ld, (%d,%d)-->(%d,%d)\n", log->c, log->c->id, log->old_x, log->old_y, log->new_x, log->new_y); + break; + + case UI_SET_VALUE: + fprintf(stderr, "log: set %p c%ld, %lg-->%lg\n", log->c, log->c->id, log->old_v, log->new_v); + break; + + case UI_ADD_ELINE: + fprintf(stderr, "log: add %p el%ld\n", log->el, log->el->id); + break; + + case UI_DEL_ELINE: + fprintf(stderr, "log: del %p el%ld\n", log->el, log->el->id); + break; + + case UI_ADD_LINE: + fprintf(stderr, "log: add %p el%ld, l: %p\n", log->el, log->el->id, log->l); + break; + + case UI_DEL_LINE: + fprintf(stderr, "log: del %p el%ld, l: %p\n", log->el, log->el->id, log->l); + break; + default: + break; + }; +} + +static void ui_print_logs(ses_ui_t* ui) +{ + scf_list_t* l; + ui_log_t* log; + + for (l = scf_list_head(&ui->log); l != scf_list_sentinel(&ui->log); l = scf_list_next(l)) { + log = scf_list_data(l, ui_log_t, list); + + ui_print_log(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"); + 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); + + switch (log->type) { + case UI_ADD_COMPONENT: + scf_logw("free: add %p, c%ld\n", log->c, log->c->id); + + 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); + break; + + case UI_MOV_COMPONENT: + scf_logw("free: mov %p, (%d,%d)-->(%d,%d)\n", log->c, log->old_x, log->old_y, log->new_x, log->new_y); + break; + + case UI_SET_VALUE: + scf_logw("free: set %p\n", log->c); + break; + + case UI_DEL_ELINE: + scf_logw("free: del el %p\n", log->el); + break; + + case UI_DEL_LINE: + scf_logw("free: del el %p, l %p\n", log->el, log->l); + break; + + case UI_ADD_LINE: + scf_logw("free: add el %p, l %p\n", log->el, log->l); + break; + default: + break; + }; + + free(log); + log = NULL; + } + + if (scf_list_sentinel(&ui->log) == scf_list_next(ui->current)) + gtk_widget_set_sensitive(ui->redo, FALSE); + + gtk_widget_set_sensitive(ui->undo, TRUE); + + fprintf(stderr, "\n-----\n"); + ui_print_logs(ui); + fprintf(stderr, "-----\n\n"); +} + static int button_2pins_clicked(ses_ui_t* ui, int type) { ScfEcomponent* B; @@ -103,8 +261,8 @@ static int button_2pins_clicked(ses_ui_t* ui, int type) EDA_INST_ADD_COMPONENT(ui->f, B, SCF_EDA_Battery); B->x = 100; B->y = 100; - B->w = 16; - B->h = 10; + B->w = 24; + B->h = 24; B->pins[0]->x = B->x; B->pins[1]->x = B->x; @@ -116,7 +274,7 @@ static int button_2pins_clicked(ses_ui_t* ui, int type) EDA_INST_ADD_COMPONENT(ui->f, c, type); c->x = 200 + rand() % 100; c->y = 200 + rand() % 100; - c->w = 12; + c->w = 24; c->h = 24; c->pins[0]->x = c->x; @@ -124,6 +282,16 @@ static int button_2pins_clicked(ses_ui_t* ui, int type) c->pins[0]->y = c->y + 50; c->pins[1]->y = c->y - 50; + + ui_log_t* log = calloc(1, sizeof(ui_log_t)); + if (!log) + return -ENOMEM; + + log->c = c; + log->type = UI_ADD_COMPONENT; + log->ok_flag = 1; + + ui_add_log(ui, log); return 0; } @@ -140,8 +308,8 @@ static int button_transistor_clicked(ses_ui_t* ui, int type) EDA_INST_ADD_COMPONENT(ui->f, B, SCF_EDA_Battery); B->x = 100; B->y = 100; - B->w = 16; - B->h = 10; + B->w = 24; + B->h = 24; B->pins[0]->x = B->x; B->pins[1]->x = B->x; @@ -153,7 +321,7 @@ static int button_transistor_clicked(ses_ui_t* ui, int type) EDA_INST_ADD_COMPONENT(ui->f, c, type); c->x = 200 + rand() % 100; c->y = 200 + rand() % 100; - c->w = 12; + c->w = 24; c->h = 24; c->pins[SCF_EDA_NPN_B]->x = c->x; @@ -164,6 +332,16 @@ static int button_transistor_clicked(ses_ui_t* ui, int type) c->pins[SCF_EDA_NPN_E]->x = c->x + 100 * 7 / 8; c->pins[SCF_EDA_NPN_E]->y = c->y + 50; + + ui_log_t* log = calloc(1, sizeof(ui_log_t)); + if (!log) + return -ENOMEM; + + log->c = c; + log->type = UI_ADD_COMPONENT; + log->ok_flag = 1; + + ui_add_log(ui, log); return 0; } @@ -264,6 +442,8 @@ static int button_add_line(ScfEline* el, ScfLine** pl, int x0, int y0, int x1, i return ret; } + l->el = el; + *pl = l; return 0; } @@ -298,6 +478,7 @@ static int button_connect_pin(ses_ui_t* ui, ScfEpin* p0, ScfEpin* p1) { ScfEline* el = NULL; ScfLine* l = NULL; + ui_log_t* log; int ret; @@ -310,29 +491,45 @@ static int button_connect_pin(ses_ui_t* ui, ScfEpin* p0, ScfEpin* p1) ret = scf_eline__add_pin(el, p0->cid, p0->id); if (ret < 0) return ret; - p0->lid = el->id; + + log = calloc(1, sizeof(ui_log_t)); + if (!log) + return -ENOMEM; + log->el = el; + log->type = UI_ADD_ELINE; + + ui_add_log(ui, log); } else { ret = button_add_line(el, &l, p0->x, p0->y, p1->x, p1->y); if (ret < 0) return ret; + + log = calloc(1, sizeof(ui_log_t)); + if (!log) + return -ENOMEM; + log->el = el; + log->l = l; + log->p = p1; + log->type = UI_ADD_LINE; + + ui_add_log(ui, log); } ret = scf_eline__add_pin(el, p1->cid, p1->id); if (ret < 0) return ret; + p1->lid = el->id; scf_logi("\033[32m el%ld add c%ldp%ld, c%ldp%ld\033[0m\n", el->id, p0->cid, p0->id, p1->cid, p1->id); - - p1->lid = el->id; return 0; } static int button_connect_pins(ses_ui_t* ui) { + ui_log_t* log; ScfEpin* p; long i; - long j; for (i = 0; i < ui->c->n_pins; i++) { p = ui->c->pins[i]; @@ -362,6 +559,14 @@ static int button_connect_pins(ses_ui_t* ui) int ret = button_add_eline(ui, &el, &l, x, y, x, y); if (ret < 0) return ret; + + log = calloc(1, sizeof(ui_log_t)); + if (!log) + return -ENOMEM; + log->el = el; + log->type = UI_ADD_ELINE; + + ui_add_log(ui, log); } } @@ -381,35 +586,188 @@ static int button_connect_pins(ses_ui_t* ui) } else { scf_efunction_find_eline(ui->f, &el, &l, x, y); if (!el) { - j = scf_find_eline_index(ui->f, p->lid); + int dx = ui->cx - ui->c->x; + int dy = ui->cy - ui->c->y; + + x = p->x + dx; + y = p->y + dy; + + scf_efunction_find_eline(ui->f, &el, &l, x, y); + if (el) { + if (4 == el->n_pins) { + scf_efunction__del_eline(ui->f, el); + ui_del_eline(ui, el); + + log = calloc(1, sizeof(ui_log_t)); + if (!log) + return -ENOMEM; + log->el = el; + log->type = UI_DEL_ELINE; + + ui_add_log(ui, log); + } else { + scf_eline__del_line(el, l); + l->el = NULL; + p->lid = -1; + + scf_logi("\033[31m el%ld del c%ldp%ld\033[0m\n", el->id, p->cid, p->id); + + log = calloc(1, sizeof(ui_log_t)); + if (!log) + return -ENOMEM; + log->el = el; + log->l = l; + log->p = p; + log->type = UI_DEL_LINE; + + ui_add_log(ui, log); + } + } + } + } + } + + return 0; +} + +static void set_value(ScfEcomponent* c, double d) +{ + switch (c->type) { + case SCF_EDA_Battery: + c->v = d; + break; - if (j >= 0) { - el = ui->f->elines[j]; + case SCF_EDA_Resistor: + c->r = d; + break; - assert(0 == scf_eline__del_pin(el, p->cid, p->id)); - p->lid = -1; + case SCF_EDA_Capacitor: + c->uf = d; + break; + + case SCF_EDA_Inductor: + c->uh = d; + break; + default: + break; + }; +} - scf_logi("\033[31m el%ld del c%ldp%ld\033[0m\n", el->id, p->cid, p->id); +static void dialog_response(GtkDialog* self, gint response_id, gpointer user_data) +{ + ses_ui_t* ui = user_data; + ui_log_t* log; + + double d = atof(gtk_entry_get_text(ui->entry_data)); + if (d > 0.0) { + log = calloc(1, sizeof(ui_log_t)); + if (!log) + goto end; + + log->c = ui->setc; + log->type = UI_SET_VALUE; + log->new_v = d; + + ui_add_log(ui, log); + + switch (ui->setc->type) { + case SCF_EDA_Battery: + log->old_v = ui->setc->v; + ui->setc->v = d; + break; + + case SCF_EDA_Resistor: + log->old_v = ui->setc->r; + ui->setc->r = d; + break; + + case SCF_EDA_Capacitor: + log->old_v = ui->setc->uf; + ui->setc->uf = d; + break; + + case SCF_EDA_Inductor: + log->old_v = ui->setc->uh; + ui->setc->uh = d; + break; + default: + break; + }; + + log->ok_flag = 1; + } - if (2 == el->n_pins) { - c2 = ui->f->components[el->pins[0]]; - p2 = c2->pins [el->pins[1]]; +end: + ui->entry_data = NULL; + ui->setc = NULL; - assert(0 == scf_eline__del_pin(el, p2->cid, p2->id)); - p2->lid = -1; + gtk_widget_destroy(GTK_WIDGET(self)); +} - scf_logi("\033[31m el%ld del c%ldp%ld\033[0m\n", el->id, p2->cid, p2->id); +void button_set_data(ses_ui_t* ui) +{ + GtkWidget* dialog; + GtkWidget* content_area; + GtkWidget* label; + GtkWidget* entry; + + assert(ui->c); + switch (ui->c->type) { + case SCF_EDA_Battery: + label = gtk_label_new("V"); + break; - assert(0 == scf_efunction__del_eline(ui->f, el)); - ScfEline_free(el); - el = NULL; - } - } - } - } + case SCF_EDA_Resistor: + label = gtk_label_new("Ω"); + break; + + case SCF_EDA_Capacitor: + label = gtk_label_new("uF"); + break; + + case SCF_EDA_Inductor: + label = gtk_label_new("uH"); + break; + default: + return; + break; + }; + + if (!label) + return; + + dialog = gtk_dialog_new_with_buttons ("set value", + ui->window, + GTK_DIALOG_DESTROY_WITH_PARENT, + "_OK", + GTK_RESPONSE_NONE, + NULL); + + if (!dialog) { + gtk_widget_destroy(label); + return; } - return 0; + entry = gtk_entry_new(); + if (!entry) { + gtk_widget_destroy(label); + gtk_widget_destroy(dialog); + return; + } + + ui->entry_data = GTK_ENTRY(entry); + ui->setc = ui->c; + + content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); + + g_signal_connect(dialog, "response", G_CALLBACK(dialog_response), ui); + + gtk_container_add(GTK_CONTAINER(content_area), entry); + gtk_container_add(GTK_CONTAINER(content_area), label); + + gtk_orientable_set_orientation(GTK_ORIENTABLE(content_area), GTK_ORIENTATION_HORIZONTAL); + + gtk_widget_show_all(dialog); } static gboolean button_press_event(GtkWidget* self, GdkEventButton* event, gpointer user_data) @@ -421,7 +779,7 @@ static gboolean button_press_event(GtkWidget* self, GdkEventButton* event, gpoin if (gtk_widget_get_window(GTK_WIDGET(ui->gl_area)) == event->window) { ui->status = SES_UI_EDIT; - scf_logi("x: %f, y: %f", event->x, event->y); + scf_logi("x: %f, y: %f\n", event->x, event->y); if (ui->f) { ui->c = NULL; @@ -430,8 +788,22 @@ static gboolean button_press_event(GtkWidget* self, GdkEventButton* event, gpoin scf_efunction_find_pin (ui->f, &ui->c, &ui->p, event->x, event->y); scf_efunction_find_eline(ui->f, &el, &l, event->x, event->y); - ui->press_x = event->x; - ui->press_y = event->y; + int64_t us = gettime(); + + if (ui->c && !ui->p) { + if (us - ui->press_us < 100 * 1000) { + scf_logw("us - ui->press_us: %ld\n", us - ui->press_us); + + button_set_data(ui); + } + + ui->cx = ui->c->x; + ui->cy = ui->c->y; + } + + ui->press_us = us; + ui->press_x = event->x; + ui->press_y = event->y; if (ui->c) { fprintf(stderr, ", c%ld", ui->c->id); @@ -451,6 +823,7 @@ static gboolean button_press_event(GtkWidget* self, GdkEventButton* event, gpoin static gboolean button_release_event(GtkWidget* self, GdkEventButton* event, gpointer user_data) { ses_ui_t* ui = user_data; + ui_log_t* log; if (gtk_widget_get_window(GTK_WIDGET(ui->gl_area)) == event->window) { ui->status = SES_UI_EDIT; @@ -459,7 +832,32 @@ static gboolean button_release_event(GtkWidget* self, GdkEventButton* event, gpo if (ui->c) { if (!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; + } + + 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; + + ui_add_log(ui, log); + } + button_connect_pins(ui); + + if (!scf_list_empty(&ui->log)) { + log = scf_list_data(scf_list_tail(&ui->log), ui_log_t, list); + log->ok_flag = 1; + } } else { ScfEpin* p = ui->p; @@ -467,12 +865,20 @@ static gboolean button_release_event(GtkWidget* self, GdkEventButton* event, gpo ui->p = NULL; scf_efunction_find_pin(ui->f, &ui->c, &ui->p, event->x, event->y); - if (ui->p) + if (ui->p) { button_connect_pin(ui, p, ui->p); + + 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->c = NULL; + ui->p = NULL; + ui->cx = 0; + ui->cy = 0; ui->press_x = 0; ui->press_y = 0; @@ -484,28 +890,35 @@ static gboolean button_release_event(GtkWidget* self, GdkEventButton* event, gpo return TRUE; } +static void mov_component(ScfEcomponent* c, int x, int y) +{ + ScfEpin* p; + + int dx = x - c->x; + int dy = y - c->y; + int i; + + for (i = 0; i < c->n_pins; i++) { + p = c->pins[i]; + + p->x += dx; + p->y += dy; + } + + c->x += dx; + c->y += dy; +} + static gboolean button_move_event(GtkWidget* self, GdkEventMotion* event, gpointer user_data) { ses_ui_t* ui = user_data; - ScfEpin* p; - long i; + ui_log_t* log; if (ui->c) { scf_logd("event x: %f, y: %f, c%ld\n", event->x, event->y, ui->c->id); if (!ui->p) { - int dx = event->x - ui->c->x; - int dy = event->y - ui->c->y; - - for (i = 0; i < ui->c->n_pins; i++) { - p = ui->c->pins[i]; - - p->x += dx; - p->y += dy; - } - - ui->c->x += dx; - ui->c->y += dy; + mov_component(ui->c, event->x, event->y); } else { ui->move_x = event->x; ui->move_y = event->y; @@ -664,14 +1077,156 @@ static int load_png(ses_ui_t* ui) return 0; } +static void undo_clicked(GtkButton* self, gpointer user_data) +{ + ScfEcomponent* c = NULL; + ScfEpin* p = NULL; + ses_ui_t* ui = user_data; + ui_log_t* log; + + ui->status = SES_UI_EDIT; + + while (1) { + log = scf_list_data(ui->current, ui_log_t, list); + + switch (log->type) { + case UI_ADD_COMPONENT: + scf_efunction__del_component(ui->f, log->c); + break; + + case UI_MOV_COMPONENT: + mov_component(log->c, log->old_x, log->old_y); + break; + + case UI_SET_VALUE: + set_value(log->c, log->old_v); + break; + + case UI_ADD_ELINE: + scf_efunction__del_eline(ui->f, log->el); + + ui_del_eline(ui, log->el); + break; + + case UI_DEL_ELINE: + scf_efunction__add_eline(ui->f, log->el); + + ui_add_eline(ui, log->el); + break; + + case UI_ADD_LINE: + scf_eline__del_line(log->el, log->l); + log->l->el = NULL; + + if (log->p) + log->p->lid = -1; + break; + + case UI_DEL_LINE: + scf_eline__add_line(log->el, log->l); + log->l->el = log->el; + + if (log->p) + log->p->lid = log->el->id; + break; + default: + break; + }; + + ui->current = scf_list_prev(ui->current); + + if (scf_list_sentinel(&ui->log) == ui->current) { + gtk_widget_set_sensitive(ui->undo, FALSE); + break; + } + + log = scf_list_data(ui->current, ui_log_t, list); + if (log->ok_flag) + break; + } + + gtk_widget_set_sensitive(ui->redo, TRUE); +} + +static void redo_clicked(GtkButton* self, gpointer user_data) +{ + scf_list_t* l; + ses_ui_t* ui = user_data; + ui_log_t* log; + + ui->status = SES_UI_EDIT; + + for (l = scf_list_next(ui->current); l != scf_list_sentinel(&ui->log); l = scf_list_next(l)) { + log = scf_list_data(l, ui_log_t, list); + + switch (log->type) { + case UI_ADD_COMPONENT: + scf_efunction__add_component(ui->f, log->c); + break; + + case UI_MOV_COMPONENT: + mov_component(log->c, log->new_x, log->new_y); + break; + + case UI_SET_VALUE: + set_value(log->c, log->new_v); + break; + + case UI_ADD_ELINE: + scf_efunction__add_eline(ui->f, log->el); + + ui_add_eline(ui, log->el); + break; + + case UI_DEL_ELINE: + scf_efunction__del_eline(ui->f, log->el); + + ui_del_eline(ui, log->el); + break; + + case UI_ADD_LINE: + scf_eline__add_line(log->el, log->l); + log->l->el = log->el; + + if (log->p) + log->p->lid = log->el->id; + break; + + case UI_DEL_LINE: + scf_eline__del_line(log->el, log->l); + log->l->el = NULL; + + if (log->p) + log->p->lid = -1; + break; + default: + break; + }; + + if (log->ok_flag) + break; + } + + ui->current = l; + + if (scf_list_sentinel(&ui->log) == scf_list_next(ui->current)) + gtk_widget_set_sensitive(ui->redo, FALSE); + + gtk_widget_set_sensitive(ui->undo, TRUE); +} + static void forward_clicked(GtkButton* self, gpointer user_data) { ses_ui_t* ui = user_data; - if (ui->show_index < ui->apply_index - 1) - ui->show_index++; - + ui->show_index++; load_png(ui); + + gtk_widget_set_sensitive(ui->back, TRUE); + + if (ui->show_index >= ui->apply_index - 1) + gtk_widget_set_sensitive(ui->forward, FALSE); + gtk_gl_area_queue_render(ui->gl_area); } @@ -679,10 +1234,14 @@ static void back_clicked(GtkButton* self, gpointer user_data) { ses_ui_t* ui = user_data; - if (ui->show_index > 0) - ui->show_index--; - + ui->show_index--; load_png(ui); + + gtk_widget_set_sensitive(ui->forward, TRUE); + + if (ui->show_index <= 0) + gtk_widget_set_sensitive(ui->back, FALSE); + gtk_gl_area_queue_render(ui->gl_area); } @@ -711,6 +1270,9 @@ static gboolean timer_handler(gpointer user_data) load_png(ui); } + if (ui->show_index < ui->apply_index - 1) + gtk_widget_set_sensitive(ui->forward, TRUE); + gtk_gl_area_queue_render(ui->gl_area); return TRUE; } @@ -761,7 +1323,7 @@ int main(int argc, char* argv[]) fcntl(0, F_SETFL, flags); } - ses_ui_t ui = SES_UI_INIT(); + ses_ui_t ui = SES_UI_INIT(ui); GtkBuilder* builder; GObject* window; @@ -782,6 +1344,7 @@ int main(int argc, char* argv[]) gl_area = gtk_builder_get_object(builder, "gl_area"); ui.builder = builder; + ui.window = GTK_WINDOW(window); ui.gl_area = GTK_GL_AREA(gl_area); ui.entry_ns = GTK_ENTRY(gtk_builder_get_object(builder, "entry_ns")); ui.entry_count = GTK_ENTRY(gtk_builder_get_object(builder, "entry_count")); @@ -806,6 +1369,13 @@ int main(int argc, char* argv[]) GObject* zoom_out = gtk_builder_get_object(builder, "button_zoom_out"); GObject* apply = gtk_builder_get_object(builder, "button_apply"); + ui.back = GTK_WIDGET(back); + ui.forward = GTK_WIDGET(forward); + ui.undo = GTK_WIDGET(undo); + ui.redo = GTK_WIDGET(redo); + + g_signal_connect(undo, "clicked", G_CALLBACK(undo_clicked), &ui); + g_signal_connect(redo, "clicked", G_CALLBACK(redo_clicked), &ui); g_signal_connect(forward, "clicked", G_CALLBACK(forward_clicked), &ui); g_signal_connect(back, "clicked", G_CALLBACK(back_clicked), &ui); g_signal_connect(apply, "clicked", G_CALLBACK(apply_clicked), &ui); @@ -833,16 +1403,7 @@ int main(int argc, char* argv[]) gtk_widget_show_all(GTK_WIDGET(window)); gtk_main(); -#if 0 - printf("./ses examples/sin_oscillator.cpk -t 1us -V v4\n"); - fflush(stdout); - - char* buf = NULL; - long len = 0; - if (getline(&buf, &len, stdin) != -1) - scf_logw("parent pid %d: %s\n", getpid(), buf); -#endif printf("q\n"); fflush(stdout); diff --git a/ses_ui.glade b/ses_ui.glade index 2931598..a5374bb 100644 --- a/ses_ui.glade +++ b/ses_ui.glade @@ -69,6 +69,7 @@ False True True + True @@ -144,6 +145,7 @@ gtk-go-back True True + False True True True @@ -159,6 +161,7 @@ gtk-go-forward True True + False True True True @@ -174,6 +177,7 @@ gtk-undo True True + False True True True @@ -189,6 +193,7 @@ gtk-redo True True + False True True True @@ -294,6 +299,21 @@ 10 + + + gtk-refresh + True + True + True + True + True + + + False + True + 11 + + gtk-help @@ -306,7 +326,7 @@ False True - 11 + 12 diff --git a/ses_ui.h b/ses_ui.h index c6927b9..03c0e90 100644 --- a/ses_ui.h +++ b/ses_ui.h @@ -2,6 +2,7 @@ #define SES_UI_H #include"ses_core.h" +#include"scf_list.h" #include #include @@ -13,15 +14,55 @@ #include typedef struct ses_ui_s ses_ui_t; +typedef struct ui_log_s ui_log_t; + +struct ui_log_s +{ + scf_list_t list; + + ScfEcomponent* c; + ScfEpin* p; + ScfEline* el; + ScfLine* l; + + double old_v; + double new_v; + + int old_x; + int old_y; + int new_x; + int new_y; +#define UI_ADD_COMPONENT 0 +#define UI_MOV_COMPONENT 1 +#define UI_SET_VALUE 2 +#define UI_ADD_ELINE 3 +#define UI_DEL_ELINE 4 +#define UI_ADD_LINE 5 +#define UI_DEL_LINE 6 + int type; + uint32_t ok_flag; +}; struct ses_ui_s { + scf_list_t log; + scf_list_t* current; + GtkBuilder* builder; + GtkWindow* window; GtkGLArea* gl_area; + GtkWidget* undo; + GtkWidget* redo; + GtkWidget* back; + GtkWidget* forward; + GtkEntry* entry_ns; GtkEntry* entry_count; + GtkEntry* entry_data; + ScfEcomponent* setc; + cairo_surface_t* surface; cairo_t* cr; uint8_t* bgra; @@ -29,7 +70,10 @@ struct ses_ui_s ScfEfunction* f; ScfEcomponent* c; ScfEpin* p; + int cx; + int cy; + int64_t press_us; int press_x; int press_y; int move_x; @@ -50,7 +94,14 @@ struct ses_ui_s int status; }; -#define SES_UI_INIT() {NULL,NULL, NULL,NULL, NULL,NULL,NULL, NULL,NULL,NULL, 0,0,0,0, 0,0, 0,0,0,0, -1,-1, 0} +#define SES_UI_INIT(ui) {SCF_LIST_INIT(ui.log), &ui.log, \ + NULL,NULL,NULL, \ + NULL,NULL,NULL,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} static const GLfloat vert_array[] = { -1.0f, -1.0f, diff --git a/udiv.cpk b/udiv.cpk deleted file mode 100644 index 320e57be97c5004e8dd064e1e76eaa6c271c2ce7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1080 zcma)*JxT;Y5QR&4NTJ1ALI)if7#WESi;;n#coYr1fH(12n|cP1VZAn3oPGli%un-8 zRek-KLB76!*p}*Uk6&-R0x%;_YyF zI(ETJwXQPG6SWvfwsqLUP8J0W-6JBa>+F*(ba%td8f<^&EmYl6`uE9iE0>zEr9O~W zCqk+rF_4^JyV;v}>AiLfx>c7gw}G@<7(DAThZC%Vb_=?-f4SvSZngO>w}G@9kroId zhBs?x+B5T+$vU;h)Y`V$K-!Fm4)c&8LS1H*L|q2DR_pgARzKlZXai|ABG+m}O`_}^ LB|d_+*jWDn>{$_4 -- 2.25.1