KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcb_group_tool.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <kiplatform/ui.h>
25#include <tool/tool_manager.h>
29#include <status_popup.h>
30#include <board_commit.h>
32#include <pcb_group.h>
33#include <collectors.h>
34#include <footprint.h>
35#include <wx/string.h>
36
37
38std::shared_ptr<COMMIT> PCB_GROUP_TOOL::createCommit()
39{
40 return std::make_shared<BOARD_COMMIT>( m_toolMgr, m_frame->IsType( FRAME_PCB_EDITOR ),
42}
43
44
45bool PCB_GROUP_TOOL::canGroupItem( EDA_ITEM* aItem, wxString& aErrorMsg ) const
46{
47 if( !aItem || !aItem->IsBOARD_ITEM() )
48 {
49 aErrorMsg = _( "Some selected items cannot be grouped." );
50 return false;
51 }
52
53 bool isFootprintEditor = m_frame->GetFrameType() == FRAME_FOOTPRINT_EDITOR;
54 BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( aItem );
55
56 if( !isFootprintEditor && boardItem->GetParentFootprint() )
57 {
58 aErrorMsg = _( "Footprint items cannot be grouped separately from their parent footprint." );
59 return false;
60 }
61
62 if( !boardItem->IsGroupableType() )
63 {
64 aErrorMsg = _( "Some selected items cannot be grouped." );
65 return false;
66 }
67
68 return true;
69}
70
71
73{
74 bool isFootprintEditor = m_frame->GetFrameType() == FRAME_FOOTPRINT_EDITOR;
75 PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
76 PCB_PICKER_TOOL* picker = m_toolMgr->GetTool<PCB_PICKER_TOOL>();
77
78 STATUS_TEXT_POPUP statusPopup( m_frame );
79 bool done = false;
80
82 m_propertiesDialog->Show( false );
83
84 Activate();
85
86 statusPopup.SetText( _( "Click on new member..." ) );
87
88 picker->SetCursor( KICURSOR::BULLSEYE );
89 picker->SetSnapping( false );
90 picker->ClearHandlers();
91
92 picker->SetClickHandler(
93 [&]( const VECTOR2D& aPoint ) -> bool
94 {
96
97 const PCB_SELECTION& sel = selTool->RequestSelection(
98 []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
99 {
100 } );
101
102 if( sel.Empty() )
103 return true; // still looking for an item
104
105 statusPopup.Hide();
106
108 {
109 EDA_ITEM* elem = sel.Front();
110
111 if( !isFootprintEditor )
112 {
113 while( elem->GetParent() && elem->GetParent()->Type() != PCB_T )
114 elem = elem->GetParent();
115 }
116
117 m_propertiesDialog->DoAddMember( elem );
118 m_propertiesDialog->Show( true );
119 }
120
121 return false; // got our item; don't need any more
122 } );
123
124 picker->SetMotionHandler(
125 [&]( const VECTOR2D& aPos )
126 {
127 statusPopup.Move( KIPLATFORM::UI::GetMousePosition() + wxPoint( 20, -50 ) );
128 } );
129
130 picker->SetCancelHandler(
131 [&]()
132 {
134 m_propertiesDialog->Show( true );
135
136 statusPopup.Hide();
137 } );
138
139 picker->SetFinalizeHandler(
140 [&]( const int& aFinalState )
141 {
142 done = true;
143 } );
144
145 statusPopup.Move( KIPLATFORM::UI::GetMousePosition() + wxPoint( 20, -50 ) );
146 statusPopup.Popup();
147 m_frame->GetCanvas()->SetStatusPopup( statusPopup.GetPanel() );
148
149 m_toolMgr->RunAction( ACTIONS::pickerTool, &aEvent );
150
151 while( !done )
152 {
153 // Pass events unless we receive a null event, then we must shut down
154 if( TOOL_EVENT* evt = Wait() )
155 evt->SetPassEvent();
156 else
157 break;
158 }
159
160 picker->ClearHandlers();
161 m_frame->GetCanvas()->SetStatusPopup( nullptr );
162
163 return 0;
164}
165
166
168{
169 bool isFootprintEditor = m_frame->GetFrameType() == FRAME_FOOTPRINT_EDITOR;
170 PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
171 wxString errorMsg;
172
173 PCB_SELECTION selection = selTool->RequestSelection(
174 [&]( const VECTOR2I&, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* )
175 {
176 // Iterate from the back so we don't have to worry about removals.
177 for( int i = aCollector.GetCount() - 1; i >= 0; --i )
178 {
179 BOARD_ITEM* item = aCollector[i];
180
181 if( !canGroupItem( item, errorMsg ) )
182 aCollector.Remove( item );
183 }
184 } );
185
186 if( selection.GetSize() < 2 )
187 {
188 if( !errorMsg.IsEmpty() )
189 m_frame->ShowInfoBarWarning( errorMsg );
190
191 return 0;
192 }
193
194 BOARD* board = getModel<BOARD>();
195 PCB_GROUP* group = nullptr;
196
197 if( isFootprintEditor )
198 group = new PCB_GROUP( board->GetFirstFootprint() );
199 else
200 group = new PCB_GROUP( board );
201
202 for( EDA_ITEM* eda_item : selection )
203 {
204 if( eda_item->IsBOARD_ITEM() )
205 {
206 if( static_cast<BOARD_ITEM*>( eda_item )->IsLocked() )
207 group->SetLocked( true );
208 }
209 }
210
211 for( EDA_ITEM* eda_item : selection )
212 {
213 if( eda_item->IsBOARD_ITEM() )
214 {
215 if( EDA_GROUP* existingGroup = eda_item->GetParentGroup() )
216 m_commit->Modify( existingGroup->AsEdaItem(), nullptr, RECURSE_MODE::NO_RECURSE );
217
218 m_commit->Modify( eda_item );
219 group->AddItem( eda_item );
220 }
221 }
222
223 m_commit->Add( group );
224 m_commit->Push( _( "Group Items" ) );
225
227 m_toolMgr->RunAction( ACTIONS::selectItem, group->AsEdaItem() );
228
230 m_frame->OnModify();
231
232 if( !errorMsg.IsEmpty() )
233 m_frame->ShowInfoBarWarning( errorMsg );
234
235 return 0;
236}
static TOOL_ACTION selectItem
Select an item (specified as the event parameter).
Definition actions.h:227
static TOOL_ACTION pickerTool
Definition actions.h:253
static TOOL_ACTION selectionClear
Clear the current selection.
Definition actions.h:224
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:84
bool IsGroupableType() const
FOOTPRINT * GetParentFootprint() const
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:323
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition board.h:524
int GetCount() const
Return the number of objects in the list.
Definition collector.h:83
void Remove(int aIndex)
Remove the item at aIndex (first position is 0).
Definition collector.h:111
A set of EDA_ITEMs (i.e., without duplicates).
Definition eda_group.h:46
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:100
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:112
EDA_ITEM * GetParent() const
Definition eda_item.h:114
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition actions.h:352
Used when the right click button is pressed, or when the select tool is in effect.
Definition collectors.h:207
DIALOG_GROUP_PROPERTIES * m_propertiesDialog
Definition group_tool.h:86
EDA_DRAW_FRAME * m_frame
Definition group_tool.h:85
std::shared_ptr< COMMIT > m_commit
Definition group_tool.h:88
bool IsBOARD_ITEM() const
Definition view_item.h:102
bool canGroupItem(EDA_ITEM *aItem, wxString &aErrorMsg) const override
Get the correctly casted group type from the item.
int PickNewMember(const TOOL_EVENT &aEvent) override
Invoke the picker tool to select a new member of the group.
int Group(const TOOL_EVENT &aEvent) override
Ungroup selected items.
std::shared_ptr< COMMIT > createCommit() override
A set of BOARD_ITEMs (i.e., without duplicates).
Definition pcb_group.h:53
Generic tool for picking an item.
The selection tool: currently supports:
PCB_SELECTION & RequestSelection(CLIENT_SELECTION_FILTER aClientFilter)
Return the current selection, filtered according to aClientFilter.
virtual unsigned int GetSize() const override
Return the number of stored items.
Definition selection.h:105
EDA_ITEM * Front() const
Definition selection.h:177
bool Empty() const
Checks if there is anything selected.
Definition selection.h:115
Extension of STATUS_POPUP for displaying a single line text.
T * getModel() const
Return the model object if it matches the requested type.
Definition tool_base.h:198
TOOL_MANAGER * m_toolMgr
Definition tool_base.h:220
Generic, UI-independent tool event.
Definition tool_event.h:171
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Suspend execution of the tool until an event specified in aEventList arrives.
void Activate()
Run the tool.
@ BULLSEYE
Definition cursors.h:58
#define _(s)
@ NO_RECURSE
Definition eda_item.h:54
@ FRAME_PCB_EDITOR
Definition frame_type.h:42
@ FRAME_FOOTPRINT_EDITOR
Definition frame_type.h:43
wxPoint GetMousePosition()
Returns the mouse position in screen coordinates.
Definition wxgtk/ui.cpp:766
Class to handle a set of BOARD_ITEMs.
@ PCB_T
Definition typeinfo.h:79
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:687
VECTOR2< double > VECTOR2D
Definition vector2d.h:686