add ability to click and drag directly polygon/bezier points

This commit is contained in:
stefan schippers 2024-03-01 00:12:44 +01:00
parent fb6d73723e
commit e946a729f8
12 changed files with 102 additions and 33 deletions

View File

@ -298,7 +298,9 @@ void set_snap(double newsnap) /* 20161212 set new snap factor and just notify n
tclvareval(xctx->top_path, ".statusbar.3 configure -background OrangeRed", NULL);
}
}
xctx->cadhalfdotsize = CADHALFDOTSIZE * (cs < 10. ? cs : 10.) / 10.;
tclsetdoublevar("cadsnap", cs);
draw();
}
void set_grid(double newgrid)
@ -2485,11 +2487,11 @@ void calc_drawing_bbox(xRect *boundbox, int selected)
!xctx->wire[i].node[0] || !bus_hilight_hash_lookup(xctx->wire[i].node, 0,XLOOKUP)) continue;
}
if(xctx->wire[i].bus){
ov = INT_BUS_WIDTH(xctx->lw)> cadhalfdotsize ? INT_BUS_WIDTH(xctx->lw) : CADHALFDOTSIZE;
ov = INT_BUS_WIDTH(xctx->lw)> xctx->cadhalfdotsize ? INT_BUS_WIDTH(xctx->lw) : CADHALFDOTSIZE;
if(xctx->wire[i].y1 < xctx->wire[i].y2) { y1 = xctx->wire[i].y1-ov; y2 = xctx->wire[i].y2+ov; }
else { y1 = xctx->wire[i].y1+ov; y2 = xctx->wire[i].y2-ov; }
} else {
ov = cadhalfdotsize;
ov = xctx->cadhalfdotsize;
if(xctx->wire[i].y1 < xctx->wire[i].y2) { y1 = xctx->wire[i].y1-ov; y2 = xctx->wire[i].y2+ov; }
else { y1 = xctx->wire[i].y1+ov; y2 = xctx->wire[i].y2-ov; }
}
@ -2597,8 +2599,8 @@ void zoom_full(int dr, int sel, int flags, double shrink)
dbg(1, "zoom_full(): dr=%d sel=%d flags=%d areaw=%d, areah=%d\n", sel, dr, flags, xctx->areaw, xctx->areah);
if(flags & 1) change_linewidth(-1.);
/* we do this here since change_linewidth may not be called if flags & 1 == 0*/
/* cadhalfdotsize = CADHALFDOTSIZE + 0.04 * (tclgetdoublevar("cadsnap")-10); */
cadhalfdotsize = 4.0 * (cs < 10. ? cs : 10.) / 10.;
/* xctx->cadhalfdotsize = CADHALFDOTSIZE + 0.04 * (tclgetdoublevar("cadsnap")-10); */
xctx->cadhalfdotsize = 4.0 * (cs < 10. ? cs : 10.) / 10.;
if(dr && has_x) {
draw();
redraw_w_a_l_r_p_rubbers();

View File

@ -1305,6 +1305,7 @@ int rstate; /* (reduced state, without ShiftMask) */
break;
}
dbg(1, "ui_state=%d deltax=%g\n", xctx->ui_state, xctx->deltax);
if(xctx->ui_state) {
if(abs(mx-xctx->mx_save) > 8 || abs(my-xctx->my_save) > 8 ) {
my_snprintf(str, S(str), "mouse = %.16g %.16g - selected: %d w=%.16g h=%.16g",
@ -1316,11 +1317,15 @@ int rstate; /* (reduced state, without ShiftMask) */
}
}
if(xctx->ui_state & STARTZOOM) zoom_rectangle(RUBBER);
/* determine direction of a rectangle selection (or unselection with ALT key) */
if(xctx->ui_state & STARTSELECT && !(xctx->ui_state & (PLACE_SYMBOL | STARTPAN | PLACE_TEXT)) ) {
if( (state & Button1Mask) && SET_MODMASK) { /* 20171026 added unselect by area */
/* Unselect by area : determine direction */
if( (state & Button1Mask) && SET_MODMASK) {
if(mx >= xctx->mx_save) xctx->nl_dir = 0;
else xctx->nl_dir = 1;
select_rect(RUBBER,0);
/* select by area : determine direction */
} else if(state & Button1Mask) {
if(mx >= xctx->mx_save) xctx->nl_dir = 0;
else xctx->nl_dir = 1;
@ -1339,12 +1344,13 @@ int rstate; /* (reduced state, without ShiftMask) */
}
redraw_w_a_l_r_p_rubbers();
/* start of a mouse area select. No shift pressed */
/* start of a mouse area select. Button1 pressed. No shift pressed */
if(!(xctx->ui_state & STARTPOLYGON) && (state&Button1Mask) && !(xctx->ui_state & STARTWIRE) &&
!(xctx->ui_state & STARTPAN) && !(SET_MODMASK) &&
!(state & ShiftMask) && !(xctx->ui_state & (PLACE_SYMBOL | PLACE_TEXT)))
{
if(mx != xctx->mx_save || my != xctx->my_save) {
if(!xctx->poly_point_selected && (mx != xctx->mx_save || my != xctx->my_save)) {
if( !(xctx->ui_state & STARTSELECT)) {
select_rect(START,1);
xctx->onetime=1;
@ -3128,13 +3134,45 @@ int rstate; /* (reduced state, without ShiftMask) */
if( !(xctx->ui_state & STARTSELECT) && !(xctx->ui_state & STARTWIRE) && !(xctx->ui_state & STARTLINE) ) {
Selected sel;
int prev_last_sel = xctx->lastsel;
int polygon_n = -1, polygon_c = -1;
xctx->poly_point_selected = 0;
xctx->mx_save = mx; xctx->my_save = my;
xctx->mx_double_save=xctx->mousex_snap;
xctx->my_double_save=xctx->mousey_snap;
if(xctx->lastsel == 1 && xctx->sel_array[0].type==POLYGON) {
dbg(1, "1 Polygon selected\n");
polygon_n = xctx->sel_array[0].n;
polygon_c = xctx->sel_array[0].col;
}
if( !(state & ShiftMask) && !(SET_MODMASK) ) {
unselect_all(1);
}
sel = select_object(xctx->mousex, xctx->mousey, SELECTED, 0);
/* Check is user is clicking a control point of a polygon */
if(polygon_n >= 0) {
int i;
double ds = xctx->cadhalfdotsize;
xPoly *p = &xctx->poly[polygon_c][polygon_n];
for(i = 0; i < p->points; i++) {
if(
POINTINSIDE(xctx->mousex, xctx->mousey, p->x[i] - ds, p->y[i] - ds,
p->x[i] + ds, p->y[i] + ds)
) {
dbg(1, "selecting point %d\n", i);
xctx->poly[polygon_c][polygon_n].selected_point[i] = 1;
xctx->poly_point_selected = 1;
}
}
if(xctx->poly_point_selected) {
/* select_polygon(polygon_c, polygon_n, SELECTED1,1); */
xctx->poly[polygon_c][polygon_n].sel = SELECTED1;
xctx->need_reb_sel_arr=1;
move_objects(START,0,0,0);
}
}
if(!xctx->poly_point_selected) {
sel = select_object(xctx->mousex, xctx->mousey, SELECTED, 0);
}
rebuild_selected_array();
#ifndef __unix__
draw_selection(xctx->gc[SELLAYER], 0);
@ -3164,6 +3202,23 @@ int rstate; /* (reduced state, without ShiftMask) */
} /* button==Button1 */
break;
case ButtonRelease:
/* if a polygon/bezier control point was clicked, end point move operation
* and set polygon state back to SELECTED from SELECTED1 */
if((xctx->ui_state & (STARTMOVE | SELECTION)) && xctx->poly_point_selected) {
if(xctx->lastsel == 1 && xctx->sel_array[0].type==POLYGON) {
int k;
int n = xctx->sel_array[0].n;
int c = xctx->sel_array[0].col;
move_objects(END,0,0,0);
xctx->poly[c][n].sel = SELECTED;
for(k=0; k<xctx->poly[c][n].points; ++k) {
xctx->poly[c][n].selected_point[k] = 0;
}
xctx->need_reb_sel_arr=1;
}
}
if(waves_selected(event, key, state, button)) {
waves_callback(event, mx, my, key, button, aux, state);
break;
@ -3186,8 +3241,11 @@ int rstate; /* (reduced state, without ShiftMask) */
tclsetboolvar("enable_stretch", es);
break;
} else {
/* 20150927 filter out button4 and button5 events */
if(!(state&(Button4Mask|Button5Mask) ) ) select_rect(END,-1);
/* Button1 release: end of rectangle select */
if(!(state & (Button4Mask|Button5Mask) ) ) {
select_rect(END,-1);
}
}
if(draw_xhair) draw_crosshair(0);
rebuild_selected_array();

View File

@ -58,7 +58,7 @@ void update_conn_cues(int layer, int draw_cues, int dr_win)
hash_wires(); /* must be done also if wires==0 to clear wire_spatial_table */
if(!xctx->wires) return;
if(!xctx->draw_dots) return;
if(cadhalfdotsize*xctx->mooz<0.7) return;
if(xctx->cadhalfdotsize*xctx->mooz<0.7) return;
x1 = X_TO_XSCHEM(xctx->areax1);
y1 = Y_TO_XSCHEM(xctx->areay1);
x2 = X_TO_XSCHEM(xctx->areax2);
@ -107,10 +107,10 @@ void update_conn_cues(int layer, int draw_cues, int dr_win)
if(LINE_OUTSIDE(wire[i].x1, wire[i].y1,
wire[i].x2, wire[i].y2, x1, y1, x2, y2)) continue;
if( wire[i].end1 >1 ) {
filledarc(layer, ADD, wire[i].x1, wire[i].y1, cadhalfdotsize, 0, 360);
filledarc(layer, ADD, wire[i].x1, wire[i].y1, xctx->cadhalfdotsize, 0, 360);
}
if( wire[i].end2 >1 ) {
filledarc(layer, ADD, wire[i].x2, wire[i].y2, cadhalfdotsize, 0, 360);
filledarc(layer, ADD, wire[i].x2, wire[i].y2, xctx->cadhalfdotsize, 0, 360);
}
}
filledarc(layer, END, 0.0, 0.0, 0.0, 0.0, 0.0);
@ -527,7 +527,7 @@ void break_wires_at_point(double x0, double y0, int align)
draw();
xctx->draw_window = 1;
xctx->draw_pixmap = 0;
filledarc(PINLAYER, NOW, x0, y0, cadhalfdotsize, 0, 360);
filledarc(PINLAYER, NOW, x0, y0, xctx->cadhalfdotsize, 0, 360);
xctx->draw_window = w;
xctx->draw_pixmap = p;

View File

@ -1735,7 +1735,7 @@ void drawbezier(Drawable w, GC gc, int c, double *x, double *y, int points, int
#if 0
if(points == 4) {
if(gc == xctx->gc[SELLAYER]) for(i = 0; i < points; i++) {
drawtemparc(gc, NOW, x[i], y[i], cadhalfdotsize, 0., 360.);
drawtemparc(gc, NOW, x[i], y[i], xctx->cadhalfdotsize, 0., 360.);
}
i = 0;
for(t = 0; t <= 1.0; t += bez_steps) {
@ -1839,14 +1839,14 @@ void drawtemppolygon(GC gc, int what, double *x, double *y, int points, int flag
bezier = flags && (points > 2);
if((fix_broken_tiled_fill || !_unix) && gc == xctx->gctiled) {
MyXCopyAreaDouble(display, xctx->save_pixmap, xctx->window, xctx->gc[0],
x1 - cadhalfdotsize, y1 - cadhalfdotsize,
x2 + cadhalfdotsize, y2 + cadhalfdotsize,
x1 - cadhalfdotsize, y1 - cadhalfdotsize, xctx->lw);
x1 - xctx->cadhalfdotsize, y1 - xctx->cadhalfdotsize,
x2 + xctx->cadhalfdotsize, y2 + xctx->cadhalfdotsize,
x1 - xctx->cadhalfdotsize, y1 - xctx->cadhalfdotsize, xctx->lw);
} else {
if(gc == xctx->gc[SELLAYER]) for(i = 0; i < points; i++) {
if( POINTINSIDE(X_TO_SCREEN(x[i]), Y_TO_SCREEN(y[i]), xctx->areax1, xctx->areay1,
xctx->areax2, xctx->areay2)) {
drawtemparc(gc, NOW, x[i], y[i], cadhalfdotsize, 0., 360.);
drawtemparc(gc, NOW, x[i], y[i], xctx->cadhalfdotsize, 0., 360.);
}
}
if(bezier) {
@ -4158,13 +4158,17 @@ void draw(void)
int cc, c, i = 0 /*, floaters = 0 */;
xSymbol *symptr;
int textlayer;
double cs;
#if HAS_CAIRO==1
const char *textfont;
#endif
dbg(1, "draw()\n");
if(!xctx || xctx->no_draw) return;
cs = tclgetdoublevar("cadsnap");
xctx->cadhalfdotsize = 4.0 * (cs < 10. ? cs : 10.) / 10.;
xctx->crosshair_layer = tclgetintvar("crosshair_layer");
if(xctx->crosshair_layer < 0 ) xctx->crosshair_layer = 2;
if(xctx->crosshair_layer >= cadlayers ) xctx->crosshair_layer = 2;

View File

@ -1036,7 +1036,7 @@ static int edit_wire_property(void)
bus_ptr = get_tok_value(xctx->wire[k].prop_ptr,"bus",0);
if(!strboolcmp(bus_ptr, "true")) {
double ov, y1, y2;
ov = INT_BUS_WIDTH(xctx->lw) > cadhalfdotsize ? INT_BUS_WIDTH(xctx->lw) : CADHALFDOTSIZE;
ov = INT_BUS_WIDTH(xctx->lw) > xctx->cadhalfdotsize ? INT_BUS_WIDTH(xctx->lw) : CADHALFDOTSIZE;
if(xctx->wire[k].y1 < xctx->wire[k].y2) { y1 = xctx->wire[k].y1-ov; y2 = xctx->wire[k].y2+ov; }
else { y1 = xctx->wire[k].y1+ov; y2 = xctx->wire[k].y2-ov; }
bbox(ADD, xctx->wire[k].x1-ov, y1 , xctx->wire[k].x2+ov , y2 );
@ -1044,7 +1044,7 @@ static int edit_wire_property(void)
} else {
if(oldbus){
double ov, y1, y2;
ov = INT_BUS_WIDTH(xctx->lw)> cadhalfdotsize ? INT_BUS_WIDTH(xctx->lw) : CADHALFDOTSIZE;
ov = INT_BUS_WIDTH(xctx->lw)> xctx->cadhalfdotsize ? INT_BUS_WIDTH(xctx->lw) : CADHALFDOTSIZE;
if(xctx->wire[k].y1 < xctx->wire[k].y2) { y1 = xctx->wire[k].y1-ov; y2 = xctx->wire[k].y2+ov; }
else { y1 = xctx->wire[k].y1+ov; y2 = xctx->wire[k].y2-ov; }
bbox(ADD, xctx->wire[k].x1-ov, y1 , xctx->wire[k].x2+ov , y2 );
@ -1190,7 +1190,8 @@ static int edit_polygon_property(void)
if(k==0 || xctx->poly[c][i].x[k] > x2) x2 = xctx->poly[c][i].x[k];
if(k==0 || xctx->poly[c][i].y[k] > y2) y2 = xctx->poly[c][i].y[k];
}
bbox(ADD, x1-cadhalfdotsize, y1-cadhalfdotsize, x2+cadhalfdotsize, y2+cadhalfdotsize);
bbox(ADD, x1-xctx->cadhalfdotsize, y1-xctx->cadhalfdotsize,
x2+xctx->cadhalfdotsize, y2+xctx->cadhalfdotsize);
}
}
if(drw) {

View File

@ -179,7 +179,6 @@ char pwd_dir[PATH_MAX]; /* obtained via getcwd() */
int tcp_port = 0;
int text_svg=1; /* use <text> svg element for text instead of xschem's internal vector font */
int text_ps=1; /* use ps font for text instead of xschem's internal vector font */
double cadhalfdotsize = CADHALFDOTSIZE;
char bus_char[3] = {0, 0, 0};
int yyparse_error = 0;
char *xschem_executable=NULL;

View File

@ -2045,12 +2045,14 @@ void draw_hilight_net(int on_window)
else
drawline(get_color(entry->value), NOW,
xctx->wire[i].x1, xctx->wire[i].y1, xctx->wire[i].x2, xctx->wire[i].y2, 0, NULL);
if(cadhalfdotsize*xctx->mooz>=0.7) {
if(xctx->cadhalfdotsize*xctx->mooz>=0.7) {
if( xctx->wire[i].end1 >1 ) {
filledarc(get_color(entry->value), NOW, xctx->wire[i].x1, xctx->wire[i].y1, cadhalfdotsize, 0, 360);
filledarc(get_color(entry->value), NOW, xctx->wire[i].x1, xctx->wire[i].y1,
xctx->cadhalfdotsize, 0, 360);
}
if( xctx->wire[i].end2 >1 ) {
filledarc(get_color(entry->value), NOW, xctx->wire[i].x2, xctx->wire[i].y2, cadhalfdotsize, 0, 360);
filledarc(get_color(entry->value), NOW, xctx->wire[i].x2, xctx->wire[i].y2,
xctx->cadhalfdotsize, 0, 360);
}
}
}

View File

@ -882,6 +882,7 @@ void move_objects(int what, int merge, double dx, double dy)
xLine ** const line = xctx->line;
xWire * const wire = xctx->wire;
dbg(1, "move_objects: what=%d, dx=%g, dy=%g\n", what, dx, dy);
if(what & START)
{
xctx->rotatelocal=0;

View File

@ -1306,10 +1306,10 @@ void create_ps(char **psfile, int what, int fullzoom, int eps)
}
i = wireptr->n;
if( xctx->wire[i].end1 >1 ) {
ps_drawarc(WIRELAYER, 1, xctx->wire[i].x1, xctx->wire[i].y1, cadhalfdotsize, 0, 360, 0);
ps_drawarc(WIRELAYER, 1, xctx->wire[i].x1, xctx->wire[i].y1, xctx->cadhalfdotsize, 0, 360, 0);
}
if( xctx->wire[i].end2 >1 ) {
ps_drawarc(WIRELAYER, 1, xctx->wire[i].x2, xctx->wire[i].y2, cadhalfdotsize, 0, 360, 0);
ps_drawarc(WIRELAYER, 1, xctx->wire[i].x2, xctx->wire[i].y2, xctx->cadhalfdotsize, 0, 360, 0);
}
}
}

View File

@ -878,10 +878,10 @@ void svg_draw(void)
color = get_color(entry->value);
}
if( xctx->wire[i].end1 >1 ) {
svg_drawcircle(color, 1, xctx->wire[i].x1, xctx->wire[i].y1, cadhalfdotsize, 0, 360);
svg_drawcircle(color, 1, xctx->wire[i].x1, xctx->wire[i].y1, xctx->cadhalfdotsize, 0, 360);
}
if( xctx->wire[i].end2 >1 ) {
svg_drawcircle(color, 1, xctx->wire[i].x2, xctx->wire[i].y2, cadhalfdotsize, 0, 360);
svg_drawcircle(color, 1, xctx->wire[i].x2, xctx->wire[i].y2, xctx->cadhalfdotsize, 0, 360);
}
}
}

View File

@ -579,6 +579,7 @@ static void alloc_xschem_data(const char *top_path, const char *win_path)
xctx->nl_sel = xctx->nl_sem = xctx->nl_dir = 0;
xctx->hilight_time = 0; /* timestamp for sims */
xctx->poly_point_selected = 0;
xctx->hilight_nets = 0;
xctx->hilight_color = 0;
for(i=0;i<CADMAXHIER; ++i) {
@ -1998,8 +1999,8 @@ void change_linewidth(double w)
double cs = tclgetdoublevar("cadsnap");
if(tclgetboolvar("change_lw")) {
xctx->lw=xctx->mooz * 0.09 * cs;
cadhalfdotsize = CADHALFDOTSIZE * (cs < 10. ? cs : 10.) / 10.;
/* cadhalfdotsize = CADHALFDOTSIZE + 0.04 * (cs-10); */
xctx->cadhalfdotsize = CADHALFDOTSIZE * (cs < 10. ? cs : 10.) / 10.;
/* xctx->cadhalfdotsize = CADHALFDOTSIZE + 0.04 * (cs-10); */
}
/* explicitly set line width */
} else {

View File

@ -983,7 +983,7 @@ typedef struct {
Int_hashtable floater_inst_table;
Node_hashentry **node_table;
Hilight_hashentry **hilight_table;
int poly_point_selected;
int hilight_nets;
int hilight_color;
int hilight_time; /* timestamp for sims */
@ -1123,6 +1123,7 @@ typedef struct {
int draw_pixmap; /* pixmap used as 2nd buffer */
int draw_window; /* MIRRORED IN TCL */
int do_copy_area;
double cadhalfdotsize;
time_t time_last_modify;
int undo_type; /* 0: on disk, 1: in memory */
void (*push_undo)(void);