Index: trunk/doc/conf/tree/editor.html =================================================================== --- trunk/doc/conf/tree/editor.html (revision 8371) +++ trunk/doc/conf/tree/editor.html (revision 8372) @@ -43,6 +43,7 @@ description boolean 0 display element description as element name, instead of value name_on_pcb boolean 0 display Reference Designator as element name, instead of value fullscreen boolean 0 hide widgets to make more room for the drawing + move_linepoint_uses_route boolean 0 Moving a line point calculates a new line route. This allows 45/90 line modes when editing lines. route_radius real 0 temporary: route draw helper's arc radius at corners (factor of the trace thickness) click_time integer 0 default time for click expiration, in ms enable_stroke boolean 0 Enable libstroke gestures on middle mouse button when non-zero Index: trunk/src/action_helper.c =================================================================== --- trunk/src/action_helper.c (revision 8371) +++ trunk/src/action_helper.c (revision 8372) @@ -801,6 +801,7 @@ DrawVia(via); pcb_draw(); + pcb_undo_inc_serial(); lastLayer = CURRENT; } else Index: trunk/src/conf_core.h =================================================================== --- trunk/src/conf_core.h (revision 8371) +++ trunk/src/conf_core.h (revision 8372) @@ -56,6 +56,7 @@ CFT_BOOLEAN description; /* display element description as element name, instead of value */ CFT_BOOLEAN name_on_pcb; /* display Reference Designator as element name, instead of value */ CFT_BOOLEAN fullscreen; /* hide widgets to make more room for the drawing */ + CFT_BOOLEAN move_linepoint_uses_route; /* Moving a line point calculates a new line route. This allows 45/90 line modes when editing lines. */ CFT_REAL route_radius; /* temporary: route draw helper's arc radius at corners (factor of the trace thickness) */ CFT_INTEGER click_time; /* default time for click expiration, in ms */ Index: trunk/src/crosshair.c =================================================================== --- trunk/src/crosshair.c (revision 8371) +++ trunk/src/crosshair.c (revision 8372) @@ -456,20 +456,43 @@ case PCB_TYPE_LINE_POINT: { pcb_line_t *line; - pcb_point_t *point1,*point2; + pcb_point_t *point,*point1,point2; line = (pcb_line_t *) pcb_crosshair.AttachedObject.Ptr2; - point1 = (pcb_point_t *) pcb_crosshair.AttachedObject.Ptr3; - point2 = (point1 == &line->Point1 ? &line->Point2 : &line->Point1); - - XORDrawAttachedLine(point1->X + dx, point1->Y + dy, point2->X, point2->Y, line->Thickness); + point = (pcb_point_t *) pcb_crosshair.AttachedObject.Ptr3; + point1 = (point == &line->Point1 ? &line->Point2 : &line->Point1); + point2 = *point; + point2.X += dx; + point2.Y += dy; - /* Draw the DRC outline if it is enabled */ - if (conf_core.editor.show_drc) { - pcb_gui->set_color(pcb_crosshair.GC, conf_core.appearance.color.cross); - XORDrawAttachedLine(point1->X + dx, point1->Y + dy, point2->X, point2->Y,line->Thickness + 2 * (PCB->Bloat + 1) ); - pcb_gui->set_color(pcb_crosshair.GC, conf_core.appearance.color.crosshair); + if(conf_core.editor.move_linepoint_uses_route == 0) {/* config setting for selecting new 45/90 method */ + XORDrawAttachedLine(point1->X, point1->Y, point2.X, point2.Y, line->Thickness); + + /* Draw the DRC outline if it is enabled */ + if (conf_core.editor.show_drc) { + pcb_gui->set_color(pcb_crosshair.GC, conf_core.appearance.color.cross); + XORDrawAttachedLine(point1->X, point1->Y, point2.X, point2.Y,line->Thickness + 2 * (PCB->Bloat + 1) ); + pcb_gui->set_color(pcb_crosshair.GC, conf_core.appearance.color.crosshair); + } } + else { + pcb_route_t route; + pcb_route_init(&route); + pcb_route_calculate( PCB, + &route, + point1, + &point2, + pcb_layer_id(PCB->Data,(pcb_layer_t *)pcb_crosshair.AttachedObject.Ptr1), + line->Thickness, + line->Clearance, + line->Flags, + pcb_gui->shift_is_pressed(), + pcb_gui->control_is_pressed() ); + pcb_route_draw(&route,pcb_crosshair.GC); + if (conf_core.editor.show_drc) + pcb_route_draw_drc(&route,pcb_crosshair.GC); + pcb_route_destroy(&route); + } break; } Index: trunk/src/move.c =================================================================== --- trunk/src/move.c (revision 8371) +++ trunk/src/move.c (revision 8372) @@ -149,6 +149,9 @@ ptr2 = MoveLinePoint(&ctx2, Ptr1, line, &line->Point2); } /* Otherwise make a normal move */ + else if(Type == PCB_TYPE_LINE_POINT) { + ptr2 = MoveLinePointWithRoute(&ctx1, Ptr1, Ptr2, Ptr3); + } else { pcb_undo_add_obj_to_move(Type, Ptr1, Ptr2, Ptr3, DX, DY); ptr2 = pcb_object_operation(&MoveFunctions, &ctx1, Type, Ptr1, Ptr2, Ptr3); Index: trunk/src/obj_line.c =================================================================== --- trunk/src/obj_line.c (revision 8371) +++ trunk/src/obj_line.c (revision 8372) @@ -475,6 +475,48 @@ } } + + +/* moves one end of a line */ +void *MoveLinePointWithRoute(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line, pcb_point_t *Point) +{ + if((conf_core.editor.move_linepoint_uses_route == 0) || !Layer) { + return MoveLinePoint(ctx,Layer,Line,Point); + } + else { + /* Move with Route Code */ + pcb_route_t route; + pcb_point_t point1 = (&Line->Point1 == Point ? Line->Point2 : Line->Point1); + pcb_point_t point2 = *Point; + pcb_coord_t thickness = Line->Thickness; + pcb_coord_t clearance = Line->Clearance; + pcb_flag_t flags = Line->Flags; + + point2.X += ctx->move.dx; + point2.Y += ctx->move.dy; + + if((point1.X != point2.X) || (point1.Y != point2.Y)) { + /* Calculate the new line route and add apply it */ + pcb_route_init(&route); + pcb_route_calculate(PCB, + &route, + &point1, + &point2, + pcb_layer_id(PCB->Data,Layer), + thickness, + clearance, + flags, + pcb_gui->shift_is_pressed(), + pcb_gui->control_is_pressed() ); + pcb_route_apply_to_line(&route,Layer,Line); + pcb_route_destroy(&route); + } + + pcb_draw(); + } + return NULL; +} + /* moves a line between layers; lowlevel routines */ void *MoveLineToLayerLowLevel(pcb_opctx_t *ctx, pcb_layer_t * Source, pcb_line_t * line, pcb_layer_t * Destination) { Index: trunk/src/obj_line.h =================================================================== --- trunk/src/obj_line.h (revision 8371) +++ trunk/src/obj_line.h (revision 8372) @@ -90,7 +90,6 @@ pcb_line_bbox(__l__); \ } while(0) - #define PCB_LINE_LOOP(layer) do { \ pcb_line_t *line; \ gdl_iterator_t __it__; \ Index: trunk/src/obj_line_drcenf.c =================================================================== --- trunk/src/obj_line_drcenf.c (revision 8371) +++ trunk/src/obj_line_drcenf.c (revision 8372) @@ -45,7 +45,11 @@ void pcb_line_adjust_attached(void) { pcb_attached_line_t *line = &pcb_crosshair.AttachedLine; + int flags = conf_core.editor.clear_line ? PCB_FLAG_CLEARLINE : 0; + if (conf_core.editor.auto_drc && (pcb_layer_flags(PCB,pcb_layer_id(PCB->Data, CURRENT)) & PCB_LYT_COPPER)) + flags |= PCB_FLAG_FOUND; + /* I need at least one point */ if (line->State == PCB_CH_STATE_FIRST) return; @@ -67,7 +71,8 @@ &line->Point2, pcb_layer_id(PCB->Data, CURRENT), conf_core.design.line_thickness, - conf_core.design.clearance, + conf_core.design.clearance * 2, + pcb_flag_make(flags), pcb_gui->shift_is_pressed(), pcb_gui->control_is_pressed() ); Index: trunk/src/obj_line_op.h =================================================================== --- trunk/src/obj_line_op.h (revision 8371) +++ trunk/src/obj_line_op.h (revision 8372) @@ -40,6 +40,7 @@ void *CopyLine(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); void *MoveLine(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); void *MoveLinePoint(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line, pcb_point_t *Point); +void *MoveLinePointWithRoute(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line, pcb_point_t *Point); void *MoveLineToLayerLowLevel(pcb_opctx_t *ctx, pcb_layer_t * Source, pcb_line_t * line, pcb_layer_t * Destination); void *MoveLineToLayer(pcb_opctx_t *ctx, pcb_layer_t * Layer, pcb_line_t * Line); void *DestroyLine(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); Index: trunk/src/pcb-conf.lht =================================================================== --- trunk/src/pcb-conf.lht (revision 8371) +++ trunk/src/pcb-conf.lht (revision 8372) @@ -80,6 +80,7 @@ } undo_warning_size = 1024 fullscreen = 0 + move_linepoint_uses_route = 0 } # editor ha:rc { Index: trunk/src/route.c =================================================================== --- trunk/src/route.c (revision 8371) +++ trunk/src/route.c (revision 8372) @@ -35,7 +35,10 @@ #include "undo.h" #include "obj_line_draw.h" #include "obj_arc_draw.h" +#include "obj_line.h" +#include "obj_line_op.h" + void pcb_route_init(pcb_route_t * p_route) { @@ -137,7 +140,8 @@ pcb_point_t * point2, pcb_layer_id_t layer, pcb_coord_t thickness, - pcb_coord_t clearance ) + pcb_coord_t clearance, + pcb_flag_t flags ) { pcb_route_reset(route); route->start_point = *point1; @@ -147,6 +151,7 @@ route->thickness = thickness; route->clearance = clearance; route->PCB = PCB; + route->flags = flags; pcb_route_add_line(route,point1,point2,layer); } @@ -312,7 +317,8 @@ pcb_point_t * point2, pcb_layer_id_t layer_id, pcb_coord_t thickness, - pcb_coord_t clearance, + pcb_coord_t clearance, + pcb_flag_t flags, int mod1, int mod2 ) { @@ -326,7 +332,7 @@ /* If the line can be drawn directly to the target then add a single line segment. */ if(PCB->RatDraw || conf_core.editor.all_direction_lines) { - pcb_route_direct(PCB,route,point1,point2,layer_id,thickness,clearance); + pcb_route_direct(PCB,route,point1,point2,layer_id,thickness,clearance,flags); return; } @@ -338,6 +344,7 @@ route->start_layer = layer_id; route->end_layer = layer_id; route->PCB = PCB; + route->flags = flags; /* If Refraction is 0 then add a single line segment that is horizontal, vertical or 45 degrees. * This line segment might not end under the crosshair. @@ -401,8 +408,10 @@ route->end_point = *point2; } else { - pcb_route_add_line(route,point1,&target,layer_id); - pcb_route_add_line(route,&target,point2,layer_id); + if((point1->X != target.X) || (point1->Y != target.Y)) + pcb_route_add_line(route,point1,&target,layer_id); + if((point2->X != target.X) || (point2->Y != target.Y)) + pcb_route_add_line(route,&target,point2,layer_id); route->end_point = *point2; } } @@ -411,9 +420,16 @@ int pcb_route_apply(const pcb_route_t * p_route) { + return pcb_route_apply_to_line(p_route,NULL,NULL); +} +int +pcb_route_apply_to_line(const pcb_route_t * p_route,pcb_layer_t * apply_to_line_layer,pcb_line_t * apply_to_line) +{ + int i; int applied = 0; + char * number = (apply_to_line ? apply_to_line->Number : NULL); for( i=0;isize;i++) { pcb_route_object_t const * p_obj = &p_route->objects[i]; @@ -422,7 +438,49 @@ switch(p_obj->type) { case PCB_TYPE_LINE : - { + /* If the route is being applied to an existing line then the existing + line will be used as the first line in the route. This maintains the + ID of the line and line points. This is especially useful if the + route contains a single line. + */ + if(apply_to_line) { + /* Move the existing line points to the position of the route line. */ + if((p_obj->point1.X != apply_to_line->Point1.X) || (p_obj->point1.Y != apply_to_line->Point1.Y)) + pcb_undo_add_obj_to_move( PCB_TYPE_LINE_POINT, + apply_to_line_layer, + apply_to_line, + &apply_to_line->Point1, + p_obj->point1.X - apply_to_line->Point1.X, + p_obj->point1.Y - apply_to_line->Point1.Y ); + + if((p_obj->point2.X != apply_to_line->Point2.X) || (p_obj->point2.Y != apply_to_line->Point2.Y)) + pcb_undo_add_obj_to_move( PCB_TYPE_LINE_POINT, + apply_to_line_layer, + apply_to_line, + &apply_to_line->Point2, + p_obj->point2.X - apply_to_line->Point2.X, + p_obj->point2.Y - apply_to_line->Point2.Y ); + + /* Move the existing line point/s */ + EraseLine(apply_to_line); + pcb_r_delete_entry(apply_to_line_layer->line_tree, (pcb_box_t *) apply_to_line); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_LINE, apply_to_line_layer, apply_to_line); + apply_to_line->Point1.X = p_obj->point1.X; + apply_to_line->Point1.Y = p_obj->point1.Y; + apply_to_line->Point2.X = p_obj->point2.X; + apply_to_line->Point2.Y = p_obj->point2.Y; + pcb_line_bbox(apply_to_line); + pcb_r_insert_entry(layer->line_tree, (pcb_box_t *) apply_to_line, 0); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_LINE, layer, apply_to_line); + DrawLine(layer, apply_to_line); + apply_to_line_layer = layer; + + /* The existing line has been used so forget about it. */ + apply_to_line = NULL; + applied = 1; + } + else { + /* Create a new line */ pcb_line_t * line = pcb_line_new_merge( layer, p_obj->point1.X, p_obj->point1.Y, @@ -429,14 +487,15 @@ p_obj->point2.X, p_obj->point2.Y, p_route->thickness, - 2 * p_route->clearance, - pcb_flag_make(PCB_FLAG_CLEARLINE) ); + p_route->clearance, + p_route->flags ); if(line) { + if(number) + line->Number = pcb_strdup(number); pcb_added_lines++; pcb_obj_add_attribs(line, PCB->pen_attr); + DrawLine(layer, line); pcb_undo_add_obj_to_create(PCB_TYPE_LINE, layer, line, line); - DrawLine(layer, line); - pcb_undo_inc_serial(); applied = 1; } } @@ -444,6 +503,7 @@ case PCB_TYPE_ARC : { + /* Create a new arc */ pcb_arc_t * arc = pcb_arc_new( layer, p_obj->point1.X, p_obj->point1.Y, @@ -452,13 +512,12 @@ p_obj->start_angle, p_obj->delta_angle, p_route->thickness, - 2 * p_route->clearance, - pcb_flag_make(PCB_FLAG_CLEARLINE) ); + p_route->clearance, + p_route->flags ); if(arc) { pcb_added_lines++; pcb_obj_add_attribs(arc, PCB->pen_attr); pcb_undo_add_obj_to_create(PCB_TYPE_ARC, layer, arc, arc); - pcb_undo_inc_serial(); DrawArc(layer, arc); applied = 1; } @@ -469,6 +528,12 @@ break; } } + + /* If the existing apply-to-line wasn't updated then it should be deleted */ + /* (This can happen if the route does not contain any lines.) */ + if(apply_to_line != NULL) + pcb_line_destroy(apply_to_line_layer,apply_to_line); + return applied; } Index: trunk/src/route.h =================================================================== --- trunk/src/route.h (revision 8371) +++ trunk/src/route.h (revision 8372) @@ -50,6 +50,7 @@ pcb_layer_id_t start_layer; /* The ID of the layer that the route started on */ pcb_layer_id_t end_layer; /* The ID of the layer that the route ended on, usually the same as the start for simple routes*/ pcb_board_t * PCB; + pcb_flag_t flags; int size; /* The number of active objects in the array */ int capacity; /* The size of the object array */ pcb_route_object_t * objects; /* Pointer to the object array data */ @@ -82,8 +83,10 @@ pcb_layer_id_t layer_id, pcb_coord_t thickness, pcb_coord_t clearance, + pcb_flag_t flags, int mod1, int mod2 ); + void pcb_route_direct( pcb_board_t * PCB, pcb_route_t * p_route, pcb_point_t * point1, @@ -90,9 +93,11 @@ pcb_point_t * point2, pcb_layer_id_t layer, pcb_coord_t thickness, - pcb_coord_t clearance ); + pcb_coord_t clearance, + pcb_flag_t flags ); int pcb_route_apply(const pcb_route_t * p_route); +int pcb_route_apply_to_line(const pcb_route_t * p_route,pcb_layer_t * Layer,pcb_line_t * apply_to_line); void pcb_route_draw( pcb_route_t * p_route,pcb_hid_gc_t GC ); void pcb_route_draw_drc( pcb_route_t * p_route,pcb_hid_gc_t GC ); Index: trunk/src_plugins/rubberband_orig/rubberband.c =================================================================== --- trunk/src_plugins/rubberband_orig/rubberband.c (revision 8371) +++ trunk/src_plugins/rubberband_orig/rubberband.c (revision 8372) @@ -760,8 +760,7 @@ while (rbnd->RubberbandN) { /* first clear any marks that we made in the line flags */ PCB_FLAG_CLEAR(PCB_FLAG_RUBBEREND, ptr->Line); - pcb_undo_add_obj_to_move(PCB_TYPE_LINE_POINT, ptr->Layer, ptr->Line, ptr->MovedPoint, DX, DY); - MoveLinePoint(ctx[0], ptr->Layer, ptr->Line, ptr->MovedPoint); + MoveLinePointWithRoute(ctx[0], ptr->Layer, ptr->Line, ptr->MovedPoint); rbnd->RubberbandN--; ptr++; } @@ -818,13 +817,41 @@ } if ((x1 != x2) || (y1 != y2)) { - XORDrawAttachedLine(x1,y1,x2,y2, ptr->Line->Thickness); - /* Draw the DRC outline if it is enabled */ - if (conf_core.editor.show_drc) { - pcb_gui->set_color(pcb_crosshair.GC, conf_core.appearance.color.cross); - XORDrawAttachedLine(x1,y1,x2,y2,ptr->Line->Thickness + 2 * (PCB->Bloat + 1) ); - pcb_gui->set_color(pcb_crosshair.GC, conf_core.appearance.color.crosshair); + if(conf_core.editor.move_linepoint_uses_route == 0) { + XORDrawAttachedLine(x1,y1,x2,y2, ptr->Line->Thickness); + /* Draw the DRC outline if it is enabled */ + if (conf_core.editor.show_drc) { + pcb_gui->set_color(pcb_crosshair.GC, conf_core.appearance.color.cross); + XORDrawAttachedLine(x1,y1,x2,y2,ptr->Line->Thickness + 2 * (PCB->Bloat + 1) ); + pcb_gui->set_color(pcb_crosshair.GC, conf_core.appearance.color.crosshair); + } } + else { + pcb_point_t point1; + pcb_point_t point2; + pcb_route_t route; + + point1.X = x1; + point1.Y = y1; + point2.X = x2; + point2.Y = y2; + + pcb_route_init(&route); + pcb_route_calculate( PCB, + &route, + &point1, + &point2, + pcb_layer_id(PCB->Data,ptr->Layer), + ptr->Line->Thickness, + ptr->Line->Clearance, + ptr->Line->Flags, + pcb_gui->shift_is_pressed(), + pcb_gui->control_is_pressed() ); + pcb_route_draw(&route,pcb_crosshair.GC); + if (conf_core.editor.show_drc) + pcb_route_draw_drc(&route,pcb_crosshair.GC); + pcb_route_destroy(&route); + } } }