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
24#include <eda_draw_frame.h>
25#include <kiplatform/ui.h>
26#include <tool/actions.h>
27#include <tool/tool_manager.h>
28#include <tool/picker_tool.h>
29#include <tool/group_tool.h>
30#include <tool/selection.h>
31#include <status_popup.h>
32#include <commit.h>
33#include <bitmaps.h>
35#include <eda_group.h>
36
38{
39public:
41 {
42 SetIcon( BITMAPS::group ); // fixme
43 SetTitle( _( "Grouping" ) );
44
49 }
50
51 ACTION_MENU* create() const override
52 {
55 return menu;
56 }
57
59
60private:
61 void update() override
62 {
63 bool canGroup = false;
64 bool hasGroup = false;
65 bool hasMember = false;
66 bool onlyOneGroup = false;
67 bool hasUngroupedItems = false;
68
69 if( m_selectionTool != nullptr )
70 {
71 for( EDA_ITEM* item : m_selectionTool->GetSelection() )
72 {
73 canGroup = true;
74
75 if( item->Type() == PCB_GROUP_T || item->Type() == SCH_GROUP_T )
76 {
77 // Only allow one group to be selected for adding to existing group
78 if( hasGroup )
79 onlyOneGroup = false;
80 else
81 {
82 onlyOneGroup = true;
83 hasGroup = true;
84 }
85 }
86 else if( !item->GetParentGroup() )
87 hasUngroupedItems = true;
88
89 if( item->GetParentGroup() )
90 hasMember = true;
91 }
92 }
93
94 Enable( ACTIONS::group.GetUIId(), canGroup );
95 Enable( ACTIONS::ungroup.GetUIId(), hasGroup );
96 Enable( ACTIONS::addToGroup.GetUIId(), onlyOneGroup && hasUngroupedItems );
97 Enable( ACTIONS::removeFromGroup.GetUIId(), hasMember );
98 }
99
100private:
102};
103
104
106{
107}
108
109
111{
112 m_frame = getEditFrame<EDA_DRAW_FRAME>();
114}
115
116
118{
119 m_frame = getEditFrame<EDA_DRAW_FRAME>();
121
122 // Find the selection tool, so they can cooperate
123 m_selectionTool = static_cast<SELECTION_TOOL*>( m_toolMgr->FindTool( "common.InteractiveSelection" ) );
124 wxCHECK( m_selectionTool, false );
125
126 TOOL_MENU& selToolMenu = m_selectionTool->GetToolMenu();
127
128 std::shared_ptr<GROUP_CONTEXT_MENU> groupMenu = std::make_shared<GROUP_CONTEXT_MENU>();
129 groupMenu->SetTool( this );
130 groupMenu->SetSelectionTool( m_selectionTool );
131 selToolMenu.RegisterSubMenu( groupMenu );
132
133 selToolMenu.GetMenu().AddMenu( groupMenu.get(), SELECTION_CONDITIONS::NotEmpty, 100 );
134
135 return true;
136}
137
138
140{
141 EDA_GROUP* group = aEvent.Parameter<EDA_GROUP*>();
142
144 m_propertiesDialog->Destroy();
145
147
148 m_propertiesDialog->Show( true );
149
150 return 0;
151}
152
153
154int GROUP_TOOL::Ungroup( const TOOL_EVENT& aEvent )
155{
156 const SELECTION& selection = m_selectionTool->GetSelection();
157 EDA_ITEMS toSelect;
158
159 if( selection.Empty() )
161
162 SELECTION selCopy = selection;
164
165 for( EDA_ITEM* item : selCopy )
166 {
167 if( EDA_GROUP* group = dynamic_cast<EDA_GROUP*>( item ) )
168 {
169 group->AsEdaItem()->SetSelected();
170 m_commit->Remove( group->AsEdaItem(), m_frame->GetScreen() );
171
172 for( EDA_ITEM* member : group->GetItems() )
173 {
174 m_commit->Modify( member, m_frame->GetScreen(), RECURSE_MODE::NO_RECURSE );
175 toSelect.push_back( member );
176 }
177
178 group->RemoveAll();
179 }
180 }
181
182 m_commit->Push( _( "Ungroup Items" ) );
183
185
187 m_frame->OnModify();
188
189 return 0;
190}
191
192
194{
195 const SELECTION& selection = m_selectionTool->GetSelection();
196
197 EDA_GROUP* group = nullptr;
198 EDA_ITEMS toAdd;
199
200 for( EDA_ITEM* item : selection )
201 {
202 if( item->Type() == PCB_GROUP_T || item->Type() == SCH_GROUP_T )
203 {
204 // Only allow one group to be selected for adding to existing group
205 if( group != nullptr )
206 return 0;
207
208 group = dynamic_cast<EDA_GROUP*>( item );
209 }
210 else if( !item->GetParentGroup() )
211 {
212 toAdd.push_back( item );
213 }
214 }
215
216 if( !group || toAdd.empty() )
217 return 0;
218
220
221 m_commit->Modify( group->AsEdaItem(), m_frame->GetScreen(), RECURSE_MODE::NO_RECURSE );
222
223 for( EDA_ITEM* item : toAdd )
224 {
225 EDA_GROUP* existingGroup = item->GetParentGroup();
226
227 if( existingGroup != group )
228 {
229 m_commit->Modify( item, m_frame->GetScreen() );
230
231 if( existingGroup )
232 m_commit->Modify( existingGroup->AsEdaItem(), m_frame->GetScreen(), RECURSE_MODE::NO_RECURSE );
233
234 group->AddItem( item );
235 }
236 }
237
238 m_commit->Push( _( "Add Items to Group" ) );
239
240 m_selectionTool->AddItemToSel( group->AsEdaItem() );
242 m_frame->OnModify();
243
244 return 0;
245}
246
247
249{
250 const SELECTION& selection = m_selectionTool->GetSelection();
251
252 if( selection.Empty() )
254
255 for( EDA_ITEM* item : selection )
256 {
257 if( EDA_GROUP* group = item->GetParentGroup() )
258 {
259 m_commit->Modify( group->AsEdaItem(), m_frame->GetScreen(), RECURSE_MODE::NO_RECURSE );
260 m_commit->Modify( item, m_frame->GetScreen() );
261 group->RemoveItem( item );
262 }
263 }
264
265 m_commit->Push( _( "Remove Group Items" ) );
266
268 m_frame->OnModify();
269
270 return 0;
271}
272
273
275{
276 const SELECTION& selection = m_selectionTool->GetSelection();
277
278 if( selection.GetSize() == 1 &&
279 (selection[0]->Type() == SCH_GROUP_T || selection[0]->Type() == PCB_GROUP_T) )
280 {
282 }
283
284 return 0;
285}
286
287
289{
290 m_selectionTool->ExitGroup( true /* Select the group */ );
291 return 0;
292}
293
294
296{
299
300 Go( &GROUP_TOOL::Group, ACTIONS::group.MakeEvent() );
301 Go( &GROUP_TOOL::Ungroup, ACTIONS::ungroup.MakeEvent() );
306}
static TOOL_ACTION pickNewGroupMember
Definition: actions.h:241
static TOOL_ACTION selectionCursor
Select a single item under the cursor position.
Definition: actions.h:214
static TOOL_ACTION group
Definition: actions.h:232
static TOOL_ACTION groupEnter
Definition: actions.h:236
static TOOL_ACTION groupProperties
Definition: actions.h:240
static TOOL_ACTION ungroup
Definition: actions.h:233
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: actions.h:217
static TOOL_ACTION addToGroup
Definition: actions.h:234
static TOOL_ACTION removeFromGroup
Definition: actions.h:235
static TOOL_ACTION groupLeave
Definition: actions.h:237
static TOOL_ACTION selectItems
Select a list of items (specified as the event parameter)
Definition: actions.h:225
Define the structure of a menu based on ACTIONs.
Definition: action_menu.h:49
void SetTitle(const wxString &aTitle) override
Set title for the menu.
Definition: action_menu.cpp:92
void SetIcon(BITMAPS aIcon)
Assign an icon for the entry.
Definition: action_menu.cpp:78
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.
bool Show(bool show) override
virtual void OnModify()
Must be called after a model change in order to set the "modify" flag and do other frame-specific pro...
virtual BASE_SCREEN * GetScreen() const
Return a pointer to a BASE_SCREEN or one of its derivatives.
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:97
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition: actions.h:345
SELECTION_TOOL * m_selectionTool
Definition: group_tool.cpp:101
void SetSelectionTool(SELECTION_TOOL *aTool)
Definition: group_tool.cpp:58
ACTION_MENU * create() const override
Return an instance of this class. It has to be overridden in inheriting classes.
Definition: group_tool.cpp:51
void update() override
Update menu state stub.
Definition: group_tool.cpp:61
virtual int GroupProperties(const TOOL_EVENT &aEvent)
Definition: group_tool.cpp:139
SELECTION_TOOL * m_selectionTool
Definition: group_tool.h:80
virtual int LeaveGroup(const TOOL_EVENT &aEvent)
Definition: group_tool.cpp:288
bool Init() override
Init() is called once upon a registration of the tool.
Definition: group_tool.cpp:117
virtual int RemoveFromGroup(const TOOL_EVENT &aEvent)
Restrict selection to only member of the group.
Definition: group_tool.cpp:248
DIALOG_GROUP_PROPERTIES * m_propertiesDialog
Definition: group_tool.h:79
virtual std::shared_ptr< COMMIT > createCommit()=0
EDA_DRAW_FRAME * m_frame
Definition: group_tool.h:78
virtual int Ungroup(const TOOL_EVENT &aEvent)
Add selection to group.
Definition: group_tool.cpp:154
virtual int AddToGroup(const TOOL_EVENT &aEvent)
Remove selection from group.
Definition: group_tool.cpp:193
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
Definition: group_tool.cpp:110
virtual int Group(const TOOL_EVENT &aEvent)=0
Ungroup selected items.
std::shared_ptr< COMMIT > m_commit
Definition: group_tool.h:81
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.
Definition: group_tool.cpp:295
virtual int EnterGroup(const TOOL_EVENT &aEvent)
Leave the current group (deselect its members and select the group as a whole).
Definition: group_tool.cpp:274
static bool NotEmpty(const SELECTION &aSelection)
Test if there are any items selected.
int AddItemToSel(const TOOL_EVENT &aEvent)
virtual void EnterGroup()
SELECTION & GetSelection()
virtual void ExitGroup(bool aSelectGroup=false)
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
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:168
T Parameter() const
Return a parameter assigned to the event.
Definition: tool_event.h:465
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_MENU & GetToolMenu()
void PostEvent(const TOOL_EVENT &aEvent)
Put an event to the event queue to be processed at the end of event processing cycle.
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
Definition: tool_manager.h:150
TOOL_BASE * FindTool(int aId) const
Search for a tool with given ID.
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)
std::vector< EDA_ITEM * > EDA_ITEMS
Define list of drawing items for screens.
Definition: eda_item.h:552
@ SCH_GROUP_T
Definition: typeinfo.h:174
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
Definition: typeinfo.h:110