WYSISYG custom pad editor.
Fixes https://gitlab.com/kicad/code/kicad/issues/2153 Fixes https://gitlab.com/kicad/code/kicad/issues/2305
This commit is contained in:
parent
129c16cf7d
commit
da2b7071b4
|
@ -278,6 +278,8 @@ public:
|
|||
|
||||
void PrintMsg( const wxString& text );
|
||||
|
||||
WX_INFOBAR* GetInfoBar() { return m_infoBar; }
|
||||
|
||||
/**
|
||||
* Returns the settings object used in SaveSettings(), and is overloaded in
|
||||
* KICAD_MANAGER_FRAME
|
||||
|
|
|
@ -77,7 +77,7 @@ public:
|
|||
* Returns the set of currently active layers.
|
||||
* @return The set of currently active layers.
|
||||
*/
|
||||
const std::set<unsigned int> GetActiveLayers()
|
||||
const std::set<unsigned int> GetActiveLayers() const
|
||||
{
|
||||
return m_activeLayers;
|
||||
}
|
||||
|
|
|
@ -831,6 +831,12 @@ class SHAPE_POLY_SET : public SHAPE
|
|||
return IterateSegments( aOutline, aOutline, true );
|
||||
}
|
||||
|
||||
///> Returns an iterator object, for the aOutline-th outline in the set (with holes)
|
||||
CONST_SEGMENT_ITERATOR CIterateSegmentsWithHoles() const
|
||||
{
|
||||
return CIterateSegments( 0, OutlineCount() - 1, true );
|
||||
}
|
||||
|
||||
///> Returns an iterator object, for the aOutline-th outline in the set (with holes)
|
||||
CONST_SEGMENT_ITERATOR CIterateSegmentsWithHoles( int aOutline ) const
|
||||
{
|
||||
|
@ -1026,7 +1032,7 @@ class SHAPE_POLY_SET : public SHAPE
|
|||
* @return bool - true if there is a collision, false in any other case.
|
||||
*/
|
||||
bool CollideVertex( const VECTOR2I& aPoint, VERTEX_INDEX& aClosestVertex,
|
||||
int aClearance = 0 );
|
||||
int aClearance = 0 ) const;
|
||||
|
||||
/**
|
||||
* Function CollideEdge
|
||||
|
@ -1039,7 +1045,7 @@ class SHAPE_POLY_SET : public SHAPE
|
|||
* @return bool - true if there is a collision, false in any other case.
|
||||
*/
|
||||
bool CollideEdge( const VECTOR2I& aPoint, VERTEX_INDEX& aClosestVertex,
|
||||
int aClearance = 0 );
|
||||
int aClearance = 0 ) const;
|
||||
|
||||
/**
|
||||
* Constructs BBoxCaches for Contains(), below. These caches MUST be built before a
|
||||
|
|
|
@ -1243,9 +1243,9 @@ bool SHAPE_POLY_SET::Collide( const SEG& aSeg, int aClearance ) const
|
|||
if( polySet.Contains( aSeg.A ) )
|
||||
return true;
|
||||
|
||||
for( SEGMENT_ITERATOR it = ( (SHAPE_POLY_SET*) this )->IterateSegmentsWithHoles(); it; it++ )
|
||||
for( CONST_SEGMENT_ITERATOR it = CIterateSegmentsWithHoles(); it; it++ )
|
||||
{
|
||||
SEG polygonEdge = *it;
|
||||
const SEG polygonEdge = *it;
|
||||
|
||||
if( polygonEdge.Intersect( aSeg, true ) )
|
||||
return true;
|
||||
|
@ -1359,7 +1359,8 @@ void SHAPE_POLY_SET::Append( const VECTOR2I& aP, int aOutline, int aHole )
|
|||
|
||||
|
||||
bool SHAPE_POLY_SET::CollideVertex( const VECTOR2I& aPoint,
|
||||
SHAPE_POLY_SET::VERTEX_INDEX& aClosestVertex, int aClearance )
|
||||
SHAPE_POLY_SET::VERTEX_INDEX& aClosestVertex,
|
||||
int aClearance ) const
|
||||
{
|
||||
// Shows whether there was a collision
|
||||
bool collision = false;
|
||||
|
@ -1371,7 +1372,7 @@ bool SHAPE_POLY_SET::CollideVertex( const VECTOR2I& aPoint,
|
|||
// Convert clearance to double for precission when comparing distances
|
||||
clearance = aClearance;
|
||||
|
||||
for( ITERATOR iterator = IterateWithHoles(); iterator; iterator++ )
|
||||
for( CONST_ITERATOR iterator = CIterateWithHoles(); iterator; iterator++ )
|
||||
{
|
||||
// Get the difference vector between current vertex and aPoint
|
||||
delta = *iterator - aPoint;
|
||||
|
@ -1397,16 +1398,15 @@ bool SHAPE_POLY_SET::CollideVertex( const VECTOR2I& aPoint,
|
|||
|
||||
|
||||
bool SHAPE_POLY_SET::CollideEdge( const VECTOR2I& aPoint,
|
||||
SHAPE_POLY_SET::VERTEX_INDEX& aClosestVertex, int aClearance )
|
||||
SHAPE_POLY_SET::VERTEX_INDEX& aClosestVertex,
|
||||
int aClearance ) const
|
||||
{
|
||||
// Shows whether there was a collision
|
||||
bool collision = false;
|
||||
|
||||
SEGMENT_ITERATOR iterator;
|
||||
|
||||
for( iterator = IterateSegmentsWithHoles(); iterator; iterator++ )
|
||||
for( CONST_SEGMENT_ITERATOR iterator = CIterateSegmentsWithHoles(); iterator; iterator++ )
|
||||
{
|
||||
SEG currentSegment = *iterator;
|
||||
const SEG currentSegment = *iterator;
|
||||
int distance = currentSegment.Distance( aPoint );
|
||||
|
||||
// Check for collisions
|
||||
|
|
|
@ -367,6 +367,9 @@ void DRAWSEGMENT::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerB
|
|||
switch( m_Shape )
|
||||
{
|
||||
case S_CIRCLE:
|
||||
if( width == 0 )
|
||||
TransformCircleToPolygon( aCornerBuffer, GetCenter(), GetRadius() + width / 2, aError );
|
||||
else
|
||||
TransformRingToPolygon( aCornerBuffer, GetCenter(), GetRadius(), aError, width );
|
||||
break;
|
||||
|
||||
|
@ -375,13 +378,17 @@ void DRAWSEGMENT::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerB
|
|||
std::vector<wxPoint> pts;
|
||||
GetRectCorners( &pts );
|
||||
|
||||
if( width == 0 )
|
||||
{
|
||||
aCornerBuffer.NewOutline();
|
||||
|
||||
for( const wxPoint& pt : pts )
|
||||
aCornerBuffer.Append( pt );
|
||||
}
|
||||
|
||||
if( width != 0 ) // Add thick outlines
|
||||
if( width > 0 )
|
||||
{
|
||||
// Add in segments
|
||||
TransformSegmentToPolygon( aCornerBuffer, pts[0], pts[1], aError, width );
|
||||
TransformSegmentToPolygon( aCornerBuffer, pts[1], pts[2], aError, width );
|
||||
TransformSegmentToPolygon( aCornerBuffer, pts[2], pts[3], aError, width );
|
||||
|
@ -420,27 +427,15 @@ void DRAWSEGMENT::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerB
|
|||
point += offset;
|
||||
}
|
||||
|
||||
// If the polygon is not filled, treat it as a closed set of lines
|
||||
if( !IsPolygonFilled() )
|
||||
if( IsPolygonFilled() || width == 0 )
|
||||
{
|
||||
for( size_t ii = 1; ii < poly.size(); ii++ )
|
||||
TransformOvalToPolygon( aCornerBuffer, poly[ii-1], poly[ii], width, aError );
|
||||
|
||||
TransformOvalToPolygon( aCornerBuffer, poly.back(), poly.front(), width, aError );
|
||||
break;
|
||||
}
|
||||
|
||||
// Generate polygons for the outline + clearance
|
||||
// This code is compatible with a polygon with holes linked to external outline
|
||||
// by overlapping segments.
|
||||
|
||||
// Insert the initial polygon:
|
||||
aCornerBuffer.NewOutline();
|
||||
|
||||
for( wxPoint& point : poly )
|
||||
aCornerBuffer.Append( point.x, point.y );
|
||||
}
|
||||
|
||||
if( width != 0 ) // Add thick outlines
|
||||
if( width > 0 )
|
||||
{
|
||||
wxPoint pt1( poly[ poly.size() - 1] );
|
||||
|
||||
|
|
|
@ -586,6 +586,26 @@ bool DRAWSEGMENT::HitTest( const wxPoint& aPosition, int aAccuracy ) const
|
|||
switch( m_Shape )
|
||||
{
|
||||
case S_CIRCLE:
|
||||
{
|
||||
int radius = GetRadius();
|
||||
int dist = KiROUND( EuclideanNorm( aPosition - GetCenter() ) );
|
||||
|
||||
if( m_Width == 0 )
|
||||
{
|
||||
// Filled circle hit-test
|
||||
if( dist <= radius + maxdist )
|
||||
return true;
|
||||
}
|
||||
|
||||
if( m_Width > 0 )
|
||||
{
|
||||
// Ring hit-test
|
||||
if( abs( radius - dist ) <= maxdist )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case S_ARC:
|
||||
{
|
||||
wxPoint relPos = aPosition - GetCenter();
|
||||
|
@ -594,9 +614,6 @@ bool DRAWSEGMENT::HitTest( const wxPoint& aPosition, int aAccuracy ) const
|
|||
|
||||
if( abs( radius - dist ) <= maxdist )
|
||||
{
|
||||
if( m_Shape == S_CIRCLE )
|
||||
return true;
|
||||
|
||||
// For arcs, the test point angle must be >= arc angle start
|
||||
// and <= arc angle end
|
||||
// However angle values > 360 deg are not easy to handle
|
||||
|
@ -649,6 +666,20 @@ bool DRAWSEGMENT::HitTest( const wxPoint& aPosition, int aAccuracy ) const
|
|||
std::vector<wxPoint> pts;
|
||||
GetRectCorners( &pts );
|
||||
|
||||
if( m_Width == 0 )
|
||||
{
|
||||
SHAPE_POLY_SET poly;
|
||||
poly.NewOutline();
|
||||
|
||||
for( const wxPoint& pt : pts )
|
||||
poly.Append( pt );
|
||||
|
||||
if( poly.Collide( VECTOR2I( aPosition ), maxdist ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
if( m_Width > 0 )
|
||||
{
|
||||
if( TestSegmentHit( aPosition, pts[0], pts[1], maxdist )
|
||||
|| TestSegmentHit( aPosition, pts[1], pts[2], maxdist )
|
||||
|| TestSegmentHit( aPosition, pts[2], pts[3], maxdist )
|
||||
|
@ -657,16 +688,15 @@ bool DRAWSEGMENT::HitTest( const wxPoint& aPosition, int aAccuracy ) const
|
|||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case S_POLYGON:
|
||||
{
|
||||
if( !IsPolygonFilled() )
|
||||
{
|
||||
SHAPE_POLY_SET::VERTEX_INDEX i;
|
||||
auto poly = m_Poly; //todo: Fix CollideEdge to be const
|
||||
return poly.CollideEdge( VECTOR2I( aPosition ), i,
|
||||
std::max( maxdist, Millimeter2iu( 0.25 ) ) );
|
||||
SHAPE_POLY_SET::VERTEX_INDEX dummy;
|
||||
return m_Poly.CollideEdge( VECTOR2I( aPosition ), dummy, maxdist );
|
||||
}
|
||||
else
|
||||
return m_Poly.Collide( VECTOR2I( aPosition ), maxdist );
|
||||
|
|
|
@ -291,7 +291,7 @@ public:
|
|||
* Add to the basic shape list
|
||||
*/
|
||||
void AddPrimitives( const std::vector<std::shared_ptr<DRAWSEGMENT>>& aPrimitivesList );
|
||||
|
||||
void AddPrimitive( DRAWSEGMENT* aPrimitive );
|
||||
|
||||
/**
|
||||
* Function SetOrientation
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
#include <view/view_controls.h>
|
||||
#include <widgets/net_selector.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <tools/footprint_editor_tools.h>
|
||||
#include <tools/pad_tool.h>
|
||||
#include <advanced_config.h> // for pad property feature management
|
||||
|
||||
|
||||
|
@ -106,10 +106,10 @@ void PCB_BASE_FRAME::InstallPadOptionsFrame( D_PAD* aPad )
|
|||
// to set the default pad setup
|
||||
if( aPad )
|
||||
{
|
||||
FOOTPRINT_EDITOR_TOOLS* fpTools = m_toolManager->GetTool<FOOTPRINT_EDITOR_TOOLS>();
|
||||
PAD_TOOL* padTools = m_toolManager->GetTool<PAD_TOOL>();
|
||||
|
||||
if( fpTools )
|
||||
fpTools->SetLastPadName( aPad->GetName() );
|
||||
if( padTools )
|
||||
padTools->SetLastPadName( aPad->GetName() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,13 +26,9 @@
|
|||
#include <class_board.h>
|
||||
#include <class_edge_mod.h>
|
||||
#include <class_module.h>
|
||||
#include <collectors.h>
|
||||
#include <config_params.h>
|
||||
#include <confirm.h>
|
||||
#include <dialog_create_array.h>
|
||||
#include <dialog_edit_footprint_for_fp_editor.h>
|
||||
#include <dialog_move_exact.h>
|
||||
#include <fctsys.h>
|
||||
#include <footprint_edit_frame.h>
|
||||
#include <footprint_tree_pane.h>
|
||||
#include <footprint_viewer_frame.h>
|
||||
|
@ -40,28 +36,18 @@
|
|||
#include <fp_lib_table.h>
|
||||
#include <functional>
|
||||
#include <gestfich.h>
|
||||
#include <invoke_pcb_dialog.h>
|
||||
#include <kiface_i.h>
|
||||
#include <kiway.h>
|
||||
#include <kiway_express.h>
|
||||
#include <macros.h>
|
||||
#include <menus_helpers.h>
|
||||
#include <pcb_draw_panel_gal.h>
|
||||
#include <pcb_layer_box_selector.h>
|
||||
#include <pcb_layer_widget.h>
|
||||
#include <pcbnew.h>
|
||||
#include <pcbnew_id.h>
|
||||
#include <pcbnew_settings.h>
|
||||
#include <ratsnest/ratsnest_data.h>
|
||||
|
||||
#include <pgm_base.h>
|
||||
#include <settings/color_settings.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <tools/pcb_actions.h>
|
||||
#include <trigo.h>
|
||||
#include <view/view.h>
|
||||
#include <widgets/lib_tree.h>
|
||||
#include <wildcards_and_files_ext.h>
|
||||
|
||||
using namespace std::placeholders;
|
||||
|
||||
|
|
|
@ -163,6 +163,14 @@ void D_PAD::AddPrimitives( const std::vector<std::shared_ptr<DRAWSEGMENT>>& aPri
|
|||
}
|
||||
|
||||
|
||||
void D_PAD::AddPrimitive( DRAWSEGMENT* aPrimitive )
|
||||
{
|
||||
m_editPrimitives.emplace_back( aPrimitive );
|
||||
|
||||
m_shapesDirty = true;
|
||||
}
|
||||
|
||||
|
||||
// clear the basic shapes list and associated data
|
||||
void D_PAD::DeletePrimitivesList()
|
||||
{
|
||||
|
@ -190,9 +198,7 @@ void D_PAD::addPadPrimitivesToPolygon( SHAPE_POLY_SET* aMergedPolygon, int aErro
|
|||
converter.GetPoly( poly, lineWidth );
|
||||
|
||||
for( unsigned ii = 1; ii < poly.size(); ii++ )
|
||||
{
|
||||
TransformSegmentToPolygon( polyset, poly[ ii - 1 ], poly[ ii ], aError, lineWidth );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -210,9 +216,9 @@ void D_PAD::addPadPrimitivesToPolygon( SHAPE_POLY_SET* aMergedPolygon, int aErro
|
|||
break;
|
||||
}
|
||||
|
||||
case S_CIRCLE: // ring or circle
|
||||
case S_CIRCLE:
|
||||
{
|
||||
if( primitive->GetWidth() ) // ring
|
||||
if( lineWidth ) // Ring
|
||||
{
|
||||
TransformRingToPolygon( polyset, primitive->GetStart(), primitive->GetRadius(),
|
||||
aError, lineWidth );
|
||||
|
@ -226,23 +232,39 @@ void D_PAD::addPadPrimitivesToPolygon( SHAPE_POLY_SET* aMergedPolygon, int aErro
|
|||
}
|
||||
|
||||
case S_RECT:
|
||||
case S_POLYGON: // polygon
|
||||
{
|
||||
wxPoint corners[4];
|
||||
|
||||
corners[0] = primitive->GetStart();
|
||||
corners[1] = wxPoint( primitive->GetEnd().x, primitive->GetStart().y );
|
||||
corners[2] = primitive->GetEnd();
|
||||
corners[3] = wxPoint( primitive->GetStart().x, primitive->GetEnd().y );
|
||||
|
||||
if( lineWidth ) // Rect boundary
|
||||
{
|
||||
TransformSegmentToPolygon( polyset, corners[0], corners[1], aError, lineWidth );
|
||||
TransformSegmentToPolygon( polyset, corners[1], corners[2], aError, lineWidth );
|
||||
TransformSegmentToPolygon( polyset, corners[2], corners[3], aError, lineWidth );
|
||||
TransformSegmentToPolygon( polyset, corners[3], corners[0], aError, lineWidth );
|
||||
}
|
||||
else // Filled rect
|
||||
{
|
||||
// Insert the polygon:
|
||||
polyset.NewOutline();
|
||||
|
||||
for( const wxPoint& corner : corners )
|
||||
polyset.Append( corner );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case S_POLYGON:
|
||||
{
|
||||
SHAPE_POLY_SET poly;
|
||||
poly.NewOutline();
|
||||
|
||||
if( primitive->GetShape() == S_RECT )
|
||||
{
|
||||
poly.Append( primitive->GetStart() );
|
||||
poly.Append( primitive->GetEnd().x, primitive->GetStart().y );
|
||||
poly.Append( primitive->GetEnd() );
|
||||
poly.Append( primitive->GetStart().x, primitive->GetEnd().y );
|
||||
}
|
||||
else
|
||||
{
|
||||
for( const VECTOR2I& pt : primitive->GetPolyShape().Outline( 0 ).CPoints() )
|
||||
poly.Append( pt );
|
||||
}
|
||||
|
||||
if( primitive->GetWidth() > 0 )
|
||||
{
|
||||
|
|
|
@ -25,14 +25,12 @@
|
|||
*/
|
||||
|
||||
#include <limits>
|
||||
#include <class_board.h>
|
||||
#include <class_module.h>
|
||||
#include <class_edge_mod.h>
|
||||
#include <collectors.h>
|
||||
#include <pcb_edit_frame.h>
|
||||
#include <ws_proxy_view_item.h>
|
||||
#include <kiway.h>
|
||||
#include <footprint_edit_frame.h>
|
||||
#include <array_creator.h>
|
||||
#include <pcbnew_settings.h>
|
||||
#include <status_popup.h>
|
||||
|
@ -43,7 +41,7 @@
|
|||
#include <tools/pcbnew_picker_tool.h>
|
||||
#include <tools/tool_event_utils.h>
|
||||
#include <tools/grid_helper.h>
|
||||
#include <tools/footprint_editor_tools.h>
|
||||
#include <tools/pad_tool.h>
|
||||
#include <pad_naming.h>
|
||||
#include <view/view_controls.h>
|
||||
#include <connectivity/connectivity_data.h>
|
||||
|
@ -210,7 +208,7 @@ bool EDIT_TOOL::Init()
|
|||
|
||||
// Footprint actions
|
||||
menu.AddSeparator();
|
||||
menu.AddItem( PCB_ACTIONS::editFootprintInFpEditor, singleModuleCondition );
|
||||
menu.AddItem( PCB_ACTIONS::editFpInFpEditor, singleModuleCondition );
|
||||
menu.AddItem( PCB_ACTIONS::updateFootprint, singleModuleCondition );
|
||||
menu.AddItem( PCB_ACTIONS::changeFootprint, singleModuleCondition );
|
||||
|
||||
|
@ -1200,10 +1198,10 @@ int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent )
|
|||
if( increment && item->Type() == PCB_PAD_T
|
||||
&& PAD_NAMING::PadCanHaveName( *static_cast<D_PAD*>( dupe_item ) ) )
|
||||
{
|
||||
FOOTPRINT_EDITOR_TOOLS* modEdit = m_toolMgr->GetTool<FOOTPRINT_EDITOR_TOOLS>();
|
||||
wxString padName = modEdit->GetLastPadName();
|
||||
PAD_TOOL* padTool = m_toolMgr->GetTool<PAD_TOOL>();
|
||||
wxString padName = padTool->GetLastPadName();
|
||||
padName = editModule->GetNextPadName( padName );
|
||||
modEdit->SetLastPadName( padName );
|
||||
padTool->SetLastPadName( padName );
|
||||
static_cast<D_PAD*>( dupe_item )->SetName( padName );
|
||||
}
|
||||
}
|
||||
|
@ -1341,34 +1339,6 @@ bool EDIT_TOOL::updateModificationPoint( PCBNEW_SELECTION& aSelection )
|
|||
}
|
||||
|
||||
|
||||
int EDIT_TOOL::EditFpInFpEditor( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
const auto& selection = m_selectionTool->RequestSelection( FootprintFilter );
|
||||
|
||||
if( selection.Empty() )
|
||||
return 0;
|
||||
|
||||
MODULE* mod = selection.FirstOfKind<MODULE>();
|
||||
|
||||
if( !mod )
|
||||
return 0;
|
||||
|
||||
PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
|
||||
|
||||
auto editor = (FOOTPRINT_EDIT_FRAME*) editFrame->Kiway().Player( FRAME_FOOTPRINT_EDITOR, true );
|
||||
|
||||
editor->Load_Module_From_BOARD( mod );
|
||||
|
||||
editor->Show( true );
|
||||
editor->Raise(); // Iconize( false );
|
||||
|
||||
if( selection.IsHover() )
|
||||
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool EDIT_TOOL::pickCopyReferencePoint( VECTOR2I& aReferencePoint )
|
||||
{
|
||||
std::string tool = "pcbnew.InteractiveEdit.selectReferencePoint";
|
||||
|
@ -1492,8 +1462,6 @@ void EDIT_TOOL::setTransitions()
|
|||
Go( &EDIT_TOOL::Mirror, PCB_ACTIONS::mirror.MakeEvent() );
|
||||
Go( &EDIT_TOOL::ChangeTrackWidth, PCB_ACTIONS::changeTrackWidth.MakeEvent() );
|
||||
|
||||
Go( &EDIT_TOOL::EditFpInFpEditor, PCB_ACTIONS::editFootprintInFpEditor.MakeEvent() );
|
||||
|
||||
Go( &EDIT_TOOL::copyToClipboard, ACTIONS::copy.MakeEvent() );
|
||||
Go( &EDIT_TOOL::cutToClipboard, ACTIONS::cut.MakeEvent() );
|
||||
}
|
||||
|
|
|
@ -176,8 +176,6 @@ private:
|
|||
///> selected items.
|
||||
bool updateModificationPoint( PCBNEW_SELECTION& aSelection );
|
||||
|
||||
int EditFpInFpEditor( const TOOL_EVENT& aEvent );
|
||||
|
||||
bool invokeInlineRouter( int aDragMode );
|
||||
bool isInteractiveDragEnabled() const;
|
||||
|
||||
|
|
|
@ -24,21 +24,16 @@
|
|||
*/
|
||||
|
||||
#include "footprint_editor_tools.h"
|
||||
#include <pad_naming.h>
|
||||
#include "kicad_clipboard.h"
|
||||
#include "selection_tool.h"
|
||||
#include <core/optional.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <tools/pcb_actions.h>
|
||||
#include <view/view_controls.h>
|
||||
#include <pcb_painter.h>
|
||||
#include <footprint_edit_frame.h>
|
||||
#include <pcbnew_id.h>
|
||||
#include <confirm.h>
|
||||
#include <bitmaps.h>
|
||||
#include <class_module.h>
|
||||
#include <class_edge_mod.h>
|
||||
#include <board_commit.h>
|
||||
#include <project.h>
|
||||
#include <fp_lib_table.h>
|
||||
#include <dialogs/dialog_cleanup_graphics.h>
|
||||
|
@ -59,9 +54,6 @@ FOOTPRINT_EDITOR_TOOLS::~FOOTPRINT_EDITOR_TOOLS()
|
|||
void FOOTPRINT_EDITOR_TOOLS::Reset( RESET_REASON aReason )
|
||||
{
|
||||
m_frame = getEditFrame<FOOTPRINT_EDIT_FRAME>();
|
||||
|
||||
if( aReason == MODEL_RELOAD )
|
||||
m_lastPadName = wxT( "1" );
|
||||
}
|
||||
|
||||
|
||||
|
@ -316,322 +308,6 @@ int FOOTPRINT_EDITOR_TOOLS::DefaultPadProperties( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
|
||||
|
||||
int FOOTPRINT_EDITOR_TOOLS::PlacePad( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
if( !m_frame->GetBoard()->GetFirstModule() )
|
||||
return 0;
|
||||
|
||||
struct PAD_PLACER : public INTERACTIVE_PLACER_BASE
|
||||
{
|
||||
PAD_PLACER( FOOTPRINT_EDITOR_TOOLS* aFPEditTools )
|
||||
{
|
||||
m_fpEditTools = aFPEditTools;
|
||||
}
|
||||
|
||||
virtual ~PAD_PLACER()
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<BOARD_ITEM> CreateItem() override
|
||||
{
|
||||
D_PAD* pad = new D_PAD( m_board->GetFirstModule() );
|
||||
|
||||
pad->ImportSettingsFrom( m_frame->GetDesignSettings().m_Pad_Master );
|
||||
|
||||
if( PAD_NAMING::PadCanHaveName( *pad ) )
|
||||
{
|
||||
wxString padName = m_fpEditTools->GetLastPadName();
|
||||
padName = m_board->GetFirstModule()->GetNextPadName( padName );
|
||||
pad->SetName( padName );
|
||||
m_fpEditTools->SetLastPadName( padName );
|
||||
}
|
||||
|
||||
return std::unique_ptr<BOARD_ITEM>( pad );
|
||||
}
|
||||
|
||||
bool PlaceItem( BOARD_ITEM *aItem, BOARD_COMMIT& aCommit ) override
|
||||
{
|
||||
D_PAD* pad = dynamic_cast<D_PAD*>( aItem );
|
||||
|
||||
if( pad )
|
||||
{
|
||||
m_frame->GetDesignSettings().m_Pad_Master.ImportSettingsFrom( *pad );
|
||||
pad->SetLocalCoord();
|
||||
aCommit.Add( aItem );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
FOOTPRINT_EDITOR_TOOLS* m_fpEditTools;
|
||||
};
|
||||
|
||||
PAD_PLACER placer( this );
|
||||
|
||||
doInteractiveItemPlacement( aEvent.GetCommandStr().get(), &placer, _( "Place pad" ),
|
||||
IPO_REPEAT | IPO_SINGLE_CLICK | IPO_ROTATE | IPO_FLIP );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int FOOTPRINT_EDITOR_TOOLS::ExplodePadToShapes( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
PCBNEW_SELECTION& selection = m_toolMgr->GetTool<SELECTION_TOOL>()->GetSelection();
|
||||
BOARD_COMMIT commit( m_frame );
|
||||
|
||||
if( selection.Size() != 1 )
|
||||
return 0;
|
||||
|
||||
if( selection[0]->Type() != PCB_PAD_T )
|
||||
return 0;
|
||||
|
||||
auto pad = static_cast<D_PAD*>( selection[0] );
|
||||
|
||||
if( pad->GetShape() != PAD_SHAPE_CUSTOM )
|
||||
return 0;
|
||||
|
||||
commit.Modify( pad );
|
||||
|
||||
wxPoint anchor = pad->GetPosition();
|
||||
|
||||
for( const std::shared_ptr<DRAWSEGMENT>& primitive : pad->GetPrimitives() )
|
||||
{
|
||||
EDGE_MODULE* ds = new EDGE_MODULE( board()->GetFirstModule() );
|
||||
|
||||
ds->SetShape( primitive->GetShape() );
|
||||
ds->SetWidth( primitive->GetWidth() );
|
||||
ds->SetStart( primitive->GetStart() );
|
||||
ds->SetEnd( primitive->GetEnd() );
|
||||
ds->SetBezControl1( primitive->GetBezControl1() );
|
||||
ds->SetBezControl2( primitive->GetBezControl2() );
|
||||
ds->SetAngle( primitive->GetAngle() );
|
||||
ds->SetPolyShape( primitive->GetPolyShape() );
|
||||
ds->SetLocalCoord();
|
||||
|
||||
// Fix an arbitray draw layer for this EDGE_MODULE
|
||||
ds->SetLayer( Dwgs_User ); //pad->GetLayer() );
|
||||
ds->Move( anchor );
|
||||
ds->Rotate( anchor, pad->GetOrientation() );
|
||||
|
||||
commit.Add( ds );
|
||||
}
|
||||
|
||||
pad->SetShape( pad->GetAnchorPadShape() );
|
||||
// Cleanup the pad primitives data, because the initial pad was a custom
|
||||
// shaped pad, and it contains primitives, that does not exist in non custom pads,
|
||||
// and can create issues later:
|
||||
if( pad->GetShape() != PAD_SHAPE_CUSTOM ) // should be always the case
|
||||
{
|
||||
pad->DeletePrimitivesList();
|
||||
}
|
||||
|
||||
commit.Push( _("Explode pad to shapes") );
|
||||
|
||||
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int FOOTPRINT_EDITOR_TOOLS::CreatePadFromShapes( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
PCBNEW_SELECTION& selection = m_toolMgr->GetTool<SELECTION_TOOL>()->GetSelection();
|
||||
|
||||
std::unique_ptr<D_PAD> pad( new D_PAD( board()->GetFirstModule() ) );
|
||||
D_PAD *refPad = nullptr;
|
||||
bool multipleRefPadsFound = false;
|
||||
bool illegalItemsFound = false;
|
||||
|
||||
std::vector<std::shared_ptr<DRAWSEGMENT>> shapes;
|
||||
|
||||
BOARD_COMMIT commit( m_frame );
|
||||
|
||||
for( EDA_ITEM* item : selection )
|
||||
{
|
||||
switch( item->Type() )
|
||||
{
|
||||
case PCB_PAD_T:
|
||||
{
|
||||
if( refPad )
|
||||
multipleRefPadsFound = true;
|
||||
|
||||
refPad = static_cast<D_PAD*>( item );
|
||||
break;
|
||||
}
|
||||
|
||||
case PCB_MODULE_EDGE_T:
|
||||
{
|
||||
EDGE_MODULE* em = static_cast<EDGE_MODULE*>( item );
|
||||
DRAWSEGMENT* ds = new DRAWSEGMENT;
|
||||
|
||||
ds->SetShape( em->GetShape() );
|
||||
ds->SetWidth( em->GetWidth() );
|
||||
ds->SetStart( em->GetStart() );
|
||||
ds->SetEnd( em->GetEnd() );
|
||||
ds->SetBezControl1( em->GetBezControl1() );
|
||||
ds->SetBezControl2( em->GetBezControl2() );
|
||||
ds->SetAngle( em->GetAngle() );
|
||||
ds->SetPolyShape( em->GetPolyShape() );
|
||||
shapes.emplace_back( ds );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
illegalItemsFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( refPad && selection.Size() == 1 )
|
||||
{
|
||||
// don't convert a pad into itself...
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( multipleRefPadsFound )
|
||||
{
|
||||
DisplayErrorMessage( m_frame, _( "Cannot convert items to a custom-shaped pad:\n"
|
||||
"selection contains more than one reference pad." ) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( illegalItemsFound )
|
||||
{
|
||||
DisplayErrorMessage( m_frame, _( "Cannot convert items to a custom-shaped pad:\n"
|
||||
"selection contains unsupported items.\n"
|
||||
"Only graphical lines, circles, arcs and polygons "
|
||||
"are allowed." ) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
double deltaAngle = 0.0;
|
||||
|
||||
if( refPad && refPad->GetShape() == PAD_SHAPE_CUSTOM )
|
||||
{
|
||||
// it's already a pad anchor
|
||||
}
|
||||
else if( refPad )
|
||||
{
|
||||
pad.reset( static_cast<D_PAD*>( refPad->Clone() ) );
|
||||
|
||||
if( refPad->GetShape() == PAD_SHAPE_RECT )
|
||||
{
|
||||
pad->SetAnchorPadShape( PAD_SHAPE_RECT );
|
||||
deltaAngle = 0.0;
|
||||
}
|
||||
else if( refPad->GetShape() == PAD_SHAPE_CIRCLE )
|
||||
{
|
||||
pad->SetAnchorPadShape( PAD_SHAPE_CIRCLE );
|
||||
deltaAngle = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a new minimally-sized circular anchor and convert existing pad
|
||||
// to a polygon primitive
|
||||
pad->SetAnchorPadShape( PAD_SHAPE_CIRCLE );
|
||||
int r = refPad->GetDrillSize().x + Millimeter2iu( 0.2 );
|
||||
pad->SetSize( wxSize( r, r ) );
|
||||
pad->SetOffset( wxPoint( 0, 0 ) );
|
||||
|
||||
SHAPE_POLY_SET existingOutline;
|
||||
int maxError = board()->GetDesignSettings().m_MaxError;
|
||||
refPad->TransformShapeWithClearanceToPolygon( existingOutline, 0, maxError );
|
||||
|
||||
DRAWSEGMENT* shape = new DRAWSEGMENT;
|
||||
shape->SetShape( S_POLYGON );
|
||||
shape->SetPolyShape( existingOutline );
|
||||
|
||||
shapes.emplace_back( shape );
|
||||
|
||||
deltaAngle = refPad->GetOrientation();
|
||||
pad->SetOrientation( 0.0 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a default pad anchor:
|
||||
pad->SetAnchorPadShape( PAD_SHAPE_CIRCLE );
|
||||
pad->SetAttribute( PAD_ATTRIB_SMD );
|
||||
pad->SetLayerSet( D_PAD::SMDMask() );
|
||||
int radius = Millimeter2iu( 0.2 );
|
||||
pad->SetSize( wxSize( radius, radius ) );
|
||||
pad->SetOrientation( 0 );
|
||||
|
||||
if( PAD_NAMING::PadCanHaveName( *pad ) )
|
||||
{
|
||||
wxString padName = GetLastPadName();
|
||||
padName = board()->GetFirstModule()->GetNextPadName( padName );
|
||||
pad->SetName( padName );
|
||||
SetLastPadName( padName );
|
||||
}
|
||||
}
|
||||
|
||||
pad->SetShape ( PAD_SHAPE_CUSTOM );
|
||||
|
||||
OPT<VECTOR2I> anchor;
|
||||
VECTOR2I tmp;
|
||||
|
||||
if( refPad )
|
||||
{
|
||||
anchor = VECTOR2I( pad->GetPosition() );
|
||||
}
|
||||
else if( pad->GetBestAnchorPosition( tmp ) )
|
||||
{
|
||||
anchor = tmp;
|
||||
}
|
||||
|
||||
if( !anchor )
|
||||
{
|
||||
DisplayErrorMessage( m_frame, _( "Cannot convert items to a custom-shaped pad:\n"
|
||||
"unable to determine the anchor point position.\n"
|
||||
"Consider adding a small anchor pad to the selection "
|
||||
"and try again.") );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// relocate the shapes, they are relative to the anchor pad position
|
||||
for( std::shared_ptr<DRAWSEGMENT>& shape : shapes )
|
||||
{
|
||||
shape->Move( wxPoint( -anchor->x, -anchor->y ) );
|
||||
shape->Rotate( wxPoint( 0, 0 ), -deltaAngle );
|
||||
}
|
||||
|
||||
pad->SetPosition( wxPoint( anchor->x, anchor->y ) );
|
||||
pad->Rotate( wxPoint( anchor->x, anchor->y ), deltaAngle );
|
||||
pad->AddPrimitives( shapes );
|
||||
pad->ClearFlags();
|
||||
|
||||
SHAPE_POLY_SET mergedPolygon;
|
||||
pad->MergePrimitivesAsPolygon( &mergedPolygon );
|
||||
|
||||
if( mergedPolygon.OutlineCount() > 1 )
|
||||
{
|
||||
DisplayErrorMessage( m_frame, _( "Cannot convert items to a custom-shaped pad:\n"
|
||||
"selected items do not form a single solid shape.") );
|
||||
return 0;
|
||||
}
|
||||
|
||||
D_PAD* padPtr = pad.release();
|
||||
|
||||
commit.Add( padPtr );
|
||||
|
||||
for ( EDA_ITEM* item : selection )
|
||||
commit.Remove( item );
|
||||
|
||||
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
|
||||
commit.Push(_("Create Pad from Selected Shapes") );
|
||||
m_toolMgr->RunAction( PCB_ACTIONS::selectItem, true, padPtr );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int FOOTPRINT_EDITOR_TOOLS::CleanupGraphics( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
FOOTPRINT_EDIT_FRAME* editFrame = getEditFrame<FOOTPRINT_EDIT_FRAME>();
|
||||
|
@ -669,8 +345,4 @@ void FOOTPRINT_EDITOR_TOOLS::setTransitions()
|
|||
Go( &FOOTPRINT_EDITOR_TOOLS::ToggleFootprintTree, PCB_ACTIONS::toggleFootprintTree.MakeEvent() );
|
||||
Go( &FOOTPRINT_EDITOR_TOOLS::Properties, PCB_ACTIONS::footprintProperties.MakeEvent() );
|
||||
Go( &FOOTPRINT_EDITOR_TOOLS::DefaultPadProperties, PCB_ACTIONS::defaultPadProperties.MakeEvent() );
|
||||
|
||||
Go( &FOOTPRINT_EDITOR_TOOLS::PlacePad, PCB_ACTIONS::placePad.MakeEvent() );
|
||||
Go( &FOOTPRINT_EDITOR_TOOLS::CreatePadFromShapes, PCB_ACTIONS::createPadFromShapes.MakeEvent() );
|
||||
Go( &FOOTPRINT_EDITOR_TOOLS::ExplodePadToShapes, PCB_ACTIONS::explodePadToShapes.MakeEvent() );
|
||||
}
|
||||
|
|
|
@ -74,36 +74,6 @@ public:
|
|||
*/
|
||||
int DefaultPadProperties( const TOOL_EVENT& aEvent );
|
||||
|
||||
/**
|
||||
* Function PlacePad()
|
||||
* Places a pad in module editor.
|
||||
*/
|
||||
int PlacePad( const TOOL_EVENT& aEvent );
|
||||
|
||||
/**
|
||||
* Function CreateArray
|
||||
*
|
||||
* Creates an array of objects using settings from a dialog
|
||||
*/
|
||||
int CreateArray( TOOL_EVENT& aEvent );
|
||||
|
||||
/**
|
||||
* Function CreatePadFromShapes()
|
||||
*
|
||||
* Creates a custom-shaped pad from a set of selected graphical shapes
|
||||
*/
|
||||
int CreatePadFromShapes( const TOOL_EVENT& aEvent );
|
||||
|
||||
/**
|
||||
* Function ExplodePadToShapes()
|
||||
*
|
||||
* Breaks apart a complex-shaped part into a set of graphical shapes
|
||||
*/
|
||||
int ExplodePadToShapes( const TOOL_EVENT& aEvent );
|
||||
|
||||
wxString GetLastPadName() const { return m_lastPadName; }
|
||||
void SetLastPadName( const wxString& aPadName ) { m_lastPadName = aPadName; }
|
||||
|
||||
private:
|
||||
///> Sets up handlers for various events.
|
||||
void setTransitions() override;
|
||||
|
@ -111,8 +81,6 @@ private:
|
|||
private:
|
||||
FOOTPRINT_EDIT_FRAME* m_frame;
|
||||
|
||||
wxString m_lastPadName;
|
||||
|
||||
// A private clipboard for cut/copy/past of an entire footprint
|
||||
std::unique_ptr<MODULE> m_copiedModule;
|
||||
};
|
||||
|
|
|
@ -30,19 +30,21 @@
|
|||
#include <bitmaps.h>
|
||||
#include <class_board_item.h>
|
||||
#include <class_module.h>
|
||||
#include <class_edge_mod.h>
|
||||
#include <board_commit.h>
|
||||
#include <dialogs/dialog_push_pad_properties.h>
|
||||
#include <tools/pcb_actions.h>
|
||||
#include <tools/selection_tool.h>
|
||||
#include <tools/pcb_selection_conditions.h>
|
||||
#include <tools/edit_tool.h>
|
||||
#include <tools/footprint_editor_tools.h>
|
||||
#include <dialogs/dialog_enum_pads.h>
|
||||
|
||||
#include <pad_naming.h>
|
||||
#include <widgets/infobar.h>
|
||||
|
||||
PAD_TOOL::PAD_TOOL() :
|
||||
PCB_TOOL_BASE( "pcbnew.PadTool" ),
|
||||
m_padCopied( false )
|
||||
m_padCopied( false ),
|
||||
m_editPad( niluuid )
|
||||
{}
|
||||
|
||||
|
||||
|
@ -52,7 +54,11 @@ PAD_TOOL::~PAD_TOOL()
|
|||
|
||||
void PAD_TOOL::Reset( RESET_REASON aReason )
|
||||
{
|
||||
if( aReason == MODEL_RELOAD )
|
||||
m_lastPadName = wxT( "1" );
|
||||
|
||||
m_padCopied = false;
|
||||
m_editPad = niluuid;
|
||||
}
|
||||
|
||||
|
||||
|
@ -69,13 +75,24 @@ bool PAD_TOOL::Init()
|
|||
SELECTION_CONDITION singlePadSel = SELECTION_CONDITIONS::Count( 1 ) &&
|
||||
SELECTION_CONDITIONS::OnlyType( PCB_PAD_T );
|
||||
|
||||
auto explodeCondition = [&]( const SELECTION& aSel )
|
||||
{
|
||||
return m_editPad == niluuid
|
||||
&& aSel.Size() == 1 && aSel[0]->Type() == PCB_PAD_T;
|
||||
};
|
||||
|
||||
auto recombineCondition = [&]( const SELECTION& aSel )
|
||||
{
|
||||
return m_editPad != niluuid;
|
||||
};
|
||||
|
||||
menu.AddSeparator( 400 );
|
||||
|
||||
if( m_editModules )
|
||||
{
|
||||
menu.AddItem( PCB_ACTIONS::enumeratePads, SELECTION_CONDITIONS::ShowAlways, 400 );
|
||||
menu.AddItem( PCB_ACTIONS::createPadFromShapes, SELECTION_CONDITIONS::NotEmpty, 400 );
|
||||
menu.AddItem( PCB_ACTIONS::explodePadToShapes, singlePadSel, 400 );
|
||||
menu.AddItem( PCB_ACTIONS::recombinePad, recombineCondition, 400 );
|
||||
menu.AddItem( PCB_ACTIONS::explodePad, explodeCondition, 400 );
|
||||
}
|
||||
|
||||
menu.AddItem( PCB_ACTIONS::copyPadSettings, singlePadSel, 400 );
|
||||
|
@ -263,7 +280,6 @@ int PAD_TOOL::EnumeratePads( const TOOL_EVENT& aEvent )
|
|||
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
|
||||
getViewControls()->ShowCursor( true );
|
||||
|
||||
FOOTPRINT_EDITOR_TOOLS* fpTools = m_toolMgr->GetTool<FOOTPRINT_EDITOR_TOOLS>();
|
||||
KIGFX::VIEW* view = m_toolMgr->GetView();
|
||||
VECTOR2I oldCursorPos; // store the previous mouse cursor position, during mouse drag
|
||||
std::list<D_PAD*> selectedPads;
|
||||
|
@ -352,7 +368,7 @@ int PAD_TOOL::EnumeratePads( const TOOL_EVENT& aEvent )
|
|||
wxString newName = wxString::Format( wxT( "%s%d" ), padPrefix, newval );
|
||||
oldNames[newName] = { newval, pad->GetName() };
|
||||
pad->SetName( newName );
|
||||
fpTools->SetLastPadName( newName );
|
||||
SetLastPadName( newName );
|
||||
pad->SetSelected();
|
||||
getView()->Update( pad );
|
||||
|
||||
|
@ -375,7 +391,7 @@ int PAD_TOOL::EnumeratePads( const TOOL_EVENT& aEvent )
|
|||
{
|
||||
storedPadNumbers.push_back( it->second.first );
|
||||
pad->SetName( it->second.second );
|
||||
fpTools->SetLastPadName( it->second.second );
|
||||
SetLastPadName( it->second.second );
|
||||
oldNames.erase( it );
|
||||
|
||||
int newval = storedPadNumbers.front();
|
||||
|
@ -422,11 +438,273 @@ int PAD_TOOL::EnumeratePads( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
|
||||
|
||||
int PAD_TOOL::PlacePad( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
if( !board()->GetFirstModule() )
|
||||
return 0;
|
||||
|
||||
struct PAD_PLACER : public INTERACTIVE_PLACER_BASE
|
||||
{
|
||||
PAD_PLACER( PAD_TOOL* aPadTool )
|
||||
{
|
||||
m_padTool = aPadTool;
|
||||
}
|
||||
|
||||
virtual ~PAD_PLACER()
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<BOARD_ITEM> CreateItem() override
|
||||
{
|
||||
D_PAD* pad = new D_PAD( m_board->GetFirstModule() );
|
||||
|
||||
pad->ImportSettingsFrom( m_frame->GetDesignSettings().m_Pad_Master );
|
||||
|
||||
if( PAD_NAMING::PadCanHaveName( *pad ) )
|
||||
{
|
||||
wxString padName = m_padTool->GetLastPadName();
|
||||
padName = m_board->GetFirstModule()->GetNextPadName( padName );
|
||||
pad->SetName( padName );
|
||||
m_padTool->SetLastPadName( padName );
|
||||
}
|
||||
|
||||
return std::unique_ptr<BOARD_ITEM>( pad );
|
||||
}
|
||||
|
||||
bool PlaceItem( BOARD_ITEM *aItem, BOARD_COMMIT& aCommit ) override
|
||||
{
|
||||
D_PAD* pad = dynamic_cast<D_PAD*>( aItem );
|
||||
|
||||
if( pad )
|
||||
{
|
||||
m_frame->GetDesignSettings().m_Pad_Master.ImportSettingsFrom( *pad );
|
||||
pad->SetLocalCoord();
|
||||
aCommit.Add( aItem );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
PAD_TOOL* m_padTool;
|
||||
};
|
||||
|
||||
PAD_PLACER placer( this );
|
||||
|
||||
doInteractiveItemPlacement( aEvent.GetCommandStr().get(), &placer, _( "Place pad" ),
|
||||
IPO_REPEAT | IPO_SINGLE_CLICK | IPO_ROTATE | IPO_FLIP );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int PAD_TOOL::EditPad( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
PCB_DISPLAY_OPTIONS opts = frame()->GetDisplayOptions();
|
||||
WX_INFOBAR* infoBar = frame()->GetInfoBar();
|
||||
PCBNEW_SELECTION& selection = m_toolMgr->GetTool<SELECTION_TOOL>()->GetSelection();
|
||||
wxString msg;
|
||||
|
||||
if( m_editPad != niluuid )
|
||||
{
|
||||
D_PAD* pad = dynamic_cast<D_PAD*>( frame()->GetItem( m_editPad ) );
|
||||
|
||||
if( pad )
|
||||
recombinePad( pad );
|
||||
|
||||
m_editPad = niluuid;
|
||||
}
|
||||
else if( selection.Size() == 1 && selection[0]->Type() == PCB_PAD_T )
|
||||
{
|
||||
D_PAD* pad = static_cast<D_PAD*>( selection[0] );
|
||||
PCB_LAYER_ID layer = explodePad( pad );
|
||||
|
||||
m_wasHighContrast = opts.m_ContrastModeDisplay;
|
||||
frame()->SetActiveLayer( layer );
|
||||
|
||||
if( !opts.m_ContrastModeDisplay )
|
||||
m_toolMgr->RunAction( ACTIONS::highContrastMode, false );
|
||||
|
||||
if( PCB_ACTIONS::explodePad.GetHotKey() == PCB_ACTIONS::recombinePad.GetHotKey() )
|
||||
msg.Printf( _( "Pad Edit Mode. Press %s again to exit." ),
|
||||
KeyNameFromKeyCode( PCB_ACTIONS::recombinePad.GetHotKey() ) );
|
||||
else
|
||||
msg.Printf( _( "Pad Edit Mode. Press %s to exit." ),
|
||||
KeyNameFromKeyCode( PCB_ACTIONS::recombinePad.GetHotKey() ) );
|
||||
|
||||
infoBar->RemoveAllButtons();
|
||||
infoBar->ShowMessage( msg, wxICON_INFORMATION );
|
||||
|
||||
m_editPad = pad->m_Uuid;
|
||||
}
|
||||
|
||||
if( m_editPad == niluuid )
|
||||
{
|
||||
if( m_wasHighContrast != opts.m_ContrastModeDisplay )
|
||||
m_toolMgr->RunAction( ACTIONS::highContrastMode, false );
|
||||
|
||||
infoBar->Dismiss();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
PCB_LAYER_ID PAD_TOOL::explodePad( D_PAD* aPad )
|
||||
{
|
||||
PCB_LAYER_ID layer;
|
||||
BOARD_COMMIT commit( frame() );
|
||||
|
||||
if( aPad->IsOnLayer( F_Cu ) )
|
||||
layer = F_Cu;
|
||||
else if( aPad->IsOnLayer( B_Cu ) )
|
||||
layer = B_Cu;
|
||||
else
|
||||
layer = *aPad->GetLayerSet().UIOrder();
|
||||
|
||||
if( aPad->GetShape() == PAD_SHAPE_CUSTOM )
|
||||
{
|
||||
commit.Modify( aPad );
|
||||
|
||||
for( const std::shared_ptr<DRAWSEGMENT>& primitive : aPad->GetPrimitives() )
|
||||
{
|
||||
EDGE_MODULE* ds = new EDGE_MODULE( board()->GetFirstModule() );
|
||||
|
||||
ds->SetShape( primitive->GetShape() );
|
||||
ds->SetWidth( primitive->GetWidth() );
|
||||
ds->SetStart( primitive->GetStart() );
|
||||
ds->SetEnd( primitive->GetEnd() );
|
||||
ds->SetBezControl1( primitive->GetBezControl1() );
|
||||
ds->SetBezControl2( primitive->GetBezControl2() );
|
||||
ds->SetAngle( primitive->GetAngle() );
|
||||
ds->SetPolyShape( primitive->GetPolyShape() );
|
||||
ds->SetLocalCoord();
|
||||
ds->Move( aPad->GetPosition() );
|
||||
ds->Rotate( aPad->GetPosition(), aPad->GetOrientation() );
|
||||
|
||||
ds->SetLayer( layer );
|
||||
|
||||
commit.Add( ds );
|
||||
}
|
||||
|
||||
aPad->SetShape( aPad->GetAnchorPadShape() );
|
||||
aPad->DeletePrimitivesList();
|
||||
m_editPad = aPad->m_Uuid;
|
||||
}
|
||||
|
||||
commit.Push( _("Edit pad shapes") );
|
||||
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
|
||||
return layer;
|
||||
}
|
||||
|
||||
|
||||
void PAD_TOOL::recombinePad( D_PAD* aPad )
|
||||
{
|
||||
auto findNext = [&]( PCB_LAYER_ID aLayer ) -> EDGE_MODULE*
|
||||
{
|
||||
SHAPE_POLY_SET padPoly;
|
||||
aPad->TransformShapeWithClearanceToPolygon( padPoly, 0 );
|
||||
|
||||
for( BOARD_ITEM* item : board()->GetFirstModule()->GraphicalItems() )
|
||||
{
|
||||
DRAWSEGMENT* draw = dynamic_cast<DRAWSEGMENT*>( item );
|
||||
|
||||
if( !draw || ( draw->GetEditFlags() & STRUCT_DELETED ) )
|
||||
continue;
|
||||
|
||||
if( draw->GetLayer() != aLayer )
|
||||
continue;
|
||||
|
||||
SHAPE_POLY_SET drawPoly;
|
||||
draw->TransformShapeWithClearanceToPolygon( drawPoly, 0 );
|
||||
drawPoly.BooleanIntersection( padPoly, SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
if( !drawPoly.IsEmpty() )
|
||||
return (EDGE_MODULE*) item;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
BOARD_COMMIT commit( frame() );
|
||||
PCB_LAYER_ID layer;
|
||||
|
||||
if( aPad->IsOnLayer( F_Cu ) )
|
||||
layer = F_Cu;
|
||||
else if( aPad->IsOnLayer( B_Cu ) )
|
||||
layer = B_Cu;
|
||||
else
|
||||
layer = *aPad->GetLayerSet().UIOrder();
|
||||
|
||||
while( EDGE_MODULE* edge = findNext( layer ) )
|
||||
{
|
||||
commit.Modify( aPad );
|
||||
|
||||
// We've found an intersecting item. First convert the pad to a custom-shape
|
||||
// pad (if it isn't already)
|
||||
//
|
||||
if( aPad->GetShape() == PAD_SHAPE_RECT || aPad->GetShape() == PAD_SHAPE_CIRCLE )
|
||||
{
|
||||
aPad->SetAnchorPadShape( aPad->GetShape() );
|
||||
}
|
||||
else if( aPad->GetShape() != PAD_SHAPE_CUSTOM )
|
||||
{
|
||||
// Create a new minimally-sized circular anchor and convert existing pad
|
||||
// to a polygon primitive
|
||||
SHAPE_POLY_SET existingOutline;
|
||||
int maxError = board()->GetDesignSettings().m_MaxError;
|
||||
aPad->TransformShapeWithClearanceToPolygon( existingOutline, 0, maxError );
|
||||
|
||||
aPad->SetAnchorPadShape( PAD_SHAPE_CIRCLE );
|
||||
int r = aPad->GetDrillSize().x + Millimeter2iu( 0.2 );
|
||||
aPad->SetSize( wxSize( r, r ) );
|
||||
aPad->SetOffset( wxPoint( 0, 0 ) );
|
||||
|
||||
DRAWSEGMENT* shape = new DRAWSEGMENT;
|
||||
shape->SetShape( S_POLYGON );
|
||||
shape->SetPolyShape( existingOutline );
|
||||
shape->Move( - aPad->GetPosition() );
|
||||
shape->Rotate( wxPoint( 0, 0 ), - aPad->GetOrientation() );
|
||||
|
||||
aPad->AddPrimitive( shape );
|
||||
}
|
||||
|
||||
aPad->SetShape( PAD_SHAPE_CUSTOM );
|
||||
|
||||
// Now add the new shape to the primitives list
|
||||
//
|
||||
DRAWSEGMENT* ds = new DRAWSEGMENT;
|
||||
|
||||
ds->SetShape( edge->GetShape() );
|
||||
ds->SetWidth( edge->GetWidth() );
|
||||
ds->SetStart( edge->GetStart() );
|
||||
ds->SetEnd( edge->GetEnd() );
|
||||
ds->SetBezControl1( edge->GetBezControl1() );
|
||||
ds->SetBezControl2( edge->GetBezControl2() );
|
||||
ds->SetAngle( edge->GetAngle() );
|
||||
ds->SetPolyShape( edge->GetPolyShape() );
|
||||
|
||||
ds->Move( - aPad->GetPosition() );
|
||||
ds->Rotate( wxPoint( 0, 0 ), - aPad->GetOrientation() );
|
||||
aPad->AddPrimitive( ds );
|
||||
|
||||
edge->SetFlags( STRUCT_DELETED );
|
||||
commit.Remove( edge );
|
||||
}
|
||||
|
||||
commit.Push(_("Recombine pads") );
|
||||
}
|
||||
|
||||
|
||||
void PAD_TOOL::setTransitions()
|
||||
{
|
||||
Go( &PAD_TOOL::pastePadProperties, PCB_ACTIONS::applyPadSettings.MakeEvent() );
|
||||
Go( &PAD_TOOL::copyPadSettings, PCB_ACTIONS::copyPadSettings.MakeEvent() );
|
||||
Go( &PAD_TOOL::pushPadSettings, PCB_ACTIONS::pushPadSettings.MakeEvent() );
|
||||
|
||||
Go( &PAD_TOOL::PlacePad, PCB_ACTIONS::placePad.MakeEvent() );
|
||||
Go( &PAD_TOOL::EnumeratePads, PCB_ACTIONS::enumeratePads.MakeEvent() );
|
||||
|
||||
Go( &PAD_TOOL::EditPad, PCB_ACTIONS::explodePad.MakeEvent() );
|
||||
Go( &PAD_TOOL::EditPad, PCB_ACTIONS::recombinePad.MakeEvent() );
|
||||
}
|
||||
|
|
|
@ -52,10 +52,31 @@ public:
|
|||
*/
|
||||
int EnumeratePads( const TOOL_EVENT& aEvent );
|
||||
|
||||
/**
|
||||
* Function PlacePad()
|
||||
* Places a pad in module editor.
|
||||
*/
|
||||
int PlacePad( const TOOL_EVENT& aEvent );
|
||||
|
||||
/**
|
||||
* Function CreatePadFromShapes()
|
||||
*
|
||||
* Creates a custom-shaped pad from a set of selected graphical shapes
|
||||
*/
|
||||
int CreatePadFromShapes( const TOOL_EVENT& aEvent );
|
||||
|
||||
/**
|
||||
* Enters/exits WYSIWYG pad shape editing
|
||||
*/
|
||||
int EditPad( const TOOL_EVENT& aEvent );
|
||||
|
||||
wxString GetLastPadName() const { return m_lastPadName; }
|
||||
void SetLastPadName( const wxString& aPadName ) { m_lastPadName = aPadName; }
|
||||
|
||||
private:
|
||||
///> Bind handlers to corresponding TOOL_ACTIONs
|
||||
void setTransitions() override;
|
||||
|
||||
private:
|
||||
///> Determine if there are any footprints on the board
|
||||
bool haveFootprints();
|
||||
|
||||
|
@ -68,8 +89,15 @@ private:
|
|||
///> Push pad settings from a pad to other pads on board or module
|
||||
int pushPadSettings( const TOOL_EVENT& aEvent );
|
||||
|
||||
///> Flag to indicate there are valid settings stored in the Master Pad object
|
||||
bool m_padCopied;
|
||||
PCB_LAYER_ID explodePad( D_PAD* aPad );
|
||||
void recombinePad( D_PAD* aPad );
|
||||
|
||||
private:
|
||||
wxString m_lastPadName;
|
||||
bool m_padCopied; // Indicates there are valid settings in the Master Pad object
|
||||
|
||||
bool m_wasHighContrast;
|
||||
KIID m_editPad;
|
||||
};
|
||||
|
||||
#endif // __PAD_TOOL_H
|
||||
|
|
|
@ -179,7 +179,7 @@ TOOL_ACTION PCB_ACTIONS::runDRC( "pcbnew.DRCTool.runDRC",
|
|||
|
||||
// EDIT_TOOL
|
||||
//
|
||||
TOOL_ACTION PCB_ACTIONS::editFootprintInFpEditor( "pcbnew.InteractiveEdit.EditFpInFpEditor",
|
||||
TOOL_ACTION PCB_ACTIONS::editFpInFpEditor( "pcbnew.EditorControl.EditFpInFpEditor",
|
||||
AS_GLOBAL,
|
||||
MD_CTRL + 'E', LEGACY_HK_NAME( "Edit with Footprint Editor" ),
|
||||
_( "Open in Footprint Editor" ),
|
||||
|
@ -333,36 +333,6 @@ TOOL_ACTION PCB_ACTIONS::footprintProperties( "pcbnew.ModuleEditor.footprintProp
|
|||
_( "Footprint Properties..." ), "",
|
||||
module_options_xpm );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::placePad( "pcbnew.ModuleEditor.placePad",
|
||||
AS_GLOBAL, 0, "",
|
||||
_( "Add Pad" ), _( "Add a pad" ),
|
||||
pad_xpm, AF_ACTIVATE );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::createPadFromShapes( "pcbnew.ModuleEditor.createPadFromShapes",
|
||||
AS_CONTEXT, 0, "",
|
||||
_( "Create Pad from Selected Shapes" ),
|
||||
_( "Creates a custom-shaped pads from a set of selected shapes" ),
|
||||
primitives_to_custom_pad_xpm );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::explodePadToShapes( "pcbnew.ModuleEditor.explodePadToShapes",
|
||||
AS_CONTEXT, 0, "",
|
||||
_( "Explode Pad to Graphic Shapes" ),
|
||||
_( "Converts a custom-shaped pads to a set of graphical shapes" ),
|
||||
custom_pad_to_primitives_xpm );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::defaultPadProperties( "pcbnew.ModuleEditor.defaultPadProperties",
|
||||
AS_GLOBAL, 0, "",
|
||||
_( "Default Pad Properties..." ), _( "Edit the pad properties used when creating new pads" ),
|
||||
options_pad_xpm );
|
||||
|
||||
|
||||
// SHAPE_EDITOR_TOOLS
|
||||
//
|
||||
TOOL_ACTION PCB_ACTIONS::shapeProperties( "pcbnew.ShapeEditor.shapeProperties",
|
||||
AS_GLOBAL, 0, "",
|
||||
_( "Shape Properties..." ), "",
|
||||
options_pad_xpm );
|
||||
|
||||
|
||||
// GLOBAL_EDIT_TOOL
|
||||
//
|
||||
|
@ -475,6 +445,30 @@ TOOL_ACTION PCB_ACTIONS::enumeratePads( "pcbnew.PadTool.enumeratePads",
|
|||
_( "Renumber pads by clicking on them in the desired order" ),
|
||||
pad_enumerate_xpm, AF_ACTIVATE );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::placePad( "pcbnew.PadTool.placePad",
|
||||
AS_GLOBAL, 0, "",
|
||||
_( "Add Pad" ), _( "Add a pad" ),
|
||||
pad_xpm, AF_ACTIVATE );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::explodePad( "pcbnew.PadTool.explodePad",
|
||||
AS_GLOBAL,
|
||||
MD_CTRL + 'E', "",
|
||||
_( "Edit Pad as Graphic Shapes" ),
|
||||
_( "Ungroups a custom-shaped pad for editing as individual graphic shapes" ),
|
||||
custom_pad_to_primitives_xpm );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::recombinePad( "pcbnew.PadTool.recombinePad",
|
||||
AS_GLOBAL,
|
||||
MD_CTRL + 'E', "",
|
||||
_( "Finish Pad Edit" ),
|
||||
_( "Regroups all touching graphic shapes into the edited pad" ),
|
||||
custom_pad_to_primitives_xpm );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::defaultPadProperties( "pcbnew.PadTool.defaultPadProperties",
|
||||
AS_GLOBAL, 0, "",
|
||||
_( "Default Pad Properties..." ), _( "Edit the pad properties used when creating new pads" ),
|
||||
options_pad_xpm );
|
||||
|
||||
|
||||
// PCB_EDITOR_CONTROL
|
||||
//
|
||||
|
|
|
@ -319,7 +319,7 @@ public:
|
|||
static TOOL_ACTION listNets;
|
||||
static TOOL_ACTION runDRC;
|
||||
|
||||
static TOOL_ACTION editFootprintInFpEditor;
|
||||
static TOOL_ACTION editFpInFpEditor;
|
||||
static TOOL_ACTION showLayersManager;
|
||||
static TOOL_ACTION showMicrowaveToolbar;
|
||||
static TOOL_ACTION showPythonConsole;
|
||||
|
@ -350,13 +350,12 @@ public:
|
|||
|
||||
static TOOL_ACTION footprintProperties;
|
||||
static TOOL_ACTION defaultPadProperties;
|
||||
static TOOL_ACTION shapeProperties;
|
||||
|
||||
/// Activation of the drawing tool (placing a PAD)
|
||||
static TOOL_ACTION placePad;
|
||||
|
||||
static TOOL_ACTION createPadFromShapes;
|
||||
static TOOL_ACTION explodePadToShapes;
|
||||
static TOOL_ACTION explodePad;
|
||||
static TOOL_ACTION recombinePad;
|
||||
|
||||
/// Tool for quick pad enumeration
|
||||
static TOOL_ACTION enumeratePads;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "pcb_actions.h"
|
||||
#include "pcbnew_picker_tool.h"
|
||||
#include "selection_tool.h"
|
||||
#include "edit_tool.h"
|
||||
#include <bitmaps.h>
|
||||
#include <board_commit.h>
|
||||
#include <class_board.h>
|
||||
|
@ -57,6 +58,7 @@
|
|||
#include <view/view_group.h>
|
||||
#include <wildcards_and_files_ext.h>
|
||||
#include <ws_proxy_undo_item.h>
|
||||
#include <footprint_edit_frame.h>
|
||||
|
||||
using namespace std::placeholders;
|
||||
|
||||
|
@ -1077,8 +1079,8 @@ int PCB_EDITOR_CONTROL::ZoneMerge( const TOOL_EVENT& aEvent )
|
|||
|
||||
int PCB_EDITOR_CONTROL::ZoneDuplicate( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
auto selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
|
||||
const auto& selection = selTool->GetSelection();
|
||||
SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
|
||||
const SELECTION& selection = selTool->GetSelection();
|
||||
|
||||
// because this pops up the zone editor, it would be confusing to handle multiple zones,
|
||||
// so just handle single selections containing exactly one zone
|
||||
|
@ -1126,6 +1128,35 @@ int PCB_EDITOR_CONTROL::ZoneDuplicate( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
|
||||
|
||||
int PCB_EDITOR_CONTROL::EditFpInFpEditor( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
|
||||
const SELECTION& selection = selTool->RequestSelection( EDIT_TOOL::FootprintFilter );
|
||||
|
||||
if( selection.Empty() )
|
||||
return 0;
|
||||
|
||||
MODULE* mod = selection.FirstOfKind<MODULE>();
|
||||
|
||||
if( !mod )
|
||||
return 0;
|
||||
|
||||
PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
|
||||
|
||||
auto editor = (FOOTPRINT_EDIT_FRAME*) editFrame->Kiway().Player( FRAME_FOOTPRINT_EDITOR, true );
|
||||
|
||||
editor->Load_Module_From_BOARD( mod );
|
||||
|
||||
editor->Show( true );
|
||||
editor->Raise(); // Iconize( false );
|
||||
|
||||
if( selection.IsHover() )
|
||||
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void PCB_EDITOR_CONTROL::DoSetDrillOrigin( KIGFX::VIEW* aView, PCB_BASE_FRAME* aFrame,
|
||||
BOARD_ITEM* originViewItem, const VECTOR2D& aPosition )
|
||||
{
|
||||
|
@ -1203,6 +1234,8 @@ void PCB_EDITOR_CONTROL::setTransitions()
|
|||
Go( &PCB_EDITOR_CONTROL::PlaceModule, PCB_ACTIONS::placeModule.MakeEvent() );
|
||||
Go( &PCB_EDITOR_CONTROL::DrillOrigin, PCB_ACTIONS::drillOrigin.MakeEvent() );
|
||||
|
||||
Go( &PCB_EDITOR_CONTROL::EditFpInFpEditor, PCB_ACTIONS::editFpInFpEditor.MakeEvent() );
|
||||
|
||||
// Other
|
||||
Go( &PCB_EDITOR_CONTROL::ToggleLockSelected, PCB_ACTIONS::toggleLock.MakeEvent() );
|
||||
Go( &PCB_EDITOR_CONTROL::LockSelected, PCB_ACTIONS::lock.MakeEvent() );
|
||||
|
|
|
@ -86,6 +86,8 @@ public:
|
|||
///> Duplicates a zone onto a layer (prompts for new layer)
|
||||
int ZoneDuplicate( const TOOL_EVENT& aEvent );
|
||||
|
||||
int EditFpInFpEditor( const TOOL_EVENT& aEvent );
|
||||
|
||||
/**
|
||||
* Function PlaceTarget()
|
||||
* Allows user to place a layer alignment target.
|
||||
|
|
|
@ -463,8 +463,6 @@ bool SELECTION_TOOL::selectPoint( const VECTOR2I& aWhere, bool aOnDrag,
|
|||
{
|
||||
if( m_selection.GetSize() > 0 )
|
||||
{
|
||||
// Don't fire an event now as it will end up redundant if we fire a SelectedEvent
|
||||
// or an UnselectedEvent.
|
||||
ClearSelection( true /*quiet mode*/ );
|
||||
anySubtracted = true;
|
||||
}
|
||||
|
@ -1525,23 +1523,20 @@ BOARD_ITEM* SELECTION_TOOL::pickSmallestComponent( GENERAL_COLLECTOR* aCollector
|
|||
|
||||
bool SELECTION_TOOL::Selectable( const BOARD_ITEM* aItem, bool checkVisibilityOnly ) const
|
||||
{
|
||||
// Is high contrast mode enabled?
|
||||
bool highContrast = getView()->GetPainter()->GetSettings()->GetHighContrast();
|
||||
const RENDER_SETTINGS* settings = getView()->GetPainter()->GetSettings();
|
||||
|
||||
int layers[KIGFX::VIEW::VIEW_MAX_LAYERS], layers_count;
|
||||
|
||||
// Filter out items that do not belong to active layers
|
||||
std::set<unsigned int> activeLayers = getView()->GetPainter()->GetSettings()->GetActiveLayers();
|
||||
|
||||
aItem->ViewGetLayers( layers, layers_count );
|
||||
|
||||
if( highContrast )
|
||||
if( settings->GetHighContrast() )
|
||||
{
|
||||
int itemLayers[KIGFX::VIEW::VIEW_MAX_LAYERS], layers_count;
|
||||
std::set<unsigned int> activeLayers = settings->GetActiveLayers();
|
||||
|
||||
aItem->ViewGetLayers( itemLayers, layers_count );
|
||||
|
||||
bool onActive = false; // Is the item on any of active layers?
|
||||
|
||||
for( int i = 0; i < layers_count; ++i )
|
||||
{
|
||||
if( activeLayers.count( layers[i] ) > 0 ) // Item is on at least one of the active layers
|
||||
if( activeLayers.count( itemLayers[i] ) > 0 ) // Item is on at least one of the active layers
|
||||
{
|
||||
onActive = true;
|
||||
break;
|
||||
|
@ -1665,7 +1660,7 @@ bool SELECTION_TOOL::Selectable( const BOARD_ITEM* aItem, bool checkVisibilityOn
|
|||
// pick up items under an (unlocked) module without also moving the module's sub-parts.
|
||||
if( !m_editModules && !checkVisibilityOnly )
|
||||
{
|
||||
if( m_multiple && !highContrast )
|
||||
if( m_multiple && !settings->GetHighContrast() )
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue