KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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#include "tool/group_tool.h"
24
25#include <set>
26
27#include <eda_draw_frame.h>
28#include <kiplatform/ui.h>
29#include <tool/actions.h>
30#include <tool/tool_manager.h>
31#include <tool/picker_tool.h>
32#include <tool/selection.h>
33#include <tool/selection_tool.h>
34#include <status_popup.h>
35#include <commit.h>
36#include <bitmaps.h>
38#include <eda_group.h>
39
41{
42public:
44 {
45 SetIcon( BITMAPS::group ); // fixme
46 SetTitle( _( "Grouping" ) );
47
52 }
53
54 ACTION_MENU* create() const override
55 {
58 return menu;
59 }
60
62
63private:
64 void update() override
65 {
66 int selectionCount = 0;
67 bool hasGroup = false;
68 bool hasMember = false;
69 bool onlyOneGroup = false;
70 bool hasUngroupedItems = false;
71
72 if( m_selectionTool != nullptr )
73 {
74 for( EDA_ITEM* item : m_selectionTool->GetSelection() )
75 {
76 selectionCount++;
77
78 if( item->Type() == PCB_GROUP_T || item->Type() == SCH_GROUP_T )
79 {
80 // Only allow one group to be selected for adding to existing group
81 if( hasGroup )
82 onlyOneGroup = false;
83 else
84 {
85 onlyOneGroup = true;
86 hasGroup = true;
87 }
88 }
89 else if( !item->GetParentGroup() )
90 hasUngroupedItems = true;
91
92 if( item->GetParentGroup() )
93 hasMember = true;
94 }
95 }
96
97 Enable( ACTIONS::group.GetUIId(), selectionCount >= 2 );
98 Enable( ACTIONS::ungroup.GetUIId(), hasGroup );
99 Enable( ACTIONS::addToGroup.GetUIId(), onlyOneGroup && hasUngroupedItems );
100 Enable( ACTIONS::removeFromGroup.GetUIId(), hasMember );
101 }
102
103private:
105};
106
107
109{
110}
111
112
118
119
121{
124
125 // Find the selection tool, so they can cooperate
126 m_selectionTool = static_cast<SELECTION_TOOL*>( m_toolMgr->FindTool( "common.InteractiveSelection" ) );
127 wxCHECK( m_selectionTool, false );
128
129 TOOL_MENU& selToolMenu = m_selectionTool->GetToolMenu();
130
131 std::shared_ptr<GROUP_CONTEXT_MENU> groupMenu = std::make_shared<GROUP_CONTEXT_MENU>();
132 groupMenu->SetTool( this );
133 groupMenu->SetSelectionTool( m_selectionTool );
134 selToolMenu.RegisterSubMenu( groupMenu );
135
136 selToolMenu.GetMenu().AddMenu( groupMenu.get(), SELECTION_CONDITIONS::NotEmpty, 100 );
137
138 return true;
139}
140
141
143{
144 EDA_GROUP* group = aEvent.Parameter<EDA_GROUP*>();
145
147 m_propertiesDialog->Destroy();
148
150
151 m_propertiesDialog->Show( true );
152
153 return 0;
154}
155
156
157int GROUP_TOOL::Ungroup( const TOOL_EVENT& aEvent )
158{
159 const SELECTION& selection = m_selectionTool->GetSelection();
160 EDA_ITEMS toSelect;
161
162 if( selection.Empty() )
164
165 SELECTION selCopy = selection;
167
168 for( EDA_ITEM* item : selCopy )
169 {
170 if( EDA_GROUP* group = dynamic_cast<EDA_GROUP*>( item ) )
171 {
172 group->AsEdaItem()->SetSelected();
173 m_commit->Remove( group->AsEdaItem(), m_frame->GetScreen() );
174
175 for( EDA_ITEM* member : group->GetItems() )
176 {
177 m_commit->Modify( member, m_frame->GetScreen(), RECURSE_MODE::NO_RECURSE );
178 toSelect.push_back( member );
179 }
180
181 group->RemoveAll();
182 }
183 }
184
185 m_commit->Push( _( "Ungroup Items" ) );
186
187 m_toolMgr->RunAction<EDA_ITEMS*>( ACTIONS::selectItems, &toSelect );
188
190 m_frame->OnModify();
191
192 return 0;
193}
194
195
197{
198 const SELECTION& selection = m_selectionTool->GetSelection();
199
200 EDA_GROUP* group = nullptr;
201 EDA_ITEMS toAdd;
202
203 for( EDA_ITEM* item : selection )
204 {
205 if( item->Type() == PCB_GROUP_T || item->Type() == SCH_GROUP_T )
206 {
207 // Only allow one group to be selected for adding to existing group
208 if( group != nullptr )
209 return 0;
210
211 group = dynamic_cast<EDA_GROUP*>( item );
212 }
213 else if( !item->GetParentGroup() )
214 {
215 toAdd.push_back( item );
216 }
217 }
218
219 if( !group || toAdd.empty() )
220 return 0;
221
223
224 m_commit->Modify( group->AsEdaItem(), m_frame->GetScreen(), RECURSE_MODE::NO_RECURSE );
225
226 for( EDA_ITEM* item : toAdd )
227 {
228 EDA_GROUP* existingGroup = item->GetParentGroup();
229
230 if( existingGroup != group )
231 {
232 m_commit->Modify( item, m_frame->GetScreen() );
233
234 if( existingGroup )
235 m_commit->Modify( existingGroup->AsEdaItem(), m_frame->GetScreen(), RECURSE_MODE::NO_RECURSE );
236
237 group->AddItem( item );
238 }
239 }
240
241 m_commit->Push( _( "Add Items to Group" ) );
242
243 m_selectionTool->AddItemToSel( group->AsEdaItem() );
245 m_frame->OnModify();
246
247 return 0;
248}
249
250
252{
253 const SELECTION& selection = m_selectionTool->GetSelection();
254
255 if( selection.Empty() )
257
258 std::set<EDA_GROUP*> affectedGroups;
259
260 for( EDA_ITEM* item : selection )
261 {
262 if( EDA_GROUP* group = item->GetParentGroup() )
263 {
264 m_commit->Modify( group->AsEdaItem(), m_frame->GetScreen(), RECURSE_MODE::NO_RECURSE );
265 m_commit->Modify( item, m_frame->GetScreen() );
266 group->RemoveItem( item );
267 affectedGroups.insert( group );
268 }
269 }
270
271 for( EDA_GROUP* group : affectedGroups )
272 {
273 if( group->GetItems().size() < 2 )
274 {
275 group->RemoveAll();
276 m_commit->Remove( group->AsEdaItem(), m_frame->GetScreen() );
277 }
278 }
279
280 m_commit->Push( _( "Remove Group Items" ) );
281
283 m_frame->OnModify();
284
285 return 0;
286}
287
288
290{
291 const SELECTION& selection = m_selectionTool->GetSelection();
292
293 if( selection.GetSize() == 1 &&
294 (selection[0]->Type() == SCH_GROUP_T || selection[0]->Type() == PCB_GROUP_T) )
295 {
296 m_selectionTool->EnterGroup();
297 }
298
299 return 0;
300}
301
302
304{
305 m_selectionTool->ExitGroup( true /* Select the group */ );
306 return 0;
307}
308
309
static TOOL_ACTION pickNewGroupMember
Definition actions.h:248
static TOOL_ACTION selectionCursor
Select a single item under the cursor position.
Definition actions.h:217
static TOOL_ACTION group
Definition actions.h:239
static TOOL_ACTION groupEnter
Definition actions.h:243
static TOOL_ACTION groupProperties
Definition actions.h:247
static TOOL_ACTION ungroup
Definition actions.h:240
static TOOL_ACTION selectionClear
Clear the current selection.
Definition actions.h:224
static TOOL_ACTION addToGroup
Definition actions.h:241
static TOOL_ACTION removeFromGroup
Definition actions.h:242
static TOOL_ACTION groupLeave
Definition actions.h:244
static TOOL_ACTION selectItems
Select a list of items (specified as the event parameter)
Definition actions.h:232
ACTION_MENU(bool isContextMenu, TOOL_INTERACTIVE *aTool=nullptr)
Default constructor.
void SetTitle(const wxString &aTitle) override
Set title for the menu.
void SetIcon(BITMAPS aIcon)
Assign an icon for the entry.
wxMenuItem * Add(const wxString &aLabel, int aId, BITMAPS aIcon)
Add a wxWidgets-style entry to the menu.
void AddMenu(ACTION_MENU *aMenu, const SELECTION_CONDITION &aCondition=SELECTION_CONDITIONS::ShowAlways, int aOrder=ANY_ORDER)
Add a submenu to the menu.
A set of EDA_ITEMs (i.e., without duplicates).
Definition eda_group.h:46
virtual EDA_ITEM * AsEdaItem()=0
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:99
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
SELECTION_TOOL * m_selectionTool
void SetSelectionTool(SELECTION_TOOL *aTool)
ACTION_MENU * create() const override
Return an instance of this class. It has to be overridden in inheriting classes.
void update() override
Update menu state stub.
virtual int GroupProperties(const TOOL_EVENT &aEvent)
SELECTION_TOOL * m_selectionTool
Definition group_tool.h:83
virtual int LeaveGroup(const TOOL_EVENT &aEvent)
bool Init() override
Init() is called once upon a registration of the tool.
virtual int RemoveFromGroup(const TOOL_EVENT &aEvent)
Restrict selection to only member of the group.
DIALOG_GROUP_PROPERTIES * m_propertiesDialog
Definition group_tool.h:82
virtual std::shared_ptr< COMMIT > createCommit()=0
EDA_DRAW_FRAME * m_frame
Definition group_tool.h:81
virtual int Ungroup(const TOOL_EVENT &aEvent)
Add selection to group.
virtual int AddToGroup(const TOOL_EVENT &aEvent)
Remove selection from group.
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
virtual int Group(const TOOL_EVENT &aEvent)=0
Ungroup selected items.
std::shared_ptr< COMMIT > m_commit
Definition group_tool.h:84
virtual int PickNewMember(const TOOL_EVENT &aEvent)=0
Invoke the picker tool to select a new member of the group.
void setTransitions() override
< Set up handlers for various events.
virtual int EnterGroup(const TOOL_EVENT &aEvent)
Leave the current group (deselect its members and select the group as a whole).
static bool NotEmpty(const SELECTION &aSelection)
Test if there are any items selected.
virtual unsigned int GetSize() const override
Return the number of stored items.
Definition selection.h:105
bool Empty() const
Checks if there is anything selected.
Definition selection.h:115
T * getEditFrame() const
Return the application window object, casted to requested user type.
Definition tool_base.h:186
TOOL_MANAGER * m_toolMgr
Definition tool_base.h:220
RESET_REASON
Determine the reason of reset for a tool.
Definition tool_base.h:78
Generic, UI-independent tool event.
Definition tool_event.h:171
T Parameter() const
Return a parameter assigned to the event.
Definition tool_event.h:473
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
TOOL_INTERACTIVE(TOOL_ID aId, const std::string &aName)
Create a tool with given id & name.
Manage a CONDITIONAL_MENU and some number of CONTEXT_MENUs as sub-menus.
Definition tool_menu.h:43
CONDITIONAL_MENU & GetMenu()
Definition tool_menu.cpp:44
void RegisterSubMenu(std::shared_ptr< ACTION_MENU > aSubMenu)
Store a submenu of this menu model.
Definition tool_menu.cpp:50
#define _(s)
@ NO_RECURSE
Definition eda_item.h:53
std::vector< EDA_ITEM * > EDA_ITEMS
@ SCH_GROUP_T
Definition typeinfo.h:177
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
Definition typeinfo.h:111