From 3cdd6526c6fc25d2cbd67d52ba2e4ee4fe01ba2e Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Tue, 5 Mar 2024 11:57:15 +0100 Subject: [PATCH] add xschem closest_object command, improve intuitive_interface (dont full-select already partially selected item when dragging) --- doc/xschem_man/developer_info.html | 26 ++++++++++++++---- src/actions.c | 3 +-- src/callback.c | 43 ++++++++++++++++-------------- src/editprop.c | 2 +- src/scheduler.c | 36 +++++++++++++++++++++++++ src/select.c | 8 ++++-- src/xschem.h | 2 +- 7 files changed, 89 insertions(+), 31 deletions(-) diff --git a/doc/xschem_man/developer_info.html b/doc/xschem_man/developer_info.html index 6ba11cda..421ce724 100644 --- a/doc/xschem_man/developer_info.html +++ b/doc/xschem_man/developer_info.html @@ -519,11 +519,6 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns" - - - - - @@ -572,6 +567,18 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
  • check_unique_names [1|0]
  •     Check if all instances have a unique refdes (name attribute in xschem), 
        highlight such instances. If second parameter is '1' rename duplicates 
    +
  • closest_object
  • +   returns index of closest object to mouse coordinates
    +   index = type layer n
    +   type = wire | text | line | poly | rect | arc | inst
    +   layer is the layer number the object is drawn with
    +   (valid for line, poly, rect, arc)
    +   n is the index of the object in the xschem array
    +   example:
    +      $  after 3000 {set obj [xschem closest_object]} 
    +   (after 3s) 
    +      $ puts $obj
    +      line 4 19 
  • circle
  •     Start a GUI placement of a circle.
        User should click 3 unaligned points to define the circle 
    @@ -713,6 +720,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
  • header_text header metadata (license info etc) present in schematic
  • infowindow_text ERC messages
  • instances number of instances in schematic
  • +
  • intuitive_interface ERC messages
  • last_created_window return win_path of last created tab or window
  • lastsel number of selected objects
  • line_width get line width
  • @@ -1323,6 +1331,7 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns"
  • hide_symbols set to 0,1,2 for various hiding level of symbols
  • hilight_color set hilight color for next hilight
  • infowindow_text ERC messages
  • +
  • intuitive_interface ERC messages
  • netlist_name set custom netlist name
  • netlist_type set netlisting mode (spice, verilog, vhdl, tedax, symbol)
  • no_draw set no drawing flag (0 or 1)
  • @@ -1545,6 +1554,13 @@ C {verilog_timescale.sym} 1050 -100 0 0 {name=s1 timestep="1ns" precision="1ns" + + + + + + + diff --git a/src/actions.c b/src/actions.c index e36054f0..e53849bf 100644 --- a/src/actions.c +++ b/src/actions.c @@ -1731,7 +1731,6 @@ void launcher(void) else if(xctx->sel_array[0].type==LINE) prop_ptr = xctx->line[c][n].prop_ptr; else if(xctx->sel_array[0].type==WIRE) prop_ptr = xctx->wire[n].prop_ptr; else if(xctx->sel_array[0].type==xTEXT) prop_ptr = xctx->text[n].prop_ptr; - /* select_object(mx,my,SELECTED, 0); */ my_strncpy(program, get_tok_value(prop_ptr,"program",0), S(program)); /* handle backslashes */ url = get_tok_value(prop_ptr,"url",0); /* handle backslashes */ dbg(1, "launcher(): url=%s\n", url); @@ -1744,7 +1743,7 @@ void launcher(void) } } tcleval("after 300"); - select_object(mx,my,0, 0); + select_object(mx,my,0, 0, NULL); } } diff --git a/src/callback.c b/src/callback.c index 49ff531f..3416e99a 100644 --- a/src/callback.c +++ b/src/callback.c @@ -1942,7 +1942,7 @@ int rstate; /* (reduced state, without ShiftMask) */ abs(my-xctx->my_save) > 8 ) { /* set reasonable threshold before unsel */ if(!xctx->already_selected) { select_object(X_TO_XSCHEM(xctx->mx_save), - Y_TO_XSCHEM(xctx->my_save), 0, 0); /* remove near obj if dragging */ + Y_TO_XSCHEM(xctx->my_save), 0, 0, NULL); /* remove near obj if dragging */ } rebuild_selected_array(); } @@ -3309,26 +3309,13 @@ int rstate; /* (reduced state, without ShiftMask) */ } if(xctx->ui_state & STARTPAN) { xctx->ui_state &=~STARTPAN; - /* xctx->mx_save = mx; xctx->my_save = my; */ - /* xctx->mx_double_save=xctx->mousex_snap; */ - /* xctx->my_double_save=xctx->mousey_snap; */ break; } - /* - * if(button == Button3 && tclgetvar("graph_selected")[0] && xctx->semaphore >=2 ) - * { - Selected sel; - * sel = select_object(xctx->mousex, xctx->mousey, SELECTED, 0); - * if(sel.type) send_net_to_graph(1); - * - * } - * else - */ if(button == Button3 && state == ControlMask && xctx->semaphore <2) { Selected sel; - sel = select_object(xctx->mousex, xctx->mousey, SELECTED, 0); + sel = select_object(xctx->mousex, xctx->mousey, SELECTED, 0, NULL); if(sel.type) select_connected_nets(1); } else if(button == Button3 && EQUAL_MODMASK && !(state & ShiftMask) && xctx->semaphore <2) @@ -3342,7 +3329,7 @@ int rstate; /* (reduced state, without ShiftMask) */ else if(button == Button3 && state == ShiftMask && xctx->semaphore <2) { Selected sel; - sel = select_object(xctx->mousex, xctx->mousey, SELECTED, 0); + sel = select_object(xctx->mousex, xctx->mousey, SELECTED, 0, NULL); if(sel.type) select_connected_nets(0); } else if(button == Button3 && state == 0 && xctx->semaphore <2) { @@ -3356,7 +3343,7 @@ int rstate; /* (reduced state, without ShiftMask) */ xctx->mx_save = mx; xctx->my_save = my; xctx->mx_double_save=xctx->mousex_snap; xctx->my_double_save=xctx->mousey_snap; - select_object(xctx->mousex, xctx->mousey, 0, 0); + select_object(xctx->mousex, xctx->mousey, 0, 0, NULL); rebuild_selected_array(); /* sets or clears xctx->ui_state SELECTION flag */ } else if(button==Button2 && (state == 0)) { @@ -3373,7 +3360,7 @@ int rstate; /* (reduced state, without ShiftMask) */ } else if(button==Button1 && state==0 && tclgetvar("edit_symbol_prop_new_sel")[0]) { tcleval("set edit_symbol_prop_new_sel 1; .dialog.f1.b1 invoke"); /* invoke 'OK' of edit prop dialog */ } else if(button==Button1 && (state & ShiftMask) && tclgetvar("edit_symbol_prop_new_sel")[0]) { - select_object(xctx->mousex, xctx->mousey, SELECTED, 0); + select_object(xctx->mousex, xctx->mousey, SELECTED, 0, NULL); tclsetvar("preserve_unchanged_attrs", "1"); rebuild_selected_array(); } @@ -3394,6 +3381,7 @@ int rstate; /* (reduced state, without ShiftMask) */ /* Button1Press to select objects */ if( !(xctx->ui_state & STARTSELECT) && !(xctx->ui_state & STARTWIRE) && !(xctx->ui_state & STARTLINE) ) { Selected sel; + int already_selected = 0; int prev_last_sel = xctx->lastsel; int no_shift_no_ctrl = !(state & (ShiftMask | ControlMask)); @@ -3403,8 +3391,23 @@ int rstate; /* (reduced state, without ShiftMask) */ xctx->my_double_save=xctx->mousey_snap; if(!xctx->intuitive_interface && no_shift_no_ctrl ) unselect_all(1); - sel = select_object(xctx->mousex, xctx->mousey, SELECTED, 0); + sel = find_closest_obj(xctx->mousex, xctx->mousey, 0); + if(xctx->intuitive_interface && !sel.type && no_shift_no_ctrl ) unselect_all(1); + + switch(sel.type) + { + case WIRE: if(xctx->wire[sel.n].sel) already_selected = 1; break; + case xTEXT: if(xctx->text[sel.n].sel) already_selected = 1; break; + case LINE: if(xctx->line[sel.col][sel.n].sel) already_selected = 1; break; + case POLYGON: if(xctx->poly[sel.col][sel.n].sel) already_selected = 1; break; + case xRECT: if(xctx->rect[sel.col][sel.n].sel) already_selected = 1; break; + case ARC: if(xctx->arc[sel.col][sel.n].sel) already_selected = 1; break; + case ELEMENT: if(xctx->inst[sel.n].sel) already_selected = 1; break; + default: break; + } /*end switch */ + + if(!already_selected) select_object(xctx->mousex, xctx->mousey, SELECTED, 0, &sel); rebuild_selected_array(); if(xctx->lastsel == 1 && xctx->sel_array[0].type==POLYGON) @@ -3524,7 +3527,7 @@ int rstate; /* (reduced state, without ShiftMask) */ if(!xctx->lastsel && xctx->ui_state == 0) { /* Following 5 lines do again a selection overriding lock, * so locked instance attrs can be edited */ - sel = select_object(xctx->mousex, xctx->mousey, SELECTED, 1); + sel = select_object(xctx->mousex, xctx->mousey, SELECTED, 1, NULL); if(sel.type) { xctx->ui_state = SELECTION; rebuild_selected_array(); diff --git a/src/editprop.c b/src/editprop.c index 7c91cba4..4e5cb0c2 100644 --- a/src/editprop.c +++ b/src/editprop.c @@ -1811,7 +1811,7 @@ void edit_property(int x) modified |= edit_symbol_property(x, j); while( x == 0 && tclgetvar("edit_symbol_prop_new_sel")[0] == '1') { unselect_all(1); - select_object(xctx->mousex, xctx->mousey, SELECTED, 0); + select_object(xctx->mousex, xctx->mousey, SELECTED, 0, NULL); rebuild_selected_array(); type = xctx->sel_array[0].type; diff --git a/src/scheduler.c b/src/scheduler.c index f53150db..e66295f1 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -445,6 +445,42 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg } Tcl_ResetResult(interp); } + /* closest_object + * returns index of closest object to mouse coordinates + * index = type layer n + * type = wire | text | line | poly | rect | arc | inst + * layer is the layer number the object is drawn with + * (valid for line, poly, rect, arc) + * n is the index of the object in the xschem array + * example: + * $ after 3000 {set obj [xschem closest_object]} + * (after 3s) + * $ puts $obj + * line 4 19 */ + else if(!strcmp(argv[1], "closest_object")) + { + char res[100]; + const char *type; + Selected sel; + if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;} + + sel = find_closest_obj(xctx->mousex, xctx->mousey, 0); + switch(sel.type) + { + case WIRE: type="wire"; break; + case xTEXT: type="text"; break; + case LINE: type="line"; break; + case POLYGON: type="poly"; break; + case xRECT: type="rect"; break; + case ARC: type="arc" ; break; + case ELEMENT: type="inst"; break; + default: break; + } /*end switch */ + + if(sel.type) my_snprintf(res, S(res), "%s %d %d", type, sel.col, sel.n); + else my_snprintf(res, S(res), "nosel"); + Tcl_SetResult(interp, res, TCL_VOLATILE); + } /* circle * Start a GUI placement of a circle. diff --git a/src/select.c b/src/select.c index e81f0cab..f0fc2389 100644 --- a/src/select.c +++ b/src/select.c @@ -1166,11 +1166,15 @@ void select_line(int c, int i, unsigned short select_mode, int fast ) } /* 20160503 return type field */ -Selected select_object(double mx,double my, unsigned short select_mode, int override_lock) +Selected select_object(double mx,double my, unsigned short select_mode, + int override_lock, Selected *selptr) { Selected sel; xctx->already_selected = 0; - sel = find_closest_obj(mx, my, override_lock); + if(!selptr) + sel = find_closest_obj(mx, my, override_lock); + else + sel = *selptr; dbg(1, "select_object(): sel.n=%d, sel.col=%d, sel.type=%d\n", sel.n, sel.col, sel.type); switch(sel.type) diff --git a/src/xschem.h b/src/xschem.h index e0ce63c0..d78da5f4 100644 --- a/src/xschem.h +++ b/src/xschem.h @@ -1353,7 +1353,7 @@ extern int text_bbox_nocairo(const char * str,double xscale, double yscale, #endif extern Selected select_object(double mx,double my, unsigned short sel_mode, - int override_lock); /* return type 20160503 */ + int override_lock, Selected *selptr); extern int set_first_sel(unsigned short type, int n, unsigned int col); extern void unselect_all(int dr); extern void select_attached_nets(void);