support Flip_V & Flip_H components
authoryu.dongliang <18588496441@163.com>
Fri, 13 Jun 2025 16:21:09 +0000 (00:21 +0800)
committeryu.dongliang <18588496441@163.com>
Fri, 13 Jun 2025 16:21:09 +0000 (00:21 +0800)
ses_ui.c
ses_ui.glade
ses_ui.h

index fa8ae6a5df3fa8ad0c9fcf05097c18ba91f9ded4..6b7d840bcf3d4d663ab52579eeaf45a5798d0b5d 100644 (file)
--- a/ses_ui.c
+++ b/ses_ui.c
@@ -173,6 +173,13 @@ static void ui_print_log(ui_log_t* log)
                        fprintf(stderr, "log: set %p c%ld, %lg-->%lg\n", log->c, log->c->id, log->old_v, log->new_v);
                        break;
 
+               case UI_FLIP_H:
+                       fprintf(stderr, "log: flip_h %p c%ld\n", log->c, log->c->id);
+                       break;
+               case UI_FLIP_V:
+                       fprintf(stderr, "log: flip_v %p c%ld\n", log->c, log->c->id);
+                       break;
+
                case UI_ADD_ELINE:
                        fprintf(stderr, "log: add %p el%ld\n", log->el, log->el->id);
                        break;
@@ -235,6 +242,13 @@ static void ui_free_log(ui_log_t* log, int unused)
                                scf_logw("free: set %p\n", log->c);
                                break;
 
+                       case UI_FLIP_H:
+                               scf_logw("free: flip_h %p\n", log->c);
+                               break;
+                       case UI_FLIP_V:
+                               scf_logw("free: flip_v %p\n", log->c);
+                               break;
+
                        case UI_DEL_ELINE:
                                scf_logw("free: del el %p\n", log->el);
                                break;
@@ -590,22 +604,24 @@ static int button_line_to(ses_ui_t* ui, int x0, int y0, int x1, int y1)
                        log->type = UI_ADD_ELINE;
 
                        ui_add_log(ui, log);
+                       goto add_pin;
                }
-       } else {
-               ret = button_add_line(el, &l, x0, y0, x1, y1);
-               if (ret < 0)
-                       return ret;
+       }
 
-               log = calloc(1, sizeof(ui_log_t));
-               if (!log)
-                       return -ENOMEM;
-               log->el   = el;
-               log->l    = l;
-               log->type = UI_ADD_LINE;
+       ret = button_add_line(el, &l, x0, y0, x1, y1);
+       if (ret < 0)
+               return ret;
 
-               ui_add_log(ui, log);
-       }
+       log = calloc(1, sizeof(ui_log_t));
+       if (!log)
+               return -ENOMEM;
+       log->el   = el;
+       log->l    = l;
+       log->type = UI_ADD_LINE;
 
+       ui_add_log(ui, log);
+
+add_pin:
        for (i = 0; i < ui->f->n_components; i++) {
                c  =        ui->f->components[i];
 
@@ -823,7 +839,7 @@ end:
        gtk_widget_destroy(GTK_WIDGET(self));
 }
 
-void button_set_data(ses_ui_t* ui)
+static void button_set_data(ses_ui_t* ui)
 {
        GtkWidget* dialog;
        GtkWidget* content_area;
@@ -896,8 +912,6 @@ 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\n", event->x, event->y);
-
                gtk_window_set_focus(ui->window, GTK_WIDGET(ui->gl_area));
 
                if (ui->f) {
@@ -905,30 +919,57 @@ static gboolean button_press_event(GtkWidget* self, GdkEventButton* event, gpoin
                        ui->p = NULL;
 
                        scf_efunction_find_pin(ui->f, &ui->c, &ui->p, event->x, event->y);
+#if 1
+                       scf_logi("x: %f, y: %f", event->x, event->y);
 
+                       if (ui->c) {
+                               fprintf(stderr, ", c%ld", ui->c->id);
+                               if (ui->p)
+                                       fprintf(stderr, "p%ld", ui->p->id);
+                       }
+                       fprintf(stderr, "\n");
+#endif
                        int64_t us = gettime();
 
                        if (ui->c && !ui->p) {
-                               if (us - ui->press_us < 10 * 1000) {
-                                       scf_logw("us - ui->press_us: %ld\n", us - ui->press_us);
+                               if (GDK_BUTTON_PRIMARY == event->button) {
+                                       if (us - ui->press_us < 10 * 1000) {
+                                               scf_logi("us - ui->press_us: %ld\n", us - ui->press_us);
 
-                                       button_set_data(ui);
-                               }
+                                               button_set_data(ui);
+                                       }
 
-                               ui->cx = ui->c->x;
-                               ui->cy = ui->c->y;
-                       }
+                                       ui->cx = ui->c->x;
+                                       ui->cy = ui->c->y;
 
-                       ui->press_us = us;
-                       ui->press_x  = event->x;
-                       ui->press_y  = event->y;
+                                       ui->press_us = us;
+                                       ui->press_x  = event->x;
+                                       ui->press_y  = event->y;
+                               } else {
+                                       ui->setc = ui->c;
 
-                       if (ui->c) {
-                               fprintf(stderr, ", c%ld", ui->c->id);
-                               if (ui->p)
-                                       fprintf(stderr, "p%ld", ui->p->id);
+                                       if (2 == ui->c->n_pins)
+                                               gtk_widget_set_sensitive(ui->flip_h, FALSE);
+                                       else
+                                               gtk_widget_set_sensitive(ui->flip_h, TRUE);
+
+                                       gtk_menu_popup_at_pointer(ui->popup, NULL);
+
+                                       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;
+                               }
+                       } else {
+                               ui->press_x  = event->x;
+                               ui->press_y  = event->y;
                        }
-                       fprintf(stderr, "\n");
                }
        }
 
@@ -1180,6 +1221,99 @@ static int load_file(ses_ui_t* ui, const char* cpk)
        return 0;
 }
 
+static void flip_v(ScfEcomponent* c)
+{
+       ScfEpin*  pb;
+       ScfEpin*  pe;
+       ScfEpin*  pc;
+
+       switch (c->type) {
+               case SCF_EDA_Battery:
+               case SCF_EDA_Resistor:
+               case SCF_EDA_Capacitor:
+               case SCF_EDA_Inductor:
+               case SCF_EDA_Diode:
+               case SCF_EDA_Crystal:
+                       SCF_XCHG(c->pins[0]->y, c->pins[1]->y);
+                       break;
+
+               case SCF_EDA_NPN:
+               case SCF_EDA_PNP:
+                       pb = c->pins[SCF_EDA_NPN_B];
+                       pe = c->pins[SCF_EDA_NPN_E];
+                       pc = c->pins[SCF_EDA_NPN_C];
+
+                       pb->y = c->y + (c->y - pb->y);
+                       pe->y = c->y + (c->y - pe->y);
+                       pc->y = pe->y;
+                       break;
+               default:
+                       break;
+       };
+}
+
+static void flip_h(ScfEcomponent* c)
+{
+       ScfEpin*  pb;
+       ScfEpin*  pe;
+       ScfEpin*  pc;
+
+       switch (c->type) {
+               case SCF_EDA_NPN:
+               case SCF_EDA_PNP:
+                       pc = c->pins[SCF_EDA_NPN_C];
+                       pe = c->pins[SCF_EDA_NPN_E];
+                       SCF_XCHG(pc->x, pe->x);
+                       break;
+               default:
+                       break;
+       };
+}
+
+static void flip_h_activate(GtkMenuItem* self, gpointer user_data)
+{
+       ses_ui_t*  ui = user_data;
+       ui_log_t*  log;
+
+       scf_logi("\n");
+
+       log = calloc(1, sizeof(ui_log_t));
+       if (!log)
+               return;
+
+       log->c    = ui->setc;
+       log->type = UI_FLIP_H;
+       log->ok_flag = 1;
+
+       ui_add_log(ui, log);
+
+       flip_h(ui->setc);
+
+       ui->setc = NULL;
+}
+
+static void flip_v_activate(GtkMenuItem* self, gpointer user_data)
+{
+       ses_ui_t*  ui = user_data;
+       ui_log_t*  log;
+
+       scf_logi("\n");
+
+       log = calloc(1, sizeof(ui_log_t));
+       if (!log)
+               return;
+
+       log->c    = ui->setc;
+       log->type = UI_FLIP_V;
+       log->ok_flag = 1;
+
+       ui_add_log(ui, log);
+
+       flip_v(ui->setc);
+
+       ui->setc = NULL;
+}
+
 static void open_activate(GtkMenuItem* self, gpointer user_data)
 {
        scf_logi("\n");
@@ -1390,6 +1524,14 @@ static void undo_clicked(GtkButton* self, gpointer user_data)
                                set_value(log->c, log->old_v);
                                break;
 
+                       case UI_FLIP_V:
+                               flip_v(log->c);
+                               break;
+
+                       case UI_FLIP_H:
+                               flip_h(log->c);
+                               break;
+
                        case UI_ADD_ELINE:
                                scf_efunction__del_eline(ui->f, log->el);
 
@@ -1459,6 +1601,14 @@ static void redo_clicked(GtkButton* self, gpointer user_data)
                                set_value(log->c, log->new_v);
                                break;
 
+                       case UI_FLIP_V:
+                               flip_v(log->c);
+                               break;
+
+                       case UI_FLIP_H:
+                               flip_h(log->c);
+                               break;
+
                        case UI_ADD_ELINE:
                                scf_efunction__add_eline(ui->f, log->el);
 
@@ -1654,6 +1804,7 @@ int main(int argc, char* argv[])
        ui.gl_area     = GTK_GL_AREA(gl_area);
        ui.text_log    = GTK_TEXT_VIEW(text_log);
 
+       ui.popup       = GTK_MENU (gtk_builder_get_object(builder, "menu_popup"));
        ui.entry_ns    = GTK_ENTRY(gtk_builder_get_object(builder, "entry_ns"));
        ui.entry_count = GTK_ENTRY(gtk_builder_get_object(builder, "entry_count"));
 
@@ -1674,10 +1825,18 @@ int main(int argc, char* argv[])
        GObject*    save_as    = gtk_builder_get_object(builder, "file_save_as");
        GObject*    quit       = gtk_builder_get_object(builder, "file_quit");
 
+       GObject*    flip_h     = gtk_builder_get_object(builder, "flip_h");
+       GObject*    flip_v     = gtk_builder_get_object(builder, "flip_v");
+
        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);
+       g_signal_connect(flip_h,    "activate",   G_CALLBACK(flip_h_activate),   &ui);
+       g_signal_connect(flip_v,    "activate",   G_CALLBACK(flip_v_activate),   &ui);
+
+       ui.flip_h = GTK_WIDGET(flip_h);
+       ui.flip_v = GTK_WIDGET(flip_v);
 
        GObject*    back       = gtk_builder_get_object(builder, "button_back");
        GObject*    forward    = gtk_builder_get_object(builder, "button_forward");
index 33ee01dd7f521b4c27dcce302d14c483f143deed..429022f59a74aecec6050274d04a550fb1f670b0 100644 (file)
                       <object class="GtkButton" id="button_back">
                         <property name="label">gtk-go-back</property>
                         <property name="visible">True</property>
-                        <property name="can-focus">True</property>
                         <property name="sensitive">False</property>
+                        <property name="can-focus">True</property>
                         <property name="receives-default">True</property>
                         <property name="use-stock">True</property>
                         <property name="always-show-image">True</property>
                       <object class="GtkButton" id="button_forward">
                         <property name="label">gtk-go-forward</property>
                         <property name="visible">True</property>
-                        <property name="can-focus">True</property>
                         <property name="sensitive">False</property>
+                        <property name="can-focus">True</property>
                         <property name="receives-default">True</property>
                         <property name="use-stock">True</property>
                         <property name="always-show-image">True</property>
                       <object class="GtkButton" id="button_undo">
                         <property name="label">gtk-undo</property>
                         <property name="visible">True</property>
-                        <property name="can-focus">True</property>
                         <property name="sensitive">False</property>
+                        <property name="can-focus">True</property>
                         <property name="receives-default">True</property>
                         <property name="use-stock">True</property>
                         <property name="always-show-image">True</property>
                       <object class="GtkButton" id="button_redo">
                         <property name="label">gtk-redo</property>
                         <property name="visible">True</property>
-                        <property name="can-focus">True</property>
                         <property name="sensitive">False</property>
+                        <property name="can-focus">True</property>
                         <property name="receives-default">True</property>
                         <property name="use-stock">True</property>
                         <property name="always-show-image">True</property>
       </object>
     </child>
   </object>
+  <object class="GtkMenu" id="menu_popup">
+    <property name="visible">True</property>
+    <property name="can-focus">False</property>
+    <child>
+      <object class="GtkRadioMenuItem" id="flip_h">
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <property name="label" translatable="yes">H Flip/水平反转</property>
+        <property name="use-underline">True</property>
+        <property name="draw-as-radio">True</property>
+      </object>
+    </child>
+    <child>
+      <object class="GtkRadioMenuItem" id="flip_v">
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <property name="label" translatable="yes">V flip/垂直反转</property>
+        <property name="use-underline">True</property>
+        <property name="draw-as-radio">True</property>
+      </object>
+    </child>
+  </object>
 </interface>
index 1bddc66bd33e30004890c28d4f67ccc0a7aba220..fcc87ad8862cb9b2904f63a11b5fa57878d2777c 100644 (file)
--- a/ses_ui.h
+++ b/ses_ui.h
@@ -41,6 +41,8 @@ struct ui_log_s
 #define UI_DEL_LINE       6
 #define UI_ADD_PIN        7
 #define UI_DEL_PIN        8
+#define UI_FLIP_H         9
+#define UI_FLIP_V        10
        int               type;
        uint32_t          ok_flag;
 };
@@ -60,6 +62,10 @@ struct ses_ui_s
        GtkWidget*        back;
        GtkWidget*        forward;
 
+       GtkMenu*          popup;
+       GtkWidget*        flip_h;
+       GtkWidget*        flip_v;
+
        GtkEntry*         entry_ns;
        GtkEntry*         entry_count;
 
@@ -102,6 +108,7 @@ struct ses_ui_s
 #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,NULL, \