kicad/pcbnew/cotation.cpp

487 lines
16 KiB
C++

/*****************************************/
/* Edition du pcb: Gestion des cotations */
/*****************************************/
#include "fctsys.h"
#include "common.h"
#include "class_drawpanel.h"
#include "pcbnew.h"
#include "wxPcbStruct.h"
#include "class_board_design_settings.h"
/* Routines Locales */
static void Exit_EditCotation( WinEDA_DrawPanel* Panel, wxDC* DC );
static void Montre_Position_New_Cotation( WinEDA_DrawPanel* panel, wxDC* DC, bool erase );
static void Ajuste_Details_Cotation( COTATION* pts, bool aDoNotChangeText = false );
/* Variables "locales" : */
static int status_cotation; /* = 0 : pas de cotation en cours
* = 1 : debut place, fin a placer
* = 2 : fin placee, texte a ajuster */
/*
* Les routines generent une cotation de la forme
* - cote usuelle:
*
| |
| dist |
|<---------->|
| |
*
*/
#define MAX_CHAR 40 /* longueur maxi de la cotation */
/* Dimension des fleches */
#define FLECHE_L 500
enum id_Cotation_properties {
ID_TEXTPCB_SELECT_LAYER = 1900
};
/************************************/
/* class WinEDA_CotationPropertiesFrame */
/************************************/
class WinEDA_CotationPropertiesFrame : public wxDialog
{
private:
WinEDA_PcbFrame* m_Parent;
wxDC* m_DC;
COTATION* CurrentCotation;
WinEDA_EnterText* m_Name;
WinEDA_SizeCtrl* m_TxtSizeCtrl;
WinEDA_ValueCtrl* m_TxtWidthCtrl;
wxRadioBox* m_Mirror;
WinEDAChoiceBox* m_SelLayerBox;
public:
// Constructor and destructor
WinEDA_CotationPropertiesFrame( WinEDA_PcbFrame* parent,
COTATION* Cotation, wxDC* DC, const wxPoint& pos );
~WinEDA_CotationPropertiesFrame()
{
}
private:
void OnCancelClick( wxCommandEvent& event );
void OnOkClick( wxCommandEvent& event );
DECLARE_EVENT_TABLE()
};
BEGIN_EVENT_TABLE( WinEDA_CotationPropertiesFrame, wxDialog )
EVT_BUTTON( wxID_OK, WinEDA_CotationPropertiesFrame::OnOkClick )
EVT_BUTTON( wxID_CANCEL, WinEDA_CotationPropertiesFrame::OnCancelClick )
END_EVENT_TABLE()
WinEDA_CotationPropertiesFrame::WinEDA_CotationPropertiesFrame( WinEDA_PcbFrame* parent,
COTATION* Cotation, wxDC* DC,
const wxPoint& framepos ) :
wxDialog( parent, -1, _( "Dimension properties" ), framepos, wxSize( 340, 270 ),
DIALOG_STYLE )
{
wxButton* Button;
m_Parent = parent;
m_DC = DC;
Centre();
CurrentCotation = Cotation;
wxBoxSizer* MainBoxSizer = new wxBoxSizer( wxHORIZONTAL );
SetSizer( MainBoxSizer );
wxBoxSizer* LeftBoxSizer = new wxBoxSizer( wxVERTICAL );
wxBoxSizer* RightBoxSizer = new wxBoxSizer( wxVERTICAL );
MainBoxSizer->Add( LeftBoxSizer, 0, wxGROW | wxALL, 5 );
MainBoxSizer->Add( RightBoxSizer, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
/* Creation des boutons de commande */
Button = new wxButton( this, wxID_OK, _( "OK" ) );
RightBoxSizer->Add( Button, 0, wxGROW | wxALL, 5 );
Button = new wxButton( this, wxID_CANCEL, _( "Cancel" ) );
RightBoxSizer->Add( Button, 0, wxGROW | wxALL, 5 );
wxString display_msg[2] = { _( "Normal" ), _( "Mirror" ) };
m_Mirror = new wxRadioBox( this, -1, _( "Display" ),
wxDefaultPosition, wxSize( -1, -1 ), 2, display_msg,
1, wxRA_SPECIFY_COLS );
if( Cotation->m_Text->m_Mirror )
m_Mirror->SetSelection( 1 );;
RightBoxSizer->Add( m_Mirror, 0, wxGROW | wxALL, 5 );
m_Name = new WinEDA_EnterText( this, wxT( "Text:" ),
Cotation->m_Text->m_Text,
LeftBoxSizer, wxSize( 200, -1 ) );
m_TxtSizeCtrl = new WinEDA_SizeCtrl( this, _( "Size" ),
Cotation->m_Text->m_Size,
g_UnitMetric, LeftBoxSizer, m_Parent->m_InternalUnits );
m_TxtWidthCtrl = new WinEDA_ValueCtrl( this, _( "Width" ),
Cotation->m_Width,
g_UnitMetric, LeftBoxSizer, m_Parent->m_InternalUnits );
wxStaticText* text = new wxStaticText( this, -1, _( "Layer:" ) );
LeftBoxSizer->Add( text, 0, wxGROW | wxLEFT | wxRIGHT | wxTOP, 5 );
m_SelLayerBox = new WinEDAChoiceBox( this, ID_TEXTPCB_SELECT_LAYER,
wxDefaultPosition, wxDefaultSize );
LeftBoxSizer->Add( m_SelLayerBox, 0, wxGROW | wxLEFT | wxRIGHT | wxBOTTOM, 5 );
for( int layer = FIRST_NO_COPPER_LAYER; layer<NB_LAYERS; layer++ )
{
m_SelLayerBox->Append( parent->GetBoard()->GetLayerName( layer ) );
}
m_SelLayerBox->SetSelection( Cotation->GetLayer() - FIRST_NO_COPPER_LAYER );
GetSizer()->Fit( this );
GetSizer()->SetSizeHints( this );
}
/**********************************************************************/
void WinEDA_CotationPropertiesFrame::OnCancelClick( wxCommandEvent& WXUNUSED (event) )
/**********************************************************************/
{
EndModal( -1 );
}
/***********************************************************************************/
void WinEDA_CotationPropertiesFrame::OnOkClick( wxCommandEvent& event )
/***********************************************************************************/
{
if( m_DC ) // Effacement ancien texte
{
CurrentCotation->Draw( m_Parent->DrawPanel, m_DC, GR_XOR );
}
m_Parent->SaveCopyInUndoList(CurrentCotation, UR_CHANGED);
if( m_Name->GetValue() != wxEmptyString )
{
CurrentCotation->SetText( m_Name->GetValue() );
}
CurrentCotation->m_Text->m_Size = m_TxtSizeCtrl->GetValue();
CurrentCotation->m_Text->m_Width = CurrentCotation->m_Width =
m_TxtWidthCtrl->GetValue();
CurrentCotation->m_Text->m_Mirror = (m_Mirror->GetSelection() == 1) ? true : false;
CurrentCotation->SetLayer( m_SelLayerBox->GetChoice() + FIRST_NO_COPPER_LAYER );
if( m_DC ) // Affichage nouveau texte
{
/* Redessin du Texte */
CurrentCotation->Draw( m_Parent->DrawPanel, m_DC, GR_OR );
}
m_Parent->GetScreen()->SetModify();
EndModal( 1 );
}
/**************************************************************/
static void Exit_EditCotation( WinEDA_DrawPanel* Panel, wxDC* DC )
/**************************************************************/
{
COTATION* Cotation = (COTATION*) Panel->GetScreen()->GetCurItem();
if( Cotation )
{
if( Cotation->m_Flags & IS_NEW )
{
Cotation->Draw( Panel, DC, GR_XOR );
Cotation->DeleteStructure();
}
else
{
Cotation->Draw( Panel, DC, GR_OR );
}
}
status_cotation = 0;
Panel->ManageCurseur = NULL;
Panel->ForceCloseManageCurseur = NULL;
((WinEDA_PcbFrame*)Panel->GetParent())->SetCurItem(NULL);
}
/*************************************************************************/
COTATION* WinEDA_PcbFrame::Begin_Cotation( COTATION* Cotation, wxDC* DC )
/*************************************************************************/
{
wxPoint pos;
if( Cotation == NULL ) /* debut reel du trace */
{
status_cotation = 1;
pos = GetScreen()->m_Curseur;
Cotation = new COTATION( GetBoard() );
Cotation->m_Flags = IS_NEW;
Cotation->SetLayer( ((PCB_SCREEN*)GetScreen())->m_Active_Layer );
Cotation->m_Width = g_DesignSettings.m_DrawSegmentWidth;
Cotation->m_Text->m_Width = Cotation->m_Width;
Cotation->Barre_ox = Cotation->Barre_fx = pos.x;
Cotation->Barre_oy = Cotation->Barre_fy = pos.y;
Cotation->TraitD_ox = Cotation->TraitD_fx = pos.x;
Cotation->TraitD_oy = Cotation->TraitD_fy = pos.y;
Cotation->TraitG_ox = Cotation->TraitG_fx = pos.x;
Cotation->TraitG_oy = Cotation->TraitG_fy = pos.y;
Cotation->FlecheG1_ox = Cotation->FlecheG1_fx = pos.x;
Cotation->FlecheG1_oy = Cotation->FlecheG1_fy = pos.y;
Cotation->FlecheG2_ox = Cotation->FlecheG2_fx = pos.x;
Cotation->FlecheG2_oy = Cotation->FlecheG2_fy = pos.y;
Cotation->FlecheD1_ox = Cotation->FlecheD1_fx = pos.x;
Cotation->FlecheD1_oy = Cotation->FlecheD1_fy = pos.y;
Cotation->FlecheD2_ox = Cotation->FlecheD2_fx = pos.x;
Cotation->FlecheD2_oy = Cotation->FlecheD2_fy = pos.y;
Cotation->m_Text->m_Size = g_DesignSettings.m_PcbTextSize;
Cotation->m_Text->m_Width = g_DesignSettings.m_PcbTextWidth;
Ajuste_Details_Cotation( Cotation );
Cotation->Draw( DrawPanel, DC, GR_XOR );
DrawPanel->ManageCurseur = Montre_Position_New_Cotation;
DrawPanel->ForceCloseManageCurseur = Exit_EditCotation;
return Cotation;
}
// Cotation != NULL
if( status_cotation == 1 )
{
status_cotation = 2;
return Cotation;
}
Cotation->Draw( DrawPanel, DC, GR_OR );
Cotation->m_Flags = 0;
/* Insertion de la structure dans le Chainage .Drawings du PCB */
GetBoard()->Add( Cotation );
GetScreen()->SetModify();
DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL;
return NULL;
}
/************************************************************************************/
static void Montre_Position_New_Cotation( WinEDA_DrawPanel* panel, wxDC* DC, bool erase )
/************************************************************************************/
/* redessin du contour de la piste lors des deplacements de la souris */
{
PCB_SCREEN* screen = (PCB_SCREEN*) panel->GetScreen();
COTATION* Cotation = (COTATION*) screen->GetCurItem();
wxPoint pos = screen->m_Curseur;
if( Cotation == NULL )
return;
/* efface ancienne position */
if( erase )
{
Cotation->Draw( panel, DC, GR_XOR );
}
Cotation->SetLayer( screen->m_Active_Layer );
if( status_cotation == 1 )
{
Cotation->TraitD_ox = pos.x;
Cotation->TraitD_oy = pos.y;
Cotation->Barre_fx = Cotation->TraitD_ox;
Cotation->Barre_fy = Cotation->TraitD_oy;
Ajuste_Details_Cotation( Cotation );
}
else
{
int deltax, deltay, dx, dy;
float angle, depl;
deltax = Cotation->TraitD_ox - Cotation->TraitG_ox;
deltay = Cotation->TraitD_oy - Cotation->TraitG_oy;
/* Calcul de la direction de deplacement
* ( perpendiculaire a l'axe de la cote ) */
angle = atan2( (double)deltay, (double)deltax ) + (M_PI / 2);
deltax = pos.x - Cotation->TraitD_ox;
deltay = pos.y - Cotation->TraitD_oy;
depl = ( deltax * cos( angle ) ) + ( deltay * sin( angle ) );
dx = (int) ( depl * cos( angle ) );
dy = (int) ( depl * sin( angle ) );
Cotation->Barre_ox = Cotation->TraitG_ox + dx;
Cotation->Barre_oy = Cotation->TraitG_oy + dy;
Cotation->Barre_fx = Cotation->TraitD_ox + dx;
Cotation->Barre_fy = Cotation->TraitD_oy + dy;
Ajuste_Details_Cotation( Cotation );
}
Cotation->Draw( panel, DC, GR_XOR );
}
/***************************************************************/
void WinEDA_PcbFrame::Install_Edit_Cotation( COTATION* Cotation,
wxDC* DC, const wxPoint& pos )
/***************************************************************/
{
if( Cotation == NULL )
return;
WinEDA_CotationPropertiesFrame* frame = new WinEDA_CotationPropertiesFrame( this,
Cotation, DC, pos );
Ajuste_Details_Cotation( Cotation, true );
frame->ShowModal();
frame->Destroy();
}
/*******************************************************************/
void WinEDA_PcbFrame::Delete_Cotation( COTATION* Cotation, wxDC* DC )
/*******************************************************************/
{
if( Cotation == NULL )
return;
if( DC )
Cotation->Draw( DrawPanel, DC, GR_XOR );
SaveCopyInUndoList(Cotation, UR_DELETED);
Cotation->UnLink();
GetScreen()->SetModify();
}
/*****************************************************/
static void Ajuste_Details_Cotation( COTATION* Cotation, bool aDoNotChangeText )
/*****************************************************/
/* Calcule les details des coordonnees des differents segments constitutifs
* de la cotation
*/
{
int ii;
int mesure, deltax, deltay; /* valeur de la mesure sur les axes X et Y */
int fleche_up_X = 0, fleche_up_Y = 0; /* coord des fleches : barre / */
int fleche_dw_X = 0, fleche_dw_Y = 0; /* coord des fleches : barre \ */
int hx, hy; /* coord des traits de rappel de cote */
float angle, angle_f;
wxString msg;
/* Init des couches : */
Cotation->m_Text->SetLayer( Cotation->GetLayer() );
/* calcul de la hauteur du texte + trait de cotation */
ii = Cotation->m_Text->m_Size.y +
Cotation->m_Text->m_Width + (Cotation->m_Width * 3);
deltax = Cotation->TraitD_ox - Cotation->TraitG_ox;
deltay = Cotation->TraitD_oy - Cotation->TraitG_oy;
/* Calcul de la cote */
mesure = (int) (hypot( (double) deltax, (double) deltay ) + 0.5 );
if( deltax || deltay )
angle = atan2( (double) deltay, (double) deltax );
else
angle = 0.0;
/* Calcul des parametre dimensions X et Y des fleches et traits de cotes */
hx = hy = ii;
/* On tient compte de l'inclinaison de la cote */
if( mesure )
{
hx = (abs) ( (int) ( ( (double) deltay * hx ) / mesure ) );
hy = (abs) ( (int) ( ( (double) deltax * hy ) / mesure ) );
if( Cotation->TraitG_ox > Cotation->Barre_ox )
hx = -hx;
if( Cotation->TraitG_ox == Cotation->Barre_ox )
hx = 0;
if( Cotation->TraitG_oy > Cotation->Barre_oy )
hy = -hy;
if( Cotation->TraitG_oy == Cotation->Barre_oy )
hy = 0;
angle_f = angle + (M_PI * 27.5 / 180);
fleche_up_X = (int) ( FLECHE_L * cos( angle_f ) );
fleche_up_Y = (int) ( FLECHE_L * sin( angle_f ) );
angle_f = angle - (M_PI * 27.5 / 180);
fleche_dw_X = (int) ( FLECHE_L * cos( angle_f ) );
fleche_dw_Y = (int) ( FLECHE_L * sin( angle_f ) );
}
Cotation->FlecheG1_ox = Cotation->Barre_ox;
Cotation->FlecheG1_oy = Cotation->Barre_oy;
Cotation->FlecheG1_fx = Cotation->Barre_ox + fleche_up_X;
Cotation->FlecheG1_fy = Cotation->Barre_oy + fleche_up_Y;
Cotation->FlecheG2_ox = Cotation->Barre_ox;
Cotation->FlecheG2_oy = Cotation->Barre_oy;
Cotation->FlecheG2_fx = Cotation->Barre_ox + fleche_dw_X;
Cotation->FlecheG2_fy = Cotation->Barre_oy + fleche_dw_Y;
/*la fleche de droite est symetrique a celle de gauche:
* / = -\ et \ = -/
*/
Cotation->FlecheD1_ox = Cotation->Barre_fx;
Cotation->FlecheD1_oy = Cotation->Barre_fy;
Cotation->FlecheD1_fx = Cotation->Barre_fx - fleche_dw_X;
Cotation->FlecheD1_fy = Cotation->Barre_fy - fleche_dw_Y;
Cotation->FlecheD2_ox = Cotation->Barre_fx;
Cotation->FlecheD2_oy = Cotation->Barre_fy;
Cotation->FlecheD2_fx = Cotation->Barre_fx - fleche_up_X;
Cotation->FlecheD2_fy = Cotation->Barre_fy - fleche_up_Y;
Cotation->TraitG_fx = Cotation->Barre_ox + hx;
Cotation->TraitG_fy = Cotation->Barre_oy + hy;
Cotation->TraitD_fx = Cotation->Barre_fx + hx;
Cotation->TraitD_fy = Cotation->Barre_fy + hy;
/* Calcul de la position du centre du texte et son orientation: */
Cotation->m_Pos.x = Cotation->m_Text->m_Pos.x
= (Cotation->Barre_fx + Cotation->TraitG_fx) / 2;
Cotation->m_Pos.y = Cotation->m_Text->m_Pos.y
= (Cotation->Barre_fy + Cotation->TraitG_fy) / 2;
Cotation->m_Text->m_Orient = -(int) (angle * 1800 / M_PI);
if( Cotation->m_Text->m_Orient < 0 )
Cotation->m_Text->m_Orient += 3600;
if( Cotation->m_Text->m_Orient >= 3600 )
Cotation->m_Text->m_Orient -= 3600;
if( (Cotation->m_Text->m_Orient > 900) && (Cotation->m_Text->m_Orient <2700) )
Cotation->m_Text->m_Orient -= 1800;
if( !aDoNotChangeText )
{
Cotation->m_Value = mesure;
valeur_param( Cotation->m_Value, msg );
Cotation->SetText( msg );
}
}