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 The 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
44const std::map<DXF_IMPORT_UNITS, wxString> dxfUnitsMap = {
45 { DXF_IMPORT_UNITS::INCH, _( "Inches" ) },
46 { DXF_IMPORT_UNITS::MM, _( "Millimeters" ) },
47 { DXF_IMPORT_UNITS::MILS, _( "Mils" ) },
48 { DXF_IMPORT_UNITS::CM, _( "Centimeter" ) },
49 { DXF_IMPORT_UNITS::FEET, _( "Feet" ) },
50};
51
52
55 m_parent( aParent ),
56 m_xOrigin( aParent, nullptr, m_xCtrl, nullptr ),
57 m_yOrigin( aParent, m_yLabel, m_yCtrl, m_yUnits ),
60{
61 // The SVG import has currently a flaw: all SVG shapes are imported as curves and
62 // converted to a lot of segments. A better approach is to convert to polylines
63 // (not yet existing in Pcbnew) and keep arcs and circles as primitives (not yet
64 // possible with tinysvg library).
65
66 m_importer = std::make_unique<GRAPHICS_IMPORTER_PCBNEW>( aParent->GetModel() );
67 m_gfxImportMgr = std::make_unique<GRAPHICS_IMPORT_MGR>();
68
69 // Configure the layers list selector
70 m_SelLayerBox->SetLayersHotkeys( false ); // Do not display hotkeys
71 m_SelLayerBox->SetBoardFrame( m_parent );
72 m_SelLayerBox->Resync();
73
74 for( const std::pair<const DXF_IMPORT_UNITS, wxString>& unitEntry : dxfUnitsMap )
75 m_dxfUnitsChoice->Append( unitEntry.second );
76
78
79 wxCommandEvent dummy;
81
84
85 GetSizer()->Fit( this );
86 GetSizer()->SetSizeHints( this );
87 Centre();
88
89 m_textCtrlFileName->Connect( wxEVT_COMMAND_TEXT_UPDATED,
90 wxCommandEventHandler( DIALOG_IMPORT_GRAPHICS::onFilename ),
91 nullptr, this );
92}
93
94
96{
97 m_textCtrlFileName->Disconnect( wxEVT_COMMAND_TEXT_UPDATED,
98 wxCommandEventHandler( DIALOG_IMPORT_GRAPHICS::onFilename ),
99 nullptr, this );
100}
101
102
103void DIALOG_IMPORT_GRAPHICS::SetFilenameOverride( const wxString& aFilenameOverride )
104{
105 m_filenameOverride = aFilenameOverride;
106}
107
108
110{
111 DIALOG_SHIM::TransferDataToWindow();
112
113 // We have to set the filename field value here, otherwise it gets overwritten by state loading
114 if( !m_filenameOverride.IsEmpty() )
116
117 return true;
118}
119
120
121void DIALOG_IMPORT_GRAPHICS::onFilename( wxCommandEvent& event )
122{
123 bool enableDXFControls = true;
124 wxString ext = wxFileName( m_textCtrlFileName->GetValue() ).GetExt();
125
126 if( std::unique_ptr<GRAPHICS_IMPORT_PLUGIN> plugin = m_gfxImportMgr->GetPluginByExt( ext ) )
127 enableDXFControls = dynamic_cast<DXF_IMPORT_PLUGIN*>( plugin.get() ) != nullptr;
128
129 m_defaultLineWidth.Enable( enableDXFControls );
130
131 m_dxfUnitsLabel->Enable( enableDXFControls );
132 m_dxfUnitsChoice->Enable( enableDXFControls );
133}
134
135
136void DIALOG_IMPORT_GRAPHICS::onBrowseFiles( wxCommandEvent& event )
137{
138 wxString path;
139 wxString filename = m_textCtrlFileName->GetValue();
140
141 if( !filename.IsEmpty() )
142 {
143 wxFileName fn( filename );
144 path = fn.GetPath();
145 filename = fn.GetFullName();
146 }
147
148 // Generate the list of handled file formats
149 wxString wildcardsDesc;
150 wxString allWildcards;
151
152 for( GRAPHICS_IMPORT_MGR::GFX_FILE_T pluginType : m_gfxImportMgr->GetImportableFileTypes() )
153 {
154 std::unique_ptr<GRAPHICS_IMPORT_PLUGIN> plugin = m_gfxImportMgr->GetPlugin( pluginType );
155 const std::vector<std::string> extensions = plugin->GetFileExtensions();
156
157 wildcardsDesc += wxT( "|" ) + plugin->GetName() + AddFileExtListToFilter( extensions );
158 allWildcards += plugin->GetWildcards() + wxT( ";" );
159 }
160
161 wildcardsDesc = _( "All supported formats" ) + wxT( "|" ) + allWildcards + wildcardsDesc;
162
163 wxFileDialog dlg( m_parent, _( "Import Graphics" ), path, filename, wildcardsDesc,
164 wxFD_OPEN | wxFD_FILE_MUST_EXIST );
165
166 if( dlg.ShowModal() == wxID_OK && !dlg.GetPath().IsEmpty() )
167 m_textCtrlFileName->SetValue( dlg.GetPath() );
168}
169
170
172{
173 if( !wxDialog::TransferDataFromWindow() )
174 return false;
175
176 if( m_textCtrlFileName->GetValue().IsEmpty() )
177 {
178 wxMessageBox( _( "Please select a file to import." ) );
179 return false;
180 }
181
182 if( m_setLayerCheckbox->GetValue() && m_SelLayerBox->GetLayerSelection() < 0 )
183 {
184 wxMessageBox( _( "Please select a valid layer." ) );
185 return false;
186 }
187
188 PCBNEW_SETTINGS* cfg = m_parent->GetPcbNewSettings();
189 wxString ext = wxFileName( m_textCtrlFileName->GetValue() ).GetExt();
191 double xscale = scale;
192 double yscale = scale;
193
195 xscale *= -1.0;
196
198 yscale *= -1.0;
199
200 VECTOR2D origin( m_xOrigin.GetDoubleValue() / xscale, m_yOrigin.GetDoubleValue() / yscale );
201
202 if( std::unique_ptr<GRAPHICS_IMPORT_PLUGIN> plugin = m_gfxImportMgr->GetPluginByExt( ext ) )
203 {
204 if( DXF_IMPORT_PLUGIN* dxfPlugin = dynamic_cast<DXF_IMPORT_PLUGIN*>( plugin.get() ) )
205 {
206 auto it = dxfUnitsMap.begin();
207 std::advance( it, m_dxfUnitsChoice->GetSelection() );
208
209 if( it == dxfUnitsMap.end() )
210 dxfPlugin->SetUnit( DXF_IMPORT_UNITS::DEFAULT );
211 else
212 dxfPlugin->SetUnit( it->first );
213
214 m_importer->SetLineWidthMM( pcbIUScale.IUTomm( m_defaultLineWidth.GetIntValue() ) );
215 }
216 else
217 {
218 m_importer->SetLineWidthMM( 0.0 );
219 }
220
221 m_importer->SetPlugin( std::move( plugin ) );
222
223 if( m_setLayerCheckbox->GetValue() )
224 m_importer->SetLayer( PCB_LAYER_ID( m_SelLayerBox->GetLayerSelection() ) );
225 else
226 m_importer->SetLayer( m_parent->GetActiveLayer() );
227
228 m_importer->SetImportOffsetMM( origin * pcbIUScale.IUTomm( 1 ) );
229
230 LOCALE_IO dummy; // Ensure floats can be read.
231
232 if( m_importer->Load( m_textCtrlFileName->GetValue() ) )
233 m_importer->Import( VECTOR2D( scale, scale ) );
234
235 // Get warning messages:
236 wxString warnings = m_importer->GetMessages();
237
238 // This isn't a fatal error so allow the dialog to close with wxID_OK.
239 if( !warnings.empty() )
240 {
241 HTML_MESSAGE_BOX dlg( this, _( "Warning" ) );
242 dlg.MessageSet( _( "Items in the imported file could not be handled properly." ) );
243 warnings.Replace( wxT( "\n" ), wxT( "<br/>" ) );
244 dlg.AddHTML_Text( warnings );
245 dlg.ShowModal();
246 }
247
248 return true;
249 }
250 else
251 {
252 wxMessageBox( _( "There is no plugin to handle this file type." ) );
253 return false;
254 }
255}
256
257
258void DIALOG_IMPORT_GRAPHICS::onUpdateUI( wxUpdateUIEvent& event )
259{
260 m_xOrigin.Enable( m_placeAtCheckbox->GetValue() );
261 m_yOrigin.Enable( m_placeAtCheckbox->GetValue() );
262
263 m_tolerance.Enable( m_rbFixDiscontinuities->GetValue() );
264
265 m_SelLayerBox->Enable( m_setLayerCheckbox->GetValue() );
266}
267
268
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:112
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:110
DIALOG_IMPORT_GRAPHICS_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Import Vector Graphics File"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
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 SetFilenameOverride(const wxString &aFilenameOverride)
Set the filename override to be applied in TransferDataToWindow.
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:82
void SetupStandardButtons(std::map< int, wxString > aLabels={})
int ShowModal() override
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.
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition locale_io.h:41
DISPLAY_OPTIONS m_Display
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
virtual BOARD_ITEM_CONTAINER * GetModel() const =0
const std::map< DXF_IMPORT_UNITS, wxString > dxfUnitsMap
#define _(s)
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:60
KICOMMON_API double DoubleValueFromString(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, const wxString &aTextValue, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Convert aTextValue to a double.
const int scale
std::vector< FAB_LAYER_COLOR > dummy
VECTOR2< double > VECTOR2D
Definition vector2d.h:694
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.