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