bool PCB_LAYER_WIDGET::isAllowedInFpMode( int aId ) { for( unsigned ii = 0; ii < arrayDim( s_allowed_in_FpEditor ); ii++ ) if( s_allowed_in_FpEditor[ii] == aId ) return true; return false; }
bool PANEL_GERBVIEW_SETTINGS::TransferDataToWindow( ) { m_PolarDisplay->SetSelection( m_Parent->m_DisplayOptions.m_DisplayPolarCood ? 1 : 0 ); m_BoxUnits->SetSelection( m_Parent->GetUserUnits() ? 1 : 0 ); m_ShowPageLimitsOpt->SetValue( m_Parent->m_DisplayOptions.m_DisplayPageLimits ); for( unsigned i = 0; i < arrayDim( g_GerberPageSizeList ); ++i ) { if( g_GerberPageSizeList[i] == m_Parent->GetPageSettings().GetType() ) { m_PageSize->SetSelection( i ); break; } } return true; }
void PCB_LAYER_WIDGET::ReFillRender() { BOARD* board = myframe->GetBoard(); auto settings = board->GetDesignSettings(); ClearRenderRows(); // Add "Items" tab rows to LAYER_WIDGET, after setting color and checkbox state. // Because s_render_rows is created static, we must explicitly call // wxGetTranslation for texts which are internationalized (tool tips // and item names) for( unsigned row=0; row<arrayDim(s_render_rows); ++row ) { LAYER_WIDGET::ROW renderRow = s_render_rows[row]; if( m_fp_editor_mode && !isAllowedInFpMode( renderRow.id ) ) continue; if( renderRow.id == LAYER_VIA_MICROVIA && !settings.m_MicroViasAllowed ) continue; if( renderRow.id == LAYER_VIA_BBLIND && !settings.m_BlindBuriedViaAllowed ) continue; if( !renderRow.spacer ) { renderRow.tooltip = wxGetTranslation( s_render_rows[row].tooltip ); renderRow.rowName = wxGetTranslation( s_render_rows[row].rowName ); if( renderRow.color != COLOR4D::UNSPECIFIED ) // does this row show a color? { // this window frame must have an established BOARD, i.e. after SetBoard() renderRow.color = myframe->Settings().Colors().GetItemColor( static_cast<GAL_LAYER_ID>( renderRow.id ) ); } renderRow.state = board->IsElementVisible( static_cast<GAL_LAYER_ID>( renderRow.id ) ); } AppendRenderRow( renderRow ); } UpdateLayouts(); }
void EDA_DRAW_FRAME::Process_PageSettings( wxCommandEvent& event ) { FRAME_T smallSizeFrames[] = { FRAME_PCB, FRAME_PCB_MODULE_EDITOR, FRAME_PCB_MODULE_VIEWER, FRAME_PCB_MODULE_VIEWER_MODAL, FRAME_PCB_FOOTPRINT_WIZARD, FRAME_PCB_FOOTPRINT_PREVIEW, FRAME_CVPCB_DISPLAY }; // Fix the max page size: it is MAX_PAGE_SIZE_EDITORS // or MAX_PAGE_SIZE_PCBNEW for Pcbnew draw frames, due to the small internal // units that do not allow too large draw areas wxSize maxPageSize( MAX_PAGE_SIZE_EDITORS_MILS, MAX_PAGE_SIZE_EDITORS_MILS ); for( unsigned ii = 0; ii < arrayDim( smallSizeFrames ); ii++ ) { if( IsType( smallSizeFrames[ii] ) ) { maxPageSize.x = maxPageSize.y = MAX_PAGE_SIZE_PCBNEW_MILS; break; } } DIALOG_PAGES_SETTINGS dlg( this, maxPageSize ); dlg.SetWksFileName( BASE_SCREEN::m_PageLayoutDescrFileName ); if( dlg.ShowModal() == wxID_OK ) { #ifdef EESCHEMA RedrawScreen( wxPoint( 0, 0 ), false ); #else GetCanvas()->Refresh(); #endif } }
/** * Function AskLoadBoardFileName * puts up a wxFileDialog asking for a BOARD filename to open. * * @param aParent is a wxFrame passed to wxFileDialog. * @param aCtl is where to put the OpenProjectFiles() control bits. * * @param aFileName on entry is a probable choice, on return is the chosen filename. * @param aKicadFilesOnly true to list kiacad pcb files plugins only, false to list import plugins. * * @return bool - true if chosen, else false if user aborted. */ bool AskLoadBoardFileName( wxWindow* aParent, int* aCtl, wxString* aFileName, bool aKicadFilesOnly ) { // This is a subset of all PLUGINs which are trusted to be able to // load a BOARD. User may occasionally use the wrong plugin to load a // *.brd file (since both legacy and eagle use *.brd extension), // but eventually *.kicad_pcb will be more common than legacy *.brd files. static const struct { const wxString& filter; IO_MGR::PCB_FILE_T pluginType; } loaders[] = { { PcbFileWildcard(), IO_MGR::KICAD_SEXP }, // Current Kicad board files { LegacyPcbFileWildcard(), IO_MGR::LEGACY }, // Old Kicad board files { EaglePcbFileWildcard(), IO_MGR::EAGLE }, // Import board files { PCadPcbFileWildcard(), IO_MGR::PCAD }, // Import board files }; wxFileName fileName( *aFileName ); wxString fileFilters; if( aKicadFilesOnly ) { for( unsigned ii = 0; ii < 2; ++ii ) { if( !fileFilters.IsEmpty() ) fileFilters += wxChar( '|' ); fileFilters += wxGetTranslation( loaders[ii].filter ); } } else { for( unsigned ii = 2; ii < arrayDim( loaders ); ++ii ) { if( !fileFilters.IsEmpty() ) fileFilters += wxChar( '|' ); fileFilters += wxGetTranslation( loaders[ii].filter ); } } wxString path; wxString name; if( fileName.FileExists() ) { path = fileName.GetPath(); name = fileName.GetFullName(); } else { path = wxStandardPaths::Get().GetDocumentsDir(); // leave name empty } wxFileDialog dlg( aParent, aKicadFilesOnly ? _( "Open Board File" ) : _( "Import Non KiCad Board File" ), path, name, fileFilters, wxFD_OPEN | wxFD_FILE_MUST_EXIST ); if( dlg.ShowModal() == wxID_OK ) { // For import option, if Eagle (*.brd files), tell OpenProjectFiles() to use Eagle plugin. // It's the only special case because of the duplicate use of the *.brd file extension. // Other cases are clear because of unique file extensions. *aCtl = aKicadFilesOnly ? 0 : KICTL_EAGLE_BRD; *aFileName = dlg.GetPath(); return true; } else return false; }
void DIALOG_PAGES_SETTINGS::GetPageLayoutInfoFromDialog() { int idx = std::max( m_paperSizeComboBox->GetSelection(), 0 ); const wxString paperType = m_pageFmt[idx]; // here we assume translators will keep original paper size spellings if( paperType.Contains( PAGE_INFO::Custom ) ) { GetCustomSizeMilsFromDialog(); if( m_layout_size.x && m_layout_size.y ) { if( m_layout_size.x < m_layout_size.y ) m_orientationComboBox->SetStringSelection( _( "Portrait" ) ); else m_orientationComboBox->SetStringSelection( _( "Landscape" ) ); } } else { PAGE_INFO pageInfo; // SetType() later to lookup size static const wxChar* papers[] = { // longest common string first, since sequential search below PAGE_INFO::A4, PAGE_INFO::A3, PAGE_INFO::A2, PAGE_INFO::A1, PAGE_INFO::A0, PAGE_INFO::A, PAGE_INFO::B, PAGE_INFO::C, PAGE_INFO::D, PAGE_INFO::E, PAGE_INFO::USLetter, PAGE_INFO::USLegal, PAGE_INFO::USLedger, }; unsigned i; for( i=0; i < arrayDim( papers ); ++i ) { if( paperType.Contains( papers[i] ) ) { pageInfo.SetType( papers[i] ); break; } } wxASSERT( i != arrayDim(papers) ); // dialog UI match the above list? m_layout_size = pageInfo.GetSizeMils(); // swap sizes to match orientation bool isPortrait = (bool) m_orientationComboBox->GetSelection(); if( ( isPortrait && m_layout_size.x >= m_layout_size.y ) || ( !isPortrait && m_layout_size.x < m_layout_size.y ) ) { m_layout_size.Set( m_layout_size.y, m_layout_size.x ); } } }
void DIALOG_PAGES_SETTINGS::initDialog() { wxString msg; // initialize page format choice box and page format list. // The first shows translated strings, the second contains not translated strings m_paperSizeComboBox->Clear(); for( unsigned ii = 0; ii < arrayDim(pageFmts); ii++ ) { m_pageFmt.Add( pageFmts[ii] ); m_paperSizeComboBox->Append( wxGetTranslation( pageFmts[ii] ) ); } // initialize the page layout descr filename SetWksFileName( BASE_SCREEN::m_PageLayoutDescrFileName ); #ifdef EESCHEMA // Init display value for schematic sub-sheet number wxString format = m_TextSheetCount->GetLabel(); msg.Printf( format, m_screen->m_NumberOfScreens ); m_TextSheetCount->SetLabel( msg ); format = m_TextSheetNumber->GetLabel(); msg.Printf( format, m_screen->m_ScreenNumber ); m_TextSheetNumber->SetLabel( msg ); #else m_TextSheetCount->Show( false ); m_TextSheetNumber->Show( false ); #endif m_pageInfo = m_parent->GetPageSettings(); SetCurrentPageSizeSelection( m_pageInfo.GetType() ); m_orientationComboBox->SetSelection( m_pageInfo.IsPortrait() ); // only a click fires the "selection changed" event, so have to fabricate this check wxCommandEvent dummy; OnPaperSizeChoice( dummy ); if( m_customFmt ) { m_customSizeX.SetValue( m_pageInfo.GetWidthMils() * IU_PER_MILS ); m_customSizeY.SetValue( m_pageInfo.GetHeightMils() * IU_PER_MILS ); } else { m_customSizeX.SetValue( m_pageInfo.GetCustomWidthMils() * IU_PER_MILS ); m_customSizeY.SetValue( m_pageInfo.GetCustomHeightMils() * IU_PER_MILS ); } m_TextRevision->SetValue( m_tb.GetRevision() ); m_TextDate->SetValue( m_tb.GetDate() ); m_TextTitle->SetValue( m_tb.GetTitle() ); m_TextCompany->SetValue( m_tb.GetCompany() ); m_TextComment1->SetValue( m_tb.GetComment1() ); m_TextComment2->SetValue( m_tb.GetComment2() ); m_TextComment3->SetValue( m_tb.GetComment3() ); m_TextComment4->SetValue( m_tb.GetComment4() ); #ifndef EESCHEMA // these options have meaning only for Eeschema. // disable them for other apps m_RevisionExport->Show( false ); m_DateExport->Show( false ); m_TitleExport->Show( false ); m_CompanyExport->Show( false ); m_Comment1Export->Show( false ); m_Comment2Export->Show( false ); m_Comment3Export->Show( false ); m_Comment4Export->Show( false ); #endif GetPageLayoutInfoFromDialog(); UpdatePageLayoutExample(); // Make the OK button the default. m_sdbSizerOK->SetDefault(); m_initialized = true; }
/* * Note 1: polygons are drawm using outlines witk a thickness = aMinThicknessValue * so shapes must take in account this outline thickness * * Note 2: * Trapezoidal pads are not considered here because they are very special case * and are used in microwave applications and they *DO NOT* have a thermal relief that * change the shape by creating stubs and destroy their properties. */ void CreateThermalReliefPadPolygon( SHAPE_POLY_SET& aCornerBuffer, const D_PAD& aPad, int aThermalGap, int aCopperThickness, int aMinThicknessValue, int aError, double aThermalRot ) { wxPoint corner, corner_end; wxSize copper_thickness; wxPoint padShapePos = aPad.ShapePos(); // Note: for pad having a shape offset, // the pad position is NOT the shape position /* Keep in account the polygon outline thickness * aThermalGap must be increased by aMinThicknessValue/2 because drawing external outline * with a thickness of aMinThicknessValue will reduce gap by aMinThicknessValue/2 */ aThermalGap += aMinThicknessValue / 2; /* Keep in account the polygon outline thickness * copper_thickness must be decreased by aMinThicknessValue because drawing outlines * with a thickness of aMinThicknessValue will increase real thickness by aMinThicknessValue */ int dx = aPad.GetSize().x / 2; int dy = aPad.GetSize().y / 2; copper_thickness.x = std::min( aPad.GetSize().x, aCopperThickness ) - aMinThicknessValue; copper_thickness.y = std::min( aPad.GetSize().y, aCopperThickness ) - aMinThicknessValue; if( copper_thickness.x < 0 ) copper_thickness.x = 0; if( copper_thickness.y < 0 ) copper_thickness.y = 0; switch( aPad.GetShape() ) { case PAD_SHAPE_CIRCLE: // Add 4 similar holes { /* we create 4 copper holes and put them in position 1, 2, 3 and 4 * here is the area of the rectangular pad + its thermal gap * the 4 copper holes remove the copper in order to create the thermal gap * 4 ------ 1 * | | * | | * | | * | | * 3 ------ 2 * holes 2, 3, 4 are the same as hole 1, rotated 90, 180, 270 deg */ // Build the hole pattern, for the hole in the X >0, Y > 0 plane: // The pattern roughtly is a 90 deg arc pie std::vector <wxPoint> corners_buffer; int numSegs = std::max( GetArcToSegmentCount( dx + aThermalGap, aError, 360.0 ), 6 ); double correction = GetCircletoPolyCorrectionFactor( numSegs ); double delta = 3600.0 / numSegs; // Radius of outer arcs of the shape corrected for arc approximation by lines int outer_radius = KiROUND( ( dx + aThermalGap ) * correction ); // Crosspoint of thermal spoke sides, the first point of polygon buffer corners_buffer.push_back( wxPoint( copper_thickness.x / 2, copper_thickness.y / 2 ) ); // Add an intermediate point on spoke sides, to allow a > 90 deg angle between side // and first seg of arc approx corner.x = copper_thickness.x / 2; int y = outer_radius - (aThermalGap / 4); corner.y = KiROUND( sqrt( ( (double) y * y - (double) corner.x * corner.x ) ) ); if( aThermalRot != 0 ) corners_buffer.push_back( corner ); // calculate the starting point of the outter arc corner.x = copper_thickness.x / 2; corner.y = KiROUND( sqrt( ( (double) outer_radius * outer_radius ) - ( (double) corner.x * corner.x ) ) ); RotatePoint( &corner, 90 ); // 9 degrees is the spoke fillet size // calculate the ending point of the outer arc corner_end.x = corner.y; corner_end.y = corner.x; // calculate intermediate points (y coordinate from corner.y to corner_end.y while( (corner.y > corner_end.y) && (corner.x < corner_end.x) ) { corners_buffer.push_back( corner ); RotatePoint( &corner, delta ); } corners_buffer.push_back( corner_end ); /* add an intermediate point, to avoid angles < 90 deg between last arc approx line * and radius line */ corner.x = corners_buffer[1].y; corner.y = corners_buffer[1].x; corners_buffer.push_back( corner ); // Now, add the 4 holes ( each is the pattern, rotated by 0, 90, 180 and 270 deg // aThermalRot = 450 (45.0 degrees orientation) work fine. double angle_pad = aPad.GetOrientation(); // Pad orientation double th_angle = aThermalRot; for( unsigned ihole = 0; ihole < 4; ihole++ ) { aCornerBuffer.NewOutline(); for( unsigned ii = 0; ii < corners_buffer.size(); ii++ ) { corner = corners_buffer[ii]; RotatePoint( &corner, th_angle + angle_pad ); // Rotate by segment angle and pad orientation corner += padShapePos; aCornerBuffer.Append( corner.x, corner.y ); } th_angle += 900; // Note: th_angle in in 0.1 deg. } } break; case PAD_SHAPE_OVAL: { // Oval pad support along the lines of round and rectangular pads std::vector <wxPoint> corners_buffer; // Polygon buffer as vector dx = (aPad.GetSize().x / 2) + aThermalGap; // Cutout radius x dy = (aPad.GetSize().y / 2) + aThermalGap; // Cutout radius y wxPoint shape_offset; // We want to calculate an oval shape with dx > dy. // if this is not the case, exchange dx and dy, and rotate the shape 90 deg. int supp_angle = 0; if( dx < dy ) { std::swap( dx, dy ); supp_angle = 900; std::swap( copper_thickness.x, copper_thickness.y ); } int deltasize = dx - dy; // = distance between shape position and the 2 demi-circle ends centre // here we have dx > dy // Radius of outer arcs of the shape: int outer_radius = dy; // The radius of the outer arc is radius end + aThermalGap int numSegs = std::max( GetArcToSegmentCount( outer_radius, aError, 360.0 ), 6 ); double delta = 3600.0 / numSegs; // Some coordinate fiddling, depending on the shape offset direction shape_offset = wxPoint( deltasize, 0 ); // Crosspoint of thermal spoke sides, the first point of polygon buffer corner.x = copper_thickness.x / 2; corner.y = copper_thickness.y / 2; corners_buffer.push_back( corner ); // Arc start point calculation, the intersecting point of cutout arc and thermal spoke edge // If copper thickness is more than shape offset, we need to calculate arc intercept point. if( copper_thickness.x > deltasize ) { corner.x = copper_thickness.x / 2; corner.y = KiROUND( sqrt( ( (double) outer_radius * outer_radius ) - ( (double) ( corner.x - delta ) * ( corner.x - deltasize ) ) ) ); corner.x -= deltasize; /* creates an intermediate point, to have a > 90 deg angle * between the side and the first segment of arc approximation */ wxPoint intpoint = corner; intpoint.y -= aThermalGap / 4; corners_buffer.push_back( intpoint + shape_offset ); RotatePoint( &corner, 90 ); // 9 degrees of thermal fillet } else { corner.x = copper_thickness.x / 2; corner.y = outer_radius; corners_buffer.push_back( corner ); } // Add an intermediate point on spoke sides, to allow a > 90 deg angle between side // and first seg of arc approx wxPoint last_corner; last_corner.y = copper_thickness.y / 2; int px = outer_radius - (aThermalGap / 4); last_corner.x = KiROUND( sqrt( ( ( (double) px * px ) - (double) last_corner.y * last_corner.y ) ) ); // Arc stop point calculation, the intersecting point of cutout arc and thermal spoke edge corner_end.y = copper_thickness.y / 2; corner_end.x = KiROUND( sqrt( ( (double) outer_radius * outer_radius ) - ( (double) corner_end.y * corner_end.y ) ) ); RotatePoint( &corner_end, -90 ); // 9 degrees of thermal fillet // calculate intermediate arc points till limit is reached while( (corner.y > corner_end.y) && (corner.x < corner_end.x) ) { corners_buffer.push_back( corner + shape_offset ); RotatePoint( &corner, delta ); } //corners_buffer.push_back(corner + shape_offset); // TODO: about one mil geometry error forms somewhere. corners_buffer.push_back( corner_end + shape_offset ); corners_buffer.push_back( last_corner + shape_offset ); // Enabling the line above shows intersection point. /* Create 2 holes, rotated by pad rotation. */ double angle = aPad.GetOrientation() + supp_angle; for( int irect = 0; irect < 2; irect++ ) { aCornerBuffer.NewOutline(); for( unsigned ic = 0; ic < corners_buffer.size(); ic++ ) { wxPoint cpos = corners_buffer[ic]; RotatePoint( &cpos, angle ); cpos += padShapePos; aCornerBuffer.Append( cpos.x, cpos.y ); } angle = AddAngles( angle, 1800 ); // this is calculate hole 3 } // Create holes, that are the mirrored from the previous holes for( unsigned ic = 0; ic < corners_buffer.size(); ic++ ) { wxPoint swap = corners_buffer[ic]; swap.x = -swap.x; corners_buffer[ic] = swap; } // Now add corner 4 and 2 (2 is the corner 4 rotated by 180 deg angle = aPad.GetOrientation() + supp_angle; for( int irect = 0; irect < 2; irect++ ) { aCornerBuffer.NewOutline(); for( unsigned ic = 0; ic < corners_buffer.size(); ic++ ) { wxPoint cpos = corners_buffer[ic]; RotatePoint( &cpos, angle ); cpos += padShapePos; aCornerBuffer.Append( cpos.x, cpos.y ); } angle = AddAngles( angle, 1800 ); } } break; case PAD_SHAPE_CHAMFERED_RECT: case PAD_SHAPE_ROUNDRECT: // thermal shape is the same for rectangular shapes. case PAD_SHAPE_RECT: { /* we create 4 copper holes and put them in position 1, 2, 3 and 4 * here is the area of the rectangular pad + its thermal gap * the 4 copper holes remove the copper in order to create the thermal gap * 1 ------ 4 * | | * | | * | | * | | * 2 ------ 3 * hole 3 is the same as hole 1, rotated 180 deg * hole 4 is the same as hole 2, rotated 180 deg and is the same as hole 1, mirrored */ // First, create a rectangular hole for position 1 : // 2 ------- 3 // | | // | | // | | // 1 -------4 // Modified rectangles with one corner rounded. TODO: merging with oval thermals // and possibly round too. std::vector <wxPoint> corners_buffer; // Polygon buffer as vector dx = (aPad.GetSize().x / 2) + aThermalGap; // Cutout radius x dy = (aPad.GetSize().y / 2) + aThermalGap; // Cutout radius y // calculation is optimized for pad shape with dy >= dx (vertical rectangle). // if it is not the case, just rotate this shape 90 degrees: double angle = aPad.GetOrientation(); wxPoint corner_origin_pos( -aPad.GetSize().x / 2, -aPad.GetSize().y / 2 ); if( dy < dx ) { std::swap( dx, dy ); std::swap( copper_thickness.x, copper_thickness.y ); std::swap( corner_origin_pos.x, corner_origin_pos.y ); angle += 900.0; } // Now calculate the hole pattern in position 1 ( top left pad corner ) // The first point of polygon buffer is left lower corner, second the crosspoint of // thermal spoke sides, the third is upper right corner and the rest are rounding // vertices going anticlockwise. Note the inverted Y-axis in corners_buffer y coordinates. wxPoint arc_end_point( -dx, -(aThermalGap / 4 + copper_thickness.y / 2) ); corners_buffer.push_back( arc_end_point ); // Adds small miters to zone corners_buffer.push_back( wxPoint( -(dx - aThermalGap / 4), -copper_thickness.y / 2 ) ); // fill and spoke corner corners_buffer.push_back( wxPoint( -copper_thickness.x / 2, -copper_thickness.y / 2 ) ); corners_buffer.push_back( wxPoint( -copper_thickness.x / 2, -(dy - aThermalGap / 4) ) ); // The first point to build the rounded corner: wxPoint arc_start_point( -(aThermalGap / 4 + copper_thickness.x / 2) , -dy ); corners_buffer.push_back( arc_start_point ); int numSegs = std::max( GetArcToSegmentCount( aThermalGap, aError, 360.0 ), 6 ); double correction = GetCircletoPolyCorrectionFactor( numSegs ); int rounding_radius = KiROUND( aThermalGap * correction ); // Corner rounding radius // Calculate arc angle parameters. // the start angle id near 900 decidegrees, the final angle is near 1800.0 decidegrees. double arc_increment = 3600.0 / numSegs; // the arc_angle_start is 900.0 or slighly more, depending on the actual arc starting point double arc_angle_start = atan2( -arc_start_point.y -corner_origin_pos.y, arc_start_point.x - corner_origin_pos.x ) * 1800/M_PI; if( arc_angle_start < 900.0 ) arc_angle_start = 900.0; bool first_point = true; for( double curr_angle = arc_angle_start; ; curr_angle += arc_increment ) { wxPoint corner_position = wxPoint( rounding_radius, 0 ); RotatePoint( &corner_position, curr_angle ); // Rounding vector rotation corner_position += corner_origin_pos; // Rounding vector + Pad corner offset // The arc angle is <= 90 degrees, therefore the arc is finished if the x coordinate // decrease or the y coordinate is smaller than the y end point if( !first_point && ( corner_position.x >= corners_buffer.back().x || corner_position.y > arc_end_point.y ) ) break; first_point = false; // Note: for hole in position 1, arc x coordinate is always < x starting point // and arc y coordinate is always <= y ending point if( corner_position != corners_buffer.back() // avoid duplicate corners. && corner_position.x <= arc_start_point.x ) // skip current point at the right of the starting point corners_buffer.push_back( corner_position ); } for( int irect = 0; irect < 2; irect++ ) { aCornerBuffer.NewOutline(); for( unsigned ic = 0; ic < corners_buffer.size(); ic++ ) { wxPoint cpos = corners_buffer[ic]; RotatePoint( &cpos, angle ); // Rotate according to module orientation cpos += padShapePos; // Shift origin to position aCornerBuffer.Append( cpos.x, cpos.y ); } angle = AddAngles( angle, 1800 ); // this is calculate hole 3 } // Create holes, that are the mirrored from the previous holes for( unsigned ic = 0; ic < corners_buffer.size(); ic++ ) { wxPoint swap = corners_buffer[ic]; swap.x = -swap.x; corners_buffer[ic] = swap; } // Now add corner 4 and 2 (2 is the corner 4 rotated by 180 deg for( int irect = 0; irect < 2; irect++ ) { aCornerBuffer.NewOutline(); for( unsigned ic = 0; ic < corners_buffer.size(); ic++ ) { wxPoint cpos = corners_buffer[ic]; RotatePoint( &cpos, angle ); cpos += padShapePos; aCornerBuffer.Append( cpos.x, cpos.y ); } angle = AddAngles( angle, 1800 ); } } break; case PAD_SHAPE_TRAPEZOID: { SHAPE_POLY_SET antipad; // The full antipad area // We need a length to build the stubs of the thermal reliefs // the value is not very important. The pad bounding box gives a reasonable value EDA_RECT bbox = aPad.GetBoundingBox(); int stub_len = std::max( bbox.GetWidth(), bbox.GetHeight() ); aPad.TransformShapeWithClearanceToPolygon( antipad, aThermalGap ); SHAPE_POLY_SET stub; // A basic stub ( a rectangle) SHAPE_POLY_SET stubs; // the full stubs shape // We now substract the stubs (connections to the copper zone) //ClipperLib::Clipper clip_engine; // Prepare a clipping transform //clip_engine.AddPath( antipad, ClipperLib::ptSubject, true ); // Create stubs and add them to clipper engine wxPoint stubBuffer[4]; stubBuffer[0].x = stub_len; stubBuffer[0].y = copper_thickness.y/2; stubBuffer[1] = stubBuffer[0]; stubBuffer[1].y = -copper_thickness.y/2; stubBuffer[2] = stubBuffer[1]; stubBuffer[2].x = -stub_len; stubBuffer[3] = stubBuffer[2]; stubBuffer[3].y = copper_thickness.y/2; stub.NewOutline(); for( unsigned ii = 0; ii < arrayDim( stubBuffer ); ii++ ) { wxPoint cpos = stubBuffer[ii]; RotatePoint( &cpos, aPad.GetOrientation() ); cpos += padShapePos; stub.Append( cpos.x, cpos.y ); } stubs.Append( stub ); stubBuffer[0].y = stub_len; stubBuffer[0].x = copper_thickness.x/2; stubBuffer[1] = stubBuffer[0]; stubBuffer[1].x = -copper_thickness.x/2; stubBuffer[2] = stubBuffer[1]; stubBuffer[2].y = -stub_len; stubBuffer[3] = stubBuffer[2]; stubBuffer[3].x = copper_thickness.x/2; stub.RemoveAllContours(); stub.NewOutline(); for( unsigned ii = 0; ii < arrayDim( stubBuffer ); ii++ ) { wxPoint cpos = stubBuffer[ii]; RotatePoint( &cpos, aPad.GetOrientation() ); cpos += padShapePos; stub.Append( cpos.x, cpos.y ); } stubs.Append( stub ); stubs.Simplify( SHAPE_POLY_SET::PM_FAST ); antipad.BooleanSubtract( stubs, SHAPE_POLY_SET::PM_FAST ); aCornerBuffer.Append( antipad ); break; } default: ; } }
void KICAD_MANAGER_FRAME::OnArchiveFiles( wxCommandEvent& event ) { // List of file extensions to save. static const wxChar* extentionList[] = { wxT( "*.pro" ), wxT( "*.sch" ), wxT( "*.lib" ), wxT( "*.dcm" ), // Schematic related files wxT( "*.cmp" ), wxT( "*.brd" ), wxT( "*.kicad_pcb" ), // Brd files wxT( "*.mod" ), wxT( "*.kicad_mod" ), // fp files wxT( "*.gb?" ), wxT( "*.gbrjob" ), // Gerber files wxT( "*.gko" ), wxT( "*.gm1" ), wxT( "*.gm2" ), wxT( "*.g?" ), wxT( "*.gp1" ), wxT( "*.gp2" ), wxT( "*.gpb" ), wxT( "*.gpt" ), wxT( "*.gt?" ), wxT( "*.pos" ), wxT( "*.drl" ), // Fab files wxT( "*.d356" ), wxT( "*.rpt" ), wxT( "*.stp" ), wxT( "*.step" ), // 3d files wxT( "*.wrl" ), wxT( "*.net" ), wxT( "*.py" ), wxT( "*.pdf" ), wxT( "*.txt" ), wxT( "*.kicad_wks" ), wxT( "fp-lib-table" ), wxT( "sym-lib-table" ) }; wxString msg; wxFileName fileName = GetProjectFileName(); wxString oldCwd = wxGetCwd(); fileName.SetExt( wxT( "zip" ) ); wxFileDialog dlg( this, _( "Archive Project Files" ), fileName.GetPath(), fileName.GetFullName(), ZipFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); if( dlg.ShowModal() == wxID_CANCEL ) return; wxFileName zip = dlg.GetPath(); wxString currdirname = fileName.GetPathWithSep(); wxDir dir( currdirname ); if( !dir.IsOpened() ) // wxWidgets display a error message on issue. return; wxSetWorkingDirectory( currdirname ); // Prepare the zip file wxString zipfilename = zip.GetFullPath(); wxFFileOutputStream ostream( zipfilename ); if( !ostream.IsOk() ) // issue to create the file. Perhaps not writable dir { wxMessageBox( wxString::Format( _( "Unable to create zip archive file \"%s\"" ), zipfilename ) ); return; } wxZipOutputStream zipstream( ostream ); // Build list of filenames to put in zip archive wxString currFilename; wxArrayString files; for( unsigned ii = 0; ii < arrayDim( extentionList ); ii++ ) wxDir::GetAllFiles( currdirname, &files, extentionList[ii] ); files.Sort(); int zipBytesCnt = 0; for( unsigned ii = 0; ii < files.GetCount(); ii++ ) { wxFileSystem fsfile; wxFileName curr_fn( files[ii] ); curr_fn.MakeRelativeTo( currdirname ); currFilename = curr_fn.GetFullPath(); msg.Printf( _( "Archive file \"%s\"" ), GetChars( currFilename ) ); PrintMsg( msg ); // Read input file and add it to the zip file: wxFSFile* infile = fsfile.OpenFile( currFilename ); if( infile ) { zipstream.PutNextEntry( currFilename, infile->GetModificationTime() ); infile->GetStream()->Read( zipstream ); zipstream.CloseEntry(); int zippedsize = zipstream.GetSize() - zipBytesCnt; zipBytesCnt = zipstream.GetSize(); PrintMsg( wxT(" ") ); msg.Printf( _( "(%lu bytes, compressed %d bytes)\n" ), (unsigned long)infile->GetStream()->GetSize(), zippedsize ); PrintMsg( msg ); delete infile; } else PrintMsg( _( " >>Error\n" ) ); } zipBytesCnt = ostream.GetSize(); if( zipstream.Close() ) { msg.Printf( _( "\nZip archive \"%s\" created (%d bytes)" ), GetChars( zipfilename ), zipBytesCnt ); PrintMsg( msg ); PrintMsg( wxT( "\n** end **\n" ) ); } else { msg.Printf( wxT( "Unable to create archive \"%s\", abort\n" ), GetChars( zipfilename ) ); PrintMsg( msg ); } wxSetWorkingDirectory( oldCwd ); }
PL_EDITOR_FRAME::PL_EDITOR_FRAME( KIWAY* aKiway, wxWindow* aParent ) : EDA_DRAW_FRAME( aKiway, aParent, FRAME_PL_EDITOR, wxT( "PlEditorFrame" ), wxDefaultPosition, wxDefaultSize, KICAD_DEFAULT_DRAWFRAME_STYLE, PL_EDITOR_FRAME_NAME ) { m_UserUnits = MILLIMETRES; m_zoomLevelCoeff = 290.0; // Adjusted to roughly displays zoom level = 1 // when the screen shows a 1:1 image // obviously depends on the monitor, // but this is an acceptable value m_showAxis = false; // true to show X and Y axis on screen m_showGridAxis = true; m_showBorderAndTitleBlock = true; // true for reference drawings. m_hotkeysDescrList = PlEditorHotkeysDescr; m_originSelectChoice = 0; SetDrawBgColor( WHITE ); // default value, user option (WHITE/BLACK) WS_DATA_MODEL::GetTheInstance().m_EditMode = true; SetShowPageLimits( true ); m_AboutTitle = "PlEditor"; m_propertiesFrameWidth = 200; // Give an icon wxIcon icon; icon.CopyFromBitmap( KiBitmap( icon_pagelayout_editor_xpm ) ); SetIcon( icon ); // Create GAL canvas #ifdef __WXMAC__ // Cairo renderer doesn't handle Retina displays m_canvasType = EDA_DRAW_PANEL_GAL::GAL_TYPE_OPENGL; #else m_canvasType = EDA_DRAW_PANEL_GAL::GAL_TYPE_CAIRO; #endif auto* drawPanel = new PL_DRAW_PANEL_GAL( this, -1, wxPoint( 0, 0 ), m_FrameSize, GetGalDisplayOptions(), m_canvasType ); SetGalCanvas( drawPanel ); LoadSettings( config() ); SetSize( m_FramePos.x, m_FramePos.y, m_FrameSize.x, m_FrameSize.y ); wxSize pageSizeIU = GetPageLayout().GetPageSettings().GetSizeIU(); SetScreen( new PL_EDITOR_SCREEN( pageSizeIU ) ); if( !GetScreen()->GridExists( m_LastGridSizeId + ID_POPUP_GRID_LEVEL_1000 ) ) m_LastGridSizeId = ID_POPUP_GRID_LEVEL_1MM - ID_POPUP_GRID_LEVEL_1000; GetScreen()->SetGrid( m_LastGridSizeId + ID_POPUP_GRID_LEVEL_1000 ); setupTools(); ReCreateMenuBar(); ReCreateHToolbar(); ReCreateVToolbar(); wxWindow* stsbar = GetStatusBar(); int dims[] = { // balance of status bar on far left is set to a default or whatever is left over. -1, // When using GetTextSize() remember the width of '1' is not the same // as the width of '0' unless the font is fixed width, and it usually won't be. // zoom: GetTextSize( wxT( "Z 762000" ), stsbar ).x + 10, // cursor coords GetTextSize( wxT( "X 0234.567 Y 0234.567" ), stsbar ).x + 10, // delta distances GetTextSize( wxT( "dx 0234.567 dx 0234.567" ), stsbar ).x + 10, // Coord origin (use the bigger message) GetTextSize( _( "coord origin: Right Bottom page corner" ), stsbar ).x + 10, // units display, Inches is bigger than mm GetTextSize( _( "Inches" ), stsbar ).x + 10 }; SetStatusWidths( arrayDim( dims ), dims ); m_auimgr.SetManagedWindow( this ); m_auimgr.SetArtProvider( new EDA_DOCKART( this ) ); m_propertiesPagelayout = new PROPERTIES_FRAME( this ); // Horizontal items; layers 4 - 6 m_auimgr.AddPane( m_mainToolBar, EDA_PANE().HToolbar().Name( "MainToolbar" ).Top().Layer(6) ); m_auimgr.AddPane( m_messagePanel, EDA_PANE().Messages().Name( "MsgPanel" ).Bottom().Layer(6) ); // Vertical items; layers 1 - 3 m_auimgr.AddPane( m_drawToolBar, EDA_PANE().VToolbar().Name( "ToolsToolbar" ).Right().Layer(1) ); m_auimgr.AddPane( m_propertiesPagelayout, EDA_PANE().Palette().Name( "Props" ).Right().Layer(2) .Caption( _( "Properties" ) ).MinSize( m_propertiesPagelayout->GetMinSize() ) .BestSize( m_propertiesFrameWidth, -1 ) ); m_auimgr.AddPane( m_canvas, EDA_PANE().Canvas().Name( "DrawFrame" ).Center() ); m_auimgr.AddPane( GetGalCanvas(), EDA_PANE().Canvas().Name( "DrawFrameGal" ).Center().Hide() ); // Set up viewport KIGFX::VIEW* view = GetGalCanvas()->GetView(); view->SetScale( GetZoomLevelCoeff() / m_canvas->GetZoom() ); view->SetCenter( VECTOR2D( m_canvas->GetScreenCenterLogicalPosition() ) ); UseGalCanvas(); m_auimgr.Update(); // Initialize the current page layout WS_DATA_MODEL& pglayout = WS_DATA_MODEL::GetTheInstance(); #if 0 //start with empty layout pglayout.AllowVoidList( true ); pglayout.ClearList(); #else // start with the default Kicad layout pglayout.SetPageLayout(); #endif OnNewPageLayout(); }
EDA_DRAW_FRAME::EDA_DRAW_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrameType, const wxString& aTitle, const wxPoint& aPos, const wxSize& aSize, long aStyle, const wxString & aFrameName ) : KIWAY_PLAYER( aKiway, aParent, aFrameType, aTitle, aPos, aSize, aStyle, aFrameName ) { m_socketServer = nullptr; m_mainToolBar = NULL; m_drawToolBar = NULL; m_optionsToolBar = NULL; m_auxiliaryToolBar = NULL; m_gridSelectBox = NULL; m_zoomSelectBox = NULL; m_hotkeysDescrList = NULL; m_canvas = NULL; m_canvasType = EDA_DRAW_PANEL_GAL::GAL_TYPE_NONE; m_galCanvas = NULL; m_actions = NULL; m_toolManager = NULL; m_toolDispatcher = NULL; m_messagePanel = NULL; m_currentScreen = NULL; m_toolId = ID_NO_TOOL_SELECTED; m_lastDrawToolId = ID_NO_TOOL_SELECTED; m_showAxis = false; // true to draw axis. m_showBorderAndTitleBlock = false; // true to display reference sheet. m_showGridAxis = false; // true to draw the grid axis m_showOriginAxis = false; // true to draw the grid origin m_LastGridSizeId = 0; m_drawGrid = true; // hide/Show grid. default = show m_gridColor = COLOR4D( DARKGRAY ); // Default grid color m_showPageLimits = false; m_drawBgColor = COLOR4D( BLACK ); // the background color of the draw canvas: // BLACK for Pcbnew, BLACK or WHITE for eeschema m_snapToGrid = true; m_MsgFrameHeight = EDA_MSG_PANEL::GetRequiredHeight(); m_movingCursorWithKeyboard = false; m_zoomLevelCoeff = 1.0; m_auimgr.SetFlags(wxAUI_MGR_DEFAULT); CreateStatusBar( 6 ); // set the size of the status bar subwindows: wxWindow* stsbar = GetStatusBar(); int dims[] = { // remainder of status bar on far left is set to a default or whatever is left over. -1, // When using GetTextSize() remember the width of character '1' is not the same // as the width of '0' unless the font is fixed width, and it usually won't be. // zoom: GetTextSize( wxT( "Z 762000" ), stsbar ).x + 10, // cursor coords GetTextSize( wxT( "X 0234.567890 Y 0234.567890" ), stsbar ).x + 10, // delta distances GetTextSize( wxT( "dx 0234.567890 dx 0234.567890 d 0234.567890" ), stsbar ).x + 10, // units display, Inches is bigger than mm GetTextSize( _( "Inches" ), stsbar ).x + 10, // Size for the panel used as "Current tool in play": will take longest string from // void PCB_EDIT_FRAME::OnSelectTool( wxCommandEvent& aEvent ) in pcbnew/edit.cpp GetTextSize( wxT( "Add layer alignment target" ), stsbar ).x + 10, }; SetStatusWidths( arrayDim( dims ), dims ); // Create child subwindows. GetClientSize( &m_FrameSize.x, &m_FrameSize.y ); m_FramePos.x = m_FramePos.y = 0; m_FrameSize.y -= m_MsgFrameHeight; m_canvas = new EDA_DRAW_PANEL( this, -1, wxPoint( 0, 0 ), m_FrameSize ); m_messagePanel = new EDA_MSG_PANEL( this, -1, wxPoint( 0, m_FrameSize.y ), wxSize( m_FrameSize.x, m_MsgFrameHeight ) ); m_messagePanel->SetBackgroundColour( COLOR4D( LIGHTGRAY ).ToColour() ); }
void PCB_LAYER_WIDGET::ReFill() { BOARD* brd = myframe->GetBoard(); LSET enabled = brd->GetEnabledLayers(); ClearLayerRows(); wxString dsc; // show all coppers first, with front on top, back on bottom, then technical layers for( LSEQ cu_stack = enabled.CuStack(); cu_stack; ++cu_stack ) { PCB_LAYER_ID layer = *cu_stack; switch( layer ) { case F_Cu: dsc = _( "Front copper layer" ); break; case B_Cu: dsc = _( "Back copper layer" ); break; default: dsc = _( "Inner copper layer" ); break; } AppendLayerRow( LAYER_WIDGET::ROW( brd->GetLayerName( layer ), layer, myframe->Settings().Colors().GetLayerColor( layer ), dsc, true ) ); if( m_fp_editor_mode && LSET::ForbiddenFootprintLayers().test( layer ) ) { getLayerComp( GetLayerRowCount()-1, COLUMN_COLOR_LYRNAME )->Enable( false ); getLayerComp( GetLayerRowCount()-1, COLUMN_COLORBM )->SetToolTip( wxEmptyString ); } } UpdateLayouts(); // technical layers are shown in this order: // Because they are static, wxGetTranslation must be explicitly // called for tooltips. static const struct { PCB_LAYER_ID layerId; wxString tooltip; } non_cu_seq[] = { { F_Adhes, _( "Adhesive on board's front" ) }, { B_Adhes, _( "Adhesive on board's back" ) }, { F_Paste, _( "Solder paste on board's front" ) }, { B_Paste, _( "Solder paste on board's back" ) }, { F_SilkS, _( "Silkscreen on board's front" ) }, { B_SilkS, _( "Silkscreen on board's back" ) }, { F_Mask, _( "Solder mask on board's front" ) }, { B_Mask, _( "Solder mask on board's back" ) }, { Dwgs_User, _( "Explanatory drawings" ) }, { Cmts_User, _( "Explanatory comments" ) }, { Eco1_User, _( "User defined meaning" ) }, { Eco2_User, _( "User defined meaning" ) }, { Edge_Cuts, _( "Board's perimeter definition" ) }, { Margin, _( "Board's edge setback outline" ) }, { F_CrtYd, _( "Footprint courtyards on board's front" ) }, { B_CrtYd, _( "Footprint courtyards on board's back" ) }, { F_Fab, _( "Footprint assembly on board's front" ) }, { B_Fab, _( "Footprint assembly on board's back" ) } }; for( unsigned i=0; i<arrayDim( non_cu_seq ); ++i ) { PCB_LAYER_ID layer = non_cu_seq[i].layerId; if( !enabled[layer] ) continue; AppendLayerRow( LAYER_WIDGET::ROW( brd->GetLayerName( layer ), layer, myframe->Settings().Colors().GetLayerColor( layer ), wxGetTranslation( non_cu_seq[i].tooltip ), true ) ); if( m_fp_editor_mode && LSET::ForbiddenFootprintLayers().test( layer ) ) { getLayerComp( GetLayerRowCount()-1, COLUMN_COLOR_LYRNAME )->Enable( false ); getLayerComp( GetLayerRowCount()-1, COLUMN_COLORBM )->SetToolTip( wxEmptyString ); } } }
DIALOG_CREATE_ARRAY::DIALOG_CREATE_ARRAY( PCB_BASE_FRAME* aParent, bool enableNumbering, wxPoint aOrigPos ) : DIALOG_CREATE_ARRAY_BASE( aParent ), m_settings( NULL ), m_hSpacing( aParent, m_labelDx, m_entryDx, m_unitLabelDx ), m_vSpacing( aParent, m_labelDy, m_entryDy, m_unitLabelDy ), m_hOffset( aParent, m_labelOffsetX, m_entryOffsetX, m_unitLabelOffsetX ), m_vOffset( aParent, m_labelOffsetY, m_entryOffsetY, m_unitLabelOffsetY ), m_hCentre( aParent, m_labelCentreX, m_entryCentreX, m_unitLabelCentreX ), m_vCentre( aParent, m_labelCentreY, m_entryCentreY, m_unitLabelCentreY ), m_circRadius( aParent, m_labelCircRadius, m_valueCircRadius, m_unitLabelCircRadius ), m_circAngle( aParent, m_labelCircAngle, m_entryCircAngle, m_unitLabelCircAngle ), m_cfg_persister( saved_array_options.m_optionsSet ), m_originalItemPosition( aOrigPos ), m_numberingEnabled( enableNumbering ) { // Set up numbering scheme drop downs // // character set // NOTE: do not change the order of this relative to the NUMBERING_TYPE_T enum const wxString charSetDescriptions[] = { _( "Numerals (0,1,2,...,9,10)" ), _( "Hexadecimal (0,1,...,F,10,...)" ), _( "Alphabet, minus IOSQXZ" ), _( "Alphabet, full 26 characters" ) }; m_choicePriAxisNumbering->Set( arrayDim( charSetDescriptions ), charSetDescriptions ); m_choiceSecAxisNumbering->Set( arrayDim( charSetDescriptions ), charSetDescriptions ); m_choicePriAxisNumbering->SetSelection( 0 ); m_choiceSecAxisNumbering->SetSelection( 0 ); m_circAngle.SetUnits( EDA_UNITS_T::DEGREES ); // bind grid options to persister m_cfg_persister.Add( *m_entryNx, saved_array_options.m_gridNx ); m_cfg_persister.Add( *m_entryNy, saved_array_options.m_gridNy ); m_cfg_persister.Add( m_hSpacing, saved_array_options.m_gridDx ); m_cfg_persister.Add( m_vSpacing, saved_array_options.m_gridDy ); m_cfg_persister.Add( m_hOffset, saved_array_options.m_gridOffsetX ); m_cfg_persister.Add( m_vOffset, saved_array_options.m_gridOffsetY ); m_cfg_persister.Add( *m_entryStagger, saved_array_options.m_gridStagger ); m_cfg_persister.Add( *m_radioBoxGridStaggerType, saved_array_options.m_gridStaggerType ); m_cfg_persister.Add( *m_radioBoxGridNumberingAxis, saved_array_options.m_gridNumberingAxis ); m_cfg_persister.Add( *m_checkBoxGridReverseNumbering, saved_array_options.m_gridNumberingReverseAlternate ); m_cfg_persister.Add( *m_rbGridStartNumberingOpt, saved_array_options.m_gridNumberingStartSet ); m_cfg_persister.Add( *m_radioBoxGridNumberingScheme, saved_array_options.m_grid2dArrayNumbering ); m_cfg_persister.Add( *m_choicePriAxisNumbering, saved_array_options.m_gridPriAxisNumScheme ); m_cfg_persister.Add( *m_choiceSecAxisNumbering, saved_array_options.m_gridSecAxisNumScheme ); m_cfg_persister.Add( *m_entryGridPriNumberingOffset, saved_array_options.m_gridPriNumberingOffset ); m_cfg_persister.Add( *m_entryGridSecNumberingOffset, saved_array_options.m_gridSecNumberingOffset ); // bind circular options to persister m_cfg_persister.Add( m_hCentre, saved_array_options.m_circCentreX ); m_cfg_persister.Add( m_vCentre, saved_array_options.m_circCentreY ); m_cfg_persister.Add( m_circAngle, saved_array_options.m_circAngle ); m_cfg_persister.Add( *m_entryCircCount, saved_array_options.m_circCount ); m_cfg_persister.Add( *m_entryRotateItemsCb, saved_array_options.m_circRotate ); m_cfg_persister.Add( *m_rbCircStartNumberingOpt, saved_array_options.m_circNumberingStartSet ); m_cfg_persister.Add( *m_entryCircNumberingStart, saved_array_options.m_circNumberingOffset ); m_cfg_persister.Add( *m_gridTypeNotebook, saved_array_options.m_arrayTypeTab ); m_cfg_persister.RestoreConfigToControls(); // Run the callbacks once to process the dialog contents setControlEnablement(); calculateCircularArrayProperties(); m_stdButtonsOK->SetDefault(); Fit(); SetMinSize( GetSize() ); }