KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_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/actions.h>
24#include <frame_type.h>
25#include <eda_draw_frame.h>
26#include <symbol_edit_frame.h>
27#include <sch_edit_frame.h>
28#include <sch_screen.h>
29#include <kiplatform/ui.h>
30#include <tool/tool_manager.h>
31#include <tool/picker_tool.h>
34#include <status_popup.h>
35#include <sch_commit.h>
37#include <sch_group.h>
38#include <symbol.h>
39#include <wx/string.h>
40
41
42bool SCH_GROUP_TOOL::canGroupItem( EDA_ITEM* aItem, wxString& aErrorMsg ) const
43{
44 if( !aItem || !aItem->IsSCH_ITEM() )
45 {
46 aErrorMsg = _( "Some selected items cannot be grouped." );
47 return false;
48 }
49
50 bool isSymbolEditor = m_frame->GetFrameType() == FRAME_SCH_SYMBOL_EDITOR;
51 SCH_ITEM* schItem = static_cast<SCH_ITEM*>( aItem );
52
53 if( isSymbolEditor )
54 {
55 if( schItem->GetParentSymbol() )
56 {
57 aErrorMsg = _( "Child items cannot be grouped separately from their parent item." );
58 return false;
59 }
60 }
61 else
62 {
63 if( schItem->GetParent() && schItem->GetParent()->Type() != SCH_SCREEN_T )
64 {
65 aErrorMsg = _( "Child items cannot be grouped separately from their parent item." );
66 return false;
67 }
68 }
69
70 if( !schItem->IsGroupableType() )
71 {
72 aErrorMsg = _( "Some selected items cannot be grouped." );
73 return false;
74 }
75
76 return true;
77}
78
79
81{
82 bool isSymbolEditor = m_frame->GetFrameType() == FRAME_SCH_SYMBOL_EDITOR;
83 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
84 PICKER_TOOL* picker = m_toolMgr->GetTool<PICKER_TOOL>();
85
86 STATUS_TEXT_POPUP statusPopup( m_frame );
87 bool done = false;
88
90 m_propertiesDialog->Show( false );
91
92 Activate();
93
94 statusPopup.SetText( _( "Click on new member..." ) );
95
96 picker->SetClickHandler(
97 [&]( const VECTOR2D& aPoint ) -> bool
98 {
100
101 const SCH_SELECTION& sel = selTool->RequestSelection();
102
103 if( sel.Empty() )
104 return true; // still looking for an item
105
106 statusPopup.Hide();
107
109 {
110 EDA_ITEM* elem = sel.Front();
111
112 if( !isSymbolEditor )
113 {
114 while( elem->GetParent() && elem->GetParent()->Type() != SCH_SCREEN_T )
115 elem = elem->GetParent();
116 }
117
118 m_propertiesDialog->DoAddMember( elem );
119 m_propertiesDialog->Show( true );
120 }
121
122 return false; // got our item; don't need any more
123 } );
124
125 picker->SetMotionHandler(
126 [&]( const VECTOR2D& aPos )
127 {
128 statusPopup.Move( KIPLATFORM::UI::GetMousePosition() + wxPoint( 20, -50 ) );
129 } );
130
131 picker->SetCancelHandler(
132 [&]()
133 {
135 m_propertiesDialog->Show( true );
136
137 statusPopup.Hide();
138 } );
139
140 picker->SetFinalizeHandler(
141 [&]( const int& aFinalState )
142 {
143 done = true;
144 } );
145
146 statusPopup.Move( KIPLATFORM::UI::GetMousePosition() + wxPoint( 20, -50 ) );
147 statusPopup.Popup();
148 m_frame->GetCanvas()->SetStatusPopup( statusPopup.GetPanel() );
149
150 m_toolMgr->RunAction( ACTIONS::pickerTool, &aEvent );
151
152 while( !done )
153 {
154 // Pass events unless we receive a null event, then we must shut down
155 if( TOOL_EVENT* evt = Wait() )
156 evt->SetPassEvent();
157 else
158 break;
159 }
160
161 picker->ClearHandlers();
162 m_frame->GetCanvas()->SetStatusPopup( nullptr );
163
164 return 0;
165}
166
167
169{
170 bool isSymbolEditor = m_frame->GetFrameType() == FRAME_SCH_SYMBOL_EDITOR;
171 SCH_SELECTION_TOOL* selTool = m_toolMgr->GetTool<SCH_SELECTION_TOOL>();
172 SCH_SELECTION selection = selTool->RequestSelection();
173 wxString errorMsg;
174
175 // Iterate from the back so we don't have to worry about removals.
176 for( int ii = selection.GetSize() - 1; ii >= 0; --ii )
177 {
178 EDA_ITEM* item = selection[ii];
179
180 if( !canGroupItem( item, errorMsg ) )
181 selection.Remove( item );
182 }
183
184 if( selection.GetSize() < 2 )
185 {
186 if( !errorMsg.IsEmpty() )
187 m_frame->ShowInfoBarWarning( errorMsg );
188
189 return 0;
190 }
191
193 SCH_SCREEN* screen = static_cast<SCH_BASE_FRAME*>( m_frame )->GetScreen();
194
195 if( isSymbolEditor )
196 group->SetParent( static_cast<SYMBOL_EDIT_FRAME*>( m_frame )->GetCurSymbol() );
197 else
198 group->SetParent( screen );
199
200 for( EDA_ITEM* eda_item : selection )
201 {
202 if( EDA_GROUP* existingGroup = eda_item->GetParentGroup() )
203 m_commit->Modify( existingGroup->AsEdaItem(), screen, RECURSE_MODE::NO_RECURSE );
204
205 m_commit->Modify( eda_item, screen, RECURSE_MODE::NO_RECURSE );
206 group->AddItem( eda_item );
207 }
208
209 m_commit->Add( group, screen );
210 m_commit->Push( _( "Group Items" ) );
211
213 m_toolMgr->RunAction( ACTIONS::selectItem, group->AsEdaItem() );
214
216 m_frame->OnModify();
217
218 if( !errorMsg.IsEmpty() )
219 m_frame->ShowInfoBarWarning( errorMsg );
220
221 return 0;
222}
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 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
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 IsSCH_ITEM() const
Definition view_item.h:101
A shim class between EDA_DRAW_FRAME and several derived classes: SYMBOL_EDIT_FRAME,...
bool canGroupItem(EDA_ITEM *aItem, wxString &aErrorMsg) const override
Get the correctly casted group type from the item.
int Group(const TOOL_EVENT &aEvent) override
Ungroup selected items.
int PickNewMember(const TOOL_EVENT &aEvent) override
Invoke the picker tool to select a new member of the group.
A set of SCH_ITEMs (i.e., without duplicates).
Definition sch_group.h:52
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:166
const SYMBOL * GetParentSymbol() const
Definition sch_item.cpp:278
bool IsGroupableType() const
Definition sch_item.cpp:117
SCH_SELECTION & RequestSelection(const std::vector< KICAD_T > &aScanTypes={ SCH_LOCATE_ANY_T }, bool aPromoteCellSelections=false, bool aPromoteGroups=false)
Return either an existing selection (filtered), or the selection at the current cursor position if th...
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.
The symbol library editor main window.
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.
#define _(s)
@ NO_RECURSE
Definition eda_item.h:54
@ FRAME_SCH_SYMBOL_EDITOR
Definition frame_type.h:35
wxPoint GetMousePosition()
Returns the mouse position in screen coordinates.
Definition wxgtk/ui.cpp:766
Class to handle a set of SCH_ITEMs.
@ SCH_SCREEN_T
Definition typeinfo.h:203
VECTOR2< double > VECTOR2D
Definition vector2d.h:686