/* Add a new graphical text to the active module (footprint) * Note there always are 2 mandatory texts: reference and value. * New texts have the member TEXTE_MODULE.GetType() set to TEXT_is_DIVERS */ TEXTE_MODULE* FOOTPRINT_EDIT_FRAME::CreateTextModule( MODULE* aModule, wxDC* aDC ) { TEXTE_MODULE* text = new TEXTE_MODULE( aModule ); text->SetFlags( IS_NEW ); if( LSET::AllTechMask().test( GetActiveLayer() ) ) // i.e. a possible layer for a text text->SetLayer( GetActiveLayer() ); InstallTextOptionsFrame( text, NULL ); if( text->GetText().IsEmpty() ) { delete text; return NULL; } // Add the new text object to the beginning of the footprint draw list. if( aModule ) aModule->GraphicalItemsList().PushFront( text ); text->ClearFlags(); if( aDC ) text->Draw( m_canvas, aDC, GR_OR ); SetMsgPanel( text ); return text; }
/* Initialize the drawing of a segment of type other than trace. */ DRAWSEGMENT* PCB_EDIT_FRAME::Begin_DrawSegment( DRAWSEGMENT* Segment, STROKE_T shape, wxDC* DC ) { int lineWidth; DRAWSEGMENT* DrawItem; lineWidth = GetDesignSettings().GetLineThickness( GetActiveLayer() ); if( Segment == NULL ) // Create new segment. { SetCurItem( Segment = new DRAWSEGMENT( GetBoard() ) ); Segment->SetFlags( IS_NEW ); Segment->SetLayer( GetActiveLayer() ); Segment->SetWidth( lineWidth ); Segment->SetShape( shape ); Segment->SetAngle( 900 ); Segment->SetStart( GetCrossHairPosition() ); Segment->SetEnd( GetCrossHairPosition() ); m_canvas->SetMouseCapture( DrawSegment, Abort_EditEdge ); } else { // The ending point coordinate Segment->m_End was updated by the function // DrawSegment() called on a move mouse event during the segment creation if( Segment->GetStart() != Segment->GetEnd() ) { if( Segment->GetShape() == S_SEGMENT ) { SaveCopyInUndoList( Segment, UR_NEW ); GetBoard()->Add( Segment ); OnModify(); Segment->ClearFlags(); Segment->Draw( m_canvas, DC, GR_OR ); DrawItem = Segment; SetCurItem( Segment = new DRAWSEGMENT( GetBoard() ) ); Segment->SetFlags( IS_NEW ); Segment->SetLayer( DrawItem->GetLayer() ); Segment->SetWidth( lineWidth ); Segment->SetShape( DrawItem->GetShape() ); Segment->SetType( DrawItem->GetType() ); Segment->SetAngle( DrawItem->GetAngle() ); Segment->SetStart( DrawItem->GetEnd() ); Segment->SetEnd( DrawItem->GetEnd() ); DrawSegment( m_canvas, DC, wxDefaultPosition, false ); } else { End_Edge( Segment, DC ); Segment = NULL; } } } return Segment; }
bool GERBVIEW_FRAME::LoadZipArchiveFile( const wxString& aFullFileName ) { #define ZipFileExtension "zip" wxFileName filename = aFullFileName; wxString currentPath; if( !filename.IsOk() ) { // Use the current working directory if the file name path does not exist. if( filename.DirExists() ) currentPath = filename.GetPath(); else currentPath = m_mruPath; wxFileDialog dlg( this, _( "Open Zip File" ), currentPath, filename.GetFullName(), ZipFileWildcard(), wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_CHANGE_DIR ); if( dlg.ShowModal() == wxID_CANCEL ) return false; filename = dlg.GetPath(); currentPath = wxGetCwd(); m_mruPath = currentPath; } else { currentPath = filename.GetPath(); m_mruPath = currentPath; } wxString msg; WX_STRING_REPORTER reporter( &msg ); if( filename.IsOk() ) unarchiveFiles( filename.GetFullPath(), &reporter ); Zoom_Automatique( false ); // Synchronize layers tools with actual active layer: ReFillLayerWidget(); SetActiveLayer( GetActiveLayer() ); m_LayersManager->UpdateLayerIcons(); syncLayerBox(); if( !msg.IsEmpty() ) { wxSafeYield(); // Allows slice of time to redraw the screen // to refresh widgets, before displaying messages HTML_MESSAGE_BOX mbox( this, _( "Messages" ) ); mbox.ListSet( msg ); mbox.ShowModal(); } return true; }
BOOL LayerPropertiesTab::ChangeControlStatus(const BOOL Status) { BOOL Enable; Layer* pLayer = GetActiveLayer(); Enable = (pLayer != NULL) && Status; BOOL EnableNonFrameItem = Enable; //It shouldn't be in Webster builds anyway but we will take it out jus tin case #ifndef WEBSTER // Check if we are on a frame layer or not // If we are then we must disable some items // At present, these are the visible and editable flags as these are not user controlled. // BOOL FrameLayer = FALSE; if (pLayer != NULL && pLayer->IsFrame()) EnableNonFrameItem = FALSE; #endif pPropertiesDlg->EnableGadget(_R(IDC_GUIDETAB_GUIDELINELIST),Enable); pPropertiesDlg->EnableGadget(_R(IDC_LAYERTAB_NAME), Enable); pPropertiesDlg->EnableGadget(_R(IDC_LAYERTAB_VISIBLE), EnableNonFrameItem); pPropertiesDlg->EnableGadget(_R(IDC_LAYERTAB_EDITABLE), EnableNonFrameItem); return TRUE; }
BOOL LayerPropertiesTab::CommitSection() { TRACEUSER( "Neville", _T("LayerPropertiesTab::CommitSection\n")); ERROR2IF(pPropertiesDlg == NULL,FALSE,"LayerPropertiesTab::CommitSection called with no dialog pointer"); BOOL ok = pPropertiesDlg->TalkToPage(GetPageID()); if (!ok) return TRUE; // Talk to page failed to return now Layer* pLayer = GetActiveLayer(); // Only do the op if we have a layer with a different set of properties if (pLayer != NULL && HavePropertiesChanged(pLayer)) { // Initialise the param structure OpLayerGalParam Param(LAYER_CHANGE, pSpread); Param.pLayer = pLayer; Param.VisibleState = pPropertiesDlg->GetBoolGadgetSelected(_R(IDC_LAYERTAB_VISIBLE)); Param.LockedState = !pPropertiesDlg->GetBoolGadgetSelected(_R(IDC_LAYERTAB_EDITABLE)); Param.NewName = pPropertiesDlg->GetStringGadgetValue(_R(IDC_LAYERTAB_NAME),NULL); // Invoke the operation OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_LAYERGALCHANGE); if (pOpDesc != NULL) pOpDesc->Invoke((OpParam*)&Param); else { ERROR3("Couldn't find OPTOKEN_LAYERGALCHANGE op descriptor"); } } return TRUE; }
void PCB_EDIT_FRAME::InstallPcbGlobalDeleteFrame( const wxPoint& pos ) { DIALOG_GLOBAL_DELETION dlg( this ); dlg.SetCurrentLayer( GetActiveLayer() ); dlg.ShowModal(); }
DIMENSION* PCB_EDIT_FRAME::EditDimension( DIMENSION* aDimension, wxDC* aDC ) { wxPoint pos; if( aDimension == NULL ) { status_dimension = 1; pos = GetCrossHairPosition(); aDimension = new DIMENSION( GetBoard() ); aDimension->SetFlags( IS_NEW ); aDimension->SetLayer( GetActiveLayer() ); aDimension->SetOrigin( pos ); aDimension->SetEnd( pos ); aDimension->Text().SetSize( GetBoard()->GetDesignSettings().m_PcbTextSize ); int width = GetBoard()->GetDesignSettings().m_PcbTextWidth; int maxthickness = Clamp_Text_PenSize(width, aDimension->Text().GetSize() ); if( width > maxthickness ) { width = maxthickness; } aDimension->Text().SetThickness( width ); aDimension->SetWidth( width ); aDimension->AdjustDimensionDetails(); aDimension->Draw( m_canvas, aDC, GR_XOR ); m_canvas->SetMouseCapture( BuildDimension, AbortBuildDimension ); return aDimension; } // Dimension != NULL if( status_dimension == 1 ) { status_dimension = 2; return aDimension; } aDimension->Draw( m_canvas, aDC, GR_OR ); aDimension->ClearFlags(); /* ADD this new item in list */ GetBoard()->Add( aDimension ); // Add store it in undo/redo list SaveCopyInUndoList( aDimension, UR_NEW ); OnModify(); m_canvas->SetMouseCapture( NULL, NULL ); return NULL; }
void FOOTPRINT_EDIT_FRAME::SetActiveLayer( LAYER_ID aLayer ) { PCB_BASE_FRAME::SetActiveLayer( aLayer ); GetGalCanvas()->SetHighContrastLayer( aLayer ); m_Layers->SelectLayer( GetActiveLayer() ); m_Layers->OnLayerSelected(); if( IsGalCanvasActive() ) GetGalCanvas()->Refresh(); }
/* Add a new graphical text to the active module (footprint) * Note there always are 2 mandatory texts: reference and value. * New texts have the member TEXTE_MODULE.GetType() set to TEXT_is_DIVERS */ TEXTE_MODULE* FOOTPRINT_EDIT_FRAME::CreateTextModule( MODULE* aModule, wxDC* aDC ) { TEXTE_MODULE* text = new TEXTE_MODULE( aModule ); text->SetFlags( IS_NEW ); GetDesignSettings().m_ModuleTextWidth = Clamp_Text_PenSize( GetDesignSettings().m_ModuleTextWidth, std::min( GetDesignSettings().m_ModuleTextSize.x, GetDesignSettings().m_ModuleTextSize.y ), true ); text->SetTextSize( GetDesignSettings().m_ModuleTextSize ); text->SetThickness( GetDesignSettings().m_ModuleTextWidth ); text->SetPosition( GetCrossHairPosition() ); if( LSET::AllTechMask().test( GetActiveLayer() ) ) // i.e. a possible layer for a text text->SetLayer( GetActiveLayer() ); InstallTextModOptionsFrame( text, NULL ); m_canvas->MoveCursorToCrossHair(); if( text->GetText().IsEmpty() ) { delete text; return NULL; } // Add the new text object to the beginning of the footprint draw list. if( aModule ) aModule->GraphicalItems().PushFront( text ); text->ClearFlags(); if( aDC ) text->Draw( m_canvas, aDC, GR_OR ); SetMsgPanel( text ); return text; }
// Note: virtual, overridden in PCB_EDIT_FRAME; void PCB_BASE_FRAME::SwitchLayer( wxDC* DC, LAYER_ID layer ) { LAYER_ID preslayer = GetActiveLayer(); DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)GetDisplayOptions(); // Check if the specified layer matches the present layer if( layer == preslayer ) return; // Copper layers cannot be selected unconditionally; how many // of those layers are currently enabled needs to be checked. if( IsCopperLayer( layer ) ) { // If only one copper layer is enabled, the only such layer // that can be selected to is the "Copper" layer (so the // selection of any other copper layer is disregarded). if( m_Pcb->GetCopperLayerCount() < 2 ) { if( layer != B_Cu ) { return; } } // If more than one copper layer is enabled, the "Copper" // and "Component" layers can be selected, but the total // number of copper layers determines which internal // layers are also capable of being selected. else { if( ( layer != B_Cu ) && ( layer != F_Cu ) && ( layer >= m_Pcb->GetCopperLayerCount() - 1 ) ) { return; } } } // Is yet more checking required? E.g. when the layer to be selected // is a non-copper layer, or when switching between a copper layer // and a non-copper layer, or vice-versa? // ... GetScreen()->m_Active_Layer = layer; if( displ_opts->m_ContrastModeDisplay ) m_canvas->Refresh(); }
void FOOTPRINT_EDIT_FRAME::UpdateUserInterface() { // Update the layer manager and other widgets from the board setup // (layer and items visibility, colors ...) // Update the layer manager m_Layers->Freeze(); ReFillLayerWidget(); m_Layers->ReFillRender(); // update the layer widget to match board visibility states. m_Layers->SyncLayerVisibilities(); static_cast<PCB_DRAW_PANEL_GAL*>( GetGalCanvas() )->SyncLayersVisibility( m_Pcb ); m_Layers->SelectLayer( GetActiveLayer() ); m_Layers->OnLayerSelected(); m_Layers->Thaw(); }
GENERAL_COLLECTORS_GUIDE PCB_BASE_FRAME::GetCollectorsGuide() { GENERAL_COLLECTORS_GUIDE guide( m_Pcb->GetVisibleLayers(), GetActiveLayer() ); // account for the globals guide.SetIgnoreMTextsMarkedNoShow( ! m_Pcb->IsElementVisible( MOD_TEXT_INVISIBLE )); guide.SetIgnoreMTextsOnBack( ! m_Pcb->IsElementVisible( MOD_TEXT_BK_VISIBLE )); guide.SetIgnoreMTextsOnFront( ! m_Pcb->IsElementVisible( MOD_TEXT_FR_VISIBLE )); guide.SetIgnoreModulesOnBack( ! m_Pcb->IsElementVisible( MOD_BK_VISIBLE ) ); guide.SetIgnoreModulesOnFront( ! m_Pcb->IsElementVisible( MOD_FR_VISIBLE ) ); guide.SetIgnorePadsOnBack( ! m_Pcb->IsElementVisible( PAD_BK_VISIBLE ) ); guide.SetIgnorePadsOnFront( ! m_Pcb->IsElementVisible( PAD_FR_VISIBLE ) ); guide.SetIgnoreModulesVals( ! m_Pcb->IsElementVisible( MOD_VALUES_VISIBLE ) ); guide.SetIgnoreModulesRefs( ! m_Pcb->IsElementVisible( MOD_REFERENCES_VISIBLE ) ); return guide; }
void GERBVIEW_FRAME::Erase_Current_DrawLayer( bool query ) { int layer = GetActiveLayer(); wxString msg; msg.Printf( _( "Clear layer %d?" ), layer + 1 ); if( query && !IsOK( this, msg ) ) return; SetCurItem( NULL ); GetImagesList()->DeleteImage( layer ); ReFillLayerWidget(); syncLayerBox(); m_canvas->Refresh(); }
bool PCB_EDIT_FRAME::IsMicroViaAcceptable() { int copperlayercnt = GetBoard()->GetCopperLayerCount( ); LAYER_ID currLayer = GetActiveLayer(); if( !GetDesignSettings().m_MicroViasAllowed ) return false; // Obvious.. if( copperlayercnt < 4 ) return false; // Only on multilayer boards.. if( ( currLayer == B_Cu ) || ( currLayer == F_Cu ) || ( currLayer == copperlayercnt - 2 ) || ( currLayer == In1_Cu ) ) return true; return false; }
TRACK * PCB_EDIT_FRAME::OnHotkeyBeginRoute( wxDC* aDC ) { if( !IsCopperLayer( GetActiveLayer() ) ) return NULL; bool itemCurrentlyEdited = GetCurItem() && GetCurItem()->GetFlags(); // Ensure the track tool is active if( GetToolId() != ID_TRACK_BUTT && !itemCurrentlyEdited ) { wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED ); cmd.SetEventObject( this ); cmd.SetId( ID_TRACK_BUTT ); GetEventHandler()->ProcessEvent( cmd ); } if( GetToolId() != ID_TRACK_BUTT ) return NULL; TRACK* track = NULL; if( !itemCurrentlyEdited ) // no track in progress: { track = Begin_Route( NULL, aDC ); SetCurItem( track ); if( track ) m_canvas->SetAutoPanRequest( true ); } else if( GetCurItem()->IsNew() ) { track = Begin_Route( (TRACK*) GetCurItem(), aDC ); // SetCurItem() must not write to the msg panel // because a track info is displayed while moving the mouse cursor if( track ) // A new segment was created SetCurItem( track, false ); m_canvas->SetAutoPanRequest( true ); } return track; }
BOOL LayerPropertiesTab::ShowDetails() { String_256 LayerID; Layer* pLayer = GetActiveLayer(); if (pLayer != NULL) { LayerID = pLayer->GetLayerID(); // pPropertiesDlg->SetBoolGadgetSelected(_R(IDC_LAYERTAB_VISIBLE),pLayer->IsVisible()); // pPropertiesDlg->SetBoolGadgetSelected(_R(IDC_LAYERTAB_EDITABLE),!pLayer->IsLocked()); pPropertiesDlg->SetBoolGadgetSelected(_R(IDC_LAYERTAB_VISIBLE),pLayer->GetVisibleFlagState()); pPropertiesDlg->SetBoolGadgetSelected(_R(IDC_LAYERTAB_EDITABLE),!pLayer->GetLockedFlagState()); } pPropertiesDlg->SetStringGadgetValue(_R(IDC_LAYERTAB_NAME), LayerID); ChangeControlStatus(!GreyStatus); return TRUE; }
BOOL LayerPropertiesTab::UpdateApplyState() { BOOL OldApplyNowState = LayerPropertiesTab::GetApplyNowState(); Layer* pLayer = GetActiveLayer(); if (pLayer != NULL) LayerPropertiesTab::SetApplyNowState(HavePropertiesChanged(pLayer)); BOOL NewApplyNowState = LayerPropertiesTab::GetApplyNowState(); if (OldApplyNowState != NewApplyNowState) { if (NewApplyNowState) LayerPropertiesTab::UngreyApplyNow(); else LayerPropertiesTab::GreyApplyNow(); } return TRUE; }
GENERAL_COLLECTORS_GUIDE PCB_BASE_FRAME::GetCollectorsGuide() { GENERAL_COLLECTORS_GUIDE guide( m_Pcb->GetVisibleLayers(), GetActiveLayer(), GetGalCanvas()->GetView() ); // account for the globals guide.SetIgnoreMTextsMarkedNoShow( ! m_Pcb->IsElementVisible( LAYER_MOD_TEXT_INVISIBLE ) ); guide.SetIgnoreMTextsOnBack( ! m_Pcb->IsElementVisible( LAYER_MOD_TEXT_BK ) ); guide.SetIgnoreMTextsOnFront( ! m_Pcb->IsElementVisible( LAYER_MOD_TEXT_FR ) ); guide.SetIgnoreModulesOnBack( ! m_Pcb->IsElementVisible( LAYER_MOD_BK ) ); guide.SetIgnoreModulesOnFront( ! m_Pcb->IsElementVisible( LAYER_MOD_FR ) ); guide.SetIgnorePadsOnBack( ! m_Pcb->IsElementVisible( LAYER_PAD_BK ) ); guide.SetIgnorePadsOnFront( ! m_Pcb->IsElementVisible( LAYER_PAD_FR ) ); guide.SetIgnoreThroughHolePads( ! m_Pcb->IsElementVisible( LAYER_PADS_TH ) ); guide.SetIgnoreModulesVals( ! m_Pcb->IsElementVisible( LAYER_MOD_VALUES ) ); guide.SetIgnoreModulesRefs( ! m_Pcb->IsElementVisible( LAYER_MOD_REFERENCES ) ); guide.SetIgnoreThroughVias( ! m_Pcb->IsElementVisible( LAYER_VIA_THROUGH ) ); guide.SetIgnoreBlindBuriedVias( ! m_Pcb->IsElementVisible( LAYER_VIA_BBLIND ) ); guide.SetIgnoreMicroVias( ! m_Pcb->IsElementVisible( LAYER_VIA_MICROVIA ) ); guide.SetIgnoreTracks( ! m_Pcb->IsElementVisible( LAYER_TRACKS ) ); return guide; }
//________________________________________________________________ Bool_t KVFAZIADetector::Fired(Option_t *) { // Returns kTRUE if detector was hit (fired) in an event // // The actual meaning of hit/fired depends on the context and the option string opt. // // If the detector is in "simulation mode", i.e. if SetSimMode(kTRUE) has been called, // this method returns kTRUE if the calculated energy loss in the active layer is > 0. // // In "experimental mode" (i.e. IsSimMode() returns kFALSE), depending on the option: // //Info("Fired","Appel - %s",GetName()); if (!IsDetecting()) return kFALSE; //detector not working, no answer at all if (IsSimMode()) return (GetActiveLayer()->GetEnergyLoss()>0.); // simulation mode: detector fired if energy lost in active layer KVSignal* sig; if (fSignals){ TIter next(fSignals); while ( (sig = (KVSignal* )next()) ) { if (sig->GetN()>0){ if (!strcmp(sig->GetTitle(),"Charge") && sig->GetRawAmplitude()>20){ return kTRUE; } else{ } } else{ Warning("Fired","%s has empty signal %s",GetName(),sig->GetName()); } } } else{ Warning("Fired","%s : No signal attached to this detector ...",GetName()); return kFALSE; } return kFALSE; }
bool GERBVIEW_FRAME::LoadGerberFiles( const wxString& aFullFileName ) { wxString filetypes; wxArrayString filenamesList; wxFileName filename = aFullFileName; wxString currentPath; if( !filename.IsOk() ) { /* Standard gerber filetypes * (See http://en.wikipedia.org/wiki/Gerber_File) * the .gbr (.pho in legacy files) extension is the default used in Pcbnew * However there are a lot of other extensions used for gerber files * Because the first letter is usually g, we accept g* as extension * (Mainly internal copper layers do not have specific extension, * and filenames are like *.g1, *.g2 *.gb1 ...). * Now (2014) Ucamco (the company which manages the Gerber format) encourages * use of .gbr only and the Gerber X2 file format. */ filetypes = _( "Gerber files (.g* .lgr .pho)" ); filetypes << wxT("|"); filetypes += wxT("*.g*;*.G*;*.pho;*.PHO" ); filetypes << wxT("|"); /* Special gerber filetypes */ filetypes += _( "Top layer (*.GTL)|*.GTL;*.gtl|" ); filetypes += _( "Bottom layer (*.GBL)|*.GBL;*.gbl|" ); filetypes += _( "Bottom solder resist (*.GBS)|*.GBS;*.gbs|" ); filetypes += _( "Top solder resist (*.GTS)|*.GTS;*.gts|" ); filetypes += _( "Bottom overlay (*.GBO)|*.GBO;*.gbo|" ); filetypes += _( "Top overlay (*.GTO)|*.GTO;*.gto|" ); filetypes += _( "Bottom paste (*.GBP)|*.GBP;*.gbp|" ); filetypes += _( "Top paste (*.GTP)|*.GTP;*.gtp|" ); filetypes += _( "Keep-out layer (*.GKO)|*.GKO;*.gko|" ); filetypes += _( "Mechanical layers (*.GMx)|*.GM1;*.gm1;*.GM2;*.gm2;*.GM3;*.gm3|" ); filetypes += _( "Top Pad Master (*.GPT)|*.GPT;*.gpt|" ); filetypes += _( "Bottom Pad Master (*.GPB)|*.GPB;*.gpb|" ); // All filetypes filetypes += AllFilesWildcard; // Use the current working directory if the file name path does not exist. if( filename.DirExists() ) currentPath = filename.GetPath(); else { currentPath = m_mruPath; // On wxWidgets 3.1 (bug?) the path in wxFileDialog is ignored when // finishing by the dir separator. Remove it if any: if( currentPath.EndsWith( '\\' ) || currentPath.EndsWith( '/' ) ) currentPath.RemoveLast(); } wxFileDialog dlg( this, _( "Open Gerber File" ), currentPath, filename.GetFullName(), filetypes, wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE | wxFD_CHANGE_DIR ); if( dlg.ShowModal() == wxID_CANCEL ) return false; dlg.GetPaths( filenamesList ); // @todo Take a closer look at the CWD switching here. The current working directory // gets changed by wxFileDialog because the wxFD_CHANGE_DIR flag is set. Is this the // appropriate behavior? The current working directory is not returned to the previous // value so this may be an issue elsewhere. currentPath = wxGetCwd(); m_mruPath = currentPath; } else { filenamesList.Add( aFullFileName ); currentPath = filename.GetPath(); m_mruPath = currentPath; } // Set the busy cursor wxBusyCursor wait; // Read gerber files: each file is loaded on a new GerbView layer bool success = true; int layer = GetActiveLayer(); // Manage errors when loading files wxString msg; WX_STRING_REPORTER reporter( &msg ); for( unsigned ii = 0; ii < filenamesList.GetCount(); ii++ ) { filename = filenamesList[ii]; if( !filename.IsAbsolute() ) filename.SetPath( currentPath ); m_lastFileName = filename.GetFullPath(); SetActiveLayer( layer, false ); if( Read_GERBER_File( filename.GetFullPath() ) ) { UpdateFileHistory( m_lastFileName ); layer = getNextAvailableLayer( layer ); if( layer == NO_AVAILABLE_LAYERS && ii < filenamesList.GetCount()-1 ) { success = false; reporter.Report( MSG_NO_MORE_LAYER, REPORTER::RPT_ERROR ); // Report the name of not loaded files: ii += 1; while( ii < filenamesList.GetCount() ) { filename = filenamesList[ii++]; wxString txt; txt.Printf( MSG_NOT_LOADED, GetChars( filename.GetFullName() ) ); reporter.Report( txt, REPORTER::RPT_ERROR ); } break; } SetActiveLayer( layer, false ); } } if( !success ) { HTML_MESSAGE_BOX mbox( this, _( "Errors" ) ); mbox.ListSet( msg ); mbox.ShowModal(); } Zoom_Automatique( false ); // Synchronize layers tools with actual active layer: ReFillLayerWidget(); SetActiveLayer( GetActiveLayer() ); m_LayersManager->UpdateLayerIcons(); syncLayerBox(); return success; }
bool PCB_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotkeyCode, const wxPoint& aPosition, EDA_ITEM* aItem ) { if( aHotkeyCode == 0 ) return false; bool itemCurrentlyEdited = GetCurItem() && GetCurItem()->GetFlags(); MODULE* module = NULL; int evt_type = 0; //Used to post a wxCommandEvent on demand PCB_SCREEN* screen = GetScreen(); auto displ_opts = (PCB_DISPLAY_OPTIONS*)GetDisplayOptions(); /* Convert lower to upper case * (the usual toupper function has problem with non ascii codes like function keys */ if( (aHotkeyCode >= 'a') && (aHotkeyCode <= 'z') ) aHotkeyCode += 'A' - 'a'; EDA_HOTKEY* HK_Descr = GetDescriptorFromHotkey( aHotkeyCode, common_Hotkey_List ); if( HK_Descr == NULL ) HK_Descr = GetDescriptorFromHotkey( aHotkeyCode, board_edit_Hotkey_List ); if( HK_Descr == NULL ) return false; int hk_id = HK_Descr->m_Idcommand; // Create a wxCommandEvent that will be posted in some hot keys functions wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED ); cmd.SetEventObject( this ); LAYER_NUM ll; switch( hk_id ) { default: case HK_NOT_FOUND: return false; case HK_LEFT_CLICK: OnLeftClick( aDC, aPosition ); break; case HK_LEFT_DCLICK: // Simulate a double left click: generate 2 events OnLeftClick( aDC, aPosition ); OnLeftDClick( aDC, aPosition ); break; case HK_SWITCH_TRACK_WIDTH_TO_NEXT: if( GetCanvas()->IsMouseCaptured() ) GetCanvas()->CallMouseCapture( aDC, wxDefaultPosition, false ); if( GetDesignSettings().GetTrackWidthIndex() < GetDesignSettings().m_TrackWidthList.size() - 1 ) GetDesignSettings().SetTrackWidthIndex( GetDesignSettings().GetTrackWidthIndex() + 1 ); else GetDesignSettings().SetTrackWidthIndex( 0 ); if( GetCanvas()->IsMouseCaptured() ) GetCanvas()->CallMouseCapture( aDC, wxDefaultPosition, false ); break; case HK_SWITCH_TRACK_WIDTH_TO_PREVIOUS: if( GetCanvas()->IsMouseCaptured() ) GetCanvas()->CallMouseCapture( aDC, wxDefaultPosition, false ); if( GetDesignSettings().GetTrackWidthIndex() <= 0 ) GetDesignSettings().SetTrackWidthIndex( GetDesignSettings().m_TrackWidthList.size() -1 ); else GetDesignSettings().SetTrackWidthIndex( GetDesignSettings().GetTrackWidthIndex() - 1 ); if( GetCanvas()->IsMouseCaptured() ) GetCanvas()->CallMouseCapture( aDC, wxDefaultPosition, false ); break; case HK_SWITCH_GRID_TO_FASTGRID1: SetFastGrid1(); break; case HK_SWITCH_GRID_TO_FASTGRID2: SetFastGrid2(); break; case HK_SWITCH_GRID_TO_NEXT: evt_type = ID_POPUP_GRID_NEXT; break; case HK_SWITCH_GRID_TO_PREVIOUS: evt_type = ID_POPUP_GRID_PREV; break; case HK_SWITCH_LAYER_TO_PREVIOUS: ll = GetActiveLayer(); if( !IsCopperLayer( ll ) ) break; if( ll == F_Cu ) ll = B_Cu; else if( ll == B_Cu ) ll = ToLAYER_ID( GetBoard()->GetCopperLayerCount() - 2 ); else ll = ll - 1; SwitchLayer( aDC, ToLAYER_ID( ll ) ); break; case HK_SWITCH_LAYER_TO_NEXT: ll = GetActiveLayer(); if( !IsCopperLayer( ll ) ) break; if( ll == B_Cu ) ll = F_Cu; else if( ++ll >= GetBoard()->GetCopperLayerCount() - 1 ) ll = B_Cu; SwitchLayer( aDC, ToLAYER_ID( ll ) ); break; case HK_SWITCH_LAYER_TO_COMPONENT: SwitchLayer( aDC, F_Cu ); break; case HK_SWITCH_LAYER_TO_COPPER: SwitchLayer( aDC, B_Cu ); break; case HK_SWITCH_LAYER_TO_INNER1: SwitchLayer( aDC, In1_Cu ); break; case HK_SWITCH_LAYER_TO_INNER2: SwitchLayer( aDC, In2_Cu ); break; case HK_SWITCH_LAYER_TO_INNER3: SwitchLayer( aDC, In3_Cu ); break; case HK_SWITCH_LAYER_TO_INNER4: SwitchLayer( aDC, In4_Cu ); break; case HK_SWITCH_LAYER_TO_INNER5: SwitchLayer( aDC, In5_Cu ); break; case HK_SWITCH_LAYER_TO_INNER6: SwitchLayer( aDC, In6_Cu ); break; case HK_HELP: // Display Current hotkey list DisplayHotkeyList( this, g_Board_Editor_Hotkeys_Descr ); break; case HK_PREFERENCES: evt_type = wxID_PREFERENCES; break; case HK_ZOOM_IN: evt_type = ID_KEY_ZOOM_IN; break; case HK_ZOOM_OUT: evt_type = ID_KEY_ZOOM_OUT; break; case HK_ZOOM_REDRAW: evt_type = ID_ZOOM_REDRAW; break; case HK_ZOOM_AUTO: evt_type = ID_ZOOM_PAGE; break; case HK_ZOOM_CENTER: evt_type = ID_POPUP_ZOOM_CENTER; break; case HK_ZOOM_SELECTION: evt_type = ID_ZOOM_SELECTION; break; case HK_ADD_MODULE: evt_type = ID_PCB_MODULE_BUTT; break; case HK_UNDO: case HK_REDO: if( !itemCurrentlyEdited ) { wxCommandEvent event( wxEVT_COMMAND_TOOL_CLICKED, HK_Descr->m_IdMenuEvent ); wxPostEvent( this, event ); } break; case HK_RESET_LOCAL_COORD: // Set the relative coord GetScreen()->m_O_Curseur = GetCrossHairPosition(); break; case HK_SET_GRID_ORIGIN: PCBNEW_CONTROL::SetGridOrigin( GetGalCanvas()->GetView(), this, new KIGFX::ORIGIN_VIEWITEM( GetGridOrigin(), UR_TRANSIENT ), GetCrossHairPosition() ); m_canvas->Refresh(); break; case HK_RESET_GRID_ORIGIN: PCBNEW_CONTROL::SetGridOrigin( GetGalCanvas()->GetView(), this, new KIGFX::ORIGIN_VIEWITEM( GetGridOrigin(), UR_TRANSIENT ), wxPoint( 0, 0 ) ); m_canvas->Refresh(); break; case HK_SWITCH_UNITS: evt_type = (GetUserUnits() == INCHES) ? ID_TB_OPTIONS_SELECT_UNIT_MM : ID_TB_OPTIONS_SELECT_UNIT_INCH; break; case HK_SWITCH_TRACK_DISPLAY_MODE: displ_opts->m_DisplayPcbTrackFill = !displ_opts->m_DisplayPcbTrackFill; m_canvas->Refresh(); break; case HK_DELETE: OnHotkeyDeleteItem( aDC ); break; case HK_BACK_SPACE: if( IsCopperLayer( GetActiveLayer() ) ) { if( !itemCurrentlyEdited ) { // no track is currently being edited - select a segment and remove it. // @todo: possibly? pass the HK command code to PcbGeneralLocateAndDisplay() // so it can restrict its search to specific item types. BOARD_ITEM * item = PcbGeneralLocateAndDisplay(); // don't let backspace delete modules!! if( item && item->IsTrack() ) { Delete_Segment( aDC, (TRACK*) item ); SetCurItem( NULL ); } OnModify(); } else if( GetCurItem()->IsTrack() ) { // then an element is being edited - remove the last segment. // simple lines for debugger: TRACK* track = (TRACK*) GetCurItem(); track = Delete_Segment( aDC, track ); SetCurItem( track ); OnModify(); } } break; case HK_GET_AND_MOVE_FOOTPRINT: if( !itemCurrentlyEdited ) evt_type = ID_POPUP_PCB_GET_AND_MOVE_MODULE_REQUEST; break; case HK_FIND_ITEM: if( !itemCurrentlyEdited ) evt_type = ID_FIND_ITEMS; break; case HK_OPEN: if( !itemCurrentlyEdited ) evt_type = ID_LOAD_FILE ; break; case HK_SAVE: if( !itemCurrentlyEdited ) evt_type = ID_SAVE_BOARD; break; case HK_ADD_MICROVIA: // Place a micro via if a track is in progress if( GetToolId() != ID_TRACK_BUTT ) return true; if( !itemCurrentlyEdited ) // no track in progress: nothing to do break; if( GetCurItem()->Type() != PCB_TRACE_T ) // Should not occur return true; if( !GetCurItem()->IsNew() ) return true; // place micro via and switch layer if( IsMicroViaAcceptable() ) evt_type = ID_POPUP_PCB_PLACE_MICROVIA; break; case HK_ADD_BLIND_BURIED_VIA: case HK_ADD_THROUGH_VIA: // Switch to alternate layer and Place a via if a track is in progress if( GetBoard()->GetDesignSettings().m_BlindBuriedViaAllowed && hk_id == HK_ADD_BLIND_BURIED_VIA ) GetBoard()->GetDesignSettings().m_CurrentViaType = VIA_BLIND_BURIED; else GetBoard()->GetDesignSettings().m_CurrentViaType = VIA_THROUGH; if( !itemCurrentlyEdited ) // no track in progress: switch layer only { Other_Layer_Route( NULL, aDC ); if( displ_opts->m_ContrastModeDisplay ) m_canvas->Refresh(); break; } if( GetToolId() != ID_TRACK_BUTT ) return true; if( GetCurItem()->Type() != PCB_TRACE_T ) return true; if( !GetCurItem()->IsNew() ) return true; evt_type = hk_id == HK_ADD_BLIND_BURIED_VIA ? ID_POPUP_PCB_PLACE_BLIND_BURIED_VIA : ID_POPUP_PCB_PLACE_THROUGH_VIA; break; case HK_SEL_LAYER_AND_ADD_THROUGH_VIA: case HK_SEL_LAYER_AND_ADD_BLIND_BURIED_VIA: if( GetCurItem() == NULL || !GetCurItem()->IsNew() || GetCurItem()->Type() != PCB_TRACE_T ) break; evt_type = hk_id == HK_SEL_LAYER_AND_ADD_BLIND_BURIED_VIA ? ID_POPUP_PCB_SELECT_CU_LAYER_AND_PLACE_BLIND_BURIED_VIA : ID_POPUP_PCB_SELECT_CU_LAYER_AND_PLACE_THROUGH_VIA; break; case HK_SWITCH_TRACK_POSTURE: /* change the position of initial segment when creating new tracks * switch from _/ to -\ . */ evt_type = ID_POPUP_PCB_SWITCH_TRACK_POSTURE ; break; case HK_DRAG_TRACK_KEEP_SLOPE: OnHotkeyMoveItem( HK_DRAG_TRACK_KEEP_SLOPE ); break; case HK_PLACE_ITEM: OnHotkeyPlaceItem( aDC ); break; case HK_ADD_NEW_TRACK: // Start new track, if possible OnHotkeyBeginRoute( aDC ); break; case HK_EDIT_ITEM: // Edit board item OnHotkeyEditItem( HK_EDIT_ITEM ); break; case HK_EDIT_MODULE_WITH_MODEDIT: // Edit module with module editor OnHotkeyEditItem( HK_EDIT_MODULE_WITH_MODEDIT ); break; case HK_LOCK_UNLOCK_FOOTPRINT: // toggle module "MODULE_is_LOCKED" status: // get any module, locked or not locked and toggle its locked status if( !itemCurrentlyEdited ) { wxPoint pos = RefPos( true ); module = GetBoard()->GetFootprint( pos, screen->m_Active_Layer, true ); } else if( GetCurItem()->Type() == PCB_MODULE_T ) { module = (MODULE*) GetCurItem(); } if( module ) { SetCurItem( module ); module->SetLocked( !module->IsLocked() ); OnModify(); SetMsgPanel( module ); } break; case HK_DRAG_ITEM: // Start drag module or track segment OnHotkeyMoveItem( HK_DRAG_ITEM ); break; case HK_MOVE_ITEM: // Start move item OnHotkeyMoveItem( HK_MOVE_ITEM ); break; case HK_COPY_ITEM: evt_type = OnHotkeyCopyItem(); break; case HK_ROTATE_ITEM: // Rotation OnHotkeyRotateItem( HK_ROTATE_ITEM ); break; case HK_FLIP_ITEM: OnHotkeyFlipItem( HK_FLIP_ITEM ); break; case HK_MOVE_ITEM_EXACT: case HK_DUPLICATE_ITEM: case HK_DUPLICATE_ITEM_AND_INCREMENT: case HK_CREATE_ARRAY: OnHotkeyDuplicateOrArrayItem( HK_Descr->m_Idcommand ); break; case HK_SWITCH_HIGHCONTRAST_MODE: // switch to high contrast mode and refresh the canvas displ_opts->m_ContrastModeDisplay = !displ_opts->m_ContrastModeDisplay; m_canvas->Refresh(); break; case HK_CANVAS_CAIRO: evt_type = ID_MENU_CANVAS_CAIRO; break; case HK_CANVAS_OPENGL: evt_type = ID_MENU_CANVAS_OPENGL; break; case HK_CANVAS_LEGACY: evt_type = ID_MENU_CANVAS_LEGACY; break; case HK_ZONE_FILL_OR_REFILL: evt_type = ID_POPUP_PCB_FILL_ALL_ZONES; break; case HK_ZONE_REMOVE_FILLED: evt_type = ID_POPUP_PCB_REMOVE_FILLED_AREAS_IN_ALL_ZONES; break; } if( evt_type != 0 ) { wxCommandEvent evt( wxEVT_COMMAND_MENU_SELECTED ); evt.SetEventObject( this ); evt.SetId( evt_type ); GetEventHandler()->ProcessEvent( evt ); } return true; }
bool PCB_EDIT_FRAME::OnHotkeyDeleteItem( wxDC* aDC ) { BOARD_ITEM* item = GetCurItem(); bool ItemFree = (item == NULL) || (item->GetFlags() == 0); switch( GetToolId() ) { case ID_TRACK_BUTT: if( !IsCopperLayer ( GetActiveLayer() ) ) return false; if( ItemFree ) { item = PcbGeneralLocateAndDisplay(); if( item && !item->IsTrack() ) return false; Delete_Track( aDC, (TRACK*) item ); } else if( item->IsTrack( ) ) { // simple lines for debugger: TRACK* track = (TRACK*) item; track = Delete_Segment( aDC, track ); SetCurItem( track ); OnModify(); return true; } break; case ID_PCB_MODULE_BUTT: if( ItemFree ) { wxPoint pos = RefPos( false ); MODULE* module = GetBoard()->GetFootprint( pos, UNDEFINED_LAYER, false ); if( module == NULL || module->IsLocked() ) return false; RemoveStruct( module, aDC ); } else return false; break; default: if( ItemFree ) { item = PcbGeneralLocateAndDisplay(); // Shouldn't there be a check for locked tracks and vias here? if( item == NULL || (item->Type() == PCB_MODULE_T && (MODULE*)item->IsLocked()) ) return false; RemoveStruct( item, aDC ); } else return false; } OnModify(); SetCurItem( NULL ); return true; }
void PCB_EDIT_FRAME::OnUpdateLayerSelectBox( wxUpdateUIEvent& aEvent ) { m_SelLayerBox->SetLayerSelection( GetActiveLayer() ); }
void PCB_EDIT_FRAME::Process_Config( wxCommandEvent& event ) { int id = event.GetId(); wxFileName fn; switch( id ) { case ID_MENU_PCB_SHOW_HIDE_LAYERS_MANAGER_DIALOG: m_show_layer_manager_tools = ! m_show_layer_manager_tools; m_auimgr.GetPane( wxT( "m_LayersManagerToolBar" ) ).Show( m_show_layer_manager_tools ); m_auimgr.Update(); GetMenuBar()->SetLabel( ID_MENU_PCB_SHOW_HIDE_LAYERS_MANAGER_DIALOG, m_show_layer_manager_tools ? _("Hide &Layers Manager" ) : _("Show &Layers Manager" )); break; case ID_MENU_PCB_SHOW_HIDE_MUWAVE_TOOLBAR: m_show_microwave_tools = ! m_show_microwave_tools; m_auimgr.GetPane( wxT( "m_microWaveToolBar" ) ).Show( m_show_microwave_tools ); m_auimgr.Update(); GetMenuBar()->SetLabel( ID_MENU_PCB_SHOW_HIDE_MUWAVE_TOOLBAR, m_show_microwave_tools ? _( "Hide Microwave Toolbar" ): _( "Show Microwave Toolbar" )); break; case ID_PCB_LAYERS_SETUP: if( InvokeLayerSetup( this, GetBoard() ) ) { LAYER_ID cur_layer = GetActiveLayer(); // If after showing the dialog the user has removed the active layer, // then select a new active layer (front copper layer). if( !GetBoard()->GetEnabledLayers()[ cur_layer ] ) cur_layer = F_Cu; SetActiveLayer( cur_layer ); OnModify(); ReCreateLayerBox(); ReFillLayerWidget(); if( IsGalCanvasActive() ) static_cast<PCB_DRAW_PANEL_GAL*>( GetGalCanvas() )->SyncLayersVisibility( GetBoard() ); } break; case ID_PCB_LIB_WIZARD: case ID_PCB_LIB_TABLE_EDIT: { bool tableChanged = false; int r = 0; if( id == ID_PCB_LIB_TABLE_EDIT ) r = InvokePcbLibTableEditor( this, &GFootprintTable, Prj().PcbFootprintLibs() ); else r = InvokeFootprintWizard( this, &GFootprintTable, Prj().PcbFootprintLibs() ); if( r & 1 ) { try { FILE_OUTPUTFORMATTER sf( FP_LIB_TABLE::GetGlobalTableFileName() ); GFootprintTable.Format( &sf, 0 ); tableChanged = true; } catch( const IO_ERROR& ioe ) { wxString msg = wxString::Format( _( "Error occurred saving the global footprint library " "table:\n\n%s" ), GetChars( ioe.errorText.GetData() ) ); wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR ); } } // If no board file is defined, do not save the project specific library table. It // is kept in memory and created in the path when the new board is saved. if( (r & 2) && !GetBoard()->GetFileName().IsEmpty() ) { wxString tblName = Prj().FootprintLibTblName(); try { Prj().PcbFootprintLibs()->Save( tblName ); tableChanged = true; } catch( const IO_ERROR& ioe ) { wxString msg = wxString::Format( _( "Error occurred saving project specific footprint library " "table:\n\n%s" ), GetChars( ioe.errorText ) ); wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR ); } } FOOTPRINT_VIEWER_FRAME* viewer; if( tableChanged && (viewer = (FOOTPRINT_VIEWER_FRAME*)Kiway().Player( FRAME_PCB_MODULE_VIEWER, false )) != NULL ) { viewer->ReCreateLibraryList(); } } break; case ID_PCB_3DSHAPELIB_WIZARD: #ifdef BUILD_GITHUB_PLUGIN Invoke3DShapeLibsDownloaderWizard( this ); #endif break; case ID_PCB_MASK_CLEARANCE: { DIALOG_PADS_MASK_CLEARANCE dlg( this ); if( dlg.ShowModal() == 1 && IsGalCanvasActive() ) { for( MODULE* module = GetBoard()->m_Modules; module; module = module->Next() ) module->ViewUpdate(); GetGalCanvas()->Refresh(); } } break; case wxID_PREFERENCES: { DIALOG_GENERALOPTIONS dlg( this ); dlg.ShowModal(); } break; case ID_PCB_PAD_SETUP: InstallPadOptionsFrame( NULL ); break; case ID_CONFIG_SAVE: SaveProjectSettings( true ); break; case ID_CONFIG_READ: { fn = GetBoard()->GetFileName(); fn.SetExt( ProjectFileExtension ); wxFileDialog dlg( this, _( "Read Project File" ), fn.GetPath(), fn.GetFullName(), ProjectFileWildcard, wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_CHANGE_DIR ); if( dlg.ShowModal() == wxID_CANCEL ) break; if( !wxFileExists( dlg.GetPath() ) ) { wxString msg = wxString::Format( _( "File %s not found" ), GetChars( dlg.GetPath() ) ); DisplayError( this, msg ); break; } wxString pro_file = dlg.GetPath(); Prj().ConfigLoad( Kiface().KifaceSearch(), GROUP_PCB, GetProjectFileParameters(), pro_file ); } break; // Hotkey IDs case ID_PREFERENCES_HOTKEY_EXPORT_CONFIG: ExportHotkeyConfigToFile( g_Board_Editor_Hokeys_Descr, wxT( "pcbnew" ) ); break; case ID_PREFERENCES_HOTKEY_IMPORT_CONFIG: ImportHotkeyConfigFromFile( g_Board_Editor_Hokeys_Descr, wxT( "pcbnew" ) ); break; case ID_PREFERENCES_HOTKEY_SHOW_EDITOR: InstallHotkeyFrame( this, g_Board_Editor_Hokeys_Descr ); break; case ID_PREFERENCES_HOTKEY_SHOW_CURRENT_LIST: // Display current hotkey list for Pcbnew. DisplayHotkeyList( this, g_Board_Editor_Hokeys_Descr ); break; default: DisplayError( this, wxT( "PCB_EDIT_FRAME::Process_Config error" ) ); } }
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; }
bool GERBVIEW_FRAME::Read_EXCELLON_File( const wxString& aFullFileName ) { wxString msg; int layerId = GetActiveLayer(); // current layer used in GerbView GERBER_FILE_IMAGE_LIST* images = GetGerberLayout()->GetImagesList(); auto gerber_layer = images->GetGbrImage( layerId ); auto drill_layer = dynamic_cast<EXCELLON_IMAGE*>( gerber_layer ); if( gerber_layer && !drill_layer ) { // The active layer contains old gerber data we have to clear Erase_Current_DrawLayer( false ); } if( drill_layer == nullptr ) { drill_layer = new EXCELLON_IMAGE( layerId ); layerId = images->AddGbrImage( drill_layer, layerId ); } if( layerId < 0 ) { DisplayError( this, _( "No room to load file" ) ); return false; } // Read the Excellon drill file: bool success = drill_layer->LoadFile( aFullFileName ); if( !success ) { msg.Printf( _( "File %s not found" ), GetChars( aFullFileName ) ); DisplayError( this, msg ); return false; } // Display errors list if( drill_layer->GetMessages().size() > 0 ) { HTML_MESSAGE_BOX dlg( this, _( "Error reading EXCELLON drill file" ) ); dlg.ListSet( drill_layer->GetMessages() ); dlg.ShowModal(); } if( success ) { EDA_DRAW_PANEL_GAL* canvas = GetGalCanvas(); if( canvas ) { KIGFX::VIEW* view = canvas->GetView(); for( GERBER_DRAW_ITEM* item = drill_layer->GetItemsList(); item; item = item->Next() ) { view->Add( (KIGFX::VIEW_ITEM*) item ); } } } return success; }
TRACK* PCB_EDIT_FRAME::Delete_Segment( wxDC* DC, TRACK* aTrack ) { int current_net_code; if( aTrack == NULL ) return NULL; if( aTrack->IsNew() ) // Trace in progress, erase the last segment { if( g_CurrentTrackList.GetCount() > 0 ) { LAYER_NUM previous_layer = GetActiveLayer(); DBG( g_CurrentTrackList.VerifyListIntegrity(); ) // Delete the current trace ShowNewTrackWhenMovingCursor( m_canvas, DC, wxDefaultPosition, false ); // delete the most recently entered delete g_CurrentTrackList.PopBack(); if( g_TwoSegmentTrackBuild ) { // if in 2 track mode, and the next most recent is a segment // not a via, and the one previous to that is a via, then // delete up to the via. if( g_CurrentTrackList.GetCount() >= 2 && g_CurrentTrackSegment->Type() != PCB_VIA_T && g_CurrentTrackSegment->Back()->Type() == PCB_VIA_T ) { delete g_CurrentTrackList.PopBack(); } } while( g_CurrentTrackSegment && g_CurrentTrackSegment->Type() == PCB_VIA_T ) { delete g_CurrentTrackList.PopBack(); if( g_CurrentTrackSegment && g_CurrentTrackSegment->Type() != PCB_VIA_T ) previous_layer = g_CurrentTrackSegment->GetLayer(); } // Correct active layer which could change if a via // has been erased SetActiveLayer( previous_layer ); UpdateStatusBar(); if( g_TwoSegmentTrackBuild ) // We must have 2 segments or more, or 0 { if( g_CurrentTrackList.GetCount() == 1 && g_CurrentTrackSegment->Type() != PCB_VIA_T ) { delete g_CurrentTrackList.PopBack(); } } if( g_CurrentTrackList.GetCount() == 0 ) { m_canvas->SetMouseCapture( NULL, NULL ); if( GetBoard()->IsHighLightNetON() ) HighLight( DC ); SetCurItem( NULL ); return NULL; } else { if( m_canvas->IsMouseCaptured() ) m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); return g_CurrentTrackSegment; } }
bool GERBVIEW_FRAME::unarchiveFiles( const wxString& aFullFileName, REPORTER* aReporter ) { wxString msg; // Extract the path of aFullFileName. We use it to store temporary files wxFileName fn( aFullFileName ); wxString unzipDir = fn.GetPath(); wxFFileInputStream zipFile( aFullFileName ); if( !zipFile.IsOk() ) { if( aReporter ) { msg.Printf( _( "Zip file \"%s\" cannot be opened" ), GetChars( aFullFileName ) ); aReporter->Report( msg, REPORTER::RPT_ERROR ); } return false; } // Update the list of recent zip files. UpdateFileHistory( aFullFileName, &m_zipFileHistory ); // The unzipped file in only a temporary file. Give it a filename // which cannot conflict with an usual filename. // TODO: make Read_GERBER_File() and Read_EXCELLON_File() able to // accept a stream, and avoid using a temp file. wxFileName temp_fn( "$tempfile.tmp" ); temp_fn.MakeAbsolute( unzipDir ); wxString unzipped_tempfile = temp_fn.GetFullPath(); bool success = true; wxZipInputStream zipArchive( zipFile ); wxZipEntry* entry; bool reported_no_more_layer = false; while( ( entry = zipArchive.GetNextEntry() ) ) { wxString fname = entry->GetName(); wxFileName uzfn = fname; wxString curr_ext = uzfn.GetExt().Lower(); // The archive contains Gerber and/or Excellon drill files. Use the right loader. // However it can contain a few other files (reports, pdf files...), // which will be skipped. // Gerber files ext is usually "gbr", but can be also an other value, starting by "g" // old gerber files ext from kicad is .pho // drill files do not have a well defined ext // It is .drl in kicad, but .txt in Altium for instance // Allows only .drl for drill files. if( curr_ext[0] != 'g' && curr_ext != "pho" && curr_ext != "drl" ) { if( aReporter ) { msg.Printf( _( "Info: skip file <i>\"%s\"</i> (unknown type)\n" ), GetChars( entry->GetName() ) ); aReporter->Report( msg, REPORTER::RPT_WARNING ); } continue; } int layer = GetActiveLayer(); if( layer == NO_AVAILABLE_LAYERS ) { success = false; if( aReporter ) { if( !reported_no_more_layer ) aReporter->Report( MSG_NO_MORE_LAYER, REPORTER::RPT_ERROR ); reported_no_more_layer = true; // Report the name of not loaded files: msg.Printf( MSG_NOT_LOADED, GetChars( entry->GetName() ) ); aReporter->Report( msg, REPORTER::RPT_ERROR ); } delete entry; continue; } // Create the unzipped temporary file: { wxFFileOutputStream temporary_ofile( unzipped_tempfile ); if( temporary_ofile.Ok() ) temporary_ofile.Write( zipArchive ); else { success = false; if( aReporter ) { msg.Printf( _( "<b>Unable to create temporary file \"%s\"</b>\n"), GetChars( unzipped_tempfile ) ); aReporter->Report( msg, REPORTER::RPT_ERROR ); } } } bool read_ok = true; if( curr_ext[0] == 'g' || curr_ext == "pho" ) { // Read gerber files: each file is loaded on a new GerbView layer read_ok = Read_GERBER_File( unzipped_tempfile ); } else // if( curr_ext == "drl" ) { read_ok = Read_EXCELLON_File( unzipped_tempfile ); } delete entry; // The unzipped file is only a temporary file, delete it. wxRemoveFile( unzipped_tempfile ); if( !read_ok ) { success = false; if( aReporter ) { msg.Printf( _("<b>unzipped file %s read error</b>\n"), GetChars( unzipped_tempfile ) ); aReporter->Report( msg, REPORTER::RPT_ERROR ); } } else { GERBER_FILE_IMAGE* gerber_image = GetGbrImage( layer ); if( gerber_image ) gerber_image->m_FileName = fname; layer = getNextAvailableLayer( layer ); SetActiveLayer( layer, false ); } } return success; }
bool GERBVIEW_FRAME::LoadExcellonFiles( const wxString& aFullFileName ) { wxString filetypes; wxArrayString filenamesList; wxFileName filename = aFullFileName; wxString currentPath; if( !filename.IsOk() ) { filetypes = DrillFileWildcard(); filetypes << wxT( "|" ); /* All filetypes */ filetypes += wxGetTranslation( AllFilesWildcard ); /* Use the current working directory if the file name path does not exist. */ if( filename.DirExists() ) currentPath = filename.GetPath(); else currentPath = m_mruPath; wxFileDialog dlg( this, _( "Open Drill File" ), currentPath, filename.GetFullName(), filetypes, wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE | wxFD_CHANGE_DIR ); if( dlg.ShowModal() == wxID_CANCEL ) return false; dlg.GetPaths( filenamesList ); currentPath = wxGetCwd(); m_mruPath = currentPath; } else { filenamesList.Add( aFullFileName ); currentPath = filename.GetPath(); m_mruPath = currentPath; } // Read Excellon drill files: each file is loaded on a new GerbView layer bool success = true; int layer = GetActiveLayer(); // Manage errors when loading files wxString msg; WX_STRING_REPORTER reporter( &msg ); for( unsigned ii = 0; ii < filenamesList.GetCount(); ii++ ) { filename = filenamesList[ii]; if( !filename.IsAbsolute() ) filename.SetPath( currentPath ); m_lastFileName = filename.GetFullPath(); SetActiveLayer( layer, false ); if( Read_EXCELLON_File( filename.GetFullPath() ) ) { // Update the list of recent drill files. UpdateFileHistory( filename.GetFullPath(), &m_drillFileHistory ); layer = getNextAvailableLayer( layer ); if( layer == NO_AVAILABLE_LAYERS && ii < filenamesList.GetCount()-1 ) { success = false; reporter.Report( MSG_NO_MORE_LAYER, REPORTER::RPT_ERROR ); // Report the name of not loaded files: ii += 1; while( ii < filenamesList.GetCount() ) { filename = filenamesList[ii++]; wxString txt; txt.Printf( MSG_NOT_LOADED, GetChars( filename.GetFullName() ) ); reporter.Report( txt, REPORTER::RPT_ERROR ); } break; } SetActiveLayer( layer, false ); } } if( !success ) { HTML_MESSAGE_BOX mbox( this, _( "Errors" ) ); mbox.ListSet( msg ); mbox.ShowModal(); } Zoom_Automatique( false ); // Synchronize layers tools with actual active layer: ReFillLayerWidget(); SetActiveLayer( GetActiveLayer() ); m_LayersManager->UpdateLayerIcons(); syncLayerBox(); return success; }
EDGE_MODULE* FOOTPRINT_EDIT_FRAME::Begin_Edge_Module( EDGE_MODULE* aEdge, wxDC* DC, STROKE_T type_edge ) { MODULE* module = GetBoard()->m_Modules; if( module == NULL ) return NULL; if( aEdge == NULL ) // Start a new edge item { SaveCopyInUndoList( module, UR_CHANGED ); aEdge = new EDGE_MODULE( module ); MoveVector.x = MoveVector.y = 0; // Add the new item to the Drawings list head module->GraphicalItemsList().PushFront( aEdge ); // Update characteristics of the segment or arc. aEdge->SetFlags( IS_NEW ); aEdge->SetAngle( 0 ); aEdge->SetShape( type_edge ); if( aEdge->GetShape() == S_ARC ) aEdge->SetAngle( ArcValue ); aEdge->SetWidth( GetDesignSettings().GetLineThickness( GetActiveLayer() ) ); aEdge->SetLayer( GetActiveLayer() ); // Initialize the starting point of the new segment or arc aEdge->SetStart( GetCrossHairPosition() ); // Initialize the ending point of the new segment or arc aEdge->SetEnd( aEdge->GetStart() ); // Initialize the relative coordinates aEdge->SetStart0( aEdge->GetStart() - module->GetPosition() ); RotatePoint( &aEdge->m_Start0, -module->GetOrientation() ); aEdge->m_End0 = aEdge->m_Start0; module->CalculateBoundingBox(); m_canvas->SetMouseCapture( ShowNewEdgeModule, Abort_Move_ModuleOutline ); } /* Segment creation in progress. * The ending coordinate is updated by the function * ShowNewEdgeModule() called on move mouse event * during the segment creation */ else { if( type_edge == S_SEGMENT ) { if( aEdge->m_Start0 != aEdge->m_End0 ) { aEdge->Draw( m_canvas, DC, GR_OR ); EDGE_MODULE* newedge = new EDGE_MODULE( *aEdge ); // insert _after_ aEdge, which is the same as inserting before aEdge->Next() module->GraphicalItemsList().Insert( newedge, aEdge->Next() ); aEdge->ClearFlags(); aEdge = newedge; // point now new item aEdge->SetFlags( IS_NEW ); aEdge->SetWidth( GetDesignSettings().GetLineThickness( aEdge->GetLayer() ) ); aEdge->SetStart( GetCrossHairPosition() ); aEdge->SetEnd( aEdge->GetStart() ); // Update relative coordinate. aEdge->SetStart0( aEdge->GetStart() - module->GetPosition() ); wxPoint pt( aEdge->GetStart0() ); RotatePoint( &pt, -module->GetOrientation() ); aEdge->SetStart0( pt ); aEdge->SetEnd0( aEdge->GetStart0() ); module->CalculateBoundingBox(); module->SetLastEditTime(); OnModify(); } } else { wxLogDebug( wxT( "Begin_Edge() error" ) ); } } return aEdge; }