summaryrefslogtreecommitdiff
path: root/pcbnew/dimension.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'pcbnew/dimension.cpp')
-rw-r--r--pcbnew/dimension.cpp466
1 files changed, 466 insertions, 0 deletions
diff --git a/pcbnew/dimension.cpp b/pcbnew/dimension.cpp
new file mode 100644
index 0000000..db08445
--- /dev/null
+++ b/pcbnew/dimension.cpp
@@ -0,0 +1,466 @@
+/**
+ * @file dimension.cpp
+ * @brief Dialog and code for editing a dimension object.
+ */
+
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
+ * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
+ * Copyright (C) 1992-2015 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 <fctsys.h>
+#include <confirm.h>
+#include <gr_basic.h>
+#include <class_drawpanel.h>
+#include <wxPcbStruct.h>
+#include <drawtxt.h>
+#include <dialog_helpers.h>
+#include <macros.h>
+#include <base_units.h>
+
+#include <class_board.h>
+#include <class_pcb_text.h>
+#include <class_dimension.h>
+
+#include <pcbnew.h>
+#include <dialog_dimension_editor_base.h>
+#include <class_pcb_layer_box_selector.h>
+
+/* Local functions */
+static void BuildDimension( EDA_DRAW_PANEL* aPanel, wxDC* aDC,
+ const wxPoint& aPosition, bool aErase );
+
+static void MoveDimensionText( EDA_DRAW_PANEL* aPanel, wxDC* aDC,
+ const wxPoint& aPosition, bool aErase );
+static void AbortMoveDimensionText( EDA_DRAW_PANEL* aPanel, wxDC* aDC );
+
+
+/* Local variables : */
+static int status_dimension; /* Used in dimension creation:
+ * = 0 : initial value: no dimension in progress
+ * = 1 : First point created
+ * = 2 : Second point created, the text must be placed */
+
+/*
+ * A dimension has this shape:
+ * It has 2 reference points, and a text
+ * | |
+ * | dist |
+ * |<---------->|
+ * | |
+ *
+ */
+
+
+/*********************************/
+/* class DIALOG_DIMENSION_EDITOR */
+/*********************************/
+
+class DIALOG_DIMENSION_EDITOR : public DIALOG_DIMENSION_EDITOR_BASE
+{
+private:
+
+ PCB_EDIT_FRAME* m_Parent;
+ wxDC* m_DC;
+ DIMENSION* CurrentDimension;
+
+public:
+
+ // Constructor and destructor
+ DIALOG_DIMENSION_EDITOR( PCB_EDIT_FRAME* aParent, DIMENSION* aDimension, wxDC* aDC );
+ ~DIALOG_DIMENSION_EDITOR()
+ {
+ }
+
+
+private:
+ void OnCancelClick( wxCommandEvent& event );
+ void OnOKClick( wxCommandEvent& event );
+};
+
+
+DIALOG_DIMENSION_EDITOR::DIALOG_DIMENSION_EDITOR( PCB_EDIT_FRAME* aParent,
+ DIMENSION* aDimension, wxDC* aDC ) :
+ DIALOG_DIMENSION_EDITOR_BASE( aParent )
+{
+ SetFocus();
+
+ m_Parent = aParent;
+ m_DC = aDC;
+
+ CurrentDimension = aDimension;
+
+ if( aDimension->Text().IsMirrored() )
+ m_rbMirror->SetSelection( 1 );
+ else
+ m_rbMirror->SetSelection( 0 );
+
+ m_Name->SetValue( aDimension->Text().GetText() );
+
+ // Enter size value in dialog
+ PutValueInLocalUnits( *m_TxtSizeXCtrl, aDimension->Text().GetSize().x );
+ AddUnitSymbol( *m_staticTextSizeX );
+ PutValueInLocalUnits( *m_TxtSizeYCtrl, aDimension->Text().GetSize().y );
+ AddUnitSymbol( *m_staticTextSizeY );
+
+ // Enter lines thickness value in dialog
+ PutValueInLocalUnits( *m_TxtWidthCtrl, aDimension->GetWidth() );
+ AddUnitSymbol( *m_staticTextWidth );
+
+ // Enter position value in dialog
+ PutValueInLocalUnits( *m_textCtrlPosX, aDimension->Text().GetTextPosition().x );
+ AddUnitSymbol( *m_staticTextPosX );
+ PutValueInLocalUnits( *m_textCtrlPosY, aDimension->Text().GetTextPosition().y );
+ AddUnitSymbol( *m_staticTextPosY );
+
+ // Configure the layers list selector
+ if( !m_Parent->GetBoard()->IsLayerEnabled( aDimension->GetLayer() ) )
+ // Should not happens, because one cannot select a board item on a
+ // not activated layer, but ...
+ m_SelLayerBox->ShowNonActivatedLayers( true );
+
+ m_SelLayerBox->SetLayersHotkeys( false );
+ m_SelLayerBox->SetLayerSet( LSET::AllCuMask().set( Edge_Cuts ) );
+ m_SelLayerBox->SetBoardFrame( m_Parent );
+ m_SelLayerBox->Resync();
+
+ if( m_SelLayerBox->SetLayerSelection( aDimension->GetLayer() ) < 0 )
+ {
+ wxMessageBox( _( "This item has an illegal layer id.\n"
+ "Now, forced on the drawings layer. Please, fix it" ) );
+ m_SelLayerBox->SetLayerSelection( Dwgs_User );
+ }
+
+ m_sdbSizerBtsOK->SetDefault();
+ GetSizer()->Fit( this );
+ GetSizer()->SetSizeHints( this );
+ Centre();
+}
+
+
+void DIALOG_DIMENSION_EDITOR::OnCancelClick( wxCommandEvent& event )
+{
+ EndModal( -1 );
+}
+
+
+void DIALOG_DIMENSION_EDITOR::OnOKClick( wxCommandEvent& event )
+{
+ LAYER_ID newlayer = ToLAYER_ID( m_SelLayerBox->GetLayerSelection() );
+
+ if( !m_Parent->GetBoard()->IsLayerEnabled( newlayer ) )
+ {
+ wxMessageBox( _( "The layer currently selected is not enabled for this board\n"
+ "You cannot use it" ) );
+ return;
+ }
+
+#ifndef USE_WX_OVERLAY
+ if( m_DC ) // Delete old text.
+ {
+ CurrentDimension->Draw( m_Parent->GetCanvas(), m_DC, GR_XOR );
+ }
+#endif
+
+ m_Parent->SaveCopyInUndoList(CurrentDimension, UR_CHANGED);
+
+ if( m_Name->GetValue() != wxEmptyString )
+ {
+ CurrentDimension->SetText( m_Name->GetValue() );
+ }
+
+ wxString msg;
+
+ // Get new size value:
+ msg = m_TxtSizeXCtrl->GetValue();
+ CurrentDimension->Text().SetWidth( ValueFromString( g_UserUnit, msg ) );
+ msg = m_TxtSizeYCtrl->GetValue();
+ CurrentDimension->Text().SetHeight( ValueFromString( g_UserUnit, msg ) );
+
+ // Get new position value:
+ // It will be copied later in dimension, because
+ msg = m_textCtrlPosX->GetValue();
+ wxPoint pos;
+ pos.x = ValueFromString( g_UserUnit, msg );
+ msg = m_textCtrlPosY->GetValue();
+ pos.y = ValueFromString( g_UserUnit, msg );
+ CurrentDimension->Text().SetTextPosition( pos );
+
+ // Get new line thickness value:
+ msg = m_TxtWidthCtrl->GetValue();
+ int width = ValueFromString( g_UserUnit, msg );
+ int maxthickness = Clamp_Text_PenSize( width, CurrentDimension->Text().GetSize() );
+
+ if( width > maxthickness )
+ {
+ DisplayError( NULL,
+ _( "The text thickness is too large for the text size. "
+ "It will be clamped" ) );
+ width = maxthickness;
+ }
+
+ CurrentDimension->SetWidth( width );
+ CurrentDimension->Text().SetThickness( width );
+ CurrentDimension->Text().SetMirrored( ( m_rbMirror->GetSelection() == 1 ) ? true : false );
+ CurrentDimension->SetLayer( newlayer );
+
+#ifndef USE_WX_OVERLAY
+ if( m_DC ) // Display new text
+ {
+ CurrentDimension->Draw( m_Parent->GetCanvas(), m_DC, GR_OR );
+ }
+#else
+ m_Parent->Refresh();
+#endif
+
+ m_Parent->OnModify();
+ EndModal( 1 );
+}
+
+
+static void AbortBuildDimension( EDA_DRAW_PANEL* Panel, wxDC* aDC )
+{
+ DIMENSION* Dimension = (DIMENSION*) Panel->GetScreen()->GetCurItem();
+
+ if( Dimension )
+ {
+ if( Dimension->IsNew() )
+ {
+ Dimension->Draw( Panel, aDC, GR_XOR );
+ Dimension->DeleteStructure();
+ }
+ else
+ {
+ Dimension->Draw( Panel, aDC, GR_OR );
+ }
+ }
+
+ status_dimension = 0;
+ ((PCB_EDIT_FRAME*)Panel->GetParent())->SetCurItem( NULL );
+}
+
+
+DIMENSION* PCB_EDIT_FRAME::EditDimension( DIMENSION* aDimension, wxDC* aDC )
+{
+ wxPoint pos;
+
+ if( aDimension == NULL )
+ {
+ status_dimension = 1;
+ pos = GetCrossHairPosition();
+
+ aDimension = new DIMENSION( GetBoard() );
+ aDimension->SetFlags( IS_NEW );
+ aDimension->SetLayer( GetActiveLayer() );
+ aDimension->SetOrigin( pos );
+ aDimension->SetEnd( pos );
+
+ aDimension->Text().SetSize( GetBoard()->GetDesignSettings().m_PcbTextSize );
+ int width = GetBoard()->GetDesignSettings().m_PcbTextWidth;
+ int maxthickness = Clamp_Text_PenSize(width, aDimension->Text().GetSize() );
+
+ if( width > maxthickness )
+ {
+ width = maxthickness;
+ }
+
+ aDimension->Text().SetThickness( width );
+ aDimension->SetWidth( width );
+ aDimension->AdjustDimensionDetails();
+ aDimension->Draw( m_canvas, aDC, GR_XOR );
+
+ m_canvas->SetMouseCapture( BuildDimension, AbortBuildDimension );
+ return aDimension;
+ }
+
+ // Dimension != NULL
+ if( status_dimension == 1 )
+ {
+ status_dimension = 2;
+ return aDimension;
+ }
+
+ aDimension->Draw( m_canvas, aDC, GR_OR );
+ aDimension->ClearFlags();
+
+ /* ADD this new item in list */
+ GetBoard()->Add( aDimension );
+
+ // Add store it in undo/redo list
+ SaveCopyInUndoList( aDimension, UR_NEW );
+
+ OnModify();
+ m_canvas->SetMouseCapture( NULL, NULL );
+
+ return NULL;
+}
+
+
+static void BuildDimension( EDA_DRAW_PANEL* aPanel, wxDC* aDC,
+ const wxPoint& aPosition, bool aErase )
+{
+ PCB_SCREEN* screen = (PCB_SCREEN*) aPanel->GetScreen();
+ DIMENSION* Dimension = (DIMENSION*) screen->GetCurItem();
+ wxPoint pos = aPanel->GetParent()->GetCrossHairPosition();
+
+ if( Dimension == NULL )
+ return;
+
+ // Erase previous dimension.
+ if( aErase )
+ {
+ Dimension->Draw( aPanel, aDC, GR_XOR );
+ }
+
+ Dimension->SetLayer( screen->m_Active_Layer );
+
+ if( status_dimension == 1 )
+ {
+ Dimension->m_featureLineDO = pos;
+ Dimension->m_crossBarF = Dimension->m_featureLineDO;
+ Dimension->AdjustDimensionDetails( );
+ }
+ else
+ {
+ /* Calculating the direction of travel perpendicular to the selected axis. */
+ double angle = Dimension->GetAngle() + (M_PI / 2);
+
+ wxPoint delta = pos - Dimension->m_featureLineDO;
+ double depl = ( delta.x * cos( angle ) ) + ( delta.y * sin( angle ) );
+ Dimension->SetHeight( depl );
+ }
+
+ Dimension->Draw( aPanel, aDC, GR_XOR );
+}
+
+
+void PCB_EDIT_FRAME::ShowDimensionPropertyDialog( DIMENSION* aDimension, wxDC* aDC )
+{
+ if( aDimension == NULL )
+ return;
+
+ DIALOG_DIMENSION_EDITOR* frame = new DIALOG_DIMENSION_EDITOR( this, aDimension, aDC );
+ frame->ShowModal();
+ frame->Destroy();
+}
+
+
+void PCB_EDIT_FRAME::DeleteDimension( DIMENSION* aDimension, wxDC* aDC )
+{
+ if( aDimension == NULL )
+ return;
+
+ if( aDC )
+ aDimension->Draw( m_canvas, aDC, GR_XOR );
+
+ SaveCopyInUndoList( aDimension, UR_DELETED );
+ aDimension->UnLink();
+ OnModify();
+}
+
+
+/* Initialize parameters to move a pcb text
+ */
+static wxPoint initialTextPosition;
+
+void PCB_EDIT_FRAME::BeginMoveDimensionText( DIMENSION* aItem, wxDC* DC )
+{
+ if( aItem == NULL )
+ return;
+
+ // Store the initial position for undo/abort command
+ initialTextPosition = aItem->Text().GetTextPosition();
+
+ aItem->Draw( m_canvas, DC, GR_XOR );
+ aItem->SetFlags( IS_MOVED );
+ SetMsgPanel( aItem );
+
+ SetCrossHairPosition( aItem->Text().GetTextPosition() );
+ m_canvas->MoveCursorToCrossHair();
+
+ m_canvas->SetMouseCapture( MoveDimensionText, AbortMoveDimensionText );
+ SetCurItem( aItem );
+ m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
+}
+
+
+/* Move dimension text following the cursor. */
+static void MoveDimensionText( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition,
+ bool aErase )
+{
+ DIMENSION* dimension = (DIMENSION*) aPanel->GetScreen()->GetCurItem();
+
+ if( dimension == NULL )
+ return;
+
+ if( aErase )
+ dimension->Draw( aPanel, aDC, GR_XOR );
+
+ dimension->Text().SetTextPosition( aPanel->GetParent()->GetCrossHairPosition() );
+
+ dimension->Draw( aPanel, aDC, GR_XOR );
+}
+
+
+/*
+ * Abort current text edit progress.
+ *
+ * If a text is selected, its initial coord are regenerated
+ */
+void AbortMoveDimensionText( EDA_DRAW_PANEL* aPanel, wxDC* aDC )
+{
+ DIMENSION* dimension = (DIMENSION*) aPanel->GetScreen()->GetCurItem();
+ ( (PCB_EDIT_FRAME*) aPanel->GetParent() )->SetCurItem( NULL );
+
+ aPanel->SetMouseCapture( NULL, NULL );
+
+ if( dimension == NULL ) // Should not occur
+ return;
+
+ dimension->Draw( aPanel, aDC, GR_XOR );
+ dimension->Text().SetTextPosition( initialTextPosition );
+ dimension->ClearFlags();
+ dimension->Draw( aPanel, aDC, GR_OR );
+}
+
+
+/*
+ * Place the current dimension text being moving
+ */
+void PCB_EDIT_FRAME::PlaceDimensionText( DIMENSION* aItem, wxDC* DC )
+{
+ m_canvas->SetMouseCapture( NULL, NULL );
+ SetCurItem( NULL );
+
+ if( aItem == NULL )
+ return;
+
+ aItem->Draw( m_canvas, DC, GR_OR );
+ OnModify();
+
+ wxPoint tmp = aItem->Text().GetTextPosition();
+ aItem->Text().SetTextPosition( initialTextPosition );
+ SaveCopyInUndoList( aItem, UR_CHANGED );
+ aItem->Text().SetTextPosition( tmp );
+ aItem->ClearFlags();
+}