/**************************************/ /* edit.cpp: edit PCB implementation. */ /**************************************/ #include "fctsys.h" #include "appl_wxstruct.h" #include "class_drawpanel.h" #include "confirm.h" #include "eda_doc.h" #include "gestfich.h" #include "pcbnew_id.h" #include "pcbnew.h" #include "wxPcbStruct.h" #include "module_editor_frame.h" #include "class_board_design_settings.h" #include "protos.h" #include "dialog_drc.h" #include "kicad_device_context.h" #include "dialog_global_edit_tracks_and_vias.h" // Uncomment following line to enable wxBell() command (which beeps speaker) // #include static void Process_Move_Item( PCB_EDIT_FRAME* frame, EDA_ITEM* DrawStruct, wxDC* DC ); /* Handles the selection of command events. */ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) { int id = event.GetId(); wxPoint pos; int itmp; INSTALL_UNBUFFERED_DC( dc, DrawPanel ); BOARD_ITEM* DrawStruct = GetCurItem(); MODULE* module; DrawPanel->CrossHairOff( &dc ); wxGetMousePosition( &pos.x, &pos.y ); pos.y += 20; switch( id ) // Some (not all ) edit commands must be finished or aborted { case wxID_CUT: case wxID_COPY: case ID_PCB_USER_GRID_SETUP: case ID_TOOLBARH_PCB_SELECT_LAYER: case ID_AUX_TOOLBAR_PCB_SELECT_LAYER_PAIR: case ID_POPUP_PCB_ROTATE_TEXTEPCB: case ID_POPUP_PCB_EDIT_TEXTEPCB: case ID_POPUP_PCB_EDIT_MIRE: case ID_POPUP_PCB_ROTATE_TEXTMODULE: case ID_POPUP_PCB_ROTATE_MODULE_CLOCKWISE: case ID_POPUP_PCB_ROTATE_MODULE_COUNTERCLOCKWISE: case ID_POPUP_PCB_CHANGE_SIDE_MODULE: case ID_POPUP_PCB_EDIT_MODULE: case ID_POPUP_PCB_EDIT_TEXTMODULE: case ID_POPUP_PCB_STOP_CURRENT_DRAWING: case ID_POPUP_PCB_END_TRACK: case ID_POPUP_PCB_PLACE_VIA: case ID_POPUP_PCB_SWITCH_TRACK_POSTURE: case ID_POPUP_PCB_PLACE_MICROVIA: case ID_POPUP_PCB_IMPORT_PAD_SETTINGS: case ID_POPUP_PCB_EXPORT_PAD_SETTINGS: case ID_POPUP_PCB_GLOBAL_IMPORT_PAD_SETTINGS: case ID_POPUP_PCB_STOP_CURRENT_EDGE_ZONE: case ID_POPUP_PCB_DELETE_ZONE_LAST_CREATED_CORNER: case ID_POPUP_PCB_FILL_ALL_ZONES: case ID_POPUP_PCB_REMOVE_FILLED_AREAS_IN_ALL_ZONES: case ID_POPUP_PCB_REMOVE_FILLED_AREAS_IN_CURRENT_ZONE: case ID_POPUP_PCB_PLACE_ZONE_CORNER: case ID_POPUP_PCB_PLACE_ZONE_OUTLINES: case ID_POPUP_PCB_EDIT_ZONE_PARAMS: case ID_POPUP_PCB_DELETE_ZONE: case ID_POPUP_PCB_MOVE_ZONE_CORNER: case ID_POPUP_PCB_DRAG_ZONE_OUTLINE_SEGMENT: case ID_POPUP_PCB_MOVE_ZONE_OUTLINES: case ID_POPUP_PCB_ADD_ZONE_CORNER: case ID_POPUP_PCB_DELETE_TRACKSEG: case ID_POPUP_PCB_DELETE_TRACK: case ID_POPUP_PCB_DELETE_TRACKNET: case ID_POPUP_PCB_FILL_ZONE: case ID_POPUP_PCB_SELECT_LAYER: case ID_POPUP_PCB_SELECT_CU_LAYER: case ID_POPUP_PCB_SELECT_LAYER_PAIR: case ID_POPUP_PCB_SELECT_NO_CU_LAYER: case ID_POPUP_PCB_MOVE_TRACK_NODE: case ID_POPUP_PCB_DRAG_TRACK_SEGMENT_KEEP_SLOPE: case ID_POPUP_PCB_DRAG_TRACK_SEGMENT: case ID_POPUP_PCB_MOVE_TRACK_SEGMENT: case ID_POPUP_PCB_PLACE_MOVED_TRACK_NODE: case ID_POPUP_PCB_BREAK_TRACK: case ID_POPUP_PCB_EDIT_NET: case ID_POPUP_PCB_EDIT_TRACK: case ID_POPUP_PCB_EDIT_TRACKSEG: case ID_POPUP_PCB_LOCK_ON_TRACKSEG: case ID_POPUP_PCB_LOCK_OFF_TRACKSEG: case ID_POPUP_PCB_LOCK_ON_TRACK: case ID_POPUP_PCB_LOCK_OFF_TRACK: case ID_POPUP_PCB_LOCK_ON_NET: case ID_POPUP_PCB_LOCK_OFF_NET: case ID_POPUP_DELETE_BLOCK: case ID_POPUP_PLACE_BLOCK: case ID_POPUP_ZOOM_BLOCK: case ID_POPUP_FLIP_BLOCK: case ID_POPUP_ROTATE_BLOCK: case ID_POPUP_COPY_BLOCK: case ID_POPUP_PCB_EDIT_DRAWING: case ID_POPUP_PCB_GETINFO_MARKER: break; case ID_POPUP_CANCEL_CURRENT_COMMAND: if( DrawPanel->IsMouseCaptured() ) { DrawPanel->EndMouseCapture(); } /* Should not be executed, just in case */ if( GetScreen()->m_BlockLocate.m_Command != BLOCK_IDLE ) { GetScreen()->m_BlockLocate.m_Command = BLOCK_IDLE; GetScreen()->m_BlockLocate.m_State = STATE_NO_BLOCK; GetScreen()->m_BlockLocate.ClearItemsList(); } if( GetToolId() == ID_NO_TOOL_SELECTED ) SetToolID( ID_NO_TOOL_SELECTED, DrawPanel->GetDefaultCursor(), wxEmptyString ); else SetCursor( DrawPanel->GetDefaultCursor() ); break; default: // Finish (abort) the command if( DrawPanel->IsMouseCaptured() ) DrawPanel->m_endMouseCaptureCallback( DrawPanel, &dc ); if( GetToolId() != id ) { if( m_ID_last_state != GetToolId() ) m_ID_last_state = GetToolId(); SetToolID( ID_NO_TOOL_SELECTED, DrawPanel->GetDefaultCursor(), wxEmptyString ); } break; } switch( id ) // Execute command { case 0: break; case ID_OPEN_MODULE_EDITOR: if( m_ModuleEditFrame == NULL ) { m_ModuleEditFrame = new FOOTPRINT_EDIT_FRAME( this, _( "Module Editor" ), wxPoint( -1, -1 ), wxSize( 600, 400 ) ); m_ModuleEditFrame->Show( true ); m_ModuleEditFrame->Zoom_Automatique( false ); } else { if( m_ModuleEditFrame->IsIconized() ) m_ModuleEditFrame->Iconize( false ); m_ModuleEditFrame->Raise(); // Raising the window does not set the focus on Linux. This should work on // any platform. if( wxWindow::FindFocus() != m_ModuleEditFrame ) m_ModuleEditFrame->SetFocus(); } break; case ID_PCB_GLOBAL_DELETE: InstallPcbGlobalDeleteFrame( pos ); break; case ID_POPUP_PLACE_BLOCK: GetScreen()->m_BlockLocate.m_Command = BLOCK_MOVE; DrawPanel->m_AutoPAN_Request = false; HandleBlockPlace( &dc ); break; case ID_POPUP_COPY_BLOCK: GetScreen()->m_BlockLocate.m_Command = BLOCK_COPY; GetScreen()->m_BlockLocate.SetMessageBlock( this ); DrawPanel->m_AutoPAN_Request = false; HandleBlockPlace( &dc ); break; case ID_POPUP_ZOOM_BLOCK: GetScreen()->m_BlockLocate.m_Command = BLOCK_ZOOM; GetScreen()->m_BlockLocate.SetMessageBlock( this ); GetScreen()->m_BlockLocate.SetMessageBlock( this ); HandleBlockEnd( &dc ); break; case ID_POPUP_DELETE_BLOCK: GetScreen()->m_BlockLocate.m_Command = BLOCK_DELETE; GetScreen()->m_BlockLocate.SetMessageBlock( this ); HandleBlockEnd( &dc ); break; case ID_POPUP_ROTATE_BLOCK: GetScreen()->m_BlockLocate.m_Command = BLOCK_ROTATE; GetScreen()->m_BlockLocate.SetMessageBlock( this ); HandleBlockEnd( &dc ); break; case ID_POPUP_FLIP_BLOCK: GetScreen()->m_BlockLocate.m_Command = BLOCK_FLIP; GetScreen()->m_BlockLocate.SetMessageBlock( this ); HandleBlockEnd( &dc ); break; case ID_DRC_CONTROL: m_drc->ShowDialog(); break; case ID_GET_NETLIST: InstallNetlistFrame( &dc ); break; case ID_GET_TOOLS: // InstalloolsFrame(this, wxPoint(-1,-1) ); break; case ID_FIND_ITEMS: InstallFindFrame( pos, &dc ); break; case ID_POPUP_CLOSE_CURRENT_TOOL: SetToolID( ID_NO_TOOL_SELECTED, DrawPanel->GetDefaultCursor(), wxEmptyString ); break; case ID_POPUP_CANCEL_CURRENT_COMMAND: break; case ID_POPUP_PCB_END_LINE: DrawPanel->MoveCursorToCrossHair(); // EndSegment(&dc); break; case ID_POPUP_PCB_EDIT_TRACK: if( GetCurItem() == NULL ) break; Edit_Track_Width( &dc, (TRACK*) GetCurItem() ); DrawPanel->MoveCursorToCrossHair(); OnModify(); break; case ID_POPUP_PCB_EDIT_TRACKSEG: if( GetCurItem() == NULL ) break; Edit_TrackSegm_Width( &dc, (TRACK*) GetCurItem() ); DrawPanel->MoveCursorToCrossHair(); OnModify(); break; case ID_POPUP_PCB_EDIT_ALL_VIAS_AND_TRACK_SIZE: if( GetCurItem() == NULL ) break; { int type = GetCurItem()->Type(); if( type == TYPE_TRACK || type == TYPE_VIA ) { BOARD_CONNECTED_ITEM*item = (BOARD_CONNECTED_ITEM*) GetCurItem(); DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS dlg( this, item->GetNet() ); dlg.ShowModal(); } } DrawPanel->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_END_TRACK: DrawPanel->MoveCursorToCrossHair(); End_Route( (TRACK*) GetCurItem(), &dc ); break; case ID_POPUP_PCB_PLACE_MOVED_TRACK_NODE: DrawPanel->MoveCursorToCrossHair(); if( GetCurItem()->m_Flags & IS_DRAGGED ) { PlaceDraggedOrMovedTrackSegment( (TRACK*) GetCurItem(), &dc ); } break; case ID_POPUP_PCB_SWITCH_TRACK_POSTURE: /* change the position of initial segment when creating new tracks * switch from _/ to -\ . * If a track is in progress, it will be redrawn */ if( DrawPanel->m_mouseCaptureCallback == ShowNewTrackWhenMovingCursor ) ShowNewTrackWhenMovingCursor( DrawPanel, &dc, wxDefaultPosition, false ); g_Alternate_Track_Posture = !g_Alternate_Track_Posture; if( DrawPanel->m_mouseCaptureCallback == ShowNewTrackWhenMovingCursor ) ShowNewTrackWhenMovingCursor( DrawPanel, &dc, wxDefaultPosition, false ); break; case ID_POPUP_PCB_PLACE_MICROVIA: if( !IsMicroViaAcceptable() ) break; case ID_POPUP_PCB_PLACE_VIA: DrawPanel->MoveCursorToCrossHair(); if( GetCurItem()->m_Flags & IS_DRAGGED ) { PlaceDraggedOrMovedTrackSegment( (TRACK*) GetCurItem(), &dc ); } else { int v_type = GetBoard()->GetBoardDesignSettings()->m_CurrentViaType; // place micro via and switch layer. if( id == ID_POPUP_PCB_PLACE_MICROVIA ) GetBoard()->GetBoardDesignSettings()->m_CurrentViaType = VIA_MICROVIA; Other_Layer_Route( (TRACK*) GetCurItem(), &dc ); GetBoard()->GetBoardDesignSettings()->m_CurrentViaType = v_type; if( DisplayOpt.ContrastModeDisplay ) DrawPanel->Refresh(); } break; case ID_POPUP_PCB_DELETE_TRACKSEG: if( GetCurItem() == NULL ) break; DrawPanel->MoveCursorToCrossHair(); SetCurItem( Delete_Segment( &dc, (TRACK*) GetCurItem() ) ); OnModify(); break; case ID_POPUP_PCB_DELETE_TRACK: if( GetCurItem() == NULL ) break; DrawPanel->MoveCursorToCrossHair(); Delete_Track( &dc, (TRACK*) GetCurItem() ); SetCurItem( NULL ); OnModify(); break; case ID_POPUP_PCB_DELETE_TRACKNET: DrawPanel->MoveCursorToCrossHair(); Delete_net( &dc, (TRACK*) GetCurItem() ); SetCurItem( NULL ); OnModify(); break; case ID_POPUP_PCB_LOCK_ON_TRACKSEG: Attribut_Segment( (TRACK*) GetCurItem(), &dc, true ); break; case ID_POPUP_PCB_LOCK_OFF_TRACKSEG: Attribut_Segment( (TRACK*) GetCurItem(), &dc, false ); break; case ID_POPUP_PCB_LOCK_ON_TRACK: Attribut_Track( (TRACK*) GetCurItem(), &dc, true ); break; case ID_POPUP_PCB_LOCK_OFF_TRACK: Attribut_Track( (TRACK*) GetCurItem(), &dc, false ); break; case ID_POPUP_PCB_LOCK_ON_NET: Attribut_net( &dc, ( (TRACK*) GetCurItem() )->GetNet(), true ); break; case ID_POPUP_PCB_LOCK_OFF_NET: Attribut_net( &dc, ( (TRACK*) GetCurItem() )->GetNet(), false ); break; case ID_POPUP_PCB_SETFLAGS_TRACK_MNU: break; case ID_POPUP_PCB_DELETE_ZONE: DrawPanel->MoveCursorToCrossHair(); if( GetCurItem() == NULL ) break; { SEGZONE* zsegm = (SEGZONE*) GetCurItem(); int netcode = zsegm->GetNet(); Delete_OldZone_Fill( zsegm ); SetCurItem( NULL ); TestNetConnection( NULL, netcode ); OnModify(); GetBoard()->DisplayInfo( this ); } break; case ID_POPUP_PCB_EDIT_ZONE_PARAMS: Edit_Zone_Params( &dc, (ZONE_CONTAINER*) GetCurItem() ); SetCurItem( NULL ); // Outlines can have changed break; case ID_POPUP_PCB_ZONE_ADD_SIMILAR_ZONE: DrawPanel->MoveCursorToCrossHair(); DrawPanel->m_AutoPAN_Request = true; Add_Similar_Zone( &dc, (ZONE_CONTAINER*) GetCurItem() ); break; case ID_POPUP_PCB_ZONE_ADD_CUTOUT_ZONE: DrawPanel->MoveCursorToCrossHair(); DrawPanel->m_AutoPAN_Request = true; Add_Zone_Cutout( &dc, (ZONE_CONTAINER*) GetCurItem() ); break; case ID_POPUP_PCB_DELETE_ZONE_CONTAINER: case ID_POPUP_PCB_DELETE_ZONE_CUTOUT: DrawPanel->MoveCursorToCrossHair(); { int netcode = ( (ZONE_CONTAINER*) GetCurItem() )->GetNet(); Delete_Zone_Contour( &dc, (ZONE_CONTAINER*) GetCurItem() ); SetCurItem( NULL ); TestNetConnection( NULL, netcode ); GetBoard()->DisplayInfo( this ); } break; case ID_POPUP_PCB_DELETE_ZONE_CORNER: Remove_Zone_Corner( &dc, (ZONE_CONTAINER*) GetCurItem() ); SetCurItem( NULL ); break; case ID_POPUP_PCB_MOVE_ZONE_CORNER: { DrawPanel->MoveCursorToCrossHair(); ZONE_CONTAINER* zone_cont = (ZONE_CONTAINER*) GetCurItem(); DrawPanel->m_AutoPAN_Request = true; Start_Move_Zone_Corner( &dc, zone_cont, zone_cont->m_CornerSelection, false ); break; } case ID_POPUP_PCB_DRAG_ZONE_OUTLINE_SEGMENT: { DrawPanel->MoveCursorToCrossHair(); ZONE_CONTAINER* zone_cont = (ZONE_CONTAINER*) GetCurItem(); DrawPanel->m_AutoPAN_Request = true; Start_Move_Zone_Drag_Outline_Edge( &dc, zone_cont, zone_cont->m_CornerSelection ); break; } case ID_POPUP_PCB_MOVE_ZONE_OUTLINES: { DrawPanel->MoveCursorToCrossHair(); ZONE_CONTAINER* zone_cont = (ZONE_CONTAINER*) GetCurItem(); DrawPanel->m_AutoPAN_Request = true; Start_Move_Zone_Outlines( &dc, zone_cont ); break; } case ID_POPUP_PCB_ADD_ZONE_CORNER: { DrawPanel->MoveCursorToCrossHair(); ZONE_CONTAINER* zone_cont = (ZONE_CONTAINER*) GetCurItem(); wxPoint pos = GetScreen()->GetCrossHairPosition(); /* add corner between zone_cont->m_CornerSelection * and zone_cont->m_CornerSelection+1 * and start move the new corner */ zone_cont->Draw( DrawPanel, &dc, GR_XOR ); zone_cont->m_Poly->InsertCorner( zone_cont->m_CornerSelection, pos.x, pos.y ); zone_cont->m_CornerSelection++; zone_cont->Draw( DrawPanel, &dc, GR_XOR ); DrawPanel->m_AutoPAN_Request = true; Start_Move_Zone_Corner( &dc, zone_cont, zone_cont->m_CornerSelection, true ); break; } case ID_POPUP_PCB_PLACE_ZONE_OUTLINES: case ID_POPUP_PCB_PLACE_ZONE_CORNER: { DrawPanel->MoveCursorToCrossHair(); ZONE_CONTAINER* zone_cont = (ZONE_CONTAINER*) GetCurItem(); End_Move_Zone_Corner_Or_Outlines( &dc, zone_cont ); DrawPanel->m_AutoPAN_Request = false; break; } case ID_POPUP_PCB_FILL_ALL_ZONES: DrawPanel->MoveCursorToCrossHair(); Fill_All_Zones(); GetBoard()->DisplayInfo( this ); break; case ID_POPUP_PCB_REMOVE_FILLED_AREAS_IN_CURRENT_ZONE: if( ( GetCurItem() )->Type() == TYPE_ZONE_CONTAINER ) { ZONE_CONTAINER* zone_container = (ZONE_CONTAINER*) GetCurItem(); zone_container->UnFill(); TestNetConnection( NULL, zone_container->GetNet() ); OnModify(); GetBoard()->DisplayInfo( this ); DrawPanel->Refresh(); } SetCurItem( NULL ); break; case ID_POPUP_PCB_REMOVE_FILLED_AREAS_IN_ALL_ZONES: // Remove all zones : GetBoard()->m_Zone.DeleteAll(); // remove zone segments used to fill zones. for( int ii = 0; ii < GetBoard()->GetAreaCount(); ii++ ) { // Remove filled areas in zone ZONE_CONTAINER* zone_container = GetBoard()->GetArea( ii ); zone_container->m_FilledPolysList.clear(); } SetCurItem( NULL ); // CurItem might be deleted by this command, clear the pointer TestConnections( NULL ); TestRatsNest( NULL, 0 ); // Recalculate the active ratsnest, i.e. the unconnected links OnModify(); GetBoard()->DisplayInfo( this ); DrawPanel->Refresh(); break; case ID_POPUP_PCB_FILL_ZONE: DrawPanel->MoveCursorToCrossHair(); Fill_Zone( (ZONE_CONTAINER*) GetCurItem() ); TestNetConnection( NULL, ( (ZONE_CONTAINER*) GetCurItem() )->GetNet() ); GetBoard()->DisplayInfo( this ); DrawPanel->Refresh(); break; case ID_POPUP_PCB_MOVE_TEXTEPCB_REQUEST: Process_Move_Item( this, GetCurItem(), &dc ); DrawPanel->m_AutoPAN_Request = true; break; case ID_POPUP_PCB_DRAG_MODULE_REQUEST: g_Drag_Pistes_On = true; case ID_POPUP_PCB_MOVE_MODULE_REQUEST: if( GetCurItem() == NULL ) break; // If the current Item is a pad, text module ...: Get its parent if( GetCurItem()->Type() != TYPE_MODULE ) SetCurItem( GetCurItem()->GetParent() ); if( !GetCurItem() || GetCurItem()->Type() != TYPE_MODULE ) { g_Drag_Pistes_On = false; break; } module = (MODULE*) GetCurItem(); if( module->IsLocked() ) { wxString msg; msg.Printf( _( "Footprint %s found, but it is locked" ), module->m_Reference->m_Text.GetData() ); DisplayInfoMessage( this, msg ); break; } GetScreen()->SetCrossHairPosition( ((MODULE*) GetCurItem())->m_Pos ); DrawPanel->MoveCursorToCrossHair(); StartMove_Module( (MODULE*) GetCurItem(), &dc ); break; case ID_POPUP_PCB_GET_AND_MOVE_MODULE_REQUEST: /* get module by name and move it */ SetCurItem( GetModuleByName() ); module = (MODULE*) GetCurItem(); if( module == NULL ) break; if( module->IsLocked() ) { wxString msg; msg.Printf( _( "Footprint %s found, but it is locked" ), module->m_Reference->m_Text.GetData() ); DisplayInfoMessage( this, msg ); break; } DrawPanel->MoveCursorToCrossHair(); StartMove_Module( module, &dc ); break; case ID_POPUP_PCB_DELETE_MODULE: DrawPanel->MoveCursorToCrossHair(); // If the current Item is a pad, text module ...: Get its parent if( GetCurItem()->Type() != TYPE_MODULE ) SetCurItem( GetCurItem()->GetParent() ); if( !GetCurItem() || GetCurItem()->Type() != TYPE_MODULE ) break; module = (MODULE*) GetCurItem(); if( module->IsLocked() ) { wxString msg; msg.Printf( _( "Footprint %s found, but it is locked" ), module->m_Reference->m_Text.GetData() ); DisplayInfoMessage( this, msg ); break; } if( Delete_Module( (MODULE*) GetCurItem(), &dc, true ) ) { SetCurItem( NULL ); } break; case ID_POPUP_PCB_ROTATE_MODULE_COUNTERCLOCKWISE: DrawPanel->MoveCursorToCrossHair(); // If the current Item is a pad, text module ...: Get its parent if( GetCurItem()->Type() != TYPE_MODULE ) SetCurItem( GetCurItem()->GetParent() ); if( !GetCurItem() || GetCurItem()->Type() != TYPE_MODULE ) break; module = (MODULE*) GetCurItem(); if( module->IsLocked() ) { wxString msg; msg.Printf( _( "Footprint %s found, but it is locked" ), module->m_Reference->m_Text.GetData() ); DisplayInfoMessage( this, msg ); break; } /* This is a simple rotation, no other editing in progress */ if( !(GetCurItem()->m_Flags & IS_MOVED) ) SaveCopyInUndoList(GetCurItem(), UR_ROTATED, ((MODULE*)GetCurItem())->m_Pos); Rotate_Module( &dc, (MODULE*) GetCurItem(), g_RotationAngle, true ); break; case ID_POPUP_PCB_ROTATE_MODULE_CLOCKWISE: DrawPanel->MoveCursorToCrossHair(); // If the current Item is a pad, text module ...: Get its parent if( GetCurItem()->Type() != TYPE_MODULE ) SetCurItem( GetCurItem()->GetParent() ); if( !GetCurItem() || GetCurItem()->Type() != TYPE_MODULE ) break; module = (MODULE*) GetCurItem(); if( module->IsLocked() ) { wxString msg; msg.Printf( _( "Footprint %s found, but it is locked" ), module->m_Reference->m_Text.GetData() ); DisplayInfoMessage( this, msg ); break; } /* This is a simple rotation, no other editing in progress */ if( !(GetCurItem()->m_Flags & IS_MOVED) ) SaveCopyInUndoList( GetCurItem(), UR_ROTATED_CLOCKWISE, ((MODULE*)GetCurItem())->m_Pos ); Rotate_Module( &dc, (MODULE*) GetCurItem(), -g_RotationAngle, true ); break; case ID_POPUP_PCB_CHANGE_SIDE_MODULE: DrawPanel->MoveCursorToCrossHair(); // If the current Item is a pad, text module ...: Get its parent if( GetCurItem()->Type() != TYPE_MODULE ) SetCurItem( GetCurItem()->GetParent() ); if( !GetCurItem() || GetCurItem()->Type() != TYPE_MODULE ) break; module = (MODULE*) GetCurItem(); if( module->IsLocked() ) { wxString msg; msg.Printf( _( "Footprint %s found, but it is locked" ), module->m_Reference->m_Text.GetData() ); DisplayInfoMessage( this, msg ); break; } /* This is a simple flip, no other editing in progress */ if( !(GetCurItem()->m_Flags & IS_MOVED) ) SaveCopyInUndoList(GetCurItem(), UR_FLIPPED, ((MODULE*)GetCurItem())->m_Pos); Change_Side_Module( (MODULE*) GetCurItem(), &dc ); break; case ID_POPUP_PCB_EDIT_MODULE: // If the current Item is a pad, text module ...: Get its parent if( GetCurItem()->Type() != TYPE_MODULE ) SetCurItem( GetCurItem()->GetParent() ); if( !GetCurItem() || GetCurItem()->Type() != TYPE_MODULE ) break; InstallModuleOptionsFrame( (MODULE*) GetCurItem(), &dc ); DrawPanel->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_DRAG_PAD_REQUEST: module = (MODULE*) GetCurItem()->GetParent(); if( !module || module->Type() != TYPE_MODULE ) break; if( module->IsLocked() ) { wxString msg; msg.Printf( _( "The parent (%s) of the pad is locked" ), module->m_Reference->m_Text.GetData() ); DisplayInfoMessage( this, msg ); break; } g_Drag_Pistes_On = true; DrawPanel->MoveCursorToCrossHair(); StartMovePad( (D_PAD*) GetCurItem(), &dc ); break; case ID_POPUP_PCB_MOVE_PAD_REQUEST: module = (MODULE*) GetCurItem()->GetParent(); if( !module || module->Type() != TYPE_MODULE ) break; if( module->IsLocked() ) { wxString msg; msg.Printf( _( "The parent (%s) of the pad is locked" ), module->m_Reference->m_Text.GetData() ); DisplayInfoMessage( this, msg ); break; } g_Drag_Pistes_On = false; DrawPanel->MoveCursorToCrossHair(); StartMovePad( (D_PAD*) GetCurItem(), &dc ); break; case ID_POPUP_PCB_EDIT_PAD: InstallPadOptionsFrame( (D_PAD*) GetCurItem() ); DrawPanel->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_IMPORT_PAD_SETTINGS: DrawPanel->MoveCursorToCrossHair(); SaveCopyInUndoList( GetCurItem()->GetParent(), UR_CHANGED ); Import_Pad_Settings( (D_PAD*) GetCurItem(), true ); break; case ID_POPUP_PCB_GLOBAL_IMPORT_PAD_SETTINGS: DrawPanel->MoveCursorToCrossHair(); Global_Import_Pad_Settings( (D_PAD*) GetCurItem(), true ); break; case ID_POPUP_PCB_EXPORT_PAD_SETTINGS: DrawPanel->MoveCursorToCrossHair(); Export_Pad_Settings( (D_PAD*) GetCurItem() ); break; case ID_POPUP_PCB_DELETE_PAD: SaveCopyInUndoList( GetCurItem()->GetParent(), UR_CHANGED ); DeletePad( (D_PAD*) GetCurItem() ); SetCurItem( NULL ); DrawPanel->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_EDIT_TEXTMODULE: InstallTextModOptionsFrame( (TEXTE_MODULE*) GetCurItem(), &dc ); DrawPanel->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_RESET_TEXT_SIZE: ResetTextSize( GetCurItem(), &dc ); break; case ID_POPUP_PCB_MOVE_TEXTMODULE_REQUEST: DrawPanel->MoveCursorToCrossHair(); StartMoveTexteModule( (TEXTE_MODULE*) GetCurItem(), &dc ); break; case ID_POPUP_PCB_ROTATE_TEXTMODULE: RotateTextModule( (TEXTE_MODULE*) GetCurItem(), &dc ); DrawPanel->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_DELETE_TEXTMODULE: DeleteTextModule( (TEXTE_MODULE*) GetCurItem() ); SetCurItem( NULL ); DrawPanel->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_SELECT_LAYER: itmp = SelectLayer( getActiveLayer(), -1, -1 ); if( itmp >= 0 ) setActiveLayer( itmp ); DrawPanel->MoveCursorToCrossHair(); break; case ID_AUX_TOOLBAR_PCB_SELECT_LAYER_PAIR: SelectLayerPair(); break; case ID_POPUP_PCB_SELECT_NO_CU_LAYER: itmp = SelectLayer( getActiveLayer(), FIRST_NO_COPPER_LAYER, -1 ); if( itmp >= 0 ) setActiveLayer( itmp ); DrawPanel->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_SELECT_CU_LAYER: itmp = SelectLayer( getActiveLayer(), -1, LAST_COPPER_LAYER ); if( itmp >= 0 ) setActiveLayer( itmp ); break; case ID_POPUP_PCB_SELECT_LAYER_PAIR: SelectLayerPair(); DrawPanel->MoveCursorToCrossHair(); break; case ID_TOOLBARH_PCB_SELECT_LAYER: setActiveLayer( (size_t) m_SelLayerBox->GetLayerSelection()); if( DisplayOpt.ContrastModeDisplay ) DrawPanel->Refresh( true ); break; case ID_POPUP_PCB_EDIT_TEXTEPCB: InstallTextPCBOptionsFrame( (TEXTE_PCB*) GetCurItem(), &dc ); DrawPanel->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_ROTATE_TEXTEPCB: Rotate_Texte_Pcb( (TEXTE_PCB*) GetCurItem(), &dc ); DrawPanel->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_DELETE_TEXTEPCB: Delete_Texte_Pcb( (TEXTE_PCB*) GetCurItem(), &dc ); DrawPanel->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_MOVE_MIRE_REQUEST: BeginMoveTarget( (PCB_TARGET*) GetCurItem(), &dc ); DrawPanel->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_EDIT_MIRE: ShowTargetOptionsDialog( (PCB_TARGET*) GetCurItem(), &dc ); DrawPanel->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_DELETE_MIRE: DrawPanel->MoveCursorToCrossHair(); DeleteTarget( (PCB_TARGET*) GetCurItem(), &dc ); SetCurItem( NULL ); break; case ID_POPUP_PCB_DELETE_DIMENSION: DrawPanel->MoveCursorToCrossHair(); Delete_Dimension( (DIMENSION*) GetCurItem(), &dc ); SetCurItem( NULL ); break; case ID_POPUP_PCB_EDIT_DIMENSION: Install_Edit_Dimension( (DIMENSION*) GetCurItem(), &dc ); DrawPanel->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_DELETE_DRAWING: Delete_Segment_Edge( (DRAWSEGMENT*) GetCurItem(), &dc ); DrawPanel->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_DELETE_MARKER: RemoveStruct( GetCurItem(), &dc ); DrawPanel->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_GETINFO_MARKER: if( GetCurItem() && GetCurItem()->Type() == TYPE_MARKER_PCB ) ( (MARKER_PCB*) GetCurItem() )->DisplayMarkerInfo( this ); DrawPanel->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_DELETE_DRAWING_LAYER: if( GetCurItem()->m_Flags != 0 ) break; Delete_Drawings_All_Layer( GetCurItem()->GetLayer() ); SetCurItem( NULL ); DrawPanel->MoveCursorToCrossHair(); DrawPanel->Refresh(); break; case ID_POPUP_PCB_EDIT_DRAWING: InstallGraphicItemPropertiesDialog( (DRAWSEGMENT*) GetCurItem(), &dc ); DrawPanel->MoveCursorToCrossHair(); break; case ID_POPUP_PCB_MOVE_DRAWING_REQUEST: DrawPanel->MoveCursorToCrossHair(); Start_Move_DrawItem( (DRAWSEGMENT*) GetCurItem(), &dc ); break; case ID_POPUP_PCB_STOP_CURRENT_DRAWING: DrawPanel->MoveCursorToCrossHair(); if( GetCurItem() && (GetCurItem()->IsNew()) ) { End_Edge( (DRAWSEGMENT*) GetCurItem(), &dc ); SetCurItem( NULL ); } break; case ID_POPUP_PCB_STOP_CURRENT_EDGE_ZONE: DrawPanel->MoveCursorToCrossHair(); if( GetCurItem() && (GetCurItem()->IsNew()) ) { if( End_Zone( &dc ) ) SetCurItem( NULL ); } DrawPanel->m_AutoPAN_Request = false; break; case ID_POPUP_PCB_DELETE_ZONE_LAST_CREATED_CORNER: DrawPanel->MoveCursorToCrossHair(); if( GetCurItem() && (GetCurItem()->IsNew()) ) { if( Delete_LastCreatedCorner( &dc ) == 0 ) // No more segment in outline, SetCurItem( NULL ); } break; case ID_POPUP_PCB_MOVE_TRACK_SEGMENT: DrawPanel->MoveCursorToCrossHair(); StartMoveOneNodeOrSegment( (TRACK*) GetScreen()->GetCurItem(), &dc, id ); break; case ID_POPUP_PCB_DRAG_TRACK_SEGMENT: case ID_POPUP_PCB_MOVE_TRACK_NODE: DrawPanel->MoveCursorToCrossHair(); StartMoveOneNodeOrSegment( (TRACK*) GetScreen()->GetCurItem(), &dc, id ); break; case ID_POPUP_PCB_DRAG_TRACK_SEGMENT_KEEP_SLOPE: DrawPanel->MoveCursorToCrossHair(); Start_DragTrackSegmentAndKeepSlope( (TRACK*) GetScreen()->GetCurItem(), &dc ); break; case ID_POPUP_PCB_BREAK_TRACK: DrawPanel->MoveCursorToCrossHair(); { TRACK* track = (TRACK*) GetScreen()->GetCurItem(); wxPoint pos = GetScreen()->GetCrossHairPosition(); track->Draw( DrawPanel, &dc, GR_XOR ); PICKED_ITEMS_LIST itemsListPicker; TRACK* newtrack = CreateLockPoint( GetBoard(), pos, track, &itemsListPicker ); SaveCopyInUndoList( itemsListPicker, UR_UNSPECIFIED ); track->Draw( DrawPanel, &dc, GR_XOR ); newtrack->Draw( DrawPanel, &dc, GR_XOR ); /* compute the new ratsnest, because connectivity could change */ TestNetConnection( &dc, track->GetNet() ); } break; case ID_MENU_PCB_CLEAN: Clean_Pcb( &dc ); break; case ID_MENU_PCB_SWAP_LAYERS: Swap_Layers( event ); break; case ID_MENU_PCB_RESET_TEXTMODULE_REFERENCE_SIZES: ResetModuleTextSizes( TEXT_is_REFERENCE, &dc ); break; case ID_MENU_PCB_RESET_TEXTMODULE_VALUE_SIZES: ResetModuleTextSizes( TEXT_is_VALUE, &dc ); break; case ID_PCB_USER_GRID_SETUP: InstallGridFrame( pos ); break; case ID_POPUP_PCB_DISPLAY_FOOTPRINT_DOC: { wxConfig* cfg = wxGetApp().m_EDA_CommonConfig; cfg->Read( wxT( "module_doc_file" ), g_DocModulesFileName ); GetAssociatedDocument( this, g_DocModulesFileName, &wxGetApp().GetLibraryPathList() ); } break; case ID_MENU_ARCHIVE_NEW_MODULES: Archive_Modules( wxEmptyString, true ); break; case ID_MENU_ARCHIVE_ALL_MODULES: Archive_Modules( wxEmptyString, false ); break; default: wxString msg; msg.Printf( wxT( "PCB_EDIT_FRAME::Process_Special_Functions() id %d error" ), DrawStruct->Type() ); DisplayError( this, msg ); break; } DrawPanel->CrossHairOn( &dc ); DrawPanel->m_IgnoreMouseEvents = false; } static void Process_Move_Item( PCB_EDIT_FRAME* frame, EDA_ITEM* DrawStruct, wxDC* DC ) { if( DrawStruct == NULL ) return; switch( DrawStruct->Type() ) { case TYPE_TEXTE: frame->StartMoveTextePcb( (TEXTE_PCB*) DrawStruct, DC ); break; default: wxString msg; msg.Printf( wxT( "PCB_EDIT_FRAME::Move_Item Error: Bad DrawType %d" ), DrawStruct->Type() ); DisplayError( frame, msg ); break; } } void PCB_EDIT_FRAME::RemoveStruct( BOARD_ITEM* Item, wxDC* DC ) { if( Item == NULL ) return; switch( Item->Type() ) { case TYPE_MODULE: Delete_Module( (MODULE*) Item, DC, true ); break; case TYPE_DIMENSION: Delete_Dimension( (DIMENSION*) Item, DC ); break; case PCB_TARGET_T: DeleteTarget( (PCB_TARGET*) Item, DC ); break; case TYPE_DRAWSEGMENT: Delete_Segment_Edge( (DRAWSEGMENT*) Item, DC ); break; case TYPE_TEXTE: Delete_Texte_Pcb( (TEXTE_PCB*) Item, DC ); break; case TYPE_TRACK: Delete_Track( DC, (TRACK*) Item ); break; case TYPE_VIA: Delete_Segment( DC, (TRACK*) Item ); break; case TYPE_ZONE: Delete_OldZone_Fill( (SEGZONE*) Item ); break; case TYPE_ZONE_EDGE_CORNER: Remove_Zone_Corner( DC, (ZONE_CONTAINER*) Item ); SetCurItem( NULL ); break; case TYPE_ZONE_CONTAINER: { SetCurItem( NULL ); int netcode = ( (ZONE_CONTAINER*) Item )->GetNet(); Delete_Zone_Contour( DC, (ZONE_CONTAINER*) Item ); TestNetConnection( NULL, netcode ); GetBoard()->DisplayInfo( this ); } break; case TYPE_MARKER_PCB: if( Item == GetCurItem() ) SetCurItem( NULL ); ( (MARKER_PCB*) Item )->Draw( DrawPanel, DC, GR_XOR ); // delete the marker, and free memory. Don't use undo stack. GetBoard()->Delete( Item ); break; case TYPE_PAD: case TYPE_TEXTE_MODULE: case TYPE_EDGE_MODULE: break; case TYPE_NOT_INIT: case TYPE_PCB: default: { wxString Line; Line.Printf( wxT( "Remove: item type %d unknown." ), Item->Type() ); DisplayError( this, Line ); } break; } } void PCB_EDIT_FRAME::SwitchLayer( wxDC* DC, int layer ) { int curLayer = getActiveLayer(); // Check if the specified layer matches the present layer if( layer == curLayer ) return; // Copper layers cannot be selected unconditionally; how many // of those layers are currently enabled needs to be checked. if( IsValidCopperLayerIndex( layer ) ) { // If only one copper layer is enabled, the only such layer // that can be selected to is the "Back" layer (so the // selection of any other copper layer is disregarded). if( GetBoard()->GetCopperLayerCount() < 2 ) { if( layer != LAYER_N_BACK ) { // Uncomment following command (and line 17) to beep // the speaker. (Doing that would provide feedback to // the user that the (layer-switching) command has been // "acknowledged", but is unable to be acted upon.) // wxBell(); return; } } // If more than one copper layer is enabled, the "Copper" // and "Component" layers can be selected, but the total // number of copper layers determines which internal // layers are also capable of being selected. else { if( ( layer != LAYER_N_BACK ) && ( layer != LAYER_N_FRONT ) && ( layer >= GetBoard()->GetCopperLayerCount() - 1 ) ) { // Uncomment following command (and line 17) to beep // the speaker. (Doing that would provide feedback to // the user that the (layer-switching) command has been // "acknowledged", but is unable to be acted upon.) // wxBell(); return; } } EDA_ITEM* current = GetScreen()->GetCurItem(); // See if we are drawing a segment; if so, add a via? if( GetToolId() == ID_TRACK_BUTT && current != NULL ) { if( current->Type() == TYPE_TRACK && ( current->IsNew() ) ) { // Want to set the routing layers so that it switches properly - // see the implementation of Other_Layer_Route - the working // layer is used to 'start' the via and set the layer masks appropriately. GetScreen()->m_Route_Layer_TOP = curLayer; GetScreen()->m_Route_Layer_BOTTOM = layer; setActiveLayer( curLayer ); if( Other_Layer_Route( (TRACK*) GetScreen()->GetCurItem(), DC ) ) { if( DisplayOpt.ContrastModeDisplay ) DrawPanel->Refresh(); } // if the via was allowed by DRC, then the layer swap has already // been done by Other_Layer_Route(). if via not allowed, then // return now so assignment to setActiveLayer() below doesn't happen. return; } } } // Is yet more checking required? E.g. when the layer to be selected // is a non-copper layer, or when switching between a copper layer // and a non-copper layer, or vice-versa? // ... setActiveLayer( layer ); if( DisplayOpt.ContrastModeDisplay ) DrawPanel->Refresh(); } void PCB_EDIT_FRAME::OnSelectTool( wxCommandEvent& aEvent ) { int id = aEvent.GetId(); if( GetToolId() == id ) return; INSTALL_UNBUFFERED_DC( dc, DrawPanel ); // Stop the current command and deselect the current tool. DrawPanel->EndMouseCapture( ID_NO_TOOL_SELECTED, DrawPanel->GetDefaultCursor() ); switch( id ) { case ID_NO_TOOL_SELECTED: SetToolID( id, DrawPanel->GetDefaultCursor(), wxEmptyString ); break; case ID_TRACK_BUTT: if( Drc_On ) SetToolID( id, wxCURSOR_PENCIL, _( "Add tracks" ) ); else SetToolID( id, wxCURSOR_QUESTION_ARROW, _( "Add tracks" ) ); if( (GetBoard()->m_Status_Pcb & LISTE_RATSNEST_ITEM_OK) == 0 ) { Compile_Ratsnest( &dc, true ); } break; case ID_PCB_MODULE_BUTT: SetToolID( id, wxCURSOR_PENCIL, _( "Add module" ) ); break; case ID_PCB_ZONES_BUTT: SetToolID( id, wxCURSOR_PENCIL, _( "Add zones" ) ); if( DisplayOpt.DisplayZonesMode != 0 ) DisplayInfoMessage( this, _( "Warning: zone display is OFF!!!" ) ); if( !GetBoard()->IsHighLightNetON() && (GetBoard()->GetHighLightNetCode() > 0 ) ) High_Light( &dc ); break; case ID_PCB_MIRE_BUTT: SetToolID( id, wxCURSOR_PENCIL, _( "Add layer alignment target" ) ); break; case ID_PCB_PLACE_OFFSET_COORD_BUTT: SetToolID( id, wxCURSOR_PENCIL, _( "Adjust zero" ) ); break; case ID_PCB_PLACE_GRID_COORD_BUTT: SetToolID( id, wxCURSOR_PENCIL, _( "Adjust grid origin" ) ); break; case ID_PCB_ADD_LINE_BUTT: SetToolID( id, wxCURSOR_PENCIL, _( "Add graphic line" ) ); break; case ID_PCB_ARC_BUTT: SetToolID( id, wxCURSOR_PENCIL, _( "Add graphic arc" ) ); break; case ID_PCB_CIRCLE_BUTT: SetToolID( id, wxCURSOR_PENCIL, _( "Add graphic circle" ) ); break; case ID_PCB_ADD_TEXT_BUTT: SetToolID( id, wxCURSOR_PENCIL, _( "Add text" ) ); break; case ID_COMPONENT_BUTT: SetToolID( id, wxCURSOR_HAND, _( "Add module" ) ); break; case ID_PCB_DIMENSION_BUTT: SetToolID( id, wxCURSOR_PENCIL, _( "Add dimension" ) ); break; case ID_PCB_DELETE_ITEM_BUTT: SetToolID( id, wxCURSOR_BULLSEYE, _( "Delete item" ) ); break; case ID_PCB_HIGHLIGHT_BUTT: SetToolID( id, wxCURSOR_HAND, _( "Highlight net" ) ); break; case ID_PCB_SHOW_1_RATSNEST_BUTT: SetToolID( id, wxCURSOR_HAND, _( "Select rats nest" ) ); if( ( GetBoard()->m_Status_Pcb & LISTE_RATSNEST_ITEM_OK ) == 0 ) Compile_Ratsnest( &dc, true ); break; } }