Commit 2ee85807 authored by Maciej Suminski's avatar Maciej Suminski

Moved VIEW_GROUP creation to the selection tool. In this way selected items...

Moved VIEW_GROUP creation to the selection tool. In this way selected items are always drawn on overlay, not only when dragged.
parent 86000832
...@@ -78,15 +78,15 @@ bool MOVE_TOOL::Init() ...@@ -78,15 +78,15 @@ bool MOVE_TOOL::Init()
int MOVE_TOOL::Main( TOOL_EVENT& aEvent ) int MOVE_TOOL::Main( TOOL_EVENT& aEvent )
{ {
const SELECTION_TOOL::SELECTION selection = m_selectionTool->GetSelection();
if( selection.Empty() )
return 0; // there are no items to operate on
VECTOR2D dragPosition; VECTOR2D dragPosition;
bool dragging = false; bool dragging = false;
bool restore = false; // Should items' state be restored when finishing the tool? bool restore = false; // Should items' state be restored when finishing the tool?
VIEW* view = getView();
VIEW_CONTROLS* controls = getViewControls();
// Add a VIEW_GROUP that will hold all modified items
view->Add( &m_items );
VIEW_CONTROLS* controls = getViewControls();
controls->ShowCursor( true ); controls->ShowCursor( true );
controls->SetSnapping( true ); controls->SetSnapping( true );
controls->SetAutoPan( true ); controls->SetAutoPan( true );
...@@ -108,12 +108,12 @@ int MOVE_TOOL::Main( TOOL_EVENT& aEvent ) ...@@ -108,12 +108,12 @@ int MOVE_TOOL::Main( TOOL_EVENT& aEvent )
if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) // got rotation event? if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) // got rotation event?
{ {
m_state.Rotate( cursorPos, 900.0 ); m_state.Rotate( cursorPos, 900.0 );
m_items.ViewUpdate( VIEW_ITEM::GEOMETRY ); selection.group->ViewUpdate( VIEW_ITEM::GEOMETRY );
} }
else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) // got flip event? else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) // got flip event?
{ {
m_state.Flip( cursorPos ); m_state.Flip( cursorPos );
m_items.ViewUpdate( VIEW_ITEM::GEOMETRY ); selection.group->ViewUpdate( VIEW_ITEM::GEOMETRY );
} }
} }
...@@ -128,98 +128,38 @@ int MOVE_TOOL::Main( TOOL_EVENT& aEvent ) ...@@ -128,98 +128,38 @@ int MOVE_TOOL::Main( TOOL_EVENT& aEvent )
else else
{ {
// Prepare to drag // Prepare to drag
m_selection = m_selectionTool->GetSelection();
if( m_selection.empty() )
break; // there are no items to operate on
std::set<BOARD_ITEM*>::iterator it; std::set<BOARD_ITEM*>::iterator it;
for( it = m_selection.begin(); it != m_selection.end(); ++it ) for( it = selection.items.begin(); it != selection.items.end(); ++it )
{ {
// Save the state of the selected items, in case it has to be restored // Save the state of the selected items, in case it has to be restored
m_state.Save( *it ); m_state.Save( *it );
// Gather all selected items into one VIEW_GROUP
vgAdd( *it, &m_items );
} }
// Hide the original items, they are temporarily shown in VIEW_GROUP on overlay
vgSetVisibility( &m_items, false );
vgUpdate( &m_items, VIEW_ITEM::APPEARANCE );
dragging = true; dragging = true;
} }
m_items.ViewUpdate( VIEW_ITEM::GEOMETRY ); selection.group->ViewUpdate( VIEW_ITEM::GEOMETRY );
dragPosition = evt->Position(); dragPosition = evt->Position();
} }
else if( evt->IsMouseUp( MB_Left ) || evt->IsClick( MB_Left ) ) else if( evt->IsMouseUp( MB_Left ) || evt->IsClick( MB_Left ) )
break; // Finish break; // Finish
} }
// Restore visibility of the original items
vgSetVisibility( &m_items, true );
if( restore ) if( restore )
{ {
// Modifications has to be rollbacked, so restore the previous state of items // Modifications has to be rollbacked, so restore the previous state of items
vgUpdate( &m_items, VIEW_ITEM::APPEARANCE );
m_state.RestoreAll(); m_state.RestoreAll();
} }
else else
{ {
// Changes are applied, so update the items // Changes are applied, so update the items
vgUpdate( &m_items, m_state.GetUpdateFlag() ); selection.group->ItemsViewUpdate( m_state.GetUpdateFlag() );
m_state.Apply(); m_state.Apply();
} }
m_items.Clear();
view->Remove( &m_items );
controls->ShowCursor( false ); controls->ShowCursor( false );
controls->SetSnapping( false ); controls->SetSnapping( false );
controls->SetAutoPan( false ); controls->SetAutoPan( false );
return 0; return 0;
} }
void MOVE_TOOL::vgAdd( BOARD_ITEM* aItem, VIEW_GROUP* aGroup )
{
// Modules are treated in a special way - when they are moved, we have to
// move all the parts that make the module, not the module itself
if( aItem->Type() == PCB_MODULE_T )
{
MODULE* module = static_cast<MODULE*>( aItem );
// Add everything that belongs to the module (besides the module itself)
for( D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() )
aGroup->Add( pad );
for( BOARD_ITEM* drawing = module->GraphicalItems().GetFirst(); drawing;
drawing = drawing->Next() )
aGroup->Add( drawing );
aGroup->Add( &module->Reference() );
aGroup->Add( &module->Value() );
}
// Add items to the VIEW_GROUP, so they will be displayed on the overlay
// while dragging
aGroup->Add( aItem );
}
void MOVE_TOOL::vgSetVisibility( VIEW_GROUP* aGroup, bool aVisible ) const
{
std::set<VIEW_ITEM*>::const_iterator it, it_end;
for( it = aGroup->Begin(), it_end = aGroup->End(); it != it_end; ++it )
(*it)->ViewSetVisible( aVisible );
}
void MOVE_TOOL::vgUpdate( VIEW_GROUP* aGroup, VIEW_ITEM::ViewUpdateFlags aFlags ) const
{
std::set<VIEW_ITEM*>::const_iterator it, it_end;
for( it = aGroup->Begin(), it_end = aGroup->End(); it != it_end; ++it )
(*it)->ViewUpdate( aFlags );
}
...@@ -65,26 +65,11 @@ public: ...@@ -65,26 +65,11 @@ public:
int Main( TOOL_EVENT& aEvent ); int Main( TOOL_EVENT& aEvent );
private: private:
/// Adds an item to the VIEW_GROUP that holds all moved items and displays them on the overlay
void vgAdd( BOARD_ITEM* aItem, KiGfx::VIEW_GROUP* aGroup );
/// Changes visibility settings for items stored in a VIEW_GROUP
void vgSetVisibility( KiGfx::VIEW_GROUP* aGroup, bool aVisible ) const;
/// Updates items stored in a VIEW_GROUP with selected update flag
void vgUpdate( KiGfx::VIEW_GROUP* aGroup, KiGfx::VIEW_ITEM::ViewUpdateFlags aFlags ) const;
/// Saves the state of items and allows to restore them /// Saves the state of items and allows to restore them
ITEM_STATE m_state; ITEM_STATE m_state;
/// Selection tool used for obtaining selected items /// Selection tool used for obtaining selected items
SELECTION_TOOL* m_selectionTool; SELECTION_TOOL* m_selectionTool;
/// Set of selected items (obtained from pcbnew.InteractiveSelection tool)
std::set<BOARD_ITEM*> m_selection;
/// VIEW_GROUP that helds currently moved items
KiGfx::VIEW_GROUP m_items;
}; };
#endif #endif
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <wxPcbStruct.h> #include <wxPcbStruct.h>
#include <collectors.h> #include <collectors.h>
#include <view/view_controls.h> #include <view/view_controls.h>
#include <view/view_group.h>
#include <painter.h> #include <painter.h>
#include <tool/tool_event.h> #include <tool/tool_event.h>
...@@ -53,20 +54,19 @@ SELECTION_TOOL::SELECTION_TOOL() : ...@@ -53,20 +54,19 @@ SELECTION_TOOL::SELECTION_TOOL() :
TOOL_INTERACTIVE( "pcbnew.InteractiveSelection" ), m_multiple( false ) TOOL_INTERACTIVE( "pcbnew.InteractiveSelection" ), m_multiple( false )
{ {
m_selArea = new SELECTION_AREA; m_selArea = new SELECTION_AREA;
m_selection.group = new KiGfx::VIEW_GROUP;
} }
SELECTION_TOOL::~SELECTION_TOOL() SELECTION_TOOL::~SELECTION_TOOL()
{ {
if( m_selArea )
delete m_selArea; delete m_selArea;
delete m_selection.group;
} }
void SELECTION_TOOL::Reset() void SELECTION_TOOL::Reset()
{ {
m_selectedItems.clear();
// The tool launches upon reception of action event ("pcbnew.InteractiveSelection") // The tool launches upon reception of action event ("pcbnew.InteractiveSelection")
Go( &SELECTION_TOOL::Main, COMMON_ACTIONS::selectionActivate.MakeEvent() ); Go( &SELECTION_TOOL::Main, COMMON_ACTIONS::selectionActivate.MakeEvent() );
} }
...@@ -75,8 +75,11 @@ void SELECTION_TOOL::Reset() ...@@ -75,8 +75,11 @@ void SELECTION_TOOL::Reset()
int SELECTION_TOOL::Main( TOOL_EVENT& aEvent ) int SELECTION_TOOL::Main( TOOL_EVENT& aEvent )
{ {
BOARD* board = getModel<BOARD>( PCB_T ); BOARD* board = getModel<BOARD>( PCB_T );
VIEW* view = getView();
assert( board != NULL ); assert( board != NULL );
view->Add( m_selection.group );
// Main loop: keep receiving events // Main loop: keep receiving events
while( OPT_TOOL_EVENT evt = Wait() ) while( OPT_TOOL_EVENT evt = Wait() )
{ {
...@@ -86,7 +89,7 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent ) ...@@ -86,7 +89,7 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent )
if( evt->IsCancel() ) if( evt->IsCancel() )
{ {
if( !m_selectedItems.empty() ) // Cancel event deselects items... if( !m_selection.Empty() ) // Cancel event deselects items...
clearSelection(); clearSelection();
else // ...unless there is nothing selected else // ...unless there is nothing selected
break; // then exit the tool break; // then exit the tool
...@@ -99,7 +102,7 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent ) ...@@ -99,7 +102,7 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent )
// drag with LMB? Select multiple objects (or at least draw a selection box) or drag them // drag with LMB? Select multiple objects (or at least draw a selection box) or drag them
if( evt->IsDrag( MB_Left ) ) if( evt->IsDrag( MB_Left ) )
{ {
if( m_selectedItems.empty() || m_additive ) if( m_selection.Empty() || m_additive )
{ {
// If nothings has been selected or user wants to select more // If nothings has been selected or user wants to select more
// draw the selection box // draw the selection box
...@@ -112,7 +115,6 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent ) ...@@ -112,7 +115,6 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent )
{ {
// Yes -> run the move tool and wait till it finishes // Yes -> run the move tool and wait till it finishes
m_toolMgr->InvokeTool( "pcbnew.InteractiveMove" ); m_toolMgr->InvokeTool( "pcbnew.InteractiveMove" );
Wait();
} }
else else
{ {
...@@ -123,6 +125,9 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent ) ...@@ -123,6 +125,9 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent )
} }
} }
m_selection.group->Clear();
view->Remove( m_selection.group );
return 0; return 0;
} }
...@@ -137,9 +142,13 @@ void SELECTION_TOOL::AddMenuItem( const TOOL_ACTION& aAction ) ...@@ -137,9 +142,13 @@ void SELECTION_TOOL::AddMenuItem( const TOOL_ACTION& aAction )
void SELECTION_TOOL::toggleSelection( BOARD_ITEM* aItem ) void SELECTION_TOOL::toggleSelection( BOARD_ITEM* aItem )
{ {
if( m_selectedItems.find( aItem ) != m_selectedItems.end() ) if( m_selection.items.find( aItem ) != m_selection.items.end() )
{ {
deselectItem( aItem ); deselectItem( aItem );
// If there is nothing selected, disable the context menu
if( m_selection.Empty() )
SetContextMenu( &m_menu, CMENU_OFF );
} }
else else
{ {
...@@ -148,19 +157,29 @@ void SELECTION_TOOL::toggleSelection( BOARD_ITEM* aItem ) ...@@ -148,19 +157,29 @@ void SELECTION_TOOL::toggleSelection( BOARD_ITEM* aItem )
// Prevent selection of invisible or inactive items // Prevent selection of invisible or inactive items
if( selectable( aItem ) ) if( selectable( aItem ) )
{
selectItem( aItem ); selectItem( aItem );
// Now the context menu should be enabled
SetContextMenu( &m_menu, CMENU_BUTTON );
}
} }
} }
void SELECTION_TOOL::clearSelection() void SELECTION_TOOL::clearSelection()
{ {
BOOST_FOREACH( BOARD_ITEM* item, m_selectedItems ) VIEW_GROUP::const_iter it, it_end;
for( it = m_selection.group->Begin(), it_end = m_selection.group->End(); it != it_end; ++it )
{ {
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( *it );
item->ViewSetVisible( true );
item->ClearSelected(); item->ClearSelected();
} }
m_selectedItems.clear(); m_selection.group->Clear();
m_selection.items.clear();
// Do not show the context menu when there is nothing selected // Do not show the context menu when there is nothing selected
SetContextMenu( &m_menu, CMENU_OFF ); SetContextMenu( &m_menu, CMENU_OFF );
...@@ -258,9 +277,6 @@ bool SELECTION_TOOL::selectMultiple() ...@@ -258,9 +277,6 @@ bool SELECTION_TOOL::selectMultiple()
VIEW* view = getView(); VIEW* view = getView();
getViewControls()->SetAutoPan( true ); getViewControls()->SetAutoPan( true );
// These 2 lines remove the blink-in-the-random-place effect
m_selArea->SetOrigin( VECTOR2I( 0, 0 ) );
m_selArea->SetEnd( VECTOR2I( 0, 0 ) );
view->Add( m_selArea ); view->Add( m_selArea );
while( OPT_TOOL_EVENT evt = Wait() ) while( OPT_TOOL_EVENT evt = Wait() )
...@@ -300,14 +316,11 @@ bool SELECTION_TOOL::selectMultiple() ...@@ -300,14 +316,11 @@ bool SELECTION_TOOL::selectMultiple()
// Add only those items that are visible and fully within the selection box // Add only those items that are visible and fully within the selection box
if( selectable( item ) && selectionBox.Contains( item->ViewBBox() ) ) if( selectable( item ) && selectionBox.Contains( item->ViewBBox() ) )
{ selectItem( item );
item->SetSelected();
m_selectedItems.insert( item );
}
} }
// Now the context menu should be enabled // Now the context menu should be enabled
if( !m_selectedItems.empty() ) if( !m_selection.Empty() )
SetContextMenu( &m_menu, CMENU_BUTTON ); SetContextMenu( &m_menu, CMENU_BUTTON );
break; break;
...@@ -377,6 +390,7 @@ BOARD_ITEM* SELECTION_TOOL::disambiguationMenu( GENERAL_COLLECTOR* aCollector ) ...@@ -377,6 +390,7 @@ BOARD_ITEM* SELECTION_TOOL::disambiguationMenu( GENERAL_COLLECTOR* aCollector )
} }
} }
// Removes possible brighten mark
getView()->MarkTargetDirty( TARGET_OVERLAY ); getView()->MarkTargetDirty( TARGET_OVERLAY );
// Restore the original menu // Restore the original menu
...@@ -464,13 +478,98 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const ...@@ -464,13 +478,98 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const
} }
void SELECTION_TOOL::selectItem( BOARD_ITEM* aItem )
{
/// Selecting an item needs a few operations, so they are wrapped in a functor
class selectBase_
{
SELECTION& s;
public:
selectBase_( SELECTION& s_ ) : s( s_ ) {}
void operator()( BOARD_ITEM* item )
{
s.group->Add( item );
// Hide the original item, so it is shown only on overlay
item->ViewSetVisible( false );
item->SetSelected();
}
} selectBase( m_selection );
// Modules are treated in a special way - when they are moved, we have to
// move all the parts that make the module, not the module itself
if( aItem->Type() == PCB_MODULE_T )
{
MODULE* module = static_cast<MODULE*>( aItem );
// Add everything that belongs to the module (besides the module itself)
for( D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() )
selectBase( pad );
for( BOARD_ITEM* drawing = module->GraphicalItems().GetFirst(); drawing;
drawing = drawing->Next() )
selectBase( drawing );
selectBase( &module->Reference() );
selectBase( &module->Value() );
}
// Add items to the VIEW_GROUP, so they will be displayed on the overlay
selectBase( aItem );
m_selection.items.insert( aItem );
}
void SELECTION_TOOL::deselectItem( BOARD_ITEM* aItem )
{
/// Deselecting an item needs a few operations, so they are wrapped in a functor
class deselectBase_
{
SELECTION& s;
public:
deselectBase_( SELECTION& s_ ) : s( s_ ) {}
void operator()( BOARD_ITEM* item )
{
s.group->Remove( item );
// Restore original item visibility
item->ViewSetVisible( true );
item->ClearSelected();
}
} deselectBase( m_selection );
// Modules are treated in a special way - when they are moved, we have to
// move all the parts that make the module, not the module itself
if( aItem->Type() == PCB_MODULE_T )
{
MODULE* module = static_cast<MODULE*>( aItem );
// Add everything that belongs to the module (besides the module itself)
for( D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() )
deselectBase( pad );
for( BOARD_ITEM* drawing = module->GraphicalItems().GetFirst(); drawing;
drawing = drawing->Next() )
deselectBase( drawing );
deselectBase( &module->Reference() );
deselectBase( &module->Value() );
}
deselectBase( aItem );
m_selection.items.erase( aItem );
}
bool SELECTION_TOOL::containsSelected( const VECTOR2I& aPoint ) const bool SELECTION_TOOL::containsSelected( const VECTOR2I& aPoint ) const
{ {
const unsigned GRIP_MARGIN = 500000; const unsigned GRIP_MARGIN = 500000;
// Check if the point is located within any of the currently selected items bounding boxes // Check if the point is located within any of the currently selected items bounding boxes
std::set<BOARD_ITEM*>::iterator it, it_end; std::set<BOARD_ITEM*>::iterator it, it_end;
for( it = m_selectedItems.begin(), it_end = m_selectedItems.end(); it != it_end; ++it ) for( it = m_selection.items.begin(), it_end = m_selection.items.end(); it != it_end; ++it )
{ {
BOX2I itemBox = (*it)->ViewBBox(); BOX2I itemBox = (*it)->ViewBBox();
itemBox.Inflate( GRIP_MARGIN ); // Give some margin for gripping an item itemBox.Inflate( GRIP_MARGIN ); // Give some margin for gripping an item
......
...@@ -36,6 +36,11 @@ class SELECTION_AREA; ...@@ -36,6 +36,11 @@ class SELECTION_AREA;
class BOARD_ITEM; class BOARD_ITEM;
class GENERAL_COLLECTOR; class GENERAL_COLLECTOR;
namespace KiGfx
{
class VIEW_GROUP;
}
/** /**
* Class SELECTION_TOOL * Class SELECTION_TOOL
* *
...@@ -54,6 +59,18 @@ public: ...@@ -54,6 +59,18 @@ public:
SELECTION_TOOL(); SELECTION_TOOL();
~SELECTION_TOOL(); ~SELECTION_TOOL();
struct SELECTION
{
/// Set of selected items
std::set<BOARD_ITEM*> items;
/// VIEW_GROUP that holds currently selected items
KiGfx::VIEW_GROUP* group;
/// Checks if there is anything selected
bool Empty() const { return items.empty(); }
};
/// @copydoc TOOL_INTERACTIVE::Reset() /// @copydoc TOOL_INTERACTIVE::Reset()
void Reset(); void Reset();
...@@ -69,9 +86,9 @@ public: ...@@ -69,9 +86,9 @@ public:
* *
* Returns the set of currently selected items. * Returns the set of currently selected items.
*/ */
const std::set<BOARD_ITEM*>& GetSelection() const const SELECTION& GetSelection() const
{ {
return m_selectedItems; return m_selection;
} }
/** /**
...@@ -145,14 +162,7 @@ private: ...@@ -145,14 +162,7 @@ private:
* *
* @param aItem is an item to be selected. * @param aItem is an item to be selected.
*/ */
void selectItem( BOARD_ITEM* aItem ) void selectItem( BOARD_ITEM* aItem );
{
aItem->SetSelected();
m_selectedItems.insert( aItem );
// Now the context menu should be enabled
SetContextMenu( &m_menu, CMENU_BUTTON );
}
/** /**
* Function deselectItem() * Function deselectItem()
...@@ -160,15 +170,7 @@ private: ...@@ -160,15 +170,7 @@ private:
* *
* @param aItem is an item to be deselected. * @param aItem is an item to be deselected.
*/ */
void deselectItem( BOARD_ITEM* aItem ) void deselectItem( BOARD_ITEM* aItem );
{
aItem->ClearSelected();
m_selectedItems.erase( aItem );
if( m_selectedItems.empty() )
// If there is nothing selected, disable the context menu
SetContextMenu( &m_menu, CMENU_OFF );
}
/** /**
* Function containsSelected() * Function containsSelected()
...@@ -178,12 +180,12 @@ private: ...@@ -178,12 +180,12 @@ private:
*/ */
bool containsSelected( const VECTOR2I& aPoint ) const; bool containsSelected( const VECTOR2I& aPoint ) const;
/// Container storing currently selected items
std::set<BOARD_ITEM*> m_selectedItems;
/// Visual representation of selection box /// Visual representation of selection box
SELECTION_AREA* m_selArea; SELECTION_AREA* m_selArea;
/// Current state of selection
SELECTION m_selection;
/// Flag saying if items should be added to the current selection or rather replace it /// Flag saying if items should be added to the current selection or rather replace it
bool m_additive; bool m_additive;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment