From 5ac699776deecf118bc6bd065a630129c6880700 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 21 Feb 2014 16:57:18 +0100 Subject: [PATCH] Revisiting GAL: - VIEW_ITEM::ViewUpdate() does not update items immediately. Now it marks them to be updated and the real update occurs on the next rendering frame. - VIEW::InvalidateItem() made private. - VIEW_LAYER::enabled -> visible - Some functions moved to header files. --- common/drawpanel_gal.cpp | 20 ++++-- common/view/view.cpp | 136 ++++++++++++++++---------------------- common/view/view_item.cpp | 21 ++---- include/view/view.h | 106 ++++++++++++++++++----------- include/view/view_item.h | 42 ++++++++++-- pcbnew/class_module.cpp | 14 ++-- 6 files changed, 187 insertions(+), 152 deletions(-) diff --git a/common/drawpanel_gal.cpp b/common/drawpanel_gal.cpp index 2a03dcc571..6a7e4f9d6a 100644 --- a/common/drawpanel_gal.cpp +++ b/common/drawpanel_gal.cpp @@ -124,17 +124,22 @@ void EDA_DRAW_PANEL_GAL::onPaint( wxPaintEvent& WXUNUSED( aEvent ) ) { m_drawing = true; + m_view->UpdateItems(); m_gal->BeginDrawing(); - m_gal->SetBackgroundColor( KIGFX::COLOR4D( 0.0, 0.0, 0.0, 1.0 ) ); m_gal->ClearScreen(); - m_view->ClearTargets(); - // Grid has to be redrawn only when the NONCACHED target is redrawn - if( m_view->IsTargetDirty( KIGFX::TARGET_NONCACHED ) ) - m_gal->DrawGrid(); - m_view->Redraw(); - m_gal->DrawCursor( m_viewControls->GetCursorPosition() ); + if( m_view->IsDirty() ) + { + m_view->ClearTargets(); + // Grid has to be redrawn only when the NONCACHED target is redrawn + if( m_view->IsTargetDirty( KIGFX::TARGET_NONCACHED ) ) + m_gal->DrawGrid(); + + m_view->Redraw(); + } + + m_gal->DrawCursor( m_viewControls->GetCursorPosition() ); m_gal->EndDrawing(); m_drawing = false; @@ -215,6 +220,7 @@ void EDA_DRAW_PANEL_GAL::SwitchBackend( GalType aGalType ) wxSize size = GetClientSize(); m_gal->ResizeScreen( size.GetX(), size.GetY() ); + m_gal->SetBackgroundColor( KIGFX::COLOR4D( 0.0, 0.0, 0.0, 1.0 ) ); if( m_painter ) m_painter->SetGAL( m_gal ); diff --git a/common/view/view.cpp b/common/view/view.cpp index e9c6324012..0a18d42711 100644 --- a/common/view/view.cpp +++ b/common/view/view.cpp @@ -49,28 +49,24 @@ VIEW::VIEW( bool aIsDynamic ) : m_scaleLimits( 15000.0, 1.0 ) { m_panBoundary.SetMaximum(); + m_needsUpdate.reserve( 32768 ); // Redraw everything at the beginning - for( int i = 0; i < TARGETS_NUMBER; ++i ) - MarkTargetDirty( i ); + MarkDirty(); // View uses layers to display EDA_ITEMs (item may be displayed on several layers, for example // pad may be shown on pad, pad hole and solder paste layers). There are usual copper layers // (eg. F.Cu, B.Cu, internal and so on) and layers for displaying objects such as texts, // silkscreen, pads, vias, etc. for( int i = 0; i < VIEW_MAX_LAYERS; i++ ) - { AddLayer( i ); - } } VIEW::~VIEW() { BOOST_FOREACH( LAYER_MAP::value_type& l, m_layers ) - { delete l.second.items; - } } @@ -82,7 +78,7 @@ void VIEW::AddLayer( int aLayer, bool aDisplayOnly ) m_layers[aLayer].id = aLayer; m_layers[aLayer].items = new VIEW_RTREE(); m_layers[aLayer].renderingOrder = aLayer; - m_layers[aLayer].enabled = true; + m_layers[aLayer].visible = true; m_layers[aLayer].displayOnly = aDisplayOnly; m_layers[aLayer].target = TARGET_CACHED; } @@ -172,12 +168,12 @@ struct queryVisitor }; -int VIEW::Query( const BOX2I& aRect, std::vector& aResult ) +int VIEW::Query( const BOX2I& aRect, std::vector& aResult ) const { if( m_orderedLayers.empty() ) return 0; - std::vector::reverse_iterator i; + std::vector::const_reverse_iterator i; // execute queries in reverse direction, so that items that are on the top of // the rendering stack are returned first. @@ -257,12 +253,6 @@ void VIEW::SetGAL( GAL* aGal ) } -void VIEW::SetPainter( PAINTER* aPainter ) -{ - m_painter = aPainter; -} - - BOX2D VIEW::GetViewport() const { BOX2D rect; @@ -293,12 +283,6 @@ void VIEW::SetMirror( bool aMirrorX, bool aMirrorY ) } -void VIEW::SetScale( double aScale ) -{ - SetScale( aScale, m_center ); -} - - void VIEW::SetScale( double aScale, const VECTOR2D& aAnchor ) { if( aScale > m_scaleLimits.x ) @@ -578,8 +562,8 @@ void VIEW::UpdateAllLayersOrder() struct VIEW::drawItem { - drawItem( VIEW* aView, const VIEW_LAYER* aCurrentLayer ) : - currentLayer( aCurrentLayer ), view( aView ) + drawItem( VIEW* aView, int aLayer ) : + view( aView ), layer( aLayer ) { } @@ -587,18 +571,17 @@ struct VIEW::drawItem { // Conditions that have te be fulfilled for an item to be drawn bool drawCondition = aItem->ViewIsVisible() && - aItem->ViewGetLOD( currentLayer->id ) < view->m_scale; + aItem->ViewGetLOD( layer ) < view->m_scale; if( !drawCondition ) return true; - view->draw( aItem, currentLayer->id ); + view->draw( aItem, layer ); return true; } - const VIEW_LAYER* currentLayer; VIEW* view; - int layersCount, layers[VIEW_MAX_LAYERS]; + int layer, layersCount, layers[VIEW_MAX_LAYERS]; }; @@ -606,9 +589,9 @@ void VIEW::redrawRect( const BOX2I& aRect ) { BOOST_FOREACH( VIEW_LAYER* l, m_orderedLayers ) { - if( l->enabled && IsTargetDirty( l->target ) && areRequiredLayersEnabled( l->id ) ) + if( l->visible && IsTargetDirty( l->target ) && areRequiredLayersEnabled( l->id ) ) { - drawItem drawFunc( this, l ); + drawItem drawFunc( this, l->id ); m_gal->SetTarget( l->target ); m_gal->SetLayerDepth( l->renderingOrder ); @@ -618,7 +601,7 @@ void VIEW::redrawRect( const BOX2I& aRect ) } -void VIEW::draw( VIEW_ITEM* aItem, int aLayer, bool aImmediate ) const +void VIEW::draw( VIEW_ITEM* aItem, int aLayer, bool aImmediate ) { if( IsCached( aLayer ) && !aImmediate ) { @@ -649,11 +632,12 @@ void VIEW::draw( VIEW_ITEM* aItem, int aLayer, bool aImmediate ) const } -void VIEW::draw( VIEW_ITEM* aItem, bool aImmediate ) const +void VIEW::draw( VIEW_ITEM* aItem, bool aImmediate ) { int layers[VIEW_MAX_LAYERS], layers_count; aItem->ViewGetLayers( layers, layers_count ); + // Sorting is needed for drawing order dependent GALs (like Cairo) SortLayers( layers, layers_count ); @@ -665,26 +649,12 @@ void VIEW::draw( VIEW_ITEM* aItem, bool aImmediate ) const } -void VIEW::draw( VIEW_GROUP* aGroup, bool aImmediate ) const +void VIEW::draw( VIEW_GROUP* aGroup, bool aImmediate ) { std::set::const_iterator it; for( it = aGroup->Begin(); it != aGroup->End(); ++it ) - { draw( *it, aImmediate ); - } -} - - -bool VIEW::IsDirty() const -{ - for( int i = 0; i < TARGETS_NUMBER; ++i ) - { - if( IsTargetDirty( i ) ) - return true; - } - - return false; } @@ -709,14 +679,14 @@ struct VIEW::recacheItem bool operator()( VIEW_ITEM* aItem ) { // Remove previously cached group - int prevGroup = aItem->getGroup( layer ); + int group = aItem->getGroup( layer ); - if( prevGroup >= 0 ) - gal->DeleteGroup( prevGroup ); + if( group >= 0 ) + gal->DeleteGroup( group ); if( immediately ) { - int group = gal->BeginGroup(); + group = gal->BeginGroup(); aItem->setGroup( layer, group ); if( !view->m_painter->Draw( aItem, layer ) ) @@ -791,13 +761,13 @@ void VIEW::Redraw() redrawRect( rect ); // All targets were redrawn, so nothing is dirty - clearTargetDirty( TARGET_CACHED ); - clearTargetDirty( TARGET_NONCACHED ); - clearTargetDirty( TARGET_OVERLAY ); + markTargetClean( TARGET_CACHED ); + markTargetClean( TARGET_NONCACHED ); + markTargetClean( TARGET_OVERLAY ); } -VECTOR2D VIEW::GetScreenPixelSize() const +const VECTOR2D& VIEW::GetScreenPixelSize() const { return m_gal->GetScreenPixelSize(); } @@ -839,7 +809,7 @@ void VIEW::clearGroupCache() } -void VIEW::InvalidateItem( VIEW_ITEM* aItem, int aUpdateFlags ) +void VIEW::invalidateItem( VIEW_ITEM* aItem, int aUpdateFlags ) { // updateLayers updates geometry too, so we do not have to update both of them at the same time if( aUpdateFlags & VIEW_ITEM::LAYERS ) @@ -851,24 +821,23 @@ void VIEW::InvalidateItem( VIEW_ITEM* aItem, int aUpdateFlags ) aItem->ViewGetLayers( layers, layers_count ); // Iterate through layers used by the item and recache it immediately - for( int i = 0; i < layers_count; i++ ) + for( int i = 0; i < layers_count; ++i ) { int layerId = layers[i]; - if( aUpdateFlags & ( VIEW_ITEM::GEOMETRY | VIEW_ITEM::LAYERS ) ) + if( IsCached( layerId ) ) { - // Redraw - if( IsCached( layerId ) ) + if( aUpdateFlags & ( VIEW_ITEM::GEOMETRY | VIEW_ITEM::LAYERS ) ) updateItemGeometry( aItem, layerId ); - } - else if( aUpdateFlags & VIEW_ITEM::COLOR ) - { - updateItemColor( aItem, layerId ); + else if( aUpdateFlags & VIEW_ITEM::COLOR ) + updateItemColor( aItem, layerId ); } // Mark those layers as dirty, so the VIEW will be refreshed MarkTargetDirty( m_layers[layerId].target ); } + + aItem->clearUpdateFlags(); } @@ -890,6 +859,7 @@ void VIEW::sortLayers() void VIEW::updateItemColor( VIEW_ITEM* aItem, int aLayer ) { wxASSERT( (unsigned) aLayer < m_layers.size() ); + wxASSERT( IsCached( aLayer ) ); // Obtain the color that should be used for coloring the item on the specific layerId const COLOR4D color = m_painter->GetSettings()->GetColor( aItem, aLayer ); @@ -904,18 +874,20 @@ void VIEW::updateItemColor( VIEW_ITEM* aItem, int aLayer ) void VIEW::updateItemGeometry( VIEW_ITEM* aItem, int aLayer ) { wxASSERT( (unsigned) aLayer < m_layers.size() ); + wxASSERT( IsCached( aLayer ) ); + VIEW_LAYER& l = m_layers.at( aLayer ); m_gal->SetTarget( l.target ); m_gal->SetLayerDepth( l.renderingOrder ); // Redraw the item from scratch - int prevGroup = aItem->getGroup( aLayer ); + int group = aItem->getGroup( aLayer ); - if( prevGroup >= 0 ) - m_gal->DeleteGroup( prevGroup ); + if( group >= 0 ) + m_gal->DeleteGroup( group ); - int group = m_gal->BeginGroup(); + group = m_gal->BeginGroup(); aItem->setGroup( aLayer, group ); m_painter->Draw( static_cast( aItem ), aLayer ); m_gal->EndGroup(); @@ -951,11 +923,17 @@ void VIEW::updateLayers( VIEW_ITEM* aItem ) l.items->Remove( aItem ); MarkTargetDirty( l.target ); - // Redraw the item from scratch - int prevGroup = aItem->getGroup( layers[i] ); + if( IsCached( l.id ) ) + { + // Redraw the item from scratch + int prevGroup = aItem->getGroup( layers[i] ); - if( prevGroup >= 0 ) - m_gal->DeleteGroup( prevGroup ); + if( prevGroup >= 0 ) + { + m_gal->DeleteGroup( prevGroup ); + aItem->setGroup( l.id, -1 ); + } + } } // Add the item to new layer set @@ -981,7 +959,7 @@ bool VIEW::areRequiredLayersEnabled( int aLayerId ) const it_end = m_layers.at( aLayerId ).requiredLayers.end(); it != it_end; ++it ) { // That is enough if just one layer is not enabled - if( !m_layers.at( *it ).enabled ) + if( !m_layers.at( *it ).visible ) return false; } @@ -1023,13 +1001,15 @@ void VIEW::RecacheAllItems( bool aImmediately ) } -bool VIEW::IsTargetDirty( int aTarget ) const +void VIEW::UpdateItems() { - wxASSERT( aTarget < TARGETS_NUMBER ); + // Update items that need this + BOOST_FOREACH( VIEW_ITEM* item, m_needsUpdate ) + { + assert( item->viewRequiredUpdate() != VIEW_ITEM::NONE ); - // Check the target status - if( m_dirtyTargets[aTarget] ) - return true; + invalidateItem( item, item->viewRequiredUpdate() ); + } - return false; + m_needsUpdate.clear(); } diff --git a/common/view/view_item.cpp b/common/view/view_item.cpp index 305ab68579..900e030e61 100644 --- a/common/view/view_item.cpp +++ b/common/view/view_item.cpp @@ -31,25 +31,12 @@ using namespace KIGFX; void VIEW_ITEM::ViewSetVisible( bool aIsVisible ) { - bool update = false; - - if( m_visible != aIsVisible ) - update = true; - - m_visible = aIsVisible; - // update only if the visibility has really changed - if( update ) + if( m_visible != aIsVisible ) + { + m_visible = aIsVisible; ViewUpdate( APPEARANCE ); -} - - -void VIEW_ITEM::ViewUpdate( int aUpdateFlags ) -{ - if( !m_view ) - return; - - m_view->InvalidateItem( this, aUpdateFlags ); + } } diff --git a/include/view/view.h b/include/view/view.h index f7a7e90984..4a7965bb94 100644 --- a/include/view/view.h +++ b/include/view/view.h @@ -94,7 +94,7 @@ public: * first). * @return Number of found items. */ - int Query( const BOX2I& aRect, std::vector& aResult ); + int Query( const BOX2I& aRect, std::vector& aResult ) const; /** * Function SetRequired() @@ -140,7 +140,10 @@ public: * Function SetPainter() * Sets the painter object used by the view for drawing VIEW_ITEMS. */ - void SetPainter( PAINTER* aPainter ); + void SetPainter( PAINTER* aPainter ) + { + m_painter = aPainter; + } /** * Function GetPainter() @@ -181,7 +184,10 @@ public: * (depending on correct GAL unit length & DPI settings). * @param aScale: the scalefactor */ - void SetScale( double aScale ); + void SetScale( double aScale ) + { + SetScale( aScale, m_center ); + } /** * Function SetScale() @@ -247,7 +253,7 @@ public: * Returns the size of the our rendering area, in pixels. * @return viewport screen size */ - VECTOR2D GetScreenPixelSize() const; + const VECTOR2D& GetScreenPixelSize() const; /** * Function AddLayer() @@ -279,11 +285,11 @@ public: */ inline void SetLayerVisible( int aLayer, bool aVisible = true ) { - if( m_layers[aLayer].enabled != aVisible ) + if( m_layers[aLayer].visible != aVisible ) { // Target has to be redrawn after changing its visibility MarkTargetDirty( m_layers[aLayer].target ); - m_layers[aLayer].enabled = aVisible; + m_layers[aLayer].visible = aVisible; } } @@ -294,7 +300,7 @@ public: */ inline bool IsLayerVisible( int aLayer ) const { - return m_layers.at( aLayer ).enabled; + return m_layers.at( aLayer ).visible; } /** @@ -402,18 +408,11 @@ public: */ void Redraw(); - /** - * Function PartialRedraw() - * Redraws only the parts of the view that have been affected by items - * for which ViewUpdate() function has been called since last redraw. - */ - void PartialRedraw(); - /** * Function RecacheAllItems() * Rebuilds GAL display lists. * @param aForceNow decides if every item should be instantly recached. Otherwise items are - * going to be recached when they become visible. + * going to be recached when they become visible. */ void RecacheAllItems( bool aForceNow = false ); @@ -432,7 +431,16 @@ public: * Returns true if any of the VIEW layers needs to be refreshened. * @return True in case if any of layers is marked as dirty. */ - bool IsDirty() const; + bool IsDirty() const + { + for( int i = 0; i < TARGETS_NUMBER; ++i ) + { + if( IsTargetDirty( i ) ) + return true; + } + + return false; + } /** * Function IsTargetDirty() @@ -440,7 +448,12 @@ public: * redrawn. * @return True if the above condition is fulfilled. */ - bool IsTargetDirty( int aTarget ) const; + bool IsTargetDirty( int aTarget ) const + { + wxASSERT( aTarget < TARGETS_NUMBER ); + + return m_dirtyTargets[aTarget]; + } /** * Function MarkTargetDirty() @@ -470,6 +483,22 @@ public: m_dirtyTargets[i] = true; } + /** + * Function MarkForUpdate() + * Adds an item to a list of items that are going to be refreshed upon the next frame rendering. + * @param aItem is the item to be refreshed. + */ + void MarkForUpdate( VIEW_ITEM* aItem ) + { + m_needsUpdate.push_back( aItem ); + } + + /** + * Function UpdateItems() + * Iterates through the list of items that asked for updating and updates them. + */ + void UpdateItems(); + /** * Function SetPanBoundary() * Sets limits for panning area. @@ -493,26 +522,18 @@ public: m_scaleLimits = VECTOR2D( aMaximum, aMinimum ); } - /** - * Function InvalidateItem() - * Manages dirty flags & redraw queueing when updating an item. - * @param aItem is the item to be updated. - * @param aUpdateFlags determines the way an item is refreshed. - */ - void InvalidateItem( VIEW_ITEM* aItem, int aUpdateFlags ); - - static const int VIEW_MAX_LAYERS = 128; ///* maximum number of layers that may be shown + static const int VIEW_MAX_LAYERS = 128; ///< maximum number of layers that may be shown private: struct VIEW_LAYER { - bool enabled; ///* is the layer to be rendered? - bool displayOnly; ///* is the layer display only? - VIEW_RTREE* items; ///* R-tree indexing all items on this layer. - int renderingOrder; ///* rendering order of this layer - int id; ///* layer ID - RENDER_TARGET target; ///* where the layer should be rendered - std::set requiredLayers; ///* layers that have to be enabled to show the layer + bool visible; ///< is the layer to be rendered? + bool displayOnly; ///< is the layer display only? + VIEW_RTREE* items; ///< R-tree indexing all items on this layer. + int renderingOrder; ///< rendering order of this layer + int id; ///< layer ID + RENDER_TARGET target; ///< where the layer should be rendered + std::set requiredLayers; ///< layers that have to be enabled to show the layer }; // Convenience typedefs @@ -532,7 +553,7 @@ private: ///* Redraws contents within rect aRect void redrawRect( const BOX2I& aRect ); - inline void clearTargetDirty( int aTarget ) + inline void markTargetClean( int aTarget ) { wxASSERT( aTarget < TARGETS_NUMBER ); @@ -549,7 +570,7 @@ private: * @param aImmediate dictates the way of drawing - it allows to force immediate drawing mode * for cached items. */ - void draw( VIEW_ITEM* aItem, int aLayer, bool aImmediate = false ) const; + void draw( VIEW_ITEM* aItem, int aLayer, bool aImmediate = false ); /** * Function draw() @@ -559,7 +580,7 @@ private: * @param aImmediate dictates the way of drawing - it allows to force immediate drawing mode * for cached items. */ - void draw( VIEW_ITEM* aItem, bool aImmediate = false ) const; + void draw( VIEW_ITEM* aItem, bool aImmediate = false ); /** * Function draw() @@ -569,7 +590,7 @@ private: * @param aImmediate dictates the way of drawing - it allows to force immediate drawing mode * for cached items. */ - void draw( VIEW_GROUP* aGroup, bool aImmediate = false ) const; + void draw( VIEW_GROUP* aGroup, bool aImmediate = false ); ///* Sorts m_orderedLayers when layer rendering order has changed void sortLayers(); @@ -578,6 +599,14 @@ private: ///* used by GAL) void clearGroupCache(); + /** + * Function InvalidateItem() + * Manages dirty flags & redraw queueing when updating an item. + * @param aItem is the item to be updated. + * @param aUpdateFlags determines the way an item is refreshed. + */ + void invalidateItem( VIEW_ITEM* aItem, int aUpdateFlags ); + /// Updates colors that are used for an item to be drawn void updateItemColor( VIEW_ITEM* aItem, int aLayer ); @@ -638,6 +667,9 @@ private: /// Zoom limits VECTOR2D m_scaleLimits; + + /// Items to be updated + std::vector m_needsUpdate; }; } // namespace KIGFX diff --git a/include/view/view_item.h b/include/view/view_item.h index c06538b224..a64b1b22db 100644 --- a/include/view/view_item.h +++ b/include/view/view_item.h @@ -157,12 +157,16 @@ public: /** * Enum VIEW_UPDATE_FLAGS. * Defines the how severely the shape/appearance of the item has been changed: + * - NONE: TODO * - APPEARANCE: shape or layer set of the item have not been affected, * only colors or visibility. + * - COLOR: * - GEOMETRY: shape or layer set of the item have changed, VIEW may need to reindex it. - * - ALL: all flags above */ + * - LAYERS: TODO + * - ALL: all the flags above */ enum VIEW_UPDATE_FLAGS { + NONE = 0x00, /// No updates are required APPEARANCE = 0x01, /// Visibility flag has changed COLOR = 0x02, /// Color has changed GEOMETRY = 0x04, /// Position or shape has changed @@ -170,7 +174,8 @@ public: ALL = 0xff }; - VIEW_ITEM() : m_view( NULL ), m_visible( true ), m_groups( NULL ), m_groupsSize( 0 ) {} + VIEW_ITEM() : m_view( NULL ), m_visible( true ), m_requiredUpdate( NONE ), + m_groups( NULL ), m_groupsSize( 0 ) {} /** * Destructor. For dynamic views, removes the item from the view. @@ -262,9 +267,15 @@ public: * For dynamic VIEWs, informs the associated VIEW that the graphical representation of * this item has changed. For static views calling has no effect. * - * @param aUpdateFlags: how much the object has changed + * @param aUpdateFlags: how much the object has changed. */ - virtual void ViewUpdate( int aUpdateFlags = ALL ); + virtual void ViewUpdate( int aUpdateFlags = ALL ) + { + if( m_view && m_requiredUpdate == NONE ) + m_view->MarkForUpdate( this ); + + m_requiredUpdate |= aUpdateFlags; + } /** * Function ViewRelease() @@ -298,8 +309,9 @@ protected: deleteGroups(); } - VIEW* m_view; ///* Current dynamic view the item is assigned to. - bool m_visible; ///* Are we visible in the current dynamic VIEW. + VIEW* m_view; ///< Current dynamic view the item is assigned to. + bool m_visible; ///< Are we visible in the current dynamic VIEW. + int m_requiredUpdate; ///< Flag required for updating ///* Helper for storing cached items group ids typedef std::pair GroupPair; @@ -374,6 +386,24 @@ protected: m_layers.set( aLayers[i] ); } } + + /** + * Function viewRequiredUpdate() + * Returns current update flag for an item. + */ + virtual int viewRequiredUpdate() const + { + return m_requiredUpdate; + } + + /** + * Function clearUpdateFlags() + * Marks an item as already updated, so it is not going to be redrawn. + */ + void clearUpdateFlags() + { + m_requiredUpdate = NONE; + } }; } // namespace KIGFX diff --git a/pcbnew/class_module.cpp b/pcbnew/class_module.cpp index 60b59d8501..e12f3bcf3a 100644 --- a/pcbnew/class_module.cpp +++ b/pcbnew/class_module.cpp @@ -746,20 +746,20 @@ void MODULE::ViewUpdate( int aUpdateFlags ) if( !m_view ) return; + // Update the module itself + VIEW_ITEM::ViewUpdate( aUpdateFlags ); + // Update pads for( D_PAD* pad = m_Pads.GetFirst(); pad; pad = pad->Next() ) - m_view->InvalidateItem( pad, aUpdateFlags ); + pad->ViewUpdate( aUpdateFlags ); // Update module's drawing (mostly silkscreen) for( BOARD_ITEM* drawing = m_Drawings.GetFirst(); drawing; drawing = drawing->Next() ) - m_view->InvalidateItem( drawing, aUpdateFlags ); + drawing->ViewUpdate( aUpdateFlags ); // Update module's texts - m_view->InvalidateItem( m_Reference, aUpdateFlags ); - m_view->InvalidateItem( m_Value, aUpdateFlags ); - - // Update the module itself - m_view->InvalidateItem( this, aUpdateFlags ); + m_Reference->ViewUpdate( aUpdateFlags ); + m_Value->ViewUpdate( aUpdateFlags ); }