From bd99012ad0a26cbffc9aa47f02ee7d61c5a3b1b6 Mon Sep 17 00:00:00 2001 From: Wayne Stambaugh Date: Wed, 2 Mar 2011 10:24:39 -0500 Subject: [PATCH] Fix load gerber file path bug, fixes lp:712104. --- gerbview/files.cpp | 44 +++++---- gerbview/gerberframe.cpp | 21 +++++ gerbview/wxGerberFrame.h | 190 ++++++++++++++++++++------------------- 3 files changed, 150 insertions(+), 105 deletions(-) diff --git a/gerbview/files.cpp b/gerbview/files.cpp index 4fc9bd206a..45513a71ba 100644 --- a/gerbview/files.cpp +++ b/gerbview/files.cpp @@ -39,19 +39,19 @@ void WinEDA_GerberFrame::Files_io( wxCommandEvent& event ) switch( id ) { case wxID_FILE: - { Erase_Current_Layer( false ); LoadGerberFiles( wxEmptyString ); break; - } case ID_MENU_INC_LAYER_AND_APPEND_FILE: case ID_INC_LAYER_AND_APPEND_FILE: { - int origLayer = getActiveLayer(); - if( origLayer < NB_LAYERS ) + int origLayer = getNextAvailableLayer(); + + if( origLayer != NO_AVAILABLE_LAYERS ) { - setActiveLayer(origLayer+1); + setActiveLayer( origLayer ); + Erase_Current_Layer( false ); if( !LoadGerberFiles( wxEmptyString ) ) @@ -61,7 +61,7 @@ void WinEDA_GerberFrame::Files_io( wxCommandEvent& event ) { wxString msg; msg.Printf( _( "GerbView only supports a maximum of %d layers. You must first \ -delete an existing layer to load any new layers." ), NB_LAYERS ); +clear an existing layer to load any new layers." ), NB_LAYERS ); wxMessageBox( msg ); } } @@ -96,7 +96,7 @@ bool WinEDA_GerberFrame::LoadGerberFiles( const wxString& aFullFileName ) wxFileName filename = aFullFileName; wxString currentPath; - if( ! filename.IsOk() ) + if( !filename.IsOk() ) { /* Standard gerber filetypes * (See http://en.wikipedia.org/wiki/Gerber_File) @@ -144,7 +144,7 @@ bool WinEDA_GerberFrame::LoadGerberFiles( const wxString& aFullFileName ) if( dlg.ShowModal() == wxID_CANCEL ) return false; - dlg.GetFilenames( filenamesList ); + dlg.GetPaths( filenamesList ); currentPath = wxGetCwd(); } else @@ -160,18 +160,32 @@ bool WinEDA_GerberFrame::LoadGerberFiles( const wxString& aFullFileName ) for( unsigned ii = 0; ii < filenamesList.GetCount(); ii++ ) { wxFileName filename = filenamesList[ii]; - filename.SetPath( currentPath ); + + if( !filename.IsAbsolute() ) + filename.SetPath( currentPath ); + + if( !filename.HasExt() ) + filename.SetExt( g_PenFilenameExt ); + GetScreen()->SetFileName( filename.GetFullPath() ); - filename.SetExt( g_PenFilenameExt ); setActiveLayer( layer, false ); - if( Read_GERBER_File( GetScreen()->GetFileName(), filename.GetFullPath() ) ) + if( Read_GERBER_File( filename.GetFullPath(), filename.GetFullPath() ) ) { SetLastProject( GetScreen()->GetFileName() ); - layer++; - if( layer >= NB_LAYERS ) - layer = 0; + + layer = getNextAvailableLayer( layer ); + + if( layer == NO_AVAILABLE_LAYERS ) + { + wxString msg = wxT( "No more empty layers are available. The remaining gerber " ); + msg += wxT( "files will not be loaded." ); + wxMessageBox( msg ); + break; + } + + setActiveLayer( layer, false ); } } @@ -179,7 +193,7 @@ bool WinEDA_GerberFrame::LoadGerberFiles( const wxString& aFullFileName ) g_SaveTime = time( NULL ); // Synchronize layers tools with actual active layer: - setActiveLayer(getActiveLayer()); + setActiveLayer( getActiveLayer() ); syncLayerBox(); return true; diff --git a/gerbview/gerberframe.cpp b/gerbview/gerberframe.cpp index eefe5a53be..d763c211c8 100644 --- a/gerbview/gerberframe.cpp +++ b/gerbview/gerberframe.cpp @@ -404,6 +404,27 @@ void WinEDA_GerberFrame::SetElementVisibility( int aGERBER_VISIBLE, bool aNewSta } +int WinEDA_GerberFrame::getNextAvailableLayer( int aLayer ) const +{ + int layer = aLayer; + + for( int i = 0; i < NB_LAYERS; i++ ) + { + GERBER_IMAGE* gerber = g_GERBER_List[ layer ]; + + if( gerber == NULL || gerber->m_FileName.IsEmpty() ) + return layer; + + layer++; + + if( layer >= NB_LAYERS ) + layer = 0; + } + + return NO_AVAILABLE_LAYERS; +} + + void WinEDA_GerberFrame::syncLayerWidget() { m_LayersManager->SelectLayer( getActiveLayer() ); diff --git a/gerbview/wxGerberFrame.h b/gerbview/wxGerberFrame.h index f281dab2c0..6ce8c8d074 100644 --- a/gerbview/wxGerberFrame.h +++ b/gerbview/wxGerberFrame.h @@ -10,6 +10,10 @@ #include "class_gerbview_layer_widget.h" #include "class_layerchoicebox.h" + +#define NO_AVAILABLE_LAYERS -1 + + /** * Command IDs for the gerber file viewer. * @@ -33,9 +37,10 @@ enum id_gerbview_frm { class DCODE_SELECTION_BOX; + /****************************************************************** -* class WinEDA_GerberFrame: this is the main window used in gerbview -******************************************************************/ + * class WinEDA_GerberFrame: this is the main window used in gerbview + ******************************************************************/ class WinEDA_GerberFrame : public PCB_BASE_FRAME { @@ -53,16 +58,17 @@ public: private: int m_displayMode; // Gerber images ("layers" in Gerbview) can be drawn: - // - in fast mode (write mode) but if there are negative items - // only the last image is correctly drawn - // (no problem to see only one image or when no negative items) + // - in fast mode (write mode) but if there are negative + // items only the last image is correctly drawn (no + // problem to see only one image or when no negative items) // - in "exact" mode (but slower) in write mode: // last image covers previous images // - in "exact" mode (also slower) in OR mode // (transparency mode) // m_displayMode = 0, 1 or 2 bool m_show_layer_manager_tools; - wxArrayString m_Messages; // An array sting to store warning messages when reaging a gerber file + wxArrayString m_Messages; // An array sting to store warning messages when reaging + // a gerber file public: WinEDA_GerberFrame( wxWindow* father, const wxString& title, const wxPoint& pos, const wxSize& size, @@ -130,7 +136,7 @@ public: WinEDA_GerberFrame( wxWindow* father, const wxString& title, * Function GetGridColor() , virtual * @return the color of the grid */ - virtual int GetGridColor(); + virtual int GetGridColor(); /** * Function SetGridColor() , virtual @@ -198,6 +204,17 @@ public: WinEDA_GerberFrame( wxWindow* father, const wxString& title, } + /** + * Function getNextAvailableLayer + * finds the next empty layer starting at \a aLayer and returns it to the caller. If no + * empty layers are found, NO_AVAILABLE_LAYERS is return. + * @param aLayer The first layer to search. + * @return The first empty layer found or NO_AVAILABLE_LAYERS. + */ + int getNextAvailableLayer( int aLayer = 0 ) const; + + bool hasAvailableLayers() const { return getNextAvailableLayer() != NO_AVAILABLE_LAYERS; } + /** * Function syncLayerWidget * updates the currently "selected" layer within the PCB_LAYER_WIDGET. @@ -206,7 +223,7 @@ public: WinEDA_GerberFrame( wxWindow* father, const wxString& title, * This function cannot be inline without including layer_widget.h in * here and we do not want to do that. */ - void syncLayerWidget(); + void syncLayerWidget(); /** * Function syncLayerBox @@ -214,7 +231,7 @@ public: WinEDA_GerberFrame( wxWindow* father, const wxString& title, * The currently active layer, as defined by the return value of * getActiveLayer(). And updates the colored icon in the toolbar. */ - void syncLayerBox(); + void syncLayerBox(); /** * Function UpdateTitleAndInfo @@ -225,7 +242,7 @@ public: WinEDA_GerberFrame( wxWindow* father, const wxString& title, * Name of the Image (found in the gerber file: IN <name> command) in the status bar * and other data in toolbar */ - void UpdateTitleAndInfo(); + void UpdateTitleAndInfo(); /** * Load applications settings specific to the PCBNew. @@ -236,7 +253,7 @@ public: WinEDA_GerberFrame( wxWindow* father, const wxString& title, * drawing frames. Please put your application settings for PCBNew here * to avoid having application settings loaded all over the place. */ - virtual void LoadSettings(); + virtual void LoadSettings(); /** * Save applications settings common to PCB draw frame objects. @@ -247,25 +264,25 @@ public: WinEDA_GerberFrame( wxWindow* father, const wxString& title, * drawing frames. Please put your application settings for PCBNew here * to avoid having application settings saved all over the place. */ - virtual void SaveSettings(); + virtual void SaveSettings(); /** * Function SetLanguage * called on a language menu selection */ - virtual void SetLanguage( wxCommandEvent& event ); + virtual void SetLanguage( wxCommandEvent& event ); - void Process_Special_Functions( wxCommandEvent& event ); - void RedrawActiveWindow( wxDC* DC, bool EraseBg ); - void ReCreateHToolbar(); - void ReCreateVToolbar(); - void ReCreateOptToolbar(); - void ReCreateMenuBar(); - void OnLeftClick( wxDC* DC, const wxPoint& MousePos ); - void OnLeftDClick( wxDC* DC, const wxPoint& MousePos ); - bool OnRightClick( const wxPoint& MousePos, wxMenu* PopMenu ); - int BestZoom(); - void OnSelectOptionToolbar( wxCommandEvent& event ); + void Process_Special_Functions( wxCommandEvent& event ); + void RedrawActiveWindow( wxDC* DC, bool EraseBg ); + void ReCreateHToolbar(); + void ReCreateVToolbar(); + void ReCreateOptToolbar(); + void ReCreateMenuBar(); + void OnLeftClick( wxDC* DC, const wxPoint& MousePos ); + void OnLeftDClick( wxDC* DC, const wxPoint& MousePos ); + bool OnRightClick( const wxPoint& MousePos, wxMenu* PopMenu ); + int BestZoom(); + void OnSelectOptionToolbar( wxCommandEvent& event ); /** * Function OnSelectDisplayMode @@ -273,31 +290,31 @@ public: WinEDA_GerberFrame( wxWindow* father, const wxString& title, * Mode selection can be fast display, * or exact mode with stacked images or with transparency */ - void OnSelectDisplayMode( wxCommandEvent& event ); - void OnHotKey( wxDC* DC, int hotkey, EDA_ITEM* DrawStruct ); + void OnSelectDisplayMode( wxCommandEvent& event ); + void OnHotKey( wxDC* DC, int hotkey, EDA_ITEM* DrawStruct ); GERBER_DRAW_ITEM* GerberGeneralLocateAndDisplay(); GERBER_DRAW_ITEM* Locate( const wxPoint& aPosition, int typeloc ); - void Process_Settings( wxCommandEvent& event ); - void Process_Config( wxCommandEvent& event ); - void InstallConfigFrame( const wxPoint& pos ); - void InstallGerberOptionsDialog( wxCommandEvent& event ); - void InstallPcbGlobalDeleteFrame( const wxPoint& pos ); + void Process_Settings( wxCommandEvent& event ); + void Process_Config( wxCommandEvent& event ); + void InstallConfigFrame( const wxPoint& pos ); + void InstallGerberOptionsDialog( wxCommandEvent& event ); + void InstallPcbGlobalDeleteFrame( const wxPoint& pos ); - void OnUpdateDrawMode( wxUpdateUIEvent& aEvent ); - void OnUpdateFlashedItemsDrawMode( wxUpdateUIEvent& aEvent ); - void OnUpdateLinesDrawMode( wxUpdateUIEvent& aEvent ); - void OnUpdatePolygonsDrawMode( wxUpdateUIEvent& aEvent ); - void OnUpdateShowDCodes( wxUpdateUIEvent& aEvent ); - void OnUpdateShowLayerManager( wxUpdateUIEvent& aEvent ); - void OnUpdateSelectDCode( wxUpdateUIEvent& aEvent ); - void OnUpdateLayerSelectBox( wxUpdateUIEvent& aEvent ); + void OnUpdateDrawMode( wxUpdateUIEvent& aEvent ); + void OnUpdateFlashedItemsDrawMode( wxUpdateUIEvent& aEvent ); + void OnUpdateLinesDrawMode( wxUpdateUIEvent& aEvent ); + void OnUpdatePolygonsDrawMode( wxUpdateUIEvent& aEvent ); + void OnUpdateShowDCodes( wxUpdateUIEvent& aEvent ); + void OnUpdateShowLayerManager( wxUpdateUIEvent& aEvent ); + void OnUpdateSelectDCode( wxUpdateUIEvent& aEvent ); + void OnUpdateLayerSelectBox( wxUpdateUIEvent& aEvent ); /* handlers for block commands */ - virtual int ReturnBlockCommand( int key ); - virtual void HandleBlockPlace( wxDC* DC ); - virtual bool HandleBlockEnd( wxDC* DC ); + virtual int ReturnBlockCommand( int key ); + virtual void HandleBlockPlace( wxDC* DC ); + virtual bool HandleBlockEnd( wxDC* DC ); /* Block operations: */ @@ -308,7 +325,7 @@ public: WinEDA_GerberFrame( wxWindow* father, const wxString& title, * * @param DC A device context to draw on. */ - void Block_Delete( wxDC* DC ); + void Block_Delete( wxDC* DC ); /** * Function Block_Move @@ -319,7 +336,7 @@ public: WinEDA_GerberFrame( wxWindow* father, const wxString& title, * * @param DC A device context to draw on. */ - void Block_Move( wxDC* DC ); + void Block_Move( wxDC* DC ); /** * Function Block_Duplicate @@ -330,54 +347,51 @@ public: WinEDA_GerberFrame( wxWindow* father, const wxString& title, * * @param DC A device context to draw on. */ - void Block_Duplicate( wxDC* DC ); + void Block_Duplicate( wxDC* DC ); - void ToPostProcess( wxCommandEvent& event ); + void ToPostProcess( wxCommandEvent& event ); /** * Function ToPlotter * Open a dialog frame to create plot and drill files * relative to the current board */ - void ToPlotter( wxCommandEvent& event ); + void ToPlotter( wxCommandEvent& event ); /** * Function ToPrinter * Open a dialog frame to print layers */ - void ToPrinter( wxCommandEvent& event ); + void ToPrinter( wxCommandEvent& event ); - void Genere_HPGL( const wxString& FullFileName, int Layers ); - void Genere_GERBER( const wxString& FullFileName, int Layers ); - void Genere_PS( const wxString& FullFileName, int Layers ); - void Plot_Layer_HPGL( FILE* File, int masque_layer, - int garde, bool trace_via, - GRTraceMode trace_mode ); - void Plot_Layer_GERBER( FILE* File, int masque_layer, - int garde, bool trace_via, - GRTraceMode trace_mode ); - int Gen_D_CODE_File( const wxString& Name_File ); - void Plot_Layer_PS( FILE* File, int masque_layer, - int garde, bool trace_via, - GRTraceMode trace_mode ); + void Genere_HPGL( const wxString& FullFileName, int Layers ); + void Genere_GERBER( const wxString& FullFileName, int Layers ); + void Genere_PS( const wxString& FullFileName, int Layers ); + void Plot_Layer_HPGL( FILE* File, int masque_layer,int garde, bool trace_via, + GRTraceMode trace_mode ); + void Plot_Layer_GERBER( FILE* File, int masque_layer, int garde, bool trace_via, + GRTraceMode trace_mode ); + int Gen_D_CODE_File( const wxString& Name_File ); + void Plot_Layer_PS( FILE* File, int masque_layer, int garde, bool trace_via, + GRTraceMode trace_mode ); - void Files_io( wxCommandEvent& event ); - void OnFileHistory( wxCommandEvent& event ); + void Files_io( wxCommandEvent& event ); + void OnFileHistory( wxCommandEvent& event ); /** * function LoadGerberFiles * Load a photoplot (Gerber) file or many files. - * @param aFileName - void string or file name with full path to open or empty string to open a new - * file. In this case one one file is loaded + * @param aFileName - void string or file name with full path to open or empty string to + * open a new file. In this case one one file is loaded * if void string: user will be prompted for filename(s) * @return true if file was opened successfully. */ - bool LoadGerberFiles( const wxString& aFileName ); - int ReadGerberFile( FILE* File, bool Append ); - bool Read_GERBER_File( const wxString& GERBER_FullFileName, - const wxString& D_Code_FullFileName ); + bool LoadGerberFiles( const wxString& aFileName ); + int ReadGerberFile( FILE* File, bool Append ); + bool Read_GERBER_File( const wxString& GERBER_FullFileName, + const wxString& D_Code_FullFileName ); - void GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aHotKey = 0 ); + void GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aHotKey = 0 ); /** * Function Read_D_Code_File @@ -402,26 +416,25 @@ public: WinEDA_GerberFrame( wxWindow* father, const wxString& title, * g_GERBER_List[]
* 1 = read OK
*/ - int Read_D_Code_File( const wxString& D_Code_FullFileName ); - void CopyDCodesSizeToItems(); - void Liste_D_Codes(); + int Read_D_Code_File( const wxString& D_Code_FullFileName ); + void CopyDCodesSizeToItems(); + void Liste_D_Codes(); // PCB handling - bool Clear_Pcb( bool query ); - void Erase_Current_Layer( bool query ); - void Delete_DCode_Items( wxDC* DC, int dcode_value, int layer_number ); + bool Clear_Pcb( bool query ); + void Erase_Current_Layer( bool query ); + void Delete_DCode_Items( wxDC* DC, int dcode_value, int layer_number ); // Conversion function - void ExportDataInPcbnewFormat( wxCommandEvent& event ); + void ExportDataInPcbnewFormat( wxCommandEvent& event ); /* SaveCopyInUndoList() virtual * currently: do nothing in gerbview. * but must be defined because it is a pure virtual in PCB_BASE_FRAME */ - virtual void SaveCopyInUndoList( - BOARD_ITEM* aItemToCopy, - UndoRedoOpType aTypeCommand = UR_UNSPECIFIED, - const wxPoint& aTransformPoint = wxPoint( 0, 0 ) ) { } + virtual void SaveCopyInUndoList( BOARD_ITEM* aItemToCopy, + UndoRedoOpType aTypeCommand = UR_UNSPECIFIED, + const wxPoint& aTransformPoint = wxPoint( 0, 0 ) ) { } /** * Function SaveCopyInUndoList (overloaded). @@ -432,15 +445,13 @@ public: WinEDA_GerberFrame( wxWindow* father, const wxString& title, * @param aTransformPoint = the reference point of the transformation, * for commands like move */ - virtual void SaveCopyInUndoList( - PICKED_ITEMS_LIST& aItemsList, - UndoRedoOpType aTypeCommand, - const wxPoint& aTransformPoint = wxPoint( 0, 0 ) ) + virtual void SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, + UndoRedoOpType aTypeCommand, + const wxPoint& aTransformPoint = wxPoint( 0, 0 ) ) { // currently: do nothing in gerbview. } - /** Virtual function PrintPage * used to print a page * @param aDC = wxDC given by the calling print function @@ -448,8 +459,7 @@ public: WinEDA_GerberFrame( wxWindow* father, const wxString& title, * @param aPrintMirrorMode = not used here (Set when printing in mirror mode) * @param aData = a pointer on an auxiliary data (not always used, NULL if not used) */ - virtual void PrintPage( wxDC* aDC, - int aPrintMasklayer, bool aPrintMirrorMode, + virtual void PrintPage( wxDC* aDC, int aPrintMasklayer, bool aPrintMirrorMode, void* aData = NULL ); /** @@ -458,7 +468,7 @@ public: WinEDA_GerberFrame( wxWindow* father, const wxString& title, * between gerber layers and pcbnew layers * @return the "lookup table" if ok, or NULL */ - int* InstallDialogLayerPairChoice(); + int* InstallDialogLayerPairChoice(); /** * Function DrawItemsDCodeID @@ -467,7 +477,7 @@ public: WinEDA_GerberFrame( wxWindow* father, const wxString& title, * @param aDC = the current device contect * @param aDrawMode = GR_COPY, GR_OR ... */ - void DrawItemsDCodeID( wxDC* aDC, int aDrawMode ); + void DrawItemsDCodeID( wxDC* aDC, int aDrawMode ); DECLARE_EVENT_TABLE() };