diff --git a/common/view/view.cpp b/common/view/view.cpp index b6611153cd..6018e7b743 100644 --- a/common/view/view.cpp +++ b/common/view/view.cpp @@ -89,6 +89,7 @@ private: VIEW* m_view; ///< Current dynamic view the item is assigned to. int m_flags; ///< Visibility flags int m_requiredUpdate; ///< Flag required for updating + int m_drawPriority; ///< Order to draw this item in a layer, lowest first ///> Helper for storing cached items group ids typedef std::pair GroupPair; @@ -260,7 +261,9 @@ VIEW::VIEW( bool aIsDynamic ) : m_mirrorX( false ), m_mirrorY( false ), m_painter( NULL ), m_gal( NULL ), - m_dynamic( aIsDynamic ) + m_dynamic( aIsDynamic ), + m_useDrawPriority( false ), + m_nextDrawPriority( 0 ) { m_boundary.SetMaximum(); m_allItems.reserve( 32768 ); @@ -301,12 +304,16 @@ void VIEW::AddLayer( int aLayer, bool aDisplayOnly ) } -void VIEW::Add( VIEW_ITEM* aItem ) +void VIEW::Add( VIEW_ITEM* aItem, int aDrawPriority ) { int layers[VIEW_MAX_LAYERS], layers_count; + if( aDrawPriority < 0 ) + aDrawPriority = m_nextDrawPriority++; + aItem->m_viewPrivData = new VIEW_ITEM_DATA; aItem->m_viewPrivData->m_view = this; + aItem->m_viewPrivData->m_drawPriority = aDrawPriority; aItem->ViewGetLayers( layers, layers_count ); aItem->viewPrivData()->saveLayers( layers, layers_count ); @@ -812,8 +819,8 @@ void VIEW::UpdateAllLayersOrder() struct VIEW::drawItem { - drawItem( VIEW* aView, int aLayer ) : - view( aView ), layer( aLayer ) + drawItem( VIEW* aView, int aLayer, bool aUseDrawPriority ) : + view( aView ), layer( aLayer ), useDrawPriority( aUseDrawPriority ) { } @@ -827,13 +834,29 @@ struct VIEW::drawItem if( !drawCondition ) return true; - view->draw( aItem, layer ); + if( useDrawPriority ) + drawItems.push_back( aItem ); + else + view->draw( aItem, layer ); return true; } + void deferredDraw() + { + std::sort( drawItems.begin(), drawItems.end(), + []( VIEW_ITEM* a, VIEW_ITEM* b ) -> bool { + return b->viewPrivData()->m_drawPriority < a->viewPrivData()->m_drawPriority; + }); + + for( auto item : drawItems ) + view->draw( item, layer ); + } + VIEW* view; int layer, layers[VIEW_MAX_LAYERS]; + bool useDrawPriority; + std::vector drawItems; }; @@ -843,11 +866,14 @@ void VIEW::redrawRect( const BOX2I& aRect ) { if( l->visible && IsTargetDirty( l->target ) && areRequiredLayersEnabled( l->id ) ) { - drawItem drawFunc( this, l->id ); + drawItem drawFunc( this, l->id, m_useDrawPriority ); m_gal->SetTarget( l->target ); m_gal->SetLayerDepth( l->renderingOrder ); l->items->Query( aRect, drawFunc ); + + if( m_useDrawPriority ) + drawFunc.deferredDraw(); } } } @@ -955,6 +981,8 @@ void VIEW::Clear() for( LAYER_MAP_ITER i = m_layers.begin(); i != m_layers.end(); ++i ) i->second.items->RemoveAll(); + m_nextDrawPriority = 0; + m_gal->ClearCache(); } diff --git a/include/view/view.h b/include/view/view.h index 6de865a7a8..108b2df434 100644 --- a/include/view/view.h +++ b/include/view/view.h @@ -79,9 +79,11 @@ public: /** * Function Add() * Adds a VIEW_ITEM to the view. + * Set aDrawPriority to -1 to assign sequential priorities. * @param aItem: item to be added. No ownership is given + * @param aDrawPriority: priority to draw this item on its layer, lowest first. */ - void Add( VIEW_ITEM* aItem ); + void Add( VIEW_ITEM* aItem, int aDrawPriority = -1 ); /** * Function Remove() @@ -617,6 +619,24 @@ public: const BOX2I CalculateExtents() ; + /** + * Function IsUsingDrawPriority() + * @return true if draw priority is being respected while redrawing. + */ + bool IsUsingDrawPriority() const + { + return m_useDrawPriority; + } + + /** + * Function UseDrawPriority() + * @param aFlag is true if draw priority should be respected while redrawing. + */ + void UseDrawPriority( bool aFlag ) + { + m_useDrawPriority = aFlag; + } + static const int VIEW_MAX_LAYERS = 256; ///< maximum number of layers that may be shown private: @@ -776,6 +796,12 @@ private: /// Flat list of all items std::vector m_allItems; + + /// Flag to respect draw priority when drawing items + bool m_useDrawPriority; + + /// The next sequential drawing priority + int m_nextDrawPriority; }; } // namespace KIGFX diff --git a/pcbnew/board_commit.cpp b/pcbnew/board_commit.cpp index e245782269..bad4616646 100644 --- a/pcbnew/board_commit.cpp +++ b/pcbnew/board_commit.cpp @@ -117,7 +117,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage ) if( boardItem->Type() == PCB_MODULE_T ) { MODULE* mod = static_cast( boardItem ); - mod->RunOnChildren( std::bind( &KIGFX::VIEW::Add, view, _1 ) ); + mod->RunOnChildren( std::bind( &KIGFX::VIEW::Add, view, _1, -1 ) ); } } else @@ -327,7 +327,7 @@ void BOARD_COMMIT::Revert() { MODULE* newModule = static_cast( item ); newModule->RunOnChildren( std::bind( &EDA_ITEM::ClearFlags, _1, SELECTED ) ); - newModule->RunOnChildren( std::bind( &KIGFX::VIEW::Add, view, _1 ) ); + newModule->RunOnChildren( std::bind( &KIGFX::VIEW::Add, view, _1, -1 ) ); } view->Add( item ); @@ -355,7 +355,7 @@ void BOARD_COMMIT::Revert() { MODULE* newModule = static_cast( item ); newModule->RunOnChildren( std::bind( &EDA_ITEM::ClearFlags, _1, SELECTED ) ); - newModule->RunOnChildren( std::bind( &KIGFX::VIEW::Add, view, _1 ) ); + newModule->RunOnChildren( std::bind( &KIGFX::VIEW::Add, view, _1, -1 ) ); } view->Add( item ); diff --git a/pcbnew/footprint_preview_panel.cpp b/pcbnew/footprint_preview_panel.cpp index 17873a5f00..1502a9c938 100644 --- a/pcbnew/footprint_preview_panel.cpp +++ b/pcbnew/footprint_preview_panel.cpp @@ -202,7 +202,7 @@ void FOOTPRINT_PREVIEW_PANEL::renderFootprint( MODULE *module ) Freeze(); GetView()->Clear(); module->SetParent ( &*m_dummyBoard ); - module->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, GetView(), _1 ) ); + module->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, GetView(), _1, -1 ) ); GetView()->Add ( module ); diff --git a/pcbnew/netlist.cpp b/pcbnew/netlist.cpp index 5ceb8cfe20..a2decdc50b 100644 --- a/pcbnew/netlist.cpp +++ b/pcbnew/netlist.cpp @@ -158,7 +158,7 @@ void PCB_EDIT_FRAME::ReadPcbNetlist( const wxString& aNetlistFileName, // Reload modules for( MODULE* module = board->m_Modules; module; module = module->Next() ) { - module->RunOnChildren( std::bind( &KIGFX::VIEW::Add, view, _1 ) ); + module->RunOnChildren( std::bind( &KIGFX::VIEW::Add, view, _1, -1 ) ); view->Add( module ); } diff --git a/pcbnew/pcb_draw_panel_gal.cpp b/pcbnew/pcb_draw_panel_gal.cpp index efa3dd926d..3742f137ca 100644 --- a/pcbnew/pcb_draw_panel_gal.cpp +++ b/pcbnew/pcb_draw_panel_gal.cpp @@ -150,7 +150,7 @@ void PCB_DRAW_PANEL_GAL::DisplayBoard( const BOARD* aBoard ) // Load modules and its additional elements for( MODULE* module = aBoard->m_Modules; module; module = module->Next() ) { - module->RunOnChildren( std::bind( &KIGFX::VIEW::Add, m_view, _1 ) ); + module->RunOnChildren( std::bind( &KIGFX::VIEW::Add, m_view, _1, -1 ) ); m_view->Add( module ); } diff --git a/pcbnew/undo_redo.cpp b/pcbnew/undo_redo.cpp index f0ee448bc6..bb4b4a65b6 100644 --- a/pcbnew/undo_redo.cpp +++ b/pcbnew/undo_redo.cpp @@ -477,7 +477,7 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool if( item->Type() == PCB_MODULE_T ) { MODULE* newModule = static_cast( item ); - newModule->RunOnChildren( std::bind( &KIGFX::VIEW::Add, view, _1 ) ); + newModule->RunOnChildren( std::bind( &KIGFX::VIEW::Add, view, _1, -1 ) ); newModule->RunOnChildren( std::bind( &BOARD_ITEM::ClearFlags, _1, EDA_ITEM_ALL_FLAGS )); } @@ -508,7 +508,7 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool if( item->Type() == PCB_MODULE_T ) { MODULE* module = static_cast( item ); - module->RunOnChildren( std::bind( &KIGFX::VIEW::Add, view, _1) ); + module->RunOnChildren( std::bind( &KIGFX::VIEW::Add, view, _1, -1 ) ); } view->Add( item );