KiCad PCB EDA Suite
Loading...
Searching...
No Matches
bitmap2cmp_panel.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) 1992-2010 jean-pierre.charras
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
25#include <bitmap2cmp_frame.h>
26#include <bitmap2component.h>
27#include <bitmap2cmp_panel.h>
28#include <bitmap2cmp_settings.h>
29#include <bitmap_io.h>
30#include <common.h>
31#include <math/util.h> // for KiROUND
32#include <potracelib.h>
33#include <vector>
34#include <wx/arrstr.h>
35#include <wx/clipbrd.h>
36#include <wx/dnd.h>
37#include <wx/rawbmp.h>
38#include <wx/msgdlg.h>
39#include <wx/dcclient.h>
40#include <wx/log.h>
41#include <wx/string.h>
42#include <confirm.h>
43
44#define DEFAULT_DPI 300 // the image DPI used in formats that do not define a DPI
45
46
48 BITMAP2CMP_PANEL_BASE( aParent ),
49 m_parentFrame( aParent ),
50 m_negative( false ),
51 m_aspectRatio( 1.0 )
52{
53 for( const wxString& unit : { _( "mm" ), _( "Inch" ), _( "DPI" ) } )
54 m_PixelUnit->Append( unit );
55
58 m_outputSizeX.SetOutputSize( 0, getUnitFromSelection() );
59 m_outputSizeY.SetOutputSize( 0, getUnitFromSelection() );
60
61 m_UnitSizeX->ChangeValue( formatOutputSize( m_outputSizeX.GetOutputSize() ) );
62 m_UnitSizeY->ChangeValue( formatOutputSize( m_outputSizeY.GetOutputSize() ) );
63
64 m_buttonExportFile->Enable( false );
65 m_buttonExportClipboard->Enable( false );
66
67 m_InitialPicturePanel->SetDropTarget( new DROP_FILE( this ) );
68 m_GreyscalePicturePanel->SetDropTarget( new DROP_FILE( this ) );
69 m_BNPicturePanel->SetDropTarget( new DROP_FILE( this ) );
70}
71
73{
74 return m_Notebook->GetCurrentPage();
75}
76
77
79{
80 if( cfg->m_Units >= 0 && cfg->m_Units < (int) m_PixelUnit->GetCount() )
81 m_PixelUnit->SetSelection( cfg->m_Units );
82
83 m_sliderThreshold->SetValue( cfg->m_Threshold );
84
86 m_checkNegative->SetValue( cfg->m_Negative );
87
88 m_aspectRatio = 1.0;
89 m_aspectRatioCheckbox->SetValue( true );
90
91 switch( cfg->m_LastFormat )
92 {
93 default:
94 case FOOTPRINT_FMT: m_rbFootprint->SetValue( true ); break;
95 case SYMBOL_FMT:
96 case SYMBOL_PASTE_FMT: m_rbSymbol->SetValue( true ); break;
97 case POSTSCRIPT_FMT: m_rbPostscript->SetValue( true ); break;
98 case DRAWING_SHEET_FMT: m_rbWorksheet->SetValue( true ); break;
99 }
100
101 m_layerLabel->Enable( cfg->m_LastFormat == FOOTPRINT_FMT );
102 m_layerCtrl->Enable( cfg->m_LastFormat == FOOTPRINT_FMT );
103
104 if( cfg->m_LastLayer >= 0 && cfg->m_LastLayer < (int) m_layerCtrl->GetCount() )
105 m_layerCtrl->SetSelection( cfg->m_LastLayer );
106}
107
108
110{
111 cfg->m_Threshold = m_sliderThreshold->GetValue();
112 cfg->m_Negative = m_checkNegative->IsChecked();
114 cfg->m_LastLayer = m_layerCtrl->GetSelection();
115 cfg->m_Units = m_PixelUnit->GetSelection();
116}
117
118
119void BITMAP2CMP_PANEL::OnPaintInit( wxPaintEvent& event )
120{
121#ifdef __WXMAC__
122 // Otherwise fails due: using wxPaintDC without being in a native paint event
123 wxClientDC pict_dc( m_InitialPicturePanel );
124#else
125 wxPaintDC pict_dc( m_InitialPicturePanel );
126#endif
127
128 m_InitialPicturePanel->PrepareDC( pict_dc );
129
130 // OSX crashes with empty bitmaps (on initial refreshes)
131 if( m_Pict_Bitmap.IsOk() )
132 pict_dc.DrawBitmap( m_Pict_Bitmap, 0, 0, !!m_Pict_Bitmap.GetMask() );
133
134 event.Skip();
135}
136
137
138void BITMAP2CMP_PANEL::OnPaintGreyscale( wxPaintEvent& event )
139{
140#ifdef __WXMAC__
141 // Otherwise fails due: using wxPaintDC without being in a native paint event
142 wxClientDC greyscale_dc( m_GreyscalePicturePanel );
143#else
144 wxPaintDC greyscale_dc( m_GreyscalePicturePanel );
145#endif
146
147 m_GreyscalePicturePanel->PrepareDC( greyscale_dc );
148
149 // OSX crashes with empty bitmaps (on initial refreshes)
150 if( m_Greyscale_Bitmap.IsOk() )
151 greyscale_dc.DrawBitmap( m_Greyscale_Bitmap, 0, 0, !!m_Greyscale_Bitmap.GetMask() );
152
153 event.Skip();
154}
155
156
157void BITMAP2CMP_PANEL::OnPaintBW( wxPaintEvent& event )
158{
159#ifdef __WXMAC__
160 // Otherwise fails due: using wxPaintDC without being in a native paint event
161 wxClientDC nb_dc( m_BNPicturePanel );
162#else
163 wxPaintDC nb_dc( m_BNPicturePanel );
164#endif
165
166 m_BNPicturePanel->PrepareDC( nb_dc );
167
168 if( m_BN_Bitmap.IsOk() )
169 nb_dc.DrawBitmap( m_BN_Bitmap, 0, 0, !!m_BN_Bitmap.GetMask() );
170
171 event.Skip();
172}
173
174
175void BITMAP2CMP_PANEL::OnLoadFile( wxCommandEvent& event )
176{
177 m_parentFrame->OnLoadFile();
178}
179
180
181bool BITMAP2CMP_PANEL::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl )
182{
183 m_Pict_Image.Destroy();
184
185 if( !m_Pict_Image.LoadFile( aFileSet[0] ) )
186 {
187 // LoadFile has its own UI, no need for further failure notification here
188 return false;
189 }
190
191 m_Pict_Bitmap = wxBitmap( m_Pict_Image );
192
193 // Determine image resolution in DPI (does not existing in all formats).
194 // the resolution can be given in bit per inches or bit per cm in file
195
196 int imageDPIx = m_Pict_Image.GetOptionInt( wxIMAGE_OPTION_RESOLUTIONX );
197 int imageDPIy = m_Pict_Image.GetOptionInt( wxIMAGE_OPTION_RESOLUTIONY );
198
199 if( imageDPIx > 1 && imageDPIy > 1 )
200 {
201 if( m_Pict_Image.GetOptionInt( wxIMAGE_OPTION_RESOLUTIONUNIT ) == wxIMAGE_RESOLUTION_CM )
202 {
203 imageDPIx = KiROUND( imageDPIx * 2.54 );
204 imageDPIy = KiROUND( imageDPIy * 2.54 );
205 }
206 }
207 else // fallback to a default value (DEFAULT_DPI)
208 {
209 imageDPIx = imageDPIy = DEFAULT_DPI;
210 }
211
212 m_InputXValueDPI->SetLabel( wxString::Format( wxT( "%d" ), imageDPIx ) );
213 m_InputYValueDPI->SetLabel( wxString::Format( wxT( "%d" ), imageDPIy ) );
214
215 int h = m_Pict_Bitmap.GetHeight();
216 int w = m_Pict_Bitmap.GetWidth();
217 m_aspectRatio = (double) w / h;
218
219 m_outputSizeX.SetOriginalDPI( imageDPIx );
220 m_outputSizeX.SetOriginalSizePixels( w );
221 m_outputSizeY.SetOriginalDPI( imageDPIy );
222 m_outputSizeY.SetOriginalSizePixels( h );
223
224 // Update display to keep aspect ratio
225 wxCommandEvent dummy;
227
229
230 m_InitialPicturePanel->SetVirtualSize( w, h );
231 m_GreyscalePicturePanel->SetVirtualSize( w, h );
232 m_BNPicturePanel->SetVirtualSize( w, h );
233
234 m_Greyscale_Image.Destroy();
235 m_Greyscale_Image = m_Pict_Image.ConvertToGreyscale( );
236
237 if( m_Pict_Bitmap.GetMask() )
238 {
239 for( int x = 0; x < m_Pict_Bitmap.GetWidth(); x++ )
240 {
241 for( int y = 0; y < m_Pict_Bitmap.GetHeight(); y++ )
242 {
243 if( m_Pict_Image.GetRed( x, y ) == m_Pict_Image.GetMaskRed()
244 && m_Pict_Image.GetGreen( x, y ) == m_Pict_Image.GetMaskGreen()
245 && m_Pict_Image.GetBlue( x, y ) == m_Pict_Image.GetMaskBlue() )
246 {
247 m_Greyscale_Image.SetRGB( x, y, 255, 255, 255 );
248 }
249 }
250 }
251 }
252
253 if( m_negative )
255
258 binarize( (double)m_sliderThreshold->GetValue() / m_sliderThreshold->GetMax() );
259
260 m_buttonExportFile->Enable( true );
261 m_buttonExportClipboard->Enable( true );
262
263 m_outputSizeX.SetOutputSizeFromInitialImageSize();
264 m_UnitSizeX->ChangeValue( formatOutputSize( m_outputSizeX.GetOutputSize() ) );
265 m_outputSizeY.SetOutputSizeFromInitialImageSize();
266 m_UnitSizeY->ChangeValue( formatOutputSize( m_outputSizeY.GetOutputSize() ) );
267
268 return true;
269}
270
271
272// return a string giving the output size, according to the selected unit
274{
275 wxString text;
276
278 text.Printf( wxS( "%.1f" ), aSize );
280 text.Printf( wxS( "%.2f" ), aSize );
281 else
282 text.Printf( wxT( "%d" ), KiROUND( aSize ) );
283
284 return text;
285}
286
288{
289 // Note: the image resolution text controls are not modified here, to avoid a race between
290 // text change when entered by user and a text change if it is modified here.
291
292 if( m_Pict_Bitmap.IsOk() )
293 {
294 m_SizeXValue->SetLabel( wxString::Format( wxT( "%d" ), m_Pict_Bitmap.GetWidth() ) );
295 m_SizeYValue->SetLabel( wxString::Format( wxT( "%d" ), m_Pict_Bitmap.GetHeight() ) );
296 m_BPPValue->SetLabel( wxString::Format( wxT( "%d" ), m_Pict_Bitmap.GetDepth() ) );
297 }
298}
299
300
302{
303 // return the EDA_UNITS from the m_PixelUnit choice
304 switch( m_PixelUnit->GetSelection() )
305 {
306 case 1: return EDA_UNITS::INCH;
307 case 2: return EDA_UNITS::UNSCALED;
308 case 0:
309 default: return EDA_UNITS::MM;
310 }
311}
312
313
314void BITMAP2CMP_PANEL::OnSizeChangeX( wxCommandEvent& event )
315{
316 double new_size;
317
318 if( m_UnitSizeX->GetValue().ToDouble( &new_size ) )
319 {
320 if( m_aspectRatioCheckbox->GetValue() )
321 {
322 double calculatedY = new_size / m_aspectRatio;
323
325 {
326 // for units in DPI, keeping aspect ratio cannot use m_AspectRatioLocked.
327 // just re-scale the other dpi
328 double ratio = new_size / m_outputSizeX.GetOutputSize();
329 calculatedY = m_outputSizeY.GetOutputSize() * ratio;
330 }
331
332 m_outputSizeY.SetOutputSize( calculatedY, getUnitFromSelection() );
333 m_UnitSizeY->ChangeValue( formatOutputSize( m_outputSizeY.GetOutputSize() ) );
334 }
335
336 m_outputSizeX.SetOutputSize( new_size, getUnitFromSelection() );
337 }
338
340}
341
342
343void BITMAP2CMP_PANEL::OnSizeChangeY( wxCommandEvent& event )
344{
345 double new_size;
346
347 if( m_UnitSizeY->GetValue().ToDouble( &new_size ) )
348 {
349 if( m_aspectRatioCheckbox->GetValue() )
350 {
351 double calculatedX = new_size * m_aspectRatio;
352
354 {
355 // for units in DPI, keeping aspect ratio cannot use m_AspectRatioLocked.
356 // just re-scale the other dpi
357 double ratio = new_size / m_outputSizeX.GetOutputSize();
358 calculatedX = m_outputSizeX.GetOutputSize() * ratio;
359 }
360
361 m_outputSizeX.SetOutputSize( calculatedX, getUnitFromSelection() );
362 m_UnitSizeX->ChangeValue( formatOutputSize( m_outputSizeX.GetOutputSize() ) );
363 }
364
365 m_outputSizeY.SetOutputSize( new_size, getUnitFromSelection() );
366 }
367
369}
370
371
372void BITMAP2CMP_PANEL::OnSizeUnitChange( wxCommandEvent& event )
373{
377
378 m_UnitSizeX->ChangeValue( formatOutputSize( m_outputSizeX.GetOutputSize() ) );
379 m_UnitSizeY->ChangeValue( formatOutputSize( m_outputSizeY.GetOutputSize() ) );
380}
381
382
383void BITMAP2CMP_PANEL::SetOutputSize( const IMAGE_SIZE& aSizeX, const IMAGE_SIZE& aSizeY )
384{
385 m_outputSizeX = aSizeX;
386 m_outputSizeY = aSizeY;
388
389 m_UnitSizeX->ChangeValue( formatOutputSize( m_outputSizeX.GetOutputSize() ) );
390 m_UnitSizeY->ChangeValue( formatOutputSize( m_outputSizeY.GetOutputSize() ) );
391}
392
393
394void BITMAP2CMP_PANEL::ToggleAspectRatioLock( wxCommandEvent& event )
395{
396 if( m_aspectRatioCheckbox->GetValue() )
397 {
398 // Force display update when aspect ratio is locked
399 wxCommandEvent dummy;
401 }
402}
403
404
405void BITMAP2CMP_PANEL::binarize( double aThreshold )
406{
407 unsigned char threshold = aThreshold * 255;
408 unsigned char alpha_thresh = 0.7 * threshold;
409
410 for( int y = 0; y < m_Greyscale_Image.GetHeight(); y++ )
411 {
412 for( int x = 0; x < m_Greyscale_Image.GetWidth(); x++ )
413 {
414 unsigned char pixel = m_Greyscale_Image.GetGreen( x, y );
415 unsigned char alpha = m_Greyscale_Image.HasAlpha() ? m_Greyscale_Image.GetAlpha( x, y )
416 : wxALPHA_OPAQUE;
417
418 if( pixel < threshold && alpha > alpha_thresh )
419 pixel = 0;
420 else
421 pixel = 255;
422
423 m_NB_Image.SetRGB( x, y, pixel, pixel, pixel );
424 }
425 }
426
427 m_BN_Bitmap = wxBitmap( m_NB_Image );
428}
429
430
432{
433 for( int y = 0; y < m_Greyscale_Image.GetHeight(); y++ )
434 {
435 for( int x = 0; x < m_Greyscale_Image.GetWidth(); x++ )
436 {
437 unsigned char pixel = m_Greyscale_Image.GetGreen( x, y );
438 pixel = ~pixel;
439 m_Greyscale_Image.SetRGB( x, y, pixel, pixel, pixel );
440 }
441 }
442}
443
444
446{
447 if( m_checkNegative->GetValue() != m_negative )
448 {
450
452 binarize( (double)m_sliderThreshold->GetValue() / m_sliderThreshold->GetMax() );
453 m_negative = m_checkNegative->GetValue();
454
455 Refresh();
456 }
457}
458
459
460void BITMAP2CMP_PANEL::OnThresholdChange( wxScrollEvent& event )
461{
462 binarize( (double)m_sliderThreshold->GetValue() / m_sliderThreshold->GetMax() );
463 Refresh();
464}
465
466
467void BITMAP2CMP_PANEL::OnExportToFile( wxCommandEvent& event )
468{
469 switch( getOutputFormat() )
470 {
471 case SYMBOL_FMT:
472 case SYMBOL_PASTE_FMT: m_parentFrame->ExportEeschemaFormat(); break;
473 case FOOTPRINT_FMT: m_parentFrame->ExportPcbnewFormat(); break;
474 case POSTSCRIPT_FMT: m_parentFrame->ExportPostScriptFormat(); break;
475 case DRAWING_SHEET_FMT: m_parentFrame->ExportDrawingSheetFormat(); break;
476 }
477}
478
479
481{
482 if( m_rbSymbol->GetValue() )
483 return SYMBOL_FMT;
484 else if( m_rbPostscript->GetValue() )
485 return POSTSCRIPT_FMT;
486 else if( m_rbWorksheet->GetValue() )
487 return DRAWING_SHEET_FMT;
488 else
489 return FOOTPRINT_FMT;
490}
491
492
493void BITMAP2CMP_PANEL::OnExportToClipboard( wxCommandEvent& event )
494{
495 std::string buffer;
497 ExportToBuffer( buffer, format );
498
499 wxLogNull doNotLog; // disable logging of failed clipboard actions
500
501 // Write buffer to the clipboard
502 if( wxTheClipboard->Open() )
503 {
504 // This data objects are held by the clipboard,
505 // so do not delete them in the app.
506 wxTheClipboard->SetData( new wxTextDataObject( buffer.c_str() ) );
507 wxTheClipboard->Flush(); // Allow data to be available after closing KiCad
508 wxTheClipboard->Close();
509 }
510 else
511 {
512 wxMessageBox( _( "Unable to export to the Clipboard") );
513 }
514}
515
516
517void BITMAP2CMP_PANEL::ExportToBuffer( std::string& aOutput, OUTPUT_FMT_ID aFormat )
518{
519 // Create a potrace bitmap
520 potrace_bitmap_t* potrace_bitmap = bm_new( m_NB_Image.GetWidth(), m_NB_Image.GetHeight() );
521
522 if( !potrace_bitmap )
523 {
524 wxMessageBox( _( "Error allocating memory for potrace bitmap" ) );
525 return;
526 }
527
528 /* fill the bitmap with data */
529 for( int y = 0; y < m_NB_Image.GetHeight(); y++ )
530 {
531 for( int x = 0; x < m_NB_Image.GetWidth(); x++ )
532 {
533 unsigned char pixel = m_NB_Image.GetGreen( x, y );
534 BM_PUT( potrace_bitmap, x, y, pixel ? 0 : 1 );
535 }
536 }
537
538 wxString layer = wxT( "F.SilkS" );
539
540 if( aFormat == FOOTPRINT_FMT )
541 {
542 switch( m_layerCtrl->GetSelection() )
543 {
544 case 0: layer = wxT( "F.Cu" ); break;
545 case 1: layer = wxT( "F.SilkS" ); break;
546 case 2: layer = wxT( "F.Mask" ); break;
547 case 3: layer = wxT( "Dwgs.User" ); break;
548 case 4: layer = wxT( "Cmts.User" ); break;
549 case 5: layer = wxT( "Eco1.User" ); break;
550 case 6: layer = wxT( "Eco2.User" ); break;
551 case 7: layer = wxT( "F.Fab" ); break;
552 }
553 }
554
555
556
557 WX_STRING_REPORTER reporter;
558 BITMAPCONV_INFO converter( aOutput, reporter );
559
560 converter.ConvertBitmap( potrace_bitmap, aFormat, m_outputSizeX.GetOutputDPI(),
561 m_outputSizeY.GetOutputDPI(), layer );
562
563 if( reporter.HasMessage() )
564 wxMessageBox( reporter.GetMessages(), _( "Errors" ) );
565}
566
567
568void BITMAP2CMP_PANEL::OnFormatChange( wxCommandEvent& event )
569{
570 m_layerLabel->Enable( m_rbFootprint->GetValue() );
571 m_layerCtrl->Enable( m_rbFootprint->GetValue() );
572}
573
574
576 m_panel( panel )
577{
578}
579
580
581bool DROP_FILE::OnDropFiles( wxCoord x, wxCoord y, const wxArrayString& filenames )
582{
583 m_panel->SetFocus();
584
585 // If a file is already loaded
586 if( m_panel->GetOutputSizeX().GetOriginalSizePixels() != 0 )
587 {
588 wxString cap = _( "Replace Loaded File?" );
589 wxString msg = _( "There is already a file loaded. Do you want to replace it?" );
590 KICAD_MESSAGE_DIALOG acceptFileDlg( m_panel, msg, cap, wxYES_NO | wxICON_QUESTION | wxYES_DEFAULT );
591 int replace = acceptFileDlg.ShowModal();
592
593 if( replace == wxID_NO )
594 return false;
595 }
596
597 std::vector<wxString> fNameVec;
598 fNameVec.insert( fNameVec.begin(), filenames.begin(), filenames.end() );
599 m_panel->OpenProjectFiles( fNameVec );
600
601 return true;
602}
#define DEFAULT_DPI
OUTPUT_FMT_ID
@ DRAWING_SHEET_FMT
@ SYMBOL_FMT
@ SYMBOL_PASTE_FMT
@ POSTSCRIPT_FMT
@ FOOTPRINT_FMT
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:990
wxScrolledWindow * m_GreyscalePicturePanel
wxScrolledWindow * m_BNPicturePanel
BITMAP2CMP_PANEL_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxTAB_TRAVERSAL, const wxString &name=wxEmptyString)
wxScrolledWindow * m_InitialPicturePanel
void OnPaintGreyscale(wxPaintEvent &event) override
void binarize(double aThreshold)
void SetOutputSize(const IMAGE_SIZE &aSizeX, const IMAGE_SIZE &aSizeY)
void OnSizeUnitChange(wxCommandEvent &event) override
void OnSizeChangeX(wxCommandEvent &event) override
void OnPaintInit(wxPaintEvent &event) override
void OnExportToClipboard(wxCommandEvent &event) override
void LoadSettings(BITMAP2CMP_SETTINGS *aCfg)
void ToggleAspectRatioLock(wxCommandEvent &event) override
bool OpenProjectFiles(const std::vector< wxString > &aFilenames, int aCtl=0)
wxWindow * GetCurrentPage()
BITMAP2CMP_PANEL(BITMAP2CMP_FRAME *aParent)
void OnExportToFile(wxCommandEvent &event) override
void SaveSettings(BITMAP2CMP_SETTINGS *aCfg)
wxString formatOutputSize(double aSize)
void OnThresholdChange(wxScrollEvent &event) override
void ExportToBuffer(std::string &aOutput, OUTPUT_FMT_ID aFormat)
generate a export data of the current bitmap.
BITMAP2CMP_FRAME * m_parentFrame
void OnFormatChange(wxCommandEvent &event) override
void OnLoadFile(wxCommandEvent &event) override
EDA_UNITS getUnitFromSelection()
void OnNegativeClicked(wxCommandEvent &event) override
void OnPaintBW(wxPaintEvent &event) override
OUTPUT_FMT_ID getOutputFormat()
void OnSizeChangeY(wxCommandEvent &event) override
int ConvertBitmap(potrace_bitmap_t *aPotrace_bitmap, OUTPUT_FMT_ID aFormat, int aDpi_X, int aDpi_Y, const wxString &aLayer)
Run the conversion of the bitmap.
BITMAP2CMP_PANEL * m_panel
DROP_FILE()=delete
bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &filenames) override
virtual bool HasMessage() const
Returns true if any messages were reported.
Definition reporter.h:134
A wrapper for reporting to a wxString object.
Definition reporter.h:191
const wxString & GetMessages() const
Definition reporter.cpp:78
The common library.
This file is part of the common library.
#define KICAD_MESSAGE_DIALOG
Definition confirm.h:52
#define _(s)
EDA_UNITS
Definition eda_units.h:48
void Refresh()
Update the board display after modifying it by a python script (note: it is automatically called by a...
std::vector< FAB_LAYER_COLOR > dummy