int SCH_SCREEN::UpdatePickList() { ITEM_PICKER picker; EDA_RECT area; unsigned count; area.SetOrigin( m_BlockLocate.GetOrigin() ); area.SetSize( m_BlockLocate.GetSize() ); area.Normalize(); for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() ) { // An item is picked if its bounding box intersects the reference area. if( item->HitTest( area ) ) { picker.SetItem( item ); m_BlockLocate.PushItem( picker ); } } // if the block is composed of one item, // select it as the current item count = m_BlockLocate.GetCount(); if( count == 1 ) { SetCurItem( (SCH_ITEM*) m_BlockLocate.GetItem( 0 ) ); } else { SetCurItem( NULL ); } return count; }
void SCH_SCREEN::addConnectedItemsToBlock( const wxPoint& position ) { SCH_ITEM* item; ITEM_PICKER picker; bool addinlist = true; for( item = m_drawList.begin(); item; item = item->Next() ) { picker.SetItem( item ); if( !item->IsConnectable() || !item->IsConnected( position ) || (item->GetFlags() & SKIP_STRUCT) ) continue; if( item->IsSelected() && item->Type() != SCH_LINE_T ) continue; // A line having 2 ends, it can be tested twice: one time per end if( item->Type() == SCH_LINE_T ) { if( ! item->IsSelected() ) // First time this line is tested item->SetFlags( SELECTED | STARTPOINT | ENDPOINT ); else // second time (or more) this line is tested addinlist = false; SCH_LINE* line = (SCH_LINE*) item; if( line->GetStartPoint() == position ) item->ClearFlags( STARTPOINT ); else if( line->GetEndPoint() == position ) item->ClearFlags( ENDPOINT ); } else item->SetFlags( SELECTED ); if( addinlist ) { picker.SetFlags( item->GetFlags() ); m_BlockLocate.GetItems().PushItem( picker ); } } }
bool SCH_EDIT_FRAME::HandleBlockEnd( wxDC* aDC ) { bool nextcmd = false; bool zoom_command = false; BLOCK_SELECTOR* block = &GetScreen()->m_BlockLocate; if( block->GetCount() ) { BLOCK_STATE_T state = block->GetState(); BLOCK_COMMAND_T command = block->GetCommand(); m_canvas->CallEndMouseCapture( aDC ); block->SetState( state ); block->SetCommand( command ); m_canvas->SetMouseCapture( DrawAndSizingBlockOutlines, AbortBlockCurrentCommand ); SetCrossHairPosition( block->GetEnd() ); if( block->GetCommand() != BLOCK_ABORT ) m_canvas->MoveCursorToCrossHair(); } if( m_canvas->IsMouseCaptured() ) { switch( block->GetCommand() ) { case BLOCK_IDLE: DisplayError( this, wxT( "Error in HandleBlockPLace()" ) ); break; case BLOCK_ROTATE: GetScreen()->UpdatePickList(); DrawAndSizingBlockOutlines( m_canvas, aDC, wxDefaultPosition, false ); if( block->GetCount() ) { // Compute the rotation center and put it on grid: wxPoint rotationPoint = block->Centre(); rotationPoint = GetNearestGridPosition( rotationPoint ); SetCrossHairPosition( rotationPoint ); SaveCopyInUndoList( block->GetItems(), UR_ROTATED, rotationPoint ); RotateListOfItems( block->GetItems(), rotationPoint ); OnModify(); } block->ClearItemsList(); GetScreen()->TestDanglingEnds( m_canvas, aDC ); m_canvas->Refresh(); break; case BLOCK_DRAG: case BLOCK_DRAG_ITEM: // Drag from a drag command GetScreen()->BreakSegmentsOnJunctions(); // fall through case BLOCK_MOVE: case BLOCK_COPY: if( block->GetCommand() == BLOCK_DRAG_ITEM && GetScreen()->GetCurItem() != NULL ) { // This is a drag command, not a mouse block command // Only this item is put in list ITEM_PICKER picker; picker.SetItem( GetScreen()->GetCurItem() ); block->PushItem( picker ); } else { // Collect all items in the locate block GetScreen()->UpdatePickList(); } // fall through case BLOCK_PRESELECT_MOVE: /* Move with preselection list*/ if( block->GetCount() ) { nextcmd = true; GetScreen()->SelectBlockItems(); m_canvas->CallMouseCapture( aDC, wxDefaultPosition, false ); m_canvas->SetMouseCaptureCallback( DrawMovingBlockOutlines ); m_canvas->CallMouseCapture( aDC, wxDefaultPosition, false ); block->SetState( STATE_BLOCK_MOVE ); } else { m_canvas->CallMouseCapture( aDC, wxDefaultPosition, false ); m_canvas->SetMouseCapture( NULL, NULL ); } break; case BLOCK_DELETE: GetScreen()->UpdatePickList(); DrawAndSizingBlockOutlines( m_canvas, aDC, wxDefaultPosition, false ); if( block->GetCount() ) { DeleteItemsInList( m_canvas, block->GetItems() ); OnModify(); } block->ClearItemsList(); GetScreen()->TestDanglingEnds( m_canvas, aDC ); m_canvas->Refresh(); break; case BLOCK_SAVE: // Save a copy of items in paste buffer GetScreen()->UpdatePickList(); DrawAndSizingBlockOutlines( m_canvas, aDC, wxDefaultPosition, false ); if( block->GetCount() ) { wxPoint move_vector = -GetScreen()->m_BlockLocate.GetLastCursorPosition(); copyBlockItems( block->GetItems() ); MoveItemsInList( m_blockItems.GetItems(), move_vector ); } block->ClearItemsList(); break; case BLOCK_PASTE: block->SetState( STATE_BLOCK_MOVE ); break; case BLOCK_ZOOM: zoom_command = true; break; case BLOCK_MIRROR_X: GetScreen()->UpdatePickList(); DrawAndSizingBlockOutlines( m_canvas, aDC, wxDefaultPosition, false ); if( block->GetCount() ) { // Compute the mirror center and put it on grid. wxPoint mirrorPoint = block->Centre(); mirrorPoint = GetNearestGridPosition( mirrorPoint ); SetCrossHairPosition( mirrorPoint ); SaveCopyInUndoList( block->GetItems(), UR_MIRRORED_X, mirrorPoint ); MirrorX( block->GetItems(), mirrorPoint ); OnModify(); } GetScreen()->TestDanglingEnds( m_canvas, aDC ); m_canvas->Refresh(); break; case BLOCK_MIRROR_Y: GetScreen()->UpdatePickList(); DrawAndSizingBlockOutlines( m_canvas, aDC, wxDefaultPosition, false ); if( block->GetCount() ) { // Compute the mirror center and put it on grid. wxPoint mirrorPoint = block->Centre(); mirrorPoint = GetNearestGridPosition( mirrorPoint ); SetCrossHairPosition( mirrorPoint ); SaveCopyInUndoList( block->GetItems(), UR_MIRRORED_Y, mirrorPoint ); MirrorY( block->GetItems(), mirrorPoint ); OnModify(); } GetScreen()->TestDanglingEnds( m_canvas, aDC ); m_canvas->Refresh(); break; default: break; } } if( block->GetCommand() == BLOCK_ABORT ) { GetScreen()->ClearDrawingState(); m_canvas->Refresh(); } if( ! nextcmd ) { block->SetState( STATE_NO_BLOCK ); block->SetCommand( BLOCK_IDLE ); GetScreen()->SetCurItem( NULL ); m_canvas->EndMouseCapture( GetToolId(), m_canvas->GetCurrentCursor(), wxEmptyString, false ); } if( zoom_command ) Window_Zoom( GetScreen()->m_BlockLocate ); return nextcmd; }
int PCB_EDITOR_CONTROL::ZoneMerge( const TOOL_EVENT& aEvent ) { SELECTION selection = m_toolMgr->GetTool<SELECTION_TOOL>()->GetSelection(); BOARD* board = getModel<BOARD>(); RN_DATA* ratsnest = board->GetRatsnest(); KIGFX::VIEW* view = getView(); if( selection.Size() < 2 ) return 0; PICKED_ITEMS_LIST changes; int netcode = -1; // Loop through all combinations for( int ia1 = 0; ia1 < selection.Size() - 1; ++ia1 ) { ZONE_CONTAINER* curr_area = dynamic_cast<ZONE_CONTAINER*>( selection.Item<EDA_ITEM>( ia1 ) ); if( !curr_area ) continue; netcode = curr_area->GetNetCode(); EDA_RECT b1 = curr_area->Outline()->GetBoundingBox(); bool mod_ia1 = false; for( int ia2 = selection.Size() - 1; ia2 > ia1; --ia2 ) { ZONE_CONTAINER* area2 = dynamic_cast<ZONE_CONTAINER*>( selection.Item<EDA_ITEM>( ia2 ) ); if( !area2 ) continue; if( area2->GetNetCode() != netcode ) continue; if( curr_area->GetPriority() != area2->GetPriority() ) continue; if( curr_area->GetIsKeepout() != area2->GetIsKeepout() ) continue; if( curr_area->GetLayer() != area2->GetLayer() ) continue; EDA_RECT b2 = area2->Outline()->GetBoundingBox(); if( b1.Intersects( b2 ) ) { EDA_ITEM* backup = curr_area->Clone(); bool ret = board->TestAreaIntersection( curr_area, area2 ); if( ret && board->CombineAreas( &changes, curr_area, area2 ) ) { mod_ia1 = true; selection.items.RemovePicker( ia2 ); ITEM_PICKER picker( curr_area, UR_CHANGED ); picker.SetLink( backup ); changes.PushItem( picker ); } else { delete backup; } } } if( mod_ia1 ) --ia1; // if modified, we need to check it again } m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); m_frame->SaveCopyInUndoList( changes, UR_UNSPECIFIED ); for( unsigned i = 0; i < changes.GetCount(); ++i ) { ITEM_PICKER picker = changes.GetItemWrapper( i ); BOARD_ITEM* item = static_cast<BOARD_ITEM*>( picker.GetItem() ); if( picker.GetStatus() == UR_DELETED ) { view->Remove( item ); ratsnest->Remove( item ); } else if( picker.GetStatus() == UR_CHANGED ) { item->ViewUpdate( KIGFX::VIEW_ITEM::ALL ); m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, item ); } } return 0; }
/** * When the component table dialog is closed, * work out if we need to save any changed. * If so, capture those changes and push them to the undo stack. */ bool DIALOG_BOM_EDITOR::TransferDataFromWindow() { if( m_bom->HaveFieldsChanged() ) { /** * As we may be saving changes across multiple sheets, * we need to first determine which changes need to be made to which sheet. * To this end, we perform the following: * 1. Save the "path" of the currently displayed sheet * 2. Create a MAP of <SheetPath:ChangeList> changes that need to be made * 3. Push UNDO actions to appropriate sheets * 4. Perform all the update actions * 5. Reset the view to the current sheet */ auto currentSheet = m_parent->GetCurrentSheet(); //! Create a map of changes required for each sheet std::map<wxString, SheetUndoList> undoSheetMap; // List of components that have changed auto changed = m_bom->GetChangedComponents(); ITEM_PICKER picker; // Iterate through each of the components that were changed for( auto ref : changed ) { // Extract the SCH_COMPONENT* object auto cmp = ref.GetComp(); wxString path = ref.GetSheetPath().Path(); // Push the component into the picker list picker = ITEM_PICKER( cmp, UR_CHANGED ); picker.SetFlags( cmp->GetFlags() ); /* * If there is not currently an undo list for the given sheet, * create an empty one */ if( undoSheetMap.count( path ) == 0 ) { SheetUndoList newList; newList.path = ref.GetSheetPath(); undoSheetMap[path] = newList; } auto& pickerList = undoSheetMap[path]; pickerList.items.PushItem( picker ); } // Iterate through each sheet that needs updating for( auto it = undoSheetMap.begin(); it != undoSheetMap.end(); ++it ) { auto undo = it->second; m_parent->SetCurrentSheet( undo.path ); m_parent->SaveCopyInUndoList( undo.items, UR_CHANGED ); m_parent->OnModify(); } // Make all component changes m_bom->ApplyFieldChanges(); // Redraw the current sheet and mark as dirty m_parent->Refresh(); m_parent->OnModify(); // Reset the view to where we left the user m_parent->SetCurrentSheet(currentSheet); } return true; }
void SCH_SCREEN::addConnectedItemsToBlock( const SCH_ITEM* aItem, const wxPoint& position ) { SCH_ITEM* item; ITEM_PICKER picker; for( item = m_drawList.begin(); item; item = item->Next() ) { if( !item->IsConnectable() || ( item->GetFlags() & SKIP_STRUCT ) || !item->CanConnect( aItem ) || item == aItem ) continue; // A line having 2 ends, it can be tested twice: one time per end if( item->Type() == SCH_LINE_T ) { SCH_LINE* line = (SCH_LINE*) item; if( !item->HitTest( position ) ) continue; // First time through. Flags set to denote an end that is not moving if( !item->IsSelected() ) item->SetFlags( CANDIDATE | STARTPOINT | ENDPOINT ); if( line->GetStartPoint() == position ) item->ClearFlags( STARTPOINT ); else if( line->GetEndPoint() == position ) item->ClearFlags( ENDPOINT ); else // This picks up items such as labels that can connect to the middle of a line item->ClearFlags( STARTPOINT | ENDPOINT ); } // We want to move a mid-connected label or bus entry when the full line is being moved else if( !item->IsSelected() && aItem->Type() == SCH_LINE_T && !( aItem->GetFlags() & ( ENDPOINT | STARTPOINT ) ) ) { std::vector< wxPoint > connections; item->GetConnectionPoints( connections ); for( auto conn : connections ) { if( aItem->HitTest( conn ) ) { item->SetFlags( CANDIDATE ); break; } } } if( item->IsSelected() ) continue; if( ( item->GetFlags() & CANDIDATE ) || item->IsConnected( position ) ) // Deal with all non-line items { item->ClearFlags( CANDIDATE ); item->SetFlags( SELECTED ); picker.SetItem( item ); picker.SetFlags( item->GetFlags() ); m_BlockLocate.GetItems().PushItem( picker ); } } }