22 changed files with 506 additions and 492 deletions
-
1common/CMakeLists.txt
-
40common/dialogs/dialog_group_properties.cpp
-
4common/dialogs/dialog_group_properties.h
-
232common/tool/group_tool.cpp
-
41common/tool/group_tool.h
-
3eeschema/sch_item.h
-
8eeschema/tools/sch_edit_tool.cpp
-
4include/board_item.h
-
3include/eda_item.h
-
3include/tool/selection_tool.h
-
2pcbnew/CMakeLists.txt
-
29pcbnew/board.cpp
-
14pcbnew/board.h
-
1pcbnew/board_commit.cpp
-
3pcbnew/edit.cpp
-
4pcbnew/footprint_edit_frame.cpp
-
3pcbnew/footprint_editor_utils.cpp
-
4pcbnew/pcb_edit_frame.cpp
-
386pcbnew/tools/group_tool.cpp
-
192pcbnew/tools/pcb_group_tool.cpp
-
17pcbnew/tools/pcb_group_tool.h
-
4pcbnew/tools/pcb_selection_tool.h
@ -0,0 +1,232 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 2 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 2 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include <eda_draw_frame.h>
|
|||
#include <kiplatform/ui.h>
|
|||
#include <tool/actions.h>
|
|||
#include <tool/tool_manager.h>
|
|||
#include <tool/picker_tool.h>
|
|||
#include <tool/group_tool.h>
|
|||
#include <tool/selection.h>
|
|||
#include <status_popup.h>
|
|||
#include <commit.h>
|
|||
#include <bitmaps.h>
|
|||
#include <dialogs/dialog_group_properties.h>
|
|||
#include <eda_group.h>
|
|||
|
|||
class GROUP_CONTEXT_MENU : public ACTION_MENU |
|||
{ |
|||
public: |
|||
GROUP_CONTEXT_MENU() : ACTION_MENU( true ) |
|||
{ |
|||
SetIcon( BITMAPS::group ); // fixme
|
|||
SetTitle( _( "Grouping" ) ); |
|||
|
|||
Add( ACTIONS::group ); |
|||
Add( ACTIONS::ungroup ); |
|||
Add( ACTIONS::removeFromGroup ); |
|||
} |
|||
|
|||
ACTION_MENU* create() const override |
|||
{ |
|||
GROUP_CONTEXT_MENU* menu = new GROUP_CONTEXT_MENU(); |
|||
menu->SetSelectionTool( m_selectionTool ); |
|||
return menu; |
|||
} |
|||
|
|||
void SetSelectionTool( SELECTION_TOOL* aTool ) { m_selectionTool = aTool; } |
|||
|
|||
private: |
|||
void update() override |
|||
{ |
|||
bool canGroup = false; |
|||
bool hasGroup = false; |
|||
bool hasMember = false; |
|||
|
|||
if( m_selectionTool != nullptr ) |
|||
{ |
|||
for( EDA_ITEM* item : m_selectionTool->GetSelection() ) |
|||
{ |
|||
canGroup = true; |
|||
|
|||
if( item->Type() == PCB_GROUP_T || item->Type() == SCH_GROUP_T ) |
|||
hasGroup = true; |
|||
|
|||
if( item->GetParentGroup() ) |
|||
hasMember = true; |
|||
} |
|||
} |
|||
|
|||
Enable( ACTIONS::group.GetUIId(), canGroup ); |
|||
Enable( ACTIONS::ungroup.GetUIId(), hasGroup ); |
|||
Enable( ACTIONS::removeFromGroup.GetUIId(), hasMember ); |
|||
} |
|||
|
|||
private: |
|||
SELECTION_TOOL* m_selectionTool = nullptr; |
|||
}; |
|||
|
|||
|
|||
GROUP_TOOL::GROUP_TOOL() : TOOL_INTERACTIVE( "common.Groups" ) |
|||
{ |
|||
} |
|||
|
|||
|
|||
void GROUP_TOOL::Reset( RESET_REASON aReason ) |
|||
{ |
|||
m_frame = getEditFrame<EDA_DRAW_FRAME>(); |
|||
|
|||
if( aReason != RUN ) |
|||
m_commit = createCommit(); |
|||
} |
|||
|
|||
|
|||
bool GROUP_TOOL::Init() |
|||
{ |
|||
m_frame = getEditFrame<EDA_DRAW_FRAME>(); |
|||
|
|||
// Find the selection tool, so they can cooperate
|
|||
m_selectionTool = static_cast<SELECTION_TOOL*>( m_toolMgr->FindTool( "common.InteractiveSelection" ) ); |
|||
wxCHECK( m_selectionTool, false ); |
|||
|
|||
TOOL_MENU& selToolMenu = m_selectionTool->GetToolMenu(); |
|||
|
|||
std::shared_ptr<GROUP_CONTEXT_MENU> groupMenu = std::make_shared<GROUP_CONTEXT_MENU>(); |
|||
groupMenu->SetTool( this ); |
|||
groupMenu->SetSelectionTool( m_selectionTool ); |
|||
selToolMenu.RegisterSubMenu( groupMenu ); |
|||
|
|||
selToolMenu.GetMenu().AddMenu( groupMenu.get(), SELECTION_CONDITIONS::NotEmpty, 100 ); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
int GROUP_TOOL::GroupProperties( const TOOL_EVENT& aEvent ) |
|||
{ |
|||
EDA_GROUP* group = aEvent.Parameter<EDA_GROUP*>(); |
|||
|
|||
if( m_propertiesDialog ) |
|||
m_propertiesDialog->Destroy(); |
|||
|
|||
m_propertiesDialog = new DIALOG_GROUP_PROPERTIES( m_frame, group, *m_commit ); |
|||
|
|||
m_propertiesDialog->Show( true ); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
|
|||
int GROUP_TOOL::Ungroup( const TOOL_EVENT& aEvent ) |
|||
{ |
|||
const SELECTION& selection = m_selectionTool->GetSelection(); |
|||
EDA_ITEMS toSelect; |
|||
|
|||
if( selection.Empty() ) |
|||
m_toolMgr->RunAction( ACTIONS::selectionCursor ); |
|||
|
|||
SELECTION selCopy = selection; |
|||
m_toolMgr->RunAction( ACTIONS::selectionClear ); |
|||
|
|||
for( EDA_ITEM* item : selCopy ) |
|||
{ |
|||
EDA_GROUP* group = dynamic_cast<EDA_GROUP*>( item ); |
|||
|
|||
if( group ) |
|||
{ |
|||
for( EDA_ITEM* member : group->GetItems() ) |
|||
{ |
|||
m_commit->Stage( member, CHT_UNGROUP ); |
|||
toSelect.push_back( member ); |
|||
} |
|||
|
|||
group->AsEdaItem()->SetSelected(); |
|||
m_commit->Remove( group->AsEdaItem() ); |
|||
} |
|||
} |
|||
|
|||
m_commit->Push( _( "Ungroup Items" ) ); |
|||
|
|||
m_toolMgr->RunAction<EDA_ITEMS*>( ACTIONS::selectItems, &toSelect ); |
|||
|
|||
m_toolMgr->PostEvent( EVENTS::SelectedItemsModified ); |
|||
m_frame->OnModify(); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
|
|||
int GROUP_TOOL::RemoveFromGroup( const TOOL_EVENT& aEvent ) |
|||
{ |
|||
const SELECTION& selection = m_selectionTool->GetSelection(); |
|||
|
|||
if( selection.Empty() ) |
|||
m_toolMgr->RunAction( ACTIONS::selectionCursor ); |
|||
|
|||
for( EDA_ITEM* item : selection ) |
|||
{ |
|||
if( item->GetParentGroup() ) |
|||
m_commit->Stage( item, CHT_UNGROUP ); |
|||
} |
|||
|
|||
m_commit->Push( _( "Remove Group Items" ) ); |
|||
|
|||
m_toolMgr->PostEvent( EVENTS::SelectedItemsModified ); |
|||
m_frame->OnModify(); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
|
|||
int GROUP_TOOL::EnterGroup( const TOOL_EVENT& aEvent ) |
|||
{ |
|||
const SELECTION& selection = m_selectionTool->GetSelection(); |
|||
|
|||
if( selection.GetSize() == 1 && |
|||
(selection[0]->Type() == SCH_GROUP_T || selection[0]->Type() == PCB_GROUP_T) ) |
|||
{ |
|||
m_selectionTool->EnterGroup(); |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
|
|||
int GROUP_TOOL::LeaveGroup( const TOOL_EVENT& aEvent ) |
|||
{ |
|||
m_selectionTool->ExitGroup( true /* Select the group */ ); |
|||
return 0; |
|||
} |
|||
|
|||
|
|||
void GROUP_TOOL::setTransitions() |
|||
{ |
|||
Go( &GROUP_TOOL::GroupProperties, ACTIONS::groupProperties.MakeEvent() ); |
|||
Go( &GROUP_TOOL::PickNewMember, ACTIONS::pickNewGroupMember.MakeEvent() ); |
|||
|
|||
Go( &GROUP_TOOL::Group, ACTIONS::group.MakeEvent() ); |
|||
Go( &GROUP_TOOL::Ungroup, ACTIONS::ungroup.MakeEvent() ); |
|||
Go( &GROUP_TOOL::RemoveFromGroup, ACTIONS::removeFromGroup.MakeEvent() ); |
|||
Go( &GROUP_TOOL::EnterGroup, ACTIONS::groupEnter.MakeEvent() ); |
|||
Go( &GROUP_TOOL::LeaveGroup, ACTIONS::groupLeave.MakeEvent() ); |
|||
} |
|||
@ -1,386 +0,0 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 2 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 2 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include <kiplatform/ui.h>
|
|||
#include <tool/tool_manager.h>
|
|||
#include <tools/pcb_actions.h>
|
|||
#include <tools/pcb_selection_tool.h>
|
|||
#include <tools/group_tool.h>
|
|||
#include <tools/pcb_picker_tool.h>
|
|||
#include <status_popup.h>
|
|||
#include <board_commit.h>
|
|||
#include <bitmaps.h>
|
|||
#include <dialogs/dialog_group_properties.h>
|
|||
#include <pcb_group.h>
|
|||
#include <collectors.h>
|
|||
#include <footprint.h>
|
|||
|
|||
class GROUP_CONTEXT_MENU : public ACTION_MENU |
|||
{ |
|||
public: |
|||
GROUP_CONTEXT_MENU( ) : ACTION_MENU( true ) |
|||
{ |
|||
SetIcon( BITMAPS::group ); // fixme
|
|||
SetTitle( _( "Grouping" ) ); |
|||
|
|||
Add( ACTIONS::group ); |
|||
Add( ACTIONS::ungroup ); |
|||
Add( ACTIONS::removeFromGroup ); |
|||
} |
|||
|
|||
ACTION_MENU* create() const override |
|||
{ |
|||
return new GROUP_CONTEXT_MENU(); |
|||
} |
|||
|
|||
private: |
|||
void update() override |
|||
{ |
|||
PCB_SELECTION_TOOL* selTool = getToolManager()->GetTool<PCB_SELECTION_TOOL>(); |
|||
BOARD* board = static_cast<BOARD*>( getToolManager()->GetModel() ); |
|||
|
|||
const auto& selection = selTool->GetSelection(); |
|||
|
|||
wxString check = board->GroupsSanityCheck(); |
|||
wxCHECK_RET( check == wxEmptyString, _( "Group is in inconsistent state:" ) + wxS( " " ) + check ); |
|||
|
|||
BOARD::GroupLegalOpsField legalOps = board->GroupLegalOps( selection ); |
|||
|
|||
Enable( ACTIONS::group.GetUIId(), legalOps.create ); |
|||
Enable( ACTIONS::ungroup.GetUIId(), legalOps.ungroup ); |
|||
Enable( ACTIONS::removeFromGroup.GetUIId(), legalOps.removeItems ); |
|||
} |
|||
}; |
|||
|
|||
|
|||
GROUP_TOOL::GROUP_TOOL() : |
|||
PCB_TOOL_BASE( "pcbnew.Groups" ), |
|||
m_frame( nullptr ), |
|||
m_propertiesDialog( nullptr ), |
|||
m_selectionTool( nullptr ) |
|||
{ |
|||
} |
|||
|
|||
|
|||
void GROUP_TOOL::Reset( RESET_REASON aReason ) |
|||
{ |
|||
m_frame = getEditFrame<PCB_BASE_EDIT_FRAME>(); |
|||
|
|||
if( aReason != RUN ) |
|||
m_commit = std::make_unique<BOARD_COMMIT>( this ); |
|||
} |
|||
|
|||
|
|||
bool GROUP_TOOL::Init() |
|||
{ |
|||
m_frame = getEditFrame<PCB_BASE_EDIT_FRAME>(); |
|||
|
|||
// Find the selection tool, so they can cooperate
|
|||
m_selectionTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>(); |
|||
|
|||
// Add the group control menus to relevant other tools
|
|||
if( m_selectionTool ) |
|||
{ |
|||
TOOL_MENU& selToolMenu = m_selectionTool->GetToolMenu(); |
|||
|
|||
std::shared_ptr<GROUP_CONTEXT_MENU> groupMenu = std::make_shared<GROUP_CONTEXT_MENU>(); |
|||
groupMenu->SetTool( this ); |
|||
selToolMenu.RegisterSubMenu( groupMenu ); |
|||
|
|||
selToolMenu.GetMenu().AddMenu( groupMenu.get(), SELECTION_CONDITIONS::NotEmpty, 100 ); |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
int GROUP_TOOL::GroupProperties( const TOOL_EVENT& aEvent ) |
|||
{ |
|||
PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>(); |
|||
PCB_GROUP* group = aEvent.Parameter<PCB_GROUP*>(); |
|||
|
|||
if( m_propertiesDialog ) |
|||
m_propertiesDialog->Destroy(); |
|||
|
|||
m_propertiesDialog = new DIALOG_GROUP_PROPERTIES( editFrame, group ); |
|||
|
|||
m_propertiesDialog->Show( true ); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
|
|||
int GROUP_TOOL::PickNewMember( const TOOL_EVENT& aEvent ) |
|||
{ |
|||
PCB_PICKER_TOOL* picker = m_toolMgr->GetTool<PCB_PICKER_TOOL>(); |
|||
STATUS_TEXT_POPUP statusPopup( frame() ); |
|||
bool done = false; |
|||
|
|||
if( m_propertiesDialog ) |
|||
m_propertiesDialog->Show( false ); |
|||
|
|||
Activate(); |
|||
|
|||
statusPopup.SetText( _( "Click on new member..." ) ); |
|||
|
|||
picker->SetClickHandler( |
|||
[&]( const VECTOR2D& aPoint ) -> bool |
|||
{ |
|||
m_toolMgr->RunAction( ACTIONS::selectionClear ); |
|||
|
|||
const PCB_SELECTION& sel = m_selectionTool->RequestSelection( |
|||
[]( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, |
|||
PCB_SELECTION_TOOL* sTool ) |
|||
{ |
|||
} ); |
|||
|
|||
if( sel.Empty() ) |
|||
return true; // still looking for an item
|
|||
|
|||
statusPopup.Hide(); |
|||
|
|||
if( m_propertiesDialog ) |
|||
{ |
|||
EDA_ITEM* elem = sel.Front(); |
|||
|
|||
if( !m_isFootprintEditor ) |
|||
{ |
|||
while( elem->GetParent() && elem->GetParent()->Type() != PCB_T ) |
|||
elem = elem->GetParent(); |
|||
} |
|||
|
|||
m_propertiesDialog->DoAddMember( elem ); |
|||
m_propertiesDialog->Show( true ); |
|||
} |
|||
|
|||
return false; // got our item; don't need any more
|
|||
} ); |
|||
|
|||
picker->SetMotionHandler( |
|||
[&] ( const VECTOR2D& aPos ) |
|||
{ |
|||
statusPopup.Move( KIPLATFORM::UI::GetMousePosition() + wxPoint( 20, -50 ) ); |
|||
} ); |
|||
|
|||
picker->SetCancelHandler( |
|||
[&]() |
|||
{ |
|||
if( m_propertiesDialog ) |
|||
m_propertiesDialog->Show( true ); |
|||
|
|||
statusPopup.Hide(); |
|||
} ); |
|||
|
|||
picker->SetFinalizeHandler( |
|||
[&]( const int& aFinalState ) |
|||
{ |
|||
done = true; |
|||
} ); |
|||
|
|||
statusPopup.Move( KIPLATFORM::UI::GetMousePosition() + wxPoint( 20, -50 ) ); |
|||
statusPopup.Popup(); |
|||
canvas()->SetStatusPopup( statusPopup.GetPanel() ); |
|||
|
|||
m_toolMgr->RunAction( ACTIONS::pickerTool, &aEvent ); |
|||
|
|||
while( !done ) |
|||
{ |
|||
// Pass events unless we receive a null event, then we must shut down
|
|||
if( TOOL_EVENT* evt = Wait() ) |
|||
evt->SetPassEvent(); |
|||
else |
|||
break; |
|||
} |
|||
|
|||
canvas()->SetStatusPopup( nullptr ); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
|
|||
int GROUP_TOOL::Group( const TOOL_EVENT& aEvent ) |
|||
{ |
|||
PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>(); |
|||
PCB_SELECTION selection; |
|||
|
|||
if( m_isFootprintEditor ) |
|||
{ |
|||
selection = selTool->RequestSelection( |
|||
[]( const VECTOR2I& , GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* ) |
|||
{ |
|||
} ); |
|||
} |
|||
else |
|||
{ |
|||
selection = selTool->RequestSelection( |
|||
[]( const VECTOR2I& , GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* ) |
|||
{ |
|||
// Iterate from the back so we don't have to worry about removals.
|
|||
for( int i = aCollector.GetCount() - 1; i >= 0; --i ) |
|||
{ |
|||
BOARD_ITEM* item = aCollector[ i ]; |
|||
|
|||
if( item->GetParentFootprint() ) |
|||
aCollector.Remove( item ); |
|||
} |
|||
} ); |
|||
} |
|||
|
|||
if( selection.Empty() ) |
|||
return 0; |
|||
|
|||
BOARD* board = getModel<BOARD>(); |
|||
BOARD_COMMIT commit( m_toolMgr ); |
|||
PCB_GROUP* group = nullptr; |
|||
|
|||
if( m_isFootprintEditor ) |
|||
group = new PCB_GROUP( board->GetFirstFootprint() ); |
|||
else |
|||
group = new PCB_GROUP( board ); |
|||
|
|||
for( EDA_ITEM* eda_item : selection ) |
|||
{ |
|||
if( eda_item->IsBOARD_ITEM() ) |
|||
{ |
|||
if( static_cast<BOARD_ITEM*>( eda_item )->IsLocked() ) |
|||
group->SetLocked( true ); |
|||
} |
|||
} |
|||
|
|||
commit.Add( group ); |
|||
|
|||
for( EDA_ITEM* eda_item : selection ) |
|||
{ |
|||
if( eda_item->IsBOARD_ITEM() ) |
|||
commit.Stage( static_cast<BOARD_ITEM*>( eda_item ), CHT_GROUP ); |
|||
} |
|||
|
|||
commit.Push( _( "Group Items" ) ); |
|||
|
|||
selTool->ClearSelection(); |
|||
selTool->select( group ); |
|||
|
|||
m_toolMgr->PostEvent( EVENTS::SelectedItemsModified ); |
|||
m_frame->OnModify(); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
|
|||
int GROUP_TOOL::Ungroup( const TOOL_EVENT& aEvent ) |
|||
{ |
|||
const PCB_SELECTION& selection = m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->GetSelection(); |
|||
BOARD_COMMIT commit( m_toolMgr ); |
|||
EDA_ITEMS toSelect; |
|||
|
|||
if( selection.Empty() ) |
|||
m_toolMgr->RunAction( ACTIONS::selectionCursor ); |
|||
|
|||
PCB_SELECTION selCopy = selection; |
|||
m_toolMgr->RunAction( ACTIONS::selectionClear ); |
|||
|
|||
for( EDA_ITEM* item : selCopy ) |
|||
{ |
|||
PCB_GROUP* group = dynamic_cast<PCB_GROUP*>( item ); |
|||
|
|||
if( group ) |
|||
{ |
|||
for( EDA_ITEM* member : group->GetItems() ) |
|||
{ |
|||
commit.Stage( member, CHT_UNGROUP ); |
|||
toSelect.push_back( member ); |
|||
} |
|||
|
|||
group->SetSelected(); |
|||
commit.Remove( group ); |
|||
} |
|||
} |
|||
|
|||
commit.Push( _( "Ungroup Items" ) ); |
|||
|
|||
m_toolMgr->RunAction<EDA_ITEMS*>( ACTIONS::selectItems, &toSelect ); |
|||
|
|||
m_toolMgr->PostEvent( EVENTS::SelectedItemsModified ); |
|||
m_frame->OnModify(); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
|
|||
int GROUP_TOOL::RemoveFromGroup( const TOOL_EVENT& aEvent ) |
|||
{ |
|||
PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>(); |
|||
const PCB_SELECTION& selection = selTool->GetSelection(); |
|||
BOARD_COMMIT commit( m_frame ); |
|||
|
|||
if( selection.Empty() ) |
|||
m_toolMgr->RunAction( ACTIONS::selectionCursor ); |
|||
|
|||
for( EDA_ITEM* item : selection ) |
|||
{ |
|||
BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item ); |
|||
EDA_GROUP* group = boardItem->GetParentGroup(); |
|||
|
|||
if( group ) |
|||
commit.Stage( boardItem, CHT_UNGROUP ); |
|||
} |
|||
|
|||
commit.Push( _( "Remove Group Items" ) ); |
|||
|
|||
m_toolMgr->PostEvent( EVENTS::SelectedItemsModified ); |
|||
m_frame->OnModify(); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
|
|||
int GROUP_TOOL::EnterGroup( const TOOL_EVENT& aEvent ) |
|||
{ |
|||
PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>(); |
|||
const PCB_SELECTION& selection = selTool->GetSelection(); |
|||
|
|||
if( selection.GetSize() == 1 && selection[0]->Type() == PCB_GROUP_T ) |
|||
selTool->EnterGroup(); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
|
|||
int GROUP_TOOL::LeaveGroup( const TOOL_EVENT& aEvent ) |
|||
{ |
|||
m_toolMgr->GetTool<PCB_SELECTION_TOOL>()->ExitGroup( true /* Select the group */ ); |
|||
return 0; |
|||
} |
|||
|
|||
|
|||
void GROUP_TOOL::setTransitions() |
|||
{ |
|||
Go( &GROUP_TOOL::GroupProperties, ACTIONS::groupProperties.MakeEvent() ); |
|||
Go( &GROUP_TOOL::PickNewMember, ACTIONS::pickNewGroupMember.MakeEvent() ); |
|||
|
|||
Go( &GROUP_TOOL::Group, ACTIONS::group.MakeEvent() ); |
|||
Go( &GROUP_TOOL::Ungroup, ACTIONS::ungroup.MakeEvent() ); |
|||
Go( &GROUP_TOOL::RemoveFromGroup, ACTIONS::removeFromGroup.MakeEvent() ); |
|||
Go( &GROUP_TOOL::EnterGroup, ACTIONS::groupEnter.MakeEvent() ); |
|||
Go( &GROUP_TOOL::LeaveGroup, ACTIONS::groupLeave.MakeEvent() ); |
|||
} |
|||
@ -0,0 +1,192 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 2 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 2 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
#include <kiplatform/ui.h>
|
|||
#include <tool/tool_manager.h>
|
|||
#include <tools/pcb_group_tool.h>
|
|||
#include <tools/pcb_picker_tool.h>
|
|||
#include <tools/pcb_selection_tool.h>
|
|||
#include <status_popup.h>
|
|||
#include <board_commit.h>
|
|||
#include <dialogs/dialog_group_properties.h>
|
|||
#include <pcb_group.h>
|
|||
#include <collectors.h>
|
|||
#include <footprint.h>
|
|||
|
|||
|
|||
int PCB_GROUP_TOOL::PickNewMember( const TOOL_EVENT& aEvent ) |
|||
{ |
|||
bool isFootprintEditor = m_frame->GetFrameType() == FRAME_FOOTPRINT_EDITOR; |
|||
PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>(); |
|||
PCB_PICKER_TOOL* picker = m_toolMgr->GetTool<PCB_PICKER_TOOL>(); |
|||
|
|||
STATUS_TEXT_POPUP statusPopup( m_frame ); |
|||
bool done = false; |
|||
|
|||
if( m_propertiesDialog ) |
|||
m_propertiesDialog->Show( false ); |
|||
|
|||
Activate(); |
|||
|
|||
statusPopup.SetText( _( "Click on new member..." ) ); |
|||
|
|||
picker->SetClickHandler( |
|||
[&]( const VECTOR2D& aPoint ) -> bool |
|||
{ |
|||
m_toolMgr->RunAction( ACTIONS::selectionClear ); |
|||
|
|||
const PCB_SELECTION& sel = selTool->RequestSelection( |
|||
[]( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool ) |
|||
{ |
|||
} ); |
|||
|
|||
if( sel.Empty() ) |
|||
return true; // still looking for an item
|
|||
|
|||
statusPopup.Hide(); |
|||
|
|||
if( m_propertiesDialog ) |
|||
{ |
|||
EDA_ITEM* elem = sel.Front(); |
|||
|
|||
if( !isFootprintEditor ) |
|||
{ |
|||
while( elem->GetParent() && elem->GetParent()->Type() != PCB_T ) |
|||
elem = elem->GetParent(); |
|||
} |
|||
|
|||
m_propertiesDialog->DoAddMember( elem ); |
|||
m_propertiesDialog->Show( true ); |
|||
} |
|||
|
|||
return false; // got our item; don't need any more
|
|||
} ); |
|||
|
|||
picker->SetMotionHandler( |
|||
[&]( const VECTOR2D& aPos ) |
|||
{ |
|||
statusPopup.Move( KIPLATFORM::UI::GetMousePosition() + wxPoint( 20, -50 ) ); |
|||
} ); |
|||
|
|||
picker->SetCancelHandler( |
|||
[&]() |
|||
{ |
|||
if( m_propertiesDialog ) |
|||
m_propertiesDialog->Show( true ); |
|||
|
|||
statusPopup.Hide(); |
|||
} ); |
|||
|
|||
picker->SetFinalizeHandler( |
|||
[&]( const int& aFinalState ) |
|||
{ |
|||
done = true; |
|||
} ); |
|||
|
|||
statusPopup.Move( KIPLATFORM::UI::GetMousePosition() + wxPoint( 20, -50 ) ); |
|||
statusPopup.Popup(); |
|||
m_frame->GetCanvas()->SetStatusPopup( statusPopup.GetPanel() ); |
|||
|
|||
m_toolMgr->RunAction( ACTIONS::pickerTool, &aEvent ); |
|||
|
|||
while( !done ) |
|||
{ |
|||
// Pass events unless we receive a null event, then we must shut down
|
|||
if( TOOL_EVENT* evt = Wait() ) |
|||
evt->SetPassEvent(); |
|||
else |
|||
break; |
|||
} |
|||
|
|||
m_frame->GetCanvas()->SetStatusPopup( nullptr ); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
|
|||
int PCB_GROUP_TOOL::Group( const TOOL_EVENT& aEvent ) |
|||
{ |
|||
bool isFootprintEditor = m_frame->GetFrameType() == FRAME_FOOTPRINT_EDITOR; |
|||
PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>(); |
|||
PCB_SELECTION selection; |
|||
|
|||
if( isFootprintEditor ) |
|||
{ |
|||
selection = selTool->RequestSelection( |
|||
[]( const VECTOR2I&, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* ) |
|||
{ |
|||
} ); |
|||
} |
|||
else |
|||
{ |
|||
selection = selTool->RequestSelection( |
|||
[]( const VECTOR2I&, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* ) |
|||
{ |
|||
// Iterate from the back so we don't have to worry about removals.
|
|||
for( int i = aCollector.GetCount() - 1; i >= 0; --i ) |
|||
{ |
|||
BOARD_ITEM* item = aCollector[i]; |
|||
|
|||
if( item->GetParentFootprint() ) |
|||
aCollector.Remove( item ); |
|||
} |
|||
} ); |
|||
} |
|||
|
|||
if( selection.Empty() ) |
|||
return 0; |
|||
|
|||
BOARD* board = getModel<BOARD>(); |
|||
PCB_GROUP* group = nullptr; |
|||
|
|||
if( isFootprintEditor ) |
|||
group = new PCB_GROUP( board->GetFirstFootprint() ); |
|||
else |
|||
group = new PCB_GROUP( board ); |
|||
|
|||
for( EDA_ITEM* eda_item : selection ) |
|||
{ |
|||
if( eda_item->IsBOARD_ITEM() ) |
|||
{ |
|||
if( static_cast<BOARD_ITEM*>( eda_item )->IsLocked() ) |
|||
group->SetLocked( true ); |
|||
} |
|||
} |
|||
|
|||
m_commit->Add( group ); |
|||
|
|||
for( EDA_ITEM* eda_item : selection ) |
|||
{ |
|||
if( eda_item->IsBOARD_ITEM() ) |
|||
m_commit->Stage( static_cast<BOARD_ITEM*>( eda_item ), CHT_GROUP ); |
|||
} |
|||
|
|||
m_commit->Push( _( "Group Items" ) ); |
|||
|
|||
m_toolMgr->RunAction( ACTIONS::selectionClear ); |
|||
m_toolMgr->RunAction( ACTIONS::selectItem, group->AsEdaItem() ); |
|||
|
|||
m_toolMgr->PostEvent( EVENTS::SelectedItemsModified ); |
|||
m_frame->OnModify(); |
|||
|
|||
return 0; |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
#include <tool/group_tool.h> |
|||
#include <board_commit.h> |
|||
|
|||
class PCB_GROUP_TOOL : public GROUP_TOOL |
|||
{ |
|||
public: |
|||
/** |
|||
* Invoke the picker tool to select a new member of the group. |
|||
*/ |
|||
int PickNewMember( const TOOL_EVENT& aEvent ) override; |
|||
|
|||
///< Group selected items. |
|||
int Group( const TOOL_EVENT& aEvent ) override; |
|||
|
|||
protected: |
|||
std::unique_ptr<COMMIT> createCommit() override { return std::make_unique<BOARD_COMMIT>( this ); } |
|||
}; |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue