Compare commits
146 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2eaa9236f2 | |||
| e4bab37b62 | |||
| 105c9c71ee | |||
| e135229ca6 | |||
| 97dea6ede5 | |||
| d871a92d1c | |||
| a152aa125b | |||
| 4e217d4028 | |||
| e5da7a4606 | |||
| faace3090c | |||
| d3e2345f94 | |||
| a3e087ab51 | |||
| 3a614a8ea1 | |||
| 9cb60dcdf5 | |||
| af6db68816 | |||
| 305ed0b65a | |||
| 263efb41e8 | |||
| d6312c7b92 | |||
| b31af4891d | |||
| 0ba08f57f2 | |||
| a2d7881afe | |||
| d79e598bf8 | |||
| a6a39cb842 | |||
| 5d0883c0e4 | |||
| e6d49424cf | |||
| 72abcd5991 | |||
| 9c2bb85858 | |||
| e9b059ee94 | |||
| 7a913844e2 | |||
| f8be7e1f57 | |||
| d5c43c4675 | |||
| 85fa6d8025 | |||
| 6b2a8f54a1 | |||
| bd1fb845b1 | |||
| 9c64c9af5d | |||
| 1057eceb2f | |||
| 445bc75319 | |||
| 4fb7ee02cd | |||
| ad11b7ebd0 | |||
| 5d9bda6f97 | |||
| 54be07c17d | |||
| 2c7ab3a28e | |||
| 3cc3c1bbd3 | |||
| ddedf2e046 | |||
| a60c339f85 | |||
| ce2c5d6528 | |||
| fd81f70355 | |||
| 100bb7c6ca | |||
| 1ffcedd9d4 | |||
| fc1f713106 | |||
| 83c3a78e6d | |||
| e6a3e7024d | |||
| d62fde0d79 | |||
| a70cf464d6 | |||
| 546260348d | |||
| 693aec949c | |||
| 5c7ac1bb7e | |||
| 8862752523 | |||
| 201c380925 | |||
| c7230a6f77 | |||
| 6b78fdf822 | |||
| 3cb326e426 | |||
| d3f9332372 | |||
| be0f6a6af2 | |||
| 25aa233cef | |||
| 5fdc424202 | |||
| 9b74bb5c92 | |||
| 8bf8a649c8 | |||
| 7ba8d8b608 | |||
| e35328fece | |||
| 366d4d7b0b | |||
| 3af1e75084 | |||
| dabd80fe4c | |||
| cb711a648f | |||
| 5b58dbc980 | |||
| 8b3c0a941c | |||
| 3ce29a3d7e | |||
| dc3c6b2f39 | |||
| 1cbee4c504 | |||
| 798e4c288a | |||
| ac39e32bc9 | |||
| 52da7f931b | |||
| fcb6f814de | |||
| 9e6b56d783 | |||
| 923dad6ca8 | |||
| 9f17d91b32 | |||
| 2bcb04a3b1 | |||
| a530b600b8 | |||
| d494a2bee2 | |||
| 6a027662ae | |||
| 577bb7bf31 | |||
| df664bd55f | |||
| 8a2705f81f | |||
| fcaf11422a | |||
| 3444409554 | |||
| 683c01b301 | |||
| e2492f773d | |||
| 1f3a2dcd1d | |||
| 4205cb32c5 | |||
| 6ab9bdb346 | |||
| a4aec1919c | |||
| 5b97d70d57 | |||
| eeeb4596c3 | |||
| 23853cae14 | |||
| 87f6f33b37 | |||
| 8c03d1bdde | |||
| 7f1c7d808d | |||
| be12aece5b | |||
| d7605f1449 | |||
| ef80642dec | |||
| a5622c93d4 | |||
| b6f9bfe9a5 | |||
| 79954657e2 | |||
| 35d3f1f72a | |||
| 388d74faf4 | |||
| 0f8747e194 | |||
| 93f16ba9e3 | |||
| bea2d42e8c | |||
| 68d644fd28 | |||
| f6e33450ff | |||
| 65008c5c0b | |||
| dbfaf568fc | |||
| 58fd6ac03e | |||
| 1e64524afb | |||
| 20a5d8effd | |||
| 8c7e0bcb0a | |||
| c69080f11e | |||
| 5a48c800ee | |||
| c6eff4d373 | |||
| 5c056c2a3e | |||
| 61f593f350 | |||
| 6cc7dc7aaa | |||
| 239f040a98 | |||
| 3827c16fde | |||
| e299343807 | |||
| 4130ce2b93 | |||
| d6acb64514 | |||
| 8e233e2591 | |||
| 9cda16220e | |||
| 36acadbd52 | |||
| 37b6552c42 | |||
| 1903052d79 | |||
| 2b4cfd9a60 | |||
| decbb65f09 | |||
| 8e2ca37edc | |||
| 8fb6bcc8b1 |
@@ -386,9 +386,22 @@ void CINFO3D_VISU::createNewPadWithClearance( const D_PAD* aPad,
|
||||
case PAD_SHAPE_RECT:
|
||||
{
|
||||
// see pcbnew/board_items_to_polygon_shape_transform.cpp
|
||||
|
||||
wxPoint corners[4];
|
||||
aPad->BuildPadPolygon( corners, wxSize( 0, 0), aPad->GetOrientation() );
|
||||
bool drawOutline;
|
||||
|
||||
// For aClearanceValue.x == aClearanceValue.y and > 0 we use the pad shape
|
||||
// and draw outlines with thicknes = aClearanceValue.
|
||||
// Otherwise we draw only the inflated/deflated shape
|
||||
if( aClearanceValue.x > 0 && aClearanceValue.x == aClearanceValue.y )
|
||||
{
|
||||
drawOutline = true;
|
||||
aPad->BuildPadPolygon( corners, wxSize( 0, 0 ), aPad->GetOrientation() );
|
||||
}
|
||||
else
|
||||
{
|
||||
drawOutline = false;
|
||||
aPad->BuildPadPolygon( corners, aClearanceValue, aPad->GetOrientation() );
|
||||
}
|
||||
|
||||
SFVEC2F corners3DU[4];
|
||||
|
||||
@@ -416,20 +429,23 @@ void CINFO3D_VISU::createNewPadWithClearance( const D_PAD* aPad,
|
||||
// Add the PAD contours
|
||||
// Round segments cannot have 0-length elements, so we approximate them
|
||||
// as a small circle
|
||||
for( int i = 1; i <= 4; i++ )
|
||||
if( drawOutline )
|
||||
{
|
||||
if( Is_segment_a_circle( corners3DU[i - 1], corners3DU[i & 3] ) )
|
||||
for( int i = 1; i <= 4; i++ )
|
||||
{
|
||||
aDstContainer->Add( new CFILLEDCIRCLE2D( corners3DU[i - 1],
|
||||
aClearanceValue.x * m_biuTo3Dunits,
|
||||
*aPad ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
aDstContainer->Add( new CROUNDSEGMENT2D( corners3DU[i - 1],
|
||||
corners3DU[i & 3],
|
||||
aClearanceValue.x * 2.0f * m_biuTo3Dunits,
|
||||
*aPad ) );
|
||||
if( Is_segment_a_circle( corners3DU[i - 1], corners3DU[i & 3] ) )
|
||||
{
|
||||
aDstContainer->Add( new CFILLEDCIRCLE2D( corners3DU[i - 1],
|
||||
aClearanceValue.x * m_biuTo3Dunits,
|
||||
*aPad ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
aDstContainer->Add( new CROUNDSEGMENT2D( corners3DU[i - 1],
|
||||
corners3DU[i & 3],
|
||||
aClearanceValue.x * 2.0f * m_biuTo3Dunits,
|
||||
*aPad ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1085,7 +1085,10 @@ bool EDA_3D_CANVAS::SetView3D( int aKeycode )
|
||||
m_settings.CameraGet().SetT0_and_T1_current_T();
|
||||
m_settings.CameraGet().Reset_T1();
|
||||
m_settings.CameraGet().RotateX_T1( glm::radians( -90.0f ) );
|
||||
m_settings.CameraGet().RotateZ_T1( glm::radians( -180.0f ) );
|
||||
// The rotation angle should be 180.
|
||||
// We use 179.999 (180 - epsilon) to avoid a full 360 deg rotation when
|
||||
// using 180 deg if the previous rotated position was already 180 deg
|
||||
m_settings.CameraGet().RotateZ_T1( glm::radians( -179.999f ) );
|
||||
request_start_moving_camera();
|
||||
return true;
|
||||
|
||||
@@ -1101,7 +1104,7 @@ bool EDA_3D_CANVAS::SetView3D( int aKeycode )
|
||||
m_settings.CameraGet().SetInterpolateMode( INTERPOLATION_BEZIER );
|
||||
m_settings.CameraGet().SetT0_and_T1_current_T();
|
||||
m_settings.CameraGet().Reset_T1();
|
||||
m_settings.CameraGet().RotateY_T1( glm::radians( 180.0f ) );
|
||||
m_settings.CameraGet().RotateY_T1( glm::radians( 179.999f ) ); // Rotation = 180-epsilon
|
||||
request_start_moving_camera(
|
||||
glm::min( glm::max( m_settings.CameraGet().ZoomGet(), 0.5f ), 1.125f ) );
|
||||
return true;
|
||||
|
||||
@@ -286,7 +286,9 @@ void C3D_RENDER_RAYTRACING::reload( REPORTER *aStatusTextReporter )
|
||||
|
||||
m_outlineBoard2dObjects = new CCONTAINER2D;
|
||||
|
||||
if( ((const SHAPE_POLY_SET &)m_settings.GetBoardPoly()).OutlineCount() == 1 )
|
||||
const int outlineCount = m_settings.GetBoardPoly().OutlineCount();
|
||||
|
||||
if( outlineCount > 0 )
|
||||
{
|
||||
float divFactor = 0.0f;
|
||||
|
||||
@@ -299,12 +301,16 @@ void C3D_RENDER_RAYTRACING::reload( REPORTER *aStatusTextReporter )
|
||||
SHAPE_POLY_SET boardPolyCopy = m_settings.GetBoardPoly();
|
||||
boardPolyCopy.Fracture( SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
Convert_path_polygon_to_polygon_blocks_and_dummy_blocks(
|
||||
boardPolyCopy,
|
||||
*m_outlineBoard2dObjects,
|
||||
m_settings.BiuTo3Dunits(),
|
||||
divFactor,
|
||||
(const BOARD_ITEM &)*m_settings.GetBoard() );
|
||||
for( int iOutlinePolyIdx = 0; iOutlinePolyIdx < outlineCount; iOutlinePolyIdx++ )
|
||||
{
|
||||
Convert_path_polygon_to_polygon_blocks_and_dummy_blocks(
|
||||
boardPolyCopy,
|
||||
*m_outlineBoard2dObjects,
|
||||
m_settings.BiuTo3Dunits(),
|
||||
divFactor,
|
||||
*dynamic_cast<const BOARD_ITEM*>( m_settings.GetBoard() ),
|
||||
iOutlinePolyIdx );
|
||||
}
|
||||
|
||||
if( m_settings.GetFlag( FL_SHOW_BOARD_BODY ) )
|
||||
{
|
||||
|
||||
@@ -408,17 +408,16 @@ void Convert_path_polygon_to_polygon_blocks_and_dummy_blocks(
|
||||
CGENERICCONTAINER2D &aDstContainer,
|
||||
float aBiuTo3DunitsScale,
|
||||
float aDivFactor,
|
||||
const BOARD_ITEM &aBoardItem )
|
||||
const BOARD_ITEM &aBoardItem,
|
||||
int aPolyIndex )
|
||||
{
|
||||
BOX2I pathBounds = aMainPath.BBox();
|
||||
|
||||
// Get the path
|
||||
|
||||
wxASSERT( aMainPath.OutlineCount() == 1 );
|
||||
const SHAPE_POLY_SET::POLYGON& curr_polywithholes = aMainPath.CPolygon( 0 );
|
||||
wxASSERT( aPolyIndex < aMainPath.OutlineCount() );
|
||||
|
||||
wxASSERT( curr_polywithholes.size() == 1 );
|
||||
const SHAPE_LINE_CHAIN& path = curr_polywithholes[0]; // a simple polygon
|
||||
const SHAPE_LINE_CHAIN& path = aMainPath.COutline( aPolyIndex );
|
||||
|
||||
BOX2I pathBounds = path.BBox();
|
||||
|
||||
// Convert the points to segments class
|
||||
CBBOX2D bbox;
|
||||
@@ -430,8 +429,10 @@ void Convert_path_polygon_to_polygon_blocks_and_dummy_blocks(
|
||||
// Contains a closed polygon used to calc if points are inside
|
||||
SEGMENTS segments;
|
||||
|
||||
segments_and_normals.resize( path.PointCount() );
|
||||
segments.resize( path.PointCount() );
|
||||
segments_and_normals.reserve( path.PointCount() );
|
||||
segments.reserve( path.PointCount() );
|
||||
|
||||
SFVEC2F prevPoint;
|
||||
|
||||
for( int i = 0; i < path.PointCount(); i++ )
|
||||
{
|
||||
@@ -440,9 +441,23 @@ void Convert_path_polygon_to_polygon_blocks_and_dummy_blocks(
|
||||
const SFVEC2F point ( (float)( a.x) * aBiuTo3DunitsScale,
|
||||
(float)(-a.y) * aBiuTo3DunitsScale );
|
||||
|
||||
bbox.Union( point );
|
||||
segments_and_normals[i].m_Start = point;
|
||||
segments[i].m_Start = point;
|
||||
// Only add points that are not coincident
|
||||
if( (i == 0) ||
|
||||
(fabs(prevPoint.x - point.x) > FLT_EPSILON) ||
|
||||
(fabs(prevPoint.y - point.y) > FLT_EPSILON) )
|
||||
{
|
||||
prevPoint = point;
|
||||
|
||||
bbox.Union( point );
|
||||
|
||||
SEGMENT_WITH_NORMALS sn;
|
||||
sn.m_Start = point;
|
||||
segments_and_normals.push_back( sn );
|
||||
|
||||
POLYSEGMENT ps;
|
||||
ps.m_Start = point;
|
||||
segments.push_back( ps );
|
||||
}
|
||||
}
|
||||
|
||||
bbox.ScaleNextUp();
|
||||
@@ -518,13 +533,13 @@ void Convert_path_polygon_to_polygon_blocks_and_dummy_blocks(
|
||||
segments_and_normals[i].m_Normals.m_Start = normalSeg;
|
||||
else
|
||||
segments_and_normals[i].m_Normals.m_Start =
|
||||
glm::normalize( (((normalBeforeSeg * dotBefore ) + normalSeg) * 0.5f) );
|
||||
glm::normalize( (normalBeforeSeg * dotBefore ) + normalSeg );
|
||||
|
||||
if( dotAfter < 0.7f )
|
||||
segments_and_normals[i].m_Normals.m_End = normalSeg;
|
||||
else
|
||||
segments_and_normals[i].m_Normals.m_End =
|
||||
glm::normalize( (((normalAfterSeg * dotAfter ) + normalSeg) * 0.5f) );
|
||||
glm::normalize( (normalAfterSeg * dotAfter ) + normalSeg );
|
||||
}
|
||||
|
||||
if( aDivFactor == 0.0f )
|
||||
|
||||
@@ -148,7 +148,8 @@ void Convert_path_polygon_to_polygon_blocks_and_dummy_blocks(
|
||||
CGENERICCONTAINER2D &aDstContainer,
|
||||
float aBiuTo3DunitsScale,
|
||||
float aDivFactor,
|
||||
const BOARD_ITEM &aBoardItem );
|
||||
const BOARD_ITEM &aBoardItem,
|
||||
int aPolyIndex );
|
||||
|
||||
void Polygon2d_TestModule();
|
||||
|
||||
|
||||
@@ -31,6 +31,17 @@
|
||||
#include <wx/log.h>
|
||||
|
||||
|
||||
// A helper function to normalize aAngle between -2PI and +2PI
|
||||
inline void normalise2PI( float& aAngle )
|
||||
{
|
||||
while( aAngle > 0.0 )
|
||||
aAngle -= M_PI*2;
|
||||
|
||||
while( aAngle < 0.0 )
|
||||
aAngle += M_PI*2;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Trace mask used to enable or disable the trace output of this class.
|
||||
* The debug output can be turned on by setting the WXTRACE environment variable to
|
||||
@@ -95,6 +106,20 @@ void CCAMERA::Reset_T1()
|
||||
m_zoom_t1 = 1.0f;
|
||||
m_rotate_aux_t1 = SFVEC3F( 0.0f );
|
||||
m_lookat_pos_t1 = m_board_lookat_pos_init;
|
||||
|
||||
|
||||
// Since 0 = 2pi, we want to reset the angle to be the closest
|
||||
// one to where we currently are. That ensures that we rotate
|
||||
// the board around the smallest distance getting there.
|
||||
if( m_rotate_aux_t0.x > M_PI )
|
||||
m_rotate_aux_t1.x = 2*M_PI;
|
||||
|
||||
if( m_rotate_aux_t0.y > M_PI )
|
||||
m_rotate_aux_t1.y = 2*M_PI;
|
||||
|
||||
if( m_rotate_aux_t0.z > M_PI )
|
||||
m_rotate_aux_t1.z = 2*M_PI;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -111,14 +136,17 @@ void CCAMERA::updateRotationMatrix()
|
||||
m_rotationMatrixAux = glm::rotate( glm::mat4( 1.0f ),
|
||||
m_rotate_aux.x,
|
||||
SFVEC3F( 1.0f, 0.0f, 0.0f ) );
|
||||
normalise2PI( m_rotate_aux.x );
|
||||
|
||||
m_rotationMatrixAux = glm::rotate( m_rotationMatrixAux,
|
||||
m_rotate_aux.y,
|
||||
SFVEC3F( 0.0f, 1.0f, 0.0f ) );
|
||||
normalise2PI( m_rotate_aux.y );
|
||||
|
||||
m_rotationMatrixAux = glm::rotate( m_rotationMatrixAux,
|
||||
m_rotate_aux.z,
|
||||
SFVEC3F( 0.0f, 0.0f, 1.0f ) );
|
||||
normalise2PI( m_rotate_aux.z );
|
||||
|
||||
m_parametersChanged = true;
|
||||
|
||||
@@ -163,7 +191,7 @@ void CCAMERA::rebuildProjection()
|
||||
|
||||
m_projectionMatrixInv = glm::inverse( m_projectionMatrix );
|
||||
|
||||
m_frustum.tang = glm::tan( glm::radians( m_frustum.angle ) * 0.5f ) ;
|
||||
m_frustum.tang = glm::tan( glm::radians( m_frustum.angle ) * 0.5f );
|
||||
|
||||
m_focalLen.x = ( (float)m_windowSize.y / (float)m_windowSize.x ) / m_frustum.tang;
|
||||
m_focalLen.y = 1.0f / m_frustum.tang;
|
||||
@@ -178,19 +206,21 @@ void CCAMERA::rebuildProjection()
|
||||
|
||||
m_frustum.nearD = -m_frustum.farD; // Use a symmetrical clip plane for ortho projection
|
||||
|
||||
const float orthoReductionFactor = m_zoom / 75.0f;
|
||||
// This formula was found by trial and error
|
||||
const float orthoReductionFactor = glm::length( m_camera_pos_init ) *
|
||||
m_zoom * m_zoom * 0.5f;
|
||||
|
||||
// Initialize Projection Matrix for Ortographic View
|
||||
m_projectionMatrix = glm::ortho( -m_windowSize.x * orthoReductionFactor,
|
||||
m_windowSize.x * orthoReductionFactor,
|
||||
-m_windowSize.y * orthoReductionFactor,
|
||||
m_windowSize.y * orthoReductionFactor,
|
||||
m_projectionMatrix = glm::ortho( -m_frustum.ratio * orthoReductionFactor,
|
||||
m_frustum.ratio * orthoReductionFactor,
|
||||
-orthoReductionFactor,
|
||||
orthoReductionFactor,
|
||||
m_frustum.nearD, m_frustum.farD );
|
||||
|
||||
m_projectionMatrixInv = glm::inverse( m_projectionMatrix );
|
||||
|
||||
m_frustum.nw = m_windowSize.x * orthoReductionFactor * 2.0f;
|
||||
m_frustum.nh = m_windowSize.y * orthoReductionFactor * 2.0f;
|
||||
m_frustum.nw = orthoReductionFactor * 2.0f * m_frustum.ratio;
|
||||
m_frustum.nh = orthoReductionFactor * 2.0f;
|
||||
m_frustum.fw = m_frustum.nw;
|
||||
m_frustum.fh = m_frustum.nh;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2020 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
|
||||
@@ -22,11 +22,12 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file eda_3d_viewer.cpp
|
||||
* @brief Implements a 3d viewer windows GUI
|
||||
*/
|
||||
|
||||
#include <wx/colordlg.h>
|
||||
#include <wx/colour.h>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/string.h>
|
||||
#include <wx/wupdlock.h>
|
||||
#include <wx/clipbrd.h>
|
||||
#include "eda_3d_viewer.h"
|
||||
|
||||
#include "../3d_viewer_id.h"
|
||||
@@ -271,6 +272,7 @@ void EDA_3D_VIEWER::OnCloseWindow( wxCloseEvent &event )
|
||||
event.Skip( true );
|
||||
}
|
||||
|
||||
|
||||
#define ROT_ANGLE 10.0
|
||||
|
||||
void EDA_3D_VIEWER::Process_Special_Functions( wxCommandEvent &event )
|
||||
@@ -292,7 +294,7 @@ void EDA_3D_VIEWER::Process_Special_Functions( wxCommandEvent &event )
|
||||
break;
|
||||
|
||||
case ID_ROTATE3D_X_POS:
|
||||
m_settings.CameraGet().RotateX( glm::radians(ROT_ANGLE) );
|
||||
m_settings.CameraGet().RotateX( glm::radians( ROT_ANGLE ) );
|
||||
|
||||
if( m_settings.RenderEngineGet() == RENDER_ENGINE_OPENGL_LEGACY )
|
||||
m_canvas->Request_refresh();
|
||||
@@ -302,7 +304,7 @@ void EDA_3D_VIEWER::Process_Special_Functions( wxCommandEvent &event )
|
||||
break;
|
||||
|
||||
case ID_ROTATE3D_X_NEG:
|
||||
m_settings.CameraGet().RotateX( -glm::radians(ROT_ANGLE) );
|
||||
m_settings.CameraGet().RotateX( -glm::radians( ROT_ANGLE ) );
|
||||
|
||||
if( m_settings.RenderEngineGet() == RENDER_ENGINE_OPENGL_LEGACY )
|
||||
m_canvas->Request_refresh();
|
||||
@@ -369,7 +371,11 @@ void EDA_3D_VIEWER::Process_Special_Functions( wxCommandEvent &event )
|
||||
|
||||
case ID_ORTHO:
|
||||
m_settings.CameraGet().ToggleProjection();
|
||||
m_canvas->Request_refresh();
|
||||
|
||||
if( m_settings.RenderEngineGet() == RENDER_ENGINE_OPENGL_LEGACY )
|
||||
m_canvas->Request_refresh();
|
||||
else
|
||||
m_canvas->RenderRaytracingRequest();
|
||||
return;
|
||||
|
||||
case ID_TOOL_SCREENCOPY_TOCLIBBOARD:
|
||||
@@ -985,6 +991,17 @@ void EDA_3D_VIEWER::takeScreenshot( wxCommandEvent& event )
|
||||
|
||||
fullFileName = m_defaultSaveScreenshotFileName.GetFullPath();
|
||||
|
||||
wxFileName fn = fullFileName;
|
||||
|
||||
if( !fn.IsDirWritable() )
|
||||
{
|
||||
wxString msg;
|
||||
|
||||
msg.Printf( _( "Insufficient permissions required to save file\n%s" ), fullFileName );
|
||||
wxMessageBox( msg, _( "Error" ), wxOK | wxICON_ERROR, this );
|
||||
return;
|
||||
}
|
||||
|
||||
// Be sure the screen area destroyed by the file dialog is redrawn
|
||||
// before making a screen copy.
|
||||
// Without this call, under Linux the screen refresh is made to late.
|
||||
|
||||
+4
-2
@@ -46,9 +46,10 @@ Russell Oliver <roliver8143[at]gmail-dot-com>
|
||||
Seth Hillbrand <hillbrand[at]ucdavis-dot-edu>
|
||||
Jeff Young <jeff[at]rokeby-dot-ie>
|
||||
Kevin Cozens <kevin[at]ve3syb-dot-ca>
|
||||
Ian McInerney <ian.s.mcinerney[at]ieee-dot-org>
|
||||
|
||||
See git repo on launchpad for contributors at
|
||||
https://code.launchpad.net/~kicad-product-committers/kicad/+git/product-git/+ref/master.
|
||||
See git repo on GitLab for contributors at
|
||||
https://gitlab.com/kicad/code/kicad/-/graphs/master
|
||||
|
||||
|
||||
== Document Writers
|
||||
@@ -75,6 +76,7 @@ Spanish (ES) Pedro Martin del Valle <pkicad[at]yahoo-dot-es>
|
||||
Spanish (ES) Iñigo Zuluaga <inigo_zuluaga[at]yahoo-dot-es>
|
||||
German (DE) Rafael Sokolowski <Rafael.Sokolowski[at]web-dot-de
|
||||
Japanese (JA) Kenta Yonekura <yoneken[at]kicad-dot-jp>
|
||||
Simplified Chinese (zh_CN) taotieren <admin[at]taotieren-dot-com>
|
||||
|
||||
Remy Halvick, David Briscoe, Dominique Laigle, Paul Burke
|
||||
|
||||
|
||||
+19
-3
@@ -413,7 +413,7 @@ endif()
|
||||
if( KICAD_USE_OCC )
|
||||
add_definitions( -DKICAD_USE_OCC )
|
||||
remove_definitions( -DKICAD_USE_OCE )
|
||||
unset( KICAD_USE_OCE )
|
||||
unset( KICAD_USE_OCE CACHE )
|
||||
endif()
|
||||
|
||||
if( KICAD_USE_CUSTOM_PADS )
|
||||
@@ -894,6 +894,16 @@ add_custom_target( uninstall
|
||||
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" )
|
||||
|
||||
|
||||
#################################################
|
||||
# Generate platform metadata files
|
||||
#################################################
|
||||
if( APPLE )
|
||||
include( ${CMAKE_MODULE_PATH}/WritePlatformMetadata_macos.cmake )
|
||||
elseif( UNIX )
|
||||
include( ${CMAKE_MODULE_PATH}/WritePlatformMetadata_linux.cmake )
|
||||
endif()
|
||||
|
||||
|
||||
#================================================
|
||||
# Installation
|
||||
#================================================
|
||||
@@ -919,7 +929,7 @@ if( UNIX AND NOT APPLE )
|
||||
set( UNIX_MIME_FILES ${UNIX_MIME_DIR}/mime )
|
||||
set( UNIX_ICON_FILES ${UNIX_MIME_DIR}/icons )
|
||||
set( UNIX_APPLICATIONS_FILES ${UNIX_MIME_DIR}/applications )
|
||||
set( UNIX_APPDATA_FILES resources/linux/appdata )
|
||||
set( UNIX_APPDATA_FILES ${PROJECT_BINARY_DIR}/resources/linux/appdata )
|
||||
|
||||
# Install Mime directory
|
||||
install( DIRECTORY ${UNIX_ICON_FILES}
|
||||
@@ -943,6 +953,9 @@ if( UNIX AND NOT APPLE )
|
||||
install( DIRECTORY ${UNIX_APPDATA_FILES}
|
||||
DESTINATION share
|
||||
COMPONENT resources
|
||||
FILES_MATCHING
|
||||
PATTERN "*appdata.xml"
|
||||
PATTERN "*.in" EXCLUDE
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -988,7 +1001,10 @@ add_subdirectory( plugins ) # 3D plugins must be built before kicad
|
||||
add_subdirectory( kicad ) # should follow pcbnew, eeschema
|
||||
add_subdirectory( tools )
|
||||
add_subdirectory( utils )
|
||||
add_subdirectory( qa )
|
||||
|
||||
if( KICAD_BUILD_QA_TESTS )
|
||||
add_subdirectory( qa )
|
||||
endif()
|
||||
|
||||
# Resources
|
||||
if ( KICAD_INSTALL_DEMOS )
|
||||
|
||||
@@ -27,6 +27,8 @@ macro( create_git_version_header _git_src_path )
|
||||
find_package( Git )
|
||||
|
||||
if( GIT_FOUND )
|
||||
message( STATUS "Using Git to determine build version string." )
|
||||
|
||||
set( _Git_SAVED_LC_ALL "$ENV{LC_ALL}" )
|
||||
set( ENV{LC_ALL} C )
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
#
|
||||
# This program source code file is part of KICAD, a free EDA CAD application.
|
||||
#
|
||||
# Copyright (C) 2019 Ian McInerney <Ian.S.McInerney@ieee.org>
|
||||
# Copyright (C) 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
|
||||
#
|
||||
|
||||
# This file will create the full KiCad version string. The base of this string
|
||||
# will be either the git tag followed by the commit hash (if built inside a git
|
||||
# repository), or the version from KiCadVersion.cmake. The user-provided
|
||||
# KICAD_VERSION_EXTRA is then appended to the base version string.
|
||||
|
||||
# Use git to determine the version string if it's available.
|
||||
include( ${CMAKE_MODULE_PATH}/CreateGitVersionHeader.cmake )
|
||||
create_git_version_header( ${SRC_PATH} )
|
||||
|
||||
# $KICAD_VERSION is set in KiCadVersion.cmake or by git (if it is available).
|
||||
set( KICAD_VERSION_FULL "${KICAD_VERSION}" )
|
||||
|
||||
# Optional user version information defined at configuration.
|
||||
if( KICAD_VERSION_EXTRA )
|
||||
set( KICAD_VERSION_FULL "${KICAD_VERSION_FULL}-${KICAD_VERSION_EXTRA}" )
|
||||
endif()
|
||||
@@ -35,4 +35,4 @@
|
||||
# be set after each version tag is added to the git repo. This will
|
||||
# give developers a reasonable idea where which branch was used to build
|
||||
# KiCad.
|
||||
set( KICAD_VERSION "5.1.5" )
|
||||
set( KICAD_VERSION "5.1.6" )
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
#
|
||||
# This program source code file is part of KICAD, a free EDA CAD application.
|
||||
#
|
||||
# Copyright (C) 2019 Ian McInerney <Ian.S.McInerney@ieee.org>
|
||||
# Copyright (C) 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
|
||||
#
|
||||
|
||||
# This file will configure the linux appdata.xml file to include the version
|
||||
# and build date.
|
||||
|
||||
message( STATUS "Creating linux metadata" )
|
||||
|
||||
# Create the KiCad version strings
|
||||
set( SRC_PATH ${PROJECT_SOURCE_DIR} )
|
||||
include( ${CMAKE_MODULE_PATH}/KiCadVersion.cmake )
|
||||
include( ${CMAKE_MODULE_PATH}/KiCadFullVersion.cmake )
|
||||
|
||||
# Create the date of the configure
|
||||
string( TIMESTAMP KICAD_CONFIG_TIMESTAMP "%Y-%m-%d" )
|
||||
|
||||
# Configure the KiCad appdata file
|
||||
configure_file( ${PROJECT_SOURCE_DIR}/resources/linux/appdata/kicad.appdata.xml.in
|
||||
${PROJECT_BINARY_DIR}/resources/linux/appdata/kicad.appdata.xml
|
||||
@ONLY )
|
||||
|
||||
# Ensure the file was configured successfully
|
||||
if( NOT EXISTS ${PROJECT_BINARY_DIR}/resources/linux/appdata/kicad.appdata.xml )
|
||||
message( FATAL_ERROR "Configuration failed to write file kicad.appdata.xml." )
|
||||
endif()
|
||||
@@ -0,0 +1,63 @@
|
||||
#
|
||||
# This program source code file is part of KICAD, a free EDA CAD application.
|
||||
#
|
||||
# Copyright (C) 2019 Ian McInerney <Ian.S.McInerney@ieee.org>
|
||||
# Copyright (C) 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
|
||||
#
|
||||
|
||||
# This file will configure the MacOS info.plist files to include the version
|
||||
# and build date.
|
||||
|
||||
message( STATUS "Creating MacOS metadata" )
|
||||
|
||||
# Create the KiCad version strings
|
||||
set( SRC_PATH ${PROJECT_SOURCE_DIR} )
|
||||
include( ${CMAKE_MODULE_PATH}/KiCadVersion.cmake )
|
||||
include( ${CMAKE_MODULE_PATH}/KiCadFullVersion.cmake )
|
||||
|
||||
|
||||
# Configure each plist file from the respurces directory and store it in the build directory
|
||||
configure_file( ${PROJECT_SOURCE_DIR}/resources/macos/plist/bitmap2component.Info.plist.in
|
||||
${PROJECT_BINARY_DIR}/bitmap2component/Info.plist
|
||||
@ONLY )
|
||||
|
||||
configure_file( ${PROJECT_SOURCE_DIR}/resources/macos/plist/eeschema.Info.plist.in
|
||||
${PROJECT_BINARY_DIR}/eeschema/Info.plist
|
||||
@ONLY )
|
||||
|
||||
configure_file( ${PROJECT_SOURCE_DIR}/resources/macos/plist/gerbview.Info.plist.in
|
||||
${PROJECT_BINARY_DIR}/gerbview/Info.plist
|
||||
@ONLY )
|
||||
|
||||
configure_file( ${PROJECT_SOURCE_DIR}/resources/macos/plist/kicad.Info.plist.in
|
||||
${PROJECT_BINARY_DIR}/kicad/Info.plist
|
||||
@ONLY )
|
||||
|
||||
configure_file( ${PROJECT_SOURCE_DIR}/resources/macos/plist/pcb_calculator.Info.plist.in
|
||||
${PROJECT_BINARY_DIR}/pcb_calculator/Info.plist
|
||||
@ONLY )
|
||||
|
||||
configure_file( ${PROJECT_SOURCE_DIR}/resources/macos/plist/pcbnew.Info.plist.in
|
||||
${PROJECT_BINARY_DIR}/pcbnew/Info.plist
|
||||
@ONLY )
|
||||
|
||||
configure_file( ${PROJECT_SOURCE_DIR}/resources/macos/plist/pleditor.Info.plist.in
|
||||
${PROJECT_BINARY_DIR}/pagelayout_editor/Info.plist
|
||||
@ONLY )
|
||||
@@ -22,25 +22,9 @@
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
#
|
||||
|
||||
# Automagically create version header file if the version string was
|
||||
# not defined during the build configuration. If CreateGitVersionHeader
|
||||
# cannot determine the current repo version, a version.h file is still
|
||||
# created with KICAD_VERSION set in KiCadVersion.cmake.
|
||||
# Create the KiCad version strings
|
||||
include( ${CMAKE_MODULE_PATH}/KiCadVersion.cmake )
|
||||
|
||||
# Always use git if it's available to determine the version string.
|
||||
message( STATUS "Using Git to determine build version string." )
|
||||
include( ${CMAKE_MODULE_PATH}/CreateGitVersionHeader.cmake )
|
||||
create_git_version_header( ${SRC_PATH} )
|
||||
|
||||
# $KICAD_VERSION will always be set to something. Even if it is the default
|
||||
# value set in KiCadVersion.cmake
|
||||
set( KICAD_VERSION_FULL "${KICAD_VERSION}" )
|
||||
|
||||
# Optional user version information defined at configuration.
|
||||
if( KICAD_VERSION_EXTRA )
|
||||
set( KICAD_VERSION_FULL "${KICAD_VERSION_FULL}-${KICAD_VERSION_EXTRA}" )
|
||||
endif()
|
||||
include( ${CMAKE_MODULE_PATH}/KiCadFullVersion.cmake )
|
||||
|
||||
set( _wvh_new_version_text
|
||||
"/* Do not modify this file, it was automatically generated by CMake. */
|
||||
|
||||
@@ -222,7 +222,7 @@ and can cause Pcbnew to crash if Python scripts create an invalid object state w
|
||||
|
||||
The KiCad version string is defined by the output of `git describe --dirty` when git is available
|
||||
or the version string defined in CMakeModules/KiCadVersion.cmake with the value of
|
||||
KICAD_VERSION_EXTRA appended to the former. If the KICAD_VERSION_EXTRA variable is not define,
|
||||
KICAD_VERSION_EXTRA appended to the former. If the KICAD_VERSION_EXTRA variable is not defined,
|
||||
it is not appended to the version string. If the KICAD_VERSION_EXTRA variable is defined it
|
||||
is appended along with a leading '-' to the full version string as follows:
|
||||
|
||||
|
||||
@@ -54,11 +54,8 @@ target_link_libraries( bitmap2component
|
||||
)
|
||||
|
||||
if( APPLE )
|
||||
include( ${CMAKE_MODULE_PATH}/KiCadVersion.cmake )
|
||||
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist @ONLY )
|
||||
|
||||
set_target_properties( bitmap2component PROPERTIES
|
||||
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist
|
||||
MACOSX_BUNDLE_INFO_PLIST ${PROJECT_BINARY_DIR}/bitmap2component/Info.plist
|
||||
)
|
||||
|
||||
# put individual bundle outside of main bundle as a first step
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array/>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>bitmap2component</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string></string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>bitmap2component.icns</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.kicad-pcb.bitmap2component</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleLongVersionString</key>
|
||||
<string>@KICAD_VERSION_FULL@</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>Bitmap 2 Component</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>@KICAD_VERSION@</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>@KICAD_VERSION_FULL@</string>
|
||||
<key>CSResourcesFileMapped</key>
|
||||
<true/>
|
||||
<key>LSRequiresCarbon</key>
|
||||
<true/>
|
||||
<key>NSRequiresAquaSystemAppearance</key>
|
||||
<true/>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string></string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<string>True</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -153,10 +153,10 @@ install( TARGETS lib_kicad
|
||||
endif()
|
||||
|
||||
|
||||
# KiCad build version string defaults to "no-vcs-found" which forces the build version header
|
||||
# command to look for git to create the version string header when the .git path is found in
|
||||
# the source path.
|
||||
set( KICAD_BRANCH_NAME "" CACHE STRING "KiCad repository name." )
|
||||
# The build version string defaults to the value in the KiCadVersion.cmake file.
|
||||
# If being built inside a git repository, the git tag and commit hash are used to create
|
||||
# a new version string instead. The user can supply an additional string to be appended
|
||||
# to the end inside the KICAD_VERSION_EXTRA variable
|
||||
set( KICAD_VERSION_EXTRA "" CACHE STRING
|
||||
"User defined configuration string to append to KiCad version." )
|
||||
|
||||
@@ -164,8 +164,6 @@ set( KICAD_VERSION_EXTRA "" CACHE STRING
|
||||
add_custom_target(
|
||||
version_header ALL
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DKICAD_VERSION=${KICAD_VERSION}
|
||||
-DKICAD_BRANCH_NAME=${KICAD_BRANCH_NAME}
|
||||
-DKICAD_VERSION_EXTRA=${KICAD_VERSION_EXTRA}
|
||||
-DOUTPUT_FILE=${CMAKE_BINARY_DIR}/kicad_build_version.h
|
||||
-DSRC_PATH=${PROJECT_SOURCE_DIR}
|
||||
@@ -278,6 +276,7 @@ set( COMMON_SRCS
|
||||
${PLOTTERS_CONTROL_SRCS}
|
||||
advanced_config.cpp
|
||||
array_options.cpp
|
||||
base64.cpp
|
||||
base_struct.cpp
|
||||
bezier_curves.cpp
|
||||
bin_mod.cpp
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2019 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* @author Seth Hillbrand <seth@kipro-pcb.com>
|
||||
*
|
||||
* 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 3
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <base64.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
|
||||
static const uint8_t ENCODE_BASE64[64] = {
|
||||
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
|
||||
0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
|
||||
0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
|
||||
0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
|
||||
0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E,
|
||||
0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
|
||||
0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33,
|
||||
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F,
|
||||
};
|
||||
|
||||
static const uint8_t E = -1;
|
||||
|
||||
static const uint8_t DECODE_BASE64[128] = {
|
||||
/* 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xA 0xB 0xC 0xD 0xE 0xF */
|
||||
E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E,
|
||||
E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E,
|
||||
E, E, E, E, E, E, E, E, E, E, E, 62, E, E, E, 63,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, E, E, E, E, E, E,
|
||||
E, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, E, E, E, E, E,
|
||||
E, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, E, E, E, E, E,
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace base64
|
||||
{
|
||||
size_t encode_length( size_t aInputLen )
|
||||
{
|
||||
return 4 * ( ( aInputLen + 2 ) / 3 ) + ( aInputLen + 2 ) % 3 - 2;
|
||||
}
|
||||
|
||||
|
||||
size_t decode_length( size_t aInputLen )
|
||||
{
|
||||
if( aInputLen % 4 == 1 )
|
||||
return 0;
|
||||
else
|
||||
return 3 * ( ( aInputLen + 2 ) / 4 ) + ( aInputLen + 2 ) % 4 - 2;
|
||||
}
|
||||
|
||||
|
||||
void encode( const std::vector<uint8_t>& aInput, std::vector<uint8_t>& aOutput )
|
||||
{
|
||||
size_t end = ( aInput.size() / 3 ) * 3;
|
||||
aOutput.reserve( encode_length( aInput.size() ) );
|
||||
|
||||
for( size_t i = 0; i < end; i += 3 )
|
||||
{
|
||||
unsigned value = ( aInput[i] << 16 ) | ( aInput[i + 1] << 8 ) | aInput[i + 2] ;
|
||||
|
||||
aOutput.emplace_back( ENCODE_BASE64[( value >> 18 ) & 0x3F] );
|
||||
aOutput.emplace_back( ENCODE_BASE64[( value >> 12 ) & 0x3F] );
|
||||
aOutput.emplace_back( ENCODE_BASE64[( value >> 6 ) & 0x3F] );
|
||||
aOutput.emplace_back( ENCODE_BASE64[value & 0x3F] );
|
||||
}
|
||||
|
||||
size_t remainder = aInput.size() - end;
|
||||
|
||||
if( remainder )
|
||||
{
|
||||
unsigned value = aInput[end];
|
||||
|
||||
if( remainder == 2 )
|
||||
{
|
||||
value = ( value << 10 ) | ( aInput[end + 1] << 2 );
|
||||
aOutput.emplace_back( ENCODE_BASE64[( value >> 12 ) & 0x3F] );
|
||||
}
|
||||
else
|
||||
{
|
||||
value <<= 4;
|
||||
}
|
||||
|
||||
aOutput.emplace_back( ENCODE_BASE64[( value >> 6 ) & 0x3F] );
|
||||
aOutput.emplace_back( ENCODE_BASE64[value & 0x3F] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void decode(const std::vector<uint8_t>& aInput, std::vector<uint8_t>& aOutput )
|
||||
{
|
||||
size_t end = ( aInput.size() / 4 ) * 4;
|
||||
size_t decode_size = decode_length( aInput.size() );
|
||||
|
||||
if( !decode_size )
|
||||
return;
|
||||
|
||||
aOutput.reserve( decode_size );
|
||||
|
||||
for( size_t i = 0; i < end; i++ )
|
||||
{
|
||||
unsigned value = ( DECODE_BASE64[aInput[i] & 0x7F] << 18 ) |
|
||||
( DECODE_BASE64[aInput[i + 1] & 0x7F] << 12 ) |
|
||||
( DECODE_BASE64[aInput[i + 2] & 0x7F] << 6 ) |
|
||||
DECODE_BASE64[aInput[i + 3] & 0x7F];
|
||||
|
||||
aOutput.emplace_back( ( value >> 16 ) & 0xff );
|
||||
aOutput.emplace_back( ( value >> 8 ) & 0xff );
|
||||
aOutput.emplace_back( value & 0xff );
|
||||
}
|
||||
|
||||
size_t remainder = aInput.size() - end;
|
||||
|
||||
if( remainder )
|
||||
{
|
||||
unsigned value = ( ( DECODE_BASE64[aInput[end] & 0x7F] ) << 6 ) |
|
||||
( DECODE_BASE64[aInput[end + 1] & 0x7F] );
|
||||
|
||||
if( remainder == 3 )
|
||||
{
|
||||
value = ( value << 6 ) | ( DECODE_BASE64[aInput[end + 2] & 0x7F] );
|
||||
value >>= 2;
|
||||
|
||||
aOutput.emplace_back( ( value >> 8 ) & 0xff );
|
||||
}
|
||||
else
|
||||
{
|
||||
value >>= 4;
|
||||
}
|
||||
aOutput[0] = value & 0xff ;
|
||||
}
|
||||
}
|
||||
|
||||
} // base64
|
||||
+42
-336
@@ -1,8 +1,7 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2014 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2014-2017 KiCad Developers, see CHANGELOG.TXT for contributors.
|
||||
* Copyright (C) 2014-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
|
||||
@@ -26,362 +25,69 @@
|
||||
/* routines to handle bezier curves */
|
||||
/************************************/
|
||||
|
||||
#include <fctsys.h>
|
||||
#include <bezier_curves.h>
|
||||
|
||||
|
||||
static inline double calc_sq_distance( int x1, int y1, int x2, int y2 )
|
||||
BEZIER_POLY::BEZIER_POLY( const std::vector<wxPoint>& aControlPoints )
|
||||
{
|
||||
int dx = x2 - x1;
|
||||
int dy = y2 - y1;
|
||||
for( unsigned ii = 0; ii < aControlPoints.size(); ++ii )
|
||||
m_ctrlPts.emplace_back( VECTOR2D( aControlPoints[ii] ) );
|
||||
|
||||
return (double)dx * dx + (double)dy * dy;
|
||||
}
|
||||
|
||||
|
||||
static inline double sqrt_len( int dx, int dy )
|
||||
{
|
||||
return ((double)dx * dx) + ((double)dy * dy);
|
||||
m_minSegLen = 0.0;
|
||||
}
|
||||
|
||||
|
||||
void BEZIER_POLY::GetPoly( std::vector<wxPoint>& aOutput, int aMinSegLen )
|
||||
{
|
||||
wxCHECK( !m_ctrlPts.empty(), /* void */ );
|
||||
m_minSegLen = std::max( 1, aMinSegLen );
|
||||
m_output = &aOutput;
|
||||
m_output->clear();
|
||||
m_output->push_back( wxPoint( m_ctrlPts.front() ) );
|
||||
aOutput.clear();
|
||||
std::vector<VECTOR2D> buffer;
|
||||
GetPoly( buffer, double( aMinSegLen ) );
|
||||
|
||||
// Only quadratic and cubic Bezier curves are handled
|
||||
if( m_ctrlPts.size() == 3 )
|
||||
recursiveBezier( m_ctrlPts[0].x, m_ctrlPts[0].y,
|
||||
m_ctrlPts[1].x, m_ctrlPts[1].y,
|
||||
m_ctrlPts[2].x, m_ctrlPts[2].y, 0 );
|
||||
|
||||
else if( m_ctrlPts.size() == 4 )
|
||||
recursiveBezier( m_ctrlPts[0].x, m_ctrlPts[0].y,
|
||||
m_ctrlPts[1].x, m_ctrlPts[1].y,
|
||||
m_ctrlPts[2].x, m_ctrlPts[2].y,
|
||||
m_ctrlPts[3].x, m_ctrlPts[3].y, 0 );
|
||||
|
||||
m_output->push_back( wxPoint( m_ctrlPts.back() ) );
|
||||
for( unsigned ii = 0; ii < buffer.size(); ++ii )
|
||||
aOutput.emplace_back( wxPoint( int( buffer[ii].x ), int( buffer[ii].y ) ) );
|
||||
}
|
||||
|
||||
|
||||
void BEZIER_POLY::recursiveBezier( int x1, int y1, int x2, int y2,
|
||||
int x3, int y3, unsigned int level )
|
||||
void BEZIER_POLY::GetPoly( std::vector<VECTOR2D>& aOutput, double aMinSegLen )
|
||||
{
|
||||
if( level > recursion_limit )
|
||||
return;
|
||||
wxASSERT( m_ctrlPts.size() == 4 );
|
||||
// FIXME Brute force method, use a better (recursive?) algorithm
|
||||
// with a max error value.
|
||||
// to optimize the number of segments
|
||||
#define CURVE_POINTS 32
|
||||
double dt = 1.0 / CURVE_POINTS;
|
||||
|
||||
// Calculate all the mid-points of the line segments
|
||||
//----------------------
|
||||
int x12 = (x1 + x2) / 2;
|
||||
int y12 = (y1 + y2) / 2;
|
||||
int x23 = (x2 + x3) / 2;
|
||||
int y23 = (y2 + y3) / 2;
|
||||
int x123 = (x12 + x23) / 2;
|
||||
int y123 = (y12 + y23) / 2;
|
||||
aOutput.clear();
|
||||
aOutput.push_back( m_ctrlPts[0] );
|
||||
|
||||
int dx = x3 - x1;
|
||||
int dy = y3 - y1;
|
||||
double d = fabs( ((double) (x2 - x3) * dy) - ((double) (y2 - y3) * dx ) );
|
||||
double da;
|
||||
// If the Bezier curve is degenerated (straight line), skip intermediate points:
|
||||
bool degenerated = m_ctrlPts[0] == m_ctrlPts[1] && m_ctrlPts[2] == m_ctrlPts[3];
|
||||
|
||||
if( d > curve_collinearity_epsilon )
|
||||
if( !degenerated )
|
||||
{
|
||||
// Regular case
|
||||
//-----------------
|
||||
if( d * d <= distance_tolerance_square * (dx * dx + dy * dy) )
|
||||
for( int ii = 1; ii < CURVE_POINTS; ii++ )
|
||||
{
|
||||
// If the curvature doesn't exceed the distance_tolerance value
|
||||
// we tend to finish subdivisions.
|
||||
//----------------------
|
||||
if( angle_tolerance < curve_angle_tolerance_epsilon )
|
||||
{
|
||||
addSegment( wxPoint( x123, y123 ) );
|
||||
return;
|
||||
}
|
||||
double t = dt * ii;
|
||||
double omt = 1.0 - t;
|
||||
double omt2 = omt * omt;
|
||||
double omt3 = omt * omt2;
|
||||
double t2 = t * t;
|
||||
double t3 = t * t2;
|
||||
|
||||
// Angle & Cusp Condition
|
||||
//----------------------
|
||||
da = fabs( atan2( (double) ( y3 - y2 ), (double) ( x3 - x2 ) ) -
|
||||
atan2( (double) ( y2 - y1 ), (double) ( x2 - x1 ) ) );
|
||||
if( da >=M_PI )
|
||||
da = 2 * M_PI - da;
|
||||
VECTOR2D vertex = omt3 * m_ctrlPts[0]
|
||||
+ 3.0 * t * omt2 * m_ctrlPts[1]
|
||||
+ 3.0 * t2 * omt * m_ctrlPts[2]
|
||||
+ t3 * m_ctrlPts[3];
|
||||
|
||||
if( da < angle_tolerance )
|
||||
{
|
||||
// Finally we can stop the recursion
|
||||
//----------------------
|
||||
addSegment( wxPoint( x123, y123 ) );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Collinear case
|
||||
//------------------
|
||||
da = sqrt_len(dx, dy);
|
||||
if( da == 0 )
|
||||
{
|
||||
d = calc_sq_distance( x1, y1, x2, y2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
d = ( (double)(x2 - x1) * dx + (double)(y2 - y1) * dy ) / da;
|
||||
if( d > 0 && d < 1 )
|
||||
{
|
||||
// Simple collinear case, 1---2---3
|
||||
// We can leave just two endpoints
|
||||
return;
|
||||
}
|
||||
if( d <= 0 )
|
||||
d = calc_sq_distance( x2, y2, x1, y1 );
|
||||
else if( d >= 1 )
|
||||
d = calc_sq_distance( x2, y2, x3, y3 );
|
||||
else
|
||||
d = calc_sq_distance( x2, y2, x1 + (int) d * dx,
|
||||
y1 + (int) d * dy );
|
||||
}
|
||||
if( d < distance_tolerance_square )
|
||||
{
|
||||
addSegment( wxPoint( x2, y2 ) );
|
||||
return;
|
||||
// a minimal filter on the lenght of the segment being created:
|
||||
// The offset from last point:
|
||||
VECTOR2D delta = vertex - aOutput.back();
|
||||
double dist = delta.EuclideanNorm();
|
||||
|
||||
if( dist > aMinSegLen )
|
||||
aOutput.push_back( vertex );
|
||||
}
|
||||
}
|
||||
|
||||
// Continue subdivision
|
||||
//----------------------
|
||||
recursiveBezier( x1, y1, x12, y12, x123, y123, level + 1 );
|
||||
recursiveBezier( x123, y123, x23, y23, x3, y3, level + 1 );
|
||||
}
|
||||
|
||||
|
||||
void BEZIER_POLY::recursiveBezier( int x1, int y1, int x2, int y2,
|
||||
int x3, int y3, int x4, int y4, unsigned int level )
|
||||
{
|
||||
if( level > recursion_limit )
|
||||
return;
|
||||
|
||||
// Calculate all the mid-points of the line segments
|
||||
//----------------------
|
||||
int x12 = (x1 + x2) / 2;
|
||||
int y12 = (y1 + y2) / 2;
|
||||
int x23 = (x2 + x3) / 2;
|
||||
int y23 = (y2 + y3) / 2;
|
||||
int x34 = (x3 + x4) / 2;
|
||||
int y34 = (y3 + y4) / 2;
|
||||
int x123 = (x12 + x23) / 2;
|
||||
int y123 = (y12 + y23) / 2;
|
||||
int x234 = (x23 + x34) / 2;
|
||||
int y234 = (y23 + y34) / 2;
|
||||
int x1234 = (x123 + x234) / 2;
|
||||
int y1234 = (y123 + y234) / 2;
|
||||
|
||||
|
||||
// Try to approximate the full cubic curve by a single straight line
|
||||
//------------------
|
||||
int dx = x4 - x1;
|
||||
int dy = y4 - y1;
|
||||
|
||||
double d2 = fabs( (double) ( (x2 - x4) * dy - (y2 - y4) * dx ) );
|
||||
double d3 = fabs( (double) ( (x3 - x4) * dy - (y3 - y4) * dx ) );
|
||||
double da1, da2, k;
|
||||
|
||||
switch( (int(d2 > curve_collinearity_epsilon) << 1) +
|
||||
int(d3 > curve_collinearity_epsilon) )
|
||||
{
|
||||
case 0:
|
||||
|
||||
// All collinear OR p1==p4
|
||||
//----------------------
|
||||
k = dx * dx + dy * dy;
|
||||
if( k == 0 )
|
||||
{
|
||||
d2 = calc_sq_distance( x1, y1, x2, y2 );
|
||||
d3 = calc_sq_distance( x4, y4, x3, y3 );
|
||||
}
|
||||
else
|
||||
{
|
||||
k = 1 / k;
|
||||
da1 = x2 - x1;
|
||||
da2 = y2 - y1;
|
||||
d2 = k * (da1 * dx + da2 * dy);
|
||||
da1 = x3 - x1;
|
||||
da2 = y3 - y1;
|
||||
d3 = k * (da1 * dx + da2 * dy);
|
||||
if( d2 > 0 && d2 < 1 && d3 > 0 && d3 < 1 )
|
||||
{
|
||||
// Simple collinear case, 1---2---3---4
|
||||
// We can leave just two endpoints
|
||||
return;
|
||||
}
|
||||
if( d2 <= 0 )
|
||||
d2 = calc_sq_distance( x2, y2, x1, y1 );
|
||||
else if( d2 >= 1 )
|
||||
d2 = calc_sq_distance( x2, y2, x4, y4 );
|
||||
else
|
||||
d2 = calc_sq_distance( x2, y2, x1 + (int) d2 * dx,
|
||||
y1 + (int) d2 * dy );
|
||||
|
||||
if( d3 <= 0 )
|
||||
d3 = calc_sq_distance( x3, y3, x1, y1 );
|
||||
else if( d3 >= 1 )
|
||||
d3 = calc_sq_distance( x3, y3, x4, y4 );
|
||||
else
|
||||
d3 = calc_sq_distance( x3, y3, x1 + (int) d3 * dx,
|
||||
y1 + (int) d3 * dy );
|
||||
}
|
||||
if( d2 > d3 )
|
||||
{
|
||||
if( d2 < distance_tolerance_square )
|
||||
{
|
||||
addSegment( wxPoint( x2, y2 ) );
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( d3 < distance_tolerance_square )
|
||||
{
|
||||
addSegment( wxPoint( x3, y3 ) );
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
||||
// p1,p2,p4 are collinear, p3 is significant
|
||||
//----------------------
|
||||
if( d3 * d3 <= distance_tolerance_square * sqrt_len(dx, dy) )
|
||||
{
|
||||
if( angle_tolerance < curve_angle_tolerance_epsilon )
|
||||
{
|
||||
addSegment( wxPoint( x23, y23 ) );
|
||||
return;
|
||||
}
|
||||
|
||||
// Angle Condition
|
||||
//----------------------
|
||||
da1 = fabs( atan2( (double) ( y4 - y3 ), (double) ( x4 - x3 ) ) -
|
||||
atan2( (double) ( y3 - y2 ), (double) ( x3 - x2 ) ) );
|
||||
if( da1 >= M_PI )
|
||||
da1 = 2 * M_PI - da1;
|
||||
|
||||
if( da1 < angle_tolerance )
|
||||
{
|
||||
addSegment( wxPoint( x2, y2 ) );
|
||||
addSegment( wxPoint( x3, y3 ) );
|
||||
return;
|
||||
}
|
||||
|
||||
if( cusp_limit != 0.0 )
|
||||
{
|
||||
if( da1 > cusp_limit )
|
||||
{
|
||||
addSegment( wxPoint( x3, y3 ) );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
||||
// p1,p3,p4 are collinear, p2 is significant
|
||||
//----------------------
|
||||
if( d2 * d2 <= distance_tolerance_square * sqrt_len(dx, dy) )
|
||||
{
|
||||
if( angle_tolerance < curve_angle_tolerance_epsilon )
|
||||
{
|
||||
addSegment( wxPoint( x23, y23 ) );
|
||||
return;
|
||||
}
|
||||
|
||||
// Angle Condition
|
||||
//----------------------
|
||||
da1 = fabs( atan2( (double) ( y3 - y2 ), (double) ( x3 - x2 ) ) -
|
||||
atan2( (double) ( y2 - y1 ), (double) ( x2 - x1 ) ) );
|
||||
if( da1 >= M_PI )
|
||||
da1 = 2 * M_PI - da1;
|
||||
|
||||
if( da1 < angle_tolerance )
|
||||
{
|
||||
addSegment( wxPoint( x2, y2 ) );
|
||||
addSegment( wxPoint( x3, y3 ) );
|
||||
return;
|
||||
}
|
||||
|
||||
if( cusp_limit != 0.0 )
|
||||
{
|
||||
if( da1 > cusp_limit )
|
||||
{
|
||||
addSegment( wxPoint( x2, y2 ) );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
|
||||
// Regular case
|
||||
//-----------------
|
||||
if( (d2 + d3) * (d2 + d3) <= distance_tolerance_square * sqrt_len(dx, dy) )
|
||||
{
|
||||
// If the curvature doesn't exceed the distance_tolerance value
|
||||
// we tend to finish subdivisions.
|
||||
//----------------------
|
||||
if( angle_tolerance < curve_angle_tolerance_epsilon )
|
||||
{
|
||||
addSegment( wxPoint( x23, y23 ) );
|
||||
return;
|
||||
}
|
||||
|
||||
// Angle & Cusp Condition
|
||||
//----------------------
|
||||
k = atan2( (double) ( y3 - y2 ), (double) ( x3 - x2 ) );
|
||||
da1 = fabs( k - atan2( (double) ( y2 - y1 ),
|
||||
(double) ( x2 - x1 ) ) );
|
||||
da2 = fabs( atan2( (double) ( y4 - y3 ),
|
||||
(double) ( x4 - x3 ) ) - k );
|
||||
if( da1 >= M_PI )
|
||||
da1 = 2 * M_PI - da1;
|
||||
if( da2 >= M_PI )
|
||||
da2 = 2 * M_PI - da2;
|
||||
|
||||
if( da1 + da2 < angle_tolerance )
|
||||
{
|
||||
// Finally we can stop the recursion
|
||||
//----------------------
|
||||
addSegment( wxPoint( x23, y23 ) );
|
||||
return;
|
||||
}
|
||||
|
||||
if( cusp_limit != 0.0 )
|
||||
{
|
||||
if( da1 > cusp_limit )
|
||||
{
|
||||
addSegment( wxPoint( x2, y2 ) );
|
||||
return;
|
||||
}
|
||||
|
||||
if( da2 > cusp_limit )
|
||||
{
|
||||
addSegment( wxPoint( x3, y3 ) );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Continue subdivision
|
||||
//----------------------
|
||||
recursiveBezier( x1, y1, x12, y12, x123, y123, x1234, y1234, level + 1 );
|
||||
recursiveBezier( x1234, y1234, x234, y234, x34, y34, x4, y4, level + 1 );
|
||||
if( aOutput.back() != m_ctrlPts[3] )
|
||||
aOutput.push_back( m_ctrlPts[3] );
|
||||
}
|
||||
|
||||
@@ -240,18 +240,23 @@ void BITMAP_BASE::DrawBitmap( wxDC* aDC, const wxPoint& aPos )
|
||||
aDC->SetLogicalOrigin( logicalOriginX / GetScalingFactor(),
|
||||
logicalOriginY / GetScalingFactor() );
|
||||
|
||||
pos.x = KiROUND( pos.x / GetScalingFactor() );
|
||||
pos.y = KiROUND( pos.y / GetScalingFactor() );
|
||||
size.x = KiROUND( size.x / GetScalingFactor() );
|
||||
size.y = KiROUND( size.y / GetScalingFactor() );
|
||||
aDC->SetClippingRegion( pos, size );
|
||||
|
||||
if( GetGRForceBlackPenState() )
|
||||
{
|
||||
wxBitmap result( m_bitmap->ConvertToImage().ConvertToGreyscale() );
|
||||
aDC->DrawBitmap( result, KiROUND( pos.x / GetScalingFactor() ),
|
||||
KiROUND( pos.y / GetScalingFactor() ), true );
|
||||
aDC->DrawBitmap( result, pos.x, pos.y, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
aDC->DrawBitmap( *m_bitmap, KiROUND( pos.x / GetScalingFactor() ),
|
||||
KiROUND( pos.y / GetScalingFactor() ), true );
|
||||
aDC->DrawBitmap( *m_bitmap, pos.x, pos.y, true );
|
||||
}
|
||||
|
||||
aDC->DestroyClippingRegion();
|
||||
aDC->SetUserScale( scale, scale );
|
||||
aDC->SetLogicalOrigin( logicalOriginX, logicalOriginY );
|
||||
}
|
||||
|
||||
+32
-13
@@ -57,33 +57,46 @@ using KIGFX::COLOR4D;
|
||||
COLOR4D g_GhostColor;
|
||||
|
||||
|
||||
// When reading/writing files, we need to swtich to setlocale( LC_NUMERIC, "C" ).
|
||||
// Works fine to read/write files with floating point numbers.
|
||||
// We can call setlocale( LC_NUMERIC, "C" ) of wxLocale( "C", "C", "C", false )
|
||||
// wxWidgets discourage a direct call to setlocale
|
||||
// However, for us, calling wxLocale( "C", "C", "C", false ) has a unwanted effect:
|
||||
// The I18N translations are no longer active, because the English dixtionary is selected.
|
||||
// To read files, this is not a major issues, but the resul can differ
|
||||
// from using setlocale(xx, "C").
|
||||
// Previouly, we called setlocale( LC_NUMERIC, "C" )
|
||||
// The old code will be removed when calling wxLocale( "C", "C", "C", false )
|
||||
// is fully tested, and all issues fixed
|
||||
#define USE_WXLOCALE 1 /* 0 to call setlocale, 1 to call wxLocale */
|
||||
|
||||
// On Windows, when using setlocale, a wx alert is generated
|
||||
// in some cases (reading a bitmap for instance)
|
||||
// So we disable alerts during the time a file is read or written
|
||||
#if !USE_WXLOCALE
|
||||
#if defined( _WIN32 ) && defined( DEBUG )
|
||||
// a wxAssertHandler_t function to filter wxWidgets alert messages when reading/writing a file
|
||||
// when switching the locale to LC_NUMERIC, "C"
|
||||
// It is used in class LOCALE_IO to hide a useless (in kicad) wxWidgets alert message
|
||||
void KiAssertFilter( const wxString &file, int line,
|
||||
const wxString &func, const wxString &cond,
|
||||
const wxString &msg)
|
||||
const wxString &func, const wxString &cond,
|
||||
const wxString &msg)
|
||||
{
|
||||
if( !msg.Contains( "Decimal separator mismatch" ) )
|
||||
wxTheApp->OnAssertFailure( file, line, func, cond, msg );
|
||||
wxTheApp->OnAssertFailure( file.c_str(), line, func.c_str(), cond.c_str(), msg.c_str() );
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
std::atomic<unsigned int> LOCALE_IO::m_c_count( 0 );
|
||||
|
||||
|
||||
// Note on Windows, setlocale( LC_NUMERIC, "C" ) works fine to read/write
|
||||
// files with floating point numbers, but generates a overzealous wx alert
|
||||
// in some cases (reading a bitmap for instance)
|
||||
// So we disable alerts during the time a file is read or written
|
||||
|
||||
LOCALE_IO::LOCALE_IO()
|
||||
LOCALE_IO::LOCALE_IO() : m_wxLocale( nullptr )
|
||||
{
|
||||
// use thread safe, atomic operation
|
||||
if( m_c_count++ == 0 )
|
||||
{
|
||||
#if USE_WXLOCALE
|
||||
m_wxLocale = new wxLocale( "C", "C", "C", false );
|
||||
#else
|
||||
// Store the user locale name, to restore this locale later, in dtor
|
||||
m_user_locale = setlocale( LC_NUMERIC, nullptr );
|
||||
#if defined( _WIN32 ) && defined( DEBUG )
|
||||
@@ -92,6 +105,7 @@ LOCALE_IO::LOCALE_IO()
|
||||
#endif
|
||||
// Switch the locale to C locale, to read/write files with fp numbers
|
||||
setlocale( LC_NUMERIC, "C" );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,10 +116,15 @@ LOCALE_IO::~LOCALE_IO()
|
||||
if( --m_c_count == 0 )
|
||||
{
|
||||
// revert to the user locale
|
||||
#if USE_WXLOCALE
|
||||
delete m_wxLocale; // Deleting m_wxLocale restored previous locale
|
||||
m_wxLocale = nullptr;
|
||||
#else
|
||||
setlocale( LC_NUMERIC, m_user_locale.c_str() );
|
||||
#if defined( _WIN32 ) && defined( DEBUG )
|
||||
// Enable wxWidgets alerts
|
||||
wxSetDefaultAssertHandler();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -425,7 +444,7 @@ wxString KIwxExpandEnvVars(const wxString& str)
|
||||
if( !expanded )
|
||||
strResult << (wxChar)bracket;
|
||||
|
||||
str_m = str[++m];
|
||||
m++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -89,10 +89,10 @@ bool KIDIALOG::Show( bool aShow )
|
||||
return it->second;
|
||||
}
|
||||
|
||||
bool ret = wxRichMessageDialog::Show( aShow );
|
||||
int ret = wxRichMessageDialog::Show( aShow );
|
||||
|
||||
// Has the user asked not to show the dialog again
|
||||
if( IsCheckBoxChecked() )
|
||||
// Has the user asked not to show the dialog again and it was confirmed
|
||||
if( IsCheckBoxChecked() && ret != wxID_CANCEL )
|
||||
doNotShowAgainDlgs[m_hash] = ret;
|
||||
|
||||
return ret;
|
||||
@@ -110,7 +110,7 @@ int KIDIALOG::ShowModal()
|
||||
int ret = wxRichMessageDialog::ShowModal();
|
||||
|
||||
// Has the user asked not to show the dialog again
|
||||
if( IsCheckBoxChecked() )
|
||||
if( IsCheckBoxChecked() && ret != wxID_CANCEL )
|
||||
doNotShowAgainDlgs[m_hash] = ret;
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -64,7 +64,7 @@ static void buildKicadAboutBanner( EDA_BASE_FRAME* aParent, ABOUT_APP_INFO& aInf
|
||||
aInfo.SetAppName( Pgm().App().GetAppName() );
|
||||
|
||||
/* Copyright information */
|
||||
aInfo.SetCopyright( "(C) 1992-2019 KiCad Developers Team" );
|
||||
aInfo.SetCopyright( "(C) 1992-2020 KiCad Developers Team" );
|
||||
|
||||
/* KiCad build version */
|
||||
wxString version;
|
||||
@@ -152,8 +152,7 @@ static void buildKicadAboutBanner( EDA_BASE_FRAME* aParent, ABOUT_APP_INFO& aInf
|
||||
description << "<ul>";
|
||||
description << "<li>"
|
||||
<< _( "Report or examine bugs - " )
|
||||
<< HtmlHyperlink( "https://bugs.launchpad.net/kicad/+bugs?orderby=-id&start=0",
|
||||
"https://bugs.launchpad.net/kicad" )
|
||||
<< HtmlHyperlink( "https://gitlab.com/kicad/code/kicad/issues" )
|
||||
<< "</li>";
|
||||
description << "</ul></p>";
|
||||
|
||||
|
||||
@@ -23,6 +23,18 @@
|
||||
|
||||
#define ALPHA_MAX 100 // the max value returned by the alpha (opacity) slider
|
||||
|
||||
|
||||
// Configure the spin controls contained inside the dialog
|
||||
void configureSpinCtrl( wxSpinCtrl* aCtrl )
|
||||
{
|
||||
wxSize textLength = aCtrl->GetTextExtent( "999" );
|
||||
wxSize ctrlSize = aCtrl->GetSizeFromTextSize( textLength );
|
||||
|
||||
aCtrl->SetMinSize( ctrlSize );
|
||||
aCtrl->SetSize( ctrlSize );
|
||||
}
|
||||
|
||||
|
||||
DIALOG_COLOR_PICKER::DIALOG_COLOR_PICKER( wxWindow* aParent, KIGFX::COLOR4D& aCurrentColor,
|
||||
bool aAllowOpacityControl, CUSTOM_COLORS_LIST* aUserColors )
|
||||
: DIALOG_COLOR_PICKER_BASE( aParent )
|
||||
@@ -131,6 +143,13 @@ bool DIALOG_COLOR_PICKER::TransferDataToWindow()
|
||||
SetEditVals( ALL_CHANGED );
|
||||
drawAll();
|
||||
|
||||
// Configure the spin control sizes
|
||||
configureSpinCtrl( m_spinCtrlGreen );
|
||||
configureSpinCtrl( m_spinCtrlBlue );
|
||||
configureSpinCtrl( m_spinCtrlRed );
|
||||
configureSpinCtrl( m_spinCtrlHue );
|
||||
configureSpinCtrl( m_spinCtrlSaturation );
|
||||
|
||||
m_notebook->GetPage( 0 )->Layout();
|
||||
m_notebook->GetPage( 1 )->Layout();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Mar 28 2019)
|
||||
// C++ code generated with wxFormBuilder (version Oct 26 2018)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@@ -56,18 +56,12 @@ DIALOG_COLOR_PICKER_BASE::DIALOG_COLOR_PICKER_BASE( wxWindow* parent, wxWindowID
|
||||
fgSizerRGB->Add( m_staticTextB, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
m_spinCtrlRed = new wxSpinCtrl( sbSizerViewRGB->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 255, 128 );
|
||||
m_spinCtrlRed->SetMinSize( wxSize( 80,-1 ) );
|
||||
|
||||
fgSizerRGB->Add( m_spinCtrlRed, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
m_spinCtrlGreen = new wxSpinCtrl( sbSizerViewRGB->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 255, 128 );
|
||||
m_spinCtrlGreen->SetMinSize( wxSize( 80,-1 ) );
|
||||
|
||||
fgSizerRGB->Add( m_spinCtrlGreen, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
m_spinCtrlBlue = new wxSpinCtrl( sbSizerViewRGB->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 255, 128 );
|
||||
m_spinCtrlBlue->SetMinSize( wxSize( 80,-1 ) );
|
||||
|
||||
fgSizerRGB->Add( m_spinCtrlBlue, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
|
||||
@@ -103,13 +97,9 @@ DIALOG_COLOR_PICKER_BASE::DIALOG_COLOR_PICKER_BASE( wxWindow* parent, wxWindowID
|
||||
fgSizerHSV->Add( m_staticTextSat, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
m_spinCtrlHue = new wxSpinCtrl( sbSizerViewHSV->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_WRAP, 0, 359, 0 );
|
||||
m_spinCtrlHue->SetMinSize( wxSize( 80,-1 ) );
|
||||
|
||||
fgSizerHSV->Add( m_spinCtrlHue, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
m_spinCtrlSaturation = new wxSpinCtrl( sbSizerViewHSV->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 255, 128 );
|
||||
m_spinCtrlSaturation->SetMinSize( wxSize( 80,-1 ) );
|
||||
|
||||
fgSizerHSV->Add( m_spinCtrlSaturation, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
<property name="file">dialog_color_picker_base</property>
|
||||
<property name="first_id">1000</property>
|
||||
<property name="help_provider">none</property>
|
||||
<property name="image_path_wrapper_function_name"></property>
|
||||
<property name="indent_with_spaces"></property>
|
||||
<property name="internationalize">1</property>
|
||||
<property name="name">DIALOG_COLOR_PICKER_BASE</property>
|
||||
@@ -26,7 +25,6 @@
|
||||
<property name="skip_php_events">1</property>
|
||||
<property name="skip_python_events">1</property>
|
||||
<property name="ui_table">UI</property>
|
||||
<property name="use_array_enum">0</property>
|
||||
<property name="use_enum">0</property>
|
||||
<property name="use_microsoft_bom">0</property>
|
||||
<object class="Dialog" expanded="1">
|
||||
@@ -506,7 +504,7 @@
|
||||
<property name="min">0</property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size">80,-1</property>
|
||||
<property name="minimum_size">-1,-1</property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_spinCtrlRed</property>
|
||||
<property name="pane_border">1</property>
|
||||
@@ -569,7 +567,7 @@
|
||||
<property name="min">0</property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size">80,-1</property>
|
||||
<property name="minimum_size">-1,-1</property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_spinCtrlGreen</property>
|
||||
<property name="pane_border">1</property>
|
||||
@@ -632,7 +630,7 @@
|
||||
<property name="min">0</property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size">80,-1</property>
|
||||
<property name="minimum_size">-1,-1</property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_spinCtrlBlue</property>
|
||||
<property name="pane_border">1</property>
|
||||
@@ -918,7 +916,7 @@
|
||||
<property name="min">0</property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size">80,-1</property>
|
||||
<property name="minimum_size">-1,-1</property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_spinCtrlHue</property>
|
||||
<property name="pane_border">1</property>
|
||||
@@ -981,7 +979,7 @@
|
||||
<property name="min">0</property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size">80,-1</property>
|
||||
<property name="minimum_size">-1,-1</property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_spinCtrlSaturation</property>
|
||||
<property name="pane_border">1</property>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Mar 28 2019)
|
||||
// C++ code generated with wxFormBuilder (version Oct 26 2018)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
|
||||
+5
-21
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2007 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 1992-2013 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* 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
|
||||
@@ -23,10 +23,6 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file displlst.cpp
|
||||
*/
|
||||
|
||||
#include <fctsys.h>
|
||||
#include <macros.h>
|
||||
#include <draw_frame.h>
|
||||
@@ -46,11 +42,9 @@ EDA_LIST_DIALOG::EDA_LIST_DIALOG( EDA_DRAW_FRAME* aParent, const wxString& aTitl
|
||||
const std::vector<wxArrayString>& aItemList,
|
||||
const wxString& aSelection,
|
||||
void( *aCallBackFunction )( wxString&, void* ),
|
||||
void* aCallBackFunctionData,
|
||||
bool aSortList, bool aShowHeaders ) :
|
||||
void* aCallBackFunctionData ) :
|
||||
EDA_LIST_DIALOG_BASE( aParent, wxID_ANY, aTitle )
|
||||
{
|
||||
m_sortList = aSortList;
|
||||
m_cb_func = aCallBackFunction;
|
||||
m_cb_data = aCallBackFunctionData;
|
||||
m_itemsListCp = &aItemList;
|
||||
@@ -59,9 +53,6 @@ EDA_LIST_DIALOG::EDA_LIST_DIALOG( EDA_DRAW_FRAME* aParent, const wxString& aTitl
|
||||
|
||||
initDialog( aItemHeaders, aSelection );
|
||||
|
||||
if( !aShowHeaders )
|
||||
m_listBox->SetSingleStyle( wxLC_NO_HEADER, true );
|
||||
|
||||
// DIALOG_SHIM needs a unique hash_key because classname is not sufficient
|
||||
// because so many dialogs share this same class, with different numbers of
|
||||
// columns, different column names, and column widths.
|
||||
@@ -111,15 +102,10 @@ void EDA_LIST_DIALOG::initDialog( const wxArrayString& aItemHeaders, const wxStr
|
||||
}
|
||||
|
||||
|
||||
void EDA_LIST_DIALOG::SetFilterHint( const wxString& aHint )
|
||||
{
|
||||
m_filterBox->SetHint( aHint );
|
||||
}
|
||||
|
||||
|
||||
void EDA_LIST_DIALOG::SetListLabel( const wxString& aLabel )
|
||||
{
|
||||
m_listLabel->SetLabel( aLabel );
|
||||
m_listBox->SetSingleStyle( wxLC_NO_HEADER, true );
|
||||
}
|
||||
|
||||
|
||||
@@ -148,8 +134,7 @@ void EDA_LIST_DIALOG::textChangeInFilterBox( wxCommandEvent& event )
|
||||
}
|
||||
}
|
||||
|
||||
if( m_sortList )
|
||||
sortList();
|
||||
sortList();
|
||||
}
|
||||
|
||||
|
||||
@@ -219,8 +204,7 @@ void EDA_LIST_DIALOG::InsertItems( const std::vector< wxArrayString >& itemList,
|
||||
}
|
||||
}
|
||||
|
||||
if( m_sortList )
|
||||
sortList();
|
||||
sortList();
|
||||
}
|
||||
|
||||
|
||||
|
||||
+37
-10
@@ -68,6 +68,12 @@ static const wxString entrySizeX = "Size_x"; ///< Width of frame, in pixels (suf
|
||||
static const wxString entryMaximized = "Maximized"; ///< Nonzero iff frame is maximized (suffix)
|
||||
///@}
|
||||
|
||||
|
||||
BEGIN_EVENT_TABLE( EDA_BASE_FRAME, wxFrame )
|
||||
EVT_MOVE( EDA_BASE_FRAME::OnMove )
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
EDA_BASE_FRAME::EDA_BASE_FRAME( wxWindow* aParent, FRAME_T aFrameType,
|
||||
const wxString& aTitle, const wxPoint& aPos, const wxSize& aSize,
|
||||
long aStyle, const wxString& aFrameName ) :
|
||||
@@ -279,18 +285,34 @@ void EDA_BASE_FRAME::LoadSettings( wxConfigBase* aCfg )
|
||||
aCfg->Read( text, &m_autoSaveInterval, DEFAULT_AUTO_SAVE_INTERVAL );
|
||||
}
|
||||
|
||||
// Ensure the window is on a connected display, and is visible.
|
||||
// (at least a corner of the frame must be visible on screen)
|
||||
// Sometimes, if a window was moved on an auxiliary display, and when this
|
||||
// display is no more available, it is not the case.
|
||||
wxRect rect( m_FramePos, m_FrameSize );
|
||||
// Ensure window isn't bigger than can be displayed
|
||||
int displayIndex = wxDisplay::GetFromPoint( m_FramePos );
|
||||
|
||||
if( wxDisplay::GetFromPoint( rect.GetTopLeft() ) == wxNOT_FOUND &&
|
||||
wxDisplay::GetFromPoint( rect.GetTopRight() ) == wxNOT_FOUND &&
|
||||
wxDisplay::GetFromPoint( rect.GetBottomLeft() ) == wxNOT_FOUND &&
|
||||
wxDisplay::GetFromPoint( rect.GetBottomRight() ) == wxNOT_FOUND )
|
||||
{
|
||||
if( displayIndex == wxNOT_FOUND )
|
||||
displayIndex = 0;
|
||||
|
||||
wxDisplay display( displayIndex );
|
||||
wxRect clientSize = display.GetClientArea();
|
||||
|
||||
// The window may have been saved on a display that is no longer present.
|
||||
// First, check the window origin and move it if it's off the chosen display
|
||||
|
||||
if( m_FramePos.x >= clientSize.x + clientSize.width ||
|
||||
m_FramePos.y >= clientSize.y + clientSize.height )
|
||||
m_FramePos = wxDefaultPosition;
|
||||
|
||||
// Now, fix up the size if needed
|
||||
|
||||
if( m_FrameSize.x + m_FramePos.x > clientSize.x + clientSize.width )
|
||||
{
|
||||
m_FrameSize.x = clientSize.width;
|
||||
m_FramePos.x = 0;
|
||||
}
|
||||
|
||||
if( m_FrameSize.y + m_FramePos.y > clientSize.y + clientSize.height )
|
||||
{
|
||||
m_FrameSize.y = clientSize.height;
|
||||
m_FramePos.y = 0;
|
||||
}
|
||||
|
||||
// Ensure Window title bar is visible
|
||||
@@ -302,7 +324,12 @@ void EDA_BASE_FRAME::LoadSettings( wxConfigBase* aCfg )
|
||||
int Ypos_min = 0;
|
||||
#endif
|
||||
if( m_FramePos.y < Ypos_min )
|
||||
{
|
||||
if( m_FrameSize.y + ( Ypos_min - m_FramePos.y ) > clientSize.height)
|
||||
m_FrameSize.y = clientSize.height - Ypos_min;
|
||||
|
||||
m_FramePos.y = Ypos_min;
|
||||
}
|
||||
|
||||
if( maximized )
|
||||
Maximize();
|
||||
|
||||
@@ -185,9 +185,9 @@ bool FILENAME_RESOLVER::createPathList()
|
||||
|
||||
if( GetKicadPaths( epaths ) )
|
||||
{
|
||||
for( const auto& i : epaths )
|
||||
for( const wxString& curr_path : epaths )
|
||||
{
|
||||
wxString pathVal = ExpandEnvVarSubstitutions( i );
|
||||
wxString pathVal = ExpandEnvVarSubstitutions( curr_path );
|
||||
|
||||
if( pathVal.empty() )
|
||||
{
|
||||
@@ -200,8 +200,8 @@ bool FILENAME_RESOLVER::createPathList()
|
||||
lpath.m_pathexp = fndummy.GetFullPath();
|
||||
}
|
||||
|
||||
lpath.m_alias = i;
|
||||
lpath.m_pathvar = i;
|
||||
lpath.m_alias = curr_path;
|
||||
lpath.m_pathvar = curr_path;
|
||||
|
||||
if( !lpath.m_pathexp.empty() && psep == *lpath.m_pathexp.rbegin() )
|
||||
lpath.m_pathexp.erase( --lpath.m_pathexp.end() );
|
||||
@@ -219,9 +219,8 @@ bool FILENAME_RESOLVER::createPathList()
|
||||
#ifdef DEBUG
|
||||
wxLogTrace( MASK_3D_RESOLVER, " * [3D model] search paths:\n" );
|
||||
std::list< SEARCH_PATH >::const_iterator sPL = m_Paths.begin();
|
||||
std::list< SEARCH_PATH >::const_iterator ePL = m_Paths.end();
|
||||
|
||||
while( sPL != ePL )
|
||||
while( sPL != m_Paths.end() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_RESOLVER, " + %s : '%s'\n", (*sPL).m_alias.GetData(),
|
||||
(*sPL).m_pathexp.GetData() );
|
||||
@@ -636,9 +635,9 @@ bool FILENAME_RESOLVER::writePathList()
|
||||
|
||||
// skip all ${ENV_VAR} alias names
|
||||
std::list< SEARCH_PATH >::const_iterator sPL = m_Paths.begin();
|
||||
std::list< SEARCH_PATH >::const_iterator ePL = m_Paths.end();
|
||||
|
||||
while( sPL != ePL && ( sPL->m_alias.StartsWith( "${" ) || sPL->m_alias.StartsWith( "$(" ) ) )
|
||||
while( sPL != m_Paths.end() &&
|
||||
( sPL->m_alias.StartsWith( "${" ) || sPL->m_alias.StartsWith( "$(" ) ) )
|
||||
++sPL;
|
||||
|
||||
wxFileName cfgpath( m_ConfigDir, RESOLVER_CONFIG );
|
||||
@@ -662,7 +661,7 @@ bool FILENAME_RESOLVER::writePathList()
|
||||
cfgFile << "#V" << CFGFILE_VERSION << "\n";
|
||||
std::string tstr;
|
||||
|
||||
while( sPL != ePL )
|
||||
while( sPL != m_Paths.end() )
|
||||
{
|
||||
tstr = sPL->m_alias.ToUTF8();
|
||||
cfgFile << "\"" << tstr.size() << ":" << tstr << "\",";
|
||||
@@ -762,10 +761,9 @@ wxString FILENAME_RESOLVER::ShortenPath( const wxString& aFullPathName )
|
||||
|
||||
wxCriticalSectionLocker lock( lock_resolver );
|
||||
std::list< SEARCH_PATH >::const_iterator sL = m_Paths.begin();
|
||||
std::list< SEARCH_PATH >::const_iterator eL = m_Paths.end();
|
||||
size_t idx;
|
||||
|
||||
while( sL != eL )
|
||||
while( sL != m_Paths.end() )
|
||||
{
|
||||
// undefined paths do not participate in the
|
||||
// file name shortening procedure
|
||||
@@ -949,7 +947,7 @@ static bool getHollerith( const std::string& aString, size_t& aIndex, wxString&
|
||||
|
||||
if( nchars > 0 )
|
||||
{
|
||||
aResult = aString.substr( i2, nchars );
|
||||
aResult = wxString::FromUTF8( aString.substr( i2, nchars ).c_str() );
|
||||
i2 += nchars;
|
||||
}
|
||||
|
||||
|
||||
@@ -78,6 +78,9 @@ CAIRO_GAL_BASE::~CAIRO_GAL_BASE()
|
||||
|
||||
if( context )
|
||||
cairo_destroy( context );
|
||||
|
||||
for( auto imageSurface : imageSurfaces )
|
||||
cairo_surface_destroy( imageSurface );
|
||||
}
|
||||
|
||||
|
||||
@@ -424,8 +427,11 @@ void CAIRO_GAL_BASE::DrawPolygon( const SHAPE_LINE_CHAIN& aPolygon )
|
||||
|
||||
|
||||
void CAIRO_GAL_BASE::DrawCurve( const VECTOR2D& aStartPoint, const VECTOR2D& aControlPointA,
|
||||
const VECTOR2D& aControlPointB, const VECTOR2D& aEndPoint )
|
||||
const VECTOR2D& aControlPointB, const VECTOR2D& aEndPoint,
|
||||
double aFilterValue )
|
||||
{
|
||||
// Note: aFilterValue is not used because the cubic Bezier curve is
|
||||
// supported by Cairo.
|
||||
syncLineWidth();
|
||||
|
||||
const auto sp = roundp( xform( aStartPoint ) );
|
||||
@@ -499,7 +505,9 @@ void CAIRO_GAL_BASE::DrawBitmap( const BITMAP_BASE& aBitmap )
|
||||
cairo_surface_mark_dirty( image );
|
||||
cairo_set_source_surface( currentContext, image, 0, 0 );
|
||||
cairo_paint( currentContext );
|
||||
cairo_surface_destroy( image );
|
||||
|
||||
// store the image handle so it can be destroyed later
|
||||
imageSurfaces.push_back( image );
|
||||
|
||||
isElementAdded = true;
|
||||
|
||||
@@ -920,6 +928,11 @@ void CAIRO_GAL_BASE::EnableDepthTest( bool aEnabled )
|
||||
|
||||
void CAIRO_GAL_BASE::resetContext()
|
||||
{
|
||||
for( auto imageSurface : imageSurfaces )
|
||||
cairo_surface_destroy( imageSurface );
|
||||
|
||||
imageSurfaces.clear();
|
||||
|
||||
ClearScreen();
|
||||
|
||||
// Compute the world <-> screen transformations
|
||||
@@ -1256,10 +1269,13 @@ void CAIRO_GAL::endDrawing()
|
||||
|
||||
// Now translate the raw context data from the format stored
|
||||
// by cairo into a format understood by wxImage.
|
||||
pixman_image_t* dstImg = pixman_image_create_bits( PIXMAN_r8g8b8,
|
||||
|
||||
pixman_image_t* dstImg = pixman_image_create_bits(
|
||||
wxPlatformInfo::Get().GetEndianness() == wxENDIAN_LITTLE ? PIXMAN_b8g8r8 :
|
||||
PIXMAN_r8g8b8,
|
||||
screenSize.x, screenSize.y, (uint32_t*) wxOutput, wxBufferWidth * 3 );
|
||||
pixman_image_t* srcImg = pixman_image_create_bits( PIXMAN_a8b8g8r8,
|
||||
screenSize.x, screenSize.y, (uint32_t*) bitmapBuffer, wxBufferWidth * 4 );
|
||||
pixman_image_t* srcImg = pixman_image_create_bits( PIXMAN_a8r8g8b8, screenSize.x, screenSize.y,
|
||||
(uint32_t*) bitmapBuffer, wxBufferWidth * 4 );
|
||||
|
||||
pixman_image_composite( PIXMAN_OP_SRC, srcImg, NULL, dstImg,
|
||||
0, 0, 0, 0, 0, 0, screenSize.x, screenSize.y );
|
||||
|
||||
@@ -64,6 +64,7 @@ static const wxChar* traceGalDispOpts = wxT( "KICAD_GAL_DISPLAY_OPTIONS" );
|
||||
GAL_DISPLAY_OPTIONS::GAL_DISPLAY_OPTIONS()
|
||||
: gl_antialiasing_mode( OPENGL_ANTIALIASING_MODE::NONE ),
|
||||
cairo_antialiasing_mode( CAIRO_ANTIALIASING_MODE::NONE ),
|
||||
m_dpi( nullptr, nullptr ),
|
||||
m_gridStyle( GRID_STYLE::DOTS ),
|
||||
m_gridLineWidth( 1.0 ),
|
||||
m_gridMinSpacing( 10.0 ),
|
||||
@@ -109,12 +110,10 @@ void GAL_DISPLAY_OPTIONS::ReadCommonConfig( wxConfigBase& aCommonConfig, wxWindo
|
||||
CAIRO_ANTIALIASING_MODE_KEY, &temp, (int) KIGFX::CAIRO_ANTIALIASING_MODE::NONE );
|
||||
cairo_antialiasing_mode = (KIGFX::CAIRO_ANTIALIASING_MODE) temp;
|
||||
|
||||
{
|
||||
const DPI_SCALING dpi{ &aCommonConfig, aWindow };
|
||||
m_scaleFactor = dpi.GetScaleFactor();
|
||||
}
|
||||
m_dpi = DPI_SCALING( &aCommonConfig, aWindow );
|
||||
|
||||
NotifyChanged();
|
||||
// Also calls NotifyChanged
|
||||
UpdateScaleFactor();
|
||||
}
|
||||
|
||||
|
||||
@@ -146,6 +145,13 @@ void GAL_DISPLAY_OPTIONS::WriteConfig( wxConfigBase& aCfg, const wxString& aBase
|
||||
}
|
||||
|
||||
|
||||
void GAL_DISPLAY_OPTIONS::UpdateScaleFactor()
|
||||
{
|
||||
m_scaleFactor = m_dpi.GetScaleFactor();
|
||||
NotifyChanged();
|
||||
}
|
||||
|
||||
|
||||
void GAL_DISPLAY_OPTIONS::NotifyChanged()
|
||||
{
|
||||
wxLogTrace( traceGalDispOpts, "Change notification" );
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <geometry/shape_poly_set.h>
|
||||
#include <text_utils.h>
|
||||
#include <bitmap_base.h>
|
||||
#include <bezier_curves.h>
|
||||
|
||||
#include <macros.h>
|
||||
|
||||
@@ -1034,34 +1035,21 @@ void OPENGL_GAL::DrawPolygon( const SHAPE_LINE_CHAIN& aPolygon )
|
||||
|
||||
|
||||
void OPENGL_GAL::DrawCurve( const VECTOR2D& aStartPoint, const VECTOR2D& aControlPointA,
|
||||
const VECTOR2D& aControlPointB, const VECTOR2D& aEndPoint )
|
||||
const VECTOR2D& aControlPointB, const VECTOR2D& aEndPoint,
|
||||
double aFilterValue )
|
||||
{
|
||||
// FIXME The drawing quality needs to be improved
|
||||
// FIXME Perhaps choose a quad/triangle strip instead?
|
||||
// FIXME Brute force method, use a better (recursive?) algorithm
|
||||
std::vector<VECTOR2D> output;
|
||||
std::vector<VECTOR2D> pointCtrl;
|
||||
|
||||
std::deque<VECTOR2D> pointList;
|
||||
pointCtrl.push_back( aStartPoint );
|
||||
pointCtrl.push_back( aControlPointA );
|
||||
pointCtrl.push_back( aControlPointB );
|
||||
pointCtrl.push_back( aEndPoint );
|
||||
|
||||
double t = 0.0;
|
||||
double dt = 1.0 / (double) CURVE_POINTS;
|
||||
BEZIER_POLY converter( pointCtrl );
|
||||
converter.GetPoly( output, aFilterValue );
|
||||
|
||||
for( int i = 0; i <= CURVE_POINTS; i++ )
|
||||
{
|
||||
double omt = 1.0 - t;
|
||||
double omt2 = omt * omt;
|
||||
double omt3 = omt * omt2;
|
||||
double t2 = t * t;
|
||||
double t3 = t * t2;
|
||||
|
||||
VECTOR2D vertex = omt3 * aStartPoint + 3.0 * t * omt2 * aControlPointA
|
||||
+ 3.0 * t2 * omt * aControlPointB + t3 * aEndPoint;
|
||||
|
||||
pointList.push_back( vertex );
|
||||
|
||||
t += dt;
|
||||
}
|
||||
|
||||
DrawPolyline( pointList );
|
||||
DrawPolyline( &output[0], output.size() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
+54
-11
@@ -268,33 +268,78 @@ std::string GBR_APERTURE_METADATA::FormatAttribute( GBR_APERTURE_ATTRIB aAttribu
|
||||
return full_attribute_string;
|
||||
}
|
||||
|
||||
|
||||
// Helper function to convert a ascii hex char to its integer value
|
||||
// If the char is not a hexa char, return -1
|
||||
int char2Hex( unsigned aCode )
|
||||
{
|
||||
if( aCode >= '0' && aCode <= '9' )
|
||||
return aCode - '0';
|
||||
|
||||
if( aCode >= 'A' && aCode <= 'F' )
|
||||
return aCode - 'A' + 10;
|
||||
|
||||
if( aCode >= 'a' && aCode <= 'f' )
|
||||
return aCode - 'a' + 10;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
wxString FormatStringFromGerber( const wxString& aString )
|
||||
{
|
||||
// make the inverse conversion of formatStringToGerber()
|
||||
// It converts a "normalized" gerber string and convert it to a 16 bits sequence unicode
|
||||
// and return a wxString (unicode 16) from the gerber string
|
||||
// Note the initial gerber string can already contain unicode chars.
|
||||
wxString txt;
|
||||
|
||||
for( unsigned ii = 0; ii < aString.Length(); ++ii )
|
||||
unsigned count = aString.Length();
|
||||
|
||||
for( unsigned ii = 0; ii < count; ++ii )
|
||||
{
|
||||
unsigned code = aString[ii];
|
||||
|
||||
if( code == '\\' )
|
||||
if( code == '\\' && ii < count-5 && aString[ii+1] == 'u' )
|
||||
{
|
||||
// Convert 4 hexadecimal digits to a 16 bit unicode
|
||||
// Note the latest Gerber X2 spec (2019 06) uses \uXXXX to encode
|
||||
// the unicode XXXX hexadecimal value
|
||||
// If 4 chars next to 'u' are hexadecimal chars,
|
||||
// convert these 4 hexadecimal digits to a 16 bit unicode
|
||||
// (Gerber allows only 4 hexadecimal digits)
|
||||
// If an error occurs, the escape sequence is not translated,
|
||||
// and used "as this"
|
||||
long value = 0;
|
||||
bool error = false;
|
||||
|
||||
for( int jj = 0; jj < 4; jj++ )
|
||||
{
|
||||
value <<= 4;
|
||||
code = aString[++ii];
|
||||
// Very basic conversion, but it expects a valid gerber file
|
||||
int hexa = (code <= '9' ? code - '0' : code - 'A' + 10) & 0xF;
|
||||
value += hexa;
|
||||
code = aString[ii+jj+2];
|
||||
|
||||
int hexa = char2Hex( code );
|
||||
|
||||
if( hexa >= 0 )
|
||||
value += hexa;
|
||||
else
|
||||
{
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
txt.Append( wxChar( value ) );
|
||||
if( !error )
|
||||
{
|
||||
if( value >= ' ' ) // Is a valid wxChar ?
|
||||
txt.Append( wxChar( value ) );
|
||||
|
||||
ii += 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
txt.Append( aString[ii] );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
txt.Append( aString[ii] );
|
||||
@@ -334,12 +379,10 @@ std::string formatStringToGerber( const wxString& aString )
|
||||
|
||||
if( convert || code > 0x7F )
|
||||
{
|
||||
txt += '\\';
|
||||
|
||||
// Convert code to 4 hexadecimal digit
|
||||
// (Gerber allows only 4 hexadecimal digit)
|
||||
char hexa[32];
|
||||
sprintf( hexa,"%4.4X", code & 0xFFFF);
|
||||
sprintf( hexa,"\\u%4.4X", code & 0xFFFF);
|
||||
txt += hexa;
|
||||
}
|
||||
else
|
||||
|
||||
+11
-2
@@ -33,6 +33,7 @@ int sgn( T aVal )
|
||||
|
||||
bool SEG::PointCloserThan( const VECTOR2I& aP, int aDist ) const
|
||||
{
|
||||
// See http://geomalgorithms.com/a02-_lines.html for some explanations and ideas.
|
||||
VECTOR2I d = B - A;
|
||||
ecoord dist_sq = (ecoord) aDist * aDist;
|
||||
|
||||
@@ -44,9 +45,17 @@ bool SEG::PointCloserThan( const VECTOR2I& aP, int aDist ) const
|
||||
else if( t >= l_squared )
|
||||
return ( aP - B ).SquaredEuclideanNorm() < dist_sq;
|
||||
|
||||
int dxdy = abs( d.x ) - abs( d.y );
|
||||
// JPC: This code is not trivial and is not commented
|
||||
// and does not work for d.x or d.y = -1...1
|
||||
// I am guessing it is here for calculation time optimization.
|
||||
// if someone can understand it, please fix it.
|
||||
// It can be tested with a segment having d.x or d.y value
|
||||
// is -1 or +1 ("this" is a quasi vertical or horizontal segment)
|
||||
int dxdy = std::abs( d.x ) - std::abs( d.y );
|
||||
|
||||
if( ( dxdy >= -1 && dxdy <= 1 ) || abs( d.x ) <= 1 || abs( d.y ) <= 1 )
|
||||
if( ( dxdy >= -1 && dxdy <= 1 ) // quasi 45 deg segment
|
||||
/*|| std::abs( d.x ) <= 1 // quasi horizontal segment
|
||||
|| std::abs( d.y ) <= 1 // quasi vertical segment */ )
|
||||
{
|
||||
int ca = -sgn( d.y );
|
||||
int cb = sgn( d.x );
|
||||
|
||||
@@ -458,6 +458,8 @@ int SHAPE_POLY_SET::AddHole( const SHAPE_LINE_CHAIN& aHole, int aOutline )
|
||||
|
||||
POLYGON& poly = m_polys[aOutline];
|
||||
|
||||
assert( aOutline < (int)m_polys.size() );
|
||||
|
||||
assert( poly.size() );
|
||||
|
||||
poly.push_back( aHole );
|
||||
|
||||
@@ -351,7 +351,12 @@ bool OpenPDF( const wxString& file )
|
||||
|
||||
if( !Pgm().UseSystemPdfBrowser() ) // Run the preferred PDF Browser
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
// Windows requires double quotes around the filename to handle spaces
|
||||
command = Pgm().GetPdfBrowserName() + wxT( " \"" ) + filename + wxT( "\"" );
|
||||
#else
|
||||
command = Pgm().GetPdfBrowserName() + wxT( " '" ) + filename + wxT( "'" );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+7
-36
@@ -1148,45 +1148,16 @@ void ClipAndDrawPoly( EDA_RECT* aClipBox, wxDC* aDC, wxPoint aPoints[], int n )
|
||||
}
|
||||
|
||||
|
||||
void GRBezier( EDA_RECT* ClipBox,
|
||||
wxDC* DC,
|
||||
int x1,
|
||||
int y1,
|
||||
int x2,
|
||||
int y2,
|
||||
int x3,
|
||||
int y3,
|
||||
int width,
|
||||
COLOR4D Color )
|
||||
void GRBezier( EDA_RECT* aClipBox, wxDC* aDC,
|
||||
std::vector<wxPoint>& aPoint,
|
||||
int aWidth, COLOR4D aColor )
|
||||
{
|
||||
std::vector<wxPoint> points;
|
||||
std::vector<wxPoint> output;
|
||||
|
||||
BEZIER_POLY converter( x1, y1, x2, y2, x3, y3 );
|
||||
converter.GetPoly( points );
|
||||
BEZIER_POLY converter( aPoint );
|
||||
converter.GetPoly( output, aWidth );
|
||||
|
||||
GRPoly( ClipBox, DC, points.size(), &points[0], false, width, Color, Color );
|
||||
}
|
||||
|
||||
|
||||
void GRBezier( EDA_RECT* ClipBox,
|
||||
wxDC* DC,
|
||||
int x1,
|
||||
int y1,
|
||||
int x2,
|
||||
int y2,
|
||||
int x3,
|
||||
int y3,
|
||||
int x4,
|
||||
int y4,
|
||||
int width,
|
||||
COLOR4D Color )
|
||||
{
|
||||
std::vector<wxPoint> points;
|
||||
|
||||
BEZIER_POLY converter( x1, y1, x2, y2, x3, y3, x4, y4 );
|
||||
converter.GetPoly( points );
|
||||
|
||||
GRPoly( ClipBox, DC, points.size(), &points[0], false, width, Color, Color );
|
||||
GRPoly( aClipBox, aDC, output.size(), &output[0], false, aWidth, aColor, aColor );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -500,7 +500,7 @@ void GRID_TRICKS::onUpdateUI( wxUpdateUIEvent& event )
|
||||
}
|
||||
}
|
||||
|
||||
if( !cursorInSelectedRow )
|
||||
if( !cursorInSelectedRow && cursorRow >= 0 )
|
||||
m_grid->SelectRow( cursorRow );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -672,6 +672,23 @@ void EDA_DRAW_FRAME::OnSize( wxSizeEvent& SizeEv )
|
||||
}
|
||||
|
||||
|
||||
void EDA_DRAW_FRAME::OnMove( wxMoveEvent& aEvent )
|
||||
{
|
||||
// If the window is moved to a different display, the scaling factor may change
|
||||
double oldFactor = m_galDisplayOptions.m_scaleFactor;
|
||||
m_galDisplayOptions.UpdateScaleFactor();
|
||||
|
||||
if( oldFactor != m_galDisplayOptions.m_scaleFactor )
|
||||
{
|
||||
wxSize clientSize = GetClientSize();
|
||||
GetGalCanvas()->GetGAL()->ResizeScreen( clientSize.x, clientSize.y );
|
||||
GetGalCanvas()->GetView()->MarkDirty();
|
||||
}
|
||||
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
|
||||
void EDA_DRAW_FRAME::SetToolID( int aId, int aCursor, const wxString& aToolMsg )
|
||||
{
|
||||
// Keep default cursor in toolbars
|
||||
|
||||
@@ -687,6 +687,12 @@ void EDA_DRAW_FRAME::OnSize( wxSizeEvent& SizeEv )
|
||||
}
|
||||
|
||||
|
||||
void EDA_DRAW_FRAME::OnMove( wxMoveEvent& aEvent )
|
||||
{
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
|
||||
void EDA_DRAW_FRAME::SetToolID( int aId, int aCursor, const wxString& aToolMsg )
|
||||
{
|
||||
// Keep default cursor in toolbars
|
||||
|
||||
+8
-5
@@ -286,17 +286,20 @@ std::string LSET::FmtHex() const
|
||||
|
||||
static const char hex[] = "0123456789abcdef";
|
||||
|
||||
int nibble_count = ( size() + 3 ) / 4;
|
||||
unsigned nibble_count = ( size() + 3 ) / 4;
|
||||
|
||||
for( int nibble=0; nibble<nibble_count; ++nibble )
|
||||
for( unsigned nibble = 0; nibble < nibble_count; ++nibble )
|
||||
{
|
||||
unsigned ndx = 0;
|
||||
|
||||
// test 4 consecutive bits and set ndx to 0-15:
|
||||
for( int nibble_bit=0; nibble_bit<4; ++nibble_bit )
|
||||
for( unsigned nibble_bit = 0; nibble_bit < 4; ++nibble_bit )
|
||||
{
|
||||
if( (*this)[nibble_bit + nibble*4] )
|
||||
ndx |= (1 << nibble_bit);
|
||||
if( ( nibble_bit + nibble * 4 ) >= size() )
|
||||
break;
|
||||
|
||||
if( (*this)[nibble_bit + nibble * 4] )
|
||||
ndx |= ( 1 << nibble_bit );
|
||||
}
|
||||
|
||||
if( nibble && !( nibble % 8 ) )
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* 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) 2019 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2020 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2020 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
|
||||
@@ -217,6 +217,10 @@ bool GERBER_PLOTTER::StartPlot()
|
||||
// Be sure the usual dark polarity is selected:
|
||||
fputs( "%LPD*%\n", outputFile );
|
||||
|
||||
// Set initial interpolation mode: always G01 (linear):
|
||||
fputs( "G01*\n", outputFile );
|
||||
|
||||
// Set aperture list starting point:
|
||||
fputs( "G04 APERTURE LIST*\n", outputFile );
|
||||
|
||||
return true;
|
||||
@@ -327,10 +331,7 @@ void GERBER_PLOTTER::selectAperture( const wxSize& aSize,
|
||||
( currentAperture->m_Type != aType ) ||
|
||||
( currentAperture->m_Size != aSize );
|
||||
|
||||
if( !m_useNetAttributes )
|
||||
aApertureAttribute = 0;
|
||||
else
|
||||
change = change || ( currentAperture->m_ApertureAttribute != aApertureAttribute );
|
||||
change = change || ( currentAperture->m_ApertureAttribute != aApertureAttribute );
|
||||
|
||||
if( change )
|
||||
{
|
||||
@@ -474,21 +475,34 @@ void GERBER_PLOTTER::Arc( const wxPoint& aCenter, double aStAngle, double aEndAn
|
||||
{
|
||||
SetCurrentLineWidth( aWidth );
|
||||
|
||||
// aFill is not used here.
|
||||
plotArc( aCenter, aStAngle, aEndAngle, aRadius, false );
|
||||
}
|
||||
|
||||
|
||||
void GERBER_PLOTTER::plotArc( const wxPoint& aCenter, double aStAngle, double aEndAngle,
|
||||
int aRadius, bool aPlotInRegion )
|
||||
{
|
||||
wxPoint start, end;
|
||||
start.x = aCenter.x + KiROUND( cosdecideg( aRadius, aStAngle ) );
|
||||
start.y = aCenter.y - KiROUND( sindecideg( aRadius, aStAngle ) );
|
||||
MoveTo( start );
|
||||
|
||||
if( !aPlotInRegion )
|
||||
MoveTo( start );
|
||||
else
|
||||
LineTo( start );
|
||||
|
||||
end.x = aCenter.x + KiROUND( cosdecideg( aRadius, aEndAngle ) );
|
||||
end.y = aCenter.y - KiROUND( sindecideg( aRadius, aEndAngle ) );
|
||||
DPOINT devEnd = userToDeviceCoordinates( end );
|
||||
DPOINT devCenter = userToDeviceCoordinates( aCenter ) - userToDeviceCoordinates( start );
|
||||
|
||||
fprintf( outputFile, "G75*\n" ); // Multiquadrant (360 degrees) mode
|
||||
fprintf( outputFile, "G75*\n" ); // Multiquadrant (360 degrees) mode
|
||||
|
||||
if( aStAngle < aEndAngle )
|
||||
fprintf( outputFile, "G03" );
|
||||
fprintf( outputFile, "G03*\n" ); // Active circular interpolation, CCW
|
||||
else
|
||||
fprintf( outputFile, "G02" );
|
||||
fprintf( outputFile, "G02*\n" ); // Active circular interpolation, CW
|
||||
|
||||
fprintf( outputFile, "X%dY%dI%dJ%dD01*\n",
|
||||
KiROUND( devEnd.x ), KiROUND( devEnd.y ),
|
||||
@@ -736,33 +750,28 @@ void GERBER_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, doub
|
||||
else // Plot pad as region.
|
||||
// Only regions and flashed items accept a object attribute TO.P for the pin name
|
||||
{
|
||||
if( size.x > size.y )
|
||||
{
|
||||
std::swap( size.x, size.y );
|
||||
|
||||
if( orient < 2700 )
|
||||
orient += 900;
|
||||
else
|
||||
orient -= 2700;
|
||||
}
|
||||
|
||||
if( trace_mode == FILLED )
|
||||
{
|
||||
// TODO: use an aperture macro to declare the rotated pad
|
||||
// to be able to flash the shape
|
||||
// For now, the pad is drawn as segment
|
||||
|
||||
// The pad is reduced to an segment with dy > dx
|
||||
int delta = size.y - size.x;
|
||||
wxPoint p0( 0, -delta / 2 );
|
||||
wxPoint p1( 0, delta / 2 );
|
||||
RotatePoint( &p0.x, &p0.y, orient );
|
||||
RotatePoint( &p1.x, &p1.y, orient );
|
||||
|
||||
ThickSegment( pos + p0, pos + p1, size.x, trace_mode, gbr_metadata );
|
||||
// Draw the oval as round rect pad with a radius = 50% min size)
|
||||
// In gerber file, it will be drawn as a region with arcs, and can be
|
||||
// detected as pads (similar to a flashed pad)
|
||||
FlashPadRoundRect( pos, aSize, std::min( aSize.x, aSize.y ) /2,
|
||||
orient, FILLED, aData );
|
||||
}
|
||||
else
|
||||
else // Non filled shape: plot outlines:
|
||||
{
|
||||
if( size.x > size.y )
|
||||
{
|
||||
std::swap( size.x, size.y );
|
||||
|
||||
if( orient < 2700 )
|
||||
orient += 900;
|
||||
else
|
||||
orient -= 2700;
|
||||
}
|
||||
|
||||
sketchOval( pos, size, orient, -1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -840,36 +849,172 @@ void GERBER_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aS
|
||||
EDA_DRAW_MODE_T aTraceMode, void* aData )
|
||||
|
||||
{
|
||||
GBR_METADATA *gbr_metadata = static_cast<GBR_METADATA*>( aData );
|
||||
|
||||
// Currently, a Pad RoundRect is plotted as polygon.
|
||||
// TODO: use Aperture macro and flash it
|
||||
SHAPE_POLY_SET outline;
|
||||
const int segmentToCircleCount = 64;
|
||||
TransformRoundRectToPolygon( outline, aPadPos, aSize, aOrient,
|
||||
aCornerRadius, segmentToCircleCount );
|
||||
GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
|
||||
|
||||
if( aTraceMode != FILLED )
|
||||
{
|
||||
SHAPE_POLY_SET outline;
|
||||
const int segmentToCircleCount = 64;
|
||||
TransformRoundRectToPolygon( outline, aPadPos, aSize, aOrient,
|
||||
aCornerRadius, segmentToCircleCount );
|
||||
|
||||
SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, &gbr_metadata );
|
||||
outline.Inflate( -GetCurrentLineWidth()/2, 16 );
|
||||
|
||||
std::vector< wxPoint > cornerList;
|
||||
// TransformRoundRectToPolygon creates only one convex polygon
|
||||
SHAPE_LINE_CHAIN& poly = outline.Outline( 0 );
|
||||
cornerList.reserve( poly.PointCount() + 1 );
|
||||
|
||||
for( int ii = 0; ii < poly.PointCount(); ++ii )
|
||||
cornerList.emplace_back( poly.CPoint( ii ).x, poly.CPoint( ii ).y );
|
||||
|
||||
// Close polygon
|
||||
cornerList.push_back( cornerList[0] );
|
||||
|
||||
// plot outlines
|
||||
PlotPoly( cornerList, NO_FILL, GetCurrentLineWidth(), gbr_metadata );
|
||||
}
|
||||
else
|
||||
{
|
||||
// A Pad RoundRect is plotted as a Gerber region.
|
||||
// Initialize region metadata:
|
||||
bool clearTA_AperFunction = false; // true if a TA.AperFunction is used
|
||||
|
||||
if( gbr_metadata )
|
||||
{
|
||||
formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
|
||||
std::string attrib = gbr_metadata->m_ApertureMetadata.FormatAttribute( !m_useX2format );
|
||||
|
||||
if( !attrib.empty() )
|
||||
{
|
||||
fputs( attrib.c_str(), outputFile );
|
||||
clearTA_AperFunction = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Plot the region using arcs in corners.
|
||||
plotRoundRectAsRegion( aPadPos, aSize, aCornerRadius, aOrient );
|
||||
|
||||
// Clear the TA attribute, to avoid the next item to inherit it:
|
||||
if( clearTA_AperFunction )
|
||||
{
|
||||
if( m_useX2format )
|
||||
{
|
||||
fputs( "%TD.AperFunction*%\n", outputFile );
|
||||
}
|
||||
else
|
||||
{
|
||||
fputs( "G04 #@! TD.AperFunction*\n", outputFile );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GERBER_PLOTTER::plotRoundRectAsRegion( const wxPoint& aRectCenter, const wxSize& aSize,
|
||||
int aCornerRadius, double aOrient )
|
||||
{
|
||||
// The region outline is generated by 4 sides and 4 90 deg arcs
|
||||
// 1 --- 2
|
||||
// | c |
|
||||
// 4 --- 3
|
||||
|
||||
// Note also in user coordinates the Y axis is from top to bottom
|
||||
// for historical reasons.
|
||||
|
||||
// A helper structure to handle outlines coordinates (segments and arcs)
|
||||
// in user coordinates
|
||||
struct RR_EDGE
|
||||
{
|
||||
wxPoint m_start;
|
||||
wxPoint m_end;
|
||||
wxPoint m_center;
|
||||
// in decidegrees: angle start. angle end = m_arc_angle_start+arc_angle
|
||||
double m_arc_angle_start;
|
||||
};
|
||||
|
||||
const double arc_angle = -900.0; // in decidegrees
|
||||
int hsizeX = aSize.x/2;
|
||||
int hsizeY = aSize.y/2;
|
||||
|
||||
RR_EDGE curr_edge;
|
||||
std::vector<RR_EDGE> rr_outline;
|
||||
|
||||
// Build outline coordinates, relative to rectangle center, rotation 0:
|
||||
|
||||
// Top left corner 1 (and 4 to 1 left vertical side @ x=-hsizeX)
|
||||
curr_edge.m_start.x = -hsizeX;
|
||||
curr_edge.m_start.y = hsizeY - aCornerRadius;
|
||||
curr_edge.m_end.x = curr_edge.m_start.x;
|
||||
curr_edge.m_end.y = -hsizeY + aCornerRadius;
|
||||
curr_edge.m_center.x = -hsizeX + aCornerRadius;
|
||||
curr_edge.m_center.y = curr_edge.m_end.y;
|
||||
curr_edge.m_arc_angle_start = aOrient + 1800.0; // En decidegree
|
||||
|
||||
rr_outline.push_back( curr_edge );
|
||||
|
||||
// Top right corner 2 (and 1 to 2 top horizontal side @ y=-hsizeY)
|
||||
curr_edge.m_start.x = -hsizeX + aCornerRadius;
|
||||
curr_edge.m_start.y = -hsizeY;
|
||||
curr_edge.m_end.x = hsizeX - aCornerRadius;
|
||||
curr_edge.m_end.y = curr_edge.m_start.y;
|
||||
curr_edge.m_center.x = curr_edge.m_end.x;
|
||||
curr_edge.m_center.y = -hsizeY + aCornerRadius;
|
||||
curr_edge.m_arc_angle_start = aOrient + 900.0; // En decidegree
|
||||
|
||||
rr_outline.push_back( curr_edge );
|
||||
|
||||
// bottom right corner 3 (and 2 to 3 right vertical side @ x=hsizeX)
|
||||
curr_edge.m_start.x = hsizeX;
|
||||
curr_edge.m_start.y = -hsizeY + aCornerRadius;
|
||||
curr_edge.m_end.x = curr_edge.m_start.x;
|
||||
curr_edge.m_end.y = hsizeY - aCornerRadius;
|
||||
curr_edge.m_center.x = hsizeX - aCornerRadius;
|
||||
curr_edge.m_center.y = curr_edge.m_end.y;
|
||||
curr_edge.m_arc_angle_start = aOrient + 0.0; // En decidegree
|
||||
|
||||
rr_outline.push_back( curr_edge );
|
||||
|
||||
// bottom left corner 4 (and 3 to 4 bottom horizontal side @ y=hsizeY)
|
||||
curr_edge.m_start.x = hsizeX - aCornerRadius;
|
||||
curr_edge.m_start.y = hsizeY;
|
||||
curr_edge.m_end.x = -hsizeX + aCornerRadius;
|
||||
curr_edge.m_end.y = curr_edge.m_start.y;
|
||||
curr_edge.m_center.x = curr_edge.m_end.x;
|
||||
curr_edge.m_center.y = hsizeY - aCornerRadius;
|
||||
curr_edge.m_arc_angle_start = aOrient - 900.0; // En decidegree
|
||||
|
||||
rr_outline.push_back( curr_edge );
|
||||
|
||||
// Move relative coordinates to the actual location and rotation:
|
||||
for( RR_EDGE& rr_edge: rr_outline )
|
||||
{
|
||||
RotatePoint( &rr_edge.m_start, aOrient );
|
||||
RotatePoint( &rr_edge.m_end, aOrient );
|
||||
RotatePoint( &rr_edge.m_center, aOrient );
|
||||
rr_edge.m_start += aRectCenter;
|
||||
rr_edge.m_end += aRectCenter;
|
||||
rr_edge.m_center += aRectCenter;
|
||||
}
|
||||
|
||||
std::vector< wxPoint > cornerList;
|
||||
// TransformRoundRectToPolygon creates only one convex polygon
|
||||
SHAPE_LINE_CHAIN& poly = outline.Outline( 0 );
|
||||
cornerList.reserve( poly.PointCount() + 1 );
|
||||
fputs( "G36*\n", outputFile ); // Start region
|
||||
fputs( "G01*\n", outputFile ); // Set linear interpolation.
|
||||
MoveTo( rr_outline[0].m_start ); // Start point of region
|
||||
|
||||
for( int ii = 0; ii < poly.PointCount(); ++ii )
|
||||
cornerList.push_back( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) );
|
||||
for( RR_EDGE& rr_edge: rr_outline )
|
||||
{
|
||||
if( aCornerRadius ) // Guard: ensure we do not create arcs with radius = 0
|
||||
{
|
||||
// LineTo( rr_edge.m_end ); // made in plotArc()
|
||||
plotArc( rr_edge.m_center, rr_edge.m_arc_angle_start, rr_edge.m_arc_angle_start+arc_angle,
|
||||
aCornerRadius, true );
|
||||
}
|
||||
else
|
||||
LineTo( rr_edge.m_end );
|
||||
}
|
||||
|
||||
// Close polygon
|
||||
cornerList.push_back( cornerList[0] );
|
||||
|
||||
if( aTraceMode == SKETCH )
|
||||
PlotPoly( cornerList, NO_FILL, GetCurrentLineWidth(), gbr_metadata );
|
||||
else
|
||||
PlotGerberRegion( cornerList, gbr_metadata );
|
||||
fputs( "G37*\n", outputFile ); // Close region
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2020 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2020 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
|
||||
@@ -90,6 +90,8 @@
|
||||
* flag_sweep : 0 = CCW, 1 = CW
|
||||
* The center of ellipse is automatically calculated.
|
||||
*/
|
||||
|
||||
#include <base64.h>
|
||||
#include <fctsys.h>
|
||||
#include <trigo.h>
|
||||
#include <eda_base_frame.h>
|
||||
@@ -100,6 +102,8 @@
|
||||
#include <macros.h>
|
||||
#include <kicad_string.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <wx/mstream.h>
|
||||
|
||||
|
||||
/**
|
||||
@@ -499,7 +503,7 @@ void SVG_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, i
|
||||
|
||||
setFillMode( NO_FILL );
|
||||
SetCurrentLineWidth( width );
|
||||
fprintf( outputFile, "<path d=\"M%g %g A%g %g 0.0 %d %d %g %g \" />\n",
|
||||
fprintf( outputFile, "<path d=\"M%g %g A%g %g 0.0 %d %d %g %g\" />\n",
|
||||
start.x, start.y, radius_dev, radius_dev,
|
||||
flg_arc, flg_sweep,
|
||||
end.x, end.y );
|
||||
@@ -554,12 +558,51 @@ void SVG_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList,
|
||||
void SVG_PLOTTER::PlotImage( const wxImage& aImage, const wxPoint& aPos,
|
||||
double aScaleFactor )
|
||||
{
|
||||
// in svg file we must insert a link to a png image file to plot an image
|
||||
// the image itself is not included in the svg file.
|
||||
// So we prefer skip the image, and just draw a rectangle,
|
||||
// like other plotters which do not support images
|
||||
wxSize pix_size( aImage.GetWidth(), aImage.GetHeight() );
|
||||
|
||||
// Requested size (in IUs)
|
||||
DPOINT drawsize( aScaleFactor * pix_size.x,
|
||||
aScaleFactor * pix_size.y );
|
||||
|
||||
// calculate the bitmap start position
|
||||
wxPoint start( aPos.x - drawsize.x / 2,
|
||||
aPos.y - drawsize.y / 2);
|
||||
|
||||
// Rectangles having a 0 size value for height or width are just not drawn on Inscape,
|
||||
// so use a line when happens.
|
||||
if( drawsize.x == 0.0 || drawsize.y == 0.0 ) // Draw a line
|
||||
{
|
||||
PLOTTER::PlotImage( aImage, aPos, aScaleFactor );
|
||||
}
|
||||
else
|
||||
{
|
||||
wxMemoryOutputStream img_stream;
|
||||
|
||||
aImage.SaveFile( img_stream, wxBITMAP_TYPE_PNG );
|
||||
size_t input_len = img_stream.GetOutputStreamBuffer()->GetBufferSize();
|
||||
std::vector<uint8_t> buffer( input_len );
|
||||
std::vector<uint8_t> encoded;
|
||||
|
||||
img_stream.CopyTo( buffer.data(), buffer.size() );
|
||||
base64::encode( buffer, encoded );
|
||||
|
||||
fprintf( outputFile,
|
||||
"<image x=\"%g\" y=\"%g\" xlink:href=\"data:image/png;base64,",
|
||||
userToDeviceSize( start.x ), userToDeviceSize( start.y )
|
||||
);
|
||||
|
||||
for( size_t i = 0; i < encoded.size(); i++ )
|
||||
{
|
||||
fprintf( outputFile, "%c", static_cast<char>( encoded[i] ) );
|
||||
|
||||
if( ( i % 64 ) == 63 )
|
||||
fprintf( outputFile, "\n" );
|
||||
}
|
||||
|
||||
fprintf( outputFile, "\"\npreserveAspectRatio=\"none\" width=\"%g\" height=\"%g\" />",
|
||||
userToDeviceSize( drawsize.x ), userToDeviceSize( drawsize.y ) );
|
||||
}
|
||||
|
||||
PLOTTER::PlotImage( aImage, aPos, aScaleFactor );
|
||||
|
||||
}
|
||||
|
||||
@@ -620,7 +663,11 @@ bool SVG_PLOTTER::StartPlot()
|
||||
"<?xml version=\"1.0\" standalone=\"no\"?>\n",
|
||||
" <!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \n",
|
||||
" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"> \n",
|
||||
"<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" \n",
|
||||
"<svg\n"
|
||||
" xmlns:svg=\"http://www.w3.org/2000/svg\"\n"
|
||||
" xmlns=\"http://www.w3.org/2000/svg\"\n",
|
||||
" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n",
|
||||
" version=\"1.1\"\n",
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -633,7 +680,7 @@ bool SVG_PLOTTER::StartPlot()
|
||||
// Write viewport pos and size
|
||||
wxPoint origin; // TODO set to actual value
|
||||
fprintf( outputFile,
|
||||
" width=\"%gcm\" height=\"%gcm\" viewBox=\"%d %d %d %d \">\n",
|
||||
" width=\"%fcm\" height=\"%fcm\" viewBox=\"%d %d %d %d\">\n",
|
||||
(double) paperSize.x / m_IUsPerDecimil * 2.54 / 10000,
|
||||
(double) paperSize.y / m_IUsPerDecimil * 2.54 / 10000,
|
||||
origin.x, origin.y,
|
||||
@@ -660,7 +707,7 @@ bool SVG_PLOTTER::StartPlot()
|
||||
m_brush_rgb_color, opacity, m_pen_rgb_color, opacity );
|
||||
|
||||
// output the pen cap and line joint
|
||||
fputs( "stroke-linecap:round; stroke-linejoin:round; \"\n", outputFile );
|
||||
fputs( "stroke-linecap:round; stroke-linejoin:round;\"\n", outputFile );
|
||||
fputs( " transform=\"translate(0 0) scale(1 1)\">\n", outputFile );
|
||||
return true;
|
||||
}
|
||||
@@ -734,8 +781,10 @@ void SVG_PLOTTER::Text( const wxPoint& aPos,
|
||||
}
|
||||
|
||||
wxSize text_size;
|
||||
text_size.x = GraphicTextWidth( aText, aSize, aItalic, width );
|
||||
text_size.y = aSize.x * 4/3; // Hershey font height to em size conversion
|
||||
// aSize.x or aSize.y is < 0 for mirrored texts.
|
||||
// The actual text size value is the absolue value
|
||||
text_size.x = std::abs( GraphicTextWidth( aText, aSize, aItalic, width ) );
|
||||
text_size.y = std::abs( aSize.x * 4/3 ); // Hershey font height to em size conversion
|
||||
DPOINT anchor_pos_dev = userToDeviceCoordinates( aPos );
|
||||
DPOINT text_pos_dev = userToDeviceCoordinates( text_pos );
|
||||
DPOINT sz_dev = userToDeviceSize( text_size );
|
||||
|
||||
@@ -96,6 +96,7 @@ principle should be easily implemented by adapting the current STL containers.
|
||||
#include <marker_base.h>
|
||||
#include <eda_text.h>
|
||||
#include <convert_to_biu.h>
|
||||
#include <build_version.h>
|
||||
%}
|
||||
|
||||
// all the wx wrappers for wxString, wxPoint, wxRect, wxChar ..
|
||||
@@ -116,6 +117,7 @@ principle should be easily implemented by adapting the current STL containers.
|
||||
%include colors_design_settings.h
|
||||
%include marker_base.h
|
||||
%include eda_text.h
|
||||
%include build_version.h
|
||||
|
||||
// Cast time_t to known type for Python
|
||||
typedef long time_t;
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>cvpcb_doc.icns</string>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>net</string>
|
||||
<string>cmp</string>
|
||||
</array>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>cvpcb document</string>
|
||||
<key>LSHandlerRank</key>
|
||||
<string>Owner</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>cvpcb</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string></string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>cvpcb.icns</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.kicad-pcb.cvpcb</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleLongVersionString</key>
|
||||
<string>@KICAD_VERSION_FULL@</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>CvPcb</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>@KICAD_VERSION@</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>@KICAD_VERSION_FULL@</string>
|
||||
<key>CSResourcesFileMapped</key>
|
||||
<true/>
|
||||
<key>LSRequiresCarbon</key>
|
||||
<true/>
|
||||
<key>NSRequiresAquaSystemAppearance</key>
|
||||
<true/>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string></string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<string>True</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -394,11 +394,8 @@ endif()
|
||||
|
||||
# these 2 binaries are a matched set, keep them together:
|
||||
if( APPLE )
|
||||
include( ${CMAKE_MODULE_PATH}/KiCadVersion.cmake )
|
||||
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist @ONLY )
|
||||
|
||||
set_target_properties( eeschema PROPERTIES
|
||||
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist
|
||||
MACOSX_BUNDLE_INFO_PLIST ${PROJECT_BINARY_DIR}/eeschema/Info.plist
|
||||
)
|
||||
|
||||
# puts binaries into the *.app bundle while linking
|
||||
|
||||
+34
-17
@@ -38,7 +38,7 @@
|
||||
#include <class_library.h>
|
||||
|
||||
|
||||
void mapExistingAnnotation( std::map<timestamp_t, wxString>& aMap )
|
||||
void mapExistingAnnotation( std::map<wxString, wxString>& aMap )
|
||||
{
|
||||
SCH_SHEET_LIST sheets( g_RootSheet );
|
||||
SCH_REFERENCE_LIST references;
|
||||
@@ -48,10 +48,19 @@ void mapExistingAnnotation( std::map<timestamp_t, wxString>& aMap )
|
||||
for( size_t i = 0; i < references.GetCount(); i++ )
|
||||
{
|
||||
SCH_COMPONENT* comp = references[ i ].GetComp();
|
||||
wxString ref = comp->GetField( REFERENCE )->GetFullyQualifiedText();
|
||||
|
||||
const SCH_SHEET_PATH* curr_sheetpath = &references[ i ].GetSheetPath();
|
||||
wxString full_path = curr_sheetpath->Path();
|
||||
full_path += wxString::Format( wxT( "/%8.8lX" ),
|
||||
(unsigned long) comp->GetTimeStamp() );
|
||||
|
||||
wxString ref = comp->GetRef( (SCH_SHEET_PATH*)curr_sheetpath );
|
||||
|
||||
if( comp->GetUnitCount() > 1 )
|
||||
ref << LIB_PART::SubReference( comp->GetUnitSelection( curr_sheetpath ) );
|
||||
|
||||
if( !ref.Contains( wxT( "?" ) ) )
|
||||
aMap[ comp->GetTimeStamp() ] = ref;
|
||||
aMap[ full_path ] = ref;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +108,7 @@ void SCH_EDIT_FRAME::AnnotateComponents( bool aAnnotateSchematic,
|
||||
SCH_MULTI_UNIT_REFERENCE_MAP lockedComponents;
|
||||
|
||||
// Map of previous annotation for building info messages
|
||||
std::map<timestamp_t, wxString> previousAnnotation;
|
||||
std::map<wxString, wxString> previousAnnotation;
|
||||
|
||||
// Test for and replace duplicate time stamps in components and sheets. Duplicate
|
||||
// time stamps can happen with old schematics, schematic conversions, or manual
|
||||
@@ -191,9 +200,19 @@ void SCH_EDIT_FRAME::AnnotateComponents( bool aAnnotateSchematic,
|
||||
for( size_t i = 0; i < references.GetCount(); i++ )
|
||||
{
|
||||
SCH_COMPONENT* comp = references[ i ].GetComp();
|
||||
wxString prevRef = previousAnnotation[ comp->GetTimeStamp() ];
|
||||
wxString newRef = comp->GetField( REFERENCE )->GetFullyQualifiedText();
|
||||
wxString msg;
|
||||
|
||||
const SCH_SHEET_PATH* curr_sheetpath = &references[ i ].GetSheetPath();
|
||||
wxString curr_full_path = curr_sheetpath->Path();
|
||||
curr_full_path += wxString::Format( wxT( "/%8.8lX" ),
|
||||
(unsigned long) comp->GetTimeStamp() );
|
||||
|
||||
wxString prevRef = previousAnnotation[ curr_full_path ];
|
||||
wxString newRef = comp->GetRef( curr_sheetpath );
|
||||
|
||||
if( comp->GetUnitCount() > 1 )
|
||||
newRef << LIB_PART::SubReference( comp->GetUnitSelection( curr_sheetpath ) );
|
||||
|
||||
wxString msg;
|
||||
|
||||
if( prevRef.Length() )
|
||||
{
|
||||
@@ -202,27 +221,25 @@ void SCH_EDIT_FRAME::AnnotateComponents( bool aAnnotateSchematic,
|
||||
|
||||
if( comp->GetUnitCount() > 1 )
|
||||
msg.Printf( _( "Updated %s (unit %s) from %s to %s" ),
|
||||
GetChars( comp->GetField( VALUE )->GetShownText() ),
|
||||
comp->GetField( VALUE )->GetShownText(),
|
||||
LIB_PART::SubReference( comp->GetUnit(), false ),
|
||||
GetChars( prevRef ),
|
||||
GetChars( newRef ) );
|
||||
prevRef, newRef );
|
||||
else
|
||||
msg.Printf( _( "Updated %s from %s to %s" ),
|
||||
GetChars( comp->GetField( VALUE )->GetShownText() ),
|
||||
GetChars( prevRef ),
|
||||
GetChars( newRef ) );
|
||||
comp->GetField( VALUE )->GetShownText(),
|
||||
prevRef, newRef );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( comp->GetUnitCount() > 1 )
|
||||
msg.Printf( _( "Annotated %s (unit %s) as %s" ),
|
||||
GetChars( comp->GetField( VALUE )->GetShownText() ),
|
||||
comp->GetField( VALUE )->GetShownText(),
|
||||
LIB_PART::SubReference( comp->GetUnit(), false ),
|
||||
GetChars( newRef ) );
|
||||
newRef );
|
||||
else
|
||||
msg.Printf( _( "Annotated %s as %s" ),
|
||||
GetChars( comp->GetField( VALUE )->GetShownText() ),
|
||||
GetChars( newRef ) );
|
||||
comp->GetField( VALUE )->GetShownText(),
|
||||
newRef );
|
||||
}
|
||||
|
||||
aReporter.Report( msg, REPORTER::RPT_ACTION );
|
||||
|
||||
@@ -595,8 +595,7 @@ void LIB_PART::RemoveDrawItem( LIB_ITEM* aItem, EDA_DRAW_PANEL* aPanel, wxDC* aD
|
||||
{
|
||||
wxLogWarning( _(
|
||||
"An attempt was made to remove the %s field from component %s in library %s." ),
|
||||
GetChars( field->GetName() ), GetChars( GetName() ),
|
||||
GetChars( GetLibraryName() ) );
|
||||
field->GetName( TRANSLATE_FIELD_NAME ), GetName(), GetLibraryName() );
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -716,6 +715,15 @@ bool LIB_PART::PinsConflictWith( LIB_PART& aOtherPart, bool aTestNums, bool aTes
|
||||
for( LIB_PIN* eachOtherPin : otherPinList )
|
||||
{
|
||||
wxASSERT( eachOtherPin );
|
||||
|
||||
// Same unit?
|
||||
if( eachThisPin->GetUnit() != eachOtherPin->GetUnit() )
|
||||
continue;
|
||||
|
||||
// Same body stype?
|
||||
if( eachThisPin->GetConvert() != eachOtherPin->GetConvert() )
|
||||
continue;
|
||||
|
||||
// Same position?
|
||||
if( eachThisPin->GetPosition() != eachOtherPin->GetPosition() )
|
||||
continue;
|
||||
@@ -741,6 +749,7 @@ bool LIB_PART::PinsConflictWith( LIB_PART& aOtherPart, bool aTestNums, bool aTes
|
||||
continue;
|
||||
|
||||
foundMatch = true;
|
||||
break; // Match found so seach is complete.
|
||||
}
|
||||
|
||||
if( !foundMatch )
|
||||
@@ -894,7 +903,7 @@ LIB_FIELD* LIB_PART::FindField( const wxString& aFieldName )
|
||||
{
|
||||
LIB_FIELD* field = ( LIB_FIELD* ) &item;
|
||||
|
||||
if( field->GetName() == aFieldName )
|
||||
if( field->GetName( NATIVE_FIELD_NAME ) == aFieldName )
|
||||
return field;
|
||||
}
|
||||
|
||||
|
||||
@@ -403,7 +403,8 @@ public:
|
||||
void GetFields( LIB_FIELDS& aList );
|
||||
|
||||
/**
|
||||
* Findd a field within this part matching \a aFieldName and returns it or NULL if not found.
|
||||
* Find a field within this part matching \a aFieldName and returns it
|
||||
* or NULL if not found.
|
||||
*/
|
||||
LIB_FIELD* FindField( const wxString& aFieldName );
|
||||
|
||||
|
||||
@@ -217,7 +217,7 @@ void DIALOG_ANNOTATE::OnApplyClick( wxCommandEvent& event )
|
||||
dlg.SetOKLabel( _( "Clear and Annotate" ) );
|
||||
dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
|
||||
|
||||
if( dlg.ShowModal() == wxCANCEL )
|
||||
if( dlg.ShowModal() == wxID_CANCEL )
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -484,7 +484,6 @@ bool DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::TransferDataFromWindow()
|
||||
// parts.
|
||||
if( m_cmp->GetUnitCount() > 1 )
|
||||
{
|
||||
const LIB_ID thisLibId = m_cmp->GetLibId();
|
||||
const wxString thisRef = m_cmp->GetRef( &( GetParent()->GetCurrentSheet() ) );
|
||||
int thisUnit = m_cmp->GetUnit();
|
||||
|
||||
@@ -495,9 +494,7 @@ bool DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::TransferDataFromWindow()
|
||||
{
|
||||
SCH_REFERENCE component = components[i];
|
||||
|
||||
if( component.GetLibPart()->GetLibId() == thisLibId
|
||||
&& component.GetRef() == thisRef
|
||||
&& component.GetUnit() != thisUnit )
|
||||
if( component.GetRef() == thisRef && component.GetUnit() != thisUnit )
|
||||
{
|
||||
SCH_COMPONENT* otherUnit = component.GetComp();
|
||||
GetParent()->SaveCopyInUndoList( otherUnit, UR_CHANGED, true /* append */);
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <confirm.h>
|
||||
#include <kicad_string.h>
|
||||
#include <sch_base_frame.h>
|
||||
#include <sch_edit_frame.h>
|
||||
#include <sch_component.h>
|
||||
#include <class_libentry.h>
|
||||
#include <lib_field.h>
|
||||
@@ -43,7 +44,7 @@
|
||||
#include <sch_validators.h>
|
||||
|
||||
#include <dialog_edit_one_field.h>
|
||||
|
||||
#include <sch_reference_list.h>
|
||||
|
||||
// These should probably moved into some other file as helpers.
|
||||
EDA_TEXT_HJUSTIFY_T IntToEdaTextHorizJustify( int aHorizJustify )
|
||||
@@ -275,12 +276,13 @@ DIALOG_SCH_EDIT_ONE_FIELD::DIALOG_SCH_EDIT_ONE_FIELD( SCH_BASE_FRAME* aParent,
|
||||
|
||||
void DIALOG_SCH_EDIT_ONE_FIELD::UpdateField( SCH_FIELD* aField, SCH_SHEET_PATH* aSheetPath )
|
||||
{
|
||||
SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
|
||||
SCH_COMPONENT* component = dynamic_cast<SCH_COMPONENT*>( aField->GetParent() );
|
||||
int fieldType = aField->GetId();
|
||||
|
||||
if( aField->GetId() == REFERENCE )
|
||||
{
|
||||
wxASSERT( aSheetPath );
|
||||
|
||||
SCH_COMPONENT* component = dynamic_cast< SCH_COMPONENT* >( aField->GetParent() );
|
||||
|
||||
wxASSERT( component );
|
||||
|
||||
if( component )
|
||||
@@ -304,9 +306,31 @@ void DIALOG_SCH_EDIT_ONE_FIELD::UpdateField( SCH_FIELD* aField, SCH_SHEET_PATH*
|
||||
aField->SetText( m_text );
|
||||
updateText( aField );
|
||||
|
||||
if( positioningModified )
|
||||
// The value, footprint and datasheet fields should be kept in sync in multi-unit
|
||||
// parts.
|
||||
if( editFrame && component && component->GetUnitCount() > 1
|
||||
&& ( fieldType == VALUE || fieldType == FOOTPRINT || fieldType == DATASHEET ) )
|
||||
{
|
||||
auto component = static_cast< SCH_COMPONENT* >( aField->GetParent() );
|
||||
component->ClearFieldsAutoplaced();
|
||||
const wxString thisRef = component->GetRef( &( editFrame->GetCurrentSheet() ) );
|
||||
int thisUnit = component->GetUnit();
|
||||
|
||||
SCH_REFERENCE_LIST components;
|
||||
editFrame->GetCurrentSheet().GetComponents( components );
|
||||
|
||||
for( unsigned i = 0; i < components.GetCount(); i++ )
|
||||
{
|
||||
SCH_REFERENCE componentRef = components[i];
|
||||
|
||||
if( componentRef.GetRef() == thisRef && componentRef.GetUnit() != thisUnit )
|
||||
{
|
||||
SCH_COMPONENT* otherUnit = componentRef.GetComp();
|
||||
editFrame->SaveCopyInUndoList( otherUnit, UR_CHANGED, true /* append */);
|
||||
otherUnit->GetField( fieldType )->SetText( m_text );
|
||||
editFrame->RefreshItem( otherUnit );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( component && positioningModified )
|
||||
component->ClearFieldsAutoplaced();
|
||||
}
|
||||
|
||||
@@ -868,10 +868,13 @@ void DIALOG_FIELDS_EDITOR_GLOBAL::LoadFieldNames()
|
||||
// Force References to always be shown
|
||||
m_config->Write( "SymbolFieldEditor/Show/Reference", true );
|
||||
|
||||
AddField( _( "Reference" ), true, true );
|
||||
AddField( _( "Value" ), true, true );
|
||||
AddField( _( "Footprint" ), true, true );
|
||||
AddField( _( "Datasheet" ), true, false );
|
||||
// *DO NOT* use translated mandatory field names:
|
||||
// They are also used as keyword to find fields in component list.
|
||||
// Changing that is not a basic change
|
||||
AddField( "Reference", true, true );
|
||||
AddField( "Value", true, true );
|
||||
AddField( "Footprint", true, true );
|
||||
AddField( "Datasheet", true, false );
|
||||
|
||||
for( auto fieldName : userFieldNames )
|
||||
AddField( fieldName, true, false );
|
||||
|
||||
@@ -324,10 +324,10 @@ public:
|
||||
void SortRows( int aSortCol, bool ascending )
|
||||
{
|
||||
std::sort( m_rows.begin(), m_rows.end(),
|
||||
[ aSortCol, ascending, this ]( LIB_PINS& lhs, LIB_PINS& rhs ) -> bool
|
||||
{
|
||||
return compare( lhs, rhs, aSortCol, ascending, m_userUnits );
|
||||
} );
|
||||
[ aSortCol, ascending, this ]( const LIB_PINS& lhs, const LIB_PINS& rhs ) -> bool
|
||||
{
|
||||
return compare( lhs, rhs, aSortCol, ascending, m_userUnits );
|
||||
} );
|
||||
}
|
||||
|
||||
void SortPins( LIB_PINS& aRow )
|
||||
|
||||
@@ -399,6 +399,7 @@ void SCH_PRINTOUT::DrawPage( SCH_SCREEN* aScreen )
|
||||
|
||||
pageSizeIU = aScreen->GetPageSettings().GetSizeIU();
|
||||
FitThisSizeToPaper( pageSizeIU );
|
||||
|
||||
fitRect = GetLogicalPaperRect();
|
||||
|
||||
wxLogDebug( wxT( "Fit rectangle: x = %d, y = %d, w = %d, h = %d" ),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2019 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2015-2020 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
|
||||
@@ -245,8 +245,13 @@ void DIALOG_RESCUE_EACH::displayItemsInConflict()
|
||||
else
|
||||
{
|
||||
RESCUE_CANDIDATE& selected_part = m_Rescuer->m_all_candidates[row];
|
||||
m_previewOldWidget->DisplayPart( selected_part.GetCacheCandidate(), 0 );
|
||||
m_previewNewWidget->DisplayPart( selected_part.GetLibCandidate(), 0 );
|
||||
|
||||
m_previewOldWidget->DisplayPart( selected_part.GetCacheCandidate(),
|
||||
selected_part.GetUnit(),
|
||||
selected_part.GetConvert() );
|
||||
m_previewNewWidget->DisplayPart( selected_part.GetLibCandidate(),
|
||||
selected_part.GetUnit(),
|
||||
selected_part.GetConvert() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -244,7 +244,8 @@ bool DIALOG_SPICE_MODEL::TransferDataFromWindow()
|
||||
[&]( const SCH_FIELD& f ) { return f.GetName() == spiceField; } ), m_schfields->end() );
|
||||
else
|
||||
m_libfields->erase( std::remove_if( m_libfields->begin(), m_libfields->end(),
|
||||
[&]( const LIB_FIELD& f ) { return f.GetName() == spiceField; } ), m_libfields->end() );
|
||||
[&]( const LIB_FIELD& f ) { return f.GetName( NATIVE_FIELD_NAME ) == spiceField; } ),
|
||||
m_libfields->end() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,7 +282,7 @@ bool DIALOG_SPICE_MODEL::TransferDataToWindow()
|
||||
// TODO: There must be a good way to template out these repetitive calls
|
||||
for( auto field : *m_libfields )
|
||||
{
|
||||
if( field.GetName() == spiceField && !field.GetText().IsEmpty() )
|
||||
if( field.GetName( NATIVE_FIELD_NAME ) == spiceField && !field.GetText().IsEmpty() )
|
||||
{
|
||||
m_fieldsTmp[idx] = field.GetText();
|
||||
break;
|
||||
@@ -677,12 +678,14 @@ void DIALOG_SPICE_MODEL::loadLibrary( const wxString& aFilePath )
|
||||
file.Open( filePath.GetFullPath() );
|
||||
int line_nr = 0;
|
||||
|
||||
// Stores the libray content. It will be displayed after reading the full library
|
||||
wxString fullText;
|
||||
|
||||
// Process the file, looking for components
|
||||
while( !file.Eof() )
|
||||
{
|
||||
const wxString& line = line_nr == 0 ? file.GetFirstLine() : file.GetNextLine();
|
||||
m_libraryContents->AppendText( line );
|
||||
m_libraryContents->AppendText( "\n" );
|
||||
fullText << line << '\n';
|
||||
|
||||
wxStringTokenizer tokenizer( line );
|
||||
|
||||
@@ -729,6 +732,9 @@ void DIALOG_SPICE_MODEL::loadLibrary( const wxString& aFilePath )
|
||||
++line_nr;
|
||||
}
|
||||
|
||||
// display the full library content:
|
||||
m_libraryContents->AppendText( fullText );
|
||||
|
||||
wxArrayString modelsList;
|
||||
|
||||
// Refresh the model name combobox values
|
||||
@@ -773,7 +779,7 @@ LIB_FIELD& DIALOG_SPICE_MODEL::getLibField( int aFieldType )
|
||||
const wxString& spiceField = NETLIST_EXPORTER_PSPICE::GetSpiceFieldName( (SPICE_FIELD) aFieldType );
|
||||
|
||||
auto fieldIt = std::find_if( m_libfields->begin(), m_libfields->end(), [&]( const LIB_FIELD& f ) {
|
||||
return f.GetName() == spiceField;
|
||||
return f.GetName( NATIVE_FIELD_NAME ) == spiceField;
|
||||
} );
|
||||
|
||||
// Found one, so return it
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Jul 11 2018)
|
||||
// C++ code generated with wxFormBuilder (version Jul 10 2019)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@@ -12,187 +12,187 @@
|
||||
DIALOG_SPICE_MODEL_BASE::DIALOG_SPICE_MODEL_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style )
|
||||
{
|
||||
this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize );
|
||||
|
||||
|
||||
wxBoxSizer* bSizer1;
|
||||
bSizer1 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
|
||||
m_notebook = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_passive = new wxPanel( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
wxBoxSizer* bSizer41;
|
||||
bSizer41 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
|
||||
wxFlexGridSizer* fgSizer1;
|
||||
fgSizer1 = new wxFlexGridSizer( 0, 3, 0, 0 );
|
||||
fgSizer1->AddGrowableCol( 1 );
|
||||
fgSizer1->SetFlexibleDirection( wxBOTH );
|
||||
fgSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
|
||||
m_staticTextPtype = new wxStaticText( m_passive, wxID_ANY, _("Type:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticTextPtype->Wrap( -1 );
|
||||
fgSizer1->Add( m_staticTextPtype, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_pasType = new wxComboBox( m_passive, wxID_ANY, _("Resistor"), wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY );
|
||||
m_pasType->Append( _("Resistor") );
|
||||
m_pasType->Append( _("Capacitor") );
|
||||
m_pasType->Append( _("Inductor") );
|
||||
m_pasType->SetSelection( 0 );
|
||||
fgSizer1->Add( m_pasType, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticText62 = new wxStaticText( m_passive, wxID_ANY, _("Passive type"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText62->Wrap( -1 );
|
||||
fgSizer1->Add( m_staticText62, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_staticTextPvalue = new wxStaticText( m_passive, wxID_ANY, _("Value:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticTextPvalue->Wrap( -1 );
|
||||
fgSizer1->Add( m_staticTextPvalue, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_pasValue = new wxTextCtrl( m_passive, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_pasValue->SetMinSize( wxSize( 200,-1 ) );
|
||||
|
||||
|
||||
fgSizer1->Add( m_pasValue, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticTextSpVal = new wxStaticText( m_passive, wxID_ANY, _("Spice value in simulation"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticTextSpVal->Wrap( -1 );
|
||||
fgSizer1->Add( m_staticTextSpVal, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
|
||||
|
||||
bSizer41->Add( fgSizer1, 0, wxEXPAND|wxALL, 5 );
|
||||
|
||||
|
||||
m_staticline1 = new wxStaticLine( m_passive, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||
bSizer41->Add( m_staticline1, 0, wxEXPAND | wxALL, 5 );
|
||||
|
||||
|
||||
wxBoxSizer* bSizerUnits;
|
||||
bSizerUnits = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
|
||||
m_staticText32 = new wxStaticText( m_passive, wxID_ANY, _("In Spice values,the decimal separator is the point.\nValues can use Spice unit symbols."), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText32->Wrap( -1 );
|
||||
bSizerUnits->Add( m_staticText32, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_staticText321 = new wxStaticText( m_passive, wxID_ANY, _("Spice unit symbols in values (case insensitive):"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText321->Wrap( -1 );
|
||||
bSizerUnits->Add( m_staticText321, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
|
||||
wxFlexGridSizer* fgSizerUnitSymbols;
|
||||
fgSizerUnitSymbols = new wxFlexGridSizer( 0, 3, 0, 0 );
|
||||
fgSizerUnitSymbols->AddGrowableCol( 1 );
|
||||
fgSizerUnitSymbols->SetFlexibleDirection( wxBOTH );
|
||||
fgSizerUnitSymbols->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
|
||||
m_staticText341 = new wxStaticText( m_passive, wxID_ANY, _("f"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText341->Wrap( -1 );
|
||||
fgSizerUnitSymbols->Add( m_staticText341, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_staticText_femto = new wxStaticText( m_passive, wxID_ANY, _("femto"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText_femto->Wrap( -1 );
|
||||
fgSizerUnitSymbols->Add( m_staticText_femto, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 );
|
||||
|
||||
|
||||
m_staticText36 = new wxStaticText( m_passive, wxID_ANY, _("1e-15"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText36->Wrap( -1 );
|
||||
fgSizerUnitSymbols->Add( m_staticText36, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_staticText37 = new wxStaticText( m_passive, wxID_ANY, _("p"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText37->Wrap( -1 );
|
||||
fgSizerUnitSymbols->Add( m_staticText37, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_staticText38 = new wxStaticText( m_passive, wxID_ANY, _("pico"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText38->Wrap( -1 );
|
||||
fgSizerUnitSymbols->Add( m_staticText38, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 );
|
||||
|
||||
|
||||
m_staticText39 = new wxStaticText( m_passive, wxID_ANY, _("1e-12"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText39->Wrap( -1 );
|
||||
fgSizerUnitSymbols->Add( m_staticText39, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_staticText40 = new wxStaticText( m_passive, wxID_ANY, _("n"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText40->Wrap( -1 );
|
||||
fgSizerUnitSymbols->Add( m_staticText40, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_staticText41 = new wxStaticText( m_passive, wxID_ANY, _("nano"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText41->Wrap( -1 );
|
||||
fgSizerUnitSymbols->Add( m_staticText41, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 );
|
||||
|
||||
|
||||
m_staticText42 = new wxStaticText( m_passive, wxID_ANY, _("1e-9"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText42->Wrap( -1 );
|
||||
fgSizerUnitSymbols->Add( m_staticText42, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_staticText43 = new wxStaticText( m_passive, wxID_ANY, _("u"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText43->Wrap( -1 );
|
||||
fgSizerUnitSymbols->Add( m_staticText43, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_staticText44 = new wxStaticText( m_passive, wxID_ANY, _("micro"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText44->Wrap( -1 );
|
||||
fgSizerUnitSymbols->Add( m_staticText44, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 );
|
||||
|
||||
|
||||
m_staticText46 = new wxStaticText( m_passive, wxID_ANY, _("1e-6"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText46->Wrap( -1 );
|
||||
fgSizerUnitSymbols->Add( m_staticText46, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_staticText47 = new wxStaticText( m_passive, wxID_ANY, _("m"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText47->Wrap( -1 );
|
||||
fgSizerUnitSymbols->Add( m_staticText47, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_staticText48 = new wxStaticText( m_passive, wxID_ANY, _("milli"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText48->Wrap( -1 );
|
||||
fgSizerUnitSymbols->Add( m_staticText48, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 );
|
||||
|
||||
|
||||
m_staticText45 = new wxStaticText( m_passive, wxID_ANY, _("1e-3"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText45->Wrap( -1 );
|
||||
fgSizerUnitSymbols->Add( m_staticText45, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_staticText49 = new wxStaticText( m_passive, wxID_ANY, _("k"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText49->Wrap( -1 );
|
||||
fgSizerUnitSymbols->Add( m_staticText49, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_staticText50 = new wxStaticText( m_passive, wxID_ANY, _("kilo"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText50->Wrap( -1 );
|
||||
fgSizerUnitSymbols->Add( m_staticText50, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 );
|
||||
|
||||
|
||||
m_staticText51 = new wxStaticText( m_passive, wxID_ANY, _("1e3"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText51->Wrap( -1 );
|
||||
fgSizerUnitSymbols->Add( m_staticText51, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_staticText52 = new wxStaticText( m_passive, wxID_ANY, _("meg"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText52->Wrap( -1 );
|
||||
fgSizerUnitSymbols->Add( m_staticText52, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_staticText53 = new wxStaticText( m_passive, wxID_ANY, _("mega"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText53->Wrap( -1 );
|
||||
fgSizerUnitSymbols->Add( m_staticText53, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 );
|
||||
|
||||
|
||||
m_staticText54 = new wxStaticText( m_passive, wxID_ANY, _("1e6"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText54->Wrap( -1 );
|
||||
fgSizerUnitSymbols->Add( m_staticText54, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_staticText55 = new wxStaticText( m_passive, wxID_ANY, _("g"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText55->Wrap( -1 );
|
||||
fgSizerUnitSymbols->Add( m_staticText55, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_staticText56 = new wxStaticText( m_passive, wxID_ANY, _("giga"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText56->Wrap( -1 );
|
||||
fgSizerUnitSymbols->Add( m_staticText56, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 );
|
||||
|
||||
|
||||
m_staticText57 = new wxStaticText( m_passive, wxID_ANY, _("1e9"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText57->Wrap( -1 );
|
||||
fgSizerUnitSymbols->Add( m_staticText57, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_staticText58 = new wxStaticText( m_passive, wxID_ANY, _("t"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText58->Wrap( -1 );
|
||||
fgSizerUnitSymbols->Add( m_staticText58, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_staticText59 = new wxStaticText( m_passive, wxID_ANY, _("tera"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText59->Wrap( -1 );
|
||||
fgSizerUnitSymbols->Add( m_staticText59, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 );
|
||||
|
||||
|
||||
m_staticText60 = new wxStaticText( m_passive, wxID_ANY, _("1e12"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText60->Wrap( -1 );
|
||||
fgSizerUnitSymbols->Add( m_staticText60, 0, wxALL, 5 );
|
||||
|
||||
|
||||
|
||||
|
||||
bSizerUnits->Add( fgSizerUnitSymbols, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
|
||||
|
||||
bSizer41->Add( bSizerUnits, 0, wxALIGN_CENTER_HORIZONTAL, 5 );
|
||||
|
||||
|
||||
|
||||
|
||||
m_passive->SetSizer( bSizer41 );
|
||||
m_passive->Layout();
|
||||
bSizer41->Fit( m_passive );
|
||||
@@ -200,129 +200,156 @@ DIALOG_SPICE_MODEL_BASE::DIALOG_SPICE_MODEL_BASE( wxWindow* parent, wxWindowID i
|
||||
m_model = new wxPanel( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
wxBoxSizer* bSizer6;
|
||||
bSizer6 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
|
||||
wxFlexGridSizer* fgSizer3;
|
||||
fgSizer3 = new wxFlexGridSizer( 0, 2, 0, 0 );
|
||||
fgSizer3->AddGrowableCol( 1 );
|
||||
fgSizer3->SetFlexibleDirection( wxBOTH );
|
||||
fgSizer3->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
|
||||
m_staticText7 = new wxStaticText( m_model, wxID_ANY, _("Library:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText7->Wrap( -1 );
|
||||
fgSizer3->Add( m_staticText7, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
wxBoxSizer* bSizer7;
|
||||
bSizer7 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
|
||||
m_modelLibrary = new wxTextCtrl( m_model, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizer7->Add( m_modelLibrary, 1, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_selectLibrary = new wxButton( m_model, wxID_ANY, _("Select file..."), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizer7->Add( m_selectLibrary, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
|
||||
|
||||
fgSizer3->Add( bSizer7, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticText5 = new wxStaticText( m_model, wxID_ANY, _("Model:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText5->Wrap( -1 );
|
||||
fgSizer3->Add( m_staticText5, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
m_modelName = new wxComboBox( m_model, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_SORT );
|
||||
|
||||
m_modelName = new wxComboBox( m_model, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_SORT );
|
||||
fgSizer3->Add( m_modelName, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticText4 = new wxStaticText( m_model, wxID_ANY, _("Type:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText4->Wrap( -1 );
|
||||
fgSizer3->Add( m_staticText4, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
m_modelType = new wxComboBox( m_model, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY );
|
||||
|
||||
m_modelType = new wxComboBox( m_model, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY );
|
||||
fgSizer3->Add( m_modelType, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
|
||||
|
||||
bSizer6->Add( fgSizer3, 0, wxEXPAND, 5 );
|
||||
|
||||
m_libraryContents = new wxTextCtrl( m_model, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_DONTWRAP|wxTE_MULTILINE|wxTE_READONLY );
|
||||
m_libraryContents->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) );
|
||||
|
||||
bSizer6->Add( m_libraryContents, 1, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
|
||||
m_libraryContents = new wxStyledTextCtrl( m_model, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, wxEmptyString );
|
||||
m_libraryContents->SetUseTabs( false );
|
||||
m_libraryContents->SetTabWidth( 4 );
|
||||
m_libraryContents->SetIndent( 4 );
|
||||
m_libraryContents->SetTabIndents( true );
|
||||
m_libraryContents->SetBackSpaceUnIndents( true );
|
||||
m_libraryContents->SetViewEOL( false );
|
||||
m_libraryContents->SetViewWhiteSpace( false );
|
||||
m_libraryContents->SetMarginWidth( 2, 0 );
|
||||
m_libraryContents->SetIndentationGuides( false );
|
||||
m_libraryContents->SetMarginWidth( 1, 0 );
|
||||
m_libraryContents->SetMarginType( 0, wxSTC_MARGIN_NUMBER );
|
||||
m_libraryContents->SetMarginWidth( 0, m_libraryContents->TextWidth( wxSTC_STYLE_LINENUMBER, wxT("_99999") ) );
|
||||
m_libraryContents->MarkerDefine( wxSTC_MARKNUM_FOLDER, wxSTC_MARK_BOXPLUS );
|
||||
m_libraryContents->MarkerSetBackground( wxSTC_MARKNUM_FOLDER, wxColour( wxT("BLACK") ) );
|
||||
m_libraryContents->MarkerSetForeground( wxSTC_MARKNUM_FOLDER, wxColour( wxT("WHITE") ) );
|
||||
m_libraryContents->MarkerDefine( wxSTC_MARKNUM_FOLDEROPEN, wxSTC_MARK_BOXMINUS );
|
||||
m_libraryContents->MarkerSetBackground( wxSTC_MARKNUM_FOLDEROPEN, wxColour( wxT("BLACK") ) );
|
||||
m_libraryContents->MarkerSetForeground( wxSTC_MARKNUM_FOLDEROPEN, wxColour( wxT("WHITE") ) );
|
||||
m_libraryContents->MarkerDefine( wxSTC_MARKNUM_FOLDERSUB, wxSTC_MARK_EMPTY );
|
||||
m_libraryContents->MarkerDefine( wxSTC_MARKNUM_FOLDEREND, wxSTC_MARK_BOXPLUS );
|
||||
m_libraryContents->MarkerSetBackground( wxSTC_MARKNUM_FOLDEREND, wxColour( wxT("BLACK") ) );
|
||||
m_libraryContents->MarkerSetForeground( wxSTC_MARKNUM_FOLDEREND, wxColour( wxT("WHITE") ) );
|
||||
m_libraryContents->MarkerDefine( wxSTC_MARKNUM_FOLDEROPENMID, wxSTC_MARK_BOXMINUS );
|
||||
m_libraryContents->MarkerSetBackground( wxSTC_MARKNUM_FOLDEROPENMID, wxColour( wxT("BLACK") ) );
|
||||
m_libraryContents->MarkerSetForeground( wxSTC_MARKNUM_FOLDEROPENMID, wxColour( wxT("WHITE") ) );
|
||||
m_libraryContents->MarkerDefine( wxSTC_MARKNUM_FOLDERMIDTAIL, wxSTC_MARK_EMPTY );
|
||||
m_libraryContents->MarkerDefine( wxSTC_MARKNUM_FOLDERTAIL, wxSTC_MARK_EMPTY );
|
||||
m_libraryContents->SetSelBackground( true, wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
|
||||
m_libraryContents->SetSelForeground( true, wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHTTEXT ) );
|
||||
bSizer6->Add( m_libraryContents, 1, wxEXPAND | wxALL, 5 );
|
||||
|
||||
|
||||
m_model->SetSizer( bSizer6 );
|
||||
m_model->Layout();
|
||||
bSizer6->Fit( m_model );
|
||||
m_notebook->AddPage( m_model, _("Model"), false );
|
||||
m_power = new wxPanel( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
m_power->SetMinSize( wxSize( 650,-1 ) );
|
||||
|
||||
|
||||
wxBoxSizer* bSizer4;
|
||||
bSizer4 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
|
||||
wxStaticBoxSizer* sbSizer1;
|
||||
sbSizer1 = new wxStaticBoxSizer( new wxStaticBox( m_power, wxID_ANY, _("DC/AC analysis:") ), wxVERTICAL );
|
||||
|
||||
|
||||
wxFlexGridSizer* fgSizer6;
|
||||
fgSizer6 = new wxFlexGridSizer( 0, 6, 0, 0 );
|
||||
fgSizer6->AddGrowableCol( 1 );
|
||||
fgSizer6->AddGrowableCol( 3 );
|
||||
fgSizer6->SetFlexibleDirection( wxBOTH );
|
||||
fgSizer6->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
|
||||
m_staticText10 = new wxStaticText( sbSizer1->GetStaticBox(), wxID_ANY, _("DC:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText10->Wrap( -1 );
|
||||
fgSizer6->Add( m_staticText10, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_genDc = new wxTextCtrl( sbSizer1->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_genDc->SetMinSize( wxSize( 60,-1 ) );
|
||||
|
||||
|
||||
fgSizer6->Add( m_genDc, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticText113 = new wxStaticText( sbSizer1->GetStaticBox(), wxID_ANY, _("Volts/Amps"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText113->Wrap( -1 );
|
||||
fgSizer6->Add( m_staticText113, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
|
||||
|
||||
|
||||
|
||||
|
||||
fgSizer6->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
|
||||
|
||||
fgSizer6->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
|
||||
|
||||
fgSizer6->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticText11 = new wxStaticText( sbSizer1->GetStaticBox(), wxID_ANY, _("AC magnitude:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText11->Wrap( -1 );
|
||||
fgSizer6->Add( m_staticText11, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_genAcMag = new wxTextCtrl( sbSizer1->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_genAcMag->SetMinSize( wxSize( 60,-1 ) );
|
||||
|
||||
|
||||
fgSizer6->Add( m_genAcMag, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticText111 = new wxStaticText( sbSizer1->GetStaticBox(), wxID_ANY, _("Volts/Amps"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText111->Wrap( -1 );
|
||||
fgSizer6->Add( m_staticText111, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
|
||||
|
||||
|
||||
m_staticText12 = new wxStaticText( sbSizer1->GetStaticBox(), wxID_ANY, _("AC phase:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText12->Wrap( -1 );
|
||||
fgSizer6->Add( m_staticText12, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5 );
|
||||
|
||||
|
||||
m_genAcPhase = new wxTextCtrl( sbSizer1->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_genAcPhase->SetMinSize( wxSize( 60,-1 ) );
|
||||
|
||||
|
||||
fgSizer6->Add( m_genAcPhase, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticText112 = new wxStaticText( sbSizer1->GetStaticBox(), wxID_ANY, _("radians"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText112->Wrap( -1 );
|
||||
fgSizer6->Add( m_staticText112, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
|
||||
|
||||
|
||||
|
||||
|
||||
sbSizer1->Add( fgSizer6, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
|
||||
|
||||
bSizer4->Add( sbSizer1, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
wxStaticBoxSizer* sbSizer3;
|
||||
sbSizer3 = new wxStaticBoxSizer( new wxStaticBox( m_power, wxID_ANY, _("Transient analysis:") ), wxVERTICAL );
|
||||
|
||||
|
||||
m_powerNotebook = new wxNotebook( sbSizer3->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_pwrPulse = new wxPanel( m_powerNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
wxFlexGridSizer* fgSizer7;
|
||||
@@ -330,87 +357,87 @@ DIALOG_SPICE_MODEL_BASE::DIALOG_SPICE_MODEL_BASE( wxWindow* parent, wxWindowID i
|
||||
fgSizer7->AddGrowableCol( 1 );
|
||||
fgSizer7->SetFlexibleDirection( wxBOTH );
|
||||
fgSizer7->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
|
||||
m_staticText13 = new wxStaticText( m_pwrPulse, wxID_ANY, _("Initial value:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText13->Wrap( -1 );
|
||||
fgSizer7->Add( m_staticText13, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_pulseInit = new wxTextCtrl( m_pwrPulse, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_pulseInit->SetMinSize( wxSize( 100,-1 ) );
|
||||
|
||||
|
||||
fgSizer7->Add( m_pulseInit, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticText131 = new wxStaticText( m_pwrPulse, wxID_ANY, _("Volts/Amps"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText131->Wrap( -1 );
|
||||
fgSizer7->Add( m_staticText131, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
|
||||
|
||||
|
||||
m_staticText14 = new wxStaticText( m_pwrPulse, wxID_ANY, _("Pulsed value:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText14->Wrap( -1 );
|
||||
fgSizer7->Add( m_staticText14, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_pulseNominal = new wxTextCtrl( m_pwrPulse, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer7->Add( m_pulseNominal, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticText132 = new wxStaticText( m_pwrPulse, wxID_ANY, _("Volts/Amps"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText132->Wrap( -1 );
|
||||
fgSizer7->Add( m_staticText132, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
|
||||
|
||||
|
||||
m_staticText15 = new wxStaticText( m_pwrPulse, wxID_ANY, _("Delay time:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText15->Wrap( -1 );
|
||||
fgSizer7->Add( m_staticText15, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_pulseDelay = new wxTextCtrl( m_pwrPulse, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer7->Add( m_pulseDelay, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticText133 = new wxStaticText( m_pwrPulse, wxID_ANY, _("seconds"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText133->Wrap( -1 );
|
||||
fgSizer7->Add( m_staticText133, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
|
||||
|
||||
|
||||
m_staticText16 = new wxStaticText( m_pwrPulse, wxID_ANY, _("Rise time:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText16->Wrap( -1 );
|
||||
fgSizer7->Add( m_staticText16, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_pulseRise = new wxTextCtrl( m_pwrPulse, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer7->Add( m_pulseRise, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticText134 = new wxStaticText( m_pwrPulse, wxID_ANY, _("seconds"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText134->Wrap( -1 );
|
||||
fgSizer7->Add( m_staticText134, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
|
||||
|
||||
|
||||
m_staticText17 = new wxStaticText( m_pwrPulse, wxID_ANY, _("Fall time:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText17->Wrap( -1 );
|
||||
fgSizer7->Add( m_staticText17, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_pulseFall = new wxTextCtrl( m_pwrPulse, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer7->Add( m_pulseFall, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticText135 = new wxStaticText( m_pwrPulse, wxID_ANY, _("seconds"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText135->Wrap( -1 );
|
||||
fgSizer7->Add( m_staticText135, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
|
||||
|
||||
|
||||
m_staticText18 = new wxStaticText( m_pwrPulse, wxID_ANY, _("Pulse width:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText18->Wrap( -1 );
|
||||
fgSizer7->Add( m_staticText18, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_pulseWidth = new wxTextCtrl( m_pwrPulse, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer7->Add( m_pulseWidth, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticText136 = new wxStaticText( m_pwrPulse, wxID_ANY, _("seconds"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText136->Wrap( -1 );
|
||||
fgSizer7->Add( m_staticText136, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
|
||||
|
||||
|
||||
m_staticText20 = new wxStaticText( m_pwrPulse, wxID_ANY, _("Period:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText20->Wrap( -1 );
|
||||
fgSizer7->Add( m_staticText20, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_pulsePeriod = new wxTextCtrl( m_pwrPulse, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer7->Add( m_pulsePeriod, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticText137 = new wxStaticText( m_pwrPulse, wxID_ANY, _("seconds"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText137->Wrap( -1 );
|
||||
fgSizer7->Add( m_staticText137, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
|
||||
|
||||
|
||||
|
||||
|
||||
m_pwrPulse->SetSizer( fgSizer7 );
|
||||
m_pwrPulse->Layout();
|
||||
fgSizer7->Fit( m_pwrPulse );
|
||||
@@ -421,65 +448,65 @@ DIALOG_SPICE_MODEL_BASE::DIALOG_SPICE_MODEL_BASE( wxWindow* parent, wxWindowID i
|
||||
fgSizer8->AddGrowableCol( 1 );
|
||||
fgSizer8->SetFlexibleDirection( wxBOTH );
|
||||
fgSizer8->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
|
||||
m_staticText21 = new wxStaticText( m_pwrSin, wxID_ANY, _("DC offset:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText21->Wrap( -1 );
|
||||
fgSizer8->Add( m_staticText21, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_sinOffset = new wxTextCtrl( m_pwrSin, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_sinOffset->SetMinSize( wxSize( 100,-1 ) );
|
||||
|
||||
|
||||
fgSizer8->Add( m_sinOffset, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticText211 = new wxStaticText( m_pwrSin, wxID_ANY, _("Volts/Amps"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText211->Wrap( -1 );
|
||||
fgSizer8->Add( m_staticText211, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
|
||||
|
||||
|
||||
m_staticText22 = new wxStaticText( m_pwrSin, wxID_ANY, _("Amplitude:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText22->Wrap( -1 );
|
||||
fgSizer8->Add( m_staticText22, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_sinAmplitude = new wxTextCtrl( m_pwrSin, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer8->Add( m_sinAmplitude, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticText212 = new wxStaticText( m_pwrSin, wxID_ANY, _("Volts/Amps"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText212->Wrap( -1 );
|
||||
fgSizer8->Add( m_staticText212, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
|
||||
|
||||
|
||||
m_staticText23 = new wxStaticText( m_pwrSin, wxID_ANY, _("Frequency:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText23->Wrap( -1 );
|
||||
fgSizer8->Add( m_staticText23, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_sinFreq = new wxTextCtrl( m_pwrSin, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer8->Add( m_sinFreq, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticText213 = new wxStaticText( m_pwrSin, wxID_ANY, _("Hz"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText213->Wrap( -1 );
|
||||
fgSizer8->Add( m_staticText213, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
|
||||
|
||||
|
||||
m_staticText24 = new wxStaticText( m_pwrSin, wxID_ANY, _("Delay:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText24->Wrap( -1 );
|
||||
fgSizer8->Add( m_staticText24, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_sinDelay = new wxTextCtrl( m_pwrSin, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer8->Add( m_sinDelay, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticText214 = new wxStaticText( m_pwrSin, wxID_ANY, _("seconds"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText214->Wrap( -1 );
|
||||
fgSizer8->Add( m_staticText214, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
|
||||
|
||||
|
||||
m_staticText25 = new wxStaticText( m_pwrSin, wxID_ANY, _("Damping factor:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText25->Wrap( -1 );
|
||||
fgSizer8->Add( m_staticText25, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_sinDampFactor = new wxTextCtrl( m_pwrSin, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer8->Add( m_sinDampFactor, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticText215 = new wxStaticText( m_pwrSin, wxID_ANY, _("1/seconds"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText215->Wrap( -1 );
|
||||
fgSizer8->Add( m_staticText215, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
|
||||
|
||||
|
||||
|
||||
|
||||
m_pwrSin->SetSizer( fgSizer8 );
|
||||
m_pwrSin->Layout();
|
||||
fgSizer8->Fit( m_pwrSin );
|
||||
@@ -490,218 +517,217 @@ DIALOG_SPICE_MODEL_BASE::DIALOG_SPICE_MODEL_BASE( wxWindow* parent, wxWindowID i
|
||||
fgSizer9->AddGrowableCol( 1 );
|
||||
fgSizer9->SetFlexibleDirection( wxBOTH );
|
||||
fgSizer9->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
|
||||
m_staticText26 = new wxStaticText( m_pwrExp, wxID_ANY, _("Initial value:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText26->Wrap( -1 );
|
||||
fgSizer9->Add( m_staticText26, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_expInit = new wxTextCtrl( m_pwrExp, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_expInit->SetMinSize( wxSize( 100,-1 ) );
|
||||
|
||||
|
||||
fgSizer9->Add( m_expInit, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticText261 = new wxStaticText( m_pwrExp, wxID_ANY, _("Volts/Amps"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText261->Wrap( -1 );
|
||||
fgSizer9->Add( m_staticText261, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
|
||||
|
||||
|
||||
m_staticText27 = new wxStaticText( m_pwrExp, wxID_ANY, _("Pulsed value:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText27->Wrap( -1 );
|
||||
fgSizer9->Add( m_staticText27, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_expPulsed = new wxTextCtrl( m_pwrExp, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer9->Add( m_expPulsed, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticText262 = new wxStaticText( m_pwrExp, wxID_ANY, _("Volts/Amps"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText262->Wrap( -1 );
|
||||
fgSizer9->Add( m_staticText262, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
|
||||
|
||||
|
||||
m_staticText28 = new wxStaticText( m_pwrExp, wxID_ANY, _("Rise delay time:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText28->Wrap( -1 );
|
||||
fgSizer9->Add( m_staticText28, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_expRiseDelay = new wxTextCtrl( m_pwrExp, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer9->Add( m_expRiseDelay, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticText263 = new wxStaticText( m_pwrExp, wxID_ANY, _("seconds"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText263->Wrap( -1 );
|
||||
fgSizer9->Add( m_staticText263, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
|
||||
|
||||
|
||||
m_staticText29 = new wxStaticText( m_pwrExp, wxID_ANY, _("Rise time constant:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText29->Wrap( -1 );
|
||||
fgSizer9->Add( m_staticText29, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_expRiseConst = new wxTextCtrl( m_pwrExp, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer9->Add( m_expRiseConst, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticText264 = new wxStaticText( m_pwrExp, wxID_ANY, _("seconds"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText264->Wrap( -1 );
|
||||
fgSizer9->Add( m_staticText264, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
|
||||
|
||||
|
||||
m_staticText30 = new wxStaticText( m_pwrExp, wxID_ANY, _("Fall delay time:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText30->Wrap( -1 );
|
||||
fgSizer9->Add( m_staticText30, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_expFallDelay = new wxTextCtrl( m_pwrExp, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer9->Add( m_expFallDelay, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticText265 = new wxStaticText( m_pwrExp, wxID_ANY, _("seconds"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText265->Wrap( -1 );
|
||||
fgSizer9->Add( m_staticText265, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
|
||||
|
||||
|
||||
m_staticText31 = new wxStaticText( m_pwrExp, wxID_ANY, _("Fall time constant:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText31->Wrap( -1 );
|
||||
fgSizer9->Add( m_staticText31, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_expFallConst = new wxTextCtrl( m_pwrExp, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer9->Add( m_expFallConst, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticText266 = new wxStaticText( m_pwrExp, wxID_ANY, _("seconds"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText266->Wrap( -1 );
|
||||
fgSizer9->Add( m_staticText266, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
|
||||
|
||||
|
||||
|
||||
|
||||
m_pwrExp->SetSizer( fgSizer9 );
|
||||
m_pwrExp->Layout();
|
||||
fgSizer9->Fit( m_pwrExp );
|
||||
m_powerNotebook->AddPage( m_pwrExp, _("Exponential"), false );
|
||||
m_pwrPwl = new wxPanel( m_powerNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
m_pwrPwl->SetToolTip( _("Piece-wise linear") );
|
||||
|
||||
|
||||
wxFlexGridSizer* fgSizer15;
|
||||
fgSizer15 = new wxFlexGridSizer( 0, 2, 0, 0 );
|
||||
fgSizer15->AddGrowableCol( 0 );
|
||||
fgSizer15->AddGrowableRow( 1 );
|
||||
fgSizer15->SetFlexibleDirection( wxBOTH );
|
||||
fgSizer15->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_ALL );
|
||||
|
||||
|
||||
wxFlexGridSizer* fgSizer10;
|
||||
fgSizer10 = new wxFlexGridSizer( 0, 3, 0, 0 );
|
||||
fgSizer10->AddGrowableCol( 1 );
|
||||
fgSizer10->SetFlexibleDirection( wxBOTH );
|
||||
fgSizer10->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
|
||||
m_staticText34 = new wxStaticText( m_pwrPwl, wxID_ANY, _("Time:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText34->Wrap( -1 );
|
||||
fgSizer10->Add( m_staticText34, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_pwlTime = new wxTextCtrl( m_pwrPwl, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_pwlTime->SetMinSize( wxSize( 100,-1 ) );
|
||||
|
||||
|
||||
fgSizer10->Add( m_pwlTime, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticText342 = new wxStaticText( m_pwrPwl, wxID_ANY, _("second"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText342->Wrap( -1 );
|
||||
fgSizer10->Add( m_staticText342, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
|
||||
|
||||
|
||||
m_staticText35 = new wxStaticText( m_pwrPwl, wxID_ANY, _("Value:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText35->Wrap( -1 );
|
||||
fgSizer10->Add( m_staticText35, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_pwlValue = new wxTextCtrl( m_pwrPwl, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer10->Add( m_pwlValue, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticText343 = new wxStaticText( m_pwrPwl, wxID_ANY, _("Volts/Amps"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText343->Wrap( -1 );
|
||||
fgSizer10->Add( m_staticText343, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT, 5 );
|
||||
|
||||
|
||||
|
||||
|
||||
fgSizer15->Add( fgSizer10, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_pwlAddButton = new wxButton( m_pwrPwl, wxID_ANY, _("Add"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer15->Add( m_pwlAddButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_pwlValList = new wxListCtrl( m_pwrPwl, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT|wxLC_SINGLE_SEL );
|
||||
m_pwlValList->SetMinSize( wxSize( 200,-1 ) );
|
||||
|
||||
|
||||
fgSizer15->Add( m_pwlValList, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_pwlRemoveBtn = new wxButton( m_pwrPwl, wxID_ANY, _("Remove"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizer15->Add( m_pwlRemoveBtn, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
|
||||
|
||||
m_pwrPwl->SetSizer( fgSizer15 );
|
||||
m_pwrPwl->Layout();
|
||||
fgSizer15->Fit( m_pwrPwl );
|
||||
m_powerNotebook->AddPage( m_pwrPwl, _("Piece-wise Linear"), false );
|
||||
m_pwrFm = new wxPanel( m_powerNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
m_pwrFm->Hide();
|
||||
|
||||
|
||||
m_powerNotebook->AddPage( m_pwrFm, _("FM"), false );
|
||||
m_pwrAm = new wxPanel( m_powerNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
m_pwrAm->Hide();
|
||||
|
||||
|
||||
m_powerNotebook->AddPage( m_pwrAm, _("AM"), false );
|
||||
m_pwrTransNoise = new wxPanel( m_powerNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
m_pwrTransNoise->Hide();
|
||||
|
||||
|
||||
m_powerNotebook->AddPage( m_pwrTransNoise, _("Transient noise"), false );
|
||||
m_pwrRandom = new wxPanel( m_powerNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
m_pwrRandom->Hide();
|
||||
|
||||
|
||||
m_powerNotebook->AddPage( m_pwrRandom, _("Random"), false );
|
||||
m_pwrExtData = new wxPanel( m_powerNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
m_pwrExtData->Hide();
|
||||
|
||||
|
||||
m_powerNotebook->AddPage( m_pwrExtData, _("External data"), false );
|
||||
|
||||
|
||||
sbSizer3->Add( m_powerNotebook, 0, wxEXPAND | wxALL, 5 );
|
||||
|
||||
|
||||
|
||||
|
||||
bSizer4->Add( sbSizer3, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
wxString m_pwrTypeChoices[] = { _("Voltage"), _("Current") };
|
||||
int m_pwrTypeNChoices = sizeof( m_pwrTypeChoices ) / sizeof( wxString );
|
||||
m_pwrType = new wxRadioBox( m_power, wxID_ANY, _("Source type:"), wxDefaultPosition, wxDefaultSize, m_pwrTypeNChoices, m_pwrTypeChoices, 1, wxRA_SPECIFY_ROWS );
|
||||
m_pwrType->SetSelection( 1 );
|
||||
bSizer4->Add( m_pwrType, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
|
||||
|
||||
m_power->SetSizer( bSizer4 );
|
||||
m_power->Layout();
|
||||
bSizer4->Fit( m_power );
|
||||
m_notebook->AddPage( m_power, _("Source"), false );
|
||||
|
||||
|
||||
bSizer1->Add( m_notebook, 1, wxEXPAND | wxALL, 5 );
|
||||
|
||||
|
||||
m_staticline2 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||
bSizer1->Add( m_staticline2, 0, wxEXPAND | wxALL, 5 );
|
||||
|
||||
|
||||
m_disabled = new wxCheckBox( this, wxID_ANY, _("Disable symbol for simulation"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizer1->Add( m_disabled, 0, wxALL, 5 );
|
||||
|
||||
|
||||
wxBoxSizer* bSizer2;
|
||||
bSizer2 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
|
||||
m_nodeSeqCheck = new wxCheckBox( this, wxID_ANY, _("Alternate node sequence:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizer2->Add( m_nodeSeqCheck, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
m_nodeSeqVal = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_nodeSeqVal->SetMinSize( wxSize( 200,-1 ) );
|
||||
|
||||
|
||||
bSizer2->Add( m_nodeSeqVal, 1, wxALL, 5 );
|
||||
|
||||
|
||||
|
||||
|
||||
bSizer1->Add( bSizer2, 0, wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_staticline3 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||
bSizer1->Add( m_staticline3, 0, wxEXPAND | wxALL, 5 );
|
||||
|
||||
|
||||
m_sdbSizer = new wxStdDialogButtonSizer();
|
||||
m_sdbSizerOK = new wxButton( this, wxID_OK );
|
||||
m_sdbSizer->AddButton( m_sdbSizerOK );
|
||||
m_sdbSizerCancel = new wxButton( this, wxID_CANCEL );
|
||||
m_sdbSizer->AddButton( m_sdbSizerCancel );
|
||||
m_sdbSizer->Realize();
|
||||
|
||||
|
||||
bSizer1->Add( m_sdbSizer, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
|
||||
|
||||
this->SetSizer( bSizer1 );
|
||||
this->Layout();
|
||||
bSizer1->Fit( this );
|
||||
|
||||
|
||||
this->Centre( wxBOTH );
|
||||
|
||||
|
||||
// Connect Events
|
||||
this->Connect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( DIALOG_SPICE_MODEL_BASE::onInitDlg ) );
|
||||
m_selectLibrary->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onSelectLibrary ), NULL, this );
|
||||
@@ -720,5 +746,5 @@ DIALOG_SPICE_MODEL_BASE::~DIALOG_SPICE_MODEL_BASE()
|
||||
m_modelName->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onModelSelected ), NULL, this );
|
||||
m_pwlAddButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onPwlAdd ), NULL, this );
|
||||
m_pwlRemoveBtn->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SPICE_MODEL_BASE::onPwlRemove ), NULL, this );
|
||||
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,11 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Jul 11 2018)
|
||||
// C++ code generated with wxFormBuilder (version Jul 10 2019)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __DIALOG_SPICE_MODEL_BASE_H__
|
||||
#define __DIALOG_SPICE_MODEL_BASE_H__
|
||||
#pragma once
|
||||
|
||||
#include <wx/artprov.h>
|
||||
#include <wx/xrc/xmlres.h>
|
||||
@@ -27,6 +26,7 @@
|
||||
#include <wx/image.h>
|
||||
#include <wx/icon.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/stc/stc.h>
|
||||
#include <wx/statbox.h>
|
||||
#include <wx/listctrl.h>
|
||||
#include <wx/notebook.h>
|
||||
@@ -43,7 +43,7 @@
|
||||
class DIALOG_SPICE_MODEL_BASE : public DIALOG_SHIM
|
||||
{
|
||||
private:
|
||||
|
||||
|
||||
protected:
|
||||
wxNotebook* m_notebook;
|
||||
wxPanel* m_passive;
|
||||
@@ -91,7 +91,7 @@ class DIALOG_SPICE_MODEL_BASE : public DIALOG_SHIM
|
||||
wxComboBox* m_modelName;
|
||||
wxStaticText* m_staticText4;
|
||||
wxComboBox* m_modelType;
|
||||
wxTextCtrl* m_libraryContents;
|
||||
wxStyledTextCtrl* m_libraryContents;
|
||||
wxPanel* m_power;
|
||||
wxStaticText* m_staticText10;
|
||||
wxTextCtrl* m_genDc;
|
||||
@@ -184,20 +184,19 @@ class DIALOG_SPICE_MODEL_BASE : public DIALOG_SHIM
|
||||
wxStdDialogButtonSizer* m_sdbSizer;
|
||||
wxButton* m_sdbSizerOK;
|
||||
wxButton* m_sdbSizerCancel;
|
||||
|
||||
|
||||
// Virtual event handlers, overide them in your derived class
|
||||
virtual void onInitDlg( wxInitDialogEvent& event ) { event.Skip(); }
|
||||
virtual void onSelectLibrary( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void onModelSelected( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void onPwlAdd( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void onPwlRemove( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
DIALOG_SPICE_MODEL_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Spice Model Editor"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
|
||||
|
||||
DIALOG_SPICE_MODEL_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Spice Model Editor"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 494,604 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
|
||||
~DIALOG_SPICE_MODEL_BASE();
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif //__DIALOG_SPICE_MODEL_BASE_H__
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <sch_draw_panel.h>
|
||||
#include <confirm.h>
|
||||
#include <sch_edit_frame.h>
|
||||
#include <sch_view.h>
|
||||
#include <kicad_device_context.h>
|
||||
|
||||
#include <general.h>
|
||||
@@ -238,6 +239,34 @@ void SCH_EDIT_FRAME::OnConvertTextType( wxCommandEvent& aEvent )
|
||||
if( screen->GetCurItem() == text )
|
||||
screen->SetCurItem( newtext );
|
||||
|
||||
// handle dangling end for the different label/text types
|
||||
if( type == SCH_TEXT_T )
|
||||
{
|
||||
if( newtext->IsDangling() )
|
||||
{
|
||||
newtext->SetIsDangling( false );
|
||||
GetCanvas()->GetView()->Update( newtext, KIGFX::REPAINT );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
newtext->SetIsDangling( true );
|
||||
}
|
||||
|
||||
TestDanglingEnds();
|
||||
|
||||
// fix rotation of the converted label, only needed for horizontal labels:
|
||||
bool newTypeIsBig = newtext->Type() == SCH_GLOBAL_LABEL_T ||
|
||||
newtext->Type() == SCH_HIERARCHICAL_LABEL_T;
|
||||
bool oldTypeIsBig = text->Type() == SCH_GLOBAL_LABEL_T ||
|
||||
text->Type() == SCH_HIERARCHICAL_LABEL_T;
|
||||
|
||||
if ( ( newTypeIsBig && !oldTypeIsBig ) ||
|
||||
( !newTypeIsBig && oldTypeIsBig ) )
|
||||
{
|
||||
newtext->MirrorY( newtext->GetPosition().x );
|
||||
}
|
||||
|
||||
if( text->IsNew() )
|
||||
{
|
||||
// if the previous text is new, no undo command to prepare here
|
||||
|
||||
@@ -357,6 +357,7 @@ static const wxString RepeatStepXEntry = "RepeatStepX";
|
||||
static const wxString RepeatStepYEntry = "RepeatStepY";
|
||||
static const wxString RepeatLabelIncrementEntry = "RepeatLabelIncrement";
|
||||
static const wxString ShowIllegalSymboLibDialog = "ShowIllegalSymbolLibDialog";
|
||||
static const wxString showSheetFileNameCaseSensitivityDlg = "ShowSheetFileNameCaseSensitivityDlg";
|
||||
|
||||
// Library editor wxConfig entry names.
|
||||
static const wxChar defaultLibWidthEntry[] = wxT( "LibeditLibWidth" );
|
||||
@@ -401,7 +402,9 @@ PARAM_CFG_ARRAY& SCH_EDIT_FRAME::GetConfigurationSettings()
|
||||
-10, +10 ) );
|
||||
m_configSettings.push_back( new PARAM_CFG_BOOL( true, ShowIllegalSymboLibDialog,
|
||||
&m_showIllegalSymbolLibDialog, true ) );
|
||||
|
||||
m_configSettings.push_back( new PARAM_CFG_BOOL( true, showSheetFileNameCaseSensitivityDlg,
|
||||
&m_showSheetFileNameCaseSensitivityDlg,
|
||||
true ) );
|
||||
return m_configSettings;
|
||||
}
|
||||
|
||||
@@ -547,6 +550,7 @@ void SCH_EDIT_FRAME::SaveSettings( wxConfigBase* aCfg )
|
||||
record.Replace( wxT(" "), wxT(" "), true ); // double space to single
|
||||
|
||||
aCfg->Write( FieldNamesEntry, record );
|
||||
aCfg->Write( showSheetFileNameCaseSensitivityDlg, m_showSheetFileNameCaseSensitivityDlg );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -82,13 +82,13 @@ FIELDS_GRID_TABLE<T>::FIELDS_GRID_TABLE( DIALOG_SHIM* aDialog, SCH_BASE_FRAME* a
|
||||
m_urlAttr = new wxGridCellAttr;
|
||||
GRID_CELL_URL_EDITOR* urlEditor = new GRID_CELL_URL_EDITOR( aDialog );
|
||||
urlEditor->SetValidator( SCH_FIELD_VALIDATOR( aFrame->IsType( FRAME_SCH_LIB_EDITOR ),
|
||||
DATASHEET ) );
|
||||
FIELD_VALUE ) );
|
||||
m_urlAttr->SetEditor( urlEditor );
|
||||
|
||||
m_nonUrlAttr = new wxGridCellAttr;
|
||||
wxGridCellTextEditor* nonUrlEditor = new wxGridCellTextEditor();
|
||||
nonUrlEditor->SetValidator( SCH_FIELD_VALIDATOR( aFrame->IsType( FRAME_SCH_LIB_EDITOR ),
|
||||
DATASHEET ) );
|
||||
FIELD_VALUE ) );
|
||||
m_nonUrlAttr->SetEditor( nonUrlEditor );
|
||||
|
||||
m_boolAttr = new wxGridCellAttr;
|
||||
|
||||
@@ -160,7 +160,7 @@ protected:
|
||||
|
||||
wxString GetHtmlFieldRow( LIB_FIELD const & aField )
|
||||
{
|
||||
wxString name = aField.GetName();
|
||||
wxString name = aField.GetName( NATIVE_FIELD_NAME );
|
||||
wxString text = aField.GetFullText( m_unit > 0 ? m_unit : 1 );
|
||||
wxString fieldhtml = FieldFormat;
|
||||
|
||||
|
||||
@@ -538,7 +538,8 @@ void LIB_FIELD::SetText( const wxString& aText )
|
||||
|
||||
wxString LIB_FIELD::GetSelectMenuText( EDA_UNITS_T aUnits ) const
|
||||
{
|
||||
return wxString::Format( _( "Field %s \"%s\"" ), GetName(), ShortenedShownText() );
|
||||
return wxString::Format( _( "Field %s \"%s\"" ), GetName( TRANSLATE_FIELD_NAME ),
|
||||
ShortenedShownText() );
|
||||
}
|
||||
|
||||
|
||||
@@ -623,7 +624,7 @@ void LIB_FIELD::GetMsgPanelInfo( EDA_UNITS_T aUnits, MSG_PANEL_ITEMS& aList )
|
||||
aList.push_back( MSG_PANEL_ITEM( _( "Height" ), msg, BLUE ) );
|
||||
|
||||
// Display field name (ref, value ...)
|
||||
aList.push_back( MSG_PANEL_ITEM( _( "Field" ), GetName(), BROWN ) );
|
||||
aList.push_back( MSG_PANEL_ITEM( _( "Field" ), GetName( TRANSLATE_FIELD_NAME ), BROWN ) );
|
||||
|
||||
// Display field text:
|
||||
aList.push_back( MSG_PANEL_ITEM( _( "Value" ), GetShownText(), BROWN ) );
|
||||
|
||||
+10
-6
@@ -119,12 +119,16 @@ public:
|
||||
* names. The user definable fields will return FieldN where N is the ID of the field
|
||||
* when the m_name member is empty.
|
||||
*
|
||||
* @param aTranslate True to return translated field name (default). False to return
|
||||
* the english name (useful when the name is used as keyword in
|
||||
* netlists ...)
|
||||
* @return Name of the field.
|
||||
*/
|
||||
wxString GetName( bool aTranslate = true ) const;
|
||||
* @param aTranslate true to return translated field name.
|
||||
* note: has meaning mainly for mandatory fields or to return a default field name.
|
||||
* Should be used only in messages (never when trying to find a field by name)
|
||||
* false to return the english name.
|
||||
* Normal option when the name is used as keyword in netlists.
|
||||
* @return Name of the field.
|
||||
*/
|
||||
#define TRANSLATE_FIELD_NAME true
|
||||
#define NATIVE_FIELD_NAME false
|
||||
wxString GetName( bool aTranslate ) const;
|
||||
|
||||
/**
|
||||
* Set a user definable field name to \a aName.
|
||||
|
||||
+94
-1
@@ -144,39 +144,132 @@ void LIB_TEXT::Move( const wxPoint& newPosition )
|
||||
}
|
||||
|
||||
|
||||
void LIB_TEXT::NormalizeJustification( bool inverse )
|
||||
{
|
||||
wxPoint delta( 0, 0 );
|
||||
EDA_RECT bbox = GetTextBox( -1 );
|
||||
|
||||
if( GetTextAngle() == 0.0 )
|
||||
{
|
||||
if( GetHorizJustify() == GR_TEXT_HJUSTIFY_LEFT )
|
||||
delta.x = bbox.GetWidth() / 2;
|
||||
else if( GetHorizJustify() == GR_TEXT_HJUSTIFY_RIGHT )
|
||||
delta.x = - bbox.GetWidth() / 2;
|
||||
|
||||
if( GetVertJustify() == GR_TEXT_VJUSTIFY_TOP )
|
||||
delta.y = - bbox.GetHeight() / 2;
|
||||
else if( GetVertJustify() == GR_TEXT_VJUSTIFY_BOTTOM )
|
||||
delta.y = bbox.GetHeight() / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( GetHorizJustify() == GR_TEXT_HJUSTIFY_LEFT )
|
||||
delta.y = bbox.GetWidth() / 2;
|
||||
else if( GetHorizJustify() == GR_TEXT_HJUSTIFY_RIGHT )
|
||||
delta.y = - bbox.GetWidth() / 2;
|
||||
|
||||
if( GetVertJustify() == GR_TEXT_VJUSTIFY_TOP )
|
||||
delta.x = + bbox.GetHeight() / 2;
|
||||
else if( GetVertJustify() == GR_TEXT_VJUSTIFY_BOTTOM )
|
||||
delta.x = - bbox.GetHeight() / 2;
|
||||
}
|
||||
|
||||
if( inverse )
|
||||
SetTextPos( GetTextPos() - delta );
|
||||
else
|
||||
SetTextPos( GetTextPos() + delta );
|
||||
}
|
||||
|
||||
|
||||
void LIB_TEXT::MirrorHorizontal( const wxPoint& center )
|
||||
{
|
||||
NormalizeJustification( false );
|
||||
int x = GetTextPos().x;
|
||||
|
||||
x -= center.x;
|
||||
x *= -1;
|
||||
x += center.x;
|
||||
|
||||
if( GetTextAngle() == 0.0 )
|
||||
{
|
||||
if( GetHorizJustify() == GR_TEXT_HJUSTIFY_LEFT )
|
||||
SetHorizJustify( GR_TEXT_HJUSTIFY_RIGHT );
|
||||
else if( GetHorizJustify() == GR_TEXT_HJUSTIFY_RIGHT )
|
||||
SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( GetVertJustify() == GR_TEXT_VJUSTIFY_TOP )
|
||||
SetVertJustify( GR_TEXT_VJUSTIFY_BOTTOM );
|
||||
else if( GetVertJustify() == GR_TEXT_VJUSTIFY_BOTTOM )
|
||||
SetVertJustify( GR_TEXT_VJUSTIFY_TOP );
|
||||
}
|
||||
|
||||
SetTextX( x );
|
||||
NormalizeJustification( true );
|
||||
}
|
||||
|
||||
|
||||
void LIB_TEXT::MirrorVertical( const wxPoint& center )
|
||||
{
|
||||
NormalizeJustification( false );
|
||||
int y = GetTextPos().y;
|
||||
|
||||
y -= center.y;
|
||||
y *= -1;
|
||||
y += center.y;
|
||||
|
||||
if( GetTextAngle() == 0.0 )
|
||||
{
|
||||
if( GetVertJustify() == GR_TEXT_VJUSTIFY_TOP )
|
||||
SetVertJustify( GR_TEXT_VJUSTIFY_BOTTOM );
|
||||
else if( GetVertJustify() == GR_TEXT_VJUSTIFY_BOTTOM )
|
||||
SetVertJustify( GR_TEXT_VJUSTIFY_TOP );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( GetHorizJustify() == GR_TEXT_HJUSTIFY_LEFT )
|
||||
SetHorizJustify( GR_TEXT_HJUSTIFY_RIGHT );
|
||||
else if( GetHorizJustify() == GR_TEXT_HJUSTIFY_RIGHT )
|
||||
SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT );
|
||||
}
|
||||
|
||||
SetTextY( y );
|
||||
NormalizeJustification( true );
|
||||
}
|
||||
|
||||
|
||||
void LIB_TEXT::Rotate( const wxPoint& center, bool aRotateCCW )
|
||||
{
|
||||
NormalizeJustification( false );
|
||||
int rot_angle = aRotateCCW ? -900 : 900;
|
||||
|
||||
wxPoint pt = GetTextPos();
|
||||
RotatePoint( &pt, center, rot_angle );
|
||||
SetTextPos( pt );
|
||||
|
||||
SetTextAngle( GetTextAngle() != 0.0 ? 0 : 900 );
|
||||
if( GetTextAngle() == 0.0 )
|
||||
{
|
||||
SetTextAngle( 900 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// 180º of rotation is a mirror
|
||||
|
||||
if( GetHorizJustify() == GR_TEXT_HJUSTIFY_LEFT )
|
||||
SetHorizJustify( GR_TEXT_HJUSTIFY_RIGHT );
|
||||
else if( GetHorizJustify() == GR_TEXT_HJUSTIFY_RIGHT )
|
||||
SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT );
|
||||
|
||||
if( GetVertJustify() == GR_TEXT_VJUSTIFY_TOP )
|
||||
SetVertJustify( GR_TEXT_VJUSTIFY_BOTTOM );
|
||||
else if( GetVertJustify() == GR_TEXT_VJUSTIFY_BOTTOM )
|
||||
SetVertJustify( GR_TEXT_VJUSTIFY_TOP );
|
||||
|
||||
SetTextAngle( 0 );
|
||||
}
|
||||
|
||||
NormalizeJustification( true );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -122,6 +122,8 @@ public:
|
||||
|
||||
void Rotate( const wxPoint& aCenter, bool aRotateCCW = true ) override;
|
||||
|
||||
void NormalizeJustification( bool inverse );
|
||||
|
||||
void Plot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
|
||||
const TRANSFORM& aTransform ) override;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2004 Jean-Pierre Charras, jp.charras ar wanadoo.fr
|
||||
* Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
|
||||
* Copyright (C) 2004-2019 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2004-2020 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
|
||||
|
||||
@@ -373,6 +373,14 @@ void LIB_EDIT_FRAME::OnSave( wxCommandEvent& aEvent )
|
||||
}
|
||||
else
|
||||
{
|
||||
wxFileName fn = Prj().SchSymbolLibTable()->GetFullURI( libName );
|
||||
wxFileName docFileName = fn;
|
||||
docFileName.SetExt( DOC_EXT );
|
||||
|
||||
// Verify the user has write privileges before attempting to save the library file.
|
||||
if( !IsWritable( fn ) || !IsWritable( docFileName ) )
|
||||
return;
|
||||
|
||||
// Save Part
|
||||
if( m_libMgr->FlushPart( partName, libName ) )
|
||||
m_libMgr->ClearPartModified( partName, libName );
|
||||
@@ -424,8 +432,7 @@ void LIB_EDIT_FRAME::savePartAs()
|
||||
itemsToDisplay.push_back( item );
|
||||
}
|
||||
|
||||
EDA_LIST_DIALOG dlg( this, _( "Save Copy of Symbol" ), headers, itemsToDisplay, old_lib,
|
||||
nullptr, nullptr, /* sort */ false, /* show headers */ false );
|
||||
EDA_LIST_DIALOG dlg( this, _( "Save Copy of Symbol" ), headers, itemsToDisplay, old_lib );
|
||||
dlg.SetListLabel( _( "Save in library:" ) );
|
||||
dlg.SetOKLabel( _( "Save" ) );
|
||||
|
||||
@@ -727,8 +734,11 @@ bool LIB_EDIT_FRAME::saveLibrary( const wxString& aLibrary, bool aNewFile )
|
||||
fn = prj.SchSymbolLibTable()->GetFullURI( aLibrary );
|
||||
}
|
||||
|
||||
wxFileName docFileName = fn;
|
||||
docFileName.SetExt( DOC_EXT );
|
||||
|
||||
// Verify the user has write privileges before attempting to save the library file.
|
||||
if( !IsWritable( fn ) )
|
||||
if( !IsWritable( fn ) || !IsWritable( docFileName ) )
|
||||
return false;
|
||||
|
||||
ClearMsgPanel();
|
||||
@@ -737,9 +747,6 @@ bool LIB_EDIT_FRAME::saveLibrary( const wxString& aLibrary, bool aNewFile )
|
||||
if( !backupFile( fn, "bak" ) )
|
||||
return false;
|
||||
|
||||
wxFileName docFileName = fn;
|
||||
docFileName.SetExt( DOC_EXT );
|
||||
|
||||
// Copy .dcm file to .bck.
|
||||
if( !backupFile( docFileName, "bck" ) )
|
||||
return false;
|
||||
|
||||
@@ -55,7 +55,7 @@ void LIB_EDIT_FRAME::EditField( LIB_FIELD* aField )
|
||||
if( aField->GetId() == VALUE )
|
||||
caption = _( "Edit Component Name" );
|
||||
else
|
||||
caption.Printf( _( "Edit %s Field" ), GetChars( aField->GetName() ) );
|
||||
caption.Printf( _( "Edit %s Field" ), aField->GetName( TRANSLATE_FIELD_NAME ) );
|
||||
|
||||
DIALOG_LIB_EDIT_ONE_FIELD dlg( this, caption, aField );
|
||||
|
||||
|
||||
@@ -619,6 +619,8 @@ void LIB_EDIT_FRAME::OnCheckComponent( wxCommandEvent& event )
|
||||
wxDefaultPosition,
|
||||
wxSize( 750, 600 ) );
|
||||
|
||||
std::vector<wxString> messages;
|
||||
|
||||
int dup_error = 0;
|
||||
|
||||
for( unsigned ii = 1; ii < pinList.size(); ii++ )
|
||||
@@ -665,7 +667,7 @@ void LIB_EDIT_FRAME::OnCheckComponent( wxCommandEvent& event )
|
||||
|
||||
msg += wxT( ".<br>" );
|
||||
|
||||
error_display.m_htmlWindow->AppendToPage( msg );
|
||||
messages.push_back( msg );
|
||||
}
|
||||
|
||||
// Test for off grid pins:
|
||||
@@ -705,11 +707,25 @@ void LIB_EDIT_FRAME::OnCheckComponent( wxCommandEvent& event )
|
||||
|
||||
msg += wxT( ".<br>" );
|
||||
|
||||
error_display.m_htmlWindow->AppendToPage( msg );
|
||||
messages.push_back( msg );
|
||||
}
|
||||
|
||||
if( !dup_error && !offgrid_error )
|
||||
DisplayInfoMessage( this, _( "No off grid or duplicate pins were found." ) );
|
||||
else
|
||||
{
|
||||
wxColour bgcolor = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW );
|
||||
wxColour fgcolor = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT );
|
||||
wxString outmsg = wxString::Format( "<html><body bgcolor='%s' text='%s'>",
|
||||
bgcolor.GetAsString( wxC2S_HTML_SYNTAX ),
|
||||
fgcolor.GetAsString( wxC2S_HTML_SYNTAX ) );
|
||||
|
||||
for( auto& msg : messages )
|
||||
outmsg += msg;
|
||||
|
||||
outmsg += "</body></html>";
|
||||
|
||||
error_display.m_htmlWindow->SetPage( outmsg );
|
||||
error_display.ShowModal();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,6 +382,7 @@ void NETLIST_EXPORTER_PSPICE::UpdateDirectives( unsigned aCtl )
|
||||
|
||||
m_directives.clear();
|
||||
bool controlBlock = false;
|
||||
bool circuitBlock = false;
|
||||
|
||||
for( unsigned i = 0; i < sheetList.size(); i++ )
|
||||
{
|
||||
@@ -437,20 +438,9 @@ void NETLIST_EXPORTER_PSPICE::UpdateDirectives( unsigned aCtl )
|
||||
m_title = line.AfterFirst( ' ' );
|
||||
}
|
||||
|
||||
// Handle .control .. .endc blocks
|
||||
else if( lowercaseline.IsSameAs( ".control" ) && ( !controlBlock ) )
|
||||
{
|
||||
controlBlock = true;
|
||||
m_directives.push_back( line );
|
||||
}
|
||||
else if( lowercaseline.IsSameAs( ".endc" ) && controlBlock )
|
||||
{
|
||||
controlBlock = false;
|
||||
m_directives.push_back( line );
|
||||
}
|
||||
|
||||
else if( line.StartsWith( '.' ) // one-line directives
|
||||
|| controlBlock // .control .. .endc block
|
||||
|| circuitBlock // .subckt .. .ends block
|
||||
|| couplingK.Matches( line ) // K## L## L## coupling constant
|
||||
|| ( directiveStarted && line.StartsWith( '+' ) ) ) // multiline directives
|
||||
{
|
||||
@@ -459,6 +449,21 @@ void NETLIST_EXPORTER_PSPICE::UpdateDirectives( unsigned aCtl )
|
||||
m_directives.emplace_back( line + " " );
|
||||
}
|
||||
|
||||
|
||||
// Handle .control .. .endc blocks
|
||||
if( lowercaseline.IsSameAs( ".control" ) && ( !controlBlock ) )
|
||||
controlBlock = true;
|
||||
|
||||
if( lowercaseline.IsSameAs( ".endc" ) && controlBlock )
|
||||
controlBlock = false;
|
||||
|
||||
// Handle .subckt .. .ends blocks
|
||||
if( lowercaseline.StartsWith( ".subckt" ) && ( !circuitBlock ) )
|
||||
circuitBlock = true;
|
||||
|
||||
if( lowercaseline.IsSameAs( ".ends" ) && circuitBlock )
|
||||
circuitBlock = false;
|
||||
|
||||
// Mark directive as started or continued in case it is a multi-line one
|
||||
directiveStarted = line.StartsWith( '.' )
|
||||
|| ( directiveStarted && line.StartsWith( '+' ) );
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Chris Pavlina <pavlina.chris@gmail.com>
|
||||
* Copyright (C) 2015-2019 KiCad Developers, see change_log.txt for contributors.
|
||||
* Copyright (C) 2015-2020 KiCad Developers, see change_log.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
|
||||
@@ -125,11 +125,15 @@ static wxFileName GetRescueLibraryFileName()
|
||||
|
||||
RESCUE_CASE_CANDIDATE::RESCUE_CASE_CANDIDATE( const wxString& aRequestedName,
|
||||
const wxString& aNewName,
|
||||
LIB_PART* aLibCandidate )
|
||||
LIB_PART* aLibCandidate,
|
||||
int aUnit,
|
||||
int aConvert )
|
||||
{
|
||||
m_requested_name = aRequestedName;
|
||||
m_new_name = aNewName;
|
||||
m_lib_candidate = aLibCandidate;
|
||||
m_unit = aUnit;
|
||||
m_convert = aConvert;
|
||||
}
|
||||
|
||||
|
||||
@@ -170,7 +174,9 @@ void RESCUE_CASE_CANDIDATE::FindRescues( RESCUER& aRescuer,
|
||||
continue;
|
||||
|
||||
RESCUE_CASE_CANDIDATE candidate( part_name, case_insensitive_matches[0]->GetName(),
|
||||
case_insensitive_matches[0]->GetPart() );
|
||||
case_insensitive_matches[0]->GetPart(),
|
||||
each_component->GetUnit(),
|
||||
each_component->GetConvert() );
|
||||
|
||||
candidate_map[part_name] = candidate;
|
||||
}
|
||||
@@ -213,12 +219,16 @@ bool RESCUE_CASE_CANDIDATE::PerformAction( RESCUER* aRescuer )
|
||||
RESCUE_CACHE_CANDIDATE::RESCUE_CACHE_CANDIDATE( const wxString& aRequestedName,
|
||||
const wxString& aNewName,
|
||||
LIB_PART* aCacheCandidate,
|
||||
LIB_PART* aLibCandidate )
|
||||
LIB_PART* aLibCandidate,
|
||||
int aUnit,
|
||||
int aConvert )
|
||||
{
|
||||
m_requested_name = aRequestedName;
|
||||
m_new_name = aNewName;
|
||||
m_cache_candidate = aCacheCandidate;
|
||||
m_lib_candidate = aLibCandidate;
|
||||
m_unit = aUnit;
|
||||
m_convert = aConvert;
|
||||
}
|
||||
|
||||
|
||||
@@ -271,7 +281,9 @@ void RESCUE_CACHE_CANDIDATE::FindRescues( RESCUER& aRescuer,
|
||||
// Check if the symbol has already been rescued.
|
||||
wxString new_name = LIB_ID::FixIllegalChars( part_name, LIB_ID::ID_SCH );
|
||||
|
||||
RESCUE_CACHE_CANDIDATE candidate( part_name, new_name, cache_match, lib_match );
|
||||
RESCUE_CACHE_CANDIDATE candidate( part_name, new_name, cache_match, lib_match,
|
||||
each_component->GetUnit(),
|
||||
each_component->GetConvert() );
|
||||
|
||||
candidate_map[part_name] = candidate;
|
||||
}
|
||||
@@ -335,13 +347,17 @@ RESCUE_SYMBOL_LIB_TABLE_CANDIDATE::RESCUE_SYMBOL_LIB_TABLE_CANDIDATE(
|
||||
const LIB_ID& aRequestedId,
|
||||
const LIB_ID& aNewId,
|
||||
LIB_PART* aCacheCandidate,
|
||||
LIB_PART* aLibCandidate ) : RESCUE_CANDIDATE()
|
||||
LIB_PART* aLibCandidate,
|
||||
int aUnit,
|
||||
int aConvert ) : RESCUE_CANDIDATE()
|
||||
{
|
||||
m_requested_id = aRequestedId;
|
||||
m_requested_name = aRequestedId.Format();
|
||||
m_new_id = aNewId;
|
||||
m_lib_candidate = aLibCandidate;
|
||||
m_cache_candidate = aCacheCandidate;
|
||||
m_unit = aUnit;
|
||||
m_convert = aConvert;
|
||||
}
|
||||
|
||||
|
||||
@@ -406,7 +422,9 @@ void RESCUE_SYMBOL_LIB_TABLE_CANDIDATE::FindRescues(
|
||||
libNickname.Replace( " ", "-" );
|
||||
LIB_ID new_id( libNickname, new_name + "-" + part_id.GetLibNickname().wx_str() );
|
||||
|
||||
RESCUE_SYMBOL_LIB_TABLE_CANDIDATE candidate( part_id, new_id, cache_match, lib_match );
|
||||
RESCUE_SYMBOL_LIB_TABLE_CANDIDATE candidate( part_id, new_id, cache_match, lib_match,
|
||||
each_component->GetUnit(),
|
||||
each_component->GetConvert() );
|
||||
|
||||
candidate_map[part_id] = candidate;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Chris Pavlina <pavlina.chris@gmail.com>
|
||||
* Copyright (C) 2015-2019 KiCad Developers, see change_log.txt for contributors.
|
||||
* Copyright (C) 2015-2020 KiCad Developers, see change_log.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
|
||||
@@ -69,6 +69,8 @@ protected:
|
||||
wxString m_requested_name;
|
||||
wxString m_new_name;
|
||||
LIB_PART* m_lib_candidate;
|
||||
int m_unit;
|
||||
int m_convert;
|
||||
|
||||
public:
|
||||
virtual ~RESCUE_CANDIDATE() {}
|
||||
@@ -95,6 +97,10 @@ public:
|
||||
*/
|
||||
virtual LIB_PART* GetLibCandidate() const { return m_lib_candidate; }
|
||||
|
||||
int GetUnit() const { return m_unit; }
|
||||
|
||||
int GetConvert() const { return m_convert; }
|
||||
|
||||
/**
|
||||
* Get a description of the action proposed, for displaying in the UI.
|
||||
*/
|
||||
@@ -125,9 +131,11 @@ public:
|
||||
* @param aRequestedName - the name the schematic asks for
|
||||
* @param aNewName - the name we want to change it to
|
||||
* @param aLibCandidate - the part that will give us
|
||||
* @param aUnit The unit of the rescued symbol.
|
||||
* @param aConvert The body style of the rescued symbol.
|
||||
*/
|
||||
RESCUE_CASE_CANDIDATE( const wxString& aRequestedName, const wxString& aNewName,
|
||||
LIB_PART* aLibCandidate );
|
||||
LIB_PART* aLibCandidate, int aUnit = 0, int aConvert = 0 );
|
||||
|
||||
RESCUE_CASE_CANDIDATE() { m_lib_candidate = NULL; }
|
||||
|
||||
@@ -156,9 +164,12 @@ public:
|
||||
* @param aNewName - the name we want to change it to
|
||||
* @param aCacheCandidate - the part from the cache
|
||||
* @param aLibCandidate - the part that would be loaded from the library
|
||||
* @param aUnit The unit of the rescued symbol.
|
||||
* @param aConvert The body style of the rescued symbol.
|
||||
*/
|
||||
RESCUE_CACHE_CANDIDATE( const wxString& aRequestedName, const wxString& aNewName,
|
||||
LIB_PART* aCacheCandidate, LIB_PART* aLibCandidate );
|
||||
LIB_PART* aCacheCandidate, LIB_PART* aLibCandidate,
|
||||
int aUnit = 0, int aConvert = 0 );
|
||||
|
||||
RESCUE_CACHE_CANDIDATE();
|
||||
|
||||
@@ -191,9 +202,12 @@ public:
|
||||
* @param aNewName - the name we want to change it to
|
||||
* @param aCacheCandidate - the part from the cache
|
||||
* @param aLibCandidate - the part that would be loaded from the library
|
||||
* @param aUnit The unit of the rescued symbol.
|
||||
* @param aConvert The body style of the rescued symbol.
|
||||
*/
|
||||
RESCUE_SYMBOL_LIB_TABLE_CANDIDATE( const LIB_ID& aRequestedId, const LIB_ID& aNewId,
|
||||
LIB_PART* aCacheCandidate, LIB_PART* aLibCandidate);
|
||||
LIB_PART* aCacheCandidate, LIB_PART* aLibCandidate,
|
||||
int aUnit = 0, int aConvert = 0 );
|
||||
|
||||
RESCUE_SYMBOL_LIB_TABLE_CANDIDATE();
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 2015-2017 KiCad Developers, see change_log.txt for contributors.
|
||||
* Copyright (C) 2015-2020 KiCad Developers, see change_log.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
|
||||
@@ -45,17 +45,22 @@
|
||||
LIB_ALIAS* SchGetLibAlias( const LIB_ID& aLibId, SYMBOL_LIB_TABLE* aLibTable, PART_LIB* aCacheLib,
|
||||
wxWindow* aParent, bool aShowErrorMsg )
|
||||
{
|
||||
// wxCHECK_MSG( aLibId.IsValid(), NULL, "LIB_ID is not valid." );
|
||||
wxCHECK_MSG( aLibTable, NULL, "Invalid symbol library table." );
|
||||
wxCHECK_MSG( aLibTable, nullptr, "Invalid symbol library table." );
|
||||
|
||||
LIB_ALIAS* alias = NULL;
|
||||
LIB_ALIAS* symbol = nullptr;
|
||||
|
||||
try
|
||||
{
|
||||
alias = aLibTable->LoadSymbol( aLibId );
|
||||
symbol = aLibTable->LoadSymbol( aLibId );
|
||||
|
||||
if( !alias && aCacheLib )
|
||||
alias = aCacheLib->FindAlias( aLibId );
|
||||
if( !symbol && aCacheLib )
|
||||
{
|
||||
wxCHECK_MSG( aCacheLib->IsCache(), nullptr, "Invalid cache library." );
|
||||
|
||||
wxString cacheName = aLibId.GetLibNickname().wx_str();
|
||||
cacheName += "_" + aLibId.GetLibItemName();
|
||||
symbol = aCacheLib->FindAlias( cacheName );
|
||||
}
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
@@ -69,7 +74,7 @@ LIB_ALIAS* SchGetLibAlias( const LIB_ID& aLibId, SYMBOL_LIB_TABLE* aLibTable, PA
|
||||
}
|
||||
}
|
||||
|
||||
return alias;
|
||||
return symbol;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -837,7 +837,7 @@ void SCH_COMPONENT::SetTimeStamp( timestamp_t aNewTimeStamp )
|
||||
}
|
||||
|
||||
|
||||
int SCH_COMPONENT::GetUnitSelection( SCH_SHEET_PATH* aSheet )
|
||||
int SCH_COMPONENT::GetUnitSelection( const SCH_SHEET_PATH* aSheet )
|
||||
{
|
||||
wxString path = GetPath( aSheet );
|
||||
wxString h_path, h_multi;
|
||||
@@ -988,7 +988,7 @@ void SCH_COMPONENT::UpdateFields( bool aResetStyle, bool aResetRef )
|
||||
{
|
||||
// Can no longer insert an empty name, since names are now keys. The
|
||||
// field index is not used beyond the first MANDATORY_FIELDS
|
||||
if( field.GetName().IsEmpty() )
|
||||
if( field.GetName( NATIVE_FIELD_NAME ).IsEmpty() )
|
||||
continue;
|
||||
|
||||
// See if field already exists (mandatory fields always exist).
|
||||
@@ -1005,11 +1005,12 @@ void SCH_COMPONENT::UpdateFields( bool aResetStyle, bool aResetRef )
|
||||
if( (unsigned) idx < MANDATORY_FIELDS )
|
||||
schField = GetField( idx );
|
||||
else
|
||||
schField = FindField( field.GetName() );
|
||||
schField = FindField( field.GetName( NATIVE_FIELD_NAME ) );
|
||||
|
||||
if( !schField )
|
||||
{
|
||||
SCH_FIELD newField( wxPoint( 0, 0 ), GetFieldCount(), this, field.GetName() );
|
||||
SCH_FIELD newField( wxPoint( 0, 0 ), GetFieldCount(), this,
|
||||
field.GetName( NATIVE_FIELD_NAME ) );
|
||||
schField = AddField( newField );
|
||||
}
|
||||
|
||||
|
||||
@@ -546,7 +546,7 @@ public:
|
||||
int aMulti );
|
||||
|
||||
// returns the unit selection, for the given sheet path.
|
||||
int GetUnitSelection( SCH_SHEET_PATH* aSheet );
|
||||
int GetUnitSelection( const SCH_SHEET_PATH* aSheet );
|
||||
|
||||
// Set the unit selection, for the given sheet path.
|
||||
void SetUnitSelection( SCH_SHEET_PATH* aSheet, int aUnitSelection );
|
||||
|
||||
@@ -23,10 +23,11 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <functional>
|
||||
#include <view/wx_view_controls.h>
|
||||
#include <worksheet_viewitem.h>
|
||||
|
||||
#include <confirm.h>
|
||||
#include <gal/graphics_abstraction_layer.h>
|
||||
#include <sch_draw_panel.h>
|
||||
#include <sch_view.h>
|
||||
@@ -34,8 +35,6 @@
|
||||
#include <sch_edit_frame.h>
|
||||
#include <preview_items/selection_area.h>
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <sch_sheet.h>
|
||||
#include <pgm_base.h>
|
||||
|
||||
@@ -174,7 +173,19 @@ void SCH_DRAW_PANEL::DisplaySheet( const SCH_SCREEN *aScreen )
|
||||
|
||||
void SCH_DRAW_PANEL::OnShow()
|
||||
{
|
||||
//m_view->RecacheAllItems();
|
||||
SCH_BASE_FRAME* frame = dynamic_cast<SCH_BASE_FRAME*>( GetParent() );
|
||||
|
||||
try
|
||||
{
|
||||
// Check if the current rendering backend can be properly initialized
|
||||
m_view->UpdateItems();
|
||||
}
|
||||
catch( const std::runtime_error& e )
|
||||
{
|
||||
// Fallback to software renderer
|
||||
DisplayInfoMessage( frame, e.what() );
|
||||
SwitchBackend( GAL_TYPE_CAIRO );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -387,6 +387,7 @@ SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ):
|
||||
m_undoItem = NULL;
|
||||
m_hasAutoSave = true;
|
||||
m_showIllegalSymbolLibDialog = true;
|
||||
m_showSheetFileNameCaseSensitivityDlg = true;
|
||||
m_FrameSize = ConvertDialogToPixels( wxSize( 500, 350 ) ); // default in case of no prefs
|
||||
m_AboutTitle = "Eeschema";
|
||||
|
||||
|
||||
@@ -151,6 +151,7 @@ private:
|
||||
bool m_autoplaceAlign; ///< align autoplaced fields to the grid
|
||||
bool m_footprintPreview; ///< whether to show footprint previews
|
||||
bool m_showIllegalSymbolLibDialog;
|
||||
bool m_showSheetFileNameCaseSensitivityDlg;
|
||||
|
||||
/// An index to the last find item in the found items list #m_foundItems.
|
||||
int m_foundItemIndex;
|
||||
@@ -985,6 +986,19 @@ private:
|
||||
*/
|
||||
bool importFile( const wxString& aFileName, int aFileType );
|
||||
|
||||
/**
|
||||
* Check \a aSchematicFileName for a potential file name case sensitivity clashes.
|
||||
*
|
||||
* On platforms where file names are case sensitive, it is possible to schematic sheet
|
||||
* file names that would cause issues on platforms where file name are case insensitive.
|
||||
* File names foo.sch and Foo.sch are unique files on Linux and MacOS but on Windows
|
||||
* this would result in a broken schematic.
|
||||
*
|
||||
* @param aSchematicFileName is the absolute path and file name of the file to test.
|
||||
* @return true if the user accepts the potential file name clase risk.
|
||||
*/
|
||||
bool allowCaseSensitiveFileNameClashes( const wxString& aSchematicFileName );
|
||||
|
||||
public:
|
||||
/**
|
||||
* Command event handler to change a text type to another one.
|
||||
|
||||
@@ -1619,6 +1619,33 @@ bool SCH_SCREENS::HasSchematic( const wxString& aSchematicFileName )
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SCREENS::CanCauseCaseSensitivityIssue( const wxString& aSchematicFileName ) const
|
||||
{
|
||||
wxString lhsLower;
|
||||
wxString rhsLower;
|
||||
wxFileName lhs;
|
||||
wxFileName rhs = aSchematicFileName;
|
||||
|
||||
wxCHECK( rhs.IsAbsolute(), false );
|
||||
|
||||
for( const SCH_SCREEN* screen : m_screens )
|
||||
{
|
||||
lhs = screen->GetFileName();
|
||||
|
||||
if( lhs.GetPath() != rhs.GetPath() )
|
||||
continue;
|
||||
|
||||
lhsLower = lhs.GetFullName().Lower();
|
||||
rhsLower = rhs.GetFullName().Lower();
|
||||
|
||||
if( lhsLower == rhsLower && lhs.GetFullName() != rhs.GetFullName() )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void SCH_SCREENS::BuildClientSheetPathList()
|
||||
{
|
||||
SCH_SHEET_LIST sheetList( g_RootSheet );
|
||||
|
||||
@@ -639,6 +639,19 @@ public:
|
||||
void BuildClientSheetPathList();
|
||||
|
||||
|
||||
/**
|
||||
* Check \a aSchematicFileName for a potential file name case sensitivity issue.
|
||||
*
|
||||
* On platforms where file names are case sensitive, it is possible to schematic sheet
|
||||
* file names that would cause issues on platforms where file name are case insensitive.
|
||||
* File names foo.sch and Foo.sch are unique files on Linux and MacOS but on Windows
|
||||
* this would result in a broken schematic.
|
||||
*
|
||||
* @param aSchematicFileName is the absolute path and file name of the file to test.
|
||||
* @return true if \a aSchematicFileName would cause an issue.
|
||||
*/
|
||||
bool CanCauseCaseSensitivityIssue( const wxString& aSchematicFileName ) const;
|
||||
|
||||
private:
|
||||
void addScreenToList( SCH_SCREEN* aScreen );
|
||||
void buildScreenList( SCH_SHEET* aSheet);
|
||||
|
||||
+21
-3
@@ -578,18 +578,36 @@ int SCH_SHEET::ComponentCount()
|
||||
|
||||
bool SCH_SHEET::SearchHierarchy( const wxString& aFilename, SCH_SCREEN** aScreen )
|
||||
{
|
||||
SCH_SHEET* sheet = nullptr;
|
||||
SCH_SCREEN* screen = nullptr;
|
||||
|
||||
if( m_screen )
|
||||
{
|
||||
// Only check the root sheet once and don't recurse.
|
||||
if( !GetParent() )
|
||||
{
|
||||
sheet = this;
|
||||
screen = m_screen;
|
||||
|
||||
if( screen && screen->GetFileName().Cmp( aFilename ) == 0 )
|
||||
{
|
||||
*aScreen = screen;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
EDA_ITEM* item = m_screen->GetDrawItems();
|
||||
|
||||
while( item )
|
||||
{
|
||||
if( item->Type() == SCH_SHEET_T )
|
||||
{
|
||||
SCH_SHEET* sheet = (SCH_SHEET*) item;
|
||||
// Must use the screen's path (which is always absolute) rather than the
|
||||
// sheet's (which could be relative).
|
||||
sheet = static_cast< SCH_SHEET* >( item );
|
||||
screen = sheet->m_screen;
|
||||
|
||||
if( sheet->m_screen
|
||||
&& sheet->m_screen->GetFileName().CmpNoCase( aFilename ) == 0 )
|
||||
if( screen && screen->GetFileName().Cmp( aFilename ) == 0 )
|
||||
{
|
||||
*aScreen = sheet->m_screen;
|
||||
return true;
|
||||
|
||||
@@ -455,6 +455,8 @@ void SCH_SHEET_LIST::BuildSheetList( SCH_SHEET* aSheet )
|
||||
{
|
||||
wxCHECK_RET( aSheet != NULL, wxT( "Cannot build sheet list from undefined sheet." ) );
|
||||
|
||||
std::vector<SCH_SHEET*> badSheets;
|
||||
|
||||
if( aSheet == g_RootSheet )
|
||||
m_isRootSheet = true;
|
||||
|
||||
@@ -477,11 +479,23 @@ void SCH_SHEET_LIST::BuildSheetList( SCH_SHEET* aSheet )
|
||||
if( item->Type() == SCH_SHEET_T )
|
||||
{
|
||||
SCH_SHEET* sheet = (SCH_SHEET*) item;
|
||||
BuildSheetList( sheet );
|
||||
|
||||
if( !m_currentSheetPath.TestForRecursion(
|
||||
sheet->GetFileName(), aSheet->GetFileName() ) )
|
||||
BuildSheetList( sheet );
|
||||
else
|
||||
badSheets.push_back( sheet );
|
||||
}
|
||||
|
||||
item = item->Next();
|
||||
}
|
||||
|
||||
|
||||
for( auto sheet : badSheets )
|
||||
{
|
||||
aSheet->GetScreen()->Remove( sheet );
|
||||
aSheet->GetScreen()->SetModify();
|
||||
}
|
||||
}
|
||||
|
||||
m_currentSheetPath.pop_back();
|
||||
|
||||
@@ -82,12 +82,13 @@ bool SCH_FIELD_VALIDATOR::Validate( wxWindow *aParent )
|
||||
|
||||
switch( m_fieldId )
|
||||
{
|
||||
case FIELD_NAME: fieldName = _( "field name" ); break;
|
||||
case REFERENCE: fieldName = _( "reference field" ); break;
|
||||
case VALUE: fieldName = _( "value field" ); break;
|
||||
case FOOTPRINT: fieldName = _( "footprint field" ); break;
|
||||
case DATASHEET: fieldName = _( "datasheet field" ); break;
|
||||
default: fieldName = _( "user defined field" ); break;
|
||||
case FIELD_NAME: fieldName = _( "field name" ); break;
|
||||
case FIELD_VALUE: fieldName = _( "field value" ); break;
|
||||
case REFERENCE: fieldName = _( "reference field" ); break;
|
||||
case VALUE: fieldName = _( "value field" ); break;
|
||||
case FOOTPRINT: fieldName = _( "footprint field" ); break;
|
||||
case DATASHEET: fieldName = _( "datasheet field" ); break;
|
||||
default: fieldName = _( "user defined field" ); break;
|
||||
};
|
||||
|
||||
wxString msg;
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
|
||||
#define FIELD_NAME -1
|
||||
#define FIELD_VALUE -2
|
||||
|
||||
|
||||
/**
|
||||
|
||||
+43
-2
@@ -574,6 +574,9 @@ bool SCH_EDIT_FRAME::EditSheet( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHierarchy,
|
||||
|
||||
if( aSheet->GetScreen() == NULL ) // New sheet.
|
||||
{
|
||||
if( !allowCaseSensitiveFileNameClashes( newFilename ) )
|
||||
return false;
|
||||
|
||||
if( useScreen || loadFromFile ) // Load from existing file.
|
||||
{
|
||||
clearAnnotation = true;
|
||||
@@ -605,6 +608,9 @@ bool SCH_EDIT_FRAME::EditSheet( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHierarchy,
|
||||
|
||||
isExistingSheet = true;
|
||||
|
||||
if( !allowCaseSensitiveFileNameClashes( newFilename ) )
|
||||
return false;
|
||||
|
||||
// Changing the filename of a sheet can modify the full hierarchy structure
|
||||
// and can be not always undoable.
|
||||
// So prepare messages for user notifications:
|
||||
@@ -627,7 +633,7 @@ bool SCH_EDIT_FRAME::EditSheet( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHierarchy,
|
||||
wxString oldFilename = aSheet->GetScreen()->GetFileName();
|
||||
oldFilename.Replace( wxT( "\\" ), wxT( "/" ) );
|
||||
|
||||
if( newFilename.CmpNoCase( oldFilename ) != 0 )
|
||||
if( newFilename.Cmp( oldFilename ) != 0 )
|
||||
{
|
||||
// Sheet file name changes cannot be undone.
|
||||
isUndoable = false;
|
||||
@@ -731,7 +737,8 @@ bool SCH_EDIT_FRAME::EditSheet( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHierarchy,
|
||||
aHierarchy->LastScreen()->Remove( aSheet );
|
||||
}
|
||||
|
||||
if( !LoadSheetFromFile( aSheet, aHierarchy, newFilename ) )
|
||||
if( !LoadSheetFromFile( aSheet, aHierarchy, newFilename )
|
||||
|| checkSheetForRecursion( aSheet, aHierarchy ) )
|
||||
{
|
||||
if( restoreSheet )
|
||||
aHierarchy->LastScreen()->Append( aSheet );
|
||||
@@ -974,3 +981,37 @@ void SCH_EDIT_FRAME::MirrorSheet( SCH_SHEET* aSheet, bool aFromXaxis )
|
||||
GetCanvas()->GetView()->Update( aSheet );
|
||||
OnModify();
|
||||
}
|
||||
|
||||
|
||||
bool SCH_EDIT_FRAME::allowCaseSensitiveFileNameClashes( const wxString& aSchematicFileName )
|
||||
{
|
||||
wxString msg;
|
||||
SCH_SCREENS screens;
|
||||
wxFileName fn = aSchematicFileName;
|
||||
|
||||
wxCHECK( fn.IsAbsolute(), false );
|
||||
|
||||
if( m_showSheetFileNameCaseSensitivityDlg
|
||||
&& screens.CanCauseCaseSensitivityIssue( aSchematicFileName ) )
|
||||
{
|
||||
msg.Printf( _( "The file name \"%s\" can cause issues with an existing file name\n"
|
||||
"already defined in the schematic on systems that support case\n"
|
||||
"insensitive file names. This will cause issues if you copy this\n"
|
||||
"project to an operating system that supports case insensitive file\n"
|
||||
"names.\n\nDo you wish to continue?" ),
|
||||
fn.GetName() );
|
||||
|
||||
wxRichMessageDialog dlg( this, msg, _( "Warning" ),
|
||||
wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION );
|
||||
dlg.ShowCheckBox( _( "Do not show this message again." ) );
|
||||
dlg.SetYesNoLabels( wxMessageDialog::ButtonLabel( _( "Create New Sheet" ) ),
|
||||
wxMessageDialog::ButtonLabel( _( "Discard New Sheet" ) ) );
|
||||
|
||||
if( dlg.ShowModal() == wxID_NO )
|
||||
return false;
|
||||
|
||||
m_showSheetFileNameCaseSensitivityDlg = !dlg.IsCheckBoxChecked();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -621,6 +621,12 @@ void LIB_VIEW_FRAME::ClickOnLibList( wxCommandEvent& event )
|
||||
m_selection_changed = true;
|
||||
|
||||
SetSelectedLibrary( m_libList->GetString( ii ) );
|
||||
|
||||
// The m_libList has now the focus, in order to be able to use arrow keys
|
||||
// to navigate inside the list.
|
||||
// the gal canvas must not steal the focus to allow navigation
|
||||
GetGalCanvas()->SetStealsFocus( false );
|
||||
m_libList->SetFocus();
|
||||
}
|
||||
|
||||
|
||||
@@ -651,6 +657,12 @@ void LIB_VIEW_FRAME::ClickOnCmpList( wxCommandEvent& event )
|
||||
m_selection_changed = true;
|
||||
|
||||
SetSelectedComponent( m_cmpList->GetString( ii ) );
|
||||
|
||||
// The m_cmpList has now the focus, in order to be able to use arrow keys
|
||||
// to navigate inside the list.
|
||||
// the gal canvas must not steal the focus to allow navigation
|
||||
GetGalCanvas()->SetStealsFocus( false );
|
||||
m_cmpList->SetFocus();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2018 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2018-2020 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
|
||||
@@ -57,7 +57,8 @@ SYMBOL_PREVIEW_WIDGET::SYMBOL_PREVIEW_WIDGET( wxWindow* aParent, KIWAY& aKiway,
|
||||
|
||||
// Do not display the grid: the look is not good for a small canvas area.
|
||||
// But mainly, due to some strange bug I (JPC) was unable to fix, the grid creates
|
||||
// strange artifacts on Windows when eeschema is run from Kicad manager (but not in stand alone...).
|
||||
// strange artifacts on Windows when eeschema is run from Kicad manager (but not in
|
||||
// stand alone...).
|
||||
m_preview->GetGAL()->SetGridVisibility( false );
|
||||
|
||||
// Early initialization of the canvas background color,
|
||||
@@ -141,7 +142,7 @@ void SYMBOL_PREVIEW_WIDGET::fitOnDrawArea()
|
||||
}
|
||||
|
||||
|
||||
void SYMBOL_PREVIEW_WIDGET::DisplaySymbol( const LIB_ID& aSymbolID, int aUnit )
|
||||
void SYMBOL_PREVIEW_WIDGET::DisplaySymbol( const LIB_ID& aSymbolID, int aUnit, int aConvert )
|
||||
{
|
||||
KIGFX::VIEW* view = m_preview->GetView();
|
||||
auto settings = static_cast<KIGFX::SCH_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
|
||||
@@ -172,19 +173,16 @@ void SYMBOL_PREVIEW_WIDGET::DisplaySymbol( const LIB_ID& aSymbolID, int aUnit )
|
||||
|
||||
// If unit isn't specified for a multi-unit part, pick the first. (Otherwise we'll
|
||||
// draw all of them.)
|
||||
if( part->IsMulti() && aUnit == 0 )
|
||||
aUnit = 1;
|
||||
|
||||
settings->m_ShowUnit = aUnit;
|
||||
settings->m_ShowUnit = ( part->IsMulti() && aUnit == 0 ) ? 1 : aUnit;
|
||||
|
||||
// For symbols having a De Morgan body style, use the first style
|
||||
settings->m_ShowConvert = part->HasConversion() ? 1 : 0;
|
||||
settings->m_ShowConvert =
|
||||
( part->HasConversion() && aConvert == 0 ) ? 1 : aConvert;
|
||||
|
||||
m_previewItem = new LIB_ALIAS( *alias, part );
|
||||
view->Add( m_previewItem );
|
||||
|
||||
// Get the symbole size, in internal units
|
||||
m_itemBBox = part->GetUnitBoundingBox( aUnit, 0 );
|
||||
m_itemBBox = part->GetUnitBoundingBox( settings->m_ShowUnit, settings->m_ShowConvert );
|
||||
|
||||
if( !m_preview->IsShown() )
|
||||
{
|
||||
@@ -201,7 +199,7 @@ void SYMBOL_PREVIEW_WIDGET::DisplaySymbol( const LIB_ID& aSymbolID, int aUnit )
|
||||
}
|
||||
|
||||
|
||||
void SYMBOL_PREVIEW_WIDGET::DisplayPart( LIB_PART* aPart, int aUnit )
|
||||
void SYMBOL_PREVIEW_WIDGET::DisplayPart( LIB_PART* aPart, int aUnit, int aConvert )
|
||||
{
|
||||
KIGFX::VIEW* view = m_preview->GetView();
|
||||
|
||||
@@ -214,19 +212,21 @@ void SYMBOL_PREVIEW_WIDGET::DisplayPart( LIB_PART* aPart, int aUnit )
|
||||
|
||||
if( aPart )
|
||||
{
|
||||
// If unit isn't specified for a multi-unit part, pick the first. (Otherwise we'll
|
||||
// draw all of them.)
|
||||
if( aPart->IsMulti() && aUnit == 0 )
|
||||
aUnit = 1;
|
||||
m_previewItem = new LIB_PART( *aPart );
|
||||
|
||||
// For symbols having a De Morgan body style, use the first style
|
||||
auto settings = static_cast<KIGFX::SCH_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
|
||||
settings->m_ShowConvert = aPart->HasConversion() ? 1 : 0;
|
||||
m_previewItem = new LIB_PART( *aPart );
|
||||
// If unit isn't specified for a multi-unit part, pick the first. (Otherwise we'll
|
||||
// draw all of them.)
|
||||
settings->m_ShowUnit = ( aPart->IsMulti() && aUnit == 0 ) ? 1 : aUnit;
|
||||
|
||||
settings->m_ShowConvert =
|
||||
( aPart->HasConversion() && aConvert == 0 ) ? 1 : aConvert;
|
||||
|
||||
view->Add( m_previewItem );
|
||||
|
||||
// Get the symbole size, in internal units
|
||||
m_itemBBox = aPart->GetUnitBoundingBox( aUnit, 0 );
|
||||
m_itemBBox = aPart->GetUnitBoundingBox( settings->m_ShowUnit, settings->m_ShowConvert );
|
||||
|
||||
// Calculate the draw scale to fit the drawing area
|
||||
fitOnDrawArea();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2018 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2018-2020 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
|
||||
@@ -58,9 +58,9 @@ public:
|
||||
/**
|
||||
* Set the currently displayed symbol.
|
||||
*/
|
||||
void DisplaySymbol( const LIB_ID& aSymbolID, int aUnit );
|
||||
void DisplaySymbol( const LIB_ID& aSymbolID, int aUnit, int aConvert = 0 );
|
||||
|
||||
void DisplayPart( LIB_PART* aPart, int aUnit );
|
||||
void DisplayPart( LIB_PART* aPart, int aUnit, int aConvert = 0 );
|
||||
|
||||
private:
|
||||
void onSize( wxSizeEvent& aEvent );
|
||||
|
||||
@@ -168,11 +168,8 @@ add_dependencies( gerbview gerbview_kiface )
|
||||
|
||||
# these 2 binaries are a matched set, keep them together
|
||||
if( APPLE )
|
||||
include( ${CMAKE_MODULE_PATH}/KiCadVersion.cmake )
|
||||
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist @ONLY )
|
||||
|
||||
set_target_properties( gerbview PROPERTIES
|
||||
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist
|
||||
MACOSX_BUNDLE_INFO_PLIST ${PROJECT_BINARY_DIR}/gerbview/Info.plist
|
||||
)
|
||||
|
||||
# puts binaries into the *.app bundle while linking
|
||||
|
||||
+5
-8
@@ -226,14 +226,14 @@ void D_CODE::DrawFlashedShape( GERBER_DRAW_ITEM* aParent,
|
||||
int delta = (m_Size.x - m_Size.y) / 2;
|
||||
start.x -= delta;
|
||||
end.x += delta;
|
||||
radius = m_Size.y;
|
||||
radius = m_Size.y; // Width in fact
|
||||
}
|
||||
else // horizontal oval
|
||||
else // vertical oval
|
||||
{
|
||||
int delta = (m_Size.y - m_Size.x) / 2;
|
||||
start.y -= delta;
|
||||
end.y += delta;
|
||||
radius = m_Size.x;
|
||||
radius = m_Size.x; // Width in fact
|
||||
}
|
||||
|
||||
start = aParent->GetABPosition( start );
|
||||
@@ -374,13 +374,10 @@ void D_CODE::ConvertShapeToPolygon()
|
||||
m_Polygon.Append( VECTOR2I( currpos ) );
|
||||
}
|
||||
|
||||
m_Polygon.Append( VECTOR2I( initialpos ) ); // close outline
|
||||
m_Polygon.Append( VECTOR2I( initialpos ) ); // close outline
|
||||
|
||||
if( m_Size.y > m_Size.x ) // vertical oval, rotate polygon.
|
||||
{
|
||||
for( auto it = m_Polygon.Iterate( 0 ); it; ++it )
|
||||
it->Rotate( -M_PI / 2 );
|
||||
}
|
||||
m_Polygon.Rotate( -M_PI / 2, VECTOR2I( 0, 0 ) );
|
||||
|
||||
addHoleToPolygon( &m_Polygon, m_DrillShape, m_Drill, initialpos );
|
||||
}
|
||||
|
||||
@@ -185,17 +185,17 @@ void GERBVIEW_FRAME::ExportDataInPcbnewFormat( wxCommandEvent& event )
|
||||
return;
|
||||
}
|
||||
|
||||
wxString fileName;
|
||||
wxString fileDialogName( wxT( "noname." ) + KiCadPcbFileExtension );
|
||||
wxString path = m_mruPath;
|
||||
|
||||
wxFileDialog filedlg( this, _( "Board File Name" ),
|
||||
path, fileName, PcbFileWildcard(),
|
||||
path, fileDialogName, PcbFileWildcard(),
|
||||
wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
|
||||
|
||||
if( filedlg.ShowModal() == wxID_CANCEL )
|
||||
return;
|
||||
|
||||
fileName = filedlg.GetPath();
|
||||
wxFileName fileName = filedlg.GetPath();
|
||||
|
||||
/* Install a dialog frame to choose the mapping
|
||||
* between gerber layers and Pcbnew layers
|
||||
@@ -207,9 +207,13 @@ void GERBVIEW_FRAME::ExportDataInPcbnewFormat( wxCommandEvent& event )
|
||||
if( ok != wxID_OK )
|
||||
return;
|
||||
|
||||
m_mruPath = wxFileName( fileName ).GetPath();
|
||||
// If no extension was entered, then force the extension to be a KiCad PCB file
|
||||
if( !fileName.HasExt() )
|
||||
fileName.SetExt( KiCadPcbFileExtension );
|
||||
|
||||
GBR_TO_PCB_EXPORTER gbr_exporter( this, fileName );
|
||||
m_mruPath = fileName.GetPath();
|
||||
|
||||
GBR_TO_PCB_EXPORTER gbr_exporter( this, fileName.GetFullPath() );
|
||||
|
||||
gbr_exporter.ExportPcb( layerdlg->GetLayersLookUpTable(), layerdlg->GetCopperLayersCount() );
|
||||
}
|
||||
@@ -536,11 +540,21 @@ void GBR_TO_PCB_EXPORTER::writePcbLineItem( bool aIsArc, wxPoint& aStart, wxPoin
|
||||
|
||||
void GBR_TO_PCB_EXPORTER::writePcbPolygonItem( GERBER_DRAW_ITEM* aGbrItem, LAYER_NUM aLayer )
|
||||
{
|
||||
fprintf( m_fp, "(gr_poly (pts " );
|
||||
|
||||
SHAPE_POLY_SET polys = aGbrItem->m_Polygon;
|
||||
|
||||
// Cleanup the polygon
|
||||
polys.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
||||
|
||||
// Ensure the polygon is valid:
|
||||
if( polys.OutlineCount() == 0 )
|
||||
return;
|
||||
|
||||
polys.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
||||
|
||||
SHAPE_LINE_CHAIN& poly = polys.Outline( 0 );
|
||||
|
||||
fprintf( m_fp, "(gr_poly (pts " );
|
||||
|
||||
#define MAX_COORD_CNT 4
|
||||
int jj = MAX_COORD_CNT;
|
||||
int cnt_max = poly.PointCount() -1;
|
||||
|
||||
@@ -339,7 +339,7 @@ const EDA_RECT GERBER_DRAW_ITEM::GetBoundingBox() const
|
||||
case GBR_SPOT_OVAL:
|
||||
{
|
||||
if( code )
|
||||
bbox.Inflate( code->m_Size.x, code->m_Size.y );
|
||||
bbox.Inflate( code->m_Size.x /2, code->m_Size.y / 2 );
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -828,6 +828,37 @@ bool GERBER_DRAW_ITEM::HitTest( const wxPoint& aRefPos ) const
|
||||
case GBR_SPOT_RECT:
|
||||
return GetBoundingBox().Contains( aRefPos );
|
||||
|
||||
case GBR_SPOT_OVAL:
|
||||
{
|
||||
EDA_RECT bbox = GetBoundingBox();
|
||||
|
||||
if( ! bbox.Contains( aRefPos ) )
|
||||
return false;
|
||||
|
||||
// This is similar to a segment with thickness = min( m_Size.x, m_Size.y )
|
||||
int radius = std::min( m_Size.x, m_Size.y )/2;
|
||||
wxPoint start, end;
|
||||
if( m_Size.x > m_Size.y ) // Horizontal oval
|
||||
{
|
||||
int len = m_Size.y - m_Size.x;
|
||||
start.x = -len/2;
|
||||
end.x = len/2;
|
||||
}
|
||||
else // Vertical oval
|
||||
{
|
||||
int len = m_Size.x - m_Size.y;
|
||||
start.y = -len/2;
|
||||
end.y = len/2;
|
||||
}
|
||||
start += bbox.Centre();
|
||||
end += bbox.Centre();
|
||||
|
||||
if( radius < MIN_HIT_TEST_RADIUS )
|
||||
radius = MIN_HIT_TEST_RADIUS;
|
||||
|
||||
return TestSegmentHit( aRefPos, start, end, radius );
|
||||
}
|
||||
|
||||
case GBR_ARC:
|
||||
{
|
||||
double radius = GetLineLength( m_Start, m_ArcCentre );
|
||||
|
||||
@@ -211,8 +211,8 @@ void GERBER_FILE_IMAGE::ResetDefaultValues()
|
||||
m_FmtLen.x = m_FmtLen.y = 3 + 4; // Initialize default format len = 3+4
|
||||
|
||||
m_Iterpolation = GERB_INTERPOL_LINEAR_1X; // Linear, 90 arc, Circ.
|
||||
m_360Arc_enbl = false; // 360 deg circular
|
||||
// interpolation disable
|
||||
m_360Arc_enbl = false; // 360 deg circular interpolation disable
|
||||
m_AsArcG74G75Cmd = false; // false until a G74 or G75 command is found
|
||||
m_Current_Tool = 0; // Current Dcode selected
|
||||
m_CommandState = 0; // State of the current command
|
||||
m_CurrentPos.x = m_CurrentPos.y = 0; // current specified coord
|
||||
@@ -385,9 +385,10 @@ void GERBER_FILE_IMAGE::RemoveAttribute( X2_ATTRIBUTE& aAttribute )
|
||||
* if a attribute name is specified (for instance %TD.CN*%) is specified,
|
||||
* only this attribute is cleared
|
||||
*/
|
||||
m_NetAttributeDict.ClearAttribute( &aAttribute.GetPrm( 1 ) );
|
||||
wxString cmd = aAttribute.GetPrm( 0 );
|
||||
m_NetAttributeDict.ClearAttribute( &cmd );
|
||||
|
||||
if( aAttribute.GetPrm( 1 ).IsEmpty() || aAttribute.GetPrm( 1 ) == ".AperFunction" )
|
||||
if( cmd.IsEmpty() || cmd == ".AperFunction" )
|
||||
m_AperFunction.Clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -163,6 +163,8 @@ public:
|
||||
bool m_Has_DCode; // true = DCodes in file
|
||||
// (false = no DCode -> separate DCode file
|
||||
bool m_360Arc_enbl; // Enbl 360 deg circular interpolation
|
||||
bool m_AsArcG74G75Cmd; // Set to true when a circular interpolation command
|
||||
// type is found. Mandatory before drawing an arc.
|
||||
bool m_PolygonFillMode; // Enable polygon mode (read coord as a polygon descr)
|
||||
int m_PolygonFillModeState; // In polygon mode: 0 = first segm, 1 = next segm
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user