Compare commits
153 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ad43570ec0 | |||
| 5dd4718db0 | |||
| ea70d8cf4c | |||
| cd2879880a | |||
| b51c8c1b3d | |||
| 5db1ee930f | |||
| 695dd57477 | |||
| 224c989072 | |||
| 80db7ff8cf | |||
| 6e6d3e9b03 | |||
| c08dd172d6 | |||
| 7972805d07 | |||
| a86147b4b1 | |||
| 335bb8792f | |||
| c8f7887cf8 | |||
| 2fe5c28787 | |||
| 64365de9de | |||
| a950d55cb2 | |||
| 3748a10ed5 | |||
| 227bb76909 | |||
| a20a6bb2a3 | |||
| 7c17aa5974 | |||
| 59795c81c5 | |||
| 84d00a7887 | |||
| 3774e31db8 | |||
| 69ac570658 | |||
| 46ecb22ef5 | |||
| ff7ea6eae0 | |||
| 2f70ac171f | |||
| 360011e563 | |||
| 2a0785d188 | |||
| a480b1a5ba | |||
| 6f31e306a1 | |||
| 5983815415 | |||
| 288050b6ec | |||
| 6d36363403 | |||
| 720c7d9fc4 | |||
| e009afd4a1 | |||
| 9e13ff25d0 | |||
| af1899ddc3 | |||
| beb30dd881 | |||
| 6d09293b11 | |||
| ca7378924c | |||
| 74316a62d3 | |||
| 3150f467bb | |||
| c033c364d4 | |||
| 37c14a65ed | |||
| dbf64ac0cf | |||
| 0eda576189 | |||
| 6ee9fb4027 | |||
| 64134cee92 | |||
| fead0eb33b | |||
| ff71b324a1 | |||
| b10ab478bd | |||
| 710b6adb8c | |||
| 6a01bdbabd | |||
| 76e19c6dcf | |||
| 8af289c33e | |||
| 35fa7db5c7 | |||
| 67739ee3d1 | |||
| d8ba7284a8 | |||
| fdc0309592 | |||
| 55d77f0dbb | |||
| 14fafebbc7 | |||
| 7ca472deb8 | |||
| fdb3612565 | |||
| bf59a6305a | |||
| 17db770d92 | |||
| b3004c9d96 | |||
| c54ebdecd2 | |||
| 6fc15ed8df | |||
| e7779d9b91 | |||
| 06a91637a7 | |||
| 08e9ce2828 | |||
| 24f82ab87d | |||
| bcf069699d | |||
| f8d694e4d0 | |||
| b80334baa1 | |||
| 6c359e2f06 | |||
| a3eff548b7 | |||
| e33a732371 | |||
| 95d3200a3a | |||
| 5ee7ae4a45 | |||
| b13a9e231b | |||
| 1011f361fd | |||
| 288a08b9c2 | |||
| cac1979f61 | |||
| 38a9477423 | |||
| 072446e79d | |||
| 4fc528819d | |||
| d5f52000ce | |||
| 8e4d7da4ea | |||
| ea3f0bada4 | |||
| 3b33ce8bcc | |||
| 74b42f1bb2 | |||
| b455a4cd54 | |||
| 5021f6ee26 | |||
| 0be2b88f5a | |||
| f3a57cf763 | |||
| ddd69019bc | |||
| 94e34cb1eb | |||
| 6470212edd | |||
| 8c3bcade1c | |||
| 70e99acce6 | |||
| 25be138ac1 | |||
| 9f196d2e64 | |||
| b51fed4118 | |||
| a914f361d3 | |||
| 846b634e0e | |||
| 08b54e205d | |||
| 7cba1e1a55 | |||
| 6ae334a751 | |||
| 61687e8499 | |||
| e014f2274f | |||
| 7e0f05f991 | |||
| 1e21b41be5 | |||
| 4a7dcfdd1f | |||
| d1684b8a72 | |||
| 8da026baff | |||
| 89a3ead51e | |||
| 5064834716 | |||
| 51a3859d7e | |||
| bf37bd8ed5 | |||
| 283fed83c3 | |||
| 48983dd31d | |||
| ccd4b0cf05 | |||
| 154c755a1b | |||
| 4157d3350e | |||
| 08ba185003 | |||
| 7b0e5cd080 | |||
| 66f50d0c0b | |||
| 973d2d6c03 | |||
| fa854b80da | |||
| 05f8bc05ec | |||
| d9af68b910 | |||
| 0c8172880f | |||
| 45559cb809 | |||
| d3e1d94046 | |||
| 2c75396b80 | |||
| 7aae0a9f65 | |||
| bfd6d96ffc | |||
| f4efa47fe7 | |||
| d1fd8b18ad | |||
| 5ee1c0ab42 | |||
| 8d53326021 | |||
| 246afee56e | |||
| 352faf526f | |||
| c183a63c50 | |||
| 9c34432b99 | |||
| 76bc0e27fc | |||
| b2f6d341dd | |||
| 7b5afe805e | |||
| b77a591c45 |
@@ -752,6 +752,11 @@ void EDA_3D_CANVAS::OnLeftDown( wxMouseEvent& event )
|
||||
SetFocus();
|
||||
stop_editingTimeOut_Timer();
|
||||
|
||||
// Ensure m_camera.m_lastPosition (current mouse position) is up to date for
|
||||
// future drag events (can be not the case when left clicking after
|
||||
// opening a context menu)
|
||||
OnMouseMoveCamera( event );
|
||||
|
||||
if( !event.Dragging() && ( m_3d_render_raytracing != nullptr ) )
|
||||
{
|
||||
RAY mouseRay = getRayAtCurrentMousePosition();
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
add_library(3d-viewer_navlib STATIC
|
||||
"nl_3d_viewer_plugin.cpp"
|
||||
"nl_3d_viewer_plugin_impl.cpp"
|
||||
"nl_footprint_properties_plugin.cpp"
|
||||
"nl_footprint_properties_plugin_impl.cpp"
|
||||
)
|
||||
|
||||
# 3d-viewer_navlib depends on make_lexer outputs in common
|
||||
|
||||
@@ -25,20 +25,17 @@
|
||||
|
||||
|
||||
NL_3D_VIEWER_PLUGIN::NL_3D_VIEWER_PLUGIN( EDA_3D_CANVAS* aViewport )
|
||||
: m_impl( nullptr )
|
||||
{
|
||||
if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver
|
||||
&& KIPLATFORM::DRIVERS::Valid3DConnexionDriverVersion() )
|
||||
{
|
||||
m_impl = new NL_3D_VIEWER_PLUGIN_IMPL( aViewport );
|
||||
m_impl = std::make_unique<NL_3D_VIEWER_PLUGIN_IMPL>( aViewport, "KiCAD 3D" );
|
||||
m_impl->Connect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NL_3D_VIEWER_PLUGIN::~NL_3D_VIEWER_PLUGIN()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
NL_3D_VIEWER_PLUGIN::~NL_3D_VIEWER_PLUGIN() = default;
|
||||
|
||||
|
||||
void NL_3D_VIEWER_PLUGIN::SetFocus( bool focus )
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#ifndef NL_3D_VIEWER_PLUGIN_H_
|
||||
#define NL_3D_VIEWER_PLUGIN_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
// Forward declarations.
|
||||
class EDA_3D_CANVAS;
|
||||
class NL_3D_VIEWER_PLUGIN_IMPL;
|
||||
@@ -54,7 +56,7 @@ public:
|
||||
void SetFocus( bool aFocus = true );
|
||||
|
||||
private:
|
||||
NL_3D_VIEWER_PLUGIN_IMPL* m_impl;
|
||||
std::unique_ptr<NL_3D_VIEWER_PLUGIN_IMPL> m_impl;
|
||||
};
|
||||
|
||||
#endif // NL_3D_VIEWER_PLUGIN_H_
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 3Dconnexion
|
||||
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2024 3Dconnexion
|
||||
* Copyright (C) 2024 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
|
||||
@@ -27,6 +27,7 @@
|
||||
// KiCAD includes
|
||||
#include <tool/action_manager.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <tool/tools_holder.h>
|
||||
|
||||
// stdlib
|
||||
#include <map>
|
||||
@@ -72,7 +73,7 @@ bool equals( glm::mat<L, C, T, Q> const& aFirst, glm::mat<L, C, T, Q> const& aSe
|
||||
}
|
||||
|
||||
|
||||
NL_3D_VIEWER_PLUGIN_IMPL::NL_3D_VIEWER_PLUGIN_IMPL( EDA_3D_CANVAS* aCanvas ) :
|
||||
NL_3D_VIEWER_PLUGIN_IMPL::NL_3D_VIEWER_PLUGIN_IMPL( EDA_3D_CANVAS* aCanvas, const std::string& aProfileHint ) :
|
||||
NAV_3D( false, false ),
|
||||
m_canvas( aCanvas ),
|
||||
m_capIsMoving( false ),
|
||||
@@ -80,12 +81,7 @@ NL_3D_VIEWER_PLUGIN_IMPL::NL_3D_VIEWER_PLUGIN_IMPL( EDA_3D_CANVAS* aCanvas ) :
|
||||
{
|
||||
m_camera = dynamic_cast<TRACK_BALL*>( m_canvas->GetCamera() );
|
||||
|
||||
PutProfileHint( "KiCAD 3D" );
|
||||
|
||||
EnableNavigation( true );
|
||||
PutFrameTimingSource( TimingSource::SpaceMouse );
|
||||
|
||||
exportCommandsAndImages();
|
||||
PutProfileHint( aProfileHint );
|
||||
}
|
||||
|
||||
|
||||
@@ -101,8 +97,19 @@ void NL_3D_VIEWER_PLUGIN_IMPL::SetFocus( bool aFocus )
|
||||
NAV_3D::Write( navlib::focus_k, aFocus );
|
||||
}
|
||||
|
||||
// temporary store for the categories
|
||||
typedef std::map<std::string, TDx::CCommandTreeNode*> CATEGORY_STORE;
|
||||
|
||||
EDA_3D_CANVAS* NL_3D_VIEWER_PLUGIN_IMPL::GetCanvas() const
|
||||
{
|
||||
return m_canvas;
|
||||
}
|
||||
|
||||
|
||||
void NL_3D_VIEWER_PLUGIN_IMPL::Connect()
|
||||
{
|
||||
EnableNavigation(true);
|
||||
PutFrameTimingSource(TimingSource::SpaceMouse);
|
||||
exportCommandsAndImages();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a category to the store.
|
||||
@@ -571,7 +578,7 @@ long NL_3D_VIEWER_PLUGIN_IMPL::SetActiveCommand( std::string commandId )
|
||||
|
||||
if( parent->IsEnabled() )
|
||||
{
|
||||
TOOL_MANAGER* tool_manager = static_cast<PCB_BASE_FRAME*>( parent )->GetToolManager();
|
||||
TOOL_MANAGER* tool_manager = dynamic_cast<TOOLS_HOLDER*>( parent )->GetToolManager();
|
||||
|
||||
if( tool_manager == nullptr )
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 3Dconnexion
|
||||
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2024 3Dconnexion
|
||||
* Copyright (C) 2024 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
|
||||
@@ -42,6 +42,11 @@
|
||||
class EDA_3D_CANVAS;
|
||||
class TRACK_BALL;
|
||||
|
||||
// temporary store for the categories
|
||||
typedef std::map<std::string, TDx::CCommandTreeNode*> CATEGORY_STORE;
|
||||
|
||||
CATEGORY_STORE::iterator add_category( std::string aCategoryPath, CATEGORY_STORE& aCategoryStore );
|
||||
|
||||
// Convenience typedef.
|
||||
typedef TDx::SpaceMouse::Navigation3D::CNavigation3D NAV_3D;
|
||||
|
||||
@@ -56,8 +61,9 @@ public:
|
||||
* Initializes a new instance of the NL_3DVIEWER_PLUGIN.
|
||||
*
|
||||
* @param aCanvas is the viewport to be navigated.
|
||||
* @param aProfileHint tells the 3DConnexion UI which profile to use.
|
||||
*/
|
||||
NL_3D_VIEWER_PLUGIN_IMPL( EDA_3D_CANVAS* aCanvas );
|
||||
NL_3D_VIEWER_PLUGIN_IMPL( EDA_3D_CANVAS* aCanvas, const std::string& aProfileHint );
|
||||
|
||||
virtual ~NL_3D_VIEWER_PLUGIN_IMPL();
|
||||
|
||||
@@ -69,11 +75,21 @@ public:
|
||||
*/
|
||||
void SetFocus( bool aFocus = true );
|
||||
|
||||
/**
|
||||
* Get the m_canvas pointer.
|
||||
*/
|
||||
EDA_3D_CANVAS* GetCanvas() const;
|
||||
|
||||
/**
|
||||
* Connect plugin implementation to the driver.
|
||||
*/
|
||||
void Connect();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Export the invocable actions and images to the 3Dconnexion UI.
|
||||
*/
|
||||
void exportCommandsAndImages();
|
||||
virtual void exportCommandsAndImages();
|
||||
|
||||
long GetCameraMatrix( navlib::matrix_t& aMatrix ) const override;
|
||||
long GetPointerPosition( navlib::point_t& aPosition ) const override;
|
||||
@@ -111,6 +127,7 @@ private:
|
||||
long GetCoordinateSystem( navlib::matrix_t& aMatrix ) const override;
|
||||
long GetIsViewRotatable( navlib::bool_t& isRotatable ) const override;
|
||||
|
||||
|
||||
private:
|
||||
EDA_3D_CANVAS* m_canvas;
|
||||
TRACK_BALL* m_camera;
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 3Dconnexion
|
||||
* Copyright (C) 2024 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 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 "nl_footprint_properties_plugin.h"
|
||||
#include "nl_footprint_properties_plugin_impl.h"
|
||||
#include <advanced_config.h>
|
||||
#include <kiplatform/drivers.h>
|
||||
|
||||
|
||||
NL_FOOTPRINT_PROPERTIES_PLUGIN::NL_FOOTPRINT_PROPERTIES_PLUGIN( EDA_3D_CANVAS* aViewport )
|
||||
{
|
||||
if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver
|
||||
&& KIPLATFORM::DRIVERS::Valid3DConnexionDriverVersion() )
|
||||
{
|
||||
m_impl = std::make_unique<NL_FOOTPRINT_PROPERTIES_PLUGIN_IMPL>( aViewport );
|
||||
m_impl->Connect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NL_FOOTPRINT_PROPERTIES_PLUGIN::~NL_FOOTPRINT_PROPERTIES_PLUGIN() = default;
|
||||
|
||||
|
||||
void NL_FOOTPRINT_PROPERTIES_PLUGIN::SetFocus( bool focus )
|
||||
{
|
||||
if( m_impl )
|
||||
m_impl->SetFocus( focus );
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 3Dconnexion
|
||||
* Copyright (C) 2024 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 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file nl_footprint_properties_plugin.h
|
||||
* @brief declaration of the nl_footprint_properties_plugin class
|
||||
*/
|
||||
|
||||
#ifndef NL_FOOTPRINT_PROPERTIES_PLUGIN_H_
|
||||
#define NL_FOOTPRINT_PROPERTIES_PLUGIN_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
// Forward declarations.
|
||||
class EDA_3D_CANVAS;
|
||||
class NL_FOOTPRINT_PROPERTIES_PLUGIN_IMPL;
|
||||
|
||||
/**
|
||||
* The class that implements the public interface to the SpaceMouse plug-in.
|
||||
*/
|
||||
class NL_FOOTPRINT_PROPERTIES_PLUGIN
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Initializes a new instance of the NL_FOOTPRINT_PROPERTIES_PLUGIN.
|
||||
*
|
||||
* @param aViewport is the viewport to be navigated.
|
||||
*/
|
||||
NL_FOOTPRINT_PROPERTIES_PLUGIN( EDA_3D_CANVAS* aViewport );
|
||||
|
||||
virtual ~NL_FOOTPRINT_PROPERTIES_PLUGIN();
|
||||
|
||||
/**
|
||||
* Set the connection to the 3Dconnexion driver to the focus state so that
|
||||
* 3DMouse data is routed here.
|
||||
*
|
||||
* @param aFocus is true to set the connection active.
|
||||
*/
|
||||
void SetFocus( bool aFocus = true );
|
||||
|
||||
private:
|
||||
std::unique_ptr<NL_FOOTPRINT_PROPERTIES_PLUGIN_IMPL> m_impl;
|
||||
};
|
||||
|
||||
#endif // NL_FOOTPRINT_PROPERTIES_PLUGIN_H_
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 3Dconnexion
|
||||
* Copyright (C) 2024 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 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 "nl_footprint_properties_plugin_impl.h"
|
||||
#include <3d-viewer/3d_canvas/eda_3d_canvas.h>
|
||||
|
||||
// KiCAD includes
|
||||
#include <tool/action_manager.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <tool/tools_holder.h>
|
||||
|
||||
#include <wx/mstream.h>
|
||||
|
||||
#define BOUNDING_BOX_SCALE_FACTOR 1.3f
|
||||
|
||||
/**
|
||||
* Flag to enable the NL_FOOTPRINT_PROPERTIES_PLUGIN debug tracing.
|
||||
*
|
||||
* Use "KI_TRACE_NL_FOOTPRINT_PROPERTIES_PLUGIN" to enable.
|
||||
*
|
||||
* @ingroup trace_env_vars
|
||||
*/
|
||||
const wxChar* NL_FOOTPRINT_PROPERTIES_PLUGIN_IMPL::m_logTrace =
|
||||
wxT( "KI_TRACE_NL_FOOTPRINT_PROPERTIES_PLUGIN" );
|
||||
|
||||
|
||||
NL_FOOTPRINT_PROPERTIES_PLUGIN_IMPL::NL_FOOTPRINT_PROPERTIES_PLUGIN_IMPL(EDA_3D_CANVAS* aCanvas) :
|
||||
NL_3D_VIEWER_PLUGIN_IMPL(aCanvas, "KiCAD Footprint Properties")
|
||||
{}
|
||||
|
||||
|
||||
long NL_FOOTPRINT_PROPERTIES_PLUGIN_IMPL::GetModelExtents( navlib::box_t& extents ) const
|
||||
{
|
||||
SFVEC3F min = NL_3D_VIEWER_PLUGIN_IMPL::GetCanvas()->GetBoardAdapter().GetBBox().Min();
|
||||
SFVEC3F max = NL_3D_VIEWER_PLUGIN_IMPL::GetCanvas()->GetBoardAdapter().GetBBox().Max();
|
||||
|
||||
SFVEC3F diff = ( BOUNDING_BOX_SCALE_FACTOR - 1.f ) / 2.f * ( max - min );
|
||||
|
||||
min -= diff;
|
||||
max += diff;
|
||||
|
||||
extents = { min.x, min.y, min.z, max.x, max.y, max.z };
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void NL_FOOTPRINT_PROPERTIES_PLUGIN_IMPL::exportCommandsAndImages()
|
||||
{
|
||||
std::list<TOOL_ACTION*> actions = ACTION_MANAGER::GetActionList();
|
||||
|
||||
if( actions.size() == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using TDx::SpaceMouse::CCommand;
|
||||
using TDx::SpaceMouse::CCommandSet;
|
||||
|
||||
// The root action set node
|
||||
CCommandSet commandSet( "EDA_3D_CANVAS", "3D Viewer" );
|
||||
|
||||
// Activate the command set
|
||||
NAV_3D::PutActiveCommands( commandSet.GetId() );
|
||||
|
||||
// temporary store for the categories
|
||||
CATEGORY_STORE categoryStore;
|
||||
|
||||
std::vector<TDx::CImage> vImages;
|
||||
|
||||
// add the action set to the category_store
|
||||
categoryStore.insert( categoryStore.end(), CATEGORY_STORE::value_type( ".", &commandSet ) );
|
||||
|
||||
std::list<TOOL_ACTION*>::const_iterator it;
|
||||
|
||||
for( it = actions.begin(); it != actions.end(); ++it )
|
||||
{
|
||||
const TOOL_ACTION* action = *it;
|
||||
std::string label = action->GetMenuLabel().ToStdString();
|
||||
|
||||
if( label.empty() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string name = action->GetName();
|
||||
|
||||
// Do no export commands for the pcbnew app.
|
||||
if( name.rfind( "pcbnew.", 0 ) == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Exclude commands which can't be used in the footprint properties.
|
||||
if( name.rfind( "3DViewer.Control.pivotCenter", 0 ) == 0
|
||||
|| name.rfind( "3DViewer.Control.material", 0 ) == 0
|
||||
|| name.rfind( "3DViewer.Control.attribute", 0 ) == 0
|
||||
|| name.rfind( "3DViewer.Control.show", 0 ) == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string strCategory = action->GetToolName();
|
||||
CATEGORY_STORE::iterator iter = categoryStore.find( strCategory );
|
||||
|
||||
if( iter == categoryStore.end() )
|
||||
{
|
||||
iter = add_category( std::move( strCategory ), categoryStore );
|
||||
}
|
||||
|
||||
std::string description = action->GetDescription().ToStdString();
|
||||
|
||||
// Arbitrary 8-bit data stream
|
||||
wxMemoryOutputStream imageStream;
|
||||
|
||||
if( action->GetIcon() != BITMAPS::INVALID_BITMAP )
|
||||
{
|
||||
wxImage image = KiBitmap( action->GetIcon() ).ConvertToImage();
|
||||
image.SaveFile( imageStream, wxBitmapType::wxBITMAP_TYPE_PNG );
|
||||
image.Destroy();
|
||||
|
||||
if( imageStream.GetSize() )
|
||||
{
|
||||
wxStreamBuffer* streamBuffer = imageStream.GetOutputStreamBuffer();
|
||||
TDx::CImage tdxImage = TDx::CImage::FromData( "", 0, name.c_str() );
|
||||
tdxImage.AssignImage( std::string( reinterpret_cast<const char*>(
|
||||
streamBuffer->GetBufferStart() ),
|
||||
streamBuffer->GetBufferSize() ),
|
||||
0 );
|
||||
|
||||
wxLogTrace( m_logTrace, wxT( "Adding image for : %s" ), name );
|
||||
vImages.push_back( std::move( tdxImage ) );
|
||||
}
|
||||
}
|
||||
|
||||
wxLogTrace( m_logTrace, wxT( "Inserting command: %s, description: %s, in category: %s" ),
|
||||
name, description, iter->first );
|
||||
|
||||
iter->second->push_back(
|
||||
CCommand( std::move( name ), std::move( label ), std::move( description ) ) );
|
||||
}
|
||||
|
||||
NAV_3D::AddCommandSet( commandSet );
|
||||
NAV_3D::AddImages( vImages );
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 3Dconnexion
|
||||
* Copyright (C) 2024 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 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file nl_footprint_properties_plugin_impl.h
|
||||
* @brief declaration of the nl_footprint_properties_plugin_impl class
|
||||
*/
|
||||
|
||||
#ifndef NL_FOOTPRINT_PROPERTIES_PLUGIN_IMPL_H_
|
||||
#define NL_FOOTPRINT_PROPERTIES_PLUGIN_IMPL_H_
|
||||
|
||||
#include "nl_3d_viewer_plugin_impl.h"
|
||||
// TDxWare SDK.
|
||||
#include <SpaceMouse/CNavigation3D.hpp>
|
||||
|
||||
/**
|
||||
* The class that adjusts NL_3D_VIEWER_PLUGIN_IMPL implementation for 3D Model preview in footprint properties dialog.
|
||||
*/
|
||||
class NL_FOOTPRINT_PROPERTIES_PLUGIN_IMPL : public NL_3D_VIEWER_PLUGIN_IMPL
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Initializes a new instance of the NL_FOOTPRINT_PROPERTIES_PLUGIN.
|
||||
*
|
||||
* @param aCanvas is the viewport to be navigated.
|
||||
*/
|
||||
NL_FOOTPRINT_PROPERTIES_PLUGIN_IMPL( EDA_3D_CANVAS* aCanvas );
|
||||
|
||||
private:
|
||||
/**
|
||||
* Get Footprint 3D Model extents.
|
||||
*
|
||||
* @param extents is the box around the 3D model.
|
||||
*/
|
||||
long GetModelExtents( navlib::box_t& extents ) const override;
|
||||
|
||||
/**
|
||||
* Export the invocable actions and images to the 3Dconnexion UI.
|
||||
*/
|
||||
void exportCommandsAndImages() override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* 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
|
||||
* "KI_TRACE_NL_FOOTPRINT_PROPERTIES_PLUGIN". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*/
|
||||
static const wxChar* m_logTrace;
|
||||
};
|
||||
#endif // NL_FOOTPRINT_PROPERTIES_PLUGIN_IMPL_H_
|
||||
@@ -570,6 +570,9 @@ void EDA_3D_VIEWER_FRAME::LoadSettings( APP_SETTINGS_BASE *aCfg )
|
||||
{
|
||||
applySettings( cfg );
|
||||
|
||||
if( !GetBoard()->GetProject() )
|
||||
GetBoard()->SetProject( &Prj() );
|
||||
|
||||
m_boardAdapter.SetBoard( GetBoard() );
|
||||
|
||||
// When opening the 3D viewer, we use the OpenGL mode, never the ray tracing engine
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
#include <eda_3d_viewer_settings.h>
|
||||
#include <board_design_settings.h>
|
||||
|
||||
#include <3d_navlib/nl_footprint_properties_plugin.h>
|
||||
|
||||
PANEL_PREVIEW_3D_MODEL::PANEL_PREVIEW_3D_MODEL( wxWindow* aParent, PCB_BASE_FRAME* aFrame,
|
||||
FOOTPRINT* aFootprint,
|
||||
std::vector<FP_3DMODEL>* aParentModelList ) :
|
||||
@@ -125,6 +127,9 @@ PANEL_PREVIEW_3D_MODEL::PANEL_PREVIEW_3D_MODEL( wxWindow* aParent, PCB_BASE_FRAM
|
||||
OGL_ATT_LIST::GetAttributesList( ANTIALIASING_MODE::AA_8X ),
|
||||
m_boardAdapter, m_currentCamera, PROJECT_PCB::Get3DCacheManager( &aFrame->Prj() ) );
|
||||
|
||||
m_spaceMouse = new NL_FOOTPRINT_PROPERTIES_PLUGIN( m_previewPane );
|
||||
m_spaceMouse->SetFocus( true );
|
||||
|
||||
m_boardAdapter.SetBoard( m_dummyBoard );
|
||||
m_boardAdapter.m_IsBoardView = false;
|
||||
m_boardAdapter.m_IsPreviewer = true; // Force display 3D models, regardless the 3D viewer options
|
||||
@@ -162,6 +167,8 @@ PANEL_PREVIEW_3D_MODEL::PANEL_PREVIEW_3D_MODEL( wxWindow* aParent, PCB_BASE_FRAM
|
||||
wxCommandEventHandler( PANEL_PREVIEW_3D_MODEL::onUnitsChanged ),
|
||||
nullptr, this );
|
||||
|
||||
Bind( wxCUSTOM_PANEL_SHOWN_EVENT, &PANEL_PREVIEW_3D_MODEL::onPanelShownEvent, this );
|
||||
|
||||
#ifdef __WXOSX__
|
||||
// Call layout once to get the proper button sizes after the bitmaps have been set
|
||||
Layout();
|
||||
@@ -190,6 +197,7 @@ PANEL_PREVIEW_3D_MODEL::~PANEL_PREVIEW_3D_MODEL()
|
||||
if( m_boardAdapter.m_Cfg )
|
||||
m_boardAdapter.m_Cfg->m_Render = m_initialRender;
|
||||
|
||||
delete m_spaceMouse;
|
||||
delete m_dummyBoard;
|
||||
delete m_previewPane;
|
||||
}
|
||||
@@ -620,6 +628,17 @@ void PANEL_PREVIEW_3D_MODEL::onUnitsChanged( wxCommandEvent& aEvent )
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREVIEW_3D_MODEL::onPanelShownEvent( wxCommandEvent& aEvent )
|
||||
{
|
||||
if( m_spaceMouse != nullptr )
|
||||
{
|
||||
m_spaceMouse->SetFocus( static_cast<bool>( aEvent.GetInt() ) );
|
||||
}
|
||||
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREVIEW_3D_MODEL::UpdateDummyFootprint( bool aReloadRequired )
|
||||
{
|
||||
m_dummyFootprint->Models().clear();
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <3d_canvas/eda_3d_canvas.h>
|
||||
#include <3d_viewer_id.h>
|
||||
#include <3d_rendering/track_ball.h>
|
||||
#include <wx/event.h>
|
||||
|
||||
// Define min and max parameter values
|
||||
#define MAX_SCALE 10000.0
|
||||
@@ -52,6 +53,7 @@
|
||||
#define OFFSET_INCREMENT_MIL 25.0
|
||||
#define OFFSET_INCREMENT_MIL_FINE 5.0
|
||||
|
||||
wxDECLARE_EVENT( wxCUSTOM_PANEL_SHOWN_EVENT, wxCommandEvent );
|
||||
|
||||
// Declared classes to create pointers
|
||||
class WX_INFOBAR;
|
||||
@@ -60,6 +62,7 @@ class FILENAME_RESOLVER;
|
||||
class BOARD;
|
||||
class BOARD_ADAPTER;
|
||||
class FOOTPRINT;
|
||||
class NL_FOOTPRINT_PROPERTIES_PLUGIN;
|
||||
|
||||
class PANEL_PREVIEW_3D_MODEL: public EDA_3D_BOARD_HOLDER, public TOOLS_HOLDER, public PANEL_PREVIEW_3D_MODEL_BASE
|
||||
{
|
||||
@@ -139,6 +142,7 @@ private:
|
||||
void doIncrementOffset( wxSpinEvent& aEvent, double aSign );
|
||||
|
||||
void onUnitsChanged( wxCommandEvent& aEvent );
|
||||
void onPanelShownEvent( wxCommandEvent& aEvent );
|
||||
|
||||
wxString formatScaleValue( double aValue );
|
||||
wxString formatRotationValue( double aValue );
|
||||
@@ -211,6 +215,8 @@ private:
|
||||
bool m_bodyStyleShowAll; /// true if the board body is show
|
||||
/// The 3d viewer Render initial settings (must be saved and restored)
|
||||
EDA_3D_VIEWER_SETTINGS::RENDER_SETTINGS m_initialRender;
|
||||
|
||||
NL_FOOTPRINT_PROPERTIES_PLUGIN* m_spaceMouse;
|
||||
};
|
||||
|
||||
#endif // PANEL_PREVIEW_3D_MODEL_H
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
# KiCad.
|
||||
#
|
||||
# Note: This version string should follow the semantic versioning system
|
||||
set( KICAD_SEMANTIC_VERSION "8.0.6" )
|
||||
set( KICAD_SEMANTIC_VERSION "8.0.7" )
|
||||
|
||||
# Default the version to the semantic version.
|
||||
# This is overridden by the git repository tag though (if using git)
|
||||
|
||||
@@ -109,6 +109,7 @@ static const wxChar OcePluginAngularDeflection[] = wxT( "OcePluginAngularDeflect
|
||||
static const wxChar TriangulateSimplificationLevel[] = wxT( "TriangulateSimplificationLevel" );
|
||||
static const wxChar TriangulateMinimumArea[] = wxT( "TriangulateMinimumArea" );
|
||||
static const wxChar EnableCacheFriendlyFracture[] = wxT( "EnableCacheFriendlyFracture" );
|
||||
static const wxChar MinParallelAngle[] = wxT( "MinParallelAngle" );
|
||||
} // namespace KEYS
|
||||
|
||||
|
||||
@@ -261,6 +262,8 @@ ADVANCED_CFG::ADVANCED_CFG()
|
||||
|
||||
m_EnableCacheFriendlyFracture = true;
|
||||
|
||||
m_MinParallelAngle = 0.001;
|
||||
|
||||
loadFromConfigFile();
|
||||
}
|
||||
|
||||
@@ -477,6 +480,10 @@ void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg )
|
||||
&m_EnableCacheFriendlyFracture,
|
||||
m_EnableCacheFriendlyFracture ) );
|
||||
|
||||
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::MinParallelAngle,
|
||||
&m_MinParallelAngle, m_MinParallelAngle,
|
||||
0.0, 45.0 ) );
|
||||
|
||||
// Special case for trace mask setting...we just grab them and set them immediately
|
||||
// Because we even use wxLogTrace inside of advanced config
|
||||
wxString traceMasks;
|
||||
|
||||
@@ -162,6 +162,9 @@ void COMMIT::makeEntry( EDA_ITEM* aItem, CHANGE_TYPE aType, EDA_ITEM* aCopy, BAS
|
||||
ent.m_copy = aCopy;
|
||||
ent.m_screen = aScreen;
|
||||
|
||||
// N.B. Do not throw an assertion for multiple changed items. An item can be changed multiple times
|
||||
// in a single commit such as when importing graphics and grouping them.
|
||||
|
||||
m_changedItems.insert( aItem );
|
||||
m_changes.push_back( ent );
|
||||
}
|
||||
|
||||
+3
-10
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2014-2020 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
|
||||
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2023, 2024 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
|
||||
@@ -347,18 +347,11 @@ const wxString ExpandEnvVarSubstitutions( const wxString& aString, const PROJECT
|
||||
}
|
||||
|
||||
|
||||
const wxString ResolveUriByEnvVars( const wxString& aUri, PROJECT* aProject )
|
||||
const wxString ResolveUriByEnvVars( const wxString& aUri, const PROJECT* aProject )
|
||||
{
|
||||
wxString uri = ExpandTextVars( aUri, aProject );
|
||||
|
||||
// URL-like URI: return as is.
|
||||
wxURL url( uri );
|
||||
|
||||
if( url.GetError() == wxURL_NOERR )
|
||||
return uri;
|
||||
|
||||
// Otherwise, the path points to a local file. Resolve environment variables if any.
|
||||
return ExpandEnvVarSubstitutions( aUri, aProject );
|
||||
return ExpandEnvVarSubstitutions( uri, aProject );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2018-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2018-2024 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
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <wx/dcmemory.h>
|
||||
|
||||
#define ALPHA_MAX 100 // the max value returned by the alpha (opacity) slider
|
||||
#define SLOPE_AXIS ( bmsize.y / 5.28 ) // was 50 at 264 size
|
||||
|
||||
using KIGFX::COLOR4D;
|
||||
|
||||
@@ -52,13 +53,17 @@ DIALOG_COLOR_PICKER::DIALOG_COLOR_PICKER( wxWindow* aParent, const COLOR4D& aCur
|
||||
m_allowOpacityCtrl = aAllowOpacityControl;
|
||||
m_previousColor4D = aCurrentColor;
|
||||
m_newColor4D = aCurrentColor;
|
||||
m_cursorsSize = 8; // Size of square cursors drawn on color bitmaps
|
||||
m_newColor4D.ToHSV( m_hue, m_sat, m_val, true );
|
||||
m_bitmapRGB = nullptr;
|
||||
m_bitmapHSV = nullptr;
|
||||
m_selectedCursor = nullptr;
|
||||
m_defaultColor = aDefaultColor;
|
||||
|
||||
updateHandleSize();
|
||||
|
||||
m_OldColorRect->SetMinSize( FromDIP( wxSize( 24, 24 ) ) );
|
||||
m_NewColorRect->SetMinSize( FromDIP( wxSize( 24, 24 ) ) );
|
||||
|
||||
if( !m_allowOpacityCtrl )
|
||||
{
|
||||
m_SizerTransparency->Show( false );
|
||||
@@ -121,16 +126,15 @@ void DIALOG_COLOR_PICKER::updatePreview( wxStaticBitmap* aStaticBitmap, COLOR4D&
|
||||
wxBitmap newBm = COLOR_SWATCH::MakeBitmap( aColor4D, COLOR4D::WHITE, aStaticBitmap->GetSize(),
|
||||
ConvertDialogToPixels( CHECKERBOARD_SIZE_DU ),
|
||||
aStaticBitmap->GetParent()->GetBackgroundColour() );
|
||||
|
||||
newBm.SetScaleFactor( GetDPIScaleFactor() );
|
||||
aStaticBitmap->SetBitmap( newBm );
|
||||
}
|
||||
|
||||
|
||||
bool DIALOG_COLOR_PICKER::TransferDataToWindow()
|
||||
{
|
||||
// Draw all bitmaps, with colors according to the color 4D
|
||||
updatePreview( m_OldColorRect, m_previousColor4D );
|
||||
SetEditVals( ALL_CHANGED, false );
|
||||
drawAll();
|
||||
|
||||
// Configure the spin control sizes
|
||||
configureSpinCtrl( m_spinCtrlGreen );
|
||||
@@ -144,6 +148,10 @@ bool DIALOG_COLOR_PICKER::TransferDataToWindow()
|
||||
|
||||
finishDialogSettings();
|
||||
|
||||
// Draw all bitmaps, with colors according to the color 4D
|
||||
updatePreview( m_OldColorRect, m_previousColor4D );
|
||||
drawAll();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -171,6 +179,8 @@ void DIALOG_COLOR_PICKER::initDefinedColors( CUSTOM_COLORS_LIST* aPredefinedColo
|
||||
{
|
||||
wxBitmap bm = COLOR_SWATCH::MakeBitmap( aColor, COLOR4D::WHITE, swatchSize,
|
||||
checkerboardSize, checkboardBackground );
|
||||
|
||||
bm.SetScaleFactor( GetDPIScaleFactor() );
|
||||
wxStaticBitmap* swatch = new wxStaticBitmap( m_panelDefinedColors, aId, bm );
|
||||
|
||||
m_fgridColor->Add( swatch, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
@@ -245,7 +255,6 @@ void DIALOG_COLOR_PICKER::createRGBBitmap()
|
||||
|
||||
// Red blue area in X Z 3d axis
|
||||
double inc = 255.0 / half_size;
|
||||
#define SLOPE_AXIS 50.0
|
||||
double slope = SLOPE_AXIS/half_size;
|
||||
color.g = 0.0;
|
||||
|
||||
@@ -315,6 +324,7 @@ void DIALOG_COLOR_PICKER::createRGBBitmap()
|
||||
|
||||
delete m_bitmapRGB;
|
||||
m_bitmapRGB = new wxBitmap( img, 24 );
|
||||
m_bitmapRGB->SetScaleFactor( m_RgbBitmap->GetDPIScaleFactor() );
|
||||
m_RgbBitmap->SetBitmap( *m_bitmapRGB );
|
||||
}
|
||||
|
||||
@@ -379,6 +389,7 @@ void DIALOG_COLOR_PICKER::createHSVBitmap()
|
||||
|
||||
delete m_bitmapHSV;
|
||||
m_bitmapHSV = new wxBitmap( img, 24 );
|
||||
m_bitmapHSV->SetScaleFactor( m_HsvBitmap->GetDPIScaleFactor() );
|
||||
m_HsvBitmap->SetBitmap( *m_bitmapHSV );
|
||||
}
|
||||
|
||||
@@ -413,8 +424,7 @@ void DIALOG_COLOR_PICKER::drawRGBPalette()
|
||||
bitmapDC.SetBrush( brush );
|
||||
int half_csize = m_cursorsSize / 2;
|
||||
|
||||
#define SLOPE_AXIS 50.0
|
||||
double slope = SLOPE_AXIS / half_size;
|
||||
double slope = SLOPE_AXIS / ( half_size );
|
||||
|
||||
// Red axis cursor (Z 3Daxis):
|
||||
m_cursorBitmapRed.x = 0;
|
||||
@@ -539,8 +549,15 @@ void DIALOG_COLOR_PICKER::SetEditVals( CHANGED_COLOR aChanged, bool aCheckTransp
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_COLOR_PICKER::updateHandleSize()
|
||||
{
|
||||
m_cursorsSize = FromDIP( 8 ); // Size of square cursors drawn on color bitmaps
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_COLOR_PICKER::drawAll()
|
||||
{
|
||||
updateHandleSize();
|
||||
m_NewColorRect->Freeze(); // Avoid flicker
|
||||
m_HsvBitmap->Freeze();
|
||||
m_RgbBitmap->Freeze();
|
||||
@@ -699,6 +716,14 @@ void DIALOG_COLOR_PICKER::onHSVMouseDrag( wxMouseEvent& event )
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_COLOR_PICKER::onSize( wxSizeEvent& event )
|
||||
{
|
||||
drawAll();
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_COLOR_PICKER::OnColorValueText( wxCommandEvent& event )
|
||||
{
|
||||
if( m_newColor4D.SetFromHexString( m_colorValue->GetValue() ) )
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
|
||||
// C++ code generated with wxFormBuilder (version 4.1.0-0-g733bf3d)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@@ -33,7 +33,10 @@ DIALOG_COLOR_PICKER_BASE::DIALOG_COLOR_PICKER_BASE( wxWindow* parent, wxWindowID
|
||||
m_RgbBitmap = new wxStaticBitmap( sbSizerViewRGB->GetStaticBox(), wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 264,264 ), 0 );
|
||||
m_RgbBitmap->SetMinSize( wxSize( 264,264 ) );
|
||||
|
||||
sbSizerViewRGB->Add( m_RgbBitmap, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 );
|
||||
sbSizerViewRGB->Add( m_RgbBitmap, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND|wxSHAPED, 5 );
|
||||
|
||||
|
||||
sbSizerViewRGB->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
wxFlexGridSizer* fgSizerRGB;
|
||||
fgSizerRGB = new wxFlexGridSizer( 0, 3, 0, 0 );
|
||||
@@ -68,18 +71,18 @@ DIALOG_COLOR_PICKER_BASE::DIALOG_COLOR_PICKER_BASE( wxWindow* parent, wxWindowID
|
||||
sbSizerViewRGB->Add( fgSizerRGB, 0, wxEXPAND, 5 );
|
||||
|
||||
|
||||
bSizerPanels->Add( sbSizerViewRGB, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
|
||||
bSizerPanels->Add( sbSizerViewRGB, 1, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
wxStaticBoxSizer* sbSizerViewHSV;
|
||||
sbSizerViewHSV = new wxStaticBoxSizer( new wxStaticBox( m_panelFreeColors, wxID_ANY, _("HSV") ), wxHORIZONTAL );
|
||||
|
||||
wxBoxSizer* bSizer10;
|
||||
bSizer10 = new wxBoxSizer( wxVERTICAL );
|
||||
sbSizerViewHSV = new wxStaticBoxSizer( new wxStaticBox( m_panelFreeColors, wxID_ANY, _("HSV") ), wxVERTICAL );
|
||||
|
||||
m_HsvBitmap = new wxStaticBitmap( sbSizerViewHSV->GetStaticBox(), wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 264,264 ), 0 );
|
||||
m_HsvBitmap->SetMinSize( wxSize( 264,264 ) );
|
||||
|
||||
bSizer10->Add( m_HsvBitmap, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 );
|
||||
sbSizerViewHSV->Add( m_HsvBitmap, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND|wxSHAPED, 5 );
|
||||
|
||||
|
||||
sbSizerViewHSV->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
wxFlexGridSizer* fgSizerHSV;
|
||||
fgSizerHSV = new wxFlexGridSizer( 0, 2, 0, 0 );
|
||||
@@ -103,26 +106,23 @@ DIALOG_COLOR_PICKER_BASE::DIALOG_COLOR_PICKER_BASE( wxWindow* parent, wxWindowID
|
||||
fgSizerHSV->Add( m_spinCtrlSaturation, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
|
||||
bSizer10->Add( fgSizerHSV, 0, wxEXPAND, 5 );
|
||||
sbSizerViewHSV->Add( fgSizerHSV, 0, wxEXPAND, 5 );
|
||||
|
||||
|
||||
sbSizerViewHSV->Add( bSizer10, 0, wxEXPAND, 5 );
|
||||
bSizerPanels->Add( sbSizerViewHSV, 1, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
wxBoxSizer* bSizerBright;
|
||||
bSizerBright = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_staticTextBright = new wxStaticText( sbSizerViewHSV->GetStaticBox(), wxID_ANY, _("Value:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticTextBright = new wxStaticText( m_panelFreeColors, wxID_ANY, _("Value:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticTextBright->Wrap( -1 );
|
||||
bSizerBright->Add( m_staticTextBright, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 );
|
||||
|
||||
m_sliderBrightness = new wxSlider( sbSizerViewHSV->GetStaticBox(), wxID_ANY, 255, 0, 255, wxDefaultPosition, wxDefaultSize, wxSL_INVERSE|wxSL_LABELS|wxSL_LEFT|wxSL_VERTICAL );
|
||||
m_sliderBrightness = new wxSlider( m_panelFreeColors, wxID_ANY, 255, 0, 255, wxDefaultPosition, wxDefaultSize, wxSL_INVERSE|wxSL_LABELS|wxSL_LEFT|wxSL_VERTICAL );
|
||||
bSizerBright->Add( m_sliderBrightness, 1, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxTOP, 5 );
|
||||
|
||||
|
||||
sbSizerViewHSV->Add( bSizerBright, 0, wxEXPAND, 5 );
|
||||
|
||||
|
||||
bSizerPanels->Add( sbSizerViewHSV, 0, wxEXPAND|wxBOTTOM|wxRIGHT, 5 );
|
||||
bSizerPanels->Add( bSizerBright, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
bSizerUpperFreeColors->Add( bSizerPanels, 1, wxEXPAND, 5 );
|
||||
@@ -153,7 +153,7 @@ DIALOG_COLOR_PICKER_BASE::DIALOG_COLOR_PICKER_BASE( wxWindow* parent, wxWindowID
|
||||
m_SizerDefinedColors->Fit( m_panelDefinedColors );
|
||||
m_notebook->AddPage( m_panelDefinedColors, _("Defined Colors"), false );
|
||||
|
||||
bSizerUpperMain->Add( m_notebook, 0, wxEXPAND | wxALL, 5 );
|
||||
bSizerUpperMain->Add( m_notebook, 1, wxEXPAND | wxALL, 5 );
|
||||
|
||||
m_SizerTransparency = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
@@ -171,35 +171,29 @@ DIALOG_COLOR_PICKER_BASE::DIALOG_COLOR_PICKER_BASE( wxWindow* parent, wxWindowID
|
||||
bSizerUpperMain->Add( m_SizerTransparency, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
|
||||
bSizerUpperMain->Add( 0, 0, 1, wxEXPAND|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
|
||||
bSizerMain->Add( bSizerUpperMain, 0, wxEXPAND, 5 );
|
||||
bSizerMain->Add( bSizerUpperMain, 1, wxEXPAND, 5 );
|
||||
|
||||
wxBoxSizer* bButtonsSizer;
|
||||
bButtonsSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
m_staticTextOldColor = new wxStaticText( this, wxID_ANY, _("Preview (old/new):"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticTextOldColor->Wrap( -1 );
|
||||
bButtonsSizer->Add( m_staticTextOldColor, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
|
||||
bButtonsSizer->Add( m_staticTextOldColor, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
m_OldColorRect = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 );
|
||||
m_OldColorRect->SetMinSize( wxSize( 24,24 ) );
|
||||
|
||||
bButtonsSizer->Add( m_OldColorRect, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
bButtonsSizer->Add( m_OldColorRect, 0, wxALIGN_CENTER_VERTICAL|wxSHAPED, 5 );
|
||||
|
||||
m_NewColorRect = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 );
|
||||
m_NewColorRect->SetMinSize( wxSize( 24,24 ) );
|
||||
|
||||
bButtonsSizer->Add( m_NewColorRect, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
|
||||
bButtonsSizer->Add( 10, 0, 0, wxEXPAND, 5 );
|
||||
bButtonsSizer->Add( m_NewColorRect, 0, wxALIGN_CENTER_VERTICAL|wxSHAPED, 5 );
|
||||
|
||||
m_colorValue = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_colorValue->SetMinSize( wxSize( 176,-1 ) );
|
||||
|
||||
bButtonsSizer->Add( m_colorValue, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
bButtonsSizer->Add( m_colorValue, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
|
||||
bButtonsSizer->Add( 20, 0, 0, wxEXPAND, 5 );
|
||||
@@ -217,7 +211,7 @@ DIALOG_COLOR_PICKER_BASE::DIALOG_COLOR_PICKER_BASE( wxWindow* parent, wxWindowID
|
||||
bButtonsSizer->Add( m_sdbSizer, 1, wxALL, 5 );
|
||||
|
||||
|
||||
bSizerMain->Add( bButtonsSizer, 1, wxEXPAND|wxLEFT, 10 );
|
||||
bSizerMain->Add( bButtonsSizer, 0, wxEXPAND|wxLEFT, 10 );
|
||||
|
||||
|
||||
this->SetSizer( bSizerMain );
|
||||
@@ -234,6 +228,7 @@ DIALOG_COLOR_PICKER_BASE::DIALOG_COLOR_PICKER_BASE( wxWindow* parent, wxWindowID
|
||||
m_spinCtrlBlue->Connect( wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler( DIALOG_COLOR_PICKER_BASE::OnChangeEditBlue ), NULL, this );
|
||||
m_HsvBitmap->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( DIALOG_COLOR_PICKER_BASE::onHSVMouseClick ), NULL, this );
|
||||
m_HsvBitmap->Connect( wxEVT_MOTION, wxMouseEventHandler( DIALOG_COLOR_PICKER_BASE::onHSVMouseDrag ), NULL, this );
|
||||
m_HsvBitmap->Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_COLOR_PICKER_BASE::onSize ), NULL, this );
|
||||
m_spinCtrlHue->Connect( wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler( DIALOG_COLOR_PICKER_BASE::OnChangeEditHue ), NULL, this );
|
||||
m_spinCtrlSaturation->Connect( wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler( DIALOG_COLOR_PICKER_BASE::OnChangeEditSat ), NULL, this );
|
||||
m_sliderBrightness->Connect( wxEVT_SCROLL_TOP, wxScrollEventHandler( DIALOG_COLOR_PICKER_BASE::OnChangeBrightness ), NULL, this );
|
||||
@@ -268,6 +263,7 @@ DIALOG_COLOR_PICKER_BASE::~DIALOG_COLOR_PICKER_BASE()
|
||||
m_spinCtrlBlue->Disconnect( wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler( DIALOG_COLOR_PICKER_BASE::OnChangeEditBlue ), NULL, this );
|
||||
m_HsvBitmap->Disconnect( wxEVT_LEFT_DOWN, wxMouseEventHandler( DIALOG_COLOR_PICKER_BASE::onHSVMouseClick ), NULL, this );
|
||||
m_HsvBitmap->Disconnect( wxEVT_MOTION, wxMouseEventHandler( DIALOG_COLOR_PICKER_BASE::onHSVMouseDrag ), NULL, this );
|
||||
m_HsvBitmap->Disconnect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_COLOR_PICKER_BASE::onSize ), NULL, this );
|
||||
m_spinCtrlHue->Disconnect( wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler( DIALOG_COLOR_PICKER_BASE::OnChangeEditHue ), NULL, this );
|
||||
m_spinCtrlSaturation->Disconnect( wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler( DIALOG_COLOR_PICKER_BASE::OnChangeEditSat ), NULL, this );
|
||||
m_sliderBrightness->Disconnect( wxEVT_SCROLL_TOP, wxScrollEventHandler( DIALOG_COLOR_PICKER_BASE::OnChangeBrightness ), NULL, this );
|
||||
|
||||
+1767
-1752
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
|
||||
// C++ code generated with wxFormBuilder (version 4.1.0-0-g733bf3d)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@@ -81,6 +81,7 @@ class DIALOG_COLOR_PICKER_BASE : public DIALOG_SHIM
|
||||
virtual void OnChangeEditBlue( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void onHSVMouseClick( wxMouseEvent& event ) { event.Skip(); }
|
||||
virtual void onHSVMouseDrag( wxMouseEvent& event ) { event.Skip(); }
|
||||
virtual void onSize( wxSizeEvent& event ) { event.Skip(); }
|
||||
virtual void OnChangeEditHue( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void OnChangeEditSat( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void OnChangeBrightness( wxScrollEvent& event ) { event.Skip(); }
|
||||
|
||||
+11
-3
@@ -2070,9 +2070,17 @@ static struct EDA_SHAPE_DESC
|
||||
shapeProps )
|
||||
.SetAvailableFunc( fillAvailable );
|
||||
|
||||
propMgr.AddProperty( new PROPERTY<EDA_SHAPE, COLOR4D>( _HKI( "Fill Color" ),
|
||||
&EDA_SHAPE::SetFillColor, &EDA_SHAPE::GetFillColor ),
|
||||
shapeProps )
|
||||
auto fillColor = new PROPERTY<EDA_SHAPE, COLOR4D>( _HKI( "Fill Color" ),
|
||||
&EDA_SHAPE::SetFillColor, &EDA_SHAPE::GetFillColor );
|
||||
fillColor->SetWriteableFunc(
|
||||
[=]( INSPECTABLE* aItem ) -> bool
|
||||
{
|
||||
if( EDA_SHAPE* edaShape = dynamic_cast<EDA_SHAPE*>( aItem ) )
|
||||
return edaShape->GetFillMode() == FILL_T::FILLED_WITH_COLOR;
|
||||
|
||||
return true;
|
||||
} );
|
||||
propMgr.AddProperty( fillColor, shapeProps )
|
||||
.SetAvailableFunc( fillAvailable )
|
||||
.SetIsHiddenFromRulesEditor();
|
||||
}
|
||||
|
||||
+50
-4
@@ -212,6 +212,26 @@ void EDA_TEXT::SetTextAngle( const EDA_ANGLE& aAngle )
|
||||
|
||||
|
||||
void EDA_TEXT::SetItalic( bool aItalic )
|
||||
{
|
||||
if( m_attributes.m_Italic != aItalic )
|
||||
{
|
||||
const KIFONT::FONT* font = GetFont();
|
||||
|
||||
if( !font || font->IsStroke() )
|
||||
{
|
||||
// For stroke fonts, just need to set the attribute.
|
||||
}
|
||||
else
|
||||
{
|
||||
// For outline fonts, italic-ness is determined by the font itself.
|
||||
SetFont( KIFONT::FONT::GetFont( font->GetName(), IsBold(), aItalic ) );
|
||||
}
|
||||
}
|
||||
|
||||
SetItalicFlag( aItalic );
|
||||
}
|
||||
|
||||
void EDA_TEXT::SetItalicFlag( bool aItalic )
|
||||
{
|
||||
m_attributes.m_Italic = aItalic;
|
||||
ClearRenderCache();
|
||||
@@ -223,12 +243,38 @@ void EDA_TEXT::SetBold( bool aBold )
|
||||
{
|
||||
if( m_attributes.m_Bold != aBold )
|
||||
{
|
||||
int size = std::min( m_attributes.m_Size.x, m_attributes.m_Size.y );
|
||||
const KIFONT::FONT* font = GetFont();
|
||||
|
||||
if( aBold )
|
||||
m_attributes.m_StrokeWidth = GetPenSizeForBold( size );
|
||||
if( !font || font->IsStroke() )
|
||||
{
|
||||
// For stroke fonts, boldness is determined by the pen size.
|
||||
const int size = std::min( m_attributes.m_Size.x, m_attributes.m_Size.y );
|
||||
|
||||
if( aBold )
|
||||
{
|
||||
m_attributes.m_StoredStrokeWidth = m_attributes.m_StrokeWidth;
|
||||
m_attributes.m_StrokeWidth = GetPenSizeForBold( size );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Restore the original stroke width from `m_StoredStrokeWidth` if it was previously stored,
|
||||
// resetting the width after unbolding.
|
||||
if( m_attributes.m_StoredStrokeWidth )
|
||||
m_attributes.m_StrokeWidth = m_attributes.m_StoredStrokeWidth;
|
||||
else
|
||||
{
|
||||
m_attributes.m_StrokeWidth = GetPenSizeForNormal( size );
|
||||
// Sets `m_StrokeWidth` to the normal pen size and stores it in `m_StoredStrokeWidth`
|
||||
// as the default, but only if the bold option was applied before this feature was implemented.
|
||||
m_attributes.m_StoredStrokeWidth = m_attributes.m_StrokeWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
m_attributes.m_StrokeWidth = GetPenSizeForNormal( size );
|
||||
{
|
||||
// For outline fonts, boldness is determined by the font itself.
|
||||
SetFont( KIFONT::FONT::GetFont( font->GetName(), aBold, IsItalic() ) );
|
||||
}
|
||||
}
|
||||
|
||||
SetBoldFlag( aBold );
|
||||
|
||||
@@ -452,6 +452,8 @@ VECTOR2I OUTLINE_FONT::getTextAsGlyphsUnlocked( BOX2I* aBBox,
|
||||
|
||||
for( SHAPE_LINE_CHAIN& hole : holes )
|
||||
{
|
||||
bool added_hole = false;
|
||||
|
||||
if( hole.PointCount() )
|
||||
{
|
||||
for( int ii = 0; ii < glyph->OutlineCount(); ++ii )
|
||||
@@ -459,9 +461,15 @@ VECTOR2I OUTLINE_FONT::getTextAsGlyphsUnlocked( BOX2I* aBBox,
|
||||
if( glyph->Outline( ii ).PointInside( hole.GetPoint( 0 ) ) )
|
||||
{
|
||||
glyph->AddHole( std::move( hole ), ii );
|
||||
added_hole = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Some lovely TTF fonts decided that winding didn't matter for outlines that
|
||||
// don't have holes, so holes that don't fit in any outline are added as outlines
|
||||
if( !added_hole )
|
||||
glyph->AddOutline( std::move( hole ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,8 @@ TEXT_ATTRIBUTES::TEXT_ATTRIBUTES( KIFONT::FONT* aFont ) :
|
||||
m_Visible( true ),
|
||||
m_Mirrored( false ),
|
||||
m_Multiline( true ),
|
||||
m_KeepUpright( false )
|
||||
m_KeepUpright( false ),
|
||||
m_StoredStrokeWidth( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
+16
-1
@@ -693,7 +693,14 @@ void GRID_TRICKS::paste_clipboard()
|
||||
|
||||
wxTheClipboard->GetData( data );
|
||||
|
||||
paste_text( data.GetText() );
|
||||
wxString text = data.GetText();
|
||||
|
||||
#ifdef __WXMAC__
|
||||
// Some editors use windows linefeeds (\r\n), which wx re-writes to \n\n
|
||||
text.Replace( "\n\n", "\n" );
|
||||
#endif
|
||||
|
||||
paste_text( text );
|
||||
}
|
||||
|
||||
wxTheClipboard->Close();
|
||||
@@ -802,6 +809,14 @@ void GRID_TRICKS::paste_text( const wxString& cb_text )
|
||||
{
|
||||
tbl->SetValue( row, col, cellTxt );
|
||||
|
||||
wxGridEvent evt( m_grid->GetId(), wxEVT_GRID_CELL_CHANGED, m_grid, row, col );
|
||||
m_grid->GetEventHandler()->ProcessEvent( evt );
|
||||
}
|
||||
// Allow paste to any cell that can accept a boolean value
|
||||
else if( tbl->CanSetValueAs( row, col, wxGRID_VALUE_BOOL ) )
|
||||
{
|
||||
tbl->SetValueAsBool( row, col, cellTxt == wxT( "1" ) );
|
||||
|
||||
wxGridEvent evt( m_grid->GetId(), wxEVT_GRID_CELL_CHANGED, m_grid, row, col );
|
||||
m_grid->GetEventHandler()->ProcessEvent( evt );
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ DXF_IMPORT_PLUGIN::DXF_IMPORT_PLUGIN() : DL_CreationAdapter()
|
||||
m_brdLayer = Dwgs_User; // The default import layer
|
||||
m_importAsFPShapes = true;
|
||||
m_minX = m_minY = std::numeric_limits<double>::max();
|
||||
m_maxX = m_maxY = std::numeric_limits<double>::min();
|
||||
m_maxX = m_maxY = std::numeric_limits<double>::lowest();
|
||||
m_currentUnit = DXF_IMPORT_UNITS::DEFAULT;
|
||||
|
||||
m_importCoordinatePrecision = 4; // initial value per dxf spec
|
||||
@@ -131,7 +131,7 @@ bool DXF_IMPORT_PLUGIN::Load( const wxString& aFileName )
|
||||
|
||||
m_internalImporter.ClearShapes();
|
||||
|
||||
reportMsg( _( "Memory was exhausted trying to load the DXF, it may be too large." ) );
|
||||
ReportMsg( _( "Memory was exhausted trying to load the DXF, it may be too large." ) );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -151,7 +151,7 @@ bool DXF_IMPORT_PLUGIN::LoadFromMemory( const wxMemoryBuffer& aMemBuffer )
|
||||
|
||||
m_internalImporter.ClearShapes();
|
||||
|
||||
reportMsg( _( "Memory was exhausted trying to load the DXF, it may be too large." ) );
|
||||
ReportMsg( _( "Memory was exhausted trying to load the DXF, it may be too large." ) );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -247,7 +247,7 @@ bool DXF_IMPORT_PLUGIN::ImportDxfFile( const wxMemoryBuffer& aMemBuffer )
|
||||
}
|
||||
|
||||
|
||||
void DXF_IMPORT_PLUGIN::reportMsg( const wxString& aMessage )
|
||||
void DXF_IMPORT_PLUGIN::ReportMsg( const wxString& aMessage )
|
||||
{
|
||||
// Add message to keep trace of not handled dxf entities
|
||||
m_messages += aMessage;
|
||||
@@ -1411,8 +1411,8 @@ void DXF_IMPORT_PLUGIN::insertSpline( double aWidth )
|
||||
ctrlp.push_back( m_curr_entity.m_SplineControlPointList[ii].m_y );
|
||||
}
|
||||
|
||||
std::vector<double> coords;
|
||||
tinyspline::BSpline beziers;
|
||||
std::vector<double> coords;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -1421,15 +1421,18 @@ void DXF_IMPORT_PLUGIN::insertSpline( double aWidth )
|
||||
|
||||
dxfspline.setControlPoints( ctrlp );
|
||||
dxfspline.setKnots( m_curr_entity.m_SplineKnotsList );
|
||||
beziers = tinyspline::BSpline( dxfspline.toBeziers() );
|
||||
|
||||
if( dxfspline.degree() < 3 )
|
||||
dxfspline = dxfspline.elevateDegree( 3 - dxfspline.degree() );
|
||||
|
||||
beziers = dxfspline.toBeziers();
|
||||
coords = beziers.controlPoints();
|
||||
}
|
||||
catch( const std::runtime_error& ) // tinyspline throws everything including data validation
|
||||
// as runtime errors
|
||||
{
|
||||
// invalid spline definition, drop this block
|
||||
reportMsg( _( "Invalid spline definition encountered" ) );
|
||||
ReportMsg( _( "Invalid spline definition encountered" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1446,14 +1449,14 @@ void DXF_IMPORT_PLUGIN::insertSpline( double aWidth )
|
||||
// not sure why this happens, but it seems to sometimes slip degree on the final bezier
|
||||
VECTOR2D bezierControl2;
|
||||
|
||||
if( ii + 4 >= coords.size() )
|
||||
if( ii + 5 >= coords.size() )
|
||||
bezierControl2 = bezierControl1;
|
||||
else
|
||||
bezierControl2 = VECTOR2D( mapX( coords[ii + 4] ), mapY( coords[ii + 5] ) );
|
||||
|
||||
VECTOR2D end;
|
||||
|
||||
if( ii + 6 >= coords.size() )
|
||||
if( ii + 7 >= coords.size() )
|
||||
end = bezierControl2;
|
||||
else
|
||||
end = VECTOR2D( mapX( coords[ii + 6] ), mapY( coords[ii + 7] ) );
|
||||
|
||||
@@ -320,10 +320,10 @@ public:
|
||||
{
|
||||
return m_messages;
|
||||
}
|
||||
// report message to keep trace of not supported dxf entities:
|
||||
void ReportMsg( const wxString& aMessage ) override;
|
||||
|
||||
private:
|
||||
// report message to keep trace of not supported dxf entities:
|
||||
void reportMsg( const wxString& aMessage );
|
||||
|
||||
// coordinate conversions from dxf file to mm
|
||||
double mapX( double aDxfCoordX );
|
||||
@@ -455,77 +455,77 @@ private:
|
||||
// Not yet handled DXF entities:
|
||||
virtual void addXLine( const DL_XLineData& ) override
|
||||
{
|
||||
reportMsg( _( "DXF construction lines not currently supported." ) );
|
||||
ReportMsg( _( "DXF construction lines not currently supported." ) );
|
||||
}
|
||||
virtual void addRay( const DL_RayData& ) override
|
||||
{
|
||||
reportMsg( _( "DXF construction lines not currently supported." ) );
|
||||
ReportMsg( _( "DXF construction lines not currently supported." ) );
|
||||
}
|
||||
|
||||
virtual void addArcAlignedText( const DL_ArcAlignedTextData& ) override
|
||||
{
|
||||
reportMsg( _( "DXF arc-aligned text not currently supported." ) );
|
||||
ReportMsg( _( "DXF arc-aligned text not currently supported." ) );
|
||||
}
|
||||
|
||||
virtual void addDimAlign( const DL_DimensionData&, const DL_DimAlignedData& ) override
|
||||
{
|
||||
reportMsg( _( "DXF dimensions not currently supported." ) );
|
||||
ReportMsg( _( "DXF dimensions not currently supported." ) );
|
||||
}
|
||||
virtual void addDimLinear( const DL_DimensionData&, const DL_DimLinearData& ) override
|
||||
{
|
||||
reportMsg( _( "DXF dimensions not currently supported." ) );
|
||||
ReportMsg( _( "DXF dimensions not currently supported." ) );
|
||||
}
|
||||
virtual void addDimRadial( const DL_DimensionData&, const DL_DimRadialData& ) override
|
||||
{
|
||||
reportMsg( _( "DXF dimensions not currently supported." ) );
|
||||
ReportMsg( _( "DXF dimensions not currently supported." ) );
|
||||
}
|
||||
virtual void addDimDiametric( const DL_DimensionData&, const DL_DimDiametricData& ) override
|
||||
{
|
||||
reportMsg( _( "DXF dimensions not currently supported." ) );
|
||||
ReportMsg( _( "DXF dimensions not currently supported." ) );
|
||||
}
|
||||
virtual void addDimAngular( const DL_DimensionData&, const DL_DimAngular2LData& ) override
|
||||
{
|
||||
reportMsg( _( "DXF dimensions not currently supported." ) );
|
||||
ReportMsg( _( "DXF dimensions not currently supported." ) );
|
||||
}
|
||||
virtual void addDimAngular3P( const DL_DimensionData&, const DL_DimAngular3PData& ) override
|
||||
{
|
||||
reportMsg( _( "DXF dimensions not currently supported." ) );
|
||||
ReportMsg( _( "DXF dimensions not currently supported." ) );
|
||||
}
|
||||
virtual void addDimOrdinate( const DL_DimensionData&, const DL_DimOrdinateData& ) override
|
||||
{
|
||||
reportMsg( _( "DXF dimensions not currently supported." ) );
|
||||
ReportMsg( _( "DXF dimensions not currently supported." ) );
|
||||
}
|
||||
virtual void addLeader( const DL_LeaderData& ) override
|
||||
{
|
||||
reportMsg( _( "DXF dimensions not currently supported." ) );
|
||||
ReportMsg( _( "DXF dimensions not currently supported." ) );
|
||||
}
|
||||
virtual void addLeaderVertex( const DL_LeaderVertexData& ) override { }
|
||||
|
||||
virtual void addHatch( const DL_HatchData& ) override
|
||||
{
|
||||
reportMsg( _( "DXF hatches not currently supported." ) );
|
||||
ReportMsg( _( "DXF hatches not currently supported." ) );
|
||||
}
|
||||
virtual void addHatchLoop( const DL_HatchLoopData& ) override { }
|
||||
virtual void addHatchEdge( const DL_HatchEdgeData& ) override { }
|
||||
|
||||
virtual void addTrace( const DL_TraceData& ) override
|
||||
{
|
||||
reportMsg( _( "DXF traces not currently supported." ) );
|
||||
ReportMsg( _( "DXF traces not currently supported." ) );
|
||||
}
|
||||
|
||||
virtual void add3dFace( const DL_3dFaceData& ) override
|
||||
{
|
||||
reportMsg( _( "DXF 3dfaces not currently supported." ) );
|
||||
ReportMsg( _( "DXF 3dfaces not currently supported." ) );
|
||||
}
|
||||
|
||||
virtual void addSolid( const DL_SolidData& ) override
|
||||
{
|
||||
reportMsg( _( "DXF solids not currently supported." ) );
|
||||
ReportMsg( _( "DXF solids not currently supported." ) );
|
||||
}
|
||||
|
||||
virtual void addImage( const DL_ImageData& ) override
|
||||
{
|
||||
reportMsg( _( "DXF images not currently supported." ) );
|
||||
ReportMsg( _( "DXF images not currently supported." ) );
|
||||
}
|
||||
virtual void linkImage( const DL_ImageDefData& ) override {}
|
||||
|
||||
|
||||
@@ -131,6 +131,8 @@ public:
|
||||
*/
|
||||
const virtual wxString& GetMessages() const = 0;
|
||||
|
||||
virtual void ReportMsg( const wxString& aMessage ) = 0;
|
||||
|
||||
protected:
|
||||
///< Importer used to create objects representing the imported shapes.
|
||||
GRAPHICS_IMPORTER* m_importer;
|
||||
|
||||
@@ -125,6 +125,11 @@ public:
|
||||
return m_plugin->GetMessages();
|
||||
}
|
||||
|
||||
void ReportMsg( const wxString& aMessage )
|
||||
{
|
||||
m_plugin->ReportMsg( aMessage );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get original image Width.
|
||||
*
|
||||
|
||||
@@ -98,6 +98,89 @@ void GRAPHICS_IMPORTER_BUFFER::AddShape( std::unique_ptr<IMPORTED_SHAPE>& aShape
|
||||
|
||||
void GRAPHICS_IMPORTER_BUFFER::ImportTo( GRAPHICS_IMPORTER& aImporter )
|
||||
{
|
||||
BOX2D boundingBox;
|
||||
|
||||
for( std::unique_ptr<IMPORTED_SHAPE>& shape : m_shapes )
|
||||
{
|
||||
BOX2D box = shape->GetBoundingBox();
|
||||
|
||||
if( box.IsValid() )
|
||||
boundingBox.Merge( box );
|
||||
}
|
||||
|
||||
boundingBox.SetOrigin( boundingBox.GetPosition().x * aImporter.GetScale().x,
|
||||
boundingBox.GetPosition().y * aImporter.GetScale().y );
|
||||
boundingBox.SetSize( boundingBox.GetSize().x * aImporter.GetScale().x,
|
||||
boundingBox.GetSize().y * aImporter.GetScale().y );
|
||||
|
||||
// Check that the scaled graphics fit in the KiCad numeric limits
|
||||
if( boundingBox.GetSize().x * aImporter.GetMillimeterToIuFactor() > std::numeric_limits<int>::max() ||
|
||||
boundingBox.GetSize().y * aImporter.GetMillimeterToIuFactor() > std::numeric_limits<int>::max() )
|
||||
{
|
||||
double scale_factor = std::numeric_limits<int>::max() / ( aImporter.GetMillimeterToIuFactor() + 100 );
|
||||
double max_scale = std::max( scale_factor / boundingBox.GetSize().x,
|
||||
scale_factor / boundingBox.GetSize().y );
|
||||
aImporter.ReportMsg( wxString::Format( _( "Imported graphic is too large. Maximum scale is %f" ),
|
||||
max_scale ) );
|
||||
return;
|
||||
}
|
||||
// They haven't set the import offset, so we set it to the bounding box origin to keep the graphics
|
||||
// in the KiCad drawing area
|
||||
else if( aImporter.GetImportOffsetMM() == VECTOR2D( 0, 0 ) )
|
||||
{
|
||||
VECTOR2D offset = boundingBox.GetOrigin();
|
||||
aImporter.SetImportOffsetMM( -offset );
|
||||
}
|
||||
else
|
||||
{
|
||||
VECTOR2D bbox_origin = boundingBox.GetOrigin();
|
||||
aImporter.SetImportOffsetMM( -bbox_origin + aImporter.GetImportOffsetMM() );
|
||||
|
||||
double total_scale_x = aImporter.GetScale().x * aImporter.GetMillimeterToIuFactor();
|
||||
double total_scale_y = aImporter.GetScale().y * aImporter.GetMillimeterToIuFactor();
|
||||
|
||||
double max_offset_x =
|
||||
( aImporter.GetImportOffsetMM().x + boundingBox.GetRight() ) * total_scale_x;
|
||||
double max_offset_y =
|
||||
( aImporter.GetImportOffsetMM().y + boundingBox.GetBottom() ) * total_scale_y;
|
||||
double min_offset_x =
|
||||
( aImporter.GetImportOffsetMM().x + boundingBox.GetLeft() ) * total_scale_x;
|
||||
double min_offset_y =
|
||||
( aImporter.GetImportOffsetMM().y + boundingBox.GetTop() ) * total_scale_y;
|
||||
|
||||
VECTOR2D newOffset = aImporter.GetImportOffsetMM();
|
||||
bool needsAdjustment = false;
|
||||
|
||||
if( max_offset_x >= std::numeric_limits<int>::max() )
|
||||
{
|
||||
newOffset.x -= ( max_offset_x - std::numeric_limits<int>::max() + 100.0 ) / total_scale_x;
|
||||
needsAdjustment = true;
|
||||
}
|
||||
else if( min_offset_x <= std::numeric_limits<int>::min() )
|
||||
{
|
||||
newOffset.x -= ( min_offset_x - std::numeric_limits<int>::min() - 100 ) / total_scale_x;
|
||||
needsAdjustment = true;
|
||||
}
|
||||
|
||||
if( max_offset_y >= std::numeric_limits<int>::max() )
|
||||
{
|
||||
newOffset.y -= ( max_offset_y - std::numeric_limits<int>::max() + 100 ) / total_scale_y;
|
||||
needsAdjustment = true;
|
||||
}
|
||||
else if( min_offset_y <= std::numeric_limits<int>::min() )
|
||||
{
|
||||
newOffset.y -= ( min_offset_y - std::numeric_limits<int>::min() - 100 ) / total_scale_y;
|
||||
needsAdjustment = true;
|
||||
}
|
||||
|
||||
if( needsAdjustment )
|
||||
{
|
||||
aImporter.ReportMsg( wxString::Format( _( "Import offset adjusted to (%f, %f) to fit within numeric limits" ),
|
||||
newOffset.x, newOffset.y ) );
|
||||
aImporter.SetImportOffsetMM( newOffset );
|
||||
}
|
||||
}
|
||||
|
||||
for( std::unique_ptr<IMPORTED_SHAPE>& shape : m_shapes )
|
||||
shape->ImportTo( aImporter );
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "graphics_importer.h"
|
||||
|
||||
#include <math/matrix3x3.h>
|
||||
#include <math/box2.h>
|
||||
#include <list>
|
||||
|
||||
|
||||
@@ -46,6 +47,8 @@ public:
|
||||
void SetParentShapeIndex( int aIndex ) { m_parentShapeIndex = aIndex; }
|
||||
int GetParentShapeIndex() const { return m_parentShapeIndex; }
|
||||
|
||||
virtual BOX2D GetBoundingBox() const = 0;
|
||||
|
||||
protected:
|
||||
int m_parentShapeIndex = -1;
|
||||
};
|
||||
@@ -75,6 +78,14 @@ public:
|
||||
m_end = aTransform * m_end + aTranslation;
|
||||
}
|
||||
|
||||
BOX2D GetBoundingBox() const override
|
||||
{
|
||||
BOX2D box;
|
||||
box.Merge( m_start );
|
||||
box.Merge( m_end );
|
||||
return box;
|
||||
}
|
||||
|
||||
private:
|
||||
VECTOR2D m_start;
|
||||
VECTOR2D m_end;
|
||||
@@ -113,6 +124,14 @@ public:
|
||||
m_radius = newRadius.EuclideanNorm();
|
||||
}
|
||||
|
||||
BOX2D GetBoundingBox() const override
|
||||
{
|
||||
BOX2D box;
|
||||
box.Merge( m_center - VECTOR2D( m_radius, m_radius ) );
|
||||
box.Merge( m_center + VECTOR2D( m_radius, m_radius ) );
|
||||
return box;
|
||||
}
|
||||
|
||||
private:
|
||||
VECTOR2D m_center;
|
||||
double m_radius;
|
||||
@@ -148,6 +167,26 @@ public:
|
||||
m_center = aTransform * m_center + aTranslation;
|
||||
}
|
||||
|
||||
BOX2D GetBoundingBox() const override
|
||||
{
|
||||
BOX2D box;
|
||||
|
||||
box.Merge( m_start + m_stroke.GetWidth() );
|
||||
box.Merge( m_start - m_stroke.GetWidth() );
|
||||
|
||||
for( double angle = 0; angle < m_angle.AsDegrees(); angle += 5 )
|
||||
{
|
||||
EDA_ANGLE ang = EDA_ANGLE( angle );
|
||||
VECTOR2D start = m_center + m_start;
|
||||
VECTOR2D pt = {start.x * ang.Cos() + start.y * ang.Sin(),
|
||||
start.x * ang.Sin() - start.y * ang.Cos()};
|
||||
|
||||
box.Merge( pt );
|
||||
}
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
private:
|
||||
VECTOR2D m_center;
|
||||
VECTOR2D m_start;
|
||||
@@ -192,6 +231,16 @@ public:
|
||||
|
||||
const IMPORTED_STROKE& GetStroke() const { return m_stroke; }
|
||||
|
||||
BOX2D GetBoundingBox() const override
|
||||
{
|
||||
BOX2D box;
|
||||
|
||||
for( const VECTOR2D& vert : m_vertices )
|
||||
box.Merge( vert );
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<VECTOR2D> m_vertices;
|
||||
IMPORTED_STROKE m_stroke;
|
||||
@@ -227,6 +276,19 @@ public:
|
||||
void Transform( const MATRIX3x3D& aTransform, const VECTOR2D& aTranslation ) override
|
||||
{
|
||||
m_origin = aTransform * m_origin + aTranslation;
|
||||
|
||||
VECTOR2D textSize = aTransform * VECTOR2D( m_width, m_height );
|
||||
m_width = textSize.x;
|
||||
m_height = textSize.y;
|
||||
}
|
||||
|
||||
BOX2D GetBoundingBox() const override
|
||||
{
|
||||
BOX2D box;
|
||||
box.Merge( m_origin );
|
||||
box.Merge( m_origin + VECTOR2D( m_width * m_text.length(), m_height ) );
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -272,6 +334,14 @@ public:
|
||||
m_end = aTransform * m_end + aTranslation;
|
||||
}
|
||||
|
||||
BOX2D GetBoundingBox() const override
|
||||
{
|
||||
BOX2D box;
|
||||
box.Merge( m_start );
|
||||
box.Merge( m_end );
|
||||
return box;
|
||||
}
|
||||
|
||||
private:
|
||||
VECTOR2D m_start;
|
||||
VECTOR2D m_bezierControl1;
|
||||
|
||||
@@ -426,3 +426,11 @@ static float distanceFromPointToLine( const VECTOR2D& aPoint, const VECTOR2D& aL
|
||||
|
||||
return fabs( distance );
|
||||
}
|
||||
|
||||
|
||||
void SVG_IMPORT_PLUGIN::ReportMsg( const wxString& aMessage )
|
||||
{
|
||||
// Add message to keep trace of not handled svg entities
|
||||
m_messages += aMessage;
|
||||
m_messages += '\n';
|
||||
}
|
||||
@@ -62,6 +62,8 @@ public:
|
||||
return m_messages;
|
||||
}
|
||||
|
||||
void ReportMsg( const wxString& aMessage ) override;
|
||||
|
||||
bool Import() override;
|
||||
bool Load( const wxString& aFileName ) override;
|
||||
bool LoadFromMemory( const wxMemoryBuffer& aMemBuffer ) override;
|
||||
|
||||
@@ -307,3 +307,20 @@ EASYEDAPRO::ParseJsonLinesWithSeparation( wxInputStream& aInput, const wxString&
|
||||
|
||||
return lineBlocks;
|
||||
}
|
||||
|
||||
|
||||
std::map<wxString, wxString>
|
||||
EASYEDAPRO::AnyMapToStringMap( const std::map<wxString, nlohmann::json>& aInput )
|
||||
{
|
||||
std::map<wxString, wxString> stringMap;
|
||||
|
||||
for( auto& [key, value] : aInput )
|
||||
{
|
||||
if( value.is_string() )
|
||||
stringMap[key] = value.get<wxString>();
|
||||
else if( value.is_number() )
|
||||
stringMap[key] = wxString::FromCDouble( value.get<double>() );
|
||||
}
|
||||
|
||||
return stringMap;
|
||||
}
|
||||
|
||||
@@ -63,6 +63,8 @@ std::vector<nlohmann::json> ParseJsonLines( wxInputStream& aInput, const wxStrin
|
||||
std::vector<std::vector<nlohmann::json>> ParseJsonLinesWithSeparation( wxInputStream& aInput,
|
||||
const wxString& aSource );
|
||||
|
||||
std::map<wxString, wxString> AnyMapToStringMap( const std::map<wxString, nlohmann::json>& aInput );
|
||||
|
||||
} // namespace EASYEDAPRO
|
||||
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <core/json_serializers.h>
|
||||
#include <string_utils.h>
|
||||
#include <io/easyedapro/easyedapro_import_utils.h>
|
||||
|
||||
|
||||
void EASYEDAPRO::from_json( const nlohmann::json& j, EASYEDAPRO::SCH_ATTR& d )
|
||||
@@ -273,7 +274,7 @@ void EASYEDAPRO::from_json( const nlohmann::json& j, EASYEDAPRO::PRJ_DEVICE& d )
|
||||
d.custom_tags = j.at( "custom_tags" );
|
||||
|
||||
if( j.at( "attributes" ).is_object() )
|
||||
d.attributes = j.at( "attributes" );
|
||||
d.attributes = AnyMapToStringMap( j.at( "attributes" ) );
|
||||
}
|
||||
|
||||
void EASYEDAPRO::from_json( const nlohmann::json& j, EASYEDAPRO::BLOB& d )
|
||||
|
||||
@@ -273,7 +273,7 @@ NUMERIC_EVALUATOR::Token NUMERIC_EVALUATOR::getToken()
|
||||
}
|
||||
|
||||
ch = m_token.input[ ++m_token.pos ];
|
||||
} while( isdigit( ch ) || isDecimalSeparator( ch ) );
|
||||
} while( isdigit( (unsigned char) ch ) || isDecimalSeparator( ch ) );
|
||||
|
||||
m_token.token[ idx ] = 0;
|
||||
};
|
||||
@@ -373,7 +373,7 @@ NUMERIC_EVALUATOR::Token NUMERIC_EVALUATOR::getToken()
|
||||
{
|
||||
/* End of input */
|
||||
}
|
||||
else if( isdigit( ch ) || isDecimalSeparator( ch ) )
|
||||
else if( isdigit( (unsigned char) ch ) || isDecimalSeparator( ch ) )
|
||||
{
|
||||
// VALUE
|
||||
extractNumber( &siScaler );
|
||||
|
||||
@@ -491,8 +491,15 @@ bool PGM_BASE::InitPgm( bool aHeadless, bool aSkipPyInit, bool aIsUnitTest )
|
||||
}
|
||||
#endif
|
||||
|
||||
// Ensure the instance checker directory exists
|
||||
// It should be globally writable because it is shared between all users on Linux, and so on a
|
||||
// multi-user machine, other need to be able to access it to check for the lock files or make
|
||||
// their own lock files.
|
||||
wxString instanceCheckerDir = PATHS::GetInstanceCheckerPath();
|
||||
PATHS::EnsurePathExists( instanceCheckerDir );
|
||||
wxChmod( instanceCheckerDir, wxPOSIX_USER_READ | wxPOSIX_USER_WRITE | wxPOSIX_USER_EXECUTE |
|
||||
wxPOSIX_GROUP_READ | wxPOSIX_GROUP_WRITE | wxPOSIX_GROUP_EXECUTE |
|
||||
wxPOSIX_OTHERS_READ | wxPOSIX_OTHERS_WRITE | wxPOSIX_OTHERS_EXECUTE );
|
||||
|
||||
wxString instanceCheckerName = wxString::Format( wxS( "%s-%s" ), pgm_name,
|
||||
GetMajorMinorVersion() );
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 1992-2012 Lorenzo Marcantonio, l.marcantonio@logossrl.com
|
||||
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2023, 2024 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
|
||||
@@ -37,7 +37,8 @@
|
||||
#include <wx/datstrm.h>
|
||||
|
||||
#include <advanced_config.h>
|
||||
#include <eda_text.h> // for IsGotoPageHref
|
||||
#include <common.h> // ResolveUriByEnvVars
|
||||
#include <eda_text.h> // for IsGotoPageHref
|
||||
#include <font/font.h>
|
||||
#include <core/ignore.h>
|
||||
#include <macros.h>
|
||||
@@ -400,12 +401,12 @@ void PDF_PLOTTER::PlotPoly( const std::vector<VECTOR2I>& aCornerList, FILL_T aFi
|
||||
SetCurrentLineWidth( aWidth );
|
||||
|
||||
VECTOR2D pos = userToDeviceCoordinates( aCornerList[0] );
|
||||
fprintf( m_workFile, "%g %g m\n", pos.x, pos.y );
|
||||
fprintf( m_workFile, "%f %f m\n", pos.x, pos.y );
|
||||
|
||||
for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
|
||||
{
|
||||
pos = userToDeviceCoordinates( aCornerList[ii] );
|
||||
fprintf( m_workFile, "%g %g l\n", pos.x, pos.y );
|
||||
fprintf( m_workFile, "%f %f l\n", pos.x, pos.y );
|
||||
}
|
||||
|
||||
// Close path and stroke and/or fill
|
||||
@@ -438,7 +439,7 @@ void PDF_PLOTTER::PenTo( const VECTOR2I& pos, char plume )
|
||||
if( m_penState != plume || pos != m_penLastpos )
|
||||
{
|
||||
VECTOR2D pos_dev = userToDeviceCoordinates( pos );
|
||||
fprintf( m_workFile, "%g %g %c\n",
|
||||
fprintf( m_workFile, "%f %f %c\n",
|
||||
pos_dev.x, pos_dev.y,
|
||||
( plume=='D' ) ? 'l' : 'm' );
|
||||
}
|
||||
@@ -1332,16 +1333,35 @@ bool PDF_PLOTTER::EndPlot()
|
||||
{
|
||||
wxString href = property.substr( property.Find( "http:" ) );
|
||||
|
||||
if( m_project )
|
||||
href = ResolveUriByEnvVars( href, m_project );
|
||||
|
||||
js += wxString::Format( wxT( "[\"%s\", \"%s\"],\n" ),
|
||||
EscapeString( property, CTX_JS_STR ),
|
||||
EscapeString( href, CTX_JS_STR ),
|
||||
EscapeString( href, CTX_JS_STR ) );
|
||||
}
|
||||
else if( property.Find( "https:" ) >= 0 )
|
||||
{
|
||||
wxString href = property.substr( property.Find( "https:" ) );
|
||||
|
||||
if( m_project )
|
||||
href = ResolveUriByEnvVars( href, m_project );
|
||||
|
||||
js += wxString::Format( wxT( "[\"%s\", \"%s\"],\n" ),
|
||||
EscapeString( property, CTX_JS_STR ),
|
||||
EscapeString( href, CTX_JS_STR ),
|
||||
EscapeString( href, CTX_JS_STR ) );
|
||||
}
|
||||
else if( property.Find( "file:" ) >= 0 )
|
||||
{
|
||||
wxString href = property.substr( property.Find( "file:" ) );
|
||||
|
||||
if( m_project )
|
||||
href = ResolveUriByEnvVars( href, m_project );
|
||||
|
||||
href = NormalizeFileUri( href );
|
||||
|
||||
js += wxString::Format( wxT( "[\"%s\", \"%s\"],\n" ),
|
||||
EscapeString( href, CTX_JS_STR ),
|
||||
EscapeString( href, CTX_JS_STR ) );
|
||||
}
|
||||
else
|
||||
@@ -1367,13 +1387,22 @@ bool PDF_PLOTTER::EndPlot()
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( url.StartsWith( "http:" ) || url.StartsWith( "https:" ) )
|
||||
else if( url.StartsWith( "http:" ) || url.StartsWith( "https:" )
|
||||
|| url.StartsWith( "file:" ) )
|
||||
{
|
||||
wxString menuText = wxString::Format( _( "Open %s" ), url );
|
||||
wxString href = url;
|
||||
|
||||
if( m_project )
|
||||
href = ResolveUriByEnvVars( url, m_project );
|
||||
|
||||
if( url.StartsWith( "file:" ) )
|
||||
href = NormalizeFileUri( href );
|
||||
|
||||
wxString menuText = wxString::Format( _( "Open %s" ), href );
|
||||
|
||||
js += wxString::Format( wxT( "[\"%s\", \"%s\"],\n" ),
|
||||
EscapeString( menuText, CTX_JS_STR ),
|
||||
EscapeString( url, CTX_JS_STR ) );
|
||||
EscapeString( href, CTX_JS_STR ),
|
||||
EscapeString( href, CTX_JS_STR ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1413,6 +1442,7 @@ function ShM(aEntries) {
|
||||
var cChoice = app.popUpMenuEx.apply(app, aParams);
|
||||
if (cChoice != null && cChoice.substring(0, 1) == '#') this.pageNum = parseInt(cChoice.slice(1));
|
||||
else if (cChoice != null && cChoice.substring(0, 4) == 'http') app.launchURL(cChoice);
|
||||
else if (cChoice != null && cChoice.substring(0, 4) == 'file') app.openDoc(cChoice.substring(7));
|
||||
}
|
||||
)JS";
|
||||
|
||||
@@ -1634,7 +1664,7 @@ void PDF_PLOTTER::Text( const VECTOR2I& aPos,
|
||||
coordinate system will be used for the overlining. Also the %f
|
||||
for the trig part of the matrix to avoid %g going in exponential
|
||||
format (which is not supported) */
|
||||
fprintf( m_workFile, "q %f %f %f %f %g %g cm BT %s %g Tf %d Tr %g Tz ",
|
||||
fprintf( m_workFile, "q %f %f %f %f %f %f cm BT %s %g Tf %d Tr %g Tz ",
|
||||
ctm_a, ctm_b, ctm_c, ctm_d, ctm_e, ctm_f,
|
||||
fontname, heightFactor, render_mode, wideningFactor * 100 );
|
||||
|
||||
|
||||
@@ -162,7 +162,8 @@ static wxString XmlEsc( const wxString& aStr, bool isAttribute = false )
|
||||
}
|
||||
|
||||
|
||||
SVG_PLOTTER::SVG_PLOTTER()
|
||||
SVG_PLOTTER::SVG_PLOTTER( const PROJECT* aProject ) :
|
||||
PSLIKE_PLOTTER( aProject )
|
||||
{
|
||||
m_graphics_changed = true;
|
||||
SetTextMode( PLOT_TEXT_MODE::STROKE );
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* 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) 2017-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2017-2023, 2024 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
|
||||
@@ -44,7 +44,8 @@
|
||||
#include <callback_gal.h>
|
||||
#include <math/util.h> // for KiROUND
|
||||
|
||||
PLOTTER::PLOTTER( )
|
||||
PLOTTER::PLOTTER( const PROJECT* aProject ) :
|
||||
m_project( aProject )
|
||||
{
|
||||
m_plotScale = 1;
|
||||
m_currentPenWidth = -1; // To-be-set marker
|
||||
|
||||
@@ -116,7 +116,7 @@ COMMON_SETTINGS::COMMON_SETTINGS() :
|
||||
m_params.emplace_back( new PARAM<int>( "auto_backup.min_interval",
|
||||
&m_Backup.min_interval, 300 ) );
|
||||
|
||||
m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "environment.vars",
|
||||
auto envVarsParam = m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "environment.vars",
|
||||
[&]() -> nlohmann::json
|
||||
{
|
||||
nlohmann::json ret = {};
|
||||
@@ -212,6 +212,7 @@ COMMON_SETTINGS::COMMON_SETTINGS() :
|
||||
}
|
||||
},
|
||||
{} ) );
|
||||
envVarsParam->SetClearUnknownKeys();
|
||||
|
||||
m_params.emplace_back( new PARAM<bool>( "input.focus_follow_sch_pcb",
|
||||
&m_Input.focus_follow_sch_pcb, false ) );
|
||||
|
||||
@@ -75,6 +75,7 @@ JSON_SETTINGS::JSON_SETTINGS( const wxString& aFilename, SETTINGS_LOC aLocation,
|
||||
m_createIfMissing( aCreateIfMissing ),
|
||||
m_createIfDefault( aCreateIfDefault ),
|
||||
m_writeFile( aWriteFile ),
|
||||
m_modified( false ),
|
||||
m_deleteLegacyAfterMigration( true ),
|
||||
m_resetParamsIfMissing( true ),
|
||||
m_schemaVersion( aSchemaVersion ),
|
||||
@@ -353,6 +354,8 @@ bool JSON_SETTINGS::LoadFromFile( const wxString& aDirectory )
|
||||
wxLogTrace( traceSettings, wxT( "Loaded <%s> with schema %d" ), GetFullFilename(),
|
||||
m_schemaVersion );
|
||||
|
||||
m_modified = false;
|
||||
|
||||
// If we migrated, clean up the legacy file (with no extension)
|
||||
if( m_writeFile && ( legacy_migrated || migrated ) )
|
||||
{
|
||||
@@ -373,15 +376,13 @@ bool JSON_SETTINGS::LoadFromFile( const wxString& aDirectory )
|
||||
|
||||
bool JSON_SETTINGS::Store()
|
||||
{
|
||||
bool modified = false;
|
||||
|
||||
for( PARAM_BASE* param : m_params )
|
||||
{
|
||||
modified |= !param->MatchesFile( this );
|
||||
m_modified |= !param->MatchesFile( this );
|
||||
param->Store( this );
|
||||
}
|
||||
|
||||
return modified;
|
||||
return m_modified;
|
||||
}
|
||||
|
||||
|
||||
@@ -469,10 +470,12 @@ bool JSON_SETTINGS::SaveToFile( const wxString& aDirectory, bool aForce )
|
||||
|
||||
for( PARAM_BASE* param : m_params )
|
||||
{
|
||||
if( PARAM_WXSTRING_MAP* stringMap = dynamic_cast<PARAM_WXSTRING_MAP*>( param ) )
|
||||
if( param->ClearUnknownKeys() )
|
||||
{
|
||||
if( stringMap->ClearUnknownKeys() )
|
||||
toSave[ stringMap->GetJsonPath() ] = nlohmann::json( {} );
|
||||
nlohmann::json_pointer p
|
||||
= JSON_SETTINGS_INTERNALS::PointerFromString( param->GetJsonPath() );
|
||||
|
||||
toSave[p] = nlohmann::json( {} );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -504,6 +507,9 @@ bool JSON_SETTINGS::SaveToFile( const wxString& aDirectory, bool aForce )
|
||||
success = false;
|
||||
}
|
||||
|
||||
if( success )
|
||||
m_modified = false;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@@ -858,7 +864,7 @@ void JSON_SETTINGS::ReleaseNestedSettings( NESTED_SETTINGS* aSettings )
|
||||
if( it != m_nested_settings.end() )
|
||||
{
|
||||
wxLogTrace( traceSettings, wxT( "Flush and release %s" ), ( *it )->GetFilename() );
|
||||
( *it )->SaveToFile();
|
||||
m_modified |= ( *it )->SaveToFile();
|
||||
m_nested_settings.erase( it );
|
||||
}
|
||||
|
||||
|
||||
+91
-14
@@ -28,11 +28,15 @@
|
||||
|
||||
#include <clocale>
|
||||
#include <cmath>
|
||||
#include <map>
|
||||
#include <core/map_helpers.h>
|
||||
#include <fmt/core.h>
|
||||
#include <macros.h>
|
||||
#include <richio.h> // StrPrintf
|
||||
#include <string_utils.h>
|
||||
#include <wx_filename.h>
|
||||
#include <fmt/chrono.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/regex.h>
|
||||
#include "locale_io.h"
|
||||
|
||||
@@ -45,6 +49,34 @@
|
||||
static const char illegalFileNameChars[] = "\\/:\"<>|*?";
|
||||
|
||||
|
||||
// Checks if a full filename is valid, i.e. does not contains illegal chars
|
||||
bool IsFullFileNameValid( const wxString& aFullFilename )
|
||||
{
|
||||
|
||||
// Test for forbidden chars in aFullFilename.
|
||||
// '\'and '/' are allowed here because aFullFilename can be a full path, and
|
||||
// ':' is allowed on Windows as second char in string.
|
||||
// So remove allowed separators from string to test
|
||||
wxString filtered_fullpath = aFullFilename;
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
// On MSW, the list returned by wxFileName::GetForbiddenChars() contains separators
|
||||
// '\'and '/'
|
||||
filtered_fullpath.Replace( "/", "_" );
|
||||
filtered_fullpath.Replace( "\\", "_" );
|
||||
|
||||
// A disk identifier is allowed, and therefore remove its separator
|
||||
if( filtered_fullpath.Length() > 1 && filtered_fullpath[1] == ':' )
|
||||
filtered_fullpath[1] = ' ';
|
||||
#endif
|
||||
|
||||
if( wxString::npos != filtered_fullpath.find_first_of( wxFileName::GetForbiddenChars() ) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
wxString ConvertToNewOverbarNotation( const wxString& aOldStr )
|
||||
{
|
||||
wxString newStr;
|
||||
@@ -540,22 +572,32 @@ wxString UnescapeHTML( const wxString& aString )
|
||||
{
|
||||
wxString converted = aString;
|
||||
|
||||
converted.Replace( wxS( """ ), wxS( "\"" ) );
|
||||
converted.Replace( wxS( "'" ), wxS( "'" ) );
|
||||
converted.Replace( wxS( "&" ), wxS( "&" ) );
|
||||
converted.Replace( wxS( "<" ), wxS( "<" ) );
|
||||
converted.Replace( wxS( ">" ), wxS( ">" ) );
|
||||
// clang-format off
|
||||
static const std::map<wxString, wxString> c_replacements = {
|
||||
{ wxS( "quot" ), wxS( "\"" ) },
|
||||
{ wxS( "apos" ), wxS( "'" ) },
|
||||
{ wxS( "amp" ), wxS( "&" ) },
|
||||
{ wxS( "lt" ), wxS( "<" ) },
|
||||
{ wxS( "gt" ), wxS( ">" ) }
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
// Yes, &#123; is going to give unexpected results.
|
||||
// Construct regex
|
||||
wxString regexStr = "&(#(\\d*)|#x([a-zA-Z0-9]{4})";
|
||||
|
||||
wxString result;
|
||||
for( auto& [key, value] : c_replacements )
|
||||
regexStr << '|' << key;
|
||||
|
||||
wxRegEx regex( "&#(\\d*);" );
|
||||
regexStr << ");";
|
||||
|
||||
wxRegEx regex( regexStr );
|
||||
|
||||
// Process matches
|
||||
size_t start = 0;
|
||||
size_t len = 0;
|
||||
|
||||
wxString str = aString;
|
||||
wxString result;
|
||||
wxString str = converted;
|
||||
|
||||
while( regex.Matches( str ) )
|
||||
{
|
||||
@@ -564,12 +606,26 @@ wxString UnescapeHTML( const wxString& aString )
|
||||
|
||||
result << str.Left( start );
|
||||
|
||||
unsigned long codeVal = 0;
|
||||
wxString code = regex.GetMatch( str, 1 );
|
||||
code.ToCULong( &codeVal );
|
||||
wxString code = regex.GetMatch( str, 1 );
|
||||
wxString codeDec = regex.GetMatch( str, 2 );
|
||||
wxString codeHex = regex.GetMatch( str, 3 );
|
||||
|
||||
if( codeVal != 0 )
|
||||
result << wxUniChar( codeVal );
|
||||
if( !codeDec.IsEmpty() || !codeHex.IsEmpty() )
|
||||
{
|
||||
unsigned long codeVal = 0;
|
||||
|
||||
if( !codeDec.IsEmpty() )
|
||||
codeDec.ToCULong( &codeVal );
|
||||
else if( !codeHex.IsEmpty() )
|
||||
codeHex.ToCULong( &codeVal, 16 );
|
||||
|
||||
if( codeVal != 0 )
|
||||
result << wxUniChar( codeVal );
|
||||
}
|
||||
else if( auto val = get_opt( c_replacements, code ) )
|
||||
{
|
||||
result << *val;
|
||||
}
|
||||
|
||||
str = str.Mid( start + len );
|
||||
}
|
||||
@@ -1400,3 +1456,24 @@ wxString From_UTF8( const std::string& aString )
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
|
||||
wxString NormalizeFileUri( const wxString& aFileUri )
|
||||
{
|
||||
wxString uriPathAndFileName;
|
||||
|
||||
wxCHECK( aFileUri.StartsWith( wxS( "file://" ), &uriPathAndFileName ), aFileUri );
|
||||
|
||||
wxString tmp = uriPathAndFileName;
|
||||
wxString retv = wxS( "file://" );
|
||||
|
||||
tmp.Replace( wxS( "\\" ), wxS( "/" ) );
|
||||
tmp.Replace( wxS( ":" ), wxS( "" ) );
|
||||
|
||||
if( !tmp.IsEmpty() && tmp[0] != '/' )
|
||||
tmp = wxS( "/" ) + tmp;
|
||||
|
||||
retv += tmp;
|
||||
|
||||
return retv;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ ACTION_MANAGER::ACTION_MANAGER( TOOL_MANAGER* aToolManager ) :
|
||||
std::string groupName = "none";
|
||||
|
||||
std::optional<TOOL_ACTION_GROUP> group = action->GetActionGroup();
|
||||
|
||||
|
||||
if( group.has_value() )
|
||||
{
|
||||
groupID = group.value().GetGroupID();
|
||||
@@ -152,19 +152,21 @@ bool ACTION_MANAGER::RunHotKey( int aHotKey ) const
|
||||
// If no luck, try without Shift, to handle keys that require it
|
||||
// e.g. to get ? you need to press Shift+/ without US keyboard layout
|
||||
// Hardcoding ? as Shift+/ is a bad idea, as on another layout you may need to press a
|
||||
// different combination
|
||||
if( it == m_actionHotKeys.end() )
|
||||
// different combination.
|
||||
// This doesn't apply for letters, as we already handled case normalisation.
|
||||
if( it == m_actionHotKeys.end() && !std::isalpha( key ) )
|
||||
{
|
||||
wxLogTrace( kicadTraceToolStack,
|
||||
wxS( "ACTION_MANAGER::RunHotKey No actions found, searching with key: %s" ),
|
||||
KeyNameFromKeyCode( key | ( mod & ~MD_SHIFT ) ) );
|
||||
|
||||
it = m_actionHotKeys.find( key | ( mod & ~MD_SHIFT ) );
|
||||
|
||||
if( it == m_actionHotKeys.end() )
|
||||
return false; // no appropriate action found for the hotkey
|
||||
}
|
||||
|
||||
// Still no luck, we're done without a match
|
||||
if( it == m_actionHotKeys.end() )
|
||||
return false; // no appropriate action found for the hotkey
|
||||
|
||||
const std::list<TOOL_ACTION*>& actions = it->second;
|
||||
|
||||
// Choose the action that has the highest priority on the active tools stack
|
||||
|
||||
+18
-5
@@ -38,6 +38,8 @@
|
||||
#include <wx/textentry.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/combo.h>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <refdes_utils.h>
|
||||
|
||||
|
||||
FOOTPRINT_NAME_VALIDATOR::FOOTPRINT_NAME_VALIDATOR( wxString* aValue ) :
|
||||
@@ -355,18 +357,24 @@ bool FIELD_VALIDATOR::Validate( wxWindow* aParent )
|
||||
return false;
|
||||
|
||||
wxString val( text->GetValue() );
|
||||
|
||||
return DoValidate( val, aParent );
|
||||
}
|
||||
|
||||
bool FIELD_VALIDATOR::DoValidate( const wxString& aValue, wxWindow* aParent )
|
||||
{
|
||||
wxString msg;
|
||||
|
||||
if( HasFlag( wxFILTER_EMPTY ) && val.empty() )
|
||||
if( HasFlag( wxFILTER_EMPTY ) && aValue.empty() )
|
||||
msg.Printf( _( "The value of the field cannot be empty." ) );
|
||||
|
||||
if( HasFlag( wxFILTER_EXCLUDE_CHAR_LIST ) && ContainsExcludedCharacters( val ) )
|
||||
if( HasFlag( wxFILTER_EXCLUDE_CHAR_LIST ) && ContainsExcludedCharacters( aValue ) )
|
||||
{
|
||||
wxArrayString badCharsFound;
|
||||
|
||||
for( const wxUniCharRef& excludeChar : GetCharExcludes() )
|
||||
{
|
||||
if( val.Find( excludeChar ) != wxNOT_FOUND )
|
||||
if( aValue.Find( excludeChar ) != wxNOT_FOUND )
|
||||
{
|
||||
if( excludeChar == '\r' )
|
||||
badCharsFound.Add( _( "carriage return" ) );
|
||||
@@ -434,14 +442,19 @@ bool FIELD_VALIDATOR::Validate( wxWindow* aParent )
|
||||
break;
|
||||
};
|
||||
}
|
||||
else if( m_fieldId == REFERENCE_FIELD && val.Contains( wxT( "${" ) ) )
|
||||
else if( m_fieldId == REFERENCE_FIELD && aValue.Contains( wxT( "${" ) ) )
|
||||
{
|
||||
msg.Printf( _( "The reference designator cannot contain text variable references" ) );
|
||||
}
|
||||
else if( m_fieldId == REFERENCE_FIELD && UTIL::GetRefDesPrefix( aValue ).IsEmpty() )
|
||||
{
|
||||
msg.Printf( _( "References must start with a letter." ) );
|
||||
}
|
||||
|
||||
if( !msg.empty() )
|
||||
{
|
||||
m_validatorWindow->SetFocus();
|
||||
if( m_validatorWindow )
|
||||
m_validatorWindow->SetFocus();
|
||||
|
||||
wxMessageBox( msg, _( "Field Validation Error" ), wxOK | wxICON_EXCLAMATION, aParent );
|
||||
|
||||
|
||||
@@ -353,19 +353,8 @@ bool DIALOG_FIELD_PROPERTIES::TransferDataFromWindow()
|
||||
else if( m_StyledTextCtrl->IsShown() )
|
||||
m_text = UnescapeString( m_StyledTextCtrl->GetValue() );
|
||||
|
||||
if( m_fieldId == REFERENCE_FIELD )
|
||||
{
|
||||
// Test if the reference string is valid:
|
||||
if( !SCH_SYMBOL::IsReferenceStringValid( m_text ) )
|
||||
{
|
||||
DisplayError( this, _( "Illegal reference designator value!" ) );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if( m_fieldId == SHEETFILENAME_V )
|
||||
{
|
||||
if( m_fieldId == SHEETFILENAME_V )
|
||||
m_text = EnsureFileExtension( m_text, FILEEXT::KiCadSchematicFileExtension );
|
||||
}
|
||||
|
||||
m_position = VECTOR2I( m_posX.GetValue(), m_posY.GetValue() );
|
||||
m_size = m_textSize.GetValue();
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#include <widgets/std_bitmap_button.h>
|
||||
#include <string_utils.h>
|
||||
#include <project_sch.h>
|
||||
|
||||
#include <refdes_utils.h>
|
||||
#include <dialog_sim_model.h>
|
||||
|
||||
#include <dialog_lib_symbol_properties.h>
|
||||
@@ -238,8 +238,8 @@ bool DIALOG_LIB_SYMBOL_PROPERTIES::Validate()
|
||||
return false;
|
||||
|
||||
// Alias symbol reference can be empty because it inherits from the parent symbol.
|
||||
if( m_libEntry->IsRoot() &&
|
||||
!SCH_SYMBOL::IsReferenceStringValid( m_fields->at( REFERENCE_FIELD ).GetText() ) )
|
||||
if( m_libEntry->IsRoot()
|
||||
&& UTIL::GetRefDesPrefix( m_fields->at( REFERENCE_FIELD ).GetText() ).IsEmpty() )
|
||||
{
|
||||
if( m_NoteBook->GetSelection() != 0 )
|
||||
m_NoteBook->SetSelection( 0 );
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include <trace_helpers.h>
|
||||
#include "panel_eeschema_color_settings.h"
|
||||
#include "wx/dcclient.h"
|
||||
#include "string_utils.h"
|
||||
|
||||
DIALOG_SHEET_PROPERTIES::DIALOG_SHEET_PROPERTIES( SCH_EDIT_FRAME* aParent, SCH_SHEET* aSheet,
|
||||
bool* aClearAnnotationNewItems,
|
||||
@@ -286,7 +287,15 @@ bool DIALOG_SHEET_PROPERTIES::TransferDataFromWindow()
|
||||
// but unedited data from existing files can be bad.)
|
||||
sheetFileName = EnsureFileExtension( sheetFileName, FILEEXT::KiCadSchematicFileExtension );
|
||||
|
||||
// Ensure sheetFileName is legal
|
||||
if( !IsFullFileNameValid( sheetFileName ) )
|
||||
{
|
||||
DisplayError( this, _( "A sheet must have a valid file name." ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
wxFileName fn( sheetFileName );
|
||||
|
||||
wxString newRelativeFilename = fn.GetFullPath();
|
||||
|
||||
// Inside Eeschema, filenames are stored using unix notation
|
||||
|
||||
@@ -634,17 +634,6 @@ bool DIALOG_SYMBOL_PROPERTIES::Validate()
|
||||
if( !m_fieldsGrid->CommitPendingChanges() || !m_fieldsGrid->Validate() )
|
||||
return false;
|
||||
|
||||
if( !SCH_SYMBOL::IsReferenceStringValid( m_fields->at( REFERENCE_FIELD ).GetText() ) )
|
||||
{
|
||||
DisplayErrorMessage( this, _( "References must start with a letter." ) );
|
||||
|
||||
wxCommandEvent *evt = new wxCommandEvent( SYMBOL_DELAY_FOCUS );
|
||||
evt->SetClientData( new VECTOR2I( REFERENCE_FIELD, FDC_VALUE ) );
|
||||
QueueEvent( evt );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for missing field names.
|
||||
for( size_t i = MANDATORY_FIELDS; i < m_fields->size(); ++i )
|
||||
{
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <schematic.h>
|
||||
#include <dialogs/panel_setup_buses.h>
|
||||
#include "grid_tricks.h"
|
||||
#include <wx/clipbrd.h>
|
||||
|
||||
PANEL_SETUP_BUSES::PANEL_SETUP_BUSES( wxWindow* aWindow, SCH_EDIT_FRAME* aFrame ) :
|
||||
PANEL_SETUP_BUSES_BASE( aWindow ),
|
||||
@@ -147,6 +148,9 @@ bool PANEL_SETUP_BUSES::TransferDataFromWindow()
|
||||
for( int ii = 0; ii < m_aliasesGrid->GetNumberRows(); ++ii )
|
||||
m_aliases[ii]->SetName( m_aliasesGrid->GetCellValue( ii, 0 ) );
|
||||
|
||||
// Associate the respective members with the last alias that is active.
|
||||
updateAliasMembers( m_lastAlias );
|
||||
|
||||
SCH_SCREENS screens( m_frame->Schematic().Root() );
|
||||
|
||||
for( SCH_SCREEN* screen = screens.GetFirst(); screen != nullptr; screen = screens.GetNext() )
|
||||
@@ -168,6 +172,12 @@ void PANEL_SETUP_BUSES::OnAddAlias( wxCommandEvent& aEvent )
|
||||
m_aliases.push_back( std::make_shared<BUS_ALIAS>( m_frame->GetScreen() ) );
|
||||
|
||||
int row = m_aliasesGrid->GetNumberRows();
|
||||
|
||||
// Associate the respective members with the previous alias. This ensures that the association starts
|
||||
// correctly when adding more than one row
|
||||
if( row > 0 )
|
||||
updateAliasMembers( row - 1 );
|
||||
|
||||
m_aliasesGrid->AppendRows();
|
||||
|
||||
m_aliasesGrid->MakeCellVisible( row, 0 );
|
||||
@@ -216,8 +226,35 @@ void PANEL_SETUP_BUSES::OnAddMember( wxCommandEvent& aEvent )
|
||||
m_membersGrid->MakeCellVisible( row, 0 );
|
||||
m_membersGrid->SetGridCursor( row, 0 );
|
||||
|
||||
m_membersGrid->EnableCellEditControl( true );
|
||||
m_membersGrid->ShowCellEditControl();
|
||||
/*
|
||||
* Check if the clipboard contains text data.
|
||||
*
|
||||
* - If `clipboardHasText` is true, select the specified row in the members grid to allow our custom
|
||||
* conext menu to paste the clipbaord .
|
||||
* - Otherwise, enable and display the cell edit control, allowing the user to manually edit the cell.
|
||||
*/
|
||||
bool clipboardHasText = false;
|
||||
|
||||
if( wxTheClipboard->Open() )
|
||||
{
|
||||
if( wxTheClipboard->IsSupported( wxDF_TEXT )
|
||||
|| wxTheClipboard->IsSupported( wxDF_UNICODETEXT ) )
|
||||
{
|
||||
clipboardHasText = true;
|
||||
}
|
||||
|
||||
wxTheClipboard->Close();
|
||||
}
|
||||
|
||||
if( clipboardHasText )
|
||||
{
|
||||
m_membersGrid->SelectRow( row );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_membersGrid->EnableCellEditControl( true );
|
||||
m_membersGrid->ShowCellEditControl();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -459,3 +496,23 @@ void PANEL_SETUP_BUSES::OnUpdateUI( wxUpdateUIEvent& event )
|
||||
}
|
||||
|
||||
|
||||
void PANEL_SETUP_BUSES::updateAliasMembers( int aAliasIndex )
|
||||
{
|
||||
if( !m_aliases.empty() && m_membersGrid->GetNumberRows() > 0 && aAliasIndex >= 0
|
||||
&& aAliasIndex < m_aliases.size() )
|
||||
{
|
||||
const std::shared_ptr<BUS_ALIAS>& alias = m_aliases[aAliasIndex];
|
||||
|
||||
alias->Members().clear();
|
||||
|
||||
for( int ii = 0; ii < m_membersGrid->GetNumberRows(); ++ii )
|
||||
{
|
||||
wxString memberValue = m_membersGrid->GetCellValue( ii, 0 );
|
||||
|
||||
if( !memberValue.empty() )
|
||||
{
|
||||
alias->Members().push_back( memberValue );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,16 @@ protected:
|
||||
|
||||
void doReloadMembersGrid();
|
||||
|
||||
/*
|
||||
* When rows are created programmatically by pasting values from the clipboard,
|
||||
* the cell change event may not be triggered. This can prevent members from
|
||||
* being automatically added to the corresponding alias.
|
||||
*
|
||||
* To ensure that members are correctly associated with the alias,
|
||||
* we manually update the members for the needed alias.
|
||||
*/
|
||||
void updateAliasMembers( int aAliasIndex );
|
||||
|
||||
private:
|
||||
SCH_EDIT_FRAME* m_frame;
|
||||
wxString m_membersLabelTemplate;
|
||||
|
||||
@@ -346,12 +346,14 @@ PANEL_SYM_LIB_TABLE::PANEL_SYM_LIB_TABLE( DIALOG_EDIT_LIBRARY_TABLES* aParent, P
|
||||
aGrid->SelectRow( 0 );
|
||||
};
|
||||
|
||||
setupGrid( m_global_grid );
|
||||
setupGrid( m_global_grid );
|
||||
m_global_grid->Bind( wxEVT_GRID_CELL_LEFT_CLICK, &PANEL_SYM_LIB_TABLE::onGridCellLeftClickHandler, this );
|
||||
|
||||
if( m_projectTable )
|
||||
{
|
||||
m_project_grid->SetTable( new SYMBOL_LIB_TABLE_GRID( *m_projectTable ), true );
|
||||
setupGrid( m_project_grid );
|
||||
m_project_grid->Bind( wxEVT_GRID_CELL_LEFT_CLICK, &PANEL_SYM_LIB_TABLE::onGridCellLeftClickHandler, this );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -389,9 +391,13 @@ PANEL_SYM_LIB_TABLE::~PANEL_SYM_LIB_TABLE()
|
||||
// Delete the GRID_TRICKS.
|
||||
// Any additional event handlers should be popped before the window is deleted.
|
||||
m_global_grid->PopEventHandler( true );
|
||||
m_global_grid->Unbind( wxEVT_GRID_CELL_LEFT_CLICK, &PANEL_SYM_LIB_TABLE::onGridCellLeftClickHandler, this );
|
||||
|
||||
if( m_project_grid )
|
||||
{
|
||||
m_project_grid->PopEventHandler( true );
|
||||
m_project_grid->Unbind( wxEVT_GRID_CELL_LEFT_CLICK, &PANEL_SYM_LIB_TABLE::onGridCellLeftClickHandler, this );
|
||||
}
|
||||
|
||||
m_path_subs_grid->PopEventHandler( true );
|
||||
}
|
||||
@@ -1072,6 +1078,33 @@ SYMBOL_LIB_TABLE_GRID* PANEL_SYM_LIB_TABLE::cur_model() const
|
||||
}
|
||||
|
||||
|
||||
void PANEL_SYM_LIB_TABLE::onGridCellLeftClickHandler( wxGridEvent& event )
|
||||
{
|
||||
// Get the grid object that triggered the event
|
||||
wxGrid* grid = dynamic_cast<wxGrid*>( event.GetEventObject() );
|
||||
|
||||
// If the event object is a wxGrid, proceed with the handling
|
||||
if( grid )
|
||||
{
|
||||
int row = event.GetRow();
|
||||
int col = event.GetCol();
|
||||
|
||||
// Get the cell renderer for the clicked cell
|
||||
wxGridCellRenderer* renderer = grid->GetCellRenderer( row, col );
|
||||
|
||||
// Check if the renderer is a wxGridCellBoolRenderer using dynamic_cast
|
||||
if( dynamic_cast<wxGridCellBoolRenderer*>( renderer ) )
|
||||
{
|
||||
// Set the grid cursor to the clicked boolean cell
|
||||
grid->SetGridCursor( row, col );
|
||||
}
|
||||
}
|
||||
|
||||
// Allow the default behavior to continue (toggle the bool)
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
size_t PANEL_SYM_LIB_TABLE::m_pageNdx = 0;
|
||||
|
||||
|
||||
@@ -1163,4 +1196,4 @@ void InvokeSchEditSymbolLibTable( KIWAY* aKiway, wxWindow *aParent )
|
||||
aKiway->ExpressMail( FRAME_SCH, MAIL_RELOAD_LIB, payload );
|
||||
aKiway->ExpressMail( FRAME_SCH_SYMBOL_EDITOR, MAIL_RELOAD_LIB, payload );
|
||||
aKiway->ExpressMail( FRAME_SCH_VIEWER, MAIL_RELOAD_LIB, payload );
|
||||
}
|
||||
}
|
||||
@@ -58,6 +58,7 @@ private:
|
||||
void onSizeGrid( wxSizeEvent& event ) override;
|
||||
void adjustPathSubsGridColumns( int aWidth );
|
||||
void onConvertLegacyLibraries( wxCommandEvent& event ) override;
|
||||
void onGridCellLeftClickHandler( wxGridEvent& event );
|
||||
|
||||
bool TransferDataFromWindow() override;
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <wx/msgdlg.h>
|
||||
|
||||
#include <pgm_base.h>
|
||||
#include <settings/settings_manager.h>
|
||||
#include <eeschema_settings.h>
|
||||
@@ -186,10 +188,41 @@ bool PANEL_TEMPLATE_FIELDNAMES::TransferDataFromWindow()
|
||||
|
||||
m_templateMgr->DeleteAllFieldNameTemplates( m_global );
|
||||
|
||||
for( const TEMPLATE_FIELDNAME& field : m_fields )
|
||||
for( TEMPLATE_FIELDNAME& field : m_fields )
|
||||
{
|
||||
if( !field.m_Name.IsEmpty() )
|
||||
{
|
||||
wxString trimmedName = field.m_Name;
|
||||
|
||||
trimmedName.Trim();
|
||||
trimmedName.Trim( false );
|
||||
|
||||
// Check if the field name contains leading and/or trailing white space.
|
||||
if( field.m_Name != trimmedName )
|
||||
{
|
||||
wxString msg;
|
||||
|
||||
msg.Printf( _( "The field name \"%s\" contains trailing and/or leading white"
|
||||
"space." ), field.m_Name );
|
||||
|
||||
wxMessageDialog dlg( this, msg, _( "Warning" ),
|
||||
wxOK | wxCANCEL | wxCENTER | wxICON_WARNING );
|
||||
|
||||
dlg.SetExtendedMessage( _( "This may result in what appears to be duplicate field "
|
||||
"names but are actually unique names differing only by "
|
||||
"white space characters. Removing the white space "
|
||||
"characters will have no effect on existing symbol "
|
||||
"field names." ) );
|
||||
|
||||
dlg.SetOKCancelLabels( wxMessageDialog::ButtonLabel( _( "Remove White Space" ) ),
|
||||
wxMessageDialog::ButtonLabel( _( "Keep White Space" ) ) );
|
||||
|
||||
if( dlg.ShowModal() == wxID_OK )
|
||||
field.m_Name = trimmedName;
|
||||
}
|
||||
|
||||
m_templateMgr->AddTemplateFieldName( field, m_global );
|
||||
}
|
||||
}
|
||||
|
||||
if( m_global )
|
||||
|
||||
@@ -533,6 +533,13 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
|
||||
SCH_COMMIT dummy( this );
|
||||
|
||||
RecalculateConnections( &dummy, GLOBAL_CLEANUP );
|
||||
|
||||
if( schematic.HasSymbolFieldNamesWithWhiteSpace() )
|
||||
{
|
||||
m_infoBar->QueueShowMessage( _( "This schematic contains symbols that have leading "
|
||||
"and/or trailing white space field names." ),
|
||||
wxICON_WARNING );
|
||||
}
|
||||
}
|
||||
|
||||
// Load any exclusions from the project file
|
||||
@@ -1404,8 +1411,8 @@ bool SCH_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType,
|
||||
|
||||
pi->SetProgressReporter( &progressReporter );
|
||||
|
||||
SCH_SHEET* loadedSheet =
|
||||
pi->LoadSchematicFile( aFileName, &Schematic(), nullptr, aProperties );
|
||||
SCH_SHEET* loadedSheet = pi->LoadSchematicFile( aFileName, &Schematic(), nullptr,
|
||||
aProperties );
|
||||
|
||||
if( loadedSheet )
|
||||
{
|
||||
|
||||
@@ -136,9 +136,11 @@ void ConvertImageToLibShapes( LIB_SYMBOL* aSymbol, int unit, wxImage img, VECTOR
|
||||
|
||||
shape->Offset( offset );
|
||||
|
||||
aSymbol->AddDrawItem( shape.release() );
|
||||
aSymbol->AddDrawItem( shape.release(), false );
|
||||
}
|
||||
}
|
||||
|
||||
aSymbol->GetDrawItems().sort();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -372,8 +372,8 @@ void SCH_EDIT_FRAME::onNetNavigatorSelection( wxTreeEvent& aEvent )
|
||||
|
||||
if( GetCurrentSheet() != itemData->GetSheetPath() )
|
||||
{
|
||||
Schematic().SetCurrentSheet( itemData->GetSheetPath() );
|
||||
DisplayCurrentSheet();
|
||||
GetToolManager()->RunAction<SCH_SHEET_PATH*>( EE_ACTIONS::changeSheet,
|
||||
&itemData->GetSheetPath() );
|
||||
}
|
||||
|
||||
// Do not focus on item when a sheet tree node is selected.
|
||||
|
||||
@@ -769,8 +769,9 @@ void SCH_EDIT_FRAME::AddCopyForRepeatItem( const SCH_ITEM* aItem )
|
||||
{
|
||||
std::unique_ptr<SCH_ITEM> repeatItem( static_cast<SCH_ITEM*>( aItem->Duplicate() ) );
|
||||
|
||||
// Clone() preserves the flags, we want 'em cleared.
|
||||
// Clone() preserves the flags & parent, we want 'em cleared.
|
||||
repeatItem->ClearFlags();
|
||||
repeatItem->SetParent( nullptr );
|
||||
|
||||
m_items_to_repeat.emplace_back( std::move( repeatItem ) );
|
||||
}
|
||||
|
||||
@@ -505,6 +505,32 @@ SCH_EASYEDAPRO_PARSER::ParseSymbol( const std::vector<nlohmann::json>& aLines,
|
||||
|
||||
ksymbol->AddDrawItem( shape.release() );
|
||||
}
|
||||
else if( type == wxS( "BEZIER" ) )
|
||||
{
|
||||
std::vector<double> points = line.at( 2 );
|
||||
wxString styleStr = line.at( 3 );
|
||||
|
||||
std::unique_ptr<LIB_SHAPE> shape =
|
||||
std::make_unique<LIB_SHAPE>( ksymbol, SHAPE_T::BEZIER );
|
||||
|
||||
for( size_t i = 1; i < points.size(); i += 2 )
|
||||
{
|
||||
VECTOR2I pt = ScalePosSym( VECTOR2D( points[i - 1], points[i] ) );
|
||||
|
||||
switch( i )
|
||||
{
|
||||
case 1: shape->SetStart( pt ); break;
|
||||
case 3: shape->SetBezierC1( pt ); break;
|
||||
case 5: shape->SetBezierC2( pt ); break;
|
||||
case 7: shape->SetEnd( pt ); break;
|
||||
}
|
||||
}
|
||||
|
||||
shape->SetUnit( currentUnit );
|
||||
ApplyLineStyle( lineStyles, shape, styleStr );
|
||||
|
||||
ksymbol->AddDrawItem( shape.release() );
|
||||
}
|
||||
else if( type == wxS( "POLY" ) )
|
||||
{
|
||||
std::vector<double> points = line.at( 2 );
|
||||
@@ -1148,8 +1174,8 @@ void SCH_EASYEDAPRO_PARSER::ParseSchematic( SCHEMATIC* aSchematic, SCH_SHEET* aR
|
||||
if( !deviceAttr )
|
||||
continue;
|
||||
|
||||
std::map<wxString, wxString> compAttrs =
|
||||
aProject.at( "devices" ).at( deviceAttr->value ).at( "attributes" );
|
||||
std::map<wxString, wxString> compAttrs = EASYEDAPRO::AnyMapToStringMap(
|
||||
aProject.at( "devices" ).at( deviceAttr->value ).at( "attributes" ) );
|
||||
|
||||
wxString symbolId;
|
||||
|
||||
@@ -1210,39 +1236,60 @@ void SCH_EASYEDAPRO_PARSER::ParseSchematic( SCHEMATIC* aSchematic, SCH_SHEET* aR
|
||||
{
|
||||
auto nameAttr = get_opt( attributes, "Name" );
|
||||
|
||||
wxString netName;
|
||||
|
||||
if( nameAttr && !nameAttr->value.IsEmpty() )
|
||||
netName = nameAttr->value;
|
||||
else
|
||||
netName = compAttrs.at( "Name" );
|
||||
|
||||
std::unique_ptr<SCH_GLOBALLABEL> label = std::make_unique<SCH_GLOBALLABEL>(
|
||||
ScalePos( component->position ), netName );
|
||||
|
||||
std::vector<SCH_PIN*> pins = schSym->GetPins( &aSchematic->CurrentSheet() );
|
||||
|
||||
if( pins.size() > 0 )
|
||||
{
|
||||
switch( pins[0]->GetType() )
|
||||
{
|
||||
case ELECTRICAL_PINTYPE::PT_INPUT:
|
||||
label->SetShape( LABEL_FLAG_SHAPE::L_INPUT );
|
||||
break;
|
||||
case ELECTRICAL_PINTYPE::PT_OUTPUT:
|
||||
label->SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
|
||||
break;
|
||||
case ELECTRICAL_PINTYPE::PT_BIDI:
|
||||
label->SetShape( LABEL_FLAG_SHAPE::L_BIDI );
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
BOX2I bbox = schSym->GetBodyAndPinsBoundingBox();
|
||||
bbox.Offset( -schSym->GetPosition() );
|
||||
VECTOR2I bboxCenter = bbox.GetCenter();
|
||||
|
||||
SPIN_STYLE spin = SPIN_STYLE::LEFT;
|
||||
|
||||
if( std::abs( bboxCenter.x ) >= std::abs( bboxCenter.y ) )
|
||||
{
|
||||
if( bboxCenter.x >= 0 )
|
||||
spin = SPIN_STYLE::RIGHT;
|
||||
else
|
||||
spin = SPIN_STYLE::LEFT;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( bboxCenter.y >= 0 )
|
||||
spin = SPIN_STYLE::BOTTOM;
|
||||
else
|
||||
spin = SPIN_STYLE::UP;
|
||||
}
|
||||
|
||||
label->SetSpinStyle( spin );
|
||||
|
||||
if( nameAttr )
|
||||
{
|
||||
std::unique_ptr<SCH_GLOBALLABEL> label = std::make_unique<SCH_GLOBALLABEL>(
|
||||
ScalePos( component->position ), nameAttr->value );
|
||||
|
||||
SPIN_STYLE spin = SPIN_STYLE::LEFT;
|
||||
|
||||
if( esymInfo.symbolAttr )
|
||||
{
|
||||
wxString symStr = esymInfo.symbolAttr->value;
|
||||
|
||||
if( symStr == wxS( "Netport-IN" ) )
|
||||
{
|
||||
spin = SPIN_STYLE::LEFT;
|
||||
label->SetShape( LABEL_FLAG_SHAPE::L_INPUT );
|
||||
}
|
||||
if( symStr == wxS( "Netport-OUT" ) )
|
||||
{
|
||||
spin = SPIN_STYLE::RIGHT;
|
||||
label->SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
|
||||
}
|
||||
if( symStr == wxS( "Netport-BI" ) )
|
||||
{
|
||||
spin = SPIN_STYLE::RIGHT;
|
||||
label->SetShape( LABEL_FLAG_SHAPE::L_BIDI );
|
||||
}
|
||||
}
|
||||
|
||||
for( double i = component->rotation; i > 0; i -= 90 )
|
||||
spin = spin.RotateCCW();
|
||||
|
||||
label->SetSpinStyle( spin );
|
||||
|
||||
nlohmann::json style = fontStyles[nameAttr->fontStyle];
|
||||
|
||||
if( !style.is_null() && style.at( 5 ).is_number() )
|
||||
@@ -1250,10 +1297,10 @@ void SCH_EASYEDAPRO_PARSER::ParseSchematic( SCHEMATIC* aSchematic, SCH_SHEET* aR
|
||||
double size = style.at( 5 ).get<double>() * 0.5;
|
||||
label->SetTextSize( VECTOR2I( ScaleSize( size ), ScaleSize( size ) ) );
|
||||
}
|
||||
|
||||
createdItems.push_back( std::move( label ) );
|
||||
}
|
||||
|
||||
createdItems.push_back( std::move( label ) );
|
||||
|
||||
continue;
|
||||
}
|
||||
else
|
||||
@@ -1285,6 +1332,12 @@ void SCH_EASYEDAPRO_PARSER::ParseSchematic( SCHEMATIC* aSchematic, SCH_SHEET* aR
|
||||
auto nameAttr = get_opt( attributes, "Name" );
|
||||
auto valueAttr = get_opt( attributes, "Value" );
|
||||
|
||||
if( valueAttr && valueAttr->value.empty() )
|
||||
valueAttr->value = get_def( compAttrs, "Value", wxString() );
|
||||
|
||||
if( nameAttr && nameAttr->value.empty() )
|
||||
nameAttr->value = get_def( compAttrs, "Name", wxString() );
|
||||
|
||||
std::optional<EASYEDAPRO::SCH_ATTR> targetValueAttr;
|
||||
|
||||
if( valueAttr && !valueAttr->value.empty() && valueAttr->valVisible )
|
||||
@@ -1412,7 +1465,7 @@ void SCH_EASYEDAPRO_PARSER::ParseSchematic( SCHEMATIC* aSchematic, SCH_SHEET* aR
|
||||
|
||||
if( netAttr )
|
||||
{
|
||||
if( !netAttr->valVisible )
|
||||
if( !netAttr->valVisible || netAttr->value.IsEmpty() )
|
||||
continue;
|
||||
|
||||
VECTOR2I kpos = ScalePos( *netAttr->position );
|
||||
|
||||
@@ -1075,7 +1075,7 @@ SCH_TEXT* SCH_IO_KICAD_LEGACY::loadText( LINE_READER& aReader )
|
||||
if( m_version > 2 || *line >= ' ' )
|
||||
{
|
||||
if( strCompare( "Italic", line, &line ) )
|
||||
text->SetItalic( true );
|
||||
text->SetItalicFlag( true );
|
||||
else if( !strCompare( "~", line, &line ) )
|
||||
SCH_PARSE_ERROR( _( "expected 'Italics' or '~'" ), aReader, line );
|
||||
}
|
||||
@@ -1359,7 +1359,7 @@ SCH_SYMBOL* SCH_IO_KICAD_LEGACY::loadSymbol( LINE_READER& aReader )
|
||||
|
||||
if( textAttrs[1] == 'I' )
|
||||
{
|
||||
field.SetItalic( true );
|
||||
field.SetItalicFlag( true );
|
||||
}
|
||||
else if( textAttrs[1] != 'N' )
|
||||
{
|
||||
|
||||
@@ -647,7 +647,7 @@ void SCH_IO_KICAD_LEGACY_LIB_CACHE::loadField( std::unique_ptr<LIB_SYMBOL>& aSym
|
||||
wxChar attr_2 = attributes[2];
|
||||
|
||||
if( attr_1 == 'I' ) // Italic
|
||||
field->SetItalic( true );
|
||||
field->SetItalicFlag( true );
|
||||
else if( attr_1 != 'N' ) // No italics is default, check for error.
|
||||
SCH_PARSE_ERROR( "invalid field text italic parameter", aReader, line );
|
||||
|
||||
@@ -1015,7 +1015,7 @@ LIB_TEXT* SCH_IO_KICAD_LEGACY_LIB_CACHE::loadText( std::unique_ptr<LIB_SYMBOL>&
|
||||
&& !is_eol( *line ) )
|
||||
{
|
||||
if( strCompare( "Italic", line, &line ) )
|
||||
text->SetItalic( true );
|
||||
text->SetItalicFlag( true );
|
||||
else if( !strCompare( "Normal", line, &line ) )
|
||||
SCH_PARSE_ERROR( "invalid text stype, expected 'Normal' or 'Italic'", aReader, line );
|
||||
|
||||
|
||||
@@ -744,7 +744,7 @@ void SCH_IO_KICAD_SEXPR_PARSER::parseEDA_TEXT( EDA_TEXT* aText, bool aConvertOve
|
||||
case T_italic:
|
||||
{
|
||||
bool italic = parseMaybeAbsentBool( true );
|
||||
aText->SetItalic( italic );
|
||||
aText->SetItalicFlag( italic );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -89,8 +89,8 @@ public:
|
||||
|
||||
bool CanConnect( const SCH_ITEM* aItem ) const override
|
||||
{
|
||||
return ( aItem->Type() == SCH_LINE_T && aItem->GetLayer() == LAYER_WIRE ) ||
|
||||
aItem->Type() == SCH_SYMBOL_T;
|
||||
return ( aItem->Type() == SCH_LINE_T && aItem->GetLayer() == LAYER_WIRE )
|
||||
|| aItem->Type() == SCH_SYMBOL_T || aItem->Type() == SCH_SHEET_T;
|
||||
}
|
||||
|
||||
std::vector<VECTOR2I> GetConnectionPoints() const override;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 1992-2018 Jean-Pierre Charras jp.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2010 Lorenzo Marcantonio
|
||||
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@gmail.com>
|
||||
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2023, 2024 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
|
||||
@@ -132,8 +132,10 @@ void SCH_PLOTTER::createPDFFile( const SCH_PLOT_SETTINGS& aPlotSettings,
|
||||
sheetList.push_back( m_schematic->CurrentSheet() );
|
||||
}
|
||||
|
||||
wxCHECK( m_schematic, /* void */ );
|
||||
|
||||
// Allocate the plotter and set the job level parameter
|
||||
PDF_PLOTTER* plotter = new PDF_PLOTTER();
|
||||
PDF_PLOTTER* plotter = new PDF_PLOTTER( &m_schematic->Prj() );
|
||||
plotter->SetRenderSettings( aRenderSettings );
|
||||
plotter->SetColorMode( !aPlotSettings.m_blackAndWhite );
|
||||
plotter->SetCreator( wxT( "Eeschema-PDF" ) );
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 1992-2018 Jean-Pierre Charras jp.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2010 Lorenzo Marcantonio
|
||||
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@gmail.com>
|
||||
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2023, 2024 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
|
||||
|
||||
@@ -1743,6 +1743,31 @@ void SCH_SCREEN::PruneOrphanedSheetInstances( const wxString& aProjectName,
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SCREEN::HasSymbolFieldNamesWithWhiteSpace() const
|
||||
{
|
||||
wxString trimmedFieldName;
|
||||
|
||||
for( const SCH_ITEM* item : Items().OfType( SCH_SYMBOL_T ) )
|
||||
{
|
||||
const SCH_SYMBOL* symbol = static_cast<const SCH_SYMBOL*>( item );
|
||||
|
||||
wxCHECK2( symbol, continue );
|
||||
|
||||
for( const SCH_FIELD& field : symbol->GetFields() )
|
||||
{
|
||||
trimmedFieldName = field.GetName();
|
||||
trimmedFieldName.Trim();
|
||||
trimmedFieldName.Trim( false );
|
||||
|
||||
if( field.GetName() != trimmedFieldName )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#if defined(DEBUG)
|
||||
void SCH_SCREEN::Show( int nestLevel, std::ostream& os ) const
|
||||
{
|
||||
@@ -2161,3 +2186,15 @@ void SCH_SCREENS::PruneOrphanedSheetInstances( const wxString& aProjectName,
|
||||
for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
|
||||
screen->PruneOrphanedSheetInstances( aProjectName, aValidSheetPaths );
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SCREENS::HasSymbolFieldNamesWithWhiteSpace() const
|
||||
{
|
||||
for( const SCH_SCREEN* screen : m_screens )
|
||||
{
|
||||
if( screen->HasSymbolFieldNamesWithWhiteSpace() )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -542,6 +542,8 @@ public:
|
||||
*/
|
||||
bool AllSymbolDefaultInstancesNotSet();
|
||||
|
||||
bool HasSymbolFieldNamesWithWhiteSpace() const;
|
||||
|
||||
#if defined(DEBUG)
|
||||
void Show( int nestLevel, std::ostream& os ) const override;
|
||||
#endif
|
||||
@@ -829,6 +831,8 @@ public:
|
||||
void PruneOrphanedSheetInstances( const wxString& aProjectName,
|
||||
const SCH_SHEET_LIST& aValidSheetPaths );
|
||||
|
||||
bool HasSymbolFieldNamesWithWhiteSpace() const;
|
||||
|
||||
private:
|
||||
void addScreenToList( SCH_SCREEN* aScreen, SCH_SHEET* aSheet );
|
||||
void buildScreenList( SCH_SHEET* aSheet);
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <string_utils.h>
|
||||
|
||||
#include <utility>
|
||||
#include <validators.h>
|
||||
|
||||
|
||||
std::unordered_map<TRANSFORM, int> SCH_SYMBOL::s_transformToOrientationCache;
|
||||
@@ -783,9 +784,12 @@ const wxString SCH_SYMBOL::GetRef( const SCH_SHEET_PATH* sheet, bool aIncludeUni
|
||||
}
|
||||
|
||||
|
||||
bool SCH_SYMBOL::IsReferenceStringValid( const wxString& aReferenceString )
|
||||
void SCH_SYMBOL::SetRefProp( const wxString& aRef )
|
||||
{
|
||||
return !UTIL::GetRefDesPrefix( aReferenceString ).IsEmpty();
|
||||
FIELD_VALIDATOR validator( REFERENCE_FIELD );
|
||||
|
||||
if( validator.DoValidate( aRef, nullptr ) )
|
||||
SetRef( &Schematic()->CurrentSheet(), aRef );
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-14
@@ -556,10 +556,7 @@ public:
|
||||
{
|
||||
return GetRef( &Schematic()->CurrentSheet() );
|
||||
}
|
||||
void SetRefProp( const wxString aRef )
|
||||
{
|
||||
SetRef( &Schematic()->CurrentSheet(), aRef );
|
||||
}
|
||||
void SetRefProp( const wxString& aRef );
|
||||
wxString GetValueProp() const
|
||||
{
|
||||
return GetValueFieldText( false, &Schematic()->CurrentSheet(), false );
|
||||
@@ -677,16 +674,6 @@ public:
|
||||
|
||||
void SwapData( SCH_ITEM* aItem ) override;
|
||||
|
||||
/**
|
||||
* Test for an acceptable reference string.
|
||||
*
|
||||
* An acceptable reference string must support unannotation i.e starts by letter
|
||||
*
|
||||
* @param aReferenceString is the reference string to validate
|
||||
* @return true if reference string is valid.
|
||||
*/
|
||||
static bool IsReferenceStringValid( const wxString& aReferenceString );
|
||||
|
||||
/**
|
||||
* Return the reference for the given sheet path.
|
||||
*
|
||||
|
||||
@@ -453,7 +453,7 @@ std::map<int, wxString> SCHEMATIC::GetVirtualPageToSheetNamesMap() const
|
||||
{
|
||||
std::map<int, wxString> namesMap;
|
||||
|
||||
for( const SCH_SHEET_PATH& sheet : GetUnorderedSheets() )
|
||||
for( const SCH_SHEET_PATH& sheet : GetSheets() )
|
||||
{
|
||||
if( sheet.size() == 1 )
|
||||
namesMap[sheet.GetVirtualPageNumber()] = _( "<root sheet>" );
|
||||
@@ -469,7 +469,7 @@ std::map<int, wxString> SCHEMATIC::GetVirtualPageToSheetPagesMap() const
|
||||
{
|
||||
std::map<int, wxString> pagesMap;
|
||||
|
||||
for( const SCH_SHEET_PATH& sheet : GetUnorderedSheets() )
|
||||
for( const SCH_SHEET_PATH& sheet : GetSheets() )
|
||||
pagesMap[sheet.GetVirtualPageNumber()] = sheet.GetPageNumber();
|
||||
|
||||
return pagesMap;
|
||||
|
||||
@@ -922,12 +922,20 @@ void SIM_PLOT_TAB::SetTraceData( TRACE* trace, std::vector<double>& aX, std::vec
|
||||
trace->SetSweepCount( aSweepCount );
|
||||
trace->SetSweepSize( aSweepSize );
|
||||
|
||||
if( ( trace->GetType() & SPT_AC_PHASE ) || ( trace->GetType() & SPT_CURRENT ) )
|
||||
// Phase and currents on second Y axis, except for AC currents, those use the same axis as voltage
|
||||
if( ( trace->GetType() & SPT_AC_PHASE )
|
||||
|| ( ( GetSimType() != ST_AC ) && ( trace->GetType() & SPT_CURRENT ) ) )
|
||||
{
|
||||
trace->SetScale( m_axis_x, m_axis_y2 );
|
||||
}
|
||||
else if( trace->GetType() & SPT_POWER )
|
||||
{
|
||||
trace->SetScale( m_axis_x, m_axis_y3 );
|
||||
}
|
||||
else
|
||||
{
|
||||
trace->SetScale( m_axis_x, m_axis_y1 );
|
||||
}
|
||||
|
||||
for( auto& [ cursorId, cursor ] : trace->GetCursors() )
|
||||
{
|
||||
|
||||
@@ -111,7 +111,7 @@ TOOL_ACTION EE_ACTIONS::selectNode( TOOL_ACTION_ARGS()
|
||||
TOOL_ACTION EE_ACTIONS::selectConnection( TOOL_ACTION_ARGS()
|
||||
.Name( "eeschema.InteractiveSelection.SelectConnection" )
|
||||
.Scope( AS_GLOBAL )
|
||||
.DefaultHotkey( MD_ALT + '4' )
|
||||
.DefaultHotkey( MD_CTRL + '4' )
|
||||
.LegacyHotkeyName( "Select Connection" )
|
||||
.FriendlyName( _( "Select Connection" ) )
|
||||
.Tooltip( _( "Select a complete connection" ) )
|
||||
|
||||
@@ -1256,6 +1256,10 @@ int SCH_EDIT_TOOL::RepeatDrawItem( const TOOL_EVENT& aEvent )
|
||||
EESCHEMA_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings<EESCHEMA_SETTINGS>();
|
||||
bool restore_state = false;
|
||||
|
||||
// Ensure newItem has a suitable parent: the current screen, because an item from
|
||||
// a list of items to repeat must be attached to this current screen
|
||||
newItem->SetParent( m_frame->GetScreen() );
|
||||
|
||||
if( SCH_LABEL_BASE* label = dynamic_cast<SCH_LABEL_BASE*>( newItem ) )
|
||||
{
|
||||
// If incrementing tries to go below zero, tell user why the value is repeated
|
||||
@@ -1285,9 +1289,18 @@ int SCH_EDIT_TOOL::RepeatDrawItem( const TOOL_EVENT& aEvent )
|
||||
if( m_frame->CheckSheetForRecursion( sheet, currentSheet ) )
|
||||
{
|
||||
// Clear out the filename so that the user can pick a new one
|
||||
const wxString originalFileName = sheet->GetFileName();
|
||||
const wxString originalScreenFileName = sheet->GetScreen()->GetFileName();
|
||||
|
||||
sheet->SetFileName( wxEmptyString );
|
||||
sheet->GetScreen()->SetFileName( wxEmptyString );
|
||||
restore_state = !m_frame->EditSheetProperties( sheet, currentSheet, nullptr );
|
||||
|
||||
if( restore_state )
|
||||
{
|
||||
sheet->SetFileName( originalFileName );
|
||||
sheet->GetScreen()->SetFileName( originalScreenFileName );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -555,6 +555,11 @@ int SCH_EDITOR_CONTROL::SimProbe( const TOOL_EVENT& aEvent )
|
||||
[this, simFrame]( const VECTOR2D& aPosition )
|
||||
{
|
||||
EE_SELECTION_TOOL* selTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>();
|
||||
|
||||
// We do not really want to keep an item selected in schematic,
|
||||
// so clear the current selection
|
||||
selTool->ClearSelection();
|
||||
|
||||
EDA_ITEM* item = selTool->GetNode( aPosition );
|
||||
SCH_SHEET_PATH& sheet = m_frame->GetCurrentSheet();
|
||||
|
||||
@@ -684,6 +689,10 @@ int SCH_EDITOR_CONTROL::SimProbe( const TOOL_EVENT& aEvent )
|
||||
}
|
||||
|
||||
// Wake the selection tool after exiting to ensure the cursor gets updated
|
||||
// and deselect previous selection from simulator to avoid any issue
|
||||
// ( avoid crash in some cases when the SimProbe tool is deselected )
|
||||
EE_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>();
|
||||
selectionTool->ClearSelection();
|
||||
m_toolMgr->PostAction( EE_ACTIONS::selectionActivate );
|
||||
} );
|
||||
|
||||
|
||||
@@ -878,12 +878,43 @@ int SYMBOL_EDITOR_EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent )
|
||||
|
||||
commit.Modify( symbol, m_frame->GetScreen() );
|
||||
|
||||
EDA_ITEMS newItems;
|
||||
std::vector<EDA_ITEM*> oldItems;
|
||||
std::vector<EDA_ITEM*> newItems;
|
||||
|
||||
for( unsigned ii = 0; ii < selection.GetSize(); ++ii )
|
||||
std::copy( selection.begin(), selection.end(), std::back_inserter( oldItems ) );
|
||||
std::sort( oldItems.begin(), oldItems.end(), []( EDA_ITEM* a, EDA_ITEM* b )
|
||||
{
|
||||
LIB_ITEM* oldItem = static_cast<LIB_ITEM*>( selection.GetItem( ii ) );
|
||||
LIB_ITEM* newItem = static_cast<LIB_ITEM*>( oldItem->Duplicate() );
|
||||
int cmp;
|
||||
|
||||
if( a->Type() != b->Type() )
|
||||
return a->Type() < b->Type();
|
||||
|
||||
// Create the new pins in the same order as the old pins
|
||||
if( a->Type() == SCH_PIN_T )
|
||||
{
|
||||
const wxString& aNum = static_cast<SCH_PIN*>( a )->GetNumber();
|
||||
const wxString& bNum = static_cast<SCH_PIN*>( b )->GetNumber();
|
||||
|
||||
cmp = StrNumCmp( aNum, bNum );
|
||||
|
||||
// If the pin numbers are not numeric, then just number them by their position
|
||||
// on the screen.
|
||||
if( aNum.IsNumber() && bNum.IsNumber() && cmp != 0 )
|
||||
return cmp < 0;
|
||||
}
|
||||
|
||||
cmp = LexicographicalCompare( a->GetPosition(), b->GetPosition() );
|
||||
|
||||
if( cmp != 0 )
|
||||
return cmp > 0;
|
||||
|
||||
return a->m_Uuid < b->m_Uuid;
|
||||
} );
|
||||
|
||||
for( EDA_ITEM* item : oldItems )
|
||||
{
|
||||
LIB_ITEM* oldItem = static_cast<LIB_ITEM*>( item );
|
||||
LIB_ITEM* newItem = oldItem->Duplicate();
|
||||
|
||||
if( newItem->Type() == LIB_PIN_T )
|
||||
{
|
||||
|
||||
@@ -144,6 +144,15 @@ target_link_libraries( gerbview_kiface_objects
|
||||
core
|
||||
)
|
||||
|
||||
message( STATUS "Including 3Dconnexion SpaceMouse navigation support in gerbview" )
|
||||
add_subdirectory( navlib )
|
||||
|
||||
if( NOT MINGW )
|
||||
target_link_libraries( gerbview_kiface_objects PUBLIC gerbview_navlib)
|
||||
endif()
|
||||
|
||||
add_dependencies( gerbview_kiface_objects gerbview_navlib )
|
||||
|
||||
# the main gerbview program, in DSO form.
|
||||
add_library( gerbview_kiface MODULE )
|
||||
|
||||
@@ -163,6 +172,8 @@ target_link_libraries( gerbview_kiface
|
||||
${wxWidgets_LIBRARIES}
|
||||
)
|
||||
|
||||
target_link_libraries( gerbview_kiface PUBLIC gerbview_navlib)
|
||||
|
||||
set_source_files_properties( gerbview.cpp PROPERTIES
|
||||
# The KIFACE is in gerbview.cpp, export it:
|
||||
COMPILE_DEFINITIONS "BUILD_KIWAY_DLL;COMPILING_DLL"
|
||||
|
||||
+40
-10
@@ -57,19 +57,21 @@
|
||||
#include <dialog_draw_layers_settings.h>
|
||||
#include <zoom_defines.h>
|
||||
|
||||
#include <navlib/nl_gerbview_plugin.h>
|
||||
#include <wx/log.h>
|
||||
|
||||
GERBVIEW_FRAME::GERBVIEW_FRAME( KIWAY* aKiway, wxWindow* aParent )
|
||||
: EDA_DRAW_FRAME( aKiway, aParent, FRAME_GERBER, wxT( "GerbView" ), wxDefaultPosition,
|
||||
GERBVIEW_FRAME::GERBVIEW_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
||||
EDA_DRAW_FRAME( aKiway, aParent, FRAME_GERBER, wxT( "GerbView" ), wxDefaultPosition,
|
||||
wxDefaultSize, KICAD_DEFAULT_DRAWFRAME_STYLE, GERBVIEW_FRAME_NAME,
|
||||
gerbIUScale ),
|
||||
m_TextInfo( nullptr ),
|
||||
m_zipFileHistory( DEFAULT_FILE_HISTORY_SIZE, ID_GERBVIEW_ZIP_FILE1,
|
||||
ID_GERBVIEW_ZIP_FILE_LIST_CLEAR, _( "Clear Recent Zip Files" ) ),
|
||||
m_drillFileHistory( DEFAULT_FILE_HISTORY_SIZE, ID_GERBVIEW_DRILL_FILE1,
|
||||
ID_GERBVIEW_DRILL_FILE_LIST_CLEAR, _( "Clear Recent Drill Files" ) ),
|
||||
m_jobFileHistory( DEFAULT_FILE_HISTORY_SIZE, ID_GERBVIEW_JOB_FILE1,
|
||||
ID_GERBVIEW_JOB_FILE_LIST_CLEAR, _( "Clear Recent Job Files" ) ),
|
||||
m_activeLayer( 0 )
|
||||
m_TextInfo( nullptr ),
|
||||
m_zipFileHistory( DEFAULT_FILE_HISTORY_SIZE, ID_GERBVIEW_ZIP_FILE1,
|
||||
ID_GERBVIEW_ZIP_FILE_LIST_CLEAR, _( "Clear Recent Zip Files" ) ),
|
||||
m_drillFileHistory( DEFAULT_FILE_HISTORY_SIZE, ID_GERBVIEW_DRILL_FILE1,
|
||||
ID_GERBVIEW_DRILL_FILE_LIST_CLEAR, _( "Clear Recent Drill Files" ) ),
|
||||
m_jobFileHistory( DEFAULT_FILE_HISTORY_SIZE, ID_GERBVIEW_JOB_FILE1,
|
||||
ID_GERBVIEW_JOB_FILE_LIST_CLEAR, _( "Clear Recent Job Files" ) ),
|
||||
m_activeLayer( 0 )
|
||||
{
|
||||
m_maximizeByDefault = true;
|
||||
m_gerberLayout = nullptr;
|
||||
@@ -1069,6 +1071,18 @@ void GERBVIEW_FRAME::ActivateGalCanvas()
|
||||
|
||||
ReCreateOptToolbar();
|
||||
ReCreateMenuBar();
|
||||
|
||||
try
|
||||
{
|
||||
if( !m_spaceMouse )
|
||||
m_spaceMouse = std::make_unique<NL_GERBVIEW_PLUGIN>();
|
||||
|
||||
m_spaceMouse->SetCanvas( galCanvas );
|
||||
}
|
||||
catch( const std::system_error& e )
|
||||
{
|
||||
wxLogTrace( wxT( "KI_TRACE_NAVLIB" ), e.what() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1236,3 +1250,19 @@ void GERBVIEW_FRAME::ToggleLayerManager()
|
||||
m_auimgr.GetPane( "LayersManager" ).Show( m_show_layer_manager_tools );
|
||||
m_auimgr.Update();
|
||||
}
|
||||
|
||||
void GERBVIEW_FRAME::handleActivateEvent( wxActivateEvent& aEvent )
|
||||
{
|
||||
EDA_DRAW_FRAME::handleActivateEvent(aEvent);
|
||||
|
||||
if( m_spaceMouse )
|
||||
m_spaceMouse->SetFocus( aEvent.GetActive() );
|
||||
}
|
||||
|
||||
void GERBVIEW_FRAME::handleIconizeEvent( wxIconizeEvent& aEvent )
|
||||
{
|
||||
EDA_DRAW_FRAME::handleIconizeEvent(aEvent);
|
||||
|
||||
if( m_spaceMouse )
|
||||
m_spaceMouse->SetFocus( false );
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#include <page_info.h>
|
||||
#include <gbr_display_options.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#define NO_AVAILABLE_LAYERS UNDEFINED_LAYER
|
||||
|
||||
class DCODE_SELECTION_BOX;
|
||||
@@ -42,6 +44,7 @@ class GERBVIEW_SETTINGS;
|
||||
class REPORTER;
|
||||
class SELECTION;
|
||||
class wxStaticText;
|
||||
class NL_GERBVIEW_PLUGIN;
|
||||
|
||||
|
||||
/**
|
||||
@@ -477,6 +480,9 @@ protected:
|
||||
void setupUIConditions() override;
|
||||
void doReCreateMenuBar() override;
|
||||
|
||||
void handleActivateEvent( wxActivateEvent& aEvent ) override;
|
||||
void handleIconizeEvent( wxIconizeEvent& aEvent ) override;
|
||||
|
||||
private:
|
||||
void updateComponentListSelectBox();
|
||||
void updateNetnameListSelectBox();
|
||||
@@ -556,6 +562,8 @@ private:
|
||||
// relative to the m_SelAperAttributesBox
|
||||
wxStaticText* m_dcodeText; // a message on the auxiliary toolbar,
|
||||
// relative to the m_DCodeSelector
|
||||
|
||||
std::unique_ptr<NL_GERBVIEW_PLUGIN> m_spaceMouse;
|
||||
};
|
||||
|
||||
#endif /* WX_GERBER_STRUCT_H */
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
|
||||
add_library(gerbview_navlib STATIC
|
||||
"nl_gerbview_plugin.cpp"
|
||||
"nl_gerbview_plugin_impl.cpp"
|
||||
)
|
||||
|
||||
# gerbview_navlib depends on make_lexer outputs in common
|
||||
add_dependencies( gerbview_navlib common )
|
||||
|
||||
# Find the 3DxWare SDK component 3DxWare::NlClient
|
||||
# find_package(TDxWare_SDK 4.0 REQUIRED COMPONENTS 3DxWare::Navlib)
|
||||
target_compile_definitions(gerbview_navlib PRIVATE
|
||||
$<TARGET_PROPERTY:3DxWare::Navlib,INTERFACE_COMPILE_DEFINITIONS>
|
||||
)
|
||||
target_compile_options(gerbview_navlib PRIVATE
|
||||
$<TARGET_PROPERTY:3DxWare::Navlib,INTERFACE_COMPILE_OPTIONS>
|
||||
)
|
||||
target_include_directories(gerbview_navlib PRIVATE
|
||||
$<TARGET_PROPERTY:3DxWare::Navlib,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:gerbview_kiface_objects,INCLUDE_DIRECTORIES>
|
||||
)
|
||||
target_link_libraries(gerbview_navlib
|
||||
$<TARGET_PROPERTY:3DxWare::Navlib,INTERFACE_LINK_LIBRARIES>
|
||||
3DxWare::Navlib
|
||||
)
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 3Dconnexion
|
||||
* Copyright (C) 2022 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 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 "nl_gerbview_plugin.h"
|
||||
#include "nl_gerbview_plugin_impl.h"
|
||||
|
||||
#include <advanced_config.h>
|
||||
#include <kiplatform/drivers.h>
|
||||
|
||||
|
||||
NL_GERBVIEW_PLUGIN::NL_GERBVIEW_PLUGIN()
|
||||
{
|
||||
if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver
|
||||
&& KIPLATFORM::DRIVERS::Valid3DConnexionDriverVersion() )
|
||||
{
|
||||
m_impl = std::make_unique<NL_GERBVIEW_PLUGIN_IMPL>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NL_GERBVIEW_PLUGIN::~NL_GERBVIEW_PLUGIN() = default;
|
||||
|
||||
|
||||
void NL_GERBVIEW_PLUGIN::SetFocus( bool focus )
|
||||
{
|
||||
if( m_impl )
|
||||
m_impl->SetFocus( focus );
|
||||
}
|
||||
|
||||
|
||||
void NL_GERBVIEW_PLUGIN::SetCanvas( EDA_DRAW_PANEL_GAL* aViewport )
|
||||
{
|
||||
if( m_impl )
|
||||
m_impl->SetCanvas( aViewport );
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 3Dconnexion
|
||||
* Copyright (C) 2022 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 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file nl_gerbview_plugin.h
|
||||
* @brief Declaration of the NL_GERBVIEW_PLUGIN class
|
||||
*/
|
||||
|
||||
#ifndef NL_GERBVIEW_PLUGIN_H_
|
||||
#define NL_GERBVIEW_PLUGIN_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
// Forward declarations.
|
||||
class EDA_DRAW_PANEL_GAL;
|
||||
class NL_GERBVIEW_PLUGIN_IMPL;
|
||||
|
||||
/**
|
||||
* The class that implements the public interface to the SpaceMouse plug-in.
|
||||
*/
|
||||
class NL_GERBVIEW_PLUGIN
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Initializes a new instance of the NL_GERBVIEW_PLUGIN.
|
||||
*/
|
||||
NL_GERBVIEW_PLUGIN();
|
||||
|
||||
virtual ~NL_GERBVIEW_PLUGIN();
|
||||
|
||||
|
||||
/**
|
||||
* Sets the viewport controlled by the SpaceMouse.
|
||||
*
|
||||
* @param aViewport is the viewport to be navigated.
|
||||
*/
|
||||
void SetCanvas( EDA_DRAW_PANEL_GAL* aViewport );
|
||||
|
||||
|
||||
/**
|
||||
* Set the connection to the 3Dconnexion driver to the focus state so that
|
||||
* 3DMouse data is routed to this connexion.
|
||||
*
|
||||
* @param aFocus is true to set the connexion active.
|
||||
*/
|
||||
void SetFocus( bool aFocus );
|
||||
|
||||
private:
|
||||
std::unique_ptr<NL_GERBVIEW_PLUGIN_IMPL> m_impl;
|
||||
};
|
||||
|
||||
#endif // NL_GERBVIEW_PLUGIN_H_
|
||||
@@ -0,0 +1,598 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 3Dconnexion
|
||||
* Copyright (C) 2022 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 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 "nl_gerbview_plugin_impl.h"
|
||||
|
||||
// KiCAD includes
|
||||
#include <gal/graphics_abstraction_layer.h>
|
||||
#include <gerbview_frame.h>
|
||||
#include <bitmaps.h>
|
||||
#include <class_draw_panel_gal.h>
|
||||
#include <view/view.h>
|
||||
#include <view/wx_view_controls.h>
|
||||
#include <tool/action_manager.h>
|
||||
#include <tool/tool_action.h>
|
||||
#include <tool/tool_manager.h>
|
||||
|
||||
// stdlib
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <cfloat>
|
||||
|
||||
#include <wx/log.h>
|
||||
#include <wx/mstream.h>
|
||||
|
||||
|
||||
/**
|
||||
* Flag to enable the NL_GERBVIEW_PLUGIN debug tracing.
|
||||
*
|
||||
* Use "KI_TRACE_NL_GERBVIEW_PLUGIN" to enable.
|
||||
*
|
||||
* @ingroup trace_env_vars
|
||||
*/
|
||||
const wxChar* NL_GERBVIEW_PLUGIN_IMPL::m_logTrace = wxT( "KI_TRACE_NL_GERBVIEW_PLUGIN" );
|
||||
|
||||
|
||||
NL_GERBVIEW_PLUGIN_IMPL::NL_GERBVIEW_PLUGIN_IMPL() : CNavigation3D( false, false )
|
||||
{
|
||||
PutProfileHint( "KiCAD Gerbview" );
|
||||
}
|
||||
|
||||
|
||||
NL_GERBVIEW_PLUGIN_IMPL::~NL_GERBVIEW_PLUGIN_IMPL()
|
||||
{
|
||||
std::error_code m_errCode;
|
||||
EnableNavigation( false, m_errCode );
|
||||
if( m_errCode.value() != 0 )
|
||||
{
|
||||
wxLogTrace( wxT( "KI_TRACE_NAVLIB" ),
|
||||
wxT( "Error occured when calling EnableNavigation. Error code: %d" ),
|
||||
m_errCode.value() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void NL_GERBVIEW_PLUGIN_IMPL::SetCanvas( EDA_DRAW_PANEL_GAL* aViewport )
|
||||
{
|
||||
m_viewport2D = aViewport;
|
||||
|
||||
if( m_viewport2D == nullptr )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_view = m_viewport2D->GetView();
|
||||
|
||||
if( m_view == nullptr )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_viewportWidth = m_view->GetBoundary().GetWidth();
|
||||
|
||||
if( !IsEnabled() )
|
||||
{
|
||||
// Use the default settings for the connexion to the 3DMouse navigation
|
||||
// They are use a single-threaded threading model and row vectors.
|
||||
EnableNavigation( true );
|
||||
|
||||
// Use the SpaceMouse internal timing source for the frame rate.
|
||||
PutFrameTimingSource( TimingSource::SpaceMouse );
|
||||
|
||||
exportCommandsAndImages();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void NL_GERBVIEW_PLUGIN_IMPL::SetFocus( bool aFocus )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "NL_GERBVIEW_PLUGIN_IMPL::SetFocus %d" ), aFocus );
|
||||
NAV_3D::Write( navlib::focus_k, aFocus );
|
||||
}
|
||||
|
||||
// temporary store for the command categories
|
||||
using CATEGORY_STORE = std::map<std::string, TDx::CCommandTreeNode*, std::less<>>;
|
||||
|
||||
|
||||
/**
|
||||
* Add a category to the store.
|
||||
*
|
||||
* The function adds category paths of the format "A.B" where B is a sub-category of A.
|
||||
*
|
||||
* @param aCategoryPath is the std::string representation of the category.
|
||||
* @param aCategoryStore is the CATEGORY_STORE instance to add to.
|
||||
*/
|
||||
static void add_category( const std::string& aCategoryPath, CATEGORY_STORE& aCategoryStore )
|
||||
{
|
||||
using TDx::SpaceMouse::CCategory;
|
||||
|
||||
auto parent_iter = aCategoryStore.begin();
|
||||
std::string::size_type pos = aCategoryPath.find_last_of( '.' );
|
||||
|
||||
if( pos != std::string::npos )
|
||||
{
|
||||
std::string parentPath = aCategoryPath.substr( 0, pos );
|
||||
|
||||
if( aCategoryStore.find( parentPath ) == aCategoryStore.end() )
|
||||
{
|
||||
add_category( parentPath, aCategoryStore );
|
||||
parent_iter = aCategoryStore.find( parentPath );
|
||||
}
|
||||
}
|
||||
|
||||
std::string name = aCategoryPath.substr( pos + 1 );
|
||||
auto categoryNode = std::make_unique<CCategory>( aCategoryPath.c_str(), name.c_str() );
|
||||
|
||||
aCategoryStore.try_emplace( aCategoryStore.end(), aCategoryPath, categoryNode.get() );
|
||||
|
||||
parent_iter->second->push_back( std::move( categoryNode ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* add_category wrapper.
|
||||
*
|
||||
* Function checks if path exists in the category and adds it if it doesn't.
|
||||
*
|
||||
* @param aCategoryPath is the std::string representation of the category.
|
||||
* @param aCategoryStore is the CATEGORY_STORE instance to add to.
|
||||
*/
|
||||
static void try_add_category( const std::string& aCategoryPath, CATEGORY_STORE& aCategoryStore )
|
||||
{
|
||||
if( aCategoryStore.find( aCategoryPath ) == aCategoryStore.end() )
|
||||
{
|
||||
add_category( aCategoryPath, aCategoryStore );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void NL_GERBVIEW_PLUGIN_IMPL::exportCommandsAndImages()
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "NL_GERBVIEW_PLUGIN_IMPL::exportCommandsAndImages" ) );
|
||||
|
||||
std::list<TOOL_ACTION*> actions = ACTION_MANAGER::GetActionList();
|
||||
|
||||
if( actions.empty() )
|
||||
return;
|
||||
|
||||
using TDx::SpaceMouse::CCommand;
|
||||
using TDx::SpaceMouse::CCommandSet;
|
||||
|
||||
// The root action set node
|
||||
CCommandSet commandSet( "GERBER_EDITOR", "Gerber Viewer" );
|
||||
|
||||
// Activate the command set
|
||||
NAV_3D::PutActiveCommands( commandSet.GetId() );
|
||||
|
||||
// temporary store for the categories initialized with action set
|
||||
CATEGORY_STORE categoryStore{ CATEGORY_STORE::value_type( ".", &commandSet ) };
|
||||
|
||||
std::vector<TDx::CImage> vImages;
|
||||
|
||||
for( const auto action : actions )
|
||||
{
|
||||
std::string label = action->GetMenuLabel().ToStdString();
|
||||
|
||||
if( label.empty() )
|
||||
continue;
|
||||
|
||||
std::string name = action->GetName();
|
||||
|
||||
// Do no export commands for the 3DViewer app.
|
||||
|
||||
if( name.rfind( "3DViewer.", 0 ) == 0 )
|
||||
continue;
|
||||
|
||||
std::string strCategory = action->GetToolName();
|
||||
std::string description = action->GetDescription().ToStdString();
|
||||
|
||||
try_add_category( strCategory, categoryStore );
|
||||
CATEGORY_STORE::iterator iter = categoryStore.find( strCategory );
|
||||
|
||||
// Arbitrary 8-bit data stream
|
||||
wxMemoryOutputStream imageStream;
|
||||
|
||||
if( action->GetIcon() != BITMAPS::INVALID_BITMAP )
|
||||
{
|
||||
wxImage image = KiBitmap( action->GetIcon() ).ConvertToImage();
|
||||
image.SaveFile( imageStream, wxBitmapType::wxBITMAP_TYPE_PNG );
|
||||
image.Destroy();
|
||||
|
||||
if( imageStream.GetSize() )
|
||||
{
|
||||
const wxStreamBuffer* streamBuffer = imageStream.GetOutputStreamBuffer();
|
||||
TDx::CImage tdxImage = TDx::CImage::FromData( "", 0, name.c_str() );
|
||||
tdxImage.AssignImage(
|
||||
std::string( static_cast<const char*>( streamBuffer->GetBufferStart() ),
|
||||
streamBuffer->GetBufferSize() ),
|
||||
0 );
|
||||
|
||||
wxLogTrace( m_logTrace, wxT( "Adding image for : %s" ), name );
|
||||
vImages.push_back( std::move( tdxImage ) );
|
||||
}
|
||||
}
|
||||
|
||||
wxLogTrace( m_logTrace, wxT( "Inserting command: %s, description: %s, in category: %s" ),
|
||||
name, description, iter->first );
|
||||
|
||||
iter->second->push_back(
|
||||
CCommand( std::move( name ), std::move( label ), std::move( description ) ) );
|
||||
}
|
||||
|
||||
NAV_3D::AddCommandSet( commandSet );
|
||||
NAV_3D::AddImages( vImages );
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::GetCameraMatrix( navlib::matrix_t& matrix ) const
|
||||
{
|
||||
if( m_view == nullptr )
|
||||
return navlib::make_result_code( navlib::navlib_errc::no_data_available );
|
||||
|
||||
m_viewPosition = m_view->GetCenter();
|
||||
|
||||
double x = m_view->IsMirroredX() ? -1 : 1;
|
||||
double y = m_view->IsMirroredY() ? 1 : -1;
|
||||
|
||||
// x * y * z = 1 for a right-handed coordinate system.
|
||||
double z = x * y;
|
||||
|
||||
// Note: the connexion has been configured as row vectors, the coordinate system is defined in
|
||||
// NL_GERBVIEW_PLUGIN_IMPL::GetCoordinateSystem and the front view in NL_GERBVIEW_PLUGIN_IMPL::GetFrontView.
|
||||
matrix = { { { x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, m_viewPosition.x, m_viewPosition.y, 0,
|
||||
1 } } };
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::GetPointerPosition( navlib::point_t& position ) const
|
||||
{
|
||||
if( m_view == nullptr )
|
||||
return navlib::make_result_code( navlib::navlib_errc::no_data_available );
|
||||
|
||||
VECTOR2D mouse_pointer = m_viewport2D->GetViewControls()->GetMousePosition();
|
||||
|
||||
position.x = mouse_pointer.x;
|
||||
position.y = mouse_pointer.y;
|
||||
position.z = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::GetViewExtents( navlib::box_t& extents ) const
|
||||
{
|
||||
if( m_view == nullptr )
|
||||
return navlib::make_result_code( navlib::navlib_errc::no_data_available );
|
||||
|
||||
double scale = m_viewport2D->GetGAL()->GetWorldScale();
|
||||
BOX2D box = m_view->GetViewport();
|
||||
|
||||
m_viewportWidth = box.GetWidth();
|
||||
|
||||
extents.min_x = -box.GetWidth() / 2.0;
|
||||
extents.min_y = -box.GetHeight() / 2.0;
|
||||
extents.min_z = m_viewport2D->GetGAL()->GetMinDepth() / scale;
|
||||
extents.max_x = box.GetWidth() / 2.0;
|
||||
extents.max_y = box.GetHeight() / 2.0;
|
||||
extents.max_z = m_viewport2D->GetGAL()->GetMaxDepth() / scale;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::GetIsViewPerspective( navlib::bool_t& perspective ) const
|
||||
{
|
||||
perspective = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::SetCameraMatrix( const navlib::matrix_t& matrix )
|
||||
{
|
||||
if( m_view == nullptr )
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
|
||||
long result = 0;
|
||||
VECTOR2D viewPos( matrix.m4x4[3][0], matrix.m4x4[3][1] );
|
||||
|
||||
if( !equals( m_view->GetCenter(), m_viewPosition,
|
||||
static_cast<VECTOR2D::coord_type>( FLT_EPSILON ) ) )
|
||||
{
|
||||
m_view->SetCenter( viewPos + m_view->GetCenter() - m_viewPosition );
|
||||
result = navlib::make_result_code( navlib::navlib_errc::error );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_view->SetCenter( viewPos );
|
||||
}
|
||||
|
||||
m_viewPosition = viewPos;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::SetViewExtents( const navlib::box_t& extents )
|
||||
{
|
||||
if( m_view == nullptr )
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
|
||||
long result = 0;
|
||||
|
||||
if( m_viewportWidth != m_view->GetViewport().GetWidth() )
|
||||
result = navlib::make_result_code( navlib::navlib_errc::error );
|
||||
|
||||
double width = m_viewportWidth;
|
||||
m_viewportWidth = extents.max_x - extents.min_x;
|
||||
|
||||
double scale = width / m_viewportWidth * m_view->GetScale();
|
||||
m_view->SetScale( scale, m_view->GetCenter() );
|
||||
|
||||
if( !equals( m_view->GetScale(), scale, static_cast<double>( FLT_EPSILON ) ) )
|
||||
result = navlib::make_result_code( navlib::navlib_errc::error );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::SetViewFOV( double fov )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::SetViewFrustum( const navlib::frustum_t& frustum )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::GetModelExtents( navlib::box_t& extents ) const
|
||||
{
|
||||
if( m_view == nullptr )
|
||||
return navlib::make_result_code( navlib::navlib_errc::no_data_available );
|
||||
|
||||
BOX2I box = static_cast<GERBVIEW_FRAME*>( m_viewport2D->GetParent() )->GetDocumentExtents();
|
||||
box.Normalize();
|
||||
|
||||
double half_depth = 0.1 / m_viewport2D->GetGAL()->GetWorldScale();
|
||||
|
||||
if( box.GetWidth() == 0 && box.GetHeight() == 0 )
|
||||
half_depth = 0;
|
||||
|
||||
extents.min_x = static_cast<double>( box.GetOrigin().x );
|
||||
extents.min_y = static_cast<double>( box.GetOrigin().y );
|
||||
extents.min_z = -half_depth;
|
||||
extents.max_x = static_cast<double>( box.GetEnd().x );
|
||||
extents.max_y = static_cast<double>( box.GetEnd().y );
|
||||
extents.max_z = half_depth;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::GetCoordinateSystem( navlib::matrix_t& matrix ) const
|
||||
{
|
||||
// The coordinate system is defined as x to the right, y down and z into the screen.
|
||||
matrix = { { { 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1 } } };
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::GetFrontView( navlib::matrix_t& matrix ) const
|
||||
{
|
||||
matrix = { { { 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1 } } };
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::GetIsSelectionEmpty( navlib::bool_t& empty ) const
|
||||
{
|
||||
empty = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::GetIsViewRotatable( navlib::bool_t& isRotatable ) const
|
||||
{
|
||||
isRotatable = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::SetActiveCommand( std::string commandId )
|
||||
{
|
||||
if( commandId.empty() )
|
||||
return 0;
|
||||
|
||||
if(m_viewport2D == nullptr)
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
wxWindow* parent = m_viewport2D->GetParent();
|
||||
|
||||
// Only allow command execution if the window is enabled. i.e. there is not a modal dialog
|
||||
// currently active.
|
||||
if( parent == nullptr || !parent->IsEnabled() )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
TOOL_MANAGER* tool_manager = dynamic_cast<TOOLS_HOLDER*>( parent )->GetToolManager();
|
||||
|
||||
// Only allow for command execution if the tool manager is accessible.
|
||||
if( tool_manager == nullptr )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
std::list<TOOL_ACTION*> actions = ACTION_MANAGER::GetActionList();
|
||||
for( const auto action : actions )
|
||||
{
|
||||
if( action == nullptr )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if( commandId == action->GetName() )
|
||||
{
|
||||
// Get the selection to use to test if the action is enabled
|
||||
const SELECTION& sel = tool_manager->GetToolHolder()->GetCurrentSelection();
|
||||
|
||||
const ACTION_CONDITIONS* aCond =
|
||||
tool_manager->GetActionManager()->GetCondition( *action );
|
||||
|
||||
if( aCond == nullptr )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
aCond->enableCondition( sel );
|
||||
tool_manager->RunAction( *action );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::SetSettingsChanged( long change )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::SetMotionFlag( bool value )
|
||||
{
|
||||
m_isMoving = value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::SetTransaction( long value )
|
||||
{
|
||||
if( value == 0L )
|
||||
m_viewport2D->ForceRefresh();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::GetViewFOV( double& fov ) const
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::GetViewFrustum( navlib::frustum_t& frustum ) const
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::GetSelectionExtents( navlib::box_t& extents ) const
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::no_data_available );
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::GetSelectionTransform( navlib::matrix_t& transform ) const
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::no_data_available );
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::SetSelectionTransform( const navlib::matrix_t& matrix )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::GetPivotPosition( navlib::point_t& position ) const
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::IsUserPivot( navlib::bool_t& userPivot ) const
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::SetPivotPosition( const navlib::point_t& position )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::GetPivotVisible( navlib::bool_t& visible ) const
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::SetPivotVisible( bool visible )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::GetHitLookAt( navlib::point_t& position ) const
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::no_data_available );
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::SetHitAperture( double aperture )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::SetHitDirection( const navlib::vector_t& direction )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::SetHitLookFrom( const navlib::point_t& eye )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::SetHitSelectionOnly( bool onlySelection )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_GERBVIEW_PLUGIN_IMPL::SetCameraTarget( const navlib::point_t& position )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 3Dconnexion
|
||||
* Copyright (C) 2022 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 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file nl_gerbview_plugin_impl.h
|
||||
* @brief Declaration of the NL_GERBVIEW_PLUGIN_IMPL class
|
||||
*/
|
||||
|
||||
#ifndef NL_GERBVIEW_PLUGIN_IMPL_H_
|
||||
#define NL_GERBVIEW_PLUGIN_IMPL_H_
|
||||
|
||||
#if _WIN32
|
||||
#ifndef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0603
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// TDxWare SDK.
|
||||
#include <SpaceMouse/CNavigation3D.hpp>
|
||||
|
||||
// wx
|
||||
#include <wx/chartype.h>
|
||||
|
||||
// KiCAD
|
||||
#include <math/vector2d.h>
|
||||
|
||||
// stdlib
|
||||
#include <string>
|
||||
|
||||
// Forward declarations.
|
||||
class EDA_DRAW_PANEL_GAL;
|
||||
namespace KIGFX
|
||||
{
|
||||
class VIEW;
|
||||
}
|
||||
|
||||
// Convenience typedef.
|
||||
typedef TDx::SpaceMouse::Navigation3D::CNavigation3D NAV_3D;
|
||||
|
||||
/**
|
||||
* The class that implements the accessors and mutators required for
|
||||
* 3D navigation in an PCB_DRAW_PANEL_GAL using a SpaceMouse.
|
||||
*/
|
||||
class NL_GERBVIEW_PLUGIN_IMPL : public NAV_3D
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Initializes a new instance of the NL_GERBVIEW_PLUGIN_IMPL.
|
||||
*/
|
||||
NL_GERBVIEW_PLUGIN_IMPL();
|
||||
|
||||
|
||||
virtual ~NL_GERBVIEW_PLUGIN_IMPL();
|
||||
|
||||
|
||||
/**
|
||||
* Sets the viewport controlled by the SpaceMouse.
|
||||
*
|
||||
* @param aViewport is the viewport to be navigated.
|
||||
*/
|
||||
void SetCanvas( EDA_DRAW_PANEL_GAL* aViewport );
|
||||
|
||||
|
||||
/**
|
||||
* Set the connection to the 3Dconnexion driver to the focus state so that
|
||||
* 3DMouse data is routed here.
|
||||
*
|
||||
* @param aFocus is true to set the connection active.
|
||||
*/
|
||||
void SetFocus( bool aFocus );
|
||||
|
||||
private:
|
||||
/**
|
||||
* Export the invocable actions and images to the 3Dconnexion UI.
|
||||
*/
|
||||
void exportCommandsAndImages();
|
||||
|
||||
long GetCameraMatrix( navlib::matrix_t& aMatrix ) const override;
|
||||
long GetPointerPosition( navlib::point_t& aPosition ) const override;
|
||||
long GetViewExtents( navlib::box_t& aExtents ) const override;
|
||||
long GetViewFOV( double& aFov ) const override;
|
||||
long GetViewFrustum( navlib::frustum_t& aFrustum ) const override;
|
||||
long GetIsViewPerspective( navlib::bool_t& aPerspective ) const override;
|
||||
long SetCameraMatrix( const navlib::matrix_t& aMatrix ) override;
|
||||
long SetViewExtents( const navlib::box_t& aExtents ) override;
|
||||
long SetViewFOV( double aFov ) override;
|
||||
long SetViewFrustum( const navlib::frustum_t& aFrustum ) override;
|
||||
long GetModelExtents( navlib::box_t& aExtents ) const override;
|
||||
long GetSelectionExtents( navlib::box_t& aExtents ) const override;
|
||||
long GetSelectionTransform( navlib::matrix_t& aTransform ) const override;
|
||||
long GetIsSelectionEmpty( navlib::bool_t& aEmpty ) const override;
|
||||
long SetSelectionTransform( const navlib::matrix_t& aMatrix ) override;
|
||||
long GetPivotPosition( navlib::point_t& aPosition ) const override;
|
||||
long IsUserPivot( navlib::bool_t& aUserPivot ) const override;
|
||||
long SetPivotPosition( const navlib::point_t& aPosition ) override;
|
||||
long GetPivotVisible( navlib::bool_t& aVisible ) const override;
|
||||
long SetPivotVisible( bool aVisible ) override;
|
||||
long GetHitLookAt( navlib::point_t& aPosition ) const override;
|
||||
long SetHitAperture( double aAperture ) override;
|
||||
long SetHitDirection( const navlib::vector_t& aDirection ) override;
|
||||
long SetHitLookFrom( const navlib::point_t& aPosition ) override;
|
||||
long SetHitSelectionOnly( bool aSelectionOnly ) override;
|
||||
long SetActiveCommand( std::string aCommandId ) override;
|
||||
|
||||
long SetSettingsChanged( long aChangeNumber ) override;
|
||||
long SetMotionFlag( bool aValue ) override;
|
||||
long SetTransaction( long aValue ) override;
|
||||
long SetCameraTarget( const navlib::point_t& aPosition ) override;
|
||||
|
||||
long GetFrontView( navlib::matrix_t& aMatrix ) const override;
|
||||
long GetCoordinateSystem( navlib::matrix_t& aMatrix ) const override;
|
||||
long GetIsViewRotatable( navlib::bool_t& isRotatable ) const override;
|
||||
|
||||
private:
|
||||
EDA_DRAW_PANEL_GAL* m_viewport2D = nullptr;
|
||||
KIGFX::VIEW* m_view = nullptr;
|
||||
bool m_isMoving = false;
|
||||
mutable double m_viewportWidth = 0.0;
|
||||
mutable VECTOR2D m_viewPosition;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* "KI_TRACE_NL_GERBVIEW_PLUGIN". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*/
|
||||
static const wxChar* m_logTrace;
|
||||
};
|
||||
|
||||
#endif // NL_GERBVIEW_PLUGIN_IMPL
|
||||
@@ -567,8 +567,17 @@ public:
|
||||
*/
|
||||
bool m_EnableCacheFriendlyFracture;
|
||||
|
||||
///@}
|
||||
/**
|
||||
* Minimum overlapping angle for which an arc is considered to be parallel
|
||||
* to its paired arc.
|
||||
*
|
||||
* Setting name: "MinParallelAngle"
|
||||
* Valid values: 0 to 45
|
||||
* Default value: 0.001
|
||||
*/
|
||||
double m_MinParallelAngle;
|
||||
|
||||
///@}
|
||||
|
||||
private:
|
||||
ADVANCED_CFG();
|
||||
|
||||
+3
-5
@@ -4,7 +4,7 @@
|
||||
* Copyright (C) 2014-2020 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2007-2015 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
|
||||
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2023, 2024 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
|
||||
@@ -102,11 +102,9 @@ wxString GetTextVars( const wxString& aSource );
|
||||
bool IsTextVar( const wxString& aSource );
|
||||
|
||||
/**
|
||||
* Replace any environment and/or text variables in file-path uris (leaving network-path URIs
|
||||
* alone).
|
||||
* Replace any environment and/or text variables in URIs
|
||||
*/
|
||||
const wxString ResolveUriByEnvVars( const wxString& aUri, PROJECT* aProject );
|
||||
|
||||
const wxString ResolveUriByEnvVars( const wxString& aUri, const PROJECT* aProject );
|
||||
|
||||
long long TimestampDir( const wxString& aDirPath, const wxString& aFilespec );
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2018-2021 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2018-2024 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
|
||||
@@ -156,6 +156,8 @@ private:
|
||||
void onHSVMouseClick( wxMouseEvent& event ) override;
|
||||
void onHSVMouseDrag( wxMouseEvent& event ) override;
|
||||
|
||||
void onSize( wxSizeEvent& event ) override;
|
||||
|
||||
void OnColorValueText( wxCommandEvent& event ) override;
|
||||
|
||||
///< Event handler for the reset button press
|
||||
@@ -187,6 +189,8 @@ private:
|
||||
*/
|
||||
void initDefinedColors( CUSTOM_COLORS_LIST* aPredefinedColors );
|
||||
|
||||
void updateHandleSize();
|
||||
|
||||
// convert double value 0 ... 1 to int 0 ... aValMax
|
||||
int normalizeToInt( double aValue, int aValMax = 255 )
|
||||
{
|
||||
|
||||
@@ -136,10 +136,33 @@ public:
|
||||
}
|
||||
double GetTextAngleDegrees() const { return m_attributes.m_Angle.AsDegrees(); }
|
||||
|
||||
/**
|
||||
* Set the text to be italic - this will also update the font if needed.
|
||||
*
|
||||
* This is the properties system interface.
|
||||
*/
|
||||
void SetItalic( bool aItalic );
|
||||
|
||||
/**
|
||||
* Set only the italic flag, without changing the font.
|
||||
*
|
||||
* Used when bulk-changing text attributes (e.g. from a dialog or import).
|
||||
*/
|
||||
void SetItalicFlag( bool aItalic );
|
||||
bool IsItalic() const { return m_attributes.m_Italic; }
|
||||
|
||||
/**
|
||||
* Set the text to be bold - this will also update the font if needed.
|
||||
*
|
||||
* This is the properties system interface.
|
||||
*/
|
||||
void SetBold( bool aBold );
|
||||
|
||||
/**
|
||||
* Set only the italic flag, without changing the font.
|
||||
*
|
||||
* Used when bulk-changing text attributes (e.g. from a dialog or import).
|
||||
*/
|
||||
void SetBoldFlag( bool aBold );
|
||||
bool IsBold() const { return m_attributes.m_Bold; }
|
||||
|
||||
|
||||
@@ -85,6 +85,7 @@ public:
|
||||
|
||||
// If true, keep rotation angle between -90...90 degrees for readability
|
||||
bool m_KeepUpright;
|
||||
int m_StoredStrokeWidth;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -81,6 +81,23 @@ public:
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
bool CanGetValueAs( int aRow, int aCol, const wxString& aTypeName ) override
|
||||
{
|
||||
if( aRow < (int) size() )
|
||||
{
|
||||
switch( aCol )
|
||||
{
|
||||
case COL_ENABLED:
|
||||
case COL_VISIBLE:
|
||||
return aTypeName == wxGRID_VALUE_BOOL;
|
||||
default:
|
||||
return aTypeName == wxGRID_VALUE_STRING;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GetValueAsBool( int aRow, int aCol ) override
|
||||
{
|
||||
if( aRow < (int) size() && aCol == COL_ENABLED )
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2016-2023, 2024 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
|
||||
@@ -107,7 +107,7 @@ public:
|
||||
static const int DO_NOT_SET_LINE_WIDTH = -2; // Skip selection
|
||||
static const int USE_DEFAULT_LINE_WIDTH = -1; // use the default pen
|
||||
|
||||
PLOTTER();
|
||||
PLOTTER( const PROJECT* aProject = nullptr );
|
||||
|
||||
virtual ~PLOTTER();
|
||||
|
||||
@@ -675,6 +675,8 @@ protected: // variables used in most of plotters:
|
||||
wxArrayString m_headerExtraLines; // a set of string to print in header file
|
||||
|
||||
RENDER_SETTINGS* m_renderSettings;
|
||||
|
||||
const PROJECT* m_project;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2016-2023, 2024 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
|
||||
@@ -35,7 +35,8 @@
|
||||
class PSLIKE_PLOTTER : public PLOTTER
|
||||
{
|
||||
public:
|
||||
PSLIKE_PLOTTER() :
|
||||
PSLIKE_PLOTTER( const PROJECT* aProject = nullptr) :
|
||||
PLOTTER( aProject ),
|
||||
plotScaleAdjX( 1 ),
|
||||
plotScaleAdjY( 1 ),
|
||||
m_textMode( PLOT_TEXT_MODE::PHANTOM )
|
||||
@@ -143,7 +144,8 @@ protected:
|
||||
class PS_PLOTTER : public PSLIKE_PLOTTER
|
||||
{
|
||||
public:
|
||||
PS_PLOTTER()
|
||||
PS_PLOTTER( const PROJECT* aProject = nullptr ) :
|
||||
PSLIKE_PLOTTER( aProject )
|
||||
{
|
||||
// The phantom plot in postscript is an hack and reportedly
|
||||
// crashes Adobe's own postscript interpreter!
|
||||
@@ -238,7 +240,8 @@ protected:
|
||||
class PDF_PLOTTER : public PSLIKE_PLOTTER
|
||||
{
|
||||
public:
|
||||
PDF_PLOTTER() :
|
||||
PDF_PLOTTER( const PROJECT* aProject = nullptr ) :
|
||||
PSLIKE_PLOTTER( aProject ),
|
||||
m_pageTreeHandle( 0 ),
|
||||
m_fontResDictHandle( 0 ),
|
||||
m_imgResDictHandle( 0 ),
|
||||
@@ -518,7 +521,7 @@ protected:
|
||||
class SVG_PLOTTER : public PSLIKE_PLOTTER
|
||||
{
|
||||
public:
|
||||
SVG_PLOTTER();
|
||||
SVG_PLOTTER( const PROJECT* aProject = nullptr );
|
||||
|
||||
static wxString GetDefaultFileExtension()
|
||||
{
|
||||
|
||||
@@ -102,7 +102,7 @@ public:
|
||||
/**
|
||||
* Stores the current parameters into the JSON document represented by this object
|
||||
* Note: this doesn't do any writing to disk; that's handled by SETTINGS_MANAGER
|
||||
* @return true if any part of the JSON document was updated
|
||||
* @return true if any part of the JSON document has been updated since the last save to disk
|
||||
*/
|
||||
virtual bool Store();
|
||||
|
||||
@@ -320,6 +320,9 @@ protected:
|
||||
/// Whether or not the backing store file should be written
|
||||
bool m_writeFile;
|
||||
|
||||
/// True if the JSON data store has been written to since the last file write
|
||||
bool m_modified;
|
||||
|
||||
/// Whether or not to delete legacy file after migration
|
||||
bool m_deleteLegacyAfterMigration;
|
||||
|
||||
|
||||
@@ -75,6 +75,8 @@ public:
|
||||
*/
|
||||
bool ClearUnknownKeys() const { return m_clearUnknownKeys; }
|
||||
|
||||
void SetClearUnknownKeys( bool aSet = true ) { m_clearUnknownKeys = aSet; }
|
||||
|
||||
protected:
|
||||
std::string m_path; ///< Address of the param in the json files
|
||||
bool m_readOnly; ///< Indicates param pointer should never be overwritten
|
||||
|
||||
+26
-2
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2004-2021 KiCad Developers, see change_log.txt for contributors.
|
||||
* Copyright (C) 2004-2021, 2024 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
|
||||
@@ -231,6 +231,13 @@ KICOMMON_API int GetTrailingInt( const wxString& aStr );
|
||||
*/
|
||||
KICOMMON_API wxString GetIllegalFileNameWxChars();
|
||||
|
||||
/**
|
||||
* Checks if a full filename is valid, i.e. does not contains illegal chars
|
||||
* path separators are allowed
|
||||
* @return true if OK.
|
||||
*/
|
||||
KICOMMON_API bool IsFullFileNameValid( const wxString& aFullFilename );
|
||||
|
||||
/**
|
||||
* Checks \a aName for illegal file name characters.
|
||||
*
|
||||
@@ -392,10 +399,27 @@ KICOMMON_API std::string FormatDouble2Str( double aValue );
|
||||
|
||||
/**
|
||||
* Convert an expected UTF8 encoded std::string to a wxString.
|
||||
* If fails, tray to convert using current locale
|
||||
* If fails, try to convert using current locale
|
||||
* If still fails, return the initial string (can be already a converted string)
|
||||
*/
|
||||
KICOMMON_API wxString From_UTF8( const std::string& aString );
|
||||
KICOMMON_API wxString From_UTF8( const char* cstring );
|
||||
|
||||
/**
|
||||
* Normalize file path \a aFileUri to URI convention.
|
||||
*
|
||||
* Unfortunately none of the wxWidgets objects results in acceptable file URIs which breaks
|
||||
* PDF plotting URI links. This is an attempt to normalize Windows local file paths to a
|
||||
* URI that PDF readers that can run JavaScript can handle.
|
||||
*
|
||||
* @note This does not expand environment or user variables. Variable expansion should be
|
||||
* performed before calling. If \a aFileUri does not begin with 'file://', \a aFileUri
|
||||
* returned unchanged.
|
||||
*
|
||||
* @param aFileUri is the string to be normalized.
|
||||
* @return the normalized string.
|
||||
*/
|
||||
KICOMMON_API wxString NormalizeFileUri( const wxString& aFileUri );
|
||||
|
||||
|
||||
#endif // STRING_UTILS_H
|
||||
|
||||
@@ -235,6 +235,8 @@ public:
|
||||
*/
|
||||
virtual bool Validate( wxWindow* aParent ) override;
|
||||
|
||||
bool DoValidate( const wxString& aValue, wxWindow* aParent );
|
||||
|
||||
private:
|
||||
int m_fieldId;
|
||||
};
|
||||
|
||||
@@ -48,8 +48,8 @@ public:
|
||||
*/
|
||||
void Insert( VIEW_ITEM* aItem, const BOX2I& bbox )
|
||||
{
|
||||
const int mmin[2] = { bbox.GetX(), bbox.GetY() };
|
||||
const int mmax[2] = { bbox.GetRight(), bbox.GetBottom() };
|
||||
const int mmin[2] = { std::min( bbox.GetX(), bbox.GetRight() ), std::min( bbox.GetY(), bbox.GetBottom() ) };
|
||||
const int mmax[2] = { std::max( bbox.GetX(), bbox.GetRight() ), std::max( bbox.GetY(), bbox.GetBottom() ) };
|
||||
|
||||
VIEW_RTREE_BASE::Insert( mmin, mmax, aItem );
|
||||
}
|
||||
@@ -65,8 +65,8 @@ public:
|
||||
|
||||
if( aBbox )
|
||||
{
|
||||
const int mmin[2] = { aBbox->GetX(), aBbox->GetY() };
|
||||
const int mmax[2] = { aBbox->GetRight(), aBbox->GetBottom() };
|
||||
const int mmin[2] = { std::min( aBbox->GetX(), aBbox->GetRight() ), std::min( aBbox->GetY(), aBbox->GetBottom() ) };
|
||||
const int mmax[2] = { std::max( aBbox->GetX(), aBbox->GetRight() ), std::max( aBbox->GetY(), aBbox->GetBottom() ) };
|
||||
VIEW_RTREE_BASE::Remove( mmin, mmax, aItem );
|
||||
return;
|
||||
}
|
||||
@@ -85,8 +85,8 @@ public:
|
||||
template <class Visitor>
|
||||
void Query( const BOX2I& aBounds, Visitor& aVisitor ) const
|
||||
{
|
||||
int mmin[2] = { aBounds.GetX(), aBounds.GetY() };
|
||||
int mmax[2] = { aBounds.GetRight(), aBounds.GetBottom() };
|
||||
int mmin[2] = { std::min( aBounds.GetX(), aBounds.GetRight() ), std::min( aBounds.GetY(), aBounds.GetBottom() ) };
|
||||
int mmax[2] = { std::max( aBounds.GetX(), aBounds.GetRight() ), std::max( aBounds.GetY(), aBounds.GetBottom() ) };
|
||||
|
||||
// We frequently use the maximum bounding box to recache all items
|
||||
// or for any item that overflows the integer width limits of BBOX2I
|
||||
|
||||
@@ -2241,12 +2241,29 @@ void PROJECT_TREE_PANE::onGitCommit( wxCommandEvent& aEvent )
|
||||
|
||||
git_oid oid;
|
||||
|
||||
#if( LIBGIT2_VER_MAJOR == 1 && LIBGIT2_VER_MINOR == 8 && LIBGIT2_VER_REVISION < 2 )
|
||||
// For libgit2 versions 1.8.0, 1.8.1.
|
||||
// This change was reverted for 1.8.2+
|
||||
#if( LIBGIT2_VER_MAJOR == 1 && LIBGIT2_VER_MINOR == 8 \
|
||||
&& ( LIBGIT2_VER_REVISION < 2 || LIBGIT2_VER_REVISION == 3 ) )
|
||||
/*
|
||||
* For libgit2 versions 1.8.0, 1.8.1. (cf19ddc52)
|
||||
* This change was reverted for 1.8.2 (49d3fadfc, main branch)
|
||||
* The revert for 1.8.2 was not included for 1.8.3 (which is on the maint/v1.8 branch, not main)
|
||||
* This change was also reverted for 1.8.4 (94ba816f6, also maint/v1.8 branch)
|
||||
*
|
||||
* As of 1.8.4, the history is like this:
|
||||
*
|
||||
* * 3f4182d15 (tag: v1.8.4, maint/v1.8)
|
||||
* * 94ba816f6 Revert "commit: fix const declaration" [puts const back]
|
||||
* * 3353f78e8 (tag: v1.8.3)
|
||||
* | * 4ce872a0f (tag: v1.8.2-rc1, tag: v1.8.2)
|
||||
* | * 49d3fadfc Revert "commit: fix const declaration" [puts const back]
|
||||
* |/
|
||||
* * 36f7e21ad (tag: v1.8.1)
|
||||
* * d74d49148 (tag: v1.8.0)
|
||||
* * cf19ddc52 commit: fix const declaration [removes const]
|
||||
*/
|
||||
git_commit* const parents[1] = { parent };
|
||||
#else
|
||||
// For libgit2 versions older than 1.8.0
|
||||
// For libgit2 versions older than 1.8.0, or equal to 1.8.2, or 1.8.4+
|
||||
const git_commit* parents[1] = { parent };
|
||||
#endif
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user