/* localize a gerber item and return a pointer to it. * Display info about this item */ GERBER_DRAW_ITEM* GERBVIEW_FRAME::Locate( const wxPoint& aPosition, int aTypeloc ) { m_messagePanel->EraseMsgBox(); wxPoint ref = aPosition; bool found = false; if( aTypeloc == CURSEUR_ON_GRILLE ) ref = GetScreen()->GetNearestGridPosition( ref ); int layer = getActiveLayer(); // Search first on active layer BOARD_ITEM* item = GetBoard()->m_Drawings; GERBER_DRAW_ITEM* gerb_item = NULL; for( ; item; item = item->Next() ) { gerb_item = (GERBER_DRAW_ITEM*) item; if( gerb_item->GetLayer()!= layer ) continue; if( gerb_item->HitTest( ref ) ) { found = true; break; } } if( !found ) // Search on all layers { item = GetBoard()->m_Drawings; for( ; item; item = item->Next() ) { gerb_item = (GERBER_DRAW_ITEM*) item; if( gerb_item->HitTest( ref ) ) { found = true; break; } } } if( found ) { gerb_item->DisplayInfo( this ); return gerb_item; } return NULL; }
void FOOTPRINT_EDIT_FRAME::Edit_Edge_Width( EDGE_MODULE* aEdge ) { MODULE* module = GetBoard()->m_Modules; SaveCopyInUndoList( module, UR_CHANGED ); if( aEdge == NULL ) { for( BOARD_ITEM *item = module->GraphicalItemsList(); item; item = item->Next() ) { aEdge = dyn_cast<EDGE_MODULE*>( item ); if( aEdge ) aEdge->SetWidth( GetDesignSettings().GetLineThickness( aEdge->GetLayer() ) ); } } else { aEdge->SetWidth( GetDesignSettings().GetLineThickness( aEdge->GetLayer() ) ); } OnModify(); module->CalculateBoundingBox(); module->SetLastEditTime(); }
/* Copy marked items, at new position = old position + offset */ void CopyMarkedItems( MODULE* module, wxPoint offset ) { if( module == NULL ) return; for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() ) { if( !pad->IsSelected() ) continue; pad->ClearFlags( SELECTED ); D_PAD* NewPad = new D_PAD( *pad ); NewPad->SetParent( module ); NewPad->SetFlags( SELECTED ); module->Pads().PushFront( NewPad ); } BOARD_ITEM* newItem; for( BOARD_ITEM* item = module->GraphicalItems(); item; item = item->Next() ) { if( !item->IsSelected() ) continue; item->ClearFlags( SELECTED ); newItem = (BOARD_ITEM*)item->Clone(); newItem->SetParent( module ); newItem->SetFlags( SELECTED ); module->GraphicalItems().PushFront( newItem ); } MoveMarkedItems( module, offset ); }
void MODULE::SetOrientation( double newangle ) { double angleChange = newangle - m_Orient; // change in rotation NORMALIZE_ANGLE_POS( newangle ); m_Orient = newangle; for( D_PAD* pad = m_Pads; pad; pad = pad->Next() ) { pad->SetOrientation( pad->GetOrientation() + angleChange ); pad->SetDrawCoord(); } // Update of the reference and value. m_Reference->SetDrawCoord(); m_Value->SetDrawCoord(); // Displace contours and text of the footprint. for( BOARD_ITEM* item = m_Drawings; item; item = item->Next() ) { if( item->Type() == PCB_MODULE_EDGE_T ) { static_cast<EDGE_MODULE*>( item )->SetDrawCoord(); } else if( item->Type() == PCB_MODULE_TEXT_T ) { static_cast<TEXTE_MODULE*>( item )->SetDrawCoord(); } } CalculateBoundingBox(); }
/* Delete marked items */ void DeleteMarkedItems( MODULE* module ) { BOARD_ITEM* item; BOARD_ITEM* next_item; D_PAD* pad; D_PAD* next_pad; if( module == NULL ) return; pad = module->Pads(); for( ; pad != NULL; pad = next_pad ) { next_pad = pad->Next(); if( !pad->IsSelected() ) continue; pad->DeleteStructure(); } item = module->GraphicalItems(); for( ; item != NULL; item = next_item ) { next_item = item->Next(); if( !item->IsSelected() ) continue; item->DeleteStructure(); } }
// plot items like text and graphics, but not tracks and module void BRDITEMS_PLOTTER::PlotBoardGraphicItems() { for( BOARD_ITEM* item = m_board->m_Drawings; item; item = item->Next() ) { switch( item->Type() ) { case PCB_LINE_T: PlotDrawSegment( (DRAWSEGMENT*) item); break; case PCB_TEXT_T: PlotTextePcb( (TEXTE_PCB*) item ); break; case PCB_DIMENSION_T: PlotDimension( (DIMENSION*) item ); break; case PCB_TARGET_T: PlotPcbTarget( (PCB_TARGET*) item ); break; case PCB_MARKER_T: default: break; } } }
void FOOTPRINT_EDIT_FRAME::Edit_Edge_Layer( EDGE_MODULE* aEdge ) { // note: if aEdge == NULL, all outline segments will be modified MODULE* module = GetBoard()->m_Modules; PCB_LAYER_ID layer = F_SilkS; bool modified = false; if( aEdge ) layer = aEdge->GetLayer(); // Ask for the new layer PCB_LAYER_ID new_layer = SelectLayer( layer, Edge_Cuts ); if( layer < 0 ) return; if( IsCopperLayer( new_layer ) ) { // an edge is put on a copper layer, and it is very dangerous. // A confirmation is requested if( !IsOK( this, _( "The graphic item will be on a copper layer.\n" "This is very dangerous. Are you sure?" ) ) ) return; } if( !aEdge ) { for( BOARD_ITEM *item = module->GraphicalItemsList() ; item != NULL; item = item->Next() ) { aEdge = dyn_cast<EDGE_MODULE*>( item ); if( aEdge && (aEdge->GetLayer() != new_layer) ) { if( ! modified ) // save only once SaveCopyInUndoList( module, UR_CHANGED ); aEdge->SetLayer( new_layer ); modified = true; } } } else if( aEdge->GetLayer() != new_layer ) { SaveCopyInUndoList( module, UR_CHANGED ); aEdge->SetLayer( new_layer ); modified = true; } if( modified ) { module->CalculateBoundingBox(); module->SetLastEditTime(); } }
void PCB_EDIT_FRAME::Delete_Drawings_All_Layer( LAYER_ID aLayer ) { if( IsCopperLayer( aLayer ) ) { DisplayError( this, _( "Copper layer global delete not allowed!" ) ); return; } wxString msg = wxString::Format( _( "Delete everything on layer %s?" ), GetChars( GetBoard()->GetLayerName( aLayer ) ) ); if( !IsOK( this, msg ) ) return; PICKED_ITEMS_LIST pickList; ITEM_PICKER picker( NULL, UR_DELETED ); BOARD_ITEM* PtNext; for( BOARD_ITEM* item = GetBoard()->m_Drawings; item; item = PtNext ) { PtNext = item->Next(); switch( item->Type() ) { case PCB_LINE_T: case PCB_TEXT_T: case PCB_DIMENSION_T: case PCB_TARGET_T: if( item->GetLayer() == aLayer ) { item->UnLink(); picker.SetItem( item ); pickList.PushItem( picker ); } break; default: { wxString msg; msg.Printf( wxT("Delete_Drawings_All_Layer() error: unknown type %d"), item->Type() ); wxMessageBox( msg ); break; } } } if( pickList.GetCount() ) { OnModify(); SaveCopyInUndoList(pickList, UR_DELETED); } }
void MODULE::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, GR_DRAWMODE aDrawMode, const wxPoint& aOffset ) { if( (m_Flags & DO_NOT_DRAW) || (IsMoving()) ) return; for( D_PAD* pad = m_Pads; pad; pad = pad->Next() ) { if( pad->IsMoving() ) continue; pad->Draw( aPanel, aDC, aDrawMode, aOffset ); } BOARD* brd = GetBoard(); // Draws footprint anchor DrawAncre( aPanel, aDC, aOffset, DIM_ANCRE_MODULE, aDrawMode ); // Draw graphic items if( brd->IsElementVisible( MOD_REFERENCES_VISIBLE ) ) { if( !(m_Reference->IsMoving()) ) m_Reference->Draw( aPanel, aDC, aDrawMode, aOffset ); } if( brd->IsElementVisible( MOD_VALUES_VISIBLE ) ) { if( !(m_Value->IsMoving()) ) m_Value->Draw( aPanel, aDC, aDrawMode, aOffset ); } for( BOARD_ITEM* item = m_Drawings; item; item = item->Next() ) { if( item->IsMoving() ) continue; switch( item->Type() ) { case PCB_MODULE_TEXT_T: case PCB_MODULE_EDGE_T: item->Draw( aPanel, aDC, aDrawMode, aOffset ); break; default: break; } } // Enable these line to draw m_BoundaryBox (debug tests purposes only) #if 0 GRRect( aPanel->GetClipBox(), aDC, m_BoundaryBox, 0, BROWN ); #endif }
void MODULE::RunOnChildren( boost::function<void (BOARD_ITEM*)> aFunction ) { for( D_PAD* pad = m_Pads.GetFirst(); pad; pad = pad->Next() ) aFunction( static_cast<BOARD_ITEM*>( pad ) ); for( BOARD_ITEM* drawing = m_Drawings.GetFirst(); drawing; drawing = drawing->Next() ) aFunction( drawing ); aFunction( static_cast<BOARD_ITEM*>( m_Reference ) ); aFunction( static_cast<BOARD_ITEM*>( m_Value ) ); }
static bool TestForExistingItem( BOARD* aPcb, BOARD_ITEM* aItem ) { static std::list<BOARD_ITEM*> itemsList; if( aItem == NULL ) // Build list { // Count items to store in itemsList: BOARD_ITEM* item; itemsList.clear(); // Store items in list: // Append tracks: for( item = aPcb->m_Track; item != NULL; item = item->Next() ) itemsList.push_back( item ); // Append modules: for( item = aPcb->m_Modules; item != NULL; item = item->Next() ) itemsList.push_back( item ); // Append drawings for( auto ditem : aPcb->Drawings() ) itemsList.push_back( ditem ); // Append zones outlines for( int ii = 0; ii < aPcb->GetAreaCount(); ii++ ) itemsList.push_back( aPcb->GetArea( ii ) ); NETINFO_LIST& netInfo = aPcb->GetNetInfo(); for( NETINFO_LIST::iterator i = netInfo.begin(); i != netInfo.end(); ++i ) itemsList.push_back( *i ); // Sort list itemsList.sort(); return false; } // search in list: return std::binary_search( itemsList.begin(), itemsList.end(), aItem ); }
void PCB_DRAW_PANEL_GAL::DisplayBoard( const BOARD* aBoard ) { m_view->Clear(); // Load zones for( int i = 0; i < aBoard->GetAreaCount(); ++i ) m_view->Add( (KIGFX::VIEW_ITEM*) ( aBoard->GetArea( i ) ) ); // Load drawings for( BOARD_ITEM* drawing = aBoard->m_Drawings; drawing; drawing = drawing->Next() ) m_view->Add( drawing ); // Load tracks for( TRACK* track = aBoard->m_Track; track; track = track->Next() ) m_view->Add( track ); // Load modules and its additional elements for( MODULE* module = aBoard->m_Modules; module; module = module->Next() ) { module->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, m_view, _1 ) ); m_view->Add( module ); } // Segzones (equivalent of ZONE_CONTAINER for legacy boards) for( SEGZONE* zone = aBoard->m_Zone; zone; zone = zone->Next() ) m_view->Add( zone ); // Ratsnest if( m_ratsnest ) { m_view->Remove( m_ratsnest ); delete m_ratsnest; } m_ratsnest = new KIGFX::RATSNEST_VIEWITEM( aBoard->GetRatsnest() ); m_view->Add( m_ratsnest ); // Display settings UseColorScheme( aBoard->GetColorsSettings() ); PCB_BASE_FRAME* frame = dynamic_cast<PCB_BASE_FRAME*>( GetParent() ); if( frame ) { SetTopLayer( frame->GetActiveLayer() ); DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*) frame->GetDisplayOptions(); static_cast<KIGFX::PCB_RENDER_SETTINGS*>( m_view->GetPainter()->GetSettings() )->LoadDisplayOptions( displ_opts ); } m_view->RecacheAllItems( true ); }
void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, SHAPE_POLY_SET& aOutlines ) { // convert tracks and vias: for( TRACK* track = m_Track; track != NULL; track = track->Next() ) { if( !track->IsOnLayer( aLayer ) ) continue; track->TransformShapeWithClearanceToPolygon( aOutlines, 0 ); } // convert pads for( MODULE* module = m_Modules; module != NULL; module = module->Next() ) { module->TransformPadsShapesWithClearanceToPolygon( aLayer, aOutlines, 0 ); // Micro-wave modules may have items on copper layers module->TransformGraphicShapesWithClearanceToPolygonSet( aLayer, aOutlines, 0 ); } // convert copper zones for( int ii = 0; ii < GetAreaCount(); ii++ ) { ZONE_CONTAINER* zone = GetArea( ii ); PCB_LAYER_ID zonelayer = zone->GetLayer(); if( zonelayer == aLayer ) zone->TransformSolidAreasShapesToPolygonSet( aOutlines ); } // convert graphic items on copper layers (texts) for( BOARD_ITEM* item = m_Drawings; item; item = item->Next() ) { if( !item->IsOnLayer( aLayer ) ) continue; switch( item->Type() ) { case PCB_LINE_T: ( (DRAWSEGMENT*) item )->TransformShapeWithClearanceToPolygon( aOutlines, 0 ); break; case PCB_TEXT_T: ( (TEXTE_PCB*) item )->TransformShapeWithClearanceToPolygonSet( aOutlines, 0 ); break; default: break; } } }
// Plot footprints graphic items (outlines) void BRDITEMS_PLOTTER::Plot_Edges_Modules() { for( MODULE* module = m_board->m_Modules; module; module = module->Next() ) { for( BOARD_ITEM* item = module->GraphicalItems().GetFirst(); item; item = item->Next() ) { EDGE_MODULE* edge = dyn_cast<EDGE_MODULE*>( item ); if( !edge || !m_layerMask[edge->GetLayer()] ) continue; Plot_1_EdgeModule( edge ); } } }
void MODULE::DrawEdgesOnly( EDA_DRAW_PANEL* panel, wxDC* DC, const wxPoint& offset, GR_DRAWMODE draw_mode ) { for( BOARD_ITEM* item = m_Drawings; item; item = item->Next() ) { switch( item->Type() ) { case PCB_MODULE_EDGE_T: item->Draw( panel, DC, draw_mode, offset ); break; default: break; } } }
void MODULE::RunOnChildren( std::function<void (BOARD_ITEM*)> aFunction ) { try { for( D_PAD* pad = m_Pads; pad; pad = pad->Next() ) aFunction( static_cast<BOARD_ITEM*>( pad ) ); for( BOARD_ITEM* drawing = m_Drawings; drawing; drawing = drawing->Next() ) aFunction( drawing ); aFunction( static_cast<BOARD_ITEM*>( m_Reference ) ); aFunction( static_cast<BOARD_ITEM*>( m_Value ) ); } catch( std::bad_function_call& e ) { DisplayError( NULL, wxT( "Error running MODULE::RunOnChildren" ) ); } }
/* Copy marked items, at new position = old position + offset */ void CopyMarkedItems( MODULE* module, wxPoint offset, bool aIncrement ) { if( module == NULL ) return; // Reference and value cannot be copied, they are unique. // Ensure they are not selected module->Reference().ClearFlags(); module->Value().ClearFlags(); for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() ) { if( !pad->IsSelected() ) continue; pad->ClearFlags( SELECTED ); D_PAD* NewPad = new D_PAD( *pad ); NewPad->SetParent( module ); NewPad->SetFlags( SELECTED ); module->Pads().PushFront( NewPad ); if( aIncrement ) NewPad->IncrementPadName( true, true ); } BOARD_ITEM* newItem; for( BOARD_ITEM* item = module->GraphicalItems(); item; item = item->Next() ) { if( !item->IsSelected() ) continue; item->ClearFlags( SELECTED ); newItem = (BOARD_ITEM*)item->Clone(); newItem->SetParent( module ); newItem->SetFlags( SELECTED ); module->GraphicalItems().PushFront( newItem ); } MoveMarkedItems( module, offset ); }
void MODULE::SetOrientation( double newangle ) { double angleChange = newangle - m_Orient; // change in rotation wxPoint pt; NORMALIZE_ANGLE_POS( newangle ); m_Orient = newangle; for( D_PAD* pad = m_Pads; pad; pad = pad->Next() ) { pt = pad->GetPos0(); pad->SetOrientation( pad->GetOrientation() + angleChange ); RotatePoint( &pt, m_Orient ); pad->SetPosition( GetPosition() + pt ); } // Update of the reference and value. m_Reference->SetDrawCoord(); m_Value->SetDrawCoord(); // Displace contours and text of the footprint. for( BOARD_ITEM* item = m_Drawings; item; item = item->Next() ) { if( item->Type() == PCB_MODULE_EDGE_T ) { EDGE_MODULE* edge = (EDGE_MODULE*) item; edge->SetDrawCoord(); } else if( item->Type() == PCB_MODULE_TEXT_T ) { TEXTE_MODULE* text = (TEXTE_MODULE*) item; text->SetDrawCoord(); } } CalculateBoundingBox(); }
void MODULE::ViewUpdate( int aUpdateFlags ) { if( !m_view ) return; // Update the module itself VIEW_ITEM::ViewUpdate( aUpdateFlags ); // Update pads for( D_PAD* pad = m_Pads.GetFirst(); pad; pad = pad->Next() ) pad->ViewUpdate( aUpdateFlags ); // Update module's drawing (mostly silkscreen) for( BOARD_ITEM* drawing = m_Drawings.GetFirst(); drawing; drawing = drawing->Next() ) drawing->ViewUpdate( aUpdateFlags ); // Update module's texts m_Reference->ViewUpdate( aUpdateFlags ); m_Value->ViewUpdate( aUpdateFlags ); }
void MODULE::ViewUpdate( int aUpdateFlags ) { if( !m_view ) return; // Update pads for( D_PAD* pad = m_Pads.GetFirst(); pad; pad = pad->Next() ) m_view->InvalidateItem( pad, aUpdateFlags ); // Update module's drawing (mostly silkscreen) for( BOARD_ITEM* drawing = m_Drawings.GetFirst(); drawing; drawing = drawing->Next() ) m_view->InvalidateItem( drawing, aUpdateFlags ); // Update module's texts m_view->InvalidateItem( m_Reference, aUpdateFlags ); m_view->InvalidateItem( m_Value, aUpdateFlags ); // Update the module itself m_view->InvalidateItem( this, aUpdateFlags ); }
void PCB_DRAW_PANEL_GAL::DisplayBoard( const BOARD* aBoard ) { m_view->Clear(); // Load zones for( int i = 0; i < aBoard->GetAreaCount(); ++i ) m_view->Add( (KIGFX::VIEW_ITEM*) ( aBoard->GetArea( i ) ) ); // Load drawings for( BOARD_ITEM* drawing = aBoard->m_Drawings; drawing; drawing = drawing->Next() ) m_view->Add( drawing ); // Load tracks for( TRACK* track = aBoard->m_Track; track; track = track->Next() ) m_view->Add( track ); // Load modules and its additional elements for( MODULE* module = aBoard->m_Modules; module; module = module->Next() ) { module->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, m_view, _1 ) ); m_view->Add( module ); } // Segzones (equivalent of ZONE_CONTAINER for legacy boards) for( SEGZONE* zone = aBoard->m_Zone; zone; zone = zone->Next() ) m_view->Add( zone ); // Ratsnest if( m_ratsnest ) { m_view->Remove( m_ratsnest ); delete m_ratsnest; } m_ratsnest = new KIGFX::RATSNEST_VIEWITEM( aBoard->GetRatsnest() ); m_view->Add( m_ratsnest ); UseColorScheme( aBoard->GetColorsSettings() ); m_view->RecacheAllItems( true ); }
/* Delete marked items */ void DeleteMarkedItems( MODULE* module ) { if( module == NULL ) return; D_PAD* next_pad; BOARD* board = module->GetBoard(); for( D_PAD* pad = module->Pads(); pad; pad = next_pad ) { next_pad = pad->Next(); if( !pad->IsSelected() ) continue; if( board ) board->PadDelete( pad ); else pad->DeleteStructure(); } BOARD_ITEM* next_item; for( BOARD_ITEM* item = module->GraphicalItems(); item; item = next_item ) { next_item = item->Next(); if( !item->IsSelected() ) continue; item->DeleteStructure(); } // Ref and value can be flagged, but cannot be deleted ClearMarkItems( module ); }
void PCB_BASE_FRAME::ResetModuleTextSizes( const wxString & aFilter, bool aRef, bool aValue, bool aOthers ) { BOARD_COMMIT commit( this ); int modTextWidth = GetDesignSettings().m_ModuleTextWidth; const wxSize& modTextSize = GetDesignSettings().m_ModuleTextSize; bool modified = false; // Change fields of footprints with fpid matching the filter for( MODULE* module = GetBoard()->m_Modules; module; module = module->Next() ) { if( !aFilter.IsEmpty() ) { if( ! WildCompareString( aFilter, FROM_UTF8( module->GetFPID().Format().c_str() ), false ) ) continue; } if( aRef ) { TEXTE_MODULE* item = &module->Reference(); if( item->GetTextSize() != GetDesignSettings().m_ModuleTextSize || item->GetThickness() != GetDesignSettings().m_ModuleTextWidth ) { commit.Modify( item ); item->SetThickness( modTextWidth ); item->SetTextSize( modTextSize ); modified = true; } } if( aValue ) { TEXTE_MODULE* item = &module->Value(); if( item->GetTextSize() != GetDesignSettings().m_ModuleTextSize || item->GetThickness() != GetDesignSettings().m_ModuleTextWidth ) { commit.Modify( item ); item->SetThickness( modTextWidth ); item->SetTextSize( modTextSize ); modified = true; } } if( aOthers ) { // Go through all other module text fields for( BOARD_ITEM* boardItem = module->GraphicalItemsList(); boardItem; boardItem = boardItem->Next() ) { if( boardItem->Type() == PCB_MODULE_TEXT_T ) { TEXTE_MODULE* item = static_cast<TEXTE_MODULE*>( boardItem ); if( item->GetTextSize() != GetDesignSettings().m_ModuleTextSize || item->GetThickness() != GetDesignSettings().m_ModuleTextWidth ) { commit.Modify( item ); item->SetThickness( modTextWidth ); item->SetTextSize( modTextSize ); modified = true; } } } } } if( modified ) { commit.Push( "Reset module text size" ); GetCanvas()->Refresh(); } }
void PCB_EDIT_FRAME::Block_SelectItems() { LSET layerMask; bool selectOnlyComplete = GetScreen()->m_BlockLocate.GetWidth() > 0 ; GetScreen()->m_BlockLocate.Normalize(); PICKED_ITEMS_LIST* itemsList = &GetScreen()->m_BlockLocate.GetItems(); ITEM_PICKER picker( NULL, UR_UNSPECIFIED ); // Add modules if( blockIncludeModules ) { for( MODULE* module = m_Pcb->m_Modules; module; module = module->Next() ) { LAYER_ID layer = module->GetLayer(); if( module->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) && ( !module->IsLocked() || blockIncludeLockedModules ) ) { if( blockIncludeItemsOnInvisibleLayers || m_Pcb->IsModuleLayerVisible( layer ) ) { picker.SetItem ( module ); itemsList->PushItem( picker ); } } } } // Add tracks and vias if( blockIncludeTracks ) { for( TRACK* track = m_Pcb->m_Track; track != NULL; track = track->Next() ) { if( track->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) ) { if( blockIncludeItemsOnInvisibleLayers || m_Pcb->IsLayerVisible( track->GetLayer() ) ) { picker.SetItem( track ); itemsList->PushItem( picker ); } } } } // Add graphic items layerMask = LSET( Edge_Cuts ); if( blockIncludeItemsOnTechLayers ) layerMask.set(); if( !blockIncludeBoardOutlineLayer ) layerMask.set( Edge_Cuts, false ); for( BOARD_ITEM* PtStruct = m_Pcb->m_Drawings; PtStruct != NULL; PtStruct = PtStruct->Next() ) { if( !m_Pcb->IsLayerVisible( PtStruct->GetLayer() ) && ! blockIncludeItemsOnInvisibleLayers) continue; bool select_me = false; switch( PtStruct->Type() ) { case PCB_LINE_T: if( !layerMask[PtStruct->GetLayer()] ) break; if( !PtStruct->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) ) break; select_me = true; // This item is in bloc: select it break; case PCB_TEXT_T: if( !blockIncludePcbTexts ) break; if( !PtStruct->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) ) break; select_me = true; // This item is in bloc: select it break; case PCB_TARGET_T: if( !layerMask[PtStruct->GetLayer()] ) break; if( !PtStruct->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) ) break; select_me = true; // This item is in bloc: select it break; case PCB_DIMENSION_T: if( !layerMask[PtStruct->GetLayer()] ) break; if( !PtStruct->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) ) break; select_me = true; // This item is in bloc: select it break; default: break; } if( select_me ) { picker.SetItem ( PtStruct ); itemsList->PushItem( picker ); } } // Add zones if( blockIncludeZones ) { for( int ii = 0; ii < m_Pcb->GetAreaCount(); ii++ ) { ZONE_CONTAINER* area = m_Pcb->GetArea( ii ); if( area->HitTest( GetScreen()->m_BlockLocate, selectOnlyComplete ) ) { if( blockIncludeItemsOnInvisibleLayers || m_Pcb->IsLayerVisible( area->GetLayer() ) ) { BOARD_ITEM* zone_c = (BOARD_ITEM*) area; picker.SetItem ( zone_c ); itemsList->PushItem( picker ); } } } } }
void DRC::testTexts() { std::vector<wxPoint> textShape; // a buffer to store the text shape (set of segments) std::vector<D_PAD*> padList = m_pcb->GetPads(); // Test text areas for vias, tracks and pads inside text areas for( BOARD_ITEM* item = m_pcb->m_Drawings; item; item = item->Next() ) { // Drc test only items on copper layers if( ! IsCopperLayer( item->GetLayer() ) ) continue; // only texts on copper layers are tested if( item->Type() != PCB_TEXT_T ) continue; textShape.clear(); // So far the bounding box makes up the text-area TEXTE_PCB* text = (TEXTE_PCB*) item; text->TransformTextShapeToSegmentList( textShape ); if( textShape.size() == 0 ) // Should not happen (empty text?) continue; for( TRACK* track = m_pcb->m_Track; track != NULL; track = track->Next() ) { if( ! track->IsOnLayer( item->GetLayer() ) ) continue; // Test the distance between each segment and the current track/via int min_dist = ( track->GetWidth() + text->GetThickness() ) /2 + track->GetClearance(NULL); if( track->Type() == PCB_TRACE_T ) { SEG segref( track->GetStart(), track->GetEnd() ); // Error condition: Distance between text segment and track segment is // smaller than the clearance of the segment for( unsigned jj = 0; jj < textShape.size(); jj += 2 ) { SEG segtest( textShape[jj], textShape[jj+1] ); int dist = segref.Distance( segtest ); if( dist < min_dist ) { addMarkerToPcb( fillMarker( track, text, DRCE_TRACK_INSIDE_TEXT, m_currentMarker ) ); m_currentMarker = nullptr; break; } } } else if( track->Type() == PCB_VIA_T ) { // Error condition: Distance between text segment and via is // smaller than the clearance of the via for( unsigned jj = 0; jj < textShape.size(); jj += 2 ) { SEG segtest( textShape[jj], textShape[jj+1] ); if( segtest.PointCloserThan( track->GetPosition(), min_dist ) ) { addMarkerToPcb( fillMarker( track, text, DRCE_VIA_INSIDE_TEXT, m_currentMarker ) ); m_currentMarker = nullptr; break; } } } } // Test pads for( unsigned ii = 0; ii < padList.size(); ii++ ) { D_PAD* pad = padList[ii]; if( ! pad->IsOnLayer( item->GetLayer() ) ) continue; wxPoint shape_pos = pad->ShapePos(); for( unsigned jj = 0; jj < textShape.size(); jj += 2 ) { /* In order to make some calculations more easier or faster, * pads and tracks coordinates will be made relative * to the segment origin */ wxPoint origin = textShape[jj]; // origin will be the origin of other coordinates m_segmEnd = textShape[jj+1] - origin; wxPoint delta = m_segmEnd; m_segmAngle = 0; // for a non horizontal or vertical segment Compute the segment angle // in tenths of degrees and its length if( delta.x || delta.y ) // delta.x == delta.y == 0 for vias { // Compute the segment angle in 0,1 degrees m_segmAngle = ArcTangente( delta.y, delta.x ); // Compute the segment length: we build an equivalent rotated segment, // this segment is horizontal, therefore dx = length RotatePoint( &delta, m_segmAngle ); // delta.x = length, delta.y = 0 } m_segmLength = delta.x; m_padToTestPos = shape_pos - origin; if( !checkClearanceSegmToPad( pad, text->GetThickness(), pad->GetClearance(NULL) ) ) { addMarkerToPcb( fillMarker( pad, text, DRCE_PAD_INSIDE_TEXT, m_currentMarker ) ); m_currentMarker = nullptr; break; } } } } }
void EDA_3D_CANVAS::buildTechLayers3DView( REPORTER* aErrorMessages, REPORTER* aActivity ) { BOARD* pcb = GetBoard(); bool useTextures = isRealisticMode() && isEnabled( FL_RENDER_TEXTURES ); // Number of segments to draw a circle using segments const int segcountforcircle = 18; double correctionFactor = 1.0 / cos( M_PI / (segcountforcircle * 2) ); const int segcountLowQuality = 12; // segments to draw a circle with low quality // to reduce time calculations // for holes and items which do not need // a fine representation double correctionFactorLQ = 1.0 / cos( M_PI / (segcountLowQuality * 2) ); // segments to draw a circle to build texts. Is is used only to build // the shape of each segment of the stroke font, therefore no need to have // many segments per circle. const int segcountInStrokeFont = 8; SHAPE_POLY_SET bufferPolys; SHAPE_POLY_SET allLayerHoles; // Contains through holes, calculated only once SHAPE_POLY_SET bufferPcbOutlines; // stores the board main outlines // Build a polygon from edge cut items wxString msg; if( !pcb->GetBoardPolygonOutlines( bufferPcbOutlines, allLayerHoles, &msg ) ) { if( aErrorMessages ) { msg << wxT("\n") << _("Unable to calculate the board outlines.\n" "Therefore use the board boundary box.") << wxT("\n\n"); aErrorMessages->Report( msg, REPORTER::RPT_WARNING ); } } // Build board holes, with no optimization of large holes shape. buildBoardThroughHolesPolygonList( allLayerHoles, segcountLowQuality, false ); // draw graphic items, on technical layers static const LAYER_ID teckLayerList[] = { B_Adhes, F_Adhes, B_Paste, F_Paste, B_SilkS, F_SilkS, B_Mask, F_Mask, }; // User layers are not drawn here, only technical layers for( LSEQ seq = LSET::AllTechMask().Seq( teckLayerList, DIM( teckLayerList ) ); seq; ++seq ) { LAYER_ID layer = *seq; if( !is3DLayerEnabled( layer ) ) continue; if( layer == Edge_Cuts && isEnabled( FL_SHOW_BOARD_BODY ) ) continue; if( aActivity ) aActivity->Report( wxString::Format( _( "Build layer %s" ), LSET::Name( layer ) ) ); bufferPolys.RemoveAllContours(); for( BOARD_ITEM* item = pcb->m_Drawings; item; item = item->Next() ) { if( !item->IsOnLayer( layer ) ) continue; switch( item->Type() ) { case PCB_LINE_T: ( (DRAWSEGMENT*) item )->TransformShapeWithClearanceToPolygon( bufferPolys, 0, segcountforcircle, correctionFactor ); break; case PCB_TEXT_T: ( (TEXTE_PCB*) item )->TransformShapeWithClearanceToPolygonSet( bufferPolys, 0, segcountLowQuality, 1.0 ); break; default: break; } } for( MODULE* module = pcb->m_Modules; module; module = module->Next() ) { if( layer == F_SilkS || layer == B_SilkS ) { // On silk screen layers, the pad shape is only the pad outline // never a filled shape D_PAD* pad = module->Pads(); int linewidth = g_DrawDefaultLineThickness; for( ; pad; pad = pad->Next() ) { if( !pad->IsOnLayer( layer ) ) continue; buildPadShapeThickOutlineAsPolygon( pad, bufferPolys, linewidth, segcountforcircle, correctionFactor ); } } else module->TransformPadsShapesWithClearanceToPolygon( layer, bufferPolys, 0, segcountforcircle, correctionFactor ); // On tech layers, use a poor circle approximation, only for texts (stroke font) module->TransformGraphicShapesWithClearanceToPolygonSet( layer, bufferPolys, 0, segcountforcircle, correctionFactor, segcountInStrokeFont ); } // Draw non copper zones if( isEnabled( FL_ZONE ) ) { for( int ii = 0; ii < pcb->GetAreaCount(); ii++ ) { ZONE_CONTAINER* zone = pcb->GetArea( ii ); if( !zone->IsOnLayer( layer ) ) continue; zone->TransformSolidAreasShapesToPolygonSet( bufferPolys, segcountLowQuality, correctionFactorLQ ); } } // bufferPolys contains polygons to merge. Many overlaps . // Calculate merged polygons and remove pads and vias holes if( bufferPolys.IsEmpty() ) continue; // Solder mask layers are "negative" layers. // Shapes should be removed from the full board area. if( layer == B_Mask || layer == F_Mask ) { SHAPE_POLY_SET cuts = bufferPolys; bufferPolys = bufferPcbOutlines; cuts.Append(allLayerHoles); cuts.Simplify(); bufferPolys.BooleanSubtract( cuts ); } // Remove holes from Solder paste layers and silkscreen else if( layer == B_Paste || layer == F_Paste || layer == B_SilkS || layer == F_SilkS ) { bufferPolys.BooleanSubtract( allLayerHoles ); } int thickness = 0; if( layer != B_Mask && layer != F_Mask ) thickness = GetPrm3DVisu().GetLayerObjectThicknessBIU( layer ); int zpos = GetPrm3DVisu().GetLayerZcoordBIU( layer ); if( layer == Edge_Cuts ) { thickness = GetPrm3DVisu().GetLayerZcoordBIU( F_Cu ) - GetPrm3DVisu().GetLayerZcoordBIU( B_Cu ); zpos = GetPrm3DVisu().GetLayerZcoordBIU( B_Cu ) + (thickness / 2); } else { // for Draw3D_SolidHorizontalPolyPolygons, zpos it the middle between bottom and top // sides. // However for top layers, zpos should be the bottom layer pos, // and for bottom layers, zpos should be the top layer pos. if( Get3DLayer_Z_Orientation( layer ) > 0 ) zpos += thickness/2; else zpos -= thickness/2 ; } float zNormal = 1.0f; // When using thickness it will draw first the top and then botton (with z inverted) // If we are not using thickness, then the znormal must face the layer direction // because it will draw just one plane if( !thickness ) zNormal = Get3DLayer_Z_Orientation( layer ); setGLTechLayersColor( layer ); Draw3D_SolidHorizontalPolyPolygons( bufferPolys, zpos, thickness, GetPrm3DVisu().m_BiuTo3Dunits, useTextures, zNormal ); } }
void EDA_3D_CANVAS::buildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList, REPORTER* aErrorMessages, REPORTER* aActivity ) { BOARD* pcb = GetBoard(); // If FL_RENDER_SHOW_HOLES_IN_ZONES is true, holes are correctly removed from copper zones areas. // If FL_RENDER_SHOW_HOLES_IN_ZONES is false, holes are not removed from copper zones areas, // but the calculation time is twice shorter. bool remove_Holes = isEnabled( FL_RENDER_SHOW_HOLES_IN_ZONES ); bool realistic_mode = isRealisticMode(); bool useTextures = isRealisticMode() && isEnabled( FL_RENDER_TEXTURES ); // Number of segments to convert a circle to polygon // We use 2 values: the first gives a good shape (for instanes rond pads) // the second is used to speed up calculations, when a poor approximation is acceptable (holes) const int segcountforcircle = 18; double correctionFactor = 1.0 / cos( M_PI / (segcountforcircle * 2.0) ); const int segcountLowQuality = 12; // segments to draw a circle with low quality // to reduce time calculations // for holes and items which do not need // a fine representation double correctionFactorLQ = 1.0 / cos( M_PI / (segcountLowQuality * 2.0) ); SHAPE_POLY_SET bufferPolys; // copper areas: tracks, pads and filled zones areas // when holes are removed from zones SHAPE_POLY_SET bufferPcbOutlines; // stores the board main outlines SHAPE_POLY_SET bufferZonesPolys; // copper filled zones areas // when holes are not removed from zones SHAPE_POLY_SET currLayerHoles; // Contains holes for the current layer SHAPE_POLY_SET allLayerHoles; // Contains holes for all layers // Build a polygon from edge cut items wxString msg; if( !pcb->GetBoardPolygonOutlines( bufferPcbOutlines, allLayerHoles, &msg ) ) { if( aErrorMessages ) { msg << wxT("\n") << _("Unable to calculate the board outlines.\n" "Therefore use the board boundary box.") << wxT("\n\n"); aErrorMessages->Report( msg, REPORTER::RPT_WARNING ); } } // Build board holes, with optimization of large holes shape. buildBoardThroughHolesPolygonList( allLayerHoles, segcountLowQuality, true ); LSET cu_set = LSET::AllCuMask( GetPrm3DVisu().m_CopperLayersCount ); glNewList( aBoardList, GL_COMPILE ); for( LSEQ cu = cu_set.CuStack(); cu; ++cu ) { LAYER_ID layer = *cu; // Skip non enabled layers in normal mode, // and internal layers in realistic mode if( !is3DLayerEnabled( layer ) ) continue; if( aActivity ) aActivity->Report( wxString::Format( _( "Build layer %s" ), LSET::Name( layer ) ) ); bufferPolys.RemoveAllContours(); bufferZonesPolys.RemoveAllContours(); currLayerHoles.RemoveAllContours(); // Draw track shapes: for( TRACK* track = pcb->m_Track; track; track = track->Next() ) { if( !track->IsOnLayer( layer ) ) continue; track->TransformShapeWithClearanceToPolygon( bufferPolys, 0, segcountforcircle, correctionFactor ); // Add blind/buried via holes if( track->Type() == PCB_VIA_T ) { VIA *via = static_cast<VIA*>( track ); if( via->GetViaType() == VIA_THROUGH ) continue; // already done int holediameter = via->GetDrillValue(); int thickness = GetPrm3DVisu().GetCopperThicknessBIU(); int hole_outer_radius = (holediameter + thickness) / 2; TransformCircleToPolygon( currLayerHoles, via->GetStart(), hole_outer_radius, segcountLowQuality ); } } // draw pad shapes for( MODULE* module = pcb->m_Modules; module; module = module->Next() ) { // Note: NPTH pads are not drawn on copper layers when the pad // has same shape as its hole module->TransformPadsShapesWithClearanceToPolygon( layer, bufferPolys, 0, segcountforcircle, correctionFactor, true ); // Micro-wave modules may have items on copper layers module->TransformGraphicShapesWithClearanceToPolygonSet( layer, bufferPolys, 0, segcountforcircle, correctionFactor ); // pad holes are already in list. } // Draw copper zones. Note: // * if the holes are removed from copper zones // the polygons are stored in bufferPolys (which contains all other polygons) // * if the holes are NOT removed from copper zones // the polygons are stored in bufferZonesPolys if( isEnabled( FL_ZONE ) ) { for( int ii = 0; ii < pcb->GetAreaCount(); ii++ ) { ZONE_CONTAINER* zone = pcb->GetArea( ii ); LAYER_NUM zonelayer = zone->GetLayer(); if( zonelayer == layer ) { zone->TransformSolidAreasShapesToPolygonSet( remove_Holes ? bufferPolys : bufferZonesPolys, segcountLowQuality, correctionFactorLQ ); } } } // draw graphic items on copper layers (texts) for( BOARD_ITEM* item = pcb->m_Drawings; item; item = item->Next() ) { if( !item->IsOnLayer( layer ) ) continue; switch( item->Type() ) { case PCB_LINE_T: // should not exist on copper layers ( (DRAWSEGMENT*) item )->TransformShapeWithClearanceToPolygon( bufferPolys, 0, segcountforcircle, correctionFactor ); break; case PCB_TEXT_T: ( (TEXTE_PCB*) item )->TransformShapeWithClearanceToPolygonSet( bufferPolys, 0, segcountLowQuality, correctionFactor ); break; default: break; } } // bufferPolys contains polygons to merge. Many overlaps . // Calculate merged polygons if( bufferPolys.IsEmpty() ) continue; // Use Clipper lib to subtract holes to copper areas if( currLayerHoles.OutlineCount() ) { currLayerHoles.Append(allLayerHoles); currLayerHoles.Simplify(); bufferPolys.BooleanSubtract( currLayerHoles ); } else bufferPolys.BooleanSubtract( allLayerHoles ); int thickness = GetPrm3DVisu().GetLayerObjectThicknessBIU( layer ); int zpos = GetPrm3DVisu().GetLayerZcoordBIU( layer ); float zNormal = 1.0f; // When using thickness it will draw first the top and then botton (with z inverted) // If we are not using thickness, then the z-normal has to match the layer direction // because just one plane will be drawn if( !thickness ) zNormal = Get3DLayer_Z_Orientation( layer ); if( realistic_mode ) { setGLCopperColor(); } else { EDA_COLOR_T color = g_ColorsSettings.GetLayerColor( layer ); SetGLColor( color ); } // If holes are removed from copper zones, bufferPolys contains all polygons // to draw (tracks+zones+texts). Draw3D_SolidHorizontalPolyPolygons( bufferPolys, zpos, thickness, GetPrm3DVisu().m_BiuTo3Dunits, useTextures, zNormal ); // If holes are not removed from copper zones (for calculation time reasons, // the zone polygons are stored in bufferZonesPolys and have to be drawn now: if( !bufferZonesPolys.IsEmpty() ) { Draw3D_SolidHorizontalPolyPolygons( bufferZonesPolys, zpos, thickness, GetPrm3DVisu().m_BiuTo3Dunits, useTextures, zNormal ); } } if( aActivity ) aActivity->Report( _( "Build board body" ) ); // Draw plated vertical holes inside the board, but not always. They are drawn: // - if the board body is not shown, to show the holes. // - or if the copper thickness is shown if( !isEnabled( FL_SHOW_BOARD_BODY ) || isEnabled( FL_USE_COPPER_THICKNESS ) ) { // Draw vias holes (vertical cylinders) for( const TRACK* track = pcb->m_Track; track; track = track->Next() ) { if( track->Type() == PCB_VIA_T ) { const VIA *via = static_cast<const VIA*>(track); draw3DViaHole( via ); } } // Draw pads holes (vertical cylinders) for( const MODULE* module = pcb->m_Modules; module; module = module->Next() ) { for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() ) if( pad->GetAttribute () != PAD_HOLE_NOT_PLATED ) draw3DPadHole( pad ); } } glEndList(); // Build the body board: glNewList( aBodyOnlyList, GL_COMPILE ); if( isRealisticMode() ) { setGLEpoxyColor( 1.00 ); } else { EDA_COLOR_T color = g_ColorsSettings.GetLayerColor( Edge_Cuts ); SetGLColor( color, 0.7 ); } float copper_thickness = GetPrm3DVisu().GetCopperThicknessBIU(); // a small offset between substrate and external copper layer to avoid artifacts // when drawing copper items on board float epsilon = Millimeter2iu( 0.01 ); float zpos = GetPrm3DVisu().GetLayerZcoordBIU( B_Cu ); float board_thickness = GetPrm3DVisu().GetLayerZcoordBIU( F_Cu ) - GetPrm3DVisu().GetLayerZcoordBIU( B_Cu ); // items on copper layers and having a thickness = copper_thickness // are drawn from zpos - copper_thickness/2 to zpos + copper_thickness // therefore substrate position is copper_thickness/2 to // substrate_height - copper_thickness/2 zpos += (copper_thickness + epsilon) / 2.0f; board_thickness -= copper_thickness + epsilon; bufferPcbOutlines.BooleanSubtract( allLayerHoles ); if( !bufferPcbOutlines.IsEmpty() ) { Draw3D_SolidHorizontalPolyPolygons( bufferPcbOutlines, zpos + board_thickness / 2.0, board_thickness, GetPrm3DVisu().m_BiuTo3Dunits, useTextures, 1.0f ); } glEndList(); }
// Redraw the BOARD items but not cursors, axis or grid void BOARD::Draw( EDA_DRAW_PANEL* aPanel, wxDC* DC, GR_DRAWMODE aDrawMode, const wxPoint& offset ) { /* The order of drawing is flexible on some systems and not on others. For * OSes which use OR to draw, the order is not important except for the * effect of the highlight and its relationship to markers. See comment * below. * This order independence comes from the fact that a binary OR operation is * commutative in nature. * However on the OSX, the OR operation is not used, and so this sequence * below is chosen to give MODULEs the highest visible priority. */ /* Draw all tracks and zones. As long as dark colors are used for the * tracks, Then the OR draw mode should show tracks underneath other * tracks. But a white track will cover any other color since it has * more bits to OR in. */ for( TRACK* track = m_Track; track; track = track->Next() ) { if( track->IsMoving() ) continue; track->Draw( aPanel, DC, aDrawMode ); } // Draw areas (i.e. zones) for( int ii = 0; ii < GetAreaCount(); ii++ ) { ZONE_CONTAINER* zone = GetArea( ii ); // Areas must be drawn here only if not moved or dragged, // because these areas are drawn by ManageCursor() in a specific manner if( ( zone->GetEditFlags() & (IN_EDIT | IS_DRAGGED | IS_MOVED) ) == 0 ) { zone->Draw( aPanel, DC, aDrawMode ); zone->DrawFilledArea( aPanel, DC, aDrawMode ); } } // Draw the graphic items for( BOARD_ITEM* item = m_Drawings; item; item = item->Next() ) { if( item->IsMoving() ) continue; switch( item->Type() ) { case PCB_DIMENSION_T: case PCB_TEXT_T: case PCB_TARGET_T: case PCB_LINE_T: item->Draw( aPanel, DC, aDrawMode ); break; default: break; } } LSET all_cu = LSET::AllCuMask(); for( MODULE* module = m_Modules; module; module = module->Next() ) { bool display = true; LSET layerMask = all_cu; if( module->IsMoving() ) continue; if( !IsElementVisible( LAYER_MOD_FR ) ) { if( module->GetLayer() == F_Cu ) display = false; layerMask.set( F_Cu, false ); } if( !IsElementVisible( LAYER_MOD_BK ) ) { if( module->GetLayer() == B_Cu ) display = false; layerMask.set( B_Cu, false ); } if( display ) module->Draw( aPanel, DC, aDrawMode ); else Trace_Pads_Only( aPanel, DC, module, 0, 0, layerMask, aDrawMode ); } // draw the BOARD's markers last, otherwise the high light will erase any marker on a pad for( unsigned i = 0; i < m_markers.size(); ++i ) { m_markers[i]->Draw( aPanel, DC, aDrawMode ); } }
/* Traces the outline of the search block structures * The entire block follows the cursor */ static void DrawMovingBlockOutlines( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition, bool aErase ) { BASE_SCREEN* screen = aPanel->GetScreen(); FOOTPRINT_EDIT_FRAME* moduleEditFrame = FOOTPRINT_EDIT_FRAME::GetActiveFootprintEditor( aPanel->GetParent() ); wxASSERT( moduleEditFrame ); MODULE* currentModule = moduleEditFrame->GetBoard()->m_Modules; BLOCK_SELECTOR* block = &screen->m_BlockLocate; GRSetDrawMode( aDC, g_XorMode ); if( aErase ) { block->Draw( aPanel, aDC, block->GetMoveVector(), g_XorMode, block->GetColor() ); if( currentModule ) { wxPoint move_offset = -block->GetMoveVector(); BOARD_ITEM* item = currentModule->GraphicalItems(); for( ; item != NULL; item = item->Next() ) { if( !item->IsSelected() ) continue; switch( item->Type() ) { case PCB_MODULE_TEXT_T: case PCB_MODULE_EDGE_T: item->Draw( aPanel, aDC, g_XorMode, move_offset ); break; default: break; } } D_PAD* pad = currentModule->Pads(); for( ; pad != NULL; pad = pad->Next() ) { if( !pad->IsSelected() ) continue; pad->Draw( aPanel, aDC, g_XorMode, move_offset ); } } } // Repaint new view. block->SetMoveVector( moduleEditFrame->GetCrossHairPosition() - block->GetLastCursorPosition() ); block->Draw( aPanel, aDC, block->GetMoveVector(), g_XorMode, block->GetColor() ); if( currentModule ) { BOARD_ITEM* item = currentModule->GraphicalItems(); wxPoint move_offset = - block->GetMoveVector(); for( ; item != NULL; item = item->Next() ) { if( !item->IsSelected() ) continue; switch( item->Type() ) { case PCB_MODULE_TEXT_T: case PCB_MODULE_EDGE_T: item->Draw( aPanel, aDC, g_XorMode, move_offset ); break; default: break; } } D_PAD* pad = currentModule->Pads(); for( ; pad != NULL; pad = pad->Next() ) { if( !pad->IsSelected() ) continue; pad->Draw( aPanel, aDC, g_XorMode, move_offset ); } } }
MODULE::MODULE( const MODULE& aModule ) : BOARD_ITEM_CONTAINER( aModule ) { m_Pos = aModule.m_Pos; m_fpid = aModule.m_fpid; m_Attributs = aModule.m_Attributs; m_ModuleStatus = aModule.m_ModuleStatus; m_Orient = aModule.m_Orient; m_BoundaryBox = aModule.m_BoundaryBox; m_CntRot90 = aModule.m_CntRot90; m_CntRot180 = aModule.m_CntRot180; m_LastEditTime = aModule.m_LastEditTime; m_Link = aModule.m_Link; m_Path = aModule.m_Path; //is this correct behavior? m_LocalClearance = aModule.m_LocalClearance; m_LocalSolderMaskMargin = aModule.m_LocalSolderMaskMargin; m_LocalSolderPasteMargin = aModule.m_LocalSolderPasteMargin; m_LocalSolderPasteMarginRatio = aModule.m_LocalSolderPasteMarginRatio; m_ZoneConnection = aModule.m_ZoneConnection; m_ThermalWidth = aModule.m_ThermalWidth; m_ThermalGap = aModule.m_ThermalGap; // Copy reference and value. m_Reference = new TEXTE_MODULE( *aModule.m_Reference ); m_Reference->SetParent( this ); m_Value = new TEXTE_MODULE( *aModule.m_Value ); m_Value->SetParent( this ); // Copy auxiliary data: Pads for( D_PAD* pad = aModule.m_Pads; pad; pad = pad->Next() ) { Add( new D_PAD( *pad ) ); } // Copy auxiliary data: Drawings for( BOARD_ITEM* item = aModule.m_Drawings; item; item = item->Next() ) { switch( item->Type() ) { case PCB_MODULE_TEXT_T: case PCB_MODULE_EDGE_T: Add( static_cast<BOARD_ITEM*>( item->Clone() ) ); break; default: wxLogMessage( wxT( "Class MODULE copy constructor internal error: unknown type" ) ); break; } } // Copy auxiliary data: 3D_Drawings info m_3D_Drawings = aModule.m_3D_Drawings; m_Doc = aModule.m_Doc; m_KeyWord = aModule.m_KeyWord; m_arflag = 0; // Ensure auxiliary data is up to date CalculateBoundingBox(); m_initial_comments = aModule.m_initial_comments ? new wxArrayString( *aModule.m_initial_comments ) : 0; }