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 <eda_draw_frame.h>
26#include <kiplatform/ui.h>
27#include <tool/actions.h>
28#include <tool/tool_manager.h>
29#include <tool/picker_tool.h>
30#include <tool/selection.h>
31#include <tool/selection_tool.h>
32#include <status_popup.h>
33#include <commit.h>
34#include <bitmaps.h>
36#include <eda_group.h>
37
39{
40public:
42 {
43 SetIcon( BITMAPS::group ); // fixme
44 SetTitle( _( "Grouping" ) );
45
50 }
51
52 ACTION_MENU* create() const override
53 {
56 return menu;
57 }
58
60
61private:
62 void update() override
63 {
64 bool canGroup = false;
65 bool hasGroup = false;
66 bool hasMember = false;
67 bool onlyOneGroup = false;
68 bool hasUngroupedItems = false;
69
70 if( m_selectionTool != nullptr )
71 {
72 for( EDA_ITEM* item : m_selectionTool->GetSelection() )
73 {
74 canGroup = true;
75
76 if( item->Type() == PCB_GROUP_T || item->Type() == SCH_GROUP_T )
77 {
78 // Only allow one group to be selected for adding to existing group
79 if( hasGroup )
80 onlyOneGroup = false;
81 else
82 {
83 onlyOneGroup = true;
84 hasGroup = true;
85 }
86 }
87 else if( !item->GetParentGroup() )
88 hasUngroupedItems = true;
89
90 if( item->GetParentGroup() )
91 hasMember = true;
92 }
93 }
94
95 Enable( ACTIONS::group.GetUIId(), canGroup );
96 Enable( ACTIONS::ungroup.GetUIId(), hasGroup );
97 Enable( ACTIONS::addToGroup.GetUIId(), onlyOneGroup && hasUngroupedItems );
98 Enable( ACTIONS::removeFromGroup.GetUIId(), hasMember );
99 }
100
101private:
103};
104
105
107{
108}
109
110
116
117
119{
122
123 // Find the selection tool, so they can cooperate
124 m_selectionTool = static_cast<SELECTION_TOOL*>( m_toolMgr->FindTool( "common.InteractiveSelection" ) );
125 wxCHECK( m_selectionTool, false );
126
127 TOOL_MENU& selToolMenu = m_selectionTool->GetToolMenu();
128
129 std::shared_ptr<GROUP_CONTEXT_MENU> groupMenu = std::make_shared<GROUP_CONTEXT_MENU>();
130 groupMenu->SetTool( this );
131 groupMenu->SetSelectionTool( m_selectionTool );
132 selToolMenu.RegisterSubMenu( groupMenu );
133
134 selToolMenu.GetMenu().AddMenu( groupMenu.get(), SELECTION_CONDITIONS::NotEmpty, 100 );
135
136 return true;
137}
138
139
141{
142 EDA_GROUP* group = aEvent.Parameter<EDA_GROUP*>();
143
145 m_propertiesDialog->Destroy();
146
148
149 m_propertiesDialog->Show( true );
150
151 return 0;
152}
153
154
155int GROUP_TOOL::Ungroup( const TOOL_EVENT& aEvent )
156{
157 const SELECTION& selection = m_selectionTool->GetSelection();
158 EDA_ITEMS toSelect;
159
160 if( selection.Empty() )
162
163 SELECTION selCopy = selection;
165
166 for( EDA_ITEM* item : selCopy )
167 {
168 if( EDA_GROUP* group = dynamic_cast<EDA_GROUP*>( item ) )
169 {
170 group->AsEdaItem()->SetSelected();
171 m_commit->Remove( group->AsEdaItem(), m_frame->GetScreen() );
172
173 for( EDA_ITEM* member : group->GetItems() )
174 {
175 m_commit->Modify( member, m_frame->GetScreen(), RECURSE_MODE::NO_RECURSE );
176 toSelect.push_back( member );
177 }
178
179 group->RemoveAll();
180 }
181 }
182
183 m_commit->Push( _( "Ungroup Items" ) );
184
185 m_toolMgr->RunAction<EDA_ITEMS*>( ACTIONS::selectItems, &toSelect );
186
188 m_frame->OnModify();
189
190 return 0;
191}
192
193
195{
196 const SELECTION& selection = m_selectionTool->GetSelection();
197
198 EDA_GROUP* group = nullptr;
199 EDA_ITEMS toAdd;
200
201 for( EDA_ITEM* item : selection )
202 {
203 if( item->Type() == PCB_GROUP_T || item->Type() == SCH_GROUP_T )
204 {
205 // Only allow one group to be selected for adding to existing group
206 if( group != nullptr )
207 return 0;
208
209 group = dynamic_cast<EDA_GROUP*>( item );
210 }
211 else if( !item->GetParentGroup() )
212 {
213 toAdd.push_back( item );
214 }
215 }
216
217 if( !group || toAdd.empty() )
218 return 0;
219
221
222 m_commit->Modify( group->AsEdaItem(), m_frame->GetScreen(), RECURSE_MODE::NO_RECURSE );
223
224 for( EDA_ITEM* item : toAdd )
225 {
226 EDA_GROUP* existingGroup = item->GetParentGroup();
227
228 if( existingGroup != group )
229 {
230 m_commit->Modify( item, m_frame->GetScreen() );
231
232 if( existingGroup )
233 m_commit->Modify( existingGroup->AsEdaItem(), m_frame->GetScreen(), RECURSE_MODE::NO_RECURSE );
234
235 group->AddItem( item );
236 }
237 }
238
239 m_commit->Push( _( "Add Items to Group" ) );
240
241 m_selectionTool->AddItemToSel( group->AsEdaItem() );
243 m_frame->OnModify();
244
245 return 0;
246}
247
248
250{
251 const SELECTION& selection = m_selectionTool->GetSelection();
252
253 if( selection.Empty() )
255
256 for( EDA_ITEM* item : selection )
257 {
258 if( EDA_GROUP* group = item->GetParentGroup() )
259 {
260 m_commit->Modify( group->AsEdaItem(), m_frame->GetScreen(), RECURSE_MODE::NO_RECURSE );
261 m_commit->Modify( item, m_frame->GetScreen() );
262 group->RemoveItem( item );
263 }
264 }
265
266 m_commit->Push( _( "Remove Group Items" ) );
267
269 m_frame->OnModify();
270
271 return 0;
272}
273
274
276{
277 const SELECTION& selection = m_selectionTool->GetSelection();
278
279 if( selection.GetSize() == 1 &&
280 (selection[0]->Type() == SCH_GROUP_T || selection[0]->Type() == PCB_GROUP_T) )
281 {
282 m_selectionTool->EnterGroup();
283 }
284
285 return 0;
286}
287
288
290{
291 m_selectionTool->ExitGroup( true /* Select the group */ );
292 return 0;
293}
294
295
static TOOL_ACTION pickNewGroupMember
Definition actions.h:247
static TOOL_ACTION selectionCursor
Select a single item under the cursor position.
Definition actions.h:216
static TOOL_ACTION group
Definition actions.h:238
static TOOL_ACTION groupEnter
Definition actions.h:242
static TOOL_ACTION groupProperties
Definition actions.h:246
static TOOL_ACTION ungroup
Definition actions.h:239
static TOOL_ACTION selectionClear
Clear the current selection.
Definition actions.h:223
static TOOL_ACTION addToGroup
Definition actions.h:240
static TOOL_ACTION removeFromGroup
Definition actions.h:241
static TOOL_ACTION groupLeave
Definition actions.h:243
static TOOL_ACTION selectItems
Select a list of items (specified as the event parameter)
Definition actions.h:231
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:98
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition actions.h:353
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:52
std::vector< EDA_ITEM * > EDA_ITEMS
Define list of drawing items for screens.
Definition eda_item.h:566
@ SCH_GROUP_T
Definition typeinfo.h:175
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
Definition typeinfo.h:110