KiCad PCB EDA Suite
dialog_import_gfx.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-2022 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
27#include "dialog_import_gfx.h"
28#include <base_units.h>
29#include <kiface_base.h>
30#include <locale_io.h>
33#include <bitmaps.h>
34#include <map>
35#include "dxf_import_plugin.h"
36#include <wx/filedlg.h>
37#include <wx/msgdlg.h>
38
39#include <memory>
40
41// Static members of DIALOG_IMPORT_GFX, to remember the user's choices during the session
44double DIALOG_IMPORT_GFX::m_importScale = 1.0; // Do not change the imported items size
45
46
47const std::map<DXF_IMPORT_UNITS, wxString> dxfUnitsMap = {
48 { DXF_IMPORT_UNITS::INCHES, _( "Inches" ) },
49 { DXF_IMPORT_UNITS::MILLIMETERS, _( "Millimeters" ) },
50 { DXF_IMPORT_UNITS::MILS, _( "Mils" ) },
51 { DXF_IMPORT_UNITS::CENTIMETERS, _( "Centimeter" ) },
52 { DXF_IMPORT_UNITS::FEET, _( "Feet" ) },
53};
54
55
56DIALOG_IMPORT_GFX::DIALOG_IMPORT_GFX( PCB_BASE_FRAME* aParent, bool aImportAsFootprintGraphic ) :
57 DIALOG_IMPORT_GFX_BASE( aParent ),
58 m_parent( aParent ),
59 m_xOrigin( aParent, m_xLabel, m_xCtrl, m_xUnits ),
60 m_yOrigin( aParent, m_yLabel, m_yCtrl, m_yUnits ),
61 m_defaultLineWidth( aParent, m_lineWidthLabel, m_lineWidthCtrl, m_lineWidthUnits )
62{
63 if( aImportAsFootprintGraphic )
64 m_importer = std::make_unique<GRAPHICS_IMPORTER_FOOTPRINT>( m_parent->GetBoard()->GetFirstFootprint() );
65 else
66 m_importer = std::make_unique<GRAPHICS_IMPORTER_BOARD>( m_parent->GetBoard() );
67
68 // construct an import manager with options from config
69 {
71 // Currently: all types are allowed, so the blacklist is empty
72 // (no GFX_FILE_T in the blacklist)
73 // To disable SVG import, enable these 2 lines
74 // if( !ADVANCED_CFG::GetCfg().m_enableSvgImport )
75 // blacklist.push_back( GRAPHICS_IMPORT_MGR::SVG );
76 // The SVG import has currently a flaw: all SVG shapes are imported as curves and
77 // converted to a lot of segments. A better approach is to convert to polylines
78 // (not yet existing in Pcbnew) and keep arcs and circles as primitives (not yet
79 // possible with tinysvg library).
80
81 m_gfxImportMgr = std::make_unique<GRAPHICS_IMPORT_MGR>( blacklist );
82 }
83
85
87
91
96
97 m_importScaleCtrl->SetValue( wxString::Format( wxT( "%f" ), m_importScale ) );
98
99 // Configure the layers list selector
100 m_SelLayerBox->SetLayersHotkeys( false ); // Do not display hotkeys
103
106
107 for( const std::pair<const DXF_IMPORT_UNITS, wxString>& unitEntry : dxfUnitsMap )
108 m_choiceDxfUnits->Append( unitEntry.second );
109
110 m_choiceDxfUnits->SetSelection( cfg->m_ImportGraphics.dxf_units );
111
113
114 wxCommandEvent dummy;
115 onFilename( dummy );
116
119
120 GetSizer()->Fit( this );
121 GetSizer()->SetSizeHints( this );
122 Centre();
123
124 m_textCtrlFileName->Connect( wxEVT_COMMAND_TEXT_UPDATED,
125 wxCommandEventHandler( DIALOG_IMPORT_GFX::onFilename ),
126 nullptr, this );
127}
128
129
131{
133
140 cfg->m_ImportGraphics.dxf_units = m_choiceDxfUnits->GetSelection();
141
143
144 m_textCtrlFileName->Disconnect( wxEVT_COMMAND_TEXT_UPDATED,
145 wxCommandEventHandler( DIALOG_IMPORT_GFX::onFilename ),
146 nullptr, this );
147}
148
149
150void DIALOG_IMPORT_GFX::onFilename( wxCommandEvent& event )
151{
152 bool enableDXFControls = true;
153 wxString ext = wxFileName( m_textCtrlFileName->GetValue() ).GetExt();
154
155 if( std::unique_ptr<GRAPHICS_IMPORT_PLUGIN> plugin = m_gfxImportMgr->GetPluginByExt( ext ) )
156 enableDXFControls = dynamic_cast<DXF_IMPORT_PLUGIN*>( plugin.get() ) != nullptr;
157
158 m_defaultLineWidth.Enable( enableDXFControls );
159
160 m_staticTextLineWidth1->Enable( enableDXFControls );
161 m_choiceDxfUnits->Enable( enableDXFControls );
162}
163
164
165void DIALOG_IMPORT_GFX::onBrowseFiles( wxCommandEvent& event )
166{
167 wxString path;
168 wxString filename = m_textCtrlFileName->GetValue();
169
170 if( !filename.IsEmpty() )
171 {
172 wxFileName fn( filename );
173 path = fn.GetPath();
174 filename = fn.GetFullName();
175 }
176
177 // Generate the list of handled file formats
178 wxString wildcardsDesc;
179 wxString allWildcards;
180
181 for( GRAPHICS_IMPORT_MGR::GFX_FILE_T pluginType : m_gfxImportMgr->GetImportableFileTypes() )
182 {
183 std::unique_ptr<GRAPHICS_IMPORT_PLUGIN> plugin = m_gfxImportMgr->GetPlugin( pluginType );
184 const std::vector<std::string> extensions = plugin->GetFileExtensions();
185
186 wildcardsDesc += wxT( "|" ) + plugin->GetName() + AddFileExtListToFilter( extensions );
187 allWildcards += plugin->GetWildcards() + wxT( ";" );
188 }
189
190 wildcardsDesc = _( "All supported formats|" ) + allWildcards + wildcardsDesc;
191
192 wxFileDialog dlg( m_parent, _( "Open File" ), path, filename, wildcardsDesc,
193 wxFD_OPEN | wxFD_FILE_MUST_EXIST );
194
195 if( dlg.ShowModal() == wxID_OK && !dlg.GetPath().IsEmpty() )
196 m_textCtrlFileName->SetValue( dlg.GetPath() );
197}
198
199
201{
202 if( !wxDialog::TransferDataFromWindow() )
203 return false;
204
205 if( m_textCtrlFileName->GetValue().IsEmpty() )
206 {
207 wxMessageBox( _( "No file selected!" ) );
208 return false;
209 }
210
212 {
213 wxMessageBox( _( "Please select a valid layer." ) );
214 return false;
215 }
216
217 wxString ext = wxFileName( m_textCtrlFileName->GetValue() ).GetExt();
220
221 if( std::unique_ptr<GRAPHICS_IMPORT_PLUGIN> plugin = m_gfxImportMgr->GetPluginByExt( ext ) )
222 {
223 if( DXF_IMPORT_PLUGIN* dxfPlugin = dynamic_cast<DXF_IMPORT_PLUGIN*>( plugin.get() ) )
224 {
225 auto it = dxfUnitsMap.begin();
226 std::advance( it, m_choiceDxfUnits->GetSelection() );
227
228 if( it == dxfUnitsMap.end() )
229 dxfPlugin->SetUnit( DXF_IMPORT_UNITS::DEFAULT );
230 else
231 dxfPlugin->SetUnit( it->first );
232
234 }
235 else
236 {
237 m_importer->SetLineWidthMM( 0.0 );
238 }
239
240 m_importer->SetPlugin( std::move( plugin ) );
242 m_importer->SetImportOffsetMM( { pcbIUScale.IUTomm( origin.x ), pcbIUScale.IUTomm( origin.y ) } );
243
244 LOCALE_IO dummy; // Ensure floats can be read.
245
246 if( m_importer->Load( m_textCtrlFileName->GetValue() ) )
247 m_importer->Import( scale );
248
249 // Get warning messages:
250 wxString warnings = m_importer->GetMessages();
251
252 // This isn't a fatal error so allow the dialog to close with wxID_OK.
253 if( !warnings.empty() )
254 {
255 HTML_MESSAGE_BOX dlg( this, _( "Warning" ) );
256 dlg.MessageSet( _( "Items in the imported file could not be handled properly." ) );
257 warnings.Replace( wxT( "\n" ), wxT( "<br/>" ) );
258 dlg.AddHTML_Text( warnings );
259 dlg.ShowModal();
260 }
261
262 return true;
263 }
264 else
265 {
266 wxMessageBox( _( "There is no plugin to handle this file type." ) );
267 return false;
268 }
269}
270
271
272void DIALOG_IMPORT_GFX::originOptionOnUpdateUI( wxUpdateUIEvent& event )
273{
276
279
282}
283
284
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:109
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:105
@ small_folder
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition: board.h:397
Class DIALOG_IMPORT_GFX_BASE.
PCB_LAYER_BOX_SELECTOR * m_SelLayerBox
wxRadioButton * m_rbInteractivePlacement
wxRadioButton * m_rbAbsolutePlacement
wxStaticText * m_staticTextLineWidth1
void onFilename(wxCommandEvent &event)
static double m_importScale
bool TransferDataFromWindow() override
void originOptionOnUpdateUI(wxUpdateUIEvent &event) override
PCB_BASE_FRAME * m_parent
DIALOG_IMPORT_GFX(PCB_BASE_FRAME *aParent, bool aUseModuleItems=false)
std::unique_ptr< GRAPHICS_IMPORT_MGR > m_gfxImportMgr
static bool m_placementInteractive
UNIT_BINDER m_defaultLineWidth
static bool m_shouldGroupItems
void onBrowseFiles(wxCommandEvent &event) override
std::unique_ptr< GRAPHICS_IMPORTER_PCBNEW > m_importer
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition: dialog_shim.h:97
void SetupStandardButtons(std::map< int, wxString > aLabels={})
GFX_FILE_T
< List of handled file types.
std::vector< GFX_FILE_T > TYPE_LIST
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:41
DIALOG_IMPORT_GRAPHICS m_ImportGraphics
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
PCBNEW_SETTINGS * GetPcbNewSettings() const
BOARD * GetBoard() const
void SetBoardFrame(PCB_BASE_FRAME *aFrame)
virtual long long int GetValue()
Return the current value in Internal Units.
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
#define _(s)
wxString AddFileExtListToFilter(const std::vector< std::string > &aExts)
Build the wildcard extension file dialog wildcard filter to add to the base message dialog.
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:59
@ Dwgs_User
Definition: layer_ids.h:109
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:451
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
Definition: sch_symbol.cpp:74
const int scale
constexpr double IUTomm(int iu) const
Definition: base_units.h:87
const double IU_PER_MM
Definition: base_units.h:77
Definition of file extensions used in Kicad.