KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_import_graphics.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
26
29#include <base_units.h>
30#include <kiface_base.h>
31#include <locale_io.h>
34#include <bitmaps.h>
36#include <map>
37#include <footprint.h>
38#include <wx/filedlg.h>
39#include <wx/msgdlg.h>
40
41#include <memory>
42
43// Static members of DIALOG_IMPORT_GRAPHICS, to remember the user's choices during the session
49double DIALOG_IMPORT_GRAPHICS::s_importScale = 1.0; // Do not change the imported items size
50
51
52const std::map<DXF_IMPORT_UNITS, wxString> dxfUnitsMap = {
53 { DXF_IMPORT_UNITS::INCHES, _( "Inches" ) },
54 { DXF_IMPORT_UNITS::MILLIMETERS, _( "Millimeters" ) },
55 { DXF_IMPORT_UNITS::MILS, _( "Mils" ) },
56 { DXF_IMPORT_UNITS::CENTIMETERS, _( "Centimeter" ) },
57 { DXF_IMPORT_UNITS::FEET, _( "Feet" ) },
58};
59
60
63 m_parent( aParent ),
64 m_xOrigin( aParent, nullptr, m_xCtrl, nullptr ),
65 m_yOrigin( aParent, m_yLabel, m_yCtrl, m_yUnits ),
66 m_defaultLineWidth( aParent, m_lineWidthLabel, m_lineWidthCtrl, m_lineWidthUnits ),
67 m_tolerance( aParent, m_toleranceLabel, m_toleranceCtrl, m_toleranceUnits )
68{
69 // The SVG import has currently a flaw: all SVG shapes are imported as curves and
70 // converted to a lot of segments. A better approach is to convert to polylines
71 // (not yet existing in Pcbnew) and keep arcs and circles as primitives (not yet
72 // possible with tinysvg library).
73
74 m_importer = std::make_unique<GRAPHICS_IMPORTER_PCBNEW>( aParent->GetModel() );
75 m_gfxImportMgr = std::make_unique<GRAPHICS_IMPORT_MGR>();
76
78
83
87
91
92 m_importScaleCtrl->SetValue( wxString::Format( wxT( "%f" ), s_importScale ) );
93
96
99
100 // Configure the layers list selector
101 m_SelLayerBox->SetLayersHotkeys( false ); // Do not display hotkeys
104
107
108 for( const std::pair<const DXF_IMPORT_UNITS, wxString>& unitEntry : dxfUnitsMap )
109 m_dxfUnitsChoice->Append( unitEntry.second );
110
111 m_dxfUnitsChoice->SetSelection( cfg->m_ImportGraphics.dxf_units );
112
113 m_browseButton->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
114
115 wxCommandEvent dummy;
116 onFilename( dummy );
117
120
121 GetSizer()->Fit( this );
122 GetSizer()->SetSizeHints( this );
123 Centre();
124
125 m_textCtrlFileName->Connect( wxEVT_COMMAND_TEXT_UPDATED,
126 wxCommandEventHandler( DIALOG_IMPORT_GRAPHICS::onFilename ),
127 nullptr, this );
128}
129
130
132{
136 s_shouldGroupItems = m_cbGroupItems->IsChecked();
138
139 PCBNEW_SETTINGS* cfg = nullptr;
140
141 try
142 {
144 }
145 catch( const std::runtime_error& e )
146 {
147 wxFAIL_MSG( e.what() );
148 }
149
150 if( cfg )
151 {
159 cfg->m_ImportGraphics.dxf_units = m_dxfUnitsChoice->GetSelection();
163 }
164
166
167 m_textCtrlFileName->Disconnect( wxEVT_COMMAND_TEXT_UPDATED,
168 wxCommandEventHandler( DIALOG_IMPORT_GRAPHICS::onFilename ),
169 nullptr, this );
170}
171
172
173void DIALOG_IMPORT_GRAPHICS::onFilename( wxCommandEvent& event )
174{
175 bool enableDXFControls = true;
176 wxString ext = wxFileName( m_textCtrlFileName->GetValue() ).GetExt();
177
178 if( std::unique_ptr<GRAPHICS_IMPORT_PLUGIN> plugin = m_gfxImportMgr->GetPluginByExt( ext ) )
179 enableDXFControls = dynamic_cast<DXF_IMPORT_PLUGIN*>( plugin.get() ) != nullptr;
180
181 m_defaultLineWidth.Enable( enableDXFControls );
182
183 m_dxfUnitsLabel->Enable( enableDXFControls );
184 m_dxfUnitsChoice->Enable( enableDXFControls );
185}
186
187
188void DIALOG_IMPORT_GRAPHICS::onBrowseFiles( wxCommandEvent& event )
189{
190 wxString path;
191 wxString filename = m_textCtrlFileName->GetValue();
192
193 if( !filename.IsEmpty() )
194 {
195 wxFileName fn( filename );
196 path = fn.GetPath();
197 filename = fn.GetFullName();
198 }
199
200 // Generate the list of handled file formats
201 wxString wildcardsDesc;
202 wxString allWildcards;
203
204 for( GRAPHICS_IMPORT_MGR::GFX_FILE_T pluginType : m_gfxImportMgr->GetImportableFileTypes() )
205 {
206 std::unique_ptr<GRAPHICS_IMPORT_PLUGIN> plugin = m_gfxImportMgr->GetPlugin( pluginType );
207 const std::vector<std::string> extensions = plugin->GetFileExtensions();
208
209 wildcardsDesc += wxT( "|" ) + plugin->GetName() + AddFileExtListToFilter( extensions );
210 allWildcards += plugin->GetWildcards() + wxT( ";" );
211 }
212
213 wildcardsDesc = _( "All supported formats" ) + wxT( "|" ) + allWildcards + wildcardsDesc;
214
215 wxFileDialog dlg( m_parent, _( "Import Graphics" ), path, filename, wildcardsDesc,
216 wxFD_OPEN | wxFD_FILE_MUST_EXIST );
217
218 if( dlg.ShowModal() == wxID_OK && !dlg.GetPath().IsEmpty() )
219 m_textCtrlFileName->SetValue( dlg.GetPath() );
220}
221
222
224{
225 if( !wxDialog::TransferDataFromWindow() )
226 return false;
227
228 if( m_textCtrlFileName->GetValue().IsEmpty() )
229 {
230 wxMessageBox( _( "Please select a file to import." ) );
231 return false;
232 }
233
234 if( m_setLayerCheckbox->GetValue() && m_SelLayerBox->GetLayerSelection() < 0 )
235 {
236 wxMessageBox( _( "Please select a valid layer." ) );
237 return false;
238 }
239
241 wxString ext = wxFileName( m_textCtrlFileName->GetValue() ).GetExt();
243 double xscale = scale;
244 double yscale = scale;
245
247 xscale *= -1.0;
248
250 yscale *= -1.0;
251
252 VECTOR2D origin( m_xOrigin.GetIntValue() / xscale, m_yOrigin.GetIntValue() / yscale );
253
254 if( std::unique_ptr<GRAPHICS_IMPORT_PLUGIN> plugin = m_gfxImportMgr->GetPluginByExt( ext ) )
255 {
256 if( DXF_IMPORT_PLUGIN* dxfPlugin = dynamic_cast<DXF_IMPORT_PLUGIN*>( plugin.get() ) )
257 {
258 auto it = dxfUnitsMap.begin();
259 std::advance( it, m_dxfUnitsChoice->GetSelection() );
260
261 if( it == dxfUnitsMap.end() )
262 dxfPlugin->SetUnit( DXF_IMPORT_UNITS::DEFAULT );
263 else
264 dxfPlugin->SetUnit( it->first );
265
267 }
268 else
269 {
270 m_importer->SetLineWidthMM( 0.0 );
271 }
272
273 m_importer->SetPlugin( std::move( plugin ) );
274
275 if( m_setLayerCheckbox->GetValue() )
277 else
278 m_importer->SetLayer( m_parent->GetActiveLayer() );
279
280 m_importer->SetImportOffsetMM( { pcbIUScale.IUTomm( origin.x ),
281 pcbIUScale.IUTomm( origin.y ) } );
282
283 LOCALE_IO dummy; // Ensure floats can be read.
284
285 if( m_importer->Load( m_textCtrlFileName->GetValue() ) )
286 m_importer->Import( VECTOR2D( scale, scale ) );
287
288 // Get warning messages:
289 wxString warnings = m_importer->GetMessages();
290
291 // This isn't a fatal error so allow the dialog to close with wxID_OK.
292 if( !warnings.empty() )
293 {
294 HTML_MESSAGE_BOX dlg( this, _( "Warning" ) );
295 dlg.MessageSet( _( "Items in the imported file could not be handled properly." ) );
296 warnings.Replace( wxT( "\n" ), wxT( "<br/>" ) );
297 dlg.AddHTML_Text( warnings );
298 dlg.ShowModal();
299 }
300
301 return true;
302 }
303 else
304 {
305 wxMessageBox( _( "There is no plugin to handle this file type." ) );
306 return false;
307 }
308}
309
310
311void DIALOG_IMPORT_GRAPHICS::onUpdateUI( wxUpdateUIEvent& event )
312{
313 m_xOrigin.Enable( m_placeAtCheckbox->GetValue() );
314 m_yOrigin.Enable( m_placeAtCheckbox->GetValue() );
315
317
318 m_SelLayerBox->Enable( m_setLayerCheckbox->GetValue() );
319}
320
321
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap)
Definition: bitmap.cpp:110
Class DIALOG_IMPORT_GRAPHICS_BASE.
PCB_LAYER_BOX_SELECTOR * m_SelLayerBox
std::unique_ptr< GRAPHICS_IMPORT_MGR > m_gfxImportMgr
void onFilename(wxCommandEvent &event)
std::unique_ptr< GRAPHICS_IMPORTER_PCBNEW > m_importer
void onBrowseFiles(wxCommandEvent &event) override
void onUpdateUI(wxUpdateUIEvent &event) override
DIALOG_IMPORT_GRAPHICS(PCB_BASE_FRAME *aParent)
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:98
void SetupStandardButtons(std::map< int, wxString > aLabels={})
GFX_FILE_T
< List of handled file types.
void MessageSet(const wxString &message)
Add a message (in bold) to message list.
void AddHTML_Text(const wxString &message)
Add HTML text (without any change) to message list.
int SetLayerSelection(int layer)
bool SetLayersHotkeys(bool value)
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: locale_io.h:49
DISPLAY_OPTIONS m_Display
DIALOG_IMPORT_GRAPHICS m_ImportGraphics
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
PCBNEW_SETTINGS * GetPcbNewSettings() const
virtual PCB_LAYER_ID GetActiveLayer() const
virtual BOARD_ITEM_CONTAINER * GetModel() const =0
void SetBoardFrame(PCB_BASE_FRAME *aFrame)
void SetBitmap(const wxBitmapBundle &aBmp)
int GetIntValue()
Definition: unit_binder.h:127
void Enable(bool aEnable)
Enable/disable the label, widget and units label.
virtual void SetValue(long long int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
const std::map< DXF_IMPORT_UNITS, wxString > dxfUnitsMap
const std::map< DXF_IMPORT_UNITS, wxString > dxfUnitsMap
#define _(s)
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ Dwgs_User
Definition: layer_ids.h:109
KICOMMON_API double DoubleValueFromString(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, const wxString &aTextValue, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Function DoubleValueFromString converts aTextValue to a double.
Definition: eda_units.cpp:572
const int scale
std::vector< FAB_LAYER_COLOR > dummy
constexpr double IUTomm(int iu) const
Definition: base_units.h:86
const double IU_PER_MM
Definition: base_units.h:76
constexpr int mmToIU(double mm) const
Definition: base_units.h:88
VECTOR2< double > VECTOR2D
Definition: vector2d.h:587
wxString AddFileExtListToFilter(const std::vector< std::string > &aExts)
Build the wildcard extension file dialog wildcard filter to add to the base message dialog.
Definition of file extensions used in Kicad.