diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index bbe7d2934f..7c195331d7 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -32,7 +32,7 @@ set(GAL_SRCS # Common part drawpanel_gal.cpp painter.cpp - worksheet_item.cpp + worksheet_viewitem.cpp gal/graphics_abstraction_layer.cpp gal/stroke_font.cpp gal/color4d.cpp diff --git a/common/view/view.cpp b/common/view/view.cpp index 10d52c62d7..b8c54e3025 100644 --- a/common/view/view.cpp +++ b/common/view/view.cpp @@ -676,9 +676,9 @@ struct VIEW::unlinkItem }; -struct VIEW::recacheLayer +struct VIEW::recacheItem { - recacheLayer( VIEW* aView, GAL* aGal, int aLayer, bool aImmediately ) : + recacheItem( VIEW* aView, GAL* aGal, int aLayer, bool aImmediately ) : view( aView ), gal( aGal ), layer( aLayer ), immediately( aImmediately ) { } @@ -688,9 +688,7 @@ struct VIEW::recacheLayer // Remove previously cached group int prevGroup = aItem->getGroup( layer ); if( prevGroup >= 0 ) - { gal->DeleteGroup( prevGroup ); - } if( immediately ) { @@ -882,6 +880,10 @@ void VIEW::updateItemGeometry( VIEW_ITEM* aItem, int aLayer ) m_gal->SetLayerDepth( l.renderingOrder ); // Redraw the item from scratch + int prevGroup = aItem->getGroup( aLayer ); + if( prevGroup >= 0 ) + m_gal->DeleteGroup( prevGroup ); + int group = m_gal->BeginGroup(); aItem->setGroup( aLayer, group ); m_painter->Draw( static_cast( aItem ), aLayer ); @@ -966,7 +968,7 @@ void VIEW::RecacheAllItems( bool aImmediately ) { m_gal->SetTarget( l->target ); m_gal->SetLayerDepth( l->renderingOrder ); - recacheLayer visitor( this, m_gal, l->id, aImmediately ); + recacheItem visitor( this, m_gal, l->id, aImmediately ); l->items->Query( r, visitor ); MarkTargetDirty( l->target ); } diff --git a/common/view/view_group.cpp b/common/view/view_group.cpp index dfaf595c5c..62ef738c82 100644 --- a/common/view/view_group.cpp +++ b/common/view/view_group.cpp @@ -71,16 +71,6 @@ void VIEW_GROUP::Clear() } -void VIEW_GROUP::FreeItems() -{ - BOOST_FOREACH( VIEW_ITEM* item, m_items ) - { - delete item; - } - m_items.clear(); -} - - unsigned int VIEW_GROUP::GetSize() const { return m_items.size(); @@ -102,6 +92,8 @@ void VIEW_GROUP::ViewDraw( int aLayer, GAL* aGal ) const // Draw all items immediately (without caching) BOOST_FOREACH( VIEW_ITEM* item, m_items ) { + aGal->PushDepth(); + int layers[VIEW::VIEW_MAX_LAYERS], layers_count; item->ViewGetLayers( layers, layers_count ); m_view->SortLayers( layers, layers_count ); @@ -110,12 +102,14 @@ void VIEW_GROUP::ViewDraw( int aLayer, GAL* aGal ) const { if( m_view->IsCached( layers[i] ) && m_view->IsLayerVisible( layers[i] ) ) { - aGal->SetLayerDepth( m_view->GetLayerOrder( layers[i] ) ); + aGal->AdvanceDepth(); if( !painter->Draw( item, layers[i] ) ) item->ViewDraw( layers[i], aGal ); // Alternative drawing method } } + + aGal->PopDepth(); } } @@ -128,6 +122,34 @@ void VIEW_GROUP::ViewGetLayers( int aLayers[], int& aCount ) const } +void VIEW_GROUP::FreeItems() +{ + BOOST_FOREACH( VIEW_ITEM* item, m_items ) + { + delete item; + } + m_items.clear(); +} + + +void VIEW_GROUP::ItemsSetVisibility( bool aVisible ) +{ + std::set::const_iterator it, it_end; + + for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it ) + (*it)->ViewSetVisible( aVisible ); +} + + +void VIEW_GROUP::ItemsViewUpdate( VIEW_ITEM::ViewUpdateFlags aFlags ) +{ + std::set::const_iterator it, it_end; + + for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it ) + (*it)->ViewUpdate( aFlags ); +} + + void VIEW_GROUP::updateBbox() { // Save the used VIEW, as it used nulled during Remove() diff --git a/common/worksheet_item.cpp b/common/worksheet_viewitem.cpp similarity index 86% rename from common/worksheet_item.cpp rename to common/worksheet_viewitem.cpp index e46d3e2822..80028a3236 100644 --- a/common/worksheet_item.cpp +++ b/common/worksheet_viewitem.cpp @@ -23,11 +23,11 @@ */ /** - * @file worksheet_item.cpp + * @file worksheet_viewitem.cpp * @brief Class that handles properties and drawing of worksheet layout. */ -#include +#include #include #include #include @@ -36,28 +36,28 @@ using namespace KiGfx; -WORKSHEET_ITEM::WORKSHEET_ITEM( const std::string& aFileName, const std::string& aSheetName, +WORKSHEET_VIEWITEM::WORKSHEET_VIEWITEM( const std::string& aFileName, const std::string& aSheetName, const PAGE_INFO* aPageInfo, const TITLE_BLOCK* aTitleBlock ) : EDA_ITEM( NOT_USED ), // this item is never added to a BOARD so it needs no type m_fileName( aFileName ), m_sheetName( aSheetName ), m_titleBlock( aTitleBlock ), m_pageInfo( aPageInfo ), m_sheetNumber( 1 ), m_sheetCount( 1 ) {} -void WORKSHEET_ITEM::SetPageInfo( const PAGE_INFO* aPageInfo ) +void WORKSHEET_VIEWITEM::SetPageInfo( const PAGE_INFO* aPageInfo ) { m_pageInfo = aPageInfo; ViewUpdate( GEOMETRY ); } -void WORKSHEET_ITEM::SetTitleBlock( const TITLE_BLOCK* aTitleBlock ) +void WORKSHEET_VIEWITEM::SetTitleBlock( const TITLE_BLOCK* aTitleBlock ) { m_titleBlock = aTitleBlock; ViewUpdate( GEOMETRY ); } -const BOX2I WORKSHEET_ITEM::ViewBBox() const +const BOX2I WORKSHEET_VIEWITEM::ViewBBox() const { BOX2I bbox; @@ -76,7 +76,7 @@ const BOX2I WORKSHEET_ITEM::ViewBBox() const } -void WORKSHEET_ITEM::ViewDraw( int aLayer, GAL* aGal ) const +void WORKSHEET_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const { RENDER_SETTINGS* settings = m_view->GetPainter()->GetSettings(); wxString fileName( m_fileName.c_str(), wxConvUTF8 ); @@ -128,14 +128,14 @@ void WORKSHEET_ITEM::ViewDraw( int aLayer, GAL* aGal ) const } -void WORKSHEET_ITEM::ViewGetLayers( int aLayers[], int& aCount ) const +void WORKSHEET_VIEWITEM::ViewGetLayers( int aLayers[], int& aCount ) const { aCount = 1; aLayers[0] = ITEM_GAL_LAYER( WORKSHEET ); } -void WORKSHEET_ITEM::draw( const WS_DRAW_ITEM_LINE* aItem, GAL* aGal ) const +void WORKSHEET_VIEWITEM::draw( const WS_DRAW_ITEM_LINE* aItem, GAL* aGal ) const { aGal->SetIsStroke( true ); aGal->SetIsFill( false ); @@ -145,7 +145,7 @@ void WORKSHEET_ITEM::draw( const WS_DRAW_ITEM_LINE* aItem, GAL* aGal ) const } -void WORKSHEET_ITEM::draw( const WS_DRAW_ITEM_RECT* aItem, GAL* aGal ) const +void WORKSHEET_VIEWITEM::draw( const WS_DRAW_ITEM_RECT* aItem, GAL* aGal ) const { aGal->SetIsStroke( true ); aGal->SetIsFill( false ); @@ -155,7 +155,7 @@ void WORKSHEET_ITEM::draw( const WS_DRAW_ITEM_RECT* aItem, GAL* aGal ) const } -void WORKSHEET_ITEM::draw( const WS_DRAW_ITEM_POLYGON* aItem, GAL* aGal ) const +void WORKSHEET_VIEWITEM::draw( const WS_DRAW_ITEM_POLYGON* aItem, GAL* aGal ) const { std::deque corners; BOOST_FOREACH( wxPoint point, aItem->m_Corners ) @@ -181,7 +181,7 @@ void WORKSHEET_ITEM::draw( const WS_DRAW_ITEM_POLYGON* aItem, GAL* aGal ) const } -void WORKSHEET_ITEM::draw( const WS_DRAW_ITEM_TEXT* aItem, GAL* aGal ) const +void WORKSHEET_VIEWITEM::draw( const WS_DRAW_ITEM_TEXT* aItem, GAL* aGal ) const { VECTOR2D position( aItem->GetTextPosition().x, aItem->GetTextPosition().y ); @@ -192,7 +192,7 @@ void WORKSHEET_ITEM::draw( const WS_DRAW_ITEM_TEXT* aItem, GAL* aGal ) const } -void WORKSHEET_ITEM::drawBorder( GAL* aGal ) const +void WORKSHEET_VIEWITEM::drawBorder( GAL* aGal ) const { VECTOR2D origin = VECTOR2D( 0.0, 0.0 ); VECTOR2D end = VECTOR2D( m_pageInfo->GetWidthMils() * 25400, diff --git a/include/gal/definitions.h b/include/gal/definitions.h index ce18235bd1..8a506852c2 100644 --- a/include/gal/definitions.h +++ b/include/gal/definitions.h @@ -38,13 +38,11 @@ namespace KiGfx */ enum RenderTarget { - TARGET_CACHED, ///< Main rendering target (cached) + TARGET_CACHED = 0, ///< Main rendering target (cached) TARGET_NONCACHED, ///< Auxiliary rendering target (noncached) - TARGET_OVERLAY ///< Items that may change while the view stays the same (noncached) + TARGET_OVERLAY, ///< Items that may change while the view stays the same (noncached) + TARGETS_NUMBER ///< Number of available rendering targets }; - - /// Number of available rendering targets - static const int TARGETS_NUMBER = 3; } #endif /* DEFINITIONS_H_ */ diff --git a/include/gal/graphics_abstraction_layer.h b/include/gal/graphics_abstraction_layer.h index 77cb3c48a8..098635d96c 100644 --- a/include/gal/graphics_abstraction_layer.h +++ b/include/gal/graphics_abstraction_layer.h @@ -798,7 +798,7 @@ public: */ inline void AdvanceDepth() { - layerDepth -= std::numeric_limits::epsilon(); + layerDepth -= 0.001; } /** diff --git a/include/layers_id_colors_and_visibility.h b/include/layers_id_colors_and_visibility.h index 71a3309dbc..49b0b03508 100644 --- a/include/layers_id_colors_and_visibility.h +++ b/include/layers_id_colors_and_visibility.h @@ -261,7 +261,6 @@ enum PCB_VISIBLE PAD_BK_NETNAMES_VISIBLE, PADS_NETNAMES_VISIBLE, - SELECTION, WORKSHEET, GP_OVERLAY, // General purpose overlay diff --git a/include/view/view.h b/include/view/view.h index 0dd12e803a..9abf733f47 100644 --- a/include/view/view.h +++ b/include/view/view.h @@ -500,7 +500,7 @@ private: // Function objects that need to access VIEW/VIEW_ITEM private/protected members struct clearLayerCache; - struct recacheLayer; + struct recacheItem; struct drawItem; struct unlinkItem; struct updateItemsColor; diff --git a/include/view/view_group.h b/include/view/view_group.h index 54dbd16521..bdec53eacb 100644 --- a/include/view/view_group.h +++ b/include/view/view_group.h @@ -45,6 +45,10 @@ public: VIEW_GROUP( VIEW* aView = NULL ); virtual ~VIEW_GROUP(); + /// Helper typedefs + typedef std::set::const_iterator const_iter; + typedef std::set::iterator iter; + /** * Function Add() * Adds an item to the group. @@ -71,7 +75,7 @@ public: * Function Begin() * Returns iterator to beginning. */ - inline std::set::const_iterator Begin() const + inline const_iter Begin() const { return m_items.begin(); } @@ -80,7 +84,7 @@ public: * Function End() * Returns iterator to end. */ - inline std::set::const_iterator End() const + inline const_iter End() const { return m_items.end(); } @@ -147,6 +151,22 @@ public: return m_view; } + /** + * Function ItemsSetVisibility() + * Sets visibility of items stored in the VIEW_GROUP. + * + * @param aVisible decides if items should be visible or not. + */ + virtual void ItemsSetVisibility( bool aVisible ); + + /** + * Function ItemsViewUpdate() + * Updates items stored in the VIEW_GROUP. + * + * @param aFlags determines the way in which items will be updated. + */ + virtual void ItemsViewUpdate( VIEW_ITEM::ViewUpdateFlags aFlags ); + protected: /// These functions cannot be used with VIEW_GROUP as they are intended only to work with /// singular VIEW_ITEMs (there is only one-to-one relation between item/layer combination and diff --git a/include/worksheet_item.h b/include/worksheet_viewitem.h similarity index 94% rename from include/worksheet_item.h rename to include/worksheet_viewitem.h index b26ec01085..fd7595f626 100644 --- a/include/worksheet_item.h +++ b/include/worksheet_viewitem.h @@ -23,12 +23,12 @@ */ /** - * @file worksheet_item.h + * @file worksheet_viewitem.h * @brief Class that handles properties and drawing of worksheet layout. */ -#ifndef WORKSHEET_ITEM_H -#define WORKSHEET_ITEM_H +#ifndef WORKSHEET_VIEWITEM_H +#define WORKSHEET_VIEWITEM_H #include @@ -44,12 +44,11 @@ namespace KiGfx { class GAL; -class WORKSHEET_ITEM : public EDA_ITEM +class WORKSHEET_VIEWITEM : public EDA_ITEM { public: - WORKSHEET_ITEM( const std::string& aFileName, const std::string& aSheetName, + WORKSHEET_VIEWITEM( const std::string& aFileName, const std::string& aSheetName, const PAGE_INFO* aPageInfo, const TITLE_BLOCK* aTitleBlock ); - ~WORKSHEET_ITEM() {} /** * Function SetFileName() @@ -160,4 +159,4 @@ protected: }; } -#endif /* WORKSHEET_ITEM_H */ +#endif /* WORKSHEET_VIEWITEM_H */ diff --git a/include/wxBasePcbFrame.h b/include/wxBasePcbFrame.h index 58ddac8154..7e1605895f 100644 --- a/include/wxBasePcbFrame.h +++ b/include/wxBasePcbFrame.h @@ -115,6 +115,8 @@ protected: MODULE* loadFootprint( const FPID& aFootprintId ) throw( IO_ERROR, PARSE_ERROR ); + ///> Rendering order of layers on GAL-based canvas (lower index in the array + ///> means that layer is displayed closer to the user, ie. on the top). static const LAYER_NUM GAL_LAYER_ORDER[]; public: diff --git a/pcbnew/basepcbframe.cpp b/pcbnew/basepcbframe.cpp index be2c8d756e..472992216e 100644 --- a/pcbnew/basepcbframe.cpp +++ b/pcbnew/basepcbframe.cpp @@ -53,7 +53,7 @@ #include #include #include -#include +#include #include #include @@ -70,11 +70,9 @@ static const wxString DisplayModuleTextEntry( wxT( "DiModTx" ) ); static const wxString FastGrid1Entry( wxT( "FastGrid1" ) ); static const wxString FastGrid2Entry( wxT( "FastGrid2" ) ); -/// Rendering order of layers on GAL-based canvas (lower index in the array -/// means that layer is displayed closer to the user, ie. on the top). const LAYER_NUM PCB_BASE_FRAME::GAL_LAYER_ORDER[] = { - ITEM_GAL_LAYER( GP_OVERLAY ), ITEM_GAL_LAYER( SELECTION ), + ITEM_GAL_LAYER( GP_OVERLAY ), ITEM_GAL_LAYER( PADS_NETNAMES_VISIBLE ), DRAW_N, COMMENT_N, ECO1_N, ECO2_N, EDGE_N, UNUSED_LAYER_29, UNUSED_LAYER_30, UNUSED_LAYER_31, @@ -242,7 +240,7 @@ void PCB_BASE_FRAME::ViewReloadBoard( const BOARD* aBoard ) const } // Add an entry for the worksheet layout - KiGfx::WORKSHEET_ITEM* worksheet = new KiGfx::WORKSHEET_ITEM( + KiGfx::WORKSHEET_VIEWITEM* worksheet = new KiGfx::WORKSHEET_VIEWITEM( std::string( aBoard->GetFileName().mb_str() ), std::string( GetScreenDesc().mb_str() ), &GetPageSettings(), &GetTitleBlock() ); @@ -897,7 +895,6 @@ void PCB_BASE_FRAME::LoadSettings() view->SetRequired( SOLDERPASTE_N_BACK, ITEM_GAL_LAYER( PAD_BK_VISIBLE ) ); view->SetRequired( SOLDERMASK_N_BACK, ITEM_GAL_LAYER( PAD_BK_VISIBLE ) ); - view->SetLayerTarget( ITEM_GAL_LAYER( SELECTION ), KiGfx::TARGET_OVERLAY ); view->SetLayerTarget( ITEM_GAL_LAYER( GP_OVERLAY ), KiGfx::TARGET_OVERLAY ); // Apply layer coloring scheme & display options diff --git a/pcbnew/class_dimension.cpp b/pcbnew/class_dimension.cpp index f7dacdc2a6..da5b9d9201 100644 --- a/pcbnew/class_dimension.cpp +++ b/pcbnew/class_dimension.cpp @@ -508,18 +508,6 @@ const BOX2I DIMENSION::ViewBBox() const } -void DIMENSION::ViewGetLayers( int aLayers[], int& aCount ) const -{ - // Layer that simply displays the text - aLayers[0] = m_Layer; - - // On the general purpose overlay there is a selection box displayed - aLayers[1] = ITEM_GAL_LAYER( SELECTION ); - - aCount = 2; -} - - EDA_ITEM* DIMENSION::Clone() const { return new DIMENSION( *this ); diff --git a/pcbnew/class_dimension.h b/pcbnew/class_dimension.h index 25baeca80f..efb5a28d3f 100644 --- a/pcbnew/class_dimension.h +++ b/pcbnew/class_dimension.h @@ -147,9 +147,6 @@ public: /// @copydoc VIEW_ITEM::ViewBBox() virtual const BOX2I ViewBBox() const; - /// @copydoc VIEW_ITEM::ViewGetLayers() - virtual void ViewGetLayers( int aLayers[], int& aCount ) const; - #if defined(DEBUG) virtual void Show( int nestLevel, std::ostream& os ) const { ShowDummy( os ); } // override #endif diff --git a/pcbnew/class_module.cpp b/pcbnew/class_module.cpp index 16ec8401d5..aef466c887 100644 --- a/pcbnew/class_module.cpp +++ b/pcbnew/class_module.cpp @@ -1024,10 +1024,3 @@ void MODULE::SetOrientation( double newangle ) CalculateBoundingBox(); } - -void MODULE::ViewGetLayers( int aLayers[], int& aCount ) const -{ - aCount = 2; - aLayers[0] = ITEM_GAL_LAYER( SELECTION ); // Selection box - aLayers[1] = m_Layer; -} diff --git a/pcbnew/class_module.h b/pcbnew/class_module.h index 1ea961ec37..ad83e94f8c 100644 --- a/pcbnew/class_module.h +++ b/pcbnew/class_module.h @@ -499,9 +499,6 @@ public: /// Return the initial comments block or NULL if none, without transfer of ownership. const wxArrayString* GetInitialComments() const { return m_initial_comments; } - /// @copydoc VIEW_ITEM::ViewGetLayers() - virtual void ViewGetLayers( int aLayers[], int& aCount ) const; - #if defined(DEBUG) virtual void Show( int nestLevel, std::ostream& os ) const { ShowDummy( os ); } // override #endif diff --git a/pcbnew/class_pcb_text.cpp b/pcbnew/class_pcb_text.cpp index 15920fa968..ac14a42e05 100644 --- a/pcbnew/class_pcb_text.cpp +++ b/pcbnew/class_pcb_text.cpp @@ -224,14 +224,3 @@ const BOX2I TEXTE_PCB::ViewBBox() const } } - -void TEXTE_PCB::ViewGetLayers( int aLayers[], int& aCount ) const -{ - // Layer that simply displays the text - aLayers[0] = m_Layer; - - // On the general purpose overlay there is a selection box displayed - aLayers[1] = ITEM_GAL_LAYER( SELECTION ); - - aCount = 2; -} diff --git a/pcbnew/class_pcb_text.h b/pcbnew/class_pcb_text.h index d8896d7ea9..e577489be9 100644 --- a/pcbnew/class_pcb_text.h +++ b/pcbnew/class_pcb_text.h @@ -134,9 +134,6 @@ public: /// @copydoc VIEW_ITEM::ViewBBox() virtual const BOX2I ViewBBox() const; - /// @copydoc VIEW_ITEM::ViewGetLayers() - virtual void ViewGetLayers( int aLayers[], int& aCount ) const; - #if defined(DEBUG) virtual void Show( int nestLevel, std::ostream& os ) const { ShowDummy( os ); } // override #endif diff --git a/pcbnew/class_text_mod.cpp b/pcbnew/class_text_mod.cpp index e4f28f31b1..31b6a4d595 100644 --- a/pcbnew/class_text_mod.cpp +++ b/pcbnew/class_text_mod.cpp @@ -472,8 +472,5 @@ void TEXTE_MODULE::ViewGetLayers( int aLayers[], int& aCount ) const break; } - // On the general purpose overlay there is a selection box displayed - aLayers[1] = ITEM_GAL_LAYER( SELECTION ); - - aCount = 2; + aCount = 1; } diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index a0c29c5602..2a304d77a4 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -76,7 +76,6 @@ void PCB_RENDER_SETTINGS::ImportLegacyColors( COLORS_DESIGN_SETTINGS* aSettings m_layerColors[ITEM_GAL_LAYER( PAD_FR_NETNAMES_VISIBLE )] = COLOR4D( 0.8, 0.8, 0.8, 0.7 ); m_layerColors[ITEM_GAL_LAYER( PAD_BK_NETNAMES_VISIBLE )] = COLOR4D( 0.8, 0.8, 0.8, 0.7 ); m_layerColors[ITEM_GAL_LAYER( WORKSHEET )] = COLOR4D( 0.5, 0.0, 0.0, 1.0 ); - m_layerColors[ITEM_GAL_LAYER( SELECTION )] = COLOR4D( 1.0, 1.0, 1.0, 0.5 ); // Netnames for copper layers for( LAYER_NUM layer = FIRST_COPPER_LAYER; layer <= LAST_COPPER_LAYER; ++layer ) @@ -227,10 +226,6 @@ bool PCB_PAINTER::Draw( const VIEW_ITEM* aItem, int aLayer ) draw( (DRAWSEGMENT*) aItem ); break; - case PCB_MODULE_T: - draw( (MODULE*) aItem, aLayer ); - break; - case PCB_TEXT_T: draw( (TEXTE_PCB*) aItem, aLayer ); break; @@ -593,8 +588,6 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer ) VECTOR2D deltaPadSize = size - padSize; // = solder[Paste/Mask]Margin or 0 VECTOR2D delta = VECTOR2D( aPad->GetDelta().x / 2, aPad->GetDelta().y / 2 ); - VECTOR2D inflate = VECTOR2D( delta.y * ( deltaPadSize.x / size.x ), - delta.x * ( deltaPadSize.y / size.y ) ); aPad->BuildPadPolygon( corners, wxSize( deltaPadSize.x, deltaPadSize.y ), 0.0 ); pointList.push_back( VECTOR2D( corners[0] ) ); @@ -699,63 +692,35 @@ void PCB_PAINTER::draw( const DRAWSEGMENT* aSegment ) } -void PCB_PAINTER::draw( const MODULE* aModule, int aLayer ) -{ - // For modules we have to draw a selection box if needed - if( aLayer == ITEM_GAL_LAYER( SELECTION ) ) - { - if( aModule->IsSelected() ) - drawSelectionBox( aModule ); - } -} - - void PCB_PAINTER::draw( const TEXTE_PCB* aText, int aLayer ) { - if( aLayer == ITEM_GAL_LAYER( SELECTION ) ) - { - if( aText->IsSelected() ) - drawSelectionBox( aText ); - } - else - { - if( aText->GetText().Length() == 0 ) - return; + if( aText->GetText().Length() == 0 ) + return; - COLOR4D strokeColor = m_pcbSettings->GetColor( aText, aText->GetLayer() ); - VECTOR2D position( aText->GetTextPosition().x, aText->GetTextPosition().y ); - double orientation = aText->GetOrientation() * M_PI / 1800.0; + COLOR4D strokeColor = m_pcbSettings->GetColor( aText, aText->GetLayer() ); + VECTOR2D position( aText->GetTextPosition().x, aText->GetTextPosition().y ); + double orientation = aText->GetOrientation() * M_PI / 1800.0; - m_gal->SetStrokeColor( strokeColor ); - m_gal->SetLineWidth( aText->GetThickness() ); - m_gal->SetTextAttributes( aText ); - m_gal->StrokeText( std::string( aText->GetText().mb_str() ), position, orientation ); - } + m_gal->SetStrokeColor( strokeColor ); + m_gal->SetLineWidth( aText->GetThickness() ); + m_gal->SetTextAttributes( aText ); + m_gal->StrokeText( std::string( aText->GetText().mb_str() ), position, orientation ); } void PCB_PAINTER::draw( const TEXTE_MODULE* aText, int aLayer ) { - if( aLayer == ITEM_GAL_LAYER( SELECTION ) ) - { - if( aText->IsSelected() ) - drawSelectionBox( aText ); - } - else - { - if( aText->GetLength() == 0 ) - return; + if( aText->GetLength() == 0 ) + return; - COLOR4D strokeColor = m_pcbSettings->GetColor( aText, aLayer ); - VECTOR2D position( aText->GetTextPosition().x, aText->GetTextPosition().y ); - double orientation = aText->GetDrawRotation() * M_PI / 1800.0; - - m_gal->SetStrokeColor( strokeColor ); - m_gal->SetLineWidth( aText->GetThickness() ); - m_gal->SetTextAttributes( aText ); - m_gal->StrokeText( std::string( aText->GetText().mb_str() ), position, orientation ); - } + COLOR4D strokeColor = m_pcbSettings->GetColor( aText, aLayer ); + VECTOR2D position( aText->GetTextPosition().x, aText->GetTextPosition().y ); + double orientation = aText->GetDrawRotation() * M_PI / 1800.0; + m_gal->SetStrokeColor( strokeColor ); + m_gal->SetLineWidth( aText->GetThickness() ); + m_gal->SetTextAttributes( aText ); + m_gal->StrokeText( std::string( aText->GetText().mb_str() ), position, orientation ); } @@ -830,41 +795,32 @@ void PCB_PAINTER::draw( const ZONE_CONTAINER* aZone ) void PCB_PAINTER::draw( const DIMENSION* aDimension, int aLayer ) { - if( aLayer == ITEM_GAL_LAYER( SELECTION ) ) - { - if( aDimension->IsSelected() ) - drawSelectionBox( aDimension ); - } - else - { - int layer = aDimension->GetLayer(); - COLOR4D strokeColor = m_pcbSettings->GetColor( aDimension, layer ); + COLOR4D strokeColor = m_pcbSettings->GetColor( aDimension, aLayer ); - m_gal->SetStrokeColor( strokeColor ); - m_gal->SetIsFill( false ); - m_gal->SetIsStroke( true ); - m_gal->SetLineWidth( aDimension->GetWidth() ); + m_gal->SetStrokeColor( strokeColor ); + m_gal->SetIsFill( false ); + m_gal->SetIsStroke( true ); + m_gal->SetLineWidth( aDimension->GetWidth() ); - // Draw an arrow - m_gal->DrawLine( VECTOR2D( aDimension->m_crossBarO ), VECTOR2D( aDimension->m_crossBarF ) ); - m_gal->DrawLine( VECTOR2D( aDimension->m_featureLineGO ), - VECTOR2D( aDimension->m_featureLineGF ) ); - m_gal->DrawLine( VECTOR2D( aDimension->m_featureLineDO ), - VECTOR2D( aDimension->m_featureLineDF ) ); - m_gal->DrawLine( VECTOR2D( aDimension->m_arrowD1O ), VECTOR2D( aDimension->m_arrowD1F ) ); - m_gal->DrawLine( VECTOR2D( aDimension->m_arrowD2O ), VECTOR2D( aDimension->m_arrowD2F ) ); - m_gal->DrawLine( VECTOR2D( aDimension->m_arrowG1O ), VECTOR2D( aDimension->m_arrowG1F ) ); - m_gal->DrawLine( VECTOR2D( aDimension->m_arrowG2O ), VECTOR2D( aDimension->m_arrowG2F ) ); + // Draw an arrow + m_gal->DrawLine( VECTOR2D( aDimension->m_crossBarO ), VECTOR2D( aDimension->m_crossBarF ) ); + m_gal->DrawLine( VECTOR2D( aDimension->m_featureLineGO ), + VECTOR2D( aDimension->m_featureLineGF ) ); + m_gal->DrawLine( VECTOR2D( aDimension->m_featureLineDO ), + VECTOR2D( aDimension->m_featureLineDF ) ); + m_gal->DrawLine( VECTOR2D( aDimension->m_arrowD1O ), VECTOR2D( aDimension->m_arrowD1F ) ); + m_gal->DrawLine( VECTOR2D( aDimension->m_arrowD2O ), VECTOR2D( aDimension->m_arrowD2F ) ); + m_gal->DrawLine( VECTOR2D( aDimension->m_arrowG1O ), VECTOR2D( aDimension->m_arrowG1F ) ); + m_gal->DrawLine( VECTOR2D( aDimension->m_arrowG2O ), VECTOR2D( aDimension->m_arrowG2F ) ); - // Draw text - TEXTE_PCB& text = aDimension->Text(); - VECTOR2D position( text.GetTextPosition().x, text.GetTextPosition().y ); - double orientation = text.GetOrientation() * M_PI / 1800.0; + // Draw text + TEXTE_PCB& text = aDimension->Text(); + VECTOR2D position( text.GetTextPosition().x, text.GetTextPosition().y ); + double orientation = text.GetOrientation() * M_PI / 1800.0; - m_gal->SetLineWidth( text.GetThickness() ); - m_gal->SetTextAttributes( &text ); - m_gal->StrokeText( std::string( text.GetText().mb_str() ), position, orientation ); - } + m_gal->SetLineWidth( text.GetThickness() ); + m_gal->SetTextAttributes( &text ); + m_gal->StrokeText( std::string( text.GetText().mb_str() ), position, orientation ); } @@ -904,14 +860,4 @@ void PCB_PAINTER::draw( const PCB_TARGET* aTarget ) } -void PCB_PAINTER::drawSelectionBox( const VIEW_ITEM* aItem ) const -{ - BOX2I boundingBox = aItem->ViewBBox(); - - m_gal->SetIsStroke( false ); - m_gal->SetIsFill( true ); - m_gal->SetFillColor( m_pcbSettings->GetLayerColor( ITEM_GAL_LAYER( SELECTION ) ) ); - m_gal->DrawRectangle( boundingBox.GetOrigin(), boundingBox.GetEnd() ); -} - const double PCB_RENDER_SETTINGS::MAX_FONT_SIZE = 100000000; diff --git a/pcbnew/pcb_painter.h b/pcbnew/pcb_painter.h index 4532fc49b6..7f9844ee41 100644 --- a/pcbnew/pcb_painter.h +++ b/pcbnew/pcb_painter.h @@ -146,15 +146,11 @@ protected: void draw( const SEGVIA*, int ); void draw( const D_PAD*, int ); void draw( const DRAWSEGMENT* ); - void draw( const MODULE*, int ); void draw( const TEXTE_PCB*, int ); void draw( const TEXTE_MODULE*, int ); void draw( const ZONE_CONTAINER* ); void draw( const DIMENSION*, int ); void draw( const PCB_TARGET* ); - - /// Draws a white semitransparent box indicating an item as selected - void drawSelectionBox( const VIEW_ITEM* aItem ) const; }; } // namespace KiGfx diff --git a/pcbnew/pcbframe.cpp b/pcbnew/pcbframe.cpp index 082ffb7bed..a5b7b933ee 100644 --- a/pcbnew/pcbframe.cpp +++ b/pcbnew/pcbframe.cpp @@ -790,7 +790,8 @@ void PCB_EDIT_FRAME::setHighContrastLayer( LAYER_NUM aLayer ) LAYER_NUM layers[] = { GetNetnameLayer( aLayer ), ITEM_GAL_LAYER( VIAS_VISIBLE ), ITEM_GAL_LAYER( VIAS_HOLES_VISIBLE ), ITEM_GAL_LAYER( PADS_VISIBLE ), - ITEM_GAL_LAYER( PADS_HOLES_VISIBLE ), ITEM_GAL_LAYER( PADS_NETNAMES_VISIBLE ) + ITEM_GAL_LAYER( PADS_HOLES_VISIBLE ), ITEM_GAL_LAYER( PADS_NETNAMES_VISIBLE ), + ITEM_GAL_LAYER( GP_OVERLAY ) }; for( unsigned int i = 0; i < sizeof( layers ) / sizeof( LAYER_NUM ); ++i ) @@ -830,7 +831,7 @@ void PCB_EDIT_FRAME::setTopLayer( LAYER_NUM aLayer ) GetNetnameLayer( aLayer ), ITEM_GAL_LAYER( VIAS_VISIBLE ), ITEM_GAL_LAYER( VIAS_HOLES_VISIBLE ), ITEM_GAL_LAYER( PADS_VISIBLE ), ITEM_GAL_LAYER( PADS_HOLES_VISIBLE ), ITEM_GAL_LAYER( PADS_NETNAMES_VISIBLE ), - ITEM_GAL_LAYER( SELECTION ) + ITEM_GAL_LAYER( GP_OVERLAY ) }; for( unsigned int i = 0; i < sizeof( layers ) / sizeof( LAYER_NUM ); ++i ) diff --git a/pcbnew/tools/bright_box.h b/pcbnew/tools/bright_box.h index e1748dbd28..e07a4b37e1 100644 --- a/pcbnew/tools/bright_box.h +++ b/pcbnew/tools/bright_box.h @@ -52,7 +52,7 @@ public: } private: - static const int BrightBoxLayer = ITEM_GAL_LAYER( SELECTION ); + static const int BrightBoxLayer = ITEM_GAL_LAYER( GP_OVERLAY ); static const KiGfx::COLOR4D BrightColor; static const double LineWidth = 100000.0; diff --git a/pcbnew/tools/move_tool.cpp b/pcbnew/tools/move_tool.cpp index 3e2170a051..6642984ca1 100644 --- a/pcbnew/tools/move_tool.cpp +++ b/pcbnew/tools/move_tool.cpp @@ -78,15 +78,15 @@ bool MOVE_TOOL::Init() 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; bool dragging = false; 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 ); - controls->ShowCursor( true ); controls->SetSnapping( true ); controls->SetAutoPan( true ); @@ -108,12 +108,12 @@ int MOVE_TOOL::Main( TOOL_EVENT& aEvent ) if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) // got rotation event? { 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? { m_state.Flip( cursorPos ); - m_items.ViewUpdate( VIEW_ITEM::GEOMETRY ); + selection.group->ViewUpdate( VIEW_ITEM::GEOMETRY ); } } @@ -128,98 +128,39 @@ int MOVE_TOOL::Main( TOOL_EVENT& aEvent ) else { // Prepare to drag - m_selection = m_selectionTool->GetSelection(); - if( m_selection.empty() ) - break; // there are no items to operate on - std::set::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 m_state.Save( *it ); - - // Gather all selected items into one VIEW_GROUP - viewGroupAdd( *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; } - m_items.ViewUpdate( VIEW_ITEM::GEOMETRY ); + selection.group->ViewUpdate( VIEW_ITEM::GEOMETRY ); dragPosition = evt->Position(); } else if( evt->IsMouseUp( MB_Left ) || evt->IsClick( MB_Left ) ) break; // Finish } - // Restore visibility of the original items - vgSetVisibility( &m_items, true ); - if( restore ) { // Modifications has to be rollbacked, so restore the previous state of items - vgUpdate( &m_items, VIEW_ITEM::APPEARANCE ); + selection.group->ItemsViewUpdate( VIEW_ITEM::APPEARANCE ); m_state.RestoreAll(); } else { // Changes are applied, so update the items - vgUpdate( &m_items, m_state.GetUpdateFlag() ); + selection.group->ItemsViewUpdate( m_state.GetUpdateFlag() ); m_state.Apply(); } - m_items.Clear(); - view->Remove( &m_items ); - controls->ShowCursor( false ); controls->SetSnapping( false ); controls->SetAutoPan( false ); return 0; } - - -void MOVE_TOOL::viewGroupAdd( 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( aItem ); - - // Add everything that belongs to the module (besides the module itself) - for( D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() ) - viewGroupAdd( pad, &m_items ); - - for( BOARD_ITEM* drawing = module->GraphicalItems().GetFirst(); drawing; - drawing = drawing->Next() ) - viewGroupAdd( drawing, &m_items ); - - viewGroupAdd( &module->Reference(), &m_items ); - viewGroupAdd( &module->Value(), &m_items ); - } - - // 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::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::const_iterator it, it_end; - for( it = aGroup->Begin(), it_end = aGroup->End(); it != it_end; ++it ) - (*it)->ViewUpdate( aFlags ); -} diff --git a/pcbnew/tools/move_tool.h b/pcbnew/tools/move_tool.h index 0074ba70b4..665663853d 100644 --- a/pcbnew/tools/move_tool.h +++ b/pcbnew/tools/move_tool.h @@ -65,26 +65,11 @@ public: int Main( TOOL_EVENT& aEvent ); private: - /// Adds an item to the VIEW_GROUP that holds all moved items and displays them on the overlay - void viewGroupAdd( 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 ITEM_STATE m_state; /// Selection tool used for obtaining selected items SELECTION_TOOL* m_selectionTool; - - /// Set of selected items (obtained from pcbnew.InteractiveSelection tool) - std::set m_selection; - - /// VIEW_GROUP that helds currently moved items - KiGfx::VIEW_GROUP m_items; }; #endif diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp index b6299e8208..e03a9e9a2f 100644 --- a/pcbnew/tools/selection_tool.cpp +++ b/pcbnew/tools/selection_tool.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -53,19 +54,25 @@ SELECTION_TOOL::SELECTION_TOOL() : TOOL_INTERACTIVE( "pcbnew.InteractiveSelection" ), m_multiple( false ) { m_selArea = new SELECTION_AREA; + m_selection.group = new KiGfx::VIEW_GROUP; } SELECTION_TOOL::~SELECTION_TOOL() { - if( m_selArea ) - delete m_selArea; + delete m_selArea; + delete m_selection.group; } void SELECTION_TOOL::Reset() { - m_selectedItems.clear(); + m_selection.group->Clear(); + m_selection.items.clear(); + + // Reinsert the VIEW_GROUP, in case it was removed from the VIEW + getView()->Remove( m_selection.group ); + getView()->Add( m_selection.group ); // The tool launches upon reception of action event ("pcbnew.InteractiveSelection") Go( &SELECTION_TOOL::Main, COMMON_ACTIONS::selectionActivate.MakeEvent() ); @@ -75,8 +82,11 @@ void SELECTION_TOOL::Reset() int SELECTION_TOOL::Main( TOOL_EVENT& aEvent ) { BOARD* board = getModel( PCB_T ); + VIEW* view = getView(); assert( board != NULL ); + view->Add( m_selection.group ); + // Main loop: keep receiving events while( OPT_TOOL_EVENT evt = Wait() ) { @@ -86,7 +96,7 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent ) if( evt->IsCancel() ) { - if( !m_selectedItems.empty() ) // Cancel event deselects items... + if( !m_selection.Empty() ) // Cancel event deselects items... clearSelection(); else // ...unless there is nothing selected break; // then exit the tool @@ -99,7 +109,7 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent ) // drag with LMB? Select multiple objects (or at least draw a selection box) or drag them 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 // draw the selection box @@ -112,7 +122,6 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent ) { // Yes -> run the move tool and wait till it finishes m_toolMgr->InvokeTool( "pcbnew.InteractiveMove" ); - Wait(); } else { @@ -123,6 +132,9 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent ) } } + m_selection.group->Clear(); + view->Remove( m_selection.group ); + return 0; } @@ -137,9 +149,13 @@ void SELECTION_TOOL::AddMenuItem( const TOOL_ACTION& aAction ) 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 ); + + // If there is nothing selected, disable the context menu + if( m_selection.Empty() ) + SetContextMenu( &m_menu, CMENU_OFF ); } else { @@ -148,19 +164,29 @@ void SELECTION_TOOL::toggleSelection( BOARD_ITEM* aItem ) // Prevent selection of invisible or inactive items if( selectable( aItem ) ) + { selectItem( aItem ); + + // Now the context menu should be enabled + SetContextMenu( &m_menu, CMENU_BUTTON ); + } } } 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( *it ); + + item->ViewSetVisible( true ); item->ClearSelected(); } - m_selectedItems.clear(); + m_selection.group->Clear(); + m_selection.items.clear(); // Do not show the context menu when there is nothing selected SetContextMenu( &m_menu, CMENU_OFF ); @@ -258,9 +284,6 @@ bool SELECTION_TOOL::selectMultiple() VIEW* view = getView(); 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 ); while( OPT_TOOL_EVENT evt = Wait() ) @@ -300,14 +323,11 @@ bool SELECTION_TOOL::selectMultiple() // Add only those items that are visible and fully within the selection box if( selectable( item ) && selectionBox.Contains( item->ViewBBox() ) ) - { - item->SetSelected(); - m_selectedItems.insert( item ); - } + selectItem( item ); } // Now the context menu should be enabled - if( !m_selectedItems.empty() ) + if( !m_selection.Empty() ) SetContextMenu( &m_menu, CMENU_BUTTON ); break; @@ -377,6 +397,7 @@ BOARD_ITEM* SELECTION_TOOL::disambiguationMenu( GENERAL_COLLECTOR* aCollector ) } } + // Removes possible brighten mark getView()->MarkTargetDirty( TARGET_OVERLAY ); // Restore the original menu @@ -450,10 +471,12 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const return false; break; + // These are not selectable, otherwise silkscreen drawings would be easily destroyed case PCB_MODULE_EDGE_T: - // These are not selectable, otherwise silkscreen drawings would be easily destroyed + // and some other stuff that should be selected + case NOT_USED: + case TYPE_NOT_INIT: return false; - break; default: // Suppress warnings break; @@ -464,13 +487,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( 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( 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 { const unsigned GRIP_MARGIN = 500000; // Check if the point is located within any of the currently selected items bounding boxes std::set::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(); itemBox.Inflate( GRIP_MARGIN ); // Give some margin for gripping an item diff --git a/pcbnew/tools/selection_tool.h b/pcbnew/tools/selection_tool.h index 8dc8982bd6..8960779a4a 100644 --- a/pcbnew/tools/selection_tool.h +++ b/pcbnew/tools/selection_tool.h @@ -36,6 +36,11 @@ class SELECTION_AREA; class BOARD_ITEM; class GENERAL_COLLECTOR; +namespace KiGfx +{ +class VIEW_GROUP; +} + /** * Class SELECTION_TOOL * @@ -54,6 +59,18 @@ public: SELECTION_TOOL(); ~SELECTION_TOOL(); + struct SELECTION + { + /// Set of selected items + std::set 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() void Reset(); @@ -69,9 +86,9 @@ public: * * Returns the set of currently selected items. */ - const std::set& GetSelection() const + const SELECTION& GetSelection() const { - return m_selectedItems; + return m_selection; } /** @@ -145,14 +162,7 @@ private: * * @param aItem is an item to be selected. */ - void selectItem( BOARD_ITEM* aItem ) - { - aItem->SetSelected(); - m_selectedItems.insert( aItem ); - - // Now the context menu should be enabled - SetContextMenu( &m_menu, CMENU_BUTTON ); - } + void selectItem( BOARD_ITEM* aItem ); /** * Function deselectItem() @@ -160,15 +170,7 @@ private: * * @param aItem is an item to be deselected. */ - 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 ); - } + void deselectItem( BOARD_ITEM* aItem ); /** * Function containsSelected() @@ -178,12 +180,12 @@ private: */ bool containsSelected( const VECTOR2I& aPoint ) const; - /// Container storing currently selected items - std::set m_selectedItems; - /// Visual representation of selection box 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 bool m_additive;