/* drawing the track segment movement * > s_MovingSegmentSlope slope = moving track segment slope * > s_StartSegmentSlope slope = slope of the segment connected to the start * point of the moving segment * > s_EndSegmentSlope slope = slope of the segment connected to the end point * of the moving segment * * moved segment function : * yt=s_MovingSegmentSlope * x + s_MovingSegment_Yorg * * segment connected to moved segment's start: * y1 = s_StartSegmentSlope * x + s_StartSegment_Yorg * * segment connected to moved segment's end: * y2=s_EndSegmentSlope * x + s_EndSegment_Yorg * * first intersection point will be located at * y1=yt -> * * xi1=(s_MovingSegment_Yorg-s_StartSegment_Yorg)/(s_StartSegmentSlope-s_MovingSegmentSlope) * yi1=s_MovingSegmentSlope*xi1+s_MovingSegment_Yorg * or yi1=s_StartSegmentSlope*xi1+s_MovingSegment_Yorg * * second intersection point * y2=yt -> * * xi2=(s_MovingSegment_Yorg-s_StartSegment_Yorg)/(s_MovingSegmentSlope-s_MovingSegmentSlope) * yi2=s_MovingSegmentSlope*xi2+s_MovingSegment_Yorg * or yi1=s_EndSegmentSlope*xi2+s_MovingSegment_Yorg * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! * !!!!! special attention to vertical segments because * !!!!! their slope=infinite * !!!!! intersection point will be calculated using the * !!!!! segment intersecting it * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! * * Slope parameters are computed once, because they can become undetermined * when moving segments * (i.e. when a segment length is 0) and we want keep them constant */ static void Show_Drag_Track_Segment_With_Cte_Slope( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition, bool aErase ) { double xi1 = 0, yi1 = 0, xi2 = 0, yi2 = 0; // calculated intersection points double tx1, tx2, ty1, ty2; // temporary storage of points int dx, dy; bool update = true; TRACK* Track; TRACK* tSegmentToStart = NULL, * tSegmentToEnd = NULL; if( g_DragSegmentList.size() == 0 ) return; /* get the segments : * from last to first in list are: * the segment to move * the segment connected to its end point (if exists) * the segment connected to its start point (if exists) */ int ii = g_DragSegmentList.size() - 1; Track = g_DragSegmentList[ii].m_Track; if( Track == NULL ) return; ii--; if( ii >= 0) { if( s_EndSegmentPresent ) { // Get the segment connected to the end point tSegmentToEnd = g_DragSegmentList[ii].m_Track; ii--; } if( s_StartSegmentPresent ) { // Get the segment connected to the start point if( ii >= 0 ) tSegmentToStart = g_DragSegmentList[ii].m_Track; } } GR_DRAWMODE draw_mode = GR_XOR | GR_HIGHLIGHT; // Undraw the current moved track segments before modification #ifndef USE_WX_OVERLAY // if( erase ) { Track->Draw( aPanel, aDC, draw_mode ); if( tSegmentToStart ) tSegmentToStart->Draw( aPanel, aDC, draw_mode ); if( tSegmentToEnd ) tSegmentToEnd->Draw( aPanel, aDC, draw_mode ); } #endif // Compute the new track segment position wxPoint Pos = aPanel->GetParent()->GetCrossHairPosition(); dx = Pos.x - s_LastPos.x; dy = Pos.y - s_LastPos.y; // move the line by dx and dy tx1 = (double) ( Track->GetStart().x + dx ); ty1 = (double) ( Track->GetStart().y + dy ); tx2 = (double) ( Track->GetEnd().x + dx ); ty2 = (double) ( Track->GetEnd().y + dy ); // recalculate the segments new parameters and intersection points // only the intercept will change, segment slopes does not change // because we are moving parallel with is initial state if( !s_MovingSegmentVertical ) s_MovingSegment_Yorg = ty1 - ( s_MovingSegmentSlope * tx1 ); if( ( !s_EndPointVertical ) && ( !s_MovingSegmentVertical ) ) { xi2 = ( s_MovingSegment_Yorg - s_EndSegment_Yorg ) / ( s_EndSegmentSlope - s_MovingSegmentSlope ); } else { if( !s_EndPointVertical ) xi2 = tx2; else { //P1=P2 if( !s_EndPointHorizontal ) xi2 = tx2 - dx; else update = false; } } if( !s_MovingSegmentVertical ) yi2 = ( s_MovingSegmentSlope * xi2 ) + s_MovingSegment_Yorg; else { if( !s_EndPointVertical ) yi2 = ( s_EndSegmentSlope * xi2 ) + s_EndSegment_Yorg; else { if( !s_EndPointHorizontal ) update = false; else yi2 = ( s_MovingSegmentSlope * xi2 ) + s_MovingSegment_Yorg; } } if( ( !s_StartPointVertical ) && ( !s_MovingSegmentVertical ) ) { xi1 = ( s_MovingSegment_Yorg - s_StartSegment_Yorg ) / ( s_StartSegmentSlope - s_MovingSegmentSlope ); } else { if( !s_StartPointVertical ) xi1 = tx1; else { //P1=P2 if( !s_StartPointHorizontal ) xi1 = tx1 - dx; else { if( !s_StartPointHorizontal ) update = false; } } } if( !s_MovingSegmentVertical ) yi1 = ( s_MovingSegmentSlope * xi1 ) + s_MovingSegment_Yorg; else { if( !s_StartPointVertical ) yi1 = ( s_StartSegmentSlope * xi1 ) + s_StartSegment_Yorg; else { if( !s_StartPointHorizontal ) update = false; else yi2 = ( s_MovingSegmentSlope * xi1 ) + s_MovingSegment_Yorg; } } // update the segment coordinates (if possible) if( tSegmentToStart == NULL ) { xi1 = tx1; yi1 = ty1; } if( tSegmentToEnd == NULL ) { xi2 = tx2; yi2 = ty2; } if( update ) { s_LastPos = Pos; Track->SetStart( wxPoint( KiROUND( xi1 ), KiROUND( yi1 ) ) ); Track->SetEnd( wxPoint( KiROUND( xi2 ), KiROUND( yi2 ) ) ); if( tSegmentToEnd ) { if( tSegmentToEnd->GetFlags() & STARTPOINT ) tSegmentToEnd->SetStart( Track->GetEnd() ); else tSegmentToEnd->SetEnd( Track->GetEnd() ); } if( tSegmentToStart ) { if( tSegmentToStart->GetFlags() & STARTPOINT ) tSegmentToStart->SetStart( Track->GetStart() ); else tSegmentToStart->SetEnd( Track->GetStart() ); } } Track->Draw( aPanel, aDC, draw_mode ); if( tSegmentToStart ) tSegmentToStart->Draw( aPanel, aDC, draw_mode ); if( tSegmentToEnd ) tSegmentToEnd->Draw( aPanel, aDC, draw_mode ); // Display track length PCB_BASE_FRAME* frame = (PCB_BASE_FRAME*) aPanel->GetParent(); frame->SetMsgPanel( Track ); }
void DialogEditModuleText::OnOkClick( wxCommandEvent& event ) { wxString msg; if ( m_module) m_parent->SaveCopyInUndoList( m_module, UR_CHANGED ); #ifndef USE_WX_OVERLAY if( m_dc ) //Erase old text on screen { m_currentText->Draw( m_parent->GetCanvas(), m_dc, GR_XOR, (m_currentText->IsMoving()) ? MoveVector : wxPoint( 0, 0 ) ); } #endif m_currentText->SetText( m_Name->GetValue() ); m_currentText->SetItalic( m_Style->GetSelection() == 1 ); wxPoint tmp; msg = m_TxtPosCtrlX->GetValue(); tmp.x = ReturnValueFromString( g_UserUnit, msg ); msg = m_TxtPosCtrlY->GetValue(); tmp.y = ReturnValueFromString( g_UserUnit, msg ); m_currentText->SetPos0( tmp ); wxSize textSize( wxSize( ReturnValueFromString( g_UserUnit, m_TxtSizeCtrlX->GetValue() ), ReturnValueFromString( g_UserUnit, m_TxtSizeCtrlY->GetValue() ) ) ); // Test for a reasonnable size: if( textSize.x < TEXTS_MIN_SIZE ) textSize.x = TEXTS_MIN_SIZE; if( textSize.y < TEXTS_MIN_SIZE ) textSize.y = TEXTS_MIN_SIZE; m_currentText->SetSize( textSize ), msg = m_TxtWidthCtlr->GetValue(); int width = ReturnValueFromString( g_UserUnit, msg ); // Test for a reasonnable width: if( width <= 1 ) width = 1; int maxthickness = Clamp_Text_PenSize(width, m_currentText->GetSize() ); if( width > maxthickness ) { DisplayError( NULL, _( "The text thickness is too large for the text size. It will be clamped" ) ); width = maxthickness; } m_currentText->SetThickness( width ); m_currentText->SetVisible( m_Show->GetSelection() == 0 ); int text_orient = (m_Orient->GetSelection() == 0) ? 0 : 900; m_currentText->SetOrientation( text_orient ); m_currentText->SetDrawCoord(); #ifndef USE_WX_OVERLAY if( m_dc ) // Display new text { m_currentText->Draw( m_parent->GetCanvas(), m_dc, GR_XOR, (m_currentText->IsMoving()) ? MoveVector : wxPoint( 0, 0 ) ); } #else m_parent->Refresh(); #endif m_parent->OnModify(); if( m_module ) m_module->SetLastEditTime(); EndModal(1); }
void POINT_EDITOR::addCorner( const VECTOR2I& aBreakPoint ) { EDA_ITEM* item = m_editPoints->GetParent(); const SELECTION& selection = m_selectionTool->GetSelection(); if( item->Type() == PCB_ZONE_AREA_T ) { getEditFrame<PCB_BASE_FRAME>()->OnModify(); getEditFrame<PCB_BASE_FRAME>()->SaveCopyInUndoList( selection.items, UR_CHANGED ); ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( item ); CPolyLine* outline = zone->Outline(); // Handle the last segment, so other segments can be easily handled in a loop unsigned int nearestIdx = outline->GetCornersCount() - 1, nextNearestIdx = 0; SEG side( VECTOR2I( outline->GetPos( nearestIdx ) ), VECTOR2I( outline->GetPos( nextNearestIdx ) ) ); unsigned int nearestDist = side.Distance( aBreakPoint ); for( int i = 0; i < outline->GetCornersCount() - 1; ++i ) { side = SEG( VECTOR2I( outline->GetPos( i ) ), VECTOR2I( outline->GetPos( i + 1 ) ) ); unsigned int distance = side.Distance( aBreakPoint ); if( distance < nearestDist ) { nearestDist = distance; nearestIdx = i; nextNearestIdx = i + 1; } } // Find the point on the closest segment VECTOR2I sideOrigin( outline->GetPos( nearestIdx ) ); VECTOR2I sideEnd( outline->GetPos( nextNearestIdx ) ); SEG nearestSide( sideOrigin, sideEnd ); VECTOR2I nearestPoint = nearestSide.NearestPoint( aBreakPoint ); // Do not add points that have the same coordinates as ones that already belong to polygon // instead, add a point in the middle of the side if( nearestPoint == sideOrigin || nearestPoint == sideEnd ) nearestPoint = ( sideOrigin + sideEnd ) / 2; outline->InsertCorner( nearestIdx, nearestPoint.x, nearestPoint.y ); } else if( item->Type() == PCB_LINE_T || item->Type() == PCB_MODULE_EDGE_T ) { bool moduleEdge = item->Type() == PCB_MODULE_EDGE_T; PCB_BASE_FRAME* frame = getEditFrame<PCB_BASE_FRAME>(); frame->OnModify(); if( moduleEdge ) frame->SaveCopyInUndoList( getModel<BOARD>()->m_Modules, UR_MODEDIT ); else frame->SaveCopyInUndoList( selection.items, UR_CHANGED ); DRAWSEGMENT* segment = static_cast<DRAWSEGMENT*>( item ); if( segment->GetShape() == S_SEGMENT ) { SEG seg( segment->GetStart(), segment->GetEnd() ); VECTOR2I nearestPoint = seg.NearestPoint( aBreakPoint ); // Move the end of the line to the break point.. segment->SetEnd( wxPoint( nearestPoint.x, nearestPoint.y ) ); // and add another one starting from the break point DRAWSEGMENT* newSegment; if( moduleEdge ) { EDGE_MODULE* edge = static_cast<EDGE_MODULE*>( segment ); assert( segment->GetParent()->Type() == PCB_MODULE_T ); newSegment = new EDGE_MODULE( *edge ); edge->SetLocalCoord(); } else { newSegment = new DRAWSEGMENT( *segment ); } newSegment->ClearSelected(); newSegment->SetStart( wxPoint( nearestPoint.x, nearestPoint.y ) ); newSegment->SetEnd( wxPoint( seg.B.x, seg.B.y ) ); if( moduleEdge ) { static_cast<EDGE_MODULE*>( newSegment )->SetLocalCoord(); getModel<BOARD>()->m_Modules->Add( newSegment ); } else { getModel<BOARD>()->Add( newSegment ); } getView()->Add( newSegment ); } } }
/* Calls the Pad editor. */ void DIALOG_GLOBAL_PADS_EDITION::InstallPadEditor( wxCommandEvent& event ) { m_parent->InstallPadOptionsFrame( m_currentPad ); }
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 ); } 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 ); } } }
int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent ) { bool increment = aEvent.IsAction( &COMMON_ACTIONS::duplicateIncrement ); // first, check if we have a selection, or try to get one SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>(); const SELECTION& selection = selTool->GetSelection(); // Be sure that there is at least one item that we can modify if( !hoverSelection( selection ) ) return 0; // we have a selection to work on now, so start the tool process PCB_BASE_FRAME* editFrame = getEditFrame<PCB_BASE_FRAME>(); editFrame->OnModify(); // prevent other tools making undo points while the duplicate is going on // so that if you cancel, you don't get a duplicate object hiding over // the original incUndoInhibit(); if( m_editModules ) editFrame->SaveCopyInUndoList( editFrame->GetBoard()->m_Modules, UR_MODEDIT ); std::vector<BOARD_ITEM*> old_items; for( int i = 0; i < selection.Size(); ++i ) { BOARD_ITEM* item = selection.Item<BOARD_ITEM>( i ); if( item ) old_items.push_back( item ); } for( unsigned i = 0; i < old_items.size(); ++i ) { BOARD_ITEM* item = old_items[i]; // Unselect the item, so we won't pick it up again // Do this first, so a single-item duplicate will correctly call // SetCurItem and show the item properties m_toolMgr->RunAction( COMMON_ACTIONS::unselectItem, true, item ); BOARD_ITEM* new_item = NULL; if( m_editModules ) new_item = editFrame->GetBoard()->m_Modules->DuplicateAndAddItem( item, increment ); else { #if 0 // @TODO: see if we allow zone duplication here // Duplicate zones is especially tricky (overlaping zones must be merged) // so zones are not duplicated if( item->Type() != PCB_ZONE_AREA_T ) #endif new_item = editFrame->GetBoard()->DuplicateAndAddItem( item, increment ); } if( new_item ) { if( new_item->Type() == PCB_MODULE_T ) { static_cast<MODULE*>( new_item )->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, getView(), _1 ) ); } editFrame->GetGalCanvas()->GetView()->Add( new_item ); // Select the new item, so we can pick it up m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, new_item ); } } // record the new items as added if( !m_editModules ) editFrame->SaveCopyInUndoList( selection.items, UR_NEW ); editFrame->DisplayToolMsg( wxString::Format( _( "Duplicated %d item(s)" ), (int) old_items.size() ) ); // pick up the selected item(s) and start moving // this works well for "dropping" copies around TOOL_EVENT evt = COMMON_ACTIONS::editActivate.MakeEvent(); Main( evt ); // and re-enable undos decUndoInhibit(); return 0; }
int EDIT_TOOL::CreateArray( const TOOL_EVENT& aEvent ) { // first, check if we have a selection, or try to get one SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>(); const SELECTION& selection = selTool->GetSelection(); // Be sure that there is at least one item that we can modify if( !hoverSelection( selection ) ) return 0; bool originalItemsModified = false; // we have a selection to work on now, so start the tool process PCB_BASE_FRAME* editFrame = getEditFrame<PCB_BASE_FRAME>(); editFrame->OnModify(); if( m_editModules ) { // Module editors do their undo point upfront for the whole module editFrame->SaveCopyInUndoList( editFrame->GetBoard()->m_Modules, UR_MODEDIT ); } else { // We may also change the original item editFrame->SaveCopyInUndoList( selection.items, UR_CHANGED ); } DIALOG_CREATE_ARRAY::ARRAY_OPTIONS* array_opts = NULL; VECTOR2I rp = selection.GetCenter(); const wxPoint rotPoint( rp.x, rp.y ); DIALOG_CREATE_ARRAY dialog( editFrame, rotPoint, &array_opts ); int ret = dialog.ShowModal(); if( ret == wxID_OK && array_opts != NULL ) { PICKED_ITEMS_LIST newItemList; for( int i = 0; i < selection.Size(); ++i ) { BOARD_ITEM* item = selection.Item<BOARD_ITEM>( i ); if( !item ) continue; wxString cachedString; if( item->Type() == PCB_MODULE_T ) { cachedString = static_cast<MODULE*>( item )->GetReferencePrefix(); } else if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( item ) ) { // Copy the text (not just take a reference cachedString = text->GetText(); } // iterate across the array, laying out the item at the // correct position const unsigned nPoints = array_opts->GetArraySize(); for( unsigned ptN = 0; ptN < nPoints; ++ptN ) { BOARD_ITEM* newItem = NULL; if( ptN == 0 ) newItem = item; else { // if renumbering, no need to increment const bool increment = !array_opts->ShouldRenumberItems(); // Some items cannot be duplicated // i.e. the ref and value fields of a footprint or zones // therefore newItem can be null if( m_editModules ) newItem = editFrame->GetBoard()->m_Modules->DuplicateAndAddItem( item, increment ); else { #if 0 // @TODO: see if we allow zone duplication here // Duplicate zones is especially tricky (overlaping zones must be merged) // so zones are not duplicated if( item->Type() == PCB_ZONE_AREA_T ) newItem = NULL; else #endif newItem = editFrame->GetBoard()->DuplicateAndAddItem( item, increment ); } if( newItem ) { array_opts->TransformItem( ptN, newItem, rotPoint ); m_toolMgr->RunAction( COMMON_ACTIONS::unselectItem, true, newItem ); newItemList.PushItem( newItem ); if( newItem->Type() == PCB_MODULE_T) { static_cast<MODULE*>( newItem )->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, getView(), _1 ) ); } editFrame->GetGalCanvas()->GetView()->Add( newItem ); getModel<BOARD>()->GetRatsnest()->Update( newItem ); } } // set the number if needed: if( newItem && array_opts->ShouldRenumberItems() ) { switch( newItem->Type() ) { case PCB_PAD_T: { const wxString padName = array_opts->GetItemNumber( ptN ); static_cast<D_PAD*>( newItem )->SetPadName( padName ); originalItemsModified = true; break; } case PCB_MODULE_T: { const wxString moduleName = array_opts->GetItemNumber( ptN ); MODULE* module = static_cast<MODULE*>( newItem ); module->SetReference( cachedString + moduleName ); originalItemsModified = true; break; } case PCB_MODULE_TEXT_T: case PCB_TEXT_T: { EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( newItem ); if( text ) text->SetText( array_opts->InterpolateNumberIntoString( ptN, cachedString ) ); originalItemsModified = true; break; } default: // no renumbering of other items break; } } } } if( !m_editModules ) { if( originalItemsModified ) { // Update the appearance of the original items selection.group->ItemsViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); } // Add all items as a single undo point for PCB editors // TODO: Can this be merged into the previous undo point (where // we saved the original items) editFrame->SaveCopyInUndoList( newItemList, UR_NEW ); } } getModel<BOARD>()->GetRatsnest()->Recalculate(); return 0; }
FOOTPRINT_VIEWER_FRAME::FOOTPRINT_VIEWER_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrameType ) : PCB_BASE_FRAME( aKiway, aParent, aFrameType, _( "Footprint Library Browser" ), wxDefaultPosition, wxDefaultSize, aFrameType == FRAME_PCB_MODULE_VIEWER_MODAL ? aParent ? KICAD_DEFAULT_DRAWFRAME_STYLE | MODAL_MODE_EXTRASTYLE : KICAD_DEFAULT_DRAWFRAME_STYLE | wxSTAY_ON_TOP : KICAD_DEFAULT_DRAWFRAME_STYLE, aFrameType == FRAME_PCB_MODULE_VIEWER_MODAL ? FOOTPRINT_VIEWER_FRAME_NAME_MODAL : FOOTPRINT_VIEWER_FRAME_NAME ) { wxASSERT( aFrameType == FRAME_PCB_MODULE_VIEWER_MODAL || aFrameType == FRAME_PCB_MODULE_VIEWER ); if( aFrameType == FRAME_PCB_MODULE_VIEWER_MODAL ) SetModal( true ); // Force the frame name used in config. the footprint viewer frame has a name // depending on aFrameType (needed to identify the frame by wxWidgets), // but only one configuration is preferable. m_configFrameName = FOOTPRINT_VIEWER_FRAME_NAME; m_showAxis = true; // true to draw axis. // Give an icon wxIcon icon; icon.CopyFromBitmap( KiBitmap( modview_icon_xpm ) ); SetIcon( icon ); m_hotkeysDescrList = g_Module_Viewer_Hokeys_Descr; m_libList = new wxListBox( this, ID_MODVIEW_LIB_LIST, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_HSCROLL ); m_footprintList = new wxListBox( this, ID_MODVIEW_FOOTPRINT_LIST, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_HSCROLL ); SetBoard( new BOARD() ); // In viewer, the default net clearance is not known (it depends on the actual board). // So we do not show the default clearance, by setting it to 0 // The footprint or pad specific clearance will be shown GetBoard()->GetDesignSettings().GetDefault()->SetClearance(0); // Ensure all layers and items are visible: GetBoard()->SetVisibleAlls(); SetScreen( new PCB_SCREEN( GetPageSizeIU() ) ); GetScreen()->m_Center = true; // Center coordinate origins on screen. LoadSettings( config() ); SetSize( m_FramePos.x, m_FramePos.y, m_FrameSize.x, m_FrameSize.y ); GetScreen()->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId ); // Menu bar is not mandatory: uncomment/comment the next line // to add/remove the menubar ReCreateMenuBar(); ReCreateHToolbar(); ReCreateVToolbar(); ReCreateLibraryList(); UpdateTitle(); PCB_BASE_FRAME* parentFrame = static_cast<PCB_BASE_FRAME*>( Kiway().Player( FRAME_PCB, true ) ); // Create GAL canvas PCB_DRAW_PANEL_GAL* drawPanel = new PCB_DRAW_PANEL_GAL( this, -1, wxPoint( 0, 0 ), m_FrameSize, parentFrame->GetGalCanvas()->GetBackend() ); SetGalCanvas( drawPanel ); // Create the manager and dispatcher & route draw panel events to the dispatcher m_toolManager = new TOOL_MANAGER; m_toolManager->SetEnvironment( GetBoard(), drawPanel->GetView(), drawPanel->GetViewControls(), this ); m_toolDispatcher = new TOOL_DISPATCHER( m_toolManager ); drawPanel->SetEventDispatcher( m_toolDispatcher ); m_toolManager->RegisterTool( new PCBNEW_CONTROL ); m_toolManager->ResetTools( TOOL_BASE::RUN ); // If a footprint was previously loaded, reload it if( getCurNickname().size() && getCurFootprintName().size() ) { FPID id; id.SetLibNickname( getCurNickname() ); id.SetFootprintName( getCurFootprintName() ); GetBoard()->Add( loadFootprint( id ) ); } drawPanel->DisplayBoard( m_Pcb ); updateView(); m_auimgr.SetManagedWindow( this ); wxSize minsize(100,-1); // Min size of list boxes // Main toolbar is initially docked at the top of the main window and dockable on any side. // The close button is disable because the footprint viewer has no main menu to re-enable it. // The tool bar will only be dockable on the top or bottom of the main frame window. This is // most likely due to the fact that the other windows are not dockable and are preventing the // tool bar from docking on the right and left. wxAuiPaneInfo toolbarPaneInfo; toolbarPaneInfo.Name( wxT( "m_mainToolBar" ) ).ToolbarPane().Top().CloseButton( false ); EDA_PANEINFO info; info.InfoToolbarPane(); EDA_PANEINFO mesg; mesg.MessageToolbarPane(); // Manage main toolbar, top pane m_auimgr.AddPane( m_mainToolBar, toolbarPaneInfo ); // Manage the list of libraries, left pane. m_auimgr.AddPane( m_libList, wxAuiPaneInfo( info ).Name( wxT( "m_libList" ) ) .Left().Row( 1 ).MinSize( minsize ) ); // Manage the list of footprints, center pane. m_auimgr.AddPane( m_footprintList, wxAuiPaneInfo( info ).Name( wxT( "m_footprintList" ) ) .Left().Row( 2 ).MinSize( minsize ) ); // Manage the draw panel, right pane. m_auimgr.AddPane( m_canvas, wxAuiPaneInfo().Name( wxT( "DrawFrame" ) ).CentrePane() ); m_auimgr.AddPane( (wxWindow*) GetGalCanvas(), wxAuiPaneInfo().Name( wxT( "DrawFrameGal" ) ).CentrePane().Hide() ); // Manage the message panel, bottom pane. m_auimgr.AddPane( m_messagePanel, wxAuiPaneInfo( mesg ).Name( wxT( "MsgPanel" ) ).Bottom() ); if( !m_perspective.IsEmpty() ) { // Restore last saved sizes, pos and other params // However m_mainToolBar size cannot be set to its last saved size // because the actual size change depending on the way modview was called: // the tool to export the current footprint exist or not. // and the saved size is not always OK // the trick is to get the default toolbar size, and set the size after // calling LoadPerspective wxSize tbsize = m_mainToolBar->GetSize(); m_auimgr.LoadPerspective( m_perspective, false ); m_auimgr.GetPane( m_mainToolBar ).BestSize( tbsize ); } // after changing something to the aui manager, // call Update()() to reflect the changes m_auimgr.Update(); // Now Drawpanel is sized, we can use BestZoom to show the component (if any) #ifdef USE_WX_GRAPHICS_CONTEXT GetScreen()->SetZoom( BestZoom() ); #else Zoom_Automatique( false ); #endif UseGalCanvas( parentFrame->IsGalCanvasActive() ); if( !IsModal() ) // For modal mode, calling ShowModal() will show this frame { Raise(); // On some window managers, this is needed Show( true ); } }
void DIALOG_COPPER_ZONE::buildAvailableListOfNets() { wxArrayString listNetName; m_Parent->GetBoard()->SortedNetnamesList( listNetName, m_NetSortingByPadCount ); if( m_NetFiltering ) { wxString doNotShowFilter = m_DoNotShowNetNameFilter->GetValue(); wxString ShowFilter = m_ShowNetNameFilter->GetValue(); for( unsigned ii = 0; ii < listNetName.GetCount(); ii++ ) { if( listNetName[ii].Matches( doNotShowFilter ) ) { listNetName.RemoveAt( ii ); ii--; } else if( !listNetName[ii].Matches( ShowFilter ) ) { listNetName.RemoveAt( ii ); ii--; } } } listNetName.Insert( wxT( "<no net>" ), 0 ); // Ensure currently selected net for the zone is visible, regardless of filters int selectedNetListNdx = -1; int net_select = m_settings.m_NetcodeSelection; if( net_select > 0 ) { NETINFO_ITEM* equipot = m_Parent->GetBoard()->FindNet( net_select ); if( equipot ) { selectedNetListNdx = listNetName.Index( equipot->GetNetname() ); if( wxNOT_FOUND == selectedNetListNdx ) { // the currently selected net must *always* be visible. listNetName.Insert( equipot->GetNetname(), 0 ); selectedNetListNdx = 0; } } } else if( net_select == 0 ) selectedNetListNdx = 0; // SetSelection() on "<no net>" else { // selectedNetListNdx remains -1, no net selected. } m_ListNetNameSelection->Clear(); m_ListNetNameSelection->InsertItems( listNetName, 0 ); m_ListNetNameSelection->SetSelection( 0 ); if( selectedNetListNdx >= 0 ) { m_ListNetNameSelection->SetSelection( selectedNetListNdx ); m_ListNetNameSelection->EnsureVisible( selectedNetListNdx ); } }
bool DIALOG_COPPER_ZONE::AcceptOptions( bool aPromptForErrors, bool aUseExportableSetupOnly ) { switch( m_PadInZoneOpt->GetSelection() ) { case 3: // Pads are not covered m_settings.SetPadConnection( PAD_ZONE_CONN_NONE ); break; case 2: // Use thermal relief for THT pads m_settings.SetPadConnection( PAD_ZONE_CONN_THT_THERMAL ); break; case 1: // Use thermal relief for pads m_settings.SetPadConnection( PAD_ZONE_CONN_THERMAL ); break; case 0: // pads are covered by copper m_settings.SetPadConnection( PAD_ZONE_CONN_FULL ); break; } switch( m_OutlineAppearanceCtrl->GetSelection() ) { case 0: m_settings.m_Zone_HatchingStyle = CPolyLine::NO_HATCH; break; case 1: m_settings.m_Zone_HatchingStyle = CPolyLine::DIAGONAL_EDGE; break; case 2: m_settings.m_Zone_HatchingStyle = CPolyLine::DIAGONAL_FULL; break; } m_settings.m_ArcToSegmentsCount = m_ArcApproximationOpt->GetSelection() == 1 ? ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF : ARC_APPROX_SEGMENTS_COUNT_LOW_DEF; if( m_Config ) { m_Config->Write( ZONE_NET_OUTLINES_HATCH_OPTION_KEY, (long) m_settings.m_Zone_HatchingStyle ); wxString filter = m_DoNotShowNetNameFilter->GetValue(); m_Config->Write( ZONE_NET_FILTER_STRING_KEY, filter ); } m_netNameShowFilter = m_ShowNetNameFilter->GetValue(); m_settings.m_FillMode = (m_FillModeCtrl->GetSelection() == 0) ? 0 : 1; wxString txtvalue = m_ZoneClearanceCtrl->GetValue(); m_settings.m_ZoneClearance = ValueFromString( g_UserUnit, txtvalue ); // Test if this is a reasonable value for this parameter // A too large value can hang Pcbnew #define CLEARANCE_MAX_VALUE ZONE_CLEARANCE_MAX_VALUE_MIL*IU_PER_MILS if( m_settings.m_ZoneClearance > CLEARANCE_MAX_VALUE ) { wxString msg; msg.Printf( _( "Clearance must be smaller than %f\" / %f mm." ), ZONE_CLEARANCE_MAX_VALUE_MIL / 1000.0, ZONE_CLEARANCE_MAX_VALUE_MIL * 0.0254 ); DisplayError( this, msg ); return false; } txtvalue = m_ZoneMinThicknessCtrl->GetValue(); m_settings.m_ZoneMinThickness = ValueFromString( g_UserUnit, txtvalue ); if( m_settings.m_ZoneMinThickness < (ZONE_THICKNESS_MIN_VALUE_MIL*IU_PER_MILS) ) { wxString msg; msg.Printf( _( "Minimum width must be larger than %f\" / %f mm." ), ZONE_THICKNESS_MIN_VALUE_MIL / 1000.0, ZONE_THICKNESS_MIN_VALUE_MIL * 0.0254 ); DisplayError( this, msg ); return false; } m_settings.SetCornerSmoothingType( m_cornerSmoothingChoice->GetSelection() ); txtvalue = m_cornerSmoothingCtrl->GetValue(); m_settings.SetCornerRadius( ValueFromString( g_UserUnit, txtvalue ) ); m_settings.m_ZonePriority = m_PriorityLevelCtrl->GetValue(); if( m_OrientEdgesOpt->GetSelection() == 0 ) m_settings.m_Zone_45_Only = false; else m_settings.m_Zone_45_Only = true; m_settings.m_ThermalReliefGap = ValueFromTextCtrl( *m_AntipadSizeValue ); m_settings.m_ThermalReliefCopperBridge = ValueFromTextCtrl( *m_CopperWidthValue ); if( m_Config ) { ConfigBaseWriteDouble( m_Config, ZONE_CLEARANCE_WIDTH_STRING_KEY, (double) m_settings.m_ZoneClearance / IU_PER_MILS ); ConfigBaseWriteDouble( m_Config, ZONE_MIN_THICKNESS_WIDTH_STRING_KEY, (double) m_settings.m_ZoneMinThickness / IU_PER_MILS ); ConfigBaseWriteDouble( m_Config, ZONE_THERMAL_RELIEF_GAP_STRING_KEY, (double) m_settings.m_ThermalReliefGap / IU_PER_MILS ); ConfigBaseWriteDouble( m_Config, ZONE_THERMAL_RELIEF_COPPER_WIDTH_STRING_KEY, (double) m_settings.m_ThermalReliefCopperBridge / IU_PER_MILS ); } if( ( m_settings.GetPadConnection() == PAD_ZONE_CONN_THT_THERMAL || m_settings.GetPadConnection() == PAD_ZONE_CONN_THERMAL ) && m_settings.m_ThermalReliefCopperBridge <= m_settings.m_ZoneMinThickness ) { DisplayError( this, _( "Thermal relief spoke must be greater than the minimum width." ) ); return false; } // If we use only exportable to others zones parameters, exit here: if( aUseExportableSetupOnly ) return true; // Get the layer selection for this zone int ii = m_LayerSelectionCtrl->GetFirstSelected(); if( ii < 0 && aPromptForErrors ) { DisplayError( this, _( "No layer selected." ) ); return false; } m_settings.m_CurrentZone_Layer = ToLAYER_ID( m_LayerId[ii] ); // Get the net name selection for this zone ii = m_ListNetNameSelection->GetSelection(); if( ii < 0 && aPromptForErrors ) { DisplayError( this, _( "No net selected." ) ); return false; } if( ii == 0 ) // the not connected option was selected: this is not a good practice: warn: { if( !IsOK( this, _( "You have chosen the \"not connected\" option. This will create " "insulated copper islands. Are you sure ?" ) ) ) return false; } wxString net_name = m_ListNetNameSelection->GetString( ii ); m_settings.m_NetcodeSelection = 0; // Search net_code for this net, if a net was selected if( m_ListNetNameSelection->GetSelection() > 0 ) { NETINFO_ITEM* net = m_Parent->GetBoard()->FindNet( net_name ); if( net ) m_settings.m_NetcodeSelection = net->GetNet(); } return true; }
void DIALOG_COPPER_ZONE::initDialog() { BOARD* board = m_Parent->GetBoard(); wxString msg; if( m_settings.m_Zone_45_Only ) m_OrientEdgesOpt->SetSelection( 1 ); m_FillModeCtrl->SetSelection( m_settings.m_FillMode ? 1 : 0 ); AddUnitSymbol( *m_ClearanceValueTitle, g_UserUnit ); msg = StringFromValue( g_UserUnit, m_settings.m_ZoneClearance ); m_ZoneClearanceCtrl->SetValue( msg ); AddUnitSymbol( *m_MinThicknessValueTitle, g_UserUnit ); msg = StringFromValue( g_UserUnit, m_settings.m_ZoneMinThickness ); m_ZoneMinThicknessCtrl->SetValue( msg ); switch( m_settings.GetPadConnection() ) { case PAD_ZONE_CONN_THT_THERMAL: // Thermals only for THT pads m_PadInZoneOpt->SetSelection( 2 ); break; case PAD_ZONE_CONN_NONE: // Pads are not covered m_PadInZoneOpt->SetSelection( 3 ); break; default: case PAD_ZONE_CONN_THERMAL: // Use thermal relief for pads m_PadInZoneOpt->SetSelection( 1 ); break; case PAD_ZONE_CONN_FULL: // pads are covered by copper m_PadInZoneOpt->SetSelection( 0 ); break; } // Antipad and spokes are significant only for thermals if( m_settings.GetPadConnection() != PAD_ZONE_CONN_THERMAL && m_settings.GetPadConnection() != PAD_ZONE_CONN_THT_THERMAL ) { m_AntipadSizeValue->Enable( false ); m_CopperWidthValue->Enable( false ); } else { m_AntipadSizeValue->Enable( true ); m_CopperWidthValue->Enable( true ); } m_PriorityLevelCtrl->SetValue( m_settings.m_ZonePriority ); AddUnitSymbol( *m_AntipadSizeText, g_UserUnit ); AddUnitSymbol( *m_CopperBridgeWidthText, g_UserUnit ); PutValueInLocalUnits( *m_AntipadSizeValue, m_settings.m_ThermalReliefGap ); PutValueInLocalUnits( *m_CopperWidthValue, m_settings.m_ThermalReliefCopperBridge ); m_cornerSmoothingChoice->SetSelection( m_settings.GetCornerSmoothingType() ); PutValueInLocalUnits( *m_cornerSmoothingCtrl, m_settings.GetCornerRadius() ); switch( m_settings.m_Zone_HatchingStyle ) { case CPolyLine::NO_HATCH: m_OutlineAppearanceCtrl->SetSelection( 0 ); break; case CPolyLine::DIAGONAL_EDGE: m_OutlineAppearanceCtrl->SetSelection( 1 ); break; case CPolyLine::DIAGONAL_FULL: m_OutlineAppearanceCtrl->SetSelection( 2 ); break; } m_ArcApproximationOpt->SetSelection( m_settings.m_ArcToSegmentsCount == ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF ? 1 : 0 ); // Create one column in m_LayerSelectionCtrl wxListItem column0; column0.SetId( 0 ); m_LayerSelectionCtrl->InsertColumn( 0, column0 ); wxImageList* imageList = new wxImageList( LAYER_BITMAP_SIZE_X, LAYER_BITMAP_SIZE_Y ); m_LayerSelectionCtrl->AssignImageList( imageList, wxIMAGE_LIST_SMALL ); int ctrlWidth = 0; // Min width for m_LayerSelectionCtrl to show the layers names int imgIdx = 0; LSET cu_set = LSET::AllCuMask( board->GetCopperLayerCount() ); for( LSEQ cu_stack = cu_set.UIOrder(); cu_stack; ++cu_stack, imgIdx++ ) { LAYER_ID layer = *cu_stack; m_LayerId.push_back( layer ); msg = board->GetLayerName( layer ); msg.Trim(); EDA_COLOR_T layerColor = board->GetLayerColor( layer ); imageList->Add( makeLayerBitmap( layerColor ) ); int itemIndex = m_LayerSelectionCtrl->InsertItem( m_LayerSelectionCtrl->GetItemCount(), msg, imgIdx ); if( m_settings.m_CurrentZone_Layer == layer ) m_LayerSelectionCtrl->Select( itemIndex ); wxSize tsize( GetTextSize( msg, m_LayerSelectionCtrl ) ); ctrlWidth = std::max( ctrlWidth, tsize.x ); } // The most easy way to ensure the right size is to use wxLIST_AUTOSIZE // unfortunately this option does not work well both on // wxWidgets 2.8 ( column width too small), and // wxWidgets 2.9 ( column width too large) ctrlWidth += LAYER_BITMAP_SIZE_X + 25; // Add bitmap width + margin between bitmap and text m_LayerSelectionCtrl->SetColumnWidth( 0, ctrlWidth ); ctrlWidth += 25; // add small margin between text and window borders // and room for vertical scroll bar m_LayerSelectionCtrl->SetMinSize( wxSize( ctrlWidth, -1 ) ); wxString netNameDoNotShowFilter = wxT( "Net-*" ); if( m_Config ) { int opt = m_Config->Read( ZONE_NET_SORT_OPTION_KEY, 1l ); m_NetDisplayOption->SetSelection( opt ); m_Config->Read( ZONE_NET_FILTER_STRING_KEY, netNameDoNotShowFilter ); } else m_NetDisplayOption->SetSelection( 1 ); m_ShowNetNameFilter->SetValue( m_netNameShowFilter ); initListNetsParams(); // Build list of nets: m_DoNotShowNetNameFilter->SetValue( netNameDoNotShowFilter ); buildAvailableListOfNets(); wxCommandEvent event; OnCornerSmoothingModeChoice( event ); }
FOOTPRINT_EDIT_FRAME::FOOTPRINT_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : PCB_BASE_EDIT_FRAME( aKiway, aParent, FRAME_PCB_MODULE_EDITOR, wxEmptyString, wxDefaultPosition, wxDefaultSize, KICAD_DEFAULT_DRAWFRAME_STYLE, GetFootprintEditorFrameName() ) { m_showBorderAndTitleBlock = false; // true to show the frame references m_showAxis = true; // true to show X and Y axis on screen m_showGridAxis = true; // show the grid origin axis m_hotkeysDescrList = g_Module_Editor_Hokeys_Descr; // Give an icon wxIcon icon; icon.CopyFromBitmap( KiBitmap( icon_modedit_xpm ) ); SetIcon( icon ); // Show a title (frame title + footprint name): updateTitle(); // Create GAL canvas PCB_BASE_FRAME* parentFrame = static_cast<PCB_BASE_FRAME*>( Kiway().Player( FRAME_PCB, true ) ); PCB_DRAW_PANEL_GAL* drawPanel = new PCB_DRAW_PANEL_GAL( this, -1, wxPoint( 0, 0 ), m_FrameSize, parentFrame->GetGalCanvas()->GetBackend() ); SetGalCanvas( drawPanel ); SetBoard( new BOARD() ); // In modedit, the default net clearance is not known. // (it depends on the actual board) // So we do not show the default clearance, by setting it to 0 // The footprint or pad specific clearance will be shown GetBoard()->GetDesignSettings().GetDefault()->SetClearance(0); // restore the last footprint from the project, if any restoreLastFootprint(); // Ensure all layers and items are visible: // In footprint editor, some layers have no meaning or // cannot be used, but we show all of them, at least to be able // to edit a bad layer GetBoard()->SetVisibleAlls(); wxFont font = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ); m_Layers = new PCB_LAYER_WIDGET( this, GetCanvas(), font.GetPointSize(), true ); LoadSettings( config() ); SetScreen( new PCB_SCREEN( GetPageSettings().GetSizeIU() ) ); GetScreen()->SetMaxUndoItems( m_UndoRedoCountMax ); GetScreen()->SetCurItem( NULL ); GetScreen()->AddGrid( m_UserGridSize, m_UserGridUnit, ID_POPUP_GRID_USER ); GetScreen()->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId ); // In modedit, set the default paper size to A4: // this should be OK for all footprint to plot/print SetPageSettings( PAGE_INFO( PAGE_INFO::A4 ) ); SetSize( m_FramePos.x, m_FramePos.y, m_FrameSize.x, m_FrameSize.y ); ReCreateMenuBar(); ReCreateHToolbar(); ReCreateAuxiliaryToolbar(); ReCreateVToolbar(); ReCreateOptToolbar(); if( m_canvas ) m_canvas->SetEnableBlockCommands( true ); m_auimgr.SetManagedWindow( this ); EDA_PANEINFO horiz; horiz.HorizontalToolbarPane(); EDA_PANEINFO vert; vert.VerticalToolbarPane(); EDA_PANEINFO mesg_pane; mesg_pane.MessageToolbarPane(); // Create a wxAuiPaneInfo for the Layers Manager, not derived from the template. // LAYER_WIDGET is floatable, but initially docked at far right EDA_PANEINFO lyrs; lyrs.LayersToolbarPane(); lyrs.MinSize( m_Layers->GetBestSize() ); // updated in ReFillLayerWidget lyrs.BestSize( m_Layers->GetBestSize() ); lyrs.Caption( _( "Visibles" ) ); m_auimgr.AddPane( m_mainToolBar, wxAuiPaneInfo( horiz ).Name( wxT( "m_mainToolBar" ) ).Top(). Row( 0 ) ); m_auimgr.AddPane( m_auxiliaryToolBar, wxAuiPaneInfo( horiz ).Name( wxT( "m_auxiliaryToolBar" ) ).Top().Row( 1 ) ); // The main right vertical toolbar m_auimgr.AddPane( m_drawToolBar, wxAuiPaneInfo( vert ).Name( wxT( "m_VToolBar" ) ).Right().Layer(1) ); // Add the layer manager ( most right side of pcbframe ) m_auimgr.AddPane( m_Layers, lyrs.Name( wxT( "m_LayersManagerToolBar" ) ).Right().Layer( 2 ) ); // Layers manager is visible m_auimgr.GetPane( wxT( "m_LayersManagerToolBar" ) ).Show( true ); // The left vertical toolbar (fast acces to display options) m_auimgr.AddPane( m_optionsToolBar, wxAuiPaneInfo( vert ).Name( wxT( "m_optionsToolBar" ) ). Left().Layer(1) ); m_auimgr.AddPane( m_canvas, wxAuiPaneInfo().Name( wxT( "DrawFrame" ) ).CentrePane() ); m_auimgr.AddPane( (wxWindow*) GetGalCanvas(), wxAuiPaneInfo().Name( wxT( "DrawFrameGal" ) ).CentrePane().Hide() ); m_auimgr.AddPane( m_messagePanel, wxAuiPaneInfo( mesg_pane ).Name( wxT( "MsgPanel" ) ).Bottom().Layer(10) ); // Create the manager and dispatcher & route draw panel events to the dispatcher setupTools(); UseGalCanvas( parentFrame->IsGalCanvasActive() ); if( m_auimgr.GetPane( wxT( "m_LayersManagerToolBar" ) ).IsShown() ) { m_Layers->ReFill(); m_Layers->ReFillRender(); GetScreen()->m_Active_Layer = F_SilkS; m_Layers->SelectLayer( F_SilkS ); m_Layers->OnLayerSelected(); } m_auimgr.Update(); Raise(); // On some window managers, this is needed Show( true ); Zoom_Automatique( false ); }