allow launcher style behaviourrt (tclcommand / url attributes) on all objects. Add (shift + but1 click) and Delete (Ctrl+ But1 click) polygon points. fixed some graphical artifacs when adding new object while some selection is present

This commit is contained in:
stefan schippers 2024-03-02 02:29:03 +01:00
parent 9f04c22aa0
commit 9f167f9568
5 changed files with 107 additions and 34 deletions

View File

@ -1715,21 +1715,30 @@ void launcher(void)
{
const char *url;
char program[PATH_MAX];
int n;
int n, c;
char *prop_ptr;
rebuild_selected_array();
tcleval("update");
if(xctx->lastsel ==1 && xctx->sel_array[0].type==ELEMENT)
if(xctx->lastsel ==1)
{
double mx=xctx->mousex, my=xctx->mousey;
/* select_object(mx,my,SELECTED, 0); */
n=xctx->sel_array[0].n;
my_strncpy(program, get_tok_value(xctx->inst[n].prop_ptr,"program",0), S(program)); /* handle backslashes */
url = get_tok_value(xctx->inst[n].prop_ptr,"url",0); /* handle backslashes */
c=xctx->sel_array[0].col;
if (xctx->sel_array[0].type==ELEMENT) prop_ptr = xctx->inst[n].prop_ptr;
else if(xctx->sel_array[0].type==xRECT) prop_ptr = xctx->rect[c][n].prop_ptr;
else if(xctx->sel_array[0].type==POLYGON) prop_ptr = xctx->poly[c][n].prop_ptr;
else if(xctx->sel_array[0].type==ARC) prop_ptr = xctx->arc[c][n].prop_ptr;
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);
if(url[0] || (program[0])) { /* open url with appropriate program */
tclvareval("launcher {", url, "} {", program, "}", NULL);
} else {
my_strncpy(program, get_tok_value(xctx->inst[n].prop_ptr,"tclcommand",0), S(program));
my_strncpy(program, get_tok_value(prop_ptr,"tclcommand",0), S(program));
if(program[0]) { /* execute tcl command */
tcleval(program);
}
@ -2818,12 +2827,13 @@ void draw_stuff(void)
static void restore_selection(double x1, double y1, double x2, double y2)
{
double xx1,yy1,xx2,yy2;
int intlw = 2 * INT_WIDTH(xctx->lw) + (int)xctx->cadhalfdotsize;
xx1 = x1; yy1 = y1; xx2 = x2; yy2 = y2;
RECTORDER(xx1,yy1,xx2,yy2);
rebuild_selected_array();
if(!xctx->lastsel) return;
bbox(START,0.0, 0.0, 0.0, 0.0);
bbox(ADD, xx1-xctx->lw, yy1-xctx->lw, xx2+xctx->lw, yy2+xctx->lw);
bbox(ADD, xx1 - intlw, yy1 - intlw, xx2 + intlw, yy2 + intlw);
bbox(SET,0.0, 0.0, 0.0, 0.0);
draw_selection(xctx->gc[SELLAYER], 0);
bbox(END,0.0, 0.0, 0.0, 0.0);
@ -3106,7 +3116,8 @@ void new_arc(int what, double sweep)
arc_3_points(xctx->nl_x1, xctx->nl_y1, xctx->nl_x2, xctx->nl_y2,
xctx->nl_x3, xctx->nl_y3, &xctx->nl_x, &xctx->nl_y, &xctx->nl_r, &xctx->nl_a, &xctx->nl_b);
if(xctx->nl_sweep_angle==360.) xctx->nl_b=360.;
if(xctx->nl_r>0.) drawtemparc(xctx->gc[xctx->rectcolor], NOW, xctx->nl_x, xctx->nl_y, xctx->nl_r, xctx->nl_a, xctx->nl_b);
if(xctx->nl_r>0.) drawtemparc(xctx->gc[xctx->rectcolor], NOW,
xctx->nl_x, xctx->nl_y, xctx->nl_r, xctx->nl_a, xctx->nl_b);
}
}
}
@ -3264,6 +3275,7 @@ void new_rect(int what)
xctx->nl_xx1=xctx->nl_x1;xctx->nl_yy1=xctx->nl_y1;xctx->nl_xx2=xctx->nl_x2;xctx->nl_yy2=xctx->nl_y2;
RECTORDER(xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2);
drawtemprect(xctx->gctiled,NOW, xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2);
restore_selection(xctx->nl_x1, xctx->nl_y1, xctx->nl_x2, xctx->nl_y2);
xctx->nl_x2=xctx->mousex_snap;xctx->nl_y2=xctx->mousey_snap;
xctx->nl_xx1=xctx->nl_x1;xctx->nl_yy1=xctx->nl_y1;xctx->nl_xx2=xctx->nl_x2;xctx->nl_yy2=xctx->nl_y2;
RECTORDER(xctx->nl_xx1,xctx->nl_yy1,xctx->nl_xx2,xctx->nl_yy2);
@ -3291,11 +3303,16 @@ void new_polygon(int what)
xctx->nl_polyy[xctx->nl_points] = xctx->nl_polyy[xctx->nl_points-1];
/* fprintf(errfp, "added point: %.16g %.16g\n", xctx->nl_polyx[xctx->nl_points-1],
xctx->nl_polyy[xctx->nl_points-1]); */
xctx->nl_x1=xctx->nl_x2=xctx->mousex_snap;xctx->nl_y1=xctx->nl_y2=xctx->mousey_snap;
xctx->ui_state |= STARTPOLYGON;
set_modify(1);
}
if( what & ADD)
{
if(xctx->mousex_snap < xctx->nl_x1) xctx->nl_x1 = xctx->mousex_snap;
if(xctx->mousex_snap > xctx->nl_x2) xctx->nl_x2 = xctx->mousex_snap;
if(xctx->mousey_snap < xctx->nl_y1) xctx->nl_y1 = xctx->mousey_snap;
if(xctx->mousey_snap > xctx->nl_y2) xctx->nl_y2 = xctx->mousey_snap;
/* closed poly */
if(what & END) {
/* delete last rubber */
@ -3333,10 +3350,16 @@ void new_polygon(int what)
}
if(what & RUBBER)
{
if(xctx->mousex_snap < xctx->nl_x1) xctx->nl_x1 = xctx->mousex_snap;
if(xctx->mousex_snap > xctx->nl_x2) xctx->nl_x2 = xctx->mousex_snap;
if(xctx->mousey_snap < xctx->nl_y1) xctx->nl_y1 = xctx->mousey_snap;
if(xctx->mousey_snap > xctx->nl_y2) xctx->nl_y2 = xctx->mousey_snap;
/* fprintf(errfp, "new_poly: RUBBER\n"); */
drawtemppolygon(xctx->gctiled, NOW, xctx->nl_polyx, xctx->nl_polyy, xctx->nl_points+1, 0);
xctx->nl_polyy[xctx->nl_points] = xctx->mousey_snap;
xctx->nl_polyx[xctx->nl_points] = xctx->mousex_snap;
restore_selection(xctx->nl_x1, xctx->nl_y1, xctx->nl_x2, xctx->nl_y2);
/* xctx->nl_x2 = xctx->mousex_snap; xctx->nl_y2 = xctx->mousey_snap; */
drawtemppolygon(xctx->gc[xctx->rectcolor], NOW, xctx->nl_polyx, xctx->nl_polyy, xctx->nl_points+1, 0);
}
}

View File

@ -3134,7 +3134,7 @@ int rstate; /* (reduced state, without ShiftMask) */
break;
}
/* Button1Press to select objects */
if( !(xctx->ui_state & STARTSELECT) && !(xctx->ui_state & STARTWIRE) && !(xctx->ui_state & STARTLINE) ) {
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;
@ -3149,10 +3149,10 @@ int rstate; /* (reduced state, without ShiftMask) */
polygon_c = xctx->sel_array[0].col;
}
/* If no shift was pressed while Button1Press delete selection */
if( !(state & ShiftMask) && !(SET_MODMASK) ) {
if( !(state & (ShiftMask | ControlMask)) && !(SET_MODMASK) ) {
unselect_all(1);
}
/* Check is user is clicking a control point of a polygon */
/* polygon point: Check is user is clicking a control point of a polygon */
if(polygon_n >= 0) {
int i;
double ds = xctx->cadhalfdotsize;
@ -3173,11 +3173,58 @@ int rstate; /* (reduced state, without ShiftMask) */
}
}
if(xctx->poly_point_selected) {
xctx->poly[polygon_c][polygon_n].sel = SELECTED1;
xctx->need_reb_sel_arr=1;
move_objects(START,0,0,0);
}
}
int j;
int c = polygon_c;
int n = polygon_n;
int points = xctx->poly[c][n].points;
/* add a new polygon/bezier point after selected one and start moving it*/
if(state & ShiftMask) {
xctx->push_undo();
points++;
my_realloc(_ALLOC_ID_, &xctx->poly[c][n].x, sizeof(double) * points);
my_realloc(_ALLOC_ID_, &xctx->poly[c][n].y, sizeof(double) * points);
my_realloc(_ALLOC_ID_, &xctx->poly[c][n].selected_point, sizeof(unsigned short) * points);
xctx->poly[c][n].selected_point[i] = 0;
for(j = points - 2; j > i; j--) {
xctx->poly[c][n].x[j + 1] = xctx->poly[c][n].x[j];
xctx->poly[c][n].y[j + 1] = xctx->poly[c][n].y[j];
xctx->poly[c][n].selected_point[j + 1] = xctx->poly[c][n].selected_point[j];
}
xctx->poly[c][n].selected_point[i + 1] = 1;
xctx->poly[c][n].x[i + 1] = xctx->poly[c][n].x[i];
xctx->poly[c][n].y[i + 1] = xctx->poly[c][n].y[i];
xctx->poly[c][n].points = points;
xctx->poly[polygon_c][polygon_n].sel = SELECTED1;
xctx->need_reb_sel_arr=1;
move_objects(START,0,0,0);
}
/* delete polygon/bezier selected point */
else if(points > 2 && state & ControlMask) {
xctx->push_undo();
points--;
for(j = i ; j < points ; j++) {
xctx->poly[c][n].x[j] = xctx->poly[c][n].x[j + 1];
xctx->poly[c][n].y[j] = xctx->poly[c][n].y[j + 1];
xctx->poly[c][n].selected_point[j] = xctx->poly[c][n].selected_point[j + 1];
}
my_realloc(_ALLOC_ID_, &xctx->poly[c][n].x, sizeof(double) * points);
my_realloc(_ALLOC_ID_, &xctx->poly[c][n].y, sizeof(double) * points);
my_realloc(_ALLOC_ID_, &xctx->poly[c][n].selected_point, sizeof(unsigned short) * points);
xctx->poly[c][n].points = points;
xctx->poly[polygon_c][polygon_n].sel = SELECTED;
xctx->need_reb_sel_arr=1;
#ifdef __unix__
draw_selection(xctx->gc[SELLAYER], 0);
#endif
} else if(!(state & (ControlMask | ShiftMask))){
xctx->push_undo();
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) */
} /* if(polygon_n >= 0) */
if(!xctx->poly_point_selected) {
sel = select_object(xctx->mousex, xctx->mousey, SELECTED, 0);
}
@ -3185,24 +3232,22 @@ int rstate; /* (reduced state, without ShiftMask) */
#ifndef __unix__
draw_selection(xctx->gc[SELLAYER], 0);
#endif
if(sel.type && state == ControlMask) {
/* control-click on an instance: execute command */
if(sel.type && state == ControlMask && !xctx->poly_point_selected) {
int savesem = xctx->semaphore;
xctx->semaphore = 0;
launcher();
xctx->semaphore = savesem;
}
if( !(state & ShiftMask) ) {
if(tclgetboolvar("auto_hilight") && xctx->hilight_nets && sel.type == 0 ) {
if(tclgetboolvar("auto_hilight") && !xctx->poly_point_selected) {
if(!(state & ShiftMask) && xctx->hilight_nets && sel.type == 0 ) {
if(!prev_last_sel) {
redraw_hilights(1); /* 1: clear all hilights, then draw */
}
}
}
if(tclgetboolvar("auto_hilight")) {
hilight_net(0);
if(xctx->lastsel) {
redraw_hilights(0);
/* draw_hilight_net(1); */
}
}
break;
@ -3220,6 +3265,7 @@ int rstate; /* (reduced state, without ShiftMask) */
int c = xctx->sel_array[0].col;
move_objects(END,0,0,0);
xctx->poly[c][n].sel = SELECTED;
xctx->poly_point_selected = 0;
for(k=0; k<xctx->poly[c][n].points; ++k) {
xctx->poly[c][n].selected_point[k] = 0;
}

View File

@ -1770,7 +1770,7 @@ void drawpolygon(int c, int what, double *x, double *y, int points, int poly_fil
}
fill = xctx->fill_pattern && xctx->fill_type[c] &&
poly_fill && (x[0] == x[points-1]) && (y[0] == y[points-1]);
bezier = flags && (points > 2);
bezier = (flags & 1) && (points > 2);
if(dash) {
char dash_arr[2];
dash_arr[0] = dash_arr[1] = (char)dash;
@ -1803,6 +1803,8 @@ void drawpolygon(int c, int what, double *x, double *y, int points, int poly_fil
my_free(_ALLOC_ID_, &p);
}
/* flags: bit 0: bezier
* bit 1: draw control point circles */
void drawtemppolygon(GC gc, int what, double *x, double *y, int points, int flags)
{
double x1,y1,x2,y2;
@ -1810,7 +1812,7 @@ void drawtemppolygon(GC gc, int what, double *x, double *y, int points, int flag
XPoint *p;
int i;
short sx, sy;
int bezier;
int bezier, drawpoints;
if(!has_x) return;
polygon_bbox(x, y, points, &x1,&y1,&x2,&y2);
sx1=X_TO_SCREEN(x1);
@ -1819,14 +1821,15 @@ void drawtemppolygon(GC gc, int what, double *x, double *y, int points, int flag
sy2=Y_TO_SCREEN(y2);
if( rectclip(xctx->areax1,xctx->areay1,xctx->areax2,xctx->areay2,&sx1,&sy1,&sx2,&sy2) ) {
bezier = flags && (points > 2);
bezier = (flags & 1) && (points > 2);
drawpoints = (flags & 2);
if((fix_broken_tiled_fill || !_unix) && gc == xctx->gctiled) {
MyXCopyAreaDouble(display, xctx->save_pixmap, xctx->window, xctx->gc[0],
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] || gc == xctx->gctiled ) for(i = 0; i < points; i++) {
if(drawpoints && (gc == xctx->gc[SELLAYER] || gc == xctx->gctiled) ) 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], xctx->cadhalfdotsize, 0., 360.);
@ -4222,7 +4225,7 @@ void draw(void)
if(xctx->enable_layer[c]) for(i=0;i<xctx->polygons[c]; ++i) {
int bezier;
xPoly *p = &xctx->poly[c][i];
bezier = !strboolcmp(get_tok_value(p->prop_ptr, "bezier", 0), "true");
bezier = 2 + !strboolcmp(get_tok_value(p->prop_ptr, "bezier", 0), "true");
drawpolygon(cc, NOW, p->x, p->y, p->points, p->fill, p->dash, bezier);
}
if(use_hash) init_inst_iterator(&ctx, x1, y1, x2, y2);
@ -4400,7 +4403,7 @@ void MyXCopyAreaDouble(Display* display, Drawable src, Drawable dest, GC gc,
double isx1, isy1, isx2, isy2, idx1, idy1;
unsigned int width, height;
int intlw = INT_WIDTH(lw);
dbg(1, "MyXCopyAreaDouble(%g, %g, %g, %g)\n", sx1, sy1, sx2, sy2);
dbg(1, "MyXCopyAreaDouble(%g, %g, %g, %g, intlw=%d)\n", sx1, sy1, sx2, sy2, intlw);
isx1=X_TO_SCREEN(sx1) - 2 * intlw;
isy1=Y_TO_SCREEN(sy1) - 2 * intlw;
isx2=X_TO_SCREEN(sx2) + 2 * intlw;

View File

@ -308,7 +308,7 @@ void draw_selection(GC g, int interruptable)
int bezier;
double *x = my_malloc(_ALLOC_ID_, sizeof(double) *xctx->poly[c][n].points);
double *y = my_malloc(_ALLOC_ID_, sizeof(double) *xctx->poly[c][n].points);
bezier = !strboolcmp(get_tok_value(xctx->poly[c][n].prop_ptr, "bezier", 0), "true");
bezier = 2 + !strboolcmp(get_tok_value(xctx->poly[c][n].prop_ptr, "bezier", 0), "true");
if(xctx->poly[c][n].sel==SELECTED || xctx->poly[c][n].sel==SELECTED1) {
for(k=0;k<xctx->poly[c][n].points; ++k) {
if( xctx->poly[c][n].sel==SELECTED || xctx->poly[c][n].selected_point[k]) {
@ -928,9 +928,10 @@ void move_objects(int what, int merge, double dx, double dy)
int firsti, firstw;
if(xctx->connect_by_kissing == 2) xctx->connect_by_kissing = 0;
/* no undo push for MERGE ad PLACE, already done before */
if( !xctx->kissing && !(xctx->ui_state & (STARTMERGE | PLACE_SYMBOL | PLACE_TEXT)) ) {
dbg(1, "move_objects(): push undo state\n");
/* no undo push for MERGE ad PLACE and polygon point drag, already done before */
if(!xctx->poly_point_selected && !xctx->kissing &&
!(xctx->ui_state & (STARTMERGE | PLACE_SYMBOL | PLACE_TEXT)) ) {
dbg(1, "move_objects(END): push undo state\n");
xctx->push_undo();
}
if((xctx->ui_state & PLACE_SYMBOL)) {

View File

@ -867,7 +867,7 @@ void unselect_all(int dr)
if(xctx->poly[c][i].sel)
{
int k;
int bezier = !strboolcmp(get_tok_value(xctx->poly[c][i].prop_ptr, "bezier", 0), "true");
int bezier = 2 + !strboolcmp(get_tok_value(xctx->poly[c][i].prop_ptr, "bezier", 0), "true");
for(k=0;k<xctx->poly[c][i].points; ++k) xctx->poly[c][i].selected_point[k] = 0;
xctx->poly[c][i].sel = 0;
if(dr) {
@ -1108,7 +1108,7 @@ void select_polygon(int c, int i, unsigned short select_mode, int fast )
my_snprintf(str, S(str), "n=%4d x0 = %.16g y0 = %.16g ...", i, xctx->poly[c][i].x[0], xctx->poly[c][i].y[0]);
statusmsg(str,1);
}
bezier = !strboolcmp(get_tok_value(xctx->poly[c][i].prop_ptr, "bezier", 0), "true");
bezier = 2 + !strboolcmp(get_tok_value(xctx->poly[c][i].prop_ptr, "bezier", 0), "true");
xctx->poly[c][i].sel = select_mode;
if(select_mode) {
drawtemppolygon(xctx->gc[SELLAYER], NOW,