bool PCB_EDIT_FRAME::Other_Layer_Route( TRACK* aTrack, wxDC* DC ) { unsigned itmp; if( aTrack == NULL ) { if( GetActiveLayer() != GetScreen()->m_Route_Layer_TOP ) SetActiveLayer( GetScreen()->m_Route_Layer_TOP ); else SetActiveLayer( GetScreen()->m_Route_Layer_BOTTOM ); UpdateStatusBar(); return true; } // Avoid more than one via on the current location: if( GetBoard()->GetViaByPosition( g_CurrentTrackSegment->GetEnd(), g_CurrentTrackSegment->GetLayer() ) ) return false; for( TRACK* segm = g_FirstTrackSegment; segm; segm = segm->Next() ) { if( segm->Type() == PCB_VIA_T && g_CurrentTrackSegment->GetEnd() == segm->GetStart() ) return false; } // Is the current segment Ok (no DRC error) ? if( g_Drc_On ) { if( BAD_DRC==m_drc->Drc( g_CurrentTrackSegment, GetBoard()->m_Track ) ) // DRC error, the change layer is not made return false; // Handle 2 segments. if( g_TwoSegmentTrackBuild && g_CurrentTrackSegment->Back() ) { if( BAD_DRC == m_drc->Drc( g_CurrentTrackSegment->Back(), GetBoard()->m_Track ) ) return false; } } /* Save current state before placing a via. * If the via cannot be placed this current state will be reused */ itmp = g_CurrentTrackList.GetCount(); Begin_Route( g_CurrentTrackSegment, DC ); m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); // create the via VIA* via = new VIA( GetBoard() ); via->SetFlags( IS_NEW ); via->SetViaType( GetDesignSettings().m_CurrentViaType ); via->SetNetCode( GetBoard()->GetHighLightNetCode() ); via->SetPosition( g_CurrentTrackSegment->GetEnd() ); // for microvias, the size and hole will be changed later. via->SetWidth( GetDesignSettings().GetCurrentViaSize()); via->SetDrill( GetDesignSettings().GetCurrentViaDrill() ); // Usual via is from copper to component. // layer pair is B_Cu and F_Cu. via->SetLayerPair( B_Cu, F_Cu ); LAYER_ID first_layer = GetActiveLayer(); LAYER_ID last_layer; // prepare switch to new active layer: if( first_layer != GetScreen()->m_Route_Layer_TOP ) last_layer = GetScreen()->m_Route_Layer_TOP; else last_layer = GetScreen()->m_Route_Layer_BOTTOM; // Adjust the actual via layer pair switch( via->GetViaType() ) { case VIA_BLIND_BURIED: via->SetLayerPair( first_layer, last_layer ); break; case VIA_MICROVIA: // from external to the near neighbor inner layer { LAYER_ID last_inner_layer = ToLAYER_ID( ( GetBoard()->GetCopperLayerCount() - 2 ) ); if( first_layer == B_Cu ) last_layer = last_inner_layer; else if( first_layer == F_Cu ) last_layer = In1_Cu; else if( first_layer == last_inner_layer ) last_layer = B_Cu; else if( first_layer == In1_Cu ) last_layer = F_Cu; // else error: will be removed later via->SetLayerPair( first_layer, last_layer ); // Update diameter and hole size, which where set previously // for normal vias NETINFO_ITEM* net = via->GetNet(); via->SetWidth( net->GetMicroViaSize() ); via->SetDrill( net->GetMicroViaDrillSize() ); } break; default: break; } if( g_Drc_On && BAD_DRC == m_drc->Drc( via, GetBoard()->m_Track ) ) { // DRC fault: the Via cannot be placed here ... delete via; m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); // delete the track(s) added in Begin_Route() while( g_CurrentTrackList.GetCount() > itmp ) { Delete_Segment( DC, g_CurrentTrackSegment ); } SetCurItem( g_CurrentTrackSegment, false ); // Refresh DRC diag, erased by previous calls if( m_drc->GetCurrentMarker() ) SetMsgPanel( m_drc->GetCurrentMarker() ); return false; } SetActiveLayer( last_layer ); TRACK* lastNonVia = g_CurrentTrackSegment; /* A new via was created. It was Ok. */ g_CurrentTrackList.PushBack( via ); /* The via is now in linked list and we need a new track segment * after the via, starting at via location. * it will become the new current segment (from via to the mouse cursor) */ TRACK* track = (TRACK*)lastNonVia->Clone(); /* the above creates a new segment from the last entered segment, with the * current width, flags, netcode, etc... values. * layer, start and end point are not correct, * and will be modified next */ // set the layer to the new value track->SetLayer( GetActiveLayer() ); /* the start point is the via position and the end point is the cursor * which also is on the via (will change when moving mouse) */ track->SetEnd( via->GetStart() ); track->SetStart( via->GetStart() ); g_CurrentTrackList.PushBack( track ); if( g_TwoSegmentTrackBuild ) { // Create a second segment (we must have 2 track segments to adjust) g_CurrentTrackList.PushBack( (TRACK*)g_CurrentTrackSegment->Clone() ); } m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); SetMsgPanel( via ); UpdateStatusBar(); return true; }
int PCB_EDIT_FRAME::SetTrackSegmentWidth( TRACK* aTrackItem, PICKED_ITEMS_LIST* aItemsListPicker, bool aUseNetclassValue ) { int return_code = TRACK_ACTION_NONE; int initial_width; int new_width; int initial_drill = -1; int new_drill = -1; NETINFO_ITEM* net = NULL; if( aUseNetclassValue ) net = aTrackItem->GetNet(); initial_width = aTrackItem->GetWidth(); if( net ) new_width = net->GetTrackWidth(); else new_width = GetDesignSettings().GetCurrentTrackWidth(); if( aTrackItem->Type() == PCB_VIA_T ) { const VIA *via = static_cast<const VIA *>( aTrackItem ); // Micro vias have a size only defined in their netclass // (no specific values defined by a table of specific value) // Ensure the netclass is accessible: if( via->GetViaType() == VIA_MICROVIA && net == NULL ) net = aTrackItem->GetNet(); // Get the draill value, regardless it is default or specific initial_drill = via->GetDrillValue(); if( net ) { new_width = net->GetViaSize(); new_drill = net->GetViaDrillSize(); } else { new_width = GetDesignSettings().GetCurrentViaSize(); new_drill = GetDesignSettings().GetCurrentViaDrill(); } if( via->GetViaType() == VIA_MICROVIA ) { if( net ) { new_width = net->GetMicroViaSize(); new_drill = net->GetMicroViaDrillSize(); } else { // Should not occur } } // Old versions set a drill value <= 0, when the default netclass it used // but it could be better to set the drill value to the actual value // to avoid issues for existing vias, if the default drill value is modified // in the netclass, and not in current vias. if( via->GetDrill() <= 0 ) // means default netclass drill value used { initial_drill = -1; // Force drill vias re-initialization } } aTrackItem->SetWidth( new_width ); // make a DRC test because the new size is bigger than the old size if( initial_width < new_width ) { int diagdrc = OK_DRC; return_code = TRACK_ACTION_SUCCESS; if( Settings().m_legacyDrcOn ) diagdrc = m_drc->DrcOnCreatingTrack( aTrackItem, GetBoard()->m_Track ); if( diagdrc != OK_DRC ) return_code = TRACK_ACTION_DRC_ERROR; } else if( initial_width > new_width ) { return_code = TRACK_ACTION_SUCCESS; } else if( (aTrackItem->Type() == PCB_VIA_T) ) { // if a via has its drill value changed, force change if( initial_drill != new_drill ) return_code = TRACK_ACTION_SUCCESS; } if( return_code == TRACK_ACTION_SUCCESS ) { OnModify(); if( aItemsListPicker ) { aTrackItem->SetWidth( initial_width ); ITEM_PICKER picker( aTrackItem, UR_CHANGED ); picker.SetLink( aTrackItem->Clone() ); aItemsListPicker->PushItem( picker ); aTrackItem->SetWidth( new_width ); if( aTrackItem->Type() == PCB_VIA_T ) { // Set new drill value. Note: currently microvias have only a default drill value VIA *via = static_cast<VIA *>( aTrackItem ); if( new_drill > 0 ) via->SetDrill( new_drill ); else via->SetDrillDefault(); } } } else { aTrackItem->SetWidth( initial_width ); } return return_code; }
bool PCB_EDIT_FRAME::SetTrackSegmentWidth( TRACK* aTrackItem, PICKED_ITEMS_LIST* aItemsListPicker, bool aUseNetclassValue ) { /* Modify one track segment width or one via diameter and drill (using DRC control). * Basic function used by other routines when editing tracks or vias * aTrackItem = the track segment or via to modify * aItemsListPicker = the list picker to use for an undo command (can be NULL) * aUseNetclassValue = true to use NetClass value, false to use BOARD::m_designSettings value * return true if done, false if no not change (due to DRC error) */ int initial_width, new_width; int initial_drill = -1,new_drill = -1; bool change_ok = false; NETINFO_ITEM* net = NULL; if( aUseNetclassValue ) net = aTrackItem->GetNet(); initial_width = aTrackItem->GetWidth(); if( net ) new_width = net->GetTrackWidth(); else new_width = GetDesignSettings().GetCurrentTrackWidth(); if( aTrackItem->Type() == PCB_VIA_T ) { const VIA *via = static_cast<const VIA *>( aTrackItem ); // Micro vias have a size only defined in their netclass // (no specific values defined by a table of specific value) // Ensure the netclass is accessible: if( via->GetViaType() == VIA_MICROVIA && net == NULL ) net = aTrackItem->GetNet(); // Get the draill value, regardless it is default or specific initial_drill = via->GetDrillValue(); if( net ) { new_width = net->GetViaSize(); new_drill = net->GetViaDrillSize(); } else { new_width = GetDesignSettings().GetCurrentViaSize(); new_drill = GetDesignSettings().GetCurrentViaDrill(); } if( via->GetViaType() == VIA_MICROVIA ) { if( net ) { new_width = net->GetMicroViaSize(); new_drill = net->GetMicroViaDrillSize(); } else { // Should not occur } } // Old versions set a drill value <= 0, when the default netclass it used // but it could be better to set the drill value to the actual value // to avoid issues for existing vias, if the default drill value is modified // in the netclass, and not in current vias. if( via->GetDrill() <= 0 ) // means default netclass drill value used { initial_drill = -1; // Force drill vias re-initialization } } aTrackItem->SetWidth( new_width ); // make a DRC test because the new size is bigger than the old size if( initial_width < new_width ) { int diagdrc = OK_DRC; if( g_Drc_On ) diagdrc = m_drc->Drc( aTrackItem, GetBoard()->m_Track ); if( diagdrc == OK_DRC ) change_ok = true; } else if( initial_width > new_width ) { change_ok = true; } else if( (aTrackItem->Type() == PCB_VIA_T) ) { // if a via has its drill value changed, force change if( initial_drill != new_drill ) change_ok = true; } if( change_ok ) { OnModify(); if( aItemsListPicker ) { aTrackItem->SetWidth( initial_width ); ITEM_PICKER picker( aTrackItem, UR_CHANGED ); picker.SetLink( aTrackItem->Clone() ); aItemsListPicker->PushItem( picker ); aTrackItem->SetWidth( new_width ); if( aTrackItem->Type() == PCB_VIA_T ) { // Set new drill value. Note: currently microvias have only a default drill value VIA *via = static_cast<VIA *>( aTrackItem ); if( new_drill > 0 ) via->SetDrill( new_drill ); else via->SetDrillDefault(); } } } else { aTrackItem->SetWidth( initial_width ); } return change_ok; }
void VIA::GetMsgPanelInfoBase( std::vector< MSG_PANEL_ITEM >& aList ) { wxString msg; BOARD* board = GetBoard(); switch( GetViaType() ) { default: case VIA_NOT_DEFINED: msg = wxT( "???" ); // Not used yet, does not exist currently break; case VIA_MICROVIA: msg = _( "Micro Via" ); // from external layer (TOP or BOTTOM) from // the near neighbor inner layer only break; case VIA_BLIND_BURIED: msg = _( "Blind/Buried Via" ); // from inner or external to inner // or external layer (no restriction) break; case VIA_THROUGH: msg = _( "Through Via" ); // Usual via (from TOP to BOTTOM layer only ) break; } aList.push_back( MSG_PANEL_ITEM( _( "Type" ), msg, DARKCYAN ) ); GetMsgPanelInfoBase_Common( aList ); // Display layer pair PCB_LAYER_ID top_layer, bottom_layer; LayerPair( &top_layer, &bottom_layer ); if( board ) msg = board->GetLayerName( top_layer ) + wxT( "/" ) + board->GetLayerName( bottom_layer ); else msg.Printf( wxT( "%d/%d" ), top_layer, bottom_layer ); aList.push_back( MSG_PANEL_ITEM( _( "Layers" ), msg, BROWN ) ); // Display width msg = ::CoordinateToString( (unsigned) m_Width ); // Display diameter value: aList.push_back( MSG_PANEL_ITEM( _( "Diameter" ), msg, DARKCYAN ) ); // Display drill value int drill_value = GetDrillValue(); msg = ::CoordinateToString( drill_value ); wxString title = _( "Drill" ); title += wxT( " " ); bool drl_specific = true; if( GetBoard() ) { NETINFO_ITEM* net = GetNet(); int drill_class_value = 0; if( net ) { if( GetViaType() == VIA_MICROVIA ) drill_class_value = net->GetMicroViaDrillSize(); else drill_class_value = net->GetViaDrillSize(); } drl_specific = drill_value != drill_class_value; } if( drl_specific ) title += _( "(Specific)" ); else title += _( "(NetClass)" ); aList.push_back( MSG_PANEL_ITEM( title, msg, RED ) ); }
void VIA::Draw( EDA_DRAW_PANEL* panel, wxDC* aDC, GR_DRAWMODE aDrawMode, const wxPoint& aOffset ) { wxCHECK_RET( panel != NULL, wxT( "VIA::Draw panel cannot be NULL." ) ); int radius; LAYER_ID curr_layer = ( (PCB_SCREEN*) panel->GetScreen() )->m_Active_Layer; int fillvia = 0; PCB_BASE_FRAME* frame = (PCB_BASE_FRAME*) panel->GetParent(); PCB_SCREEN* screen = frame->GetScreen(); DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)frame->GetDisplayOptions(); if( displ_opts->m_DisplayViaFill == FILLED ) fillvia = 1; GRSetDrawMode( aDC, aDrawMode ); BOARD * brd = GetBoard(); EDA_COLOR_T color = brd->GetVisibleElementColor( VIAS_VISIBLE + GetViaType() ); if( brd->IsElementVisible( PCB_VISIBLE(VIAS_VISIBLE + GetViaType()) ) == false && ( color & HIGHLIGHT_FLAG ) != HIGHLIGHT_FLAG ) return; // Only draw the via if at least one of the layers it crosses is being displayed if( !( brd->GetVisibleLayers() & GetLayerSet() ).any() ) return; if( displ_opts->m_ContrastModeDisplay ) { if( !IsOnLayer( curr_layer ) ) ColorTurnToDarkDarkGray( &color ); } if( aDrawMode & GR_HIGHLIGHT ) ColorChangeHighlightFlag( &color, !(aDrawMode & GR_AND) ); ColorApplyHighlightFlag( &color ); SetAlpha( &color, 150 ); radius = m_Width >> 1; // for small via size on screen (radius < 4 pixels) draw a simplified shape int radius_in_pixels = aDC->LogicalToDeviceXRel( radius ); bool fast_draw = false; // Vias are drawn as a filled circle or a double circle. The hole will be drawn later int drill_radius = GetDrillValue() / 2; int inner_radius = radius - aDC->DeviceToLogicalXRel( 2 ); if( radius_in_pixels < MIN_VIA_DRAW_SIZE ) { fast_draw = true; fillvia = false; } if( fillvia ) { GRFilledCircle( panel->GetClipBox(), aDC, m_Start + aOffset, radius, color ); } else { GRCircle( panel->GetClipBox(), aDC, m_Start + aOffset, radius, 0, color ); if ( fast_draw ) return; GRCircle( panel->GetClipBox(), aDC, m_Start + aOffset, inner_radius, 0, color ); } // Draw the via hole if the display option allows it if( displ_opts->m_DisplayViaMode != VIA_HOLE_NOT_SHOW ) { // Display all drill holes requested or Display non default holes requested bool show_hole = displ_opts->m_DisplayViaMode == ALL_VIA_HOLE_SHOW; if( !show_hole ) { NETINFO_ITEM* net = GetNet(); int drill_class_value = 0; if( net ) { if( GetViaType() == VIA_MICROVIA ) drill_class_value = net->GetMicroViaDrillSize(); else drill_class_value = net->GetViaDrillSize(); } show_hole = GetDrillValue() != drill_class_value; } if( show_hole ) { if( fillvia ) { bool blackpenstate = false; if( screen->m_IsPrinting ) { blackpenstate = GetGRForceBlackPenState(); GRForceBlackPen( false ); color = WHITE; } else { color = BLACK; // or DARKGRAY; } if( (aDrawMode & GR_XOR) == 0) GRSetDrawMode( aDC, GR_COPY ); if( aDC->LogicalToDeviceXRel( drill_radius ) > MIN_DRAW_WIDTH ) // Draw hole if large enough. GRFilledCircle( panel->GetClipBox(), aDC, m_Start.x + aOffset.x, m_Start.y + aOffset.y, drill_radius, 0, color, color ); if( screen->m_IsPrinting ) GRForceBlackPen( blackpenstate ); } else { if( drill_radius < inner_radius ) // We can show the via hole GRCircle( panel->GetClipBox(), aDC, m_Start + aOffset, drill_radius, 0, color ); } } } if( ShowClearance( displ_opts, this ) ) { GRCircle( panel->GetClipBox(), aDC, m_Start + aOffset, radius + GetClearance(), 0, color ); } // for Micro Vias, draw a partial cross : X on component layer, or + on copper layer // (so we can see 2 superimposed microvias ): if( GetViaType() == VIA_MICROVIA ) { int ax, ay, bx, by; if( IsOnLayer( B_Cu ) ) { ax = radius; ay = 0; bx = drill_radius; by = 0; } else { ax = ay = (radius * 707) / 1000; bx = by = (drill_radius * 707) / 1000; } // lines '|' or '\' GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x - ax, m_Start.y + aOffset.y - ay, m_Start.x + aOffset.x - bx, m_Start.y + aOffset.y - by, 0, color ); GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x + bx, m_Start.y + aOffset.y + by, m_Start.x + aOffset.x + ax, m_Start.y + aOffset.y + ay, 0, color ); // lines - or '/' GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x + ay, m_Start.y + aOffset.y - ax, m_Start.x + aOffset.x + by, m_Start.y + aOffset.y - bx, 0, color ); GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x - by, m_Start.y + aOffset.y + bx, m_Start.x + aOffset.x - ay, m_Start.y + aOffset.y + ax, 0, color ); } // for Buried Vias, draw a partial line : orient depending on layer pair // (so we can see superimposed buried vias ): if( GetViaType() == VIA_BLIND_BURIED ) { int ax = 0, ay = radius, bx = 0, by = drill_radius; LAYER_ID layer_top, layer_bottom; LayerPair( &layer_top, &layer_bottom ); // lines for the top layer RotatePoint( &ax, &ay, layer_top * 3600.0 / brd->GetCopperLayerCount( ) ); RotatePoint( &bx, &by, layer_top * 3600.0 / brd->GetCopperLayerCount( ) ); GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x - ax, m_Start.y + aOffset.y - ay, m_Start.x + aOffset.x - bx, m_Start.y + aOffset.y - by, 0, color ); // lines for the bottom layer ax = 0; ay = radius; bx = 0; by = drill_radius; RotatePoint( &ax, &ay, layer_bottom * 3600.0 / brd->GetCopperLayerCount( ) ); RotatePoint( &bx, &by, layer_bottom * 3600.0 / brd->GetCopperLayerCount( ) ); GRLine( panel->GetClipBox(), aDC, m_Start.x + aOffset.x - ax, m_Start.y + aOffset.y - ay, m_Start.x + aOffset.x - bx, m_Start.y + aOffset.y - by, 0, color ); } // Display the short netname: if( GetNetCode() == NETINFO_LIST::UNCONNECTED ) return; if( displ_opts->m_DisplayNetNamesMode == 0 || displ_opts->m_DisplayNetNamesMode == 1 ) return; NETINFO_ITEM* net = GetNet(); if( net == NULL ) return; int len = net->GetShortNetname().Len(); if( len > 0 ) { // calculate a good size for the text int tsize = m_Width / len; if( aDC->LogicalToDeviceXRel( tsize ) >= MIN_TEXT_SIZE ) { tsize = (tsize * 7) / 10; // small reduction to give a better look, inside via if( (aDrawMode & GR_XOR) == 0 ) GRSetDrawMode( aDC, GR_COPY ); EDA_RECT* clipbox = panel->GetClipBox(); DrawGraphicHaloText( clipbox, aDC, m_Start, color, WHITE, BLACK, net->GetShortNetname(), 0, wxSize( tsize, tsize ), GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER, tsize / 7, false, false ); } } }