367 lines
12 KiB
C++
367 lines
12 KiB
C++
/*
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
*
|
|
* Copyright (C) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
|
* Copyright (C) 2013 Dick Hollenbeck, [email protected]
|
|
* Copyright (C) 2008-2013 Wayne Stambaugh <[email protected]>
|
|
* Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, you may find one here:
|
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
|
* or you may write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#include <core/type_helpers.h>
|
|
#include <base_units.h>
|
|
#include <bitmaps.h>
|
|
#include <board_commit.h>
|
|
#include <pcb_barcode.h>
|
|
#include <pcb_text.h>
|
|
#include <layer_ids.h>
|
|
#include <math/util.h>
|
|
#include <dialog_barcode_properties.h>
|
|
#include <pcb_base_frame.h>
|
|
#include <pcb_base_edit_frame.h>
|
|
#include <pcb_painter.h>
|
|
#include <pcbnew_settings.h>
|
|
#include <settings/color_settings.h>
|
|
#include <tool/tool_manager.h>
|
|
#include <view/view_controls.h>
|
|
#include <gal/graphics_abstraction_layer.h>
|
|
#include <pcb_layer_box_selector.h>
|
|
#include <wx/msgdlg.h>
|
|
// For BOX2D viewport checks
|
|
#include <math/box2.h>
|
|
|
|
|
|
DIALOG_BARCODE_PROPERTIES::DIALOG_BARCODE_PROPERTIES( PCB_BASE_FRAME* aParent, PCB_BARCODE* aBarcode ) :
|
|
DIALOG_BARCODE_PROPERTIES_BASE( aParent ),
|
|
m_parent( aParent ),
|
|
m_posX( aParent, m_posXLabel, m_posXCtrl, m_posXUnits ),
|
|
m_posY( aParent, m_posYLabel, m_posYCtrl, m_posYUnits ),
|
|
m_sizeX( aParent, m_sizeXLabel, m_sizeXCtrl, m_sizeXUnits ),
|
|
m_sizeY( aParent, m_sizeYLabel, m_sizeYCtrl, m_sizeYUnits ),
|
|
m_textSize( aParent, m_textSizeLabel, m_textSizeCtrl, m_textSizeUnits ),
|
|
m_orientation( aParent, m_orientationLabel, m_orientationCtrl, m_orientationUnits ),
|
|
m_knockoutMarginX( aParent, m_marginXLabel, m_marginXCtrl, m_marginXUnits ),
|
|
m_knockoutMarginY( aParent, m_marginYLabel, m_marginYCtrl, m_marginYUnits )
|
|
{
|
|
m_currentBarcode = aBarcode; // aBarcode can not be NULL (no FOOTPRINT editor?)
|
|
|
|
m_board = m_parent->GetBoard();
|
|
|
|
// Use the board as parent so text variables like ${PART_NUMBER} can be resolved
|
|
// in the preview. The dummy barcode is not actually added to the board.
|
|
m_dummyBarcode = new PCB_BARCODE( m_board );
|
|
|
|
// Initialize canvas to be able to display the dummy barcode:
|
|
prepareCanvas();
|
|
|
|
m_sdbSizerOK->SetDefault();
|
|
}
|
|
|
|
|
|
DIALOG_BARCODE_PROPERTIES::~DIALOG_BARCODE_PROPERTIES()
|
|
{
|
|
delete m_dummyBarcode;
|
|
}
|
|
|
|
|
|
void DIALOG_BARCODE_PROPERTIES::OnCancel( wxCommandEvent& event )
|
|
{
|
|
// Mandatory to avoid m_panelShowPadGal trying to draw something
|
|
// in a non valid context during closing process:
|
|
m_panelShowBarcodeGal->StopDrawing();
|
|
|
|
// Now call default handler for wxID_CANCEL command event
|
|
event.Skip();
|
|
}
|
|
|
|
|
|
void DIALOG_BARCODE_PROPERTIES::prepareCanvas()
|
|
{
|
|
// Initialize the canvas to display the barcode
|
|
|
|
m_panelShowBarcodeGal->UpdateColors();
|
|
m_panelShowBarcodeGal->SwitchBackend( m_parent->GetCanvas()->GetBackend() );
|
|
m_panelShowBarcodeGal->SetStealsFocus( false );
|
|
|
|
m_panelShowBarcodeGal->Show();
|
|
|
|
KIGFX::VIEW* view = m_panelShowBarcodeGal->GetView();
|
|
|
|
// gives a non null grid size (0.001mm) because GAL layer does not like a 0 size grid:
|
|
double gridsize = pcbIUScale.mmToIU( 0.001 );
|
|
view->GetGAL()->SetGridSize( VECTOR2D( gridsize, gridsize ) );
|
|
// And do not show the grid:
|
|
view->GetGAL()->SetGridVisibility( false );
|
|
view->Add( m_dummyBarcode );
|
|
|
|
m_panelShowBarcodeGal->StartDrawing();
|
|
Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_BARCODE_PROPERTIES::OnResize ) );
|
|
}
|
|
|
|
|
|
void DIALOG_BARCODE_PROPERTIES::initValues()
|
|
{
|
|
// Copy current barcode into our working copy
|
|
if( m_currentBarcode )
|
|
*m_dummyBarcode = *m_currentBarcode;
|
|
|
|
m_dummyBarcode->AssembleBarcode();
|
|
|
|
m_orientation.SetUnits( EDA_UNITS::DEGREES );
|
|
|
|
// Configure the layers list selector. Note that footprints are built outside the current
|
|
// board and so we may need to show all layers if the barcode is on an unactivated layer.
|
|
if( !m_parent->GetBoard()->IsLayerEnabled( m_dummyBarcode->GetLayer() ) )
|
|
m_cbLayer->ShowNonActivatedLayers( true );
|
|
|
|
m_cbLayer->SetLayersHotkeys( false );
|
|
m_cbLayer->SetBoardFrame( m_parent );
|
|
m_cbLayer->Resync();
|
|
}
|
|
|
|
|
|
void DIALOG_BARCODE_PROPERTIES::OnResize( wxSizeEvent& event )
|
|
{
|
|
m_panelShowBarcodeGal->Refresh();
|
|
event.Skip();
|
|
}
|
|
|
|
|
|
void DIALOG_BARCODE_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
|
|
{
|
|
// Error correction options are only meaningful for QR codes
|
|
bool enableEC = m_barcode->GetSelection() >= to_underlying( BARCODE_T::QR_CODE );
|
|
m_errorCorrection->Enable( enableEC );
|
|
|
|
m_textSize.Enable( m_cbShowText->GetValue() );
|
|
|
|
m_knockoutMarginX.Enable( m_cbKnockout->GetValue() );
|
|
m_knockoutMarginY.Enable( m_cbKnockout->GetValue() );
|
|
|
|
if( enableEC )
|
|
{
|
|
// Micro QR codes do not support High (H) error correction level
|
|
bool isMicroQR = ( m_barcode->GetSelection() == to_underlying( BARCODE_T::MICRO_QR_CODE ) );
|
|
|
|
// Enable/disable the High option (index 3)
|
|
m_errorCorrection->Enable( 3, !isMicroQR );
|
|
|
|
// If currently High is selected and we switched to Micro QR, change to a valid option
|
|
if( isMicroQR && m_errorCorrection->GetSelection() == 3 )
|
|
{
|
|
m_errorCorrection->SetSelection( 2 ); // Default to Q (Quartile), consistent with SetErrorCorrection
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
bool DIALOG_BARCODE_PROPERTIES::TransferDataToWindow()
|
|
{
|
|
initValues();
|
|
|
|
if( m_currentBarcode )
|
|
*m_dummyBarcode = *m_currentBarcode;
|
|
|
|
m_textInput->ChangeValue( m_dummyBarcode->GetText() );
|
|
m_cbLocked->SetValue( m_dummyBarcode->IsLocked() );
|
|
m_cbLayer->SetLayerSelection( m_dummyBarcode->GetLayer() );
|
|
|
|
// Position
|
|
m_posX.ChangeValue( m_dummyBarcode->GetPosition().x );
|
|
m_posY.ChangeValue( m_dummyBarcode->GetPosition().y );
|
|
|
|
// Size
|
|
m_sizeX.ChangeValue( m_dummyBarcode->GetWidth() );
|
|
m_sizeY.ChangeValue( m_dummyBarcode->GetHeight() );
|
|
m_textSize.ChangeValue( m_dummyBarcode->GetTextSize() );
|
|
|
|
// Orientation
|
|
m_orientation.ChangeAngleValue( m_dummyBarcode->GetAngle() );
|
|
|
|
// Show text option
|
|
m_cbShowText->SetValue( m_dummyBarcode->Text().IsVisible() );
|
|
|
|
m_cbKnockout->SetValue( m_dummyBarcode->IsKnockout() );
|
|
m_knockoutMarginX.ChangeValue( m_dummyBarcode->GetMargin().x );
|
|
m_knockoutMarginY.ChangeValue( m_dummyBarcode->GetMargin().y );
|
|
|
|
// Barcode type
|
|
switch( m_dummyBarcode->GetKind() )
|
|
{
|
|
case BARCODE_T::CODE_39: m_barcode->SetSelection( 0 ); break;
|
|
case BARCODE_T::CODE_128: m_barcode->SetSelection( 1 ); break;
|
|
case BARCODE_T::DATA_MATRIX: m_barcode->SetSelection( 2 ); break;
|
|
case BARCODE_T::QR_CODE: m_barcode->SetSelection( 3 ); break;
|
|
case BARCODE_T::MICRO_QR_CODE: m_barcode->SetSelection( 4 ); break;
|
|
default: m_barcode->SetSelection( 0 ); break;
|
|
}
|
|
|
|
// Error correction level
|
|
switch( m_dummyBarcode->GetErrorCorrection() )
|
|
{
|
|
case BARCODE_ECC_T::L: m_errorCorrection->SetSelection( 0 ); break;
|
|
case BARCODE_ECC_T::M: m_errorCorrection->SetSelection( 1 ); break;
|
|
case BARCODE_ECC_T::Q: m_errorCorrection->SetSelection( 2 ); break;
|
|
case BARCODE_ECC_T::H: m_errorCorrection->SetSelection( 3 ); break;
|
|
default: m_errorCorrection->SetSelection( 0 ); break;
|
|
}
|
|
|
|
// Now all widgets have the size fixed, call finishDialogSettings
|
|
finishDialogSettings();
|
|
|
|
refreshPreview();
|
|
|
|
wxUpdateUIEvent dummy;
|
|
OnUpdateUI( dummy );
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool DIALOG_BARCODE_PROPERTIES::TransferDataFromWindow()
|
|
{
|
|
transferDataToBarcode( m_dummyBarcode );
|
|
|
|
if( !m_dummyBarcode->GetText().empty() && m_dummyBarcode->GetSymbolPoly().OutlineCount() == 0 )
|
|
{
|
|
wxMessageBox( m_dummyBarcode->GetLastError(), _( "Barcode Error" ), wxOK | wxICON_ERROR, this );
|
|
return false;
|
|
}
|
|
|
|
BOARD_COMMIT commit( m_parent );
|
|
commit.Modify( m_currentBarcode );
|
|
|
|
if( !transferDataToBarcode( m_currentBarcode ) )
|
|
return false;
|
|
|
|
m_parent->GetCanvas()->Refresh();
|
|
|
|
commit.Push( _( "Modify barcode" ) );
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool DIALOG_BARCODE_PROPERTIES::transferDataToBarcode( PCB_BARCODE* aBarcode )
|
|
{
|
|
if( !aBarcode )
|
|
return false;
|
|
|
|
aBarcode->SetText( m_textInput->GetValue() );
|
|
aBarcode->SetLocked( m_cbLocked->GetValue() );
|
|
aBarcode->SetLayer( ToLAYER_ID( m_cbLayer->GetLayerSelection() ) );
|
|
|
|
// Position
|
|
aBarcode->SetPosition( VECTOR2I( m_posX.GetIntValue(), m_posY.GetIntValue() ) );
|
|
|
|
// Size
|
|
aBarcode->SetWidth( m_sizeX.GetIntValue() );
|
|
aBarcode->SetHeight( m_sizeY.GetIntValue() );
|
|
aBarcode->SetTextSize( m_textSize.GetIntValue() );
|
|
|
|
// Orientation
|
|
EDA_ANGLE oldAngle = aBarcode->GetAngle();
|
|
EDA_ANGLE newAngle = m_orientation.GetAngleValue();
|
|
|
|
if( newAngle != oldAngle )
|
|
aBarcode->Rotate( aBarcode->GetPosition(), newAngle - oldAngle );
|
|
|
|
// Knockout
|
|
aBarcode->SetIsKnockout( m_cbKnockout->GetValue() );
|
|
aBarcode->SetMargin( VECTOR2I( m_knockoutMarginX.GetIntValue(), m_knockoutMarginY.GetIntValue() ) );
|
|
|
|
// Show text
|
|
aBarcode->Text().SetVisible( m_cbShowText->GetValue() );
|
|
|
|
// Barcode kind
|
|
switch( m_barcode->GetSelection() )
|
|
{
|
|
case 0: aBarcode->SetKind( BARCODE_T::CODE_39 ); break;
|
|
case 1: aBarcode->SetKind( BARCODE_T::CODE_128 ); break;
|
|
case 2: aBarcode->SetKind( BARCODE_T::DATA_MATRIX ); break;
|
|
case 3: aBarcode->SetKind( BARCODE_T::QR_CODE ); break;
|
|
case 4: aBarcode->SetKind( BARCODE_T::MICRO_QR_CODE ); break;
|
|
default: aBarcode->SetKind( BARCODE_T::QR_CODE ); break;
|
|
}
|
|
|
|
switch( m_errorCorrection->GetSelection() )
|
|
{
|
|
case 0: aBarcode->SetErrorCorrection( BARCODE_ECC_T::L ); break;
|
|
case 1: aBarcode->SetErrorCorrection( BARCODE_ECC_T::M ); break;
|
|
case 2: aBarcode->SetErrorCorrection( BARCODE_ECC_T::Q ); break;
|
|
case 3: aBarcode->SetErrorCorrection( BARCODE_ECC_T::H ); break;
|
|
default: aBarcode->SetErrorCorrection( BARCODE_ECC_T::L ); break;
|
|
}
|
|
|
|
aBarcode->AssembleBarcode();
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void DIALOG_BARCODE_PROPERTIES::refreshPreview()
|
|
{
|
|
KIGFX::VIEW* view = m_panelShowBarcodeGal->GetView();
|
|
|
|
// Compute the polygon bbox for the current dummy barcode (symbol + text/knockout as applicable)
|
|
const SHAPE_POLY_SET& poly = m_dummyBarcode->GetPolyShape();
|
|
|
|
if( poly.OutlineCount() > 0 )
|
|
{
|
|
BOX2I bbI = poly.BBox();
|
|
|
|
// Autozoom
|
|
view->SetViewport( BOX2D( bbI.GetOrigin(), bbI.GetSize() ) );
|
|
|
|
// Add a margin
|
|
view->SetScale( view->GetScale() * 0.7 );
|
|
}
|
|
|
|
view->SetCenter( VECTOR2D( m_dummyBarcode->GetPosition() ) );
|
|
view->Update( m_dummyBarcode );
|
|
m_panelShowBarcodeGal->Refresh();
|
|
}
|
|
|
|
|
|
void DIALOG_BARCODE_PROPERTIES::OnValuesChanged( wxCommandEvent& event )
|
|
{
|
|
if( transferDataToBarcode( m_dummyBarcode ) )
|
|
{
|
|
refreshPreview();
|
|
OnModify();
|
|
}
|
|
}
|
|
|
|
|
|
void DIALOG_BARCODE_PROPERTIES::OnTextValueChanged( wxKeyEvent& event )
|
|
{
|
|
if( transferDataToBarcode( m_dummyBarcode ) )
|
|
{
|
|
refreshPreview();
|
|
OnModify();
|
|
}
|
|
}
|
|
|
|
|
|
void PCB_BASE_EDIT_FRAME::ShowBarcodePropertiesDialog( PCB_BARCODE* aBarcode )
|
|
{
|
|
DIALOG_BARCODE_PROPERTIES dlg( this, aBarcode );
|
|
dlg.ShowModal();
|
|
}
|