KiCad PCB EDA Suite
view.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2013-2017 CERN
5  * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
8  * @author Maciej Suminski <maciej.suminski@cern.ch>
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, you may find one here:
22  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
23  * or you may search the http://www.gnu.org website for the version 2 license,
24  * or you may write to the Free Software Foundation, Inc.,
25  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
26  */
27 
28 
29 #include <eda_item.h>
31 #include <trace_helpers.h>
32 
33 #include <view/view.h>
34 #include <view/view_group.h>
35 #include <view/view_item.h>
36 #include <view/view_rtree.h>
37 #include <view/view_overlay.h>
38 
39 #include <gal/definitions.h>
41 #include <painter.h>
42 
43 #ifdef __WXDEBUG__
44 #include <profile.h>
45 #endif /* __WXDEBUG__ */
46 
47 namespace KIGFX {
48 
49 class VIEW;
50 
52 {
53 public:
55  m_view( nullptr ),
56  m_flags( KIGFX::VISIBLE ),
58  m_drawPriority( 0 ),
59  m_groups( nullptr ),
60  m_groupsSize( 0 ) {}
61 
63  {
64  deleteGroups();
65  }
66 
67  int getFlags() const
68  {
69  return m_flags;
70  }
71 
72 private:
73  friend class VIEW;
74 
81  void getLayers( int* aLayers, int& aCount ) const
82  {
83  int* layersPtr = aLayers;
84 
85  for( int layer : m_layers )
86  *layersPtr++ = layer;
87 
88  aCount = m_layers.size();
89  }
90 
92  int m_flags;
95 
97  typedef std::pair<int, int> GroupPair;
98 
103 
110  int getGroup( int aLayer ) const
111  {
112  for( int i = 0; i < m_groupsSize; ++i )
113  {
114  if( m_groups[i].first == aLayer )
115  return m_groups[i].second;
116  }
117 
118  return -1;
119  }
120 
127  void setGroup( int aLayer, int aGroup )
128  {
129  // Look if there is already an entry for the layer
130  for( int i = 0; i < m_groupsSize; ++i )
131  {
132  if( m_groups[i].first == aLayer )
133  {
134  m_groups[i].second = aGroup;
135  return;
136  }
137  }
138 
139  // If there was no entry for the given layer - create one
140  GroupPair* newGroups = new GroupPair[m_groupsSize + 1];
141 
142  if( m_groupsSize > 0 )
143  {
144  std::copy( m_groups, m_groups + m_groupsSize, newGroups );
145  delete[] m_groups;
146  }
147 
148  m_groups = newGroups;
149  newGroups[m_groupsSize++] = GroupPair( aLayer, aGroup );
150  }
151 
152 
157  {
158  delete[] m_groups;
159  m_groups = nullptr;
160  m_groupsSize = 0;
161  }
162 
163 
169  inline bool storesGroups() const
170  {
171  return m_groupsSize > 0;
172  }
173 
174 
182  void reorderGroups( std::unordered_map<int, int> aReorderMap )
183  {
184  for( int i = 0; i < m_groupsSize; ++i )
185  {
186  int orig_layer = m_groups[i].first;
187  int new_layer = orig_layer;
188 
189  try
190  {
191  new_layer = aReorderMap.at( orig_layer );
192  }
193  catch( const std::out_of_range& ) {}
194 
195  m_groups[i].first = new_layer;
196  }
197  }
198 
199 
201  std::vector<int> m_layers;
202 
209  void saveLayers( int* aLayers, int aCount )
210  {
211  m_layers.clear();
212 
213  for( int i = 0; i < aCount; ++i )
214  {
215  // this fires on some eagle board after EAGLE_PLUGIN::Load()
216  wxASSERT( unsigned( aLayers[i] ) <= unsigned( VIEW::VIEW_MAX_LAYERS ) );
217 
218  m_layers.push_back( aLayers[i] );
219  }
220  }
221 
225  int requiredUpdate() const
226  {
227  return m_requiredUpdate;
228  }
229 
234  {
236  }
237 
241  bool isRenderable() const
242  {
243  return m_flags == VISIBLE;
244  }
245 };
246 
247 
249 {
250  VIEW_ITEM_DATA* data = aItem->viewPrivData();
251 
252  if( !data )
253  return;
254 
255  if( data->m_view )
256  data->m_view->VIEW::Remove( aItem );
257 
258  delete data;
259  aItem->ClearViewPrivData();
260 }
261 
262 
263 VIEW::VIEW( bool aIsDynamic ) :
264  m_enableOrderModifier( true ),
265  m_scale( 4.0 ),
266  m_minScale( 0.2 ), m_maxScale( 5000.0 ),
267  m_mirrorX( false ), m_mirrorY( false ),
268  m_painter( NULL ),
269  m_gal( NULL ),
270  m_dynamic( aIsDynamic ),
271  m_useDrawPriority( false ),
272  m_nextDrawPriority( 0 ),
273  m_reverseDrawOrder( false )
274 {
275  // Set m_boundary to define the max area size. The default area size
276  // is defined here as the max value of a int.
277  // this is a default value acceptable for Pcbnew and Gerbview, but too large for Eeschema.
278  // So in eeschema a call to SetBoundary() with a smaller value will be needed.
279  typedef std::numeric_limits<int> coord_limits;
280  double pos = coord_limits::lowest() / 2 + coord_limits::epsilon();
281  double size = coord_limits::max() - coord_limits::epsilon();
282  m_boundary.SetOrigin( pos, pos );
283  m_boundary.SetSize( size, size );
284  SetPrintMode( 0 );
285 
286  m_allItems.reset( new std::vector<VIEW_ITEM*> );
287  m_allItems->reserve( 32768 );
288 
289  // Redraw everything at the beginning
290  MarkDirty();
291 
292  m_layers.reserve( VIEW_MAX_LAYERS );
293 
294  // View uses layers to display EDA_ITEMs (item may be displayed on several layers, for example
295  // pad may be shown on pad, pad hole and solder paste layers). There are usual copper layers
296  // (eg. F.Cu, B.Cu, internal and so on) and layers for displaying objects such as texts,
297  // silkscreen, pads, vias, etc.
298  for( int ii = 0; ii < VIEW_MAX_LAYERS; ++ii )
299  {
300  m_layers.emplace_back();
301  m_layers[ii].items = std::make_shared<VIEW_RTREE>();
302  m_layers[ii].id = ii;
303  m_layers[ii].renderingOrder = ii;
304  m_layers[ii].visible = true;
305  m_layers[ii].displayOnly = false;
306  m_layers[ii].target = TARGET_CACHED;
307  }
308 
309  sortLayers();
310 
311  m_preview.reset( new KIGFX::VIEW_GROUP() );
312  Add( m_preview.get() );
313 }
314 
315 
317 {
318  Remove( m_preview.get() );
319 }
320 
321 
322 void VIEW::Add( VIEW_ITEM* aItem, int aDrawPriority )
323 {
324  int layers[VIEW_MAX_LAYERS], layers_count;
325 
326  if( aDrawPriority < 0 )
327  aDrawPriority = m_nextDrawPriority++;
328 
329  if( !aItem->m_viewPrivData )
330  aItem->m_viewPrivData = new VIEW_ITEM_DATA;
331 
332  aItem->m_viewPrivData->m_view = this;
333  aItem->m_viewPrivData->m_drawPriority = aDrawPriority;
334 
335  aItem->ViewGetLayers( layers, layers_count );
336  aItem->viewPrivData()->saveLayers( layers, layers_count );
337 
338  m_allItems->push_back( aItem );
339 
340  for( int i = 0; i < layers_count; ++i )
341  {
342  VIEW_LAYER& l = m_layers[layers[i]];
343  l.items->Insert( aItem );
344  MarkTargetDirty( l.target );
345  }
346 
347  SetVisible( aItem, true );
348  Update( aItem, KIGFX::INITIAL_ADD );
349 }
350 
351 
352 void VIEW::Remove( VIEW_ITEM* aItem )
353 {
354  if( !aItem )
355  return;
356 
357  auto viewData = aItem->viewPrivData();
358 
359  if( !viewData )
360  return;
361 
362  wxCHECK( viewData->m_view == this, /*void*/ );
363  auto item = std::find( m_allItems->begin(), m_allItems->end(), aItem );
364 
365  if( item != m_allItems->end() )
366  {
367  m_allItems->erase( item );
368  viewData->clearUpdateFlags();
369  }
370 
371  int layers[VIEW::VIEW_MAX_LAYERS], layers_count;
372  viewData->getLayers( layers, layers_count );
373 
374  for( int i = 0; i < layers_count; ++i )
375  {
376  VIEW_LAYER& l = m_layers[layers[i]];
377  l.items->Remove( aItem );
378  MarkTargetDirty( l.target );
379 
380  // Clear the GAL cache
381  int prevGroup = viewData->getGroup( layers[i] );
382 
383  if( prevGroup >= 0 )
384  m_gal->DeleteGroup( prevGroup );
385  }
386 
387  viewData->deleteGroups();
388  viewData->m_view = nullptr;
389 }
390 
391 
392 void VIEW::SetRequired( int aLayerId, int aRequiredId, bool aRequired )
393 {
394  wxCHECK( (unsigned) aLayerId < m_layers.size(), /*void*/ );
395  wxCHECK( (unsigned) aRequiredId < m_layers.size(), /*void*/ );
396 
397  if( aRequired )
398  m_layers[aLayerId].requiredLayers.insert( aRequiredId );
399  else
400  m_layers[aLayerId].requiredLayers.erase( aRequired );
401 }
402 
403 
404 // stupid C++... python lambda would do this in one line
405 template <class CONTAINER>
407 {
408  typedef typename CONTAINER::value_type item_type;
409 
410  QUERY_VISITOR( CONTAINER& aCont, int aLayer ) :
411  m_cont( aCont ), m_layer( aLayer )
412  {
413  }
414 
415  bool operator()( VIEW_ITEM* aItem )
416  {
417  if( aItem->viewPrivData()->getFlags() & VISIBLE )
418  m_cont.push_back( VIEW::LAYER_ITEM_PAIR( aItem, m_layer ) );
419 
420  return true;
421  }
422 
424  int m_layer;
425 };
426 
427 
428 int VIEW::Query( const BOX2I& aRect, std::vector<LAYER_ITEM_PAIR>& aResult ) const
429 {
430  if( m_orderedLayers.empty() )
431  return 0;
432 
433  std::vector<VIEW_LAYER*>::const_reverse_iterator i;
434 
435  // execute queries in reverse direction, so that items that are on the top of
436  // the rendering stack are returned first.
437  for( i = m_orderedLayers.rbegin(); i != m_orderedLayers.rend(); ++i )
438  {
439  // ignore layers that do not contain actual items (i.e. the selection box, menus, floats)
440  if( ( *i )->displayOnly || !( *i )->visible )
441  continue;
442 
443  QUERY_VISITOR<std::vector<LAYER_ITEM_PAIR> > visitor( aResult, ( *i )->id );
444  ( *i )->items->Query( aRect, visitor );
445  }
446 
447  return aResult.size();
448 }
449 
450 
451 VECTOR2D VIEW::ToWorld( const VECTOR2D& aCoord, bool aAbsolute ) const
452 {
453  const MATRIX3x3D& matrix = m_gal->GetScreenWorldMatrix();
454 
455  if( aAbsolute )
456  return VECTOR2D( matrix * aCoord );
457  else
458  return VECTOR2D( matrix.GetScale().x * aCoord.x, matrix.GetScale().y * aCoord.y );
459 }
460 
461 
462 double VIEW::ToWorld( double aSize ) const
463 {
464  const MATRIX3x3D& matrix = m_gal->GetScreenWorldMatrix();
465 
466  return fabs( matrix.GetScale().x * aSize );
467 }
468 
469 
470 VECTOR2D VIEW::ToScreen( const VECTOR2D& aCoord, bool aAbsolute ) const
471 {
472  const MATRIX3x3D& matrix = m_gal->GetWorldScreenMatrix();
473 
474  if( aAbsolute )
475  return VECTOR2D( matrix * aCoord );
476  else
477  return VECTOR2D( matrix.GetScale().x * aCoord.x, matrix.GetScale().y * aCoord.y );
478 }
479 
480 
481 double VIEW::ToScreen( double aSize ) const
482 {
483  const MATRIX3x3D& matrix = m_gal->GetWorldScreenMatrix();
484 
485  return matrix.GetScale().x * aSize;
486 }
487 
488 
489 void VIEW::CopySettings( const VIEW* aOtherView )
490 {
491  wxASSERT_MSG( false, wxT( "This is not implemented" ) );
492 }
493 
494 
495 void VIEW::SetGAL( GAL* aGal )
496 {
497  bool recacheGroups = ( m_gal != nullptr ); // recache groups only if GAL is reassigned
498  m_gal = aGal;
499 
500  // clear group numbers, so everything is going to be recached
501  if( recacheGroups )
502  clearGroupCache();
503 
504  // every target has to be refreshed
505  MarkDirty();
506 
507  // force the new GAL to display the current viewport.
508  SetCenter( m_center );
509  SetScale( m_scale );
511 }
512 
513 
515 {
516  BOX2D rect;
517  VECTOR2D screenSize = m_gal->GetScreenPixelSize();
518 
519  rect.SetOrigin( ToWorld( VECTOR2D( 0, 0 ) ) );
520  rect.SetEnd( ToWorld( screenSize ) );
521 
522  return rect.Normalize();
523 }
524 
525 
526 void VIEW::SetViewport( const BOX2D& aViewport )
527 {
528  VECTOR2D ssize = ToWorld( m_gal->GetScreenPixelSize(), false );
529 
530  wxCHECK( ssize.x > 0 && ssize.y > 0, /*void*/ );
531 
532  VECTOR2D centre = aViewport.Centre();
533  VECTOR2D vsize = aViewport.GetSize();
534  double zoom = 1.0 / std::max( fabs( vsize.x / ssize.x ), fabs( vsize.y / ssize.y ) );
535 
536  SetCenter( centre );
537  SetScale( GetScale() * zoom );
538 }
539 
540 
541 void VIEW::SetMirror( bool aMirrorX, bool aMirrorY )
542 {
543  wxASSERT_MSG( !aMirrorY, _( "Mirroring for Y axis is not supported yet" ) );
544 
545  m_mirrorX = aMirrorX;
546  m_mirrorY = aMirrorY;
547  m_gal->SetFlip( aMirrorX, aMirrorY );
548 
549  // Redraw everything
550  MarkDirty();
551 }
552 
553 
554 void VIEW::SetScale( double aScale, VECTOR2D aAnchor )
555 {
556  if( aAnchor == VECTOR2D( 0, 0 ) )
557  aAnchor = m_center;
558 
559  VECTOR2D a = ToScreen( aAnchor );
560 
561  if( aScale < m_minScale )
563  else if( aScale > m_maxScale )
565  else
566  m_scale = aScale;
567 
570 
571  VECTOR2D delta = ToWorld( a ) - aAnchor;
572 
573  SetCenter( m_center - delta );
574 
575  // Redraw everything after the viewport has changed
576  MarkDirty();
577 }
578 
579 
580 void VIEW::SetCenter( const VECTOR2D& aCenter )
581 {
582  m_center = aCenter;
583 
584  if( !m_boundary.Contains( aCenter ) )
585  {
586  if( m_center.x < m_boundary.GetLeft() )
588  else if( aCenter.x > m_boundary.GetRight() )
590 
591  if( m_center.y < m_boundary.GetTop() )
593  else if( m_center.y > m_boundary.GetBottom() )
595  }
596 
599 
600  // Redraw everything after the viewport has changed
601  MarkDirty();
602 }
603 
604 
605 void VIEW::SetCenter( VECTOR2D aCenter, const BOX2D& occultingScreenRect )
606 {
607  BOX2D screenRect( VECTOR2D( 0, 0 ), m_gal->GetScreenPixelSize() );
608 
609  if( !screenRect.Intersects( occultingScreenRect ) )
610  {
611  SetCenter( aCenter );
612  return;
613  }
614 
615  BOX2D occultedRect = screenRect.Intersect( occultingScreenRect );
616  double topExposed = occultedRect.GetTop() - screenRect.GetTop();
617  double bottomExposed = screenRect.GetBottom() - occultedRect.GetBottom();
618  double leftExposed = occultedRect.GetLeft() - screenRect.GetLeft();
619  double rightExposed = screenRect.GetRight() - occultedRect.GetRight();
620 
621  if( std::max( topExposed, bottomExposed ) > std::max( leftExposed, rightExposed ) )
622  {
623  if( topExposed > bottomExposed )
624  aCenter.y += ToWorld( screenRect.GetHeight() / 2 - topExposed / 2 );
625  else
626  aCenter.y -= ToWorld( screenRect.GetHeight() / 2 - bottomExposed / 2 );
627  }
628  else
629  {
630  if( leftExposed > rightExposed )
631  aCenter.x += ToWorld( screenRect.GetWidth() / 2 - leftExposed / 2 );
632  else
633  aCenter.x -= ToWorld( screenRect.GetWidth() / 2 - rightExposed / 2 );
634  }
635 
636  SetCenter( aCenter );
637 }
638 
639 
640 void VIEW::SetLayerOrder( int aLayer, int aRenderingOrder )
641 {
642  m_layers[aLayer].renderingOrder = aRenderingOrder;
643 
644  sortLayers();
645 }
646 
647 
648 int VIEW::GetLayerOrder( int aLayer ) const
649 {
650  return m_layers.at( aLayer ).renderingOrder;
651 }
652 
653 
654 void VIEW::SortLayers( int aLayers[], int& aCount ) const
655 {
656  int maxLay, maxOrd, maxIdx;
657 
658  for( int i = 0; i < aCount; ++i )
659  {
660  maxLay = aLayers[i];
661  maxOrd = GetLayerOrder( maxLay );
662  maxIdx = i;
663 
664  // Look for the max element in the range (j..aCount)
665  for( int j = i; j < aCount; ++j )
666  {
667  if( maxOrd < GetLayerOrder( aLayers[j] ) )
668  {
669  maxLay = aLayers[j];
670  maxOrd = GetLayerOrder( maxLay );
671  maxIdx = j;
672  }
673  }
674 
675  // Swap elements
676  aLayers[maxIdx] = aLayers[i];
677  aLayers[i] = maxLay;
678  }
679 }
680 
681 
682 void VIEW::ReorderLayerData( std::unordered_map<int, int> aReorderMap )
683 {
684  std::vector<VIEW_LAYER> new_map;
685  new_map.reserve( m_layers.size() );
686 
687  for( int ii = 0; ii < VIEW_MAX_LAYERS; ++ii )
688  new_map.emplace_back();
689 
690  for( const VIEW_LAYER& layer : m_layers )
691  {
692  int orig_idx = layer.id;
693  int new_idx = orig_idx;
694 
695  if( aReorderMap.count( orig_idx ) )
696  new_idx = aReorderMap.at( orig_idx );
697 
698  new_map[new_idx] = layer;
699  new_map[new_idx].id = new_idx;
700  }
701 
702  m_layers = new_map;
703 
704  for( VIEW_ITEM* item : *m_allItems )
705  {
706  VIEW_ITEM_DATA* viewData = item->viewPrivData();
707 
708  if( !viewData )
709  continue;
710 
711  int layers[VIEW::VIEW_MAX_LAYERS], layers_count;
712 
713  item->ViewGetLayers( layers, layers_count );
714  viewData->saveLayers( layers, layers_count );
715 
716  viewData->reorderGroups( aReorderMap );
717 
718  viewData->m_requiredUpdate |= COLOR;
719  }
720 
721  UpdateItems();
722 }
723 
724 
726 {
727  UPDATE_COLOR_VISITOR( int aLayer, PAINTER* aPainter, GAL* aGal ) :
728  layer( aLayer ),
729  painter( aPainter ),
730  gal( aGal )
731  {
732  }
733 
734  bool operator()( VIEW_ITEM* aItem )
735  {
736  // Obtain the color that should be used for coloring the item
737  const COLOR4D color = painter->GetSettings()->GetColor( aItem, layer );
738  int group = aItem->viewPrivData()->getGroup( layer );
739 
740  if( group >= 0 )
742 
743  return true;
744  }
745 
746  int layer;
749 };
750 
751 
752 void VIEW::UpdateLayerColor( int aLayer )
753 {
754  // There is no point in updating non-cached layers
755  if( !IsCached( aLayer ) )
756  return;
757 
758  BOX2I r;
759 
760  r.SetMaximum();
761 
762  if( m_gal->IsVisible() )
763  {
764  GAL_UPDATE_CONTEXT ctx( m_gal );
765 
766  UPDATE_COLOR_VISITOR visitor( aLayer, m_painter, m_gal );
767  m_layers[aLayer].items->Query( r, visitor );
768  MarkTargetDirty( m_layers[aLayer].target );
769  }
770 }
771 
772 
774 {
775  if( m_gal->IsVisible() )
776  {
777  GAL_UPDATE_CONTEXT ctx( m_gal );
778 
779  for( VIEW_ITEM* item : *m_allItems )
780  {
781  VIEW_ITEM_DATA* viewData = item->viewPrivData();
782 
783  if( !viewData )
784  continue;
785 
786  int layers[VIEW::VIEW_MAX_LAYERS], layers_count;
787  viewData->getLayers( layers, layers_count );
788 
789  for( int i = 0; i < layers_count; ++i )
790  {
791  const COLOR4D color = m_painter->GetSettings()->GetColor( item, layers[i] );
792  int group = viewData->getGroup( layers[i] );
793 
794  if( group >= 0 )
796  }
797  }
798  }
799 
800  MarkDirty();
801 }
802 
803 
805 {
806  UPDATE_DEPTH_VISITOR( int aLayer, int aDepth, GAL* aGal ) :
807  layer( aLayer ),
808  depth( aDepth ),
809  gal( aGal )
810  {
811  }
812 
813  bool operator()( VIEW_ITEM* aItem )
814  {
815  int group = aItem->viewPrivData()->getGroup( layer );
816 
817  if( group >= 0 )
819 
820  return true;
821  }
822 
823  int layer, depth;
825 };
826 
827 
828 int VIEW::GetTopLayer() const
829 {
830  if( m_topLayers.size() == 0 )
831  return 0;
832 
833  return *m_topLayers.begin();
834 }
835 
836 
837 void VIEW::SetTopLayer( int aLayer, bool aEnabled )
838 {
839  if( aEnabled )
840  {
841  if( m_topLayers.count( aLayer ) == 1 )
842  return;
843 
844  m_topLayers.insert( aLayer );
845 
846  // Move the layer closer to front
848  m_layers[aLayer].renderingOrder += TOP_LAYER_MODIFIER;
849  }
850  else
851  {
852  if( m_topLayers.count( aLayer ) == 0 )
853  return;
854 
855  m_topLayers.erase( aLayer );
856 
857  // Restore the previous rendering order
859  m_layers[aLayer].renderingOrder -= TOP_LAYER_MODIFIER;
860  }
861 }
862 
863 
864 void VIEW::EnableTopLayer( bool aEnable )
865 {
866  if( aEnable == m_enableOrderModifier )
867  return;
868 
869  m_enableOrderModifier = aEnable;
870 
871  std::set<unsigned int>::iterator it;
872 
873  if( aEnable )
874  {
875  for( it = m_topLayers.begin(); it != m_topLayers.end(); ++it )
876  m_layers[*it].renderingOrder += TOP_LAYER_MODIFIER;
877  }
878  else
879  {
880  for( it = m_topLayers.begin(); it != m_topLayers.end(); ++it )
881  m_layers[*it].renderingOrder -= TOP_LAYER_MODIFIER;
882  }
883 
886 }
887 
888 
890 {
891  std::set<unsigned int>::iterator it;
892 
894  {
895  // Restore the previous rendering order for layers that were marked as top
896  for( it = m_topLayers.begin(); it != m_topLayers.end(); ++it )
897  m_layers[*it].renderingOrder -= TOP_LAYER_MODIFIER;
898  }
899 
900  m_topLayers.clear();
901 }
902 
903 
905 {
906  sortLayers();
907 
908  if( m_gal->IsVisible() )
909  {
910  GAL_UPDATE_CONTEXT ctx( m_gal );
911 
912  for( VIEW_ITEM* item : *m_allItems )
913  {
914  VIEW_ITEM_DATA* viewData = item->viewPrivData();
915 
916  if( !viewData )
917  continue;
918 
919  int layers[VIEW::VIEW_MAX_LAYERS], layers_count;
920  viewData->getLayers( layers, layers_count );
921 
922  for( int i = 0; i < layers_count; ++i )
923  {
924  int group = viewData->getGroup( layers[i] );
925 
926  if( group >= 0 )
927  m_gal->ChangeGroupDepth( group, m_layers[layers[i]].renderingOrder );
928  }
929  }
930  }
931 
932  MarkDirty();
933 }
934 
935 
937 {
938  DRAW_ITEM_VISITOR( VIEW* aView, int aLayer, bool aUseDrawPriority, bool aReverseDrawOrder ) :
939  view( aView ),
940  layer( aLayer ),
941  useDrawPriority( aUseDrawPriority ),
942  reverseDrawOrder( aReverseDrawOrder )
943  {
944  }
945 
946  bool operator()( VIEW_ITEM* aItem )
947  {
948  wxCHECK( aItem->viewPrivData(), false );
949 
950  // Conditions that have to be fulfilled for an item to be drawn
951  bool drawCondition = aItem->viewPrivData()->isRenderable() &&
952  aItem->ViewGetLOD( layer, view ) < view->m_scale;
953  if( !drawCondition )
954  return true;
955 
956  if( useDrawPriority )
957  drawItems.push_back( aItem );
958  else
959  view->draw( aItem, layer );
960 
961  return true;
962  }
963 
965  {
966  if( reverseDrawOrder )
967  std::sort( drawItems.begin(), drawItems.end(),
968  []( VIEW_ITEM* a, VIEW_ITEM* b ) -> bool {
969  return b->viewPrivData()->m_drawPriority < a->viewPrivData()->m_drawPriority;
970  });
971  else
972  std::sort( drawItems.begin(), drawItems.end(),
973  []( VIEW_ITEM* a, VIEW_ITEM* b ) -> bool {
974  return a->viewPrivData()->m_drawPriority < b->viewPrivData()->m_drawPriority;
975  });
976 
977  for( VIEW_ITEM* item : drawItems )
978  view->draw( item, layer );
979  }
980 
984  std::vector<VIEW_ITEM*> drawItems;
985 };
986 
987 
988 void VIEW::redrawRect( const BOX2I& aRect )
989 {
990  for( VIEW_LAYER* l : m_orderedLayers )
991  {
992  if( l->visible && IsTargetDirty( l->target ) && areRequiredLayersEnabled( l->id ) )
993  {
994  DRAW_ITEM_VISITOR drawFunc( this, l->id, m_useDrawPriority, m_reverseDrawOrder );
995 
996  m_gal->SetTarget( l->target );
997  m_gal->SetLayerDepth( l->renderingOrder );
998  l->items->Query( aRect, drawFunc );
999 
1000  if( m_useDrawPriority )
1001  drawFunc.deferredDraw();
1002  }
1003  }
1004 }
1005 
1006 
1007 void VIEW::draw( VIEW_ITEM* aItem, int aLayer, bool aImmediate )
1008 {
1009  VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1010 
1011  if( !viewData )
1012  return;
1013 
1014  if( IsCached( aLayer ) && !aImmediate )
1015  {
1016  // Draw using cached information or create one
1017  int group = viewData->getGroup( aLayer );
1018 
1019  if( group >= 0 )
1020  m_gal->DrawGroup( group );
1021  else
1022  Update( aItem );
1023  }
1024  else
1025  {
1026  // Immediate mode
1027  if( !m_painter->Draw( aItem, aLayer ) )
1028  aItem->ViewDraw( aLayer, this ); // Alternative drawing method
1029  }
1030 }
1031 
1032 
1033 void VIEW::draw( VIEW_ITEM* aItem, bool aImmediate )
1034 {
1035  int layers[VIEW_MAX_LAYERS], layers_count;
1036 
1037  aItem->ViewGetLayers( layers, layers_count );
1038 
1039  // Sorting is needed for drawing order dependent GALs (like Cairo)
1040  SortLayers( layers, layers_count );
1041 
1042  for( int i = 0; i < layers_count; ++i )
1043  {
1044  m_gal->SetLayerDepth( m_layers.at( layers[i] ).renderingOrder );
1045  draw( aItem, layers[i], aImmediate );
1046  }
1047 }
1048 
1049 
1050 void VIEW::draw( VIEW_GROUP* aGroup, bool aImmediate )
1051 {
1052  for( unsigned int i = 0; i < aGroup->GetSize(); i++)
1053  draw( aGroup->GetItem(i), aImmediate );
1054 }
1055 
1056 
1058 {
1059  RECACHE_ITEM_VISITOR( VIEW* aView, GAL* aGal, int aLayer ) :
1060  view( aView ),
1061  gal( aGal ),
1062  layer( aLayer )
1063  {
1064  }
1065 
1066  bool operator()( VIEW_ITEM* aItem )
1067  {
1068  VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1069 
1070  if( !viewData )
1071  return false;
1072 
1073  // Remove previously cached group
1074  int group = viewData->getGroup( layer );
1075 
1076  if( group >= 0 )
1077  gal->DeleteGroup( group );
1078 
1079  viewData->setGroup( layer, -1 );
1080  view->Update( aItem );
1081 
1082  return true;
1083  }
1084 
1087  int layer;
1088 };
1089 
1090 
1092 {
1093  BOX2I r;
1094  r.SetMaximum();
1095  m_allItems->clear();
1096 
1097  for( VIEW_LAYER& layer : m_layers )
1098  layer.items->RemoveAll();
1099 
1100  m_nextDrawPriority = 0;
1101 
1102  m_gal->ClearCache();
1103 }
1104 
1105 
1107 {
1109  {
1110  // TARGET_CACHED and TARGET_NONCACHED have to be redrawn together, as they contain
1111  // layers that rely on each other (eg. netnames are noncached, but tracks - are cached)
1114 
1115  MarkDirty();
1116  }
1117 
1118  if( IsTargetDirty( TARGET_OVERLAY ) )
1119  {
1121  }
1122 }
1123 
1124 
1126 {
1127 #ifdef __WXDEBUG__
1128  PROF_COUNTER totalRealTime;
1129 #endif /* __WXDEBUG__ */
1130 
1131  VECTOR2D screenSize = m_gal->GetScreenPixelSize();
1132  BOX2D rect( ToWorld( VECTOR2D( 0, 0 ) ),
1133  ToWorld( screenSize ) - ToWorld( VECTOR2D( 0, 0 ) ) );
1134 
1135  rect.Normalize();
1136  BOX2I recti( rect.GetPosition(), rect.GetSize() );
1137 
1138  // The view rtree uses integer positions. Large screens can overflow
1139  // this size so in this case, simply set the rectangle to the full rtree
1140  if( rect.GetWidth() > std::numeric_limits<int>::max() ||
1141  rect.GetHeight() > std::numeric_limits<int>::max() )
1142  recti.SetMaximum();
1143 
1144  redrawRect( recti );
1145  // All targets were redrawn, so nothing is dirty
1149 
1150 #ifdef __WXDEBUG__
1151  totalRealTime.Stop();
1152  wxLogTrace( traceGalProfile, "VIEW::Redraw(): %.1f ms", totalRealTime.msecs() );
1153 #endif /* __WXDEBUG__ */
1154 }
1155 
1156 
1158 {
1159  return m_gal->GetScreenPixelSize();
1160 }
1161 
1162 
1164 {
1166  view( aView )
1167  {
1168  }
1169 
1170  bool operator()( VIEW_ITEM* aItem )
1171  {
1172  aItem->viewPrivData()->deleteGroups();
1173 
1174  return true;
1175  }
1176 
1178 };
1179 
1180 
1182 {
1183  BOX2I r;
1184 
1185  r.SetMaximum();
1186  CLEAR_LAYER_CACHE_VISITOR visitor( this );
1187 
1188  for( VIEW_LAYER& layer : m_layers )
1189  layer.items->Query( r, visitor );
1190 }
1191 
1192 
1193 void VIEW::invalidateItem( VIEW_ITEM* aItem, int aUpdateFlags )
1194 {
1195  if( aUpdateFlags & INITIAL_ADD )
1196  {
1197  // Don't update layers or bbox, since it was done in VIEW::Add()
1198  // Now that we have initialized, set flags to ALL for the code below
1199  aUpdateFlags = ALL;
1200  }
1201  else
1202  {
1203  // updateLayers updates geometry too, so we do not have to update both of them at the
1204  // same time
1205  if( aUpdateFlags & LAYERS )
1206  {
1207  updateLayers( aItem );
1208  }
1209  else if( aUpdateFlags & GEOMETRY )
1210  {
1211  updateBbox( aItem );
1212  }
1213  }
1214 
1215  int layers[VIEW_MAX_LAYERS], layers_count;
1216  aItem->ViewGetLayers( layers, layers_count );
1217 
1218  // Iterate through layers used by the item and recache it immediately
1219  for( int i = 0; i < layers_count; ++i )
1220  {
1221  int layerId = layers[i];
1222 
1223  if( IsCached( layerId ) )
1224  {
1225  if( aUpdateFlags & ( GEOMETRY | LAYERS | REPAINT ) )
1226  updateItemGeometry( aItem, layerId );
1227  else if( aUpdateFlags & COLOR )
1228  updateItemColor( aItem, layerId );
1229  }
1230 
1231  // Mark those layers as dirty, so the VIEW will be refreshed
1232  MarkTargetDirty( m_layers[layerId].target );
1233  }
1234 
1235  aItem->viewPrivData()->clearUpdateFlags();
1236 }
1237 
1238 
1240 {
1241  int n = 0;
1242 
1243  m_orderedLayers.resize( m_layers.size() );
1244 
1245  for( VIEW_LAYER& layer : m_layers )
1246  m_orderedLayers[n++] = &layer;
1247 
1248  sort( m_orderedLayers.begin(), m_orderedLayers.end(), compareRenderingOrder );
1249 
1250  MarkDirty();
1251 }
1252 
1253 
1254 void VIEW::updateItemColor( VIEW_ITEM* aItem, int aLayer )
1255 {
1256  VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1257  wxCHECK( (unsigned) aLayer < m_layers.size(), /*void*/ );
1258  wxCHECK( IsCached( aLayer ), /*void*/ );
1259 
1260  if( !viewData )
1261  return;
1262 
1263  // Obtain the color that should be used for coloring the item on the specific layerId
1264  const COLOR4D color = m_painter->GetSettings()->GetColor( aItem, aLayer );
1265  int group = viewData->getGroup( aLayer );
1266 
1267  // Change the color, only if it has group assigned
1268  if( group >= 0 )
1270 }
1271 
1272 
1273 void VIEW::updateItemGeometry( VIEW_ITEM* aItem, int aLayer )
1274 {
1275  VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1276  wxCHECK( (unsigned) aLayer < m_layers.size(), /*void*/ );
1277  wxCHECK( IsCached( aLayer ), /*void*/ );
1278 
1279  if( !viewData )
1280  return;
1281 
1282  VIEW_LAYER& l = m_layers.at( aLayer );
1283 
1284  m_gal->SetTarget( l.target );
1286 
1287  // Redraw the item from scratch
1288  int group = viewData->getGroup( aLayer );
1289 
1290  if( group >= 0 )
1291  m_gal->DeleteGroup( group );
1292 
1293  group = m_gal->BeginGroup();
1294  viewData->setGroup( aLayer, group );
1295 
1296  if( !m_painter->Draw( static_cast<EDA_ITEM*>( aItem ), aLayer ) )
1297  aItem->ViewDraw( aLayer, this ); // Alternative drawing method
1298 
1299  m_gal->EndGroup();
1300 }
1301 
1302 
1304 {
1305  int layers[VIEW_MAX_LAYERS], layers_count;
1306 
1307  aItem->ViewGetLayers( layers, layers_count );
1308 
1309  for( int i = 0; i < layers_count; ++i )
1310  {
1311  VIEW_LAYER& l = m_layers[layers[i]];
1312  l.items->Remove( aItem );
1313  l.items->Insert( aItem );
1314  MarkTargetDirty( l.target );
1315  }
1316 }
1317 
1318 
1320 {
1321  VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1322  int layers[VIEW_MAX_LAYERS], layers_count;
1323 
1324  if( !viewData )
1325  return;
1326 
1327  // Remove the item from previous layer set
1328  viewData->getLayers( layers, layers_count );
1329 
1330  for( int i = 0; i < layers_count; ++i )
1331  {
1332  VIEW_LAYER& l = m_layers[layers[i]];
1333  l.items->Remove( aItem );
1334  MarkTargetDirty( l.target );
1335 
1336  if( IsCached( l.id ) )
1337  {
1338  // Redraw the item from scratch
1339  int prevGroup = viewData->getGroup( layers[i] );
1340 
1341  if( prevGroup >= 0 )
1342  {
1343  m_gal->DeleteGroup( prevGroup );
1344  viewData->setGroup( l.id, -1 );
1345  }
1346  }
1347  }
1348 
1349  // Add the item to new layer set
1350  aItem->ViewGetLayers( layers, layers_count );
1351  viewData->saveLayers( layers, layers_count );
1352 
1353  for( int i = 0; i < layers_count; i++ )
1354  {
1355  VIEW_LAYER& l = m_layers[layers[i]];
1356  l.items->Insert( aItem );
1357  MarkTargetDirty( l.target );
1358  }
1359 }
1360 
1361 
1362 bool VIEW::areRequiredLayersEnabled( int aLayerId ) const
1363 {
1364  wxCHECK( (unsigned) aLayerId < m_layers.size(), false );
1365 
1366  std::set<int>::const_iterator it, it_end;
1367 
1368  for( it = m_layers.at( aLayerId ).requiredLayers.begin(),
1369  it_end = m_layers.at( aLayerId ).requiredLayers.end(); it != it_end; ++it )
1370  {
1371  // That is enough if just one layer is not enabled
1372  if( !m_layers.at( *it ).visible || !areRequiredLayersEnabled( *it ) )
1373  return false;
1374  }
1375 
1376  return true;
1377 }
1378 
1379 
1381 {
1382  BOX2I r;
1383 
1384  r.SetMaximum();
1385 
1386  for( const VIEW_LAYER& l : m_layers )
1387  {
1388  if( IsCached( l.id ) )
1389  {
1390  RECACHE_ITEM_VISITOR visitor( this, m_gal, l.id );
1391  l.items->Query( r, visitor );
1392  }
1393  }
1394 }
1395 
1396 
1398 {
1399  if( m_gal->IsVisible() )
1400  {
1401  GAL_UPDATE_CONTEXT ctx( m_gal );
1402 
1403  for( VIEW_ITEM* item : *m_allItems )
1404  {
1405  if( item->viewPrivData() && item->viewPrivData()->m_requiredUpdate != NONE )
1406  {
1407  invalidateItem( item, item->viewPrivData()->m_requiredUpdate );
1408  item->viewPrivData()->m_requiredUpdate = NONE;
1409  }
1410  }
1411  }
1412 }
1413 
1414 
1415 void VIEW::UpdateAllItems( int aUpdateFlags )
1416 {
1417  for( VIEW_ITEM* item : *m_allItems )
1418  {
1419  if( item->viewPrivData() )
1420  item->viewPrivData()->m_requiredUpdate |= aUpdateFlags;
1421  }
1422 }
1423 
1424 
1425 void VIEW::UpdateAllItemsConditionally( int aUpdateFlags,
1426  std::function<bool( VIEW_ITEM* )> aCondition )
1427 {
1428  for( VIEW_ITEM* item : *m_allItems )
1429  {
1430  if( aCondition( item ) )
1431  {
1432  if( item->viewPrivData() )
1433  item->viewPrivData()->m_requiredUpdate |= aUpdateFlags;
1434  }
1435  }
1436 }
1437 
1438 
1439 std::unique_ptr<VIEW> VIEW::DataReference() const
1440 {
1441  std::unique_ptr<VIEW> ret = std::make_unique<VIEW>();
1442  ret->m_allItems = m_allItems;
1443  ret->m_layers = m_layers;
1444  ret->sortLayers();
1445  return ret;
1446 }
1447 
1448 
1449 void VIEW::SetVisible( VIEW_ITEM* aItem, bool aIsVisible )
1450 {
1451  VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1452 
1453  if( !viewData )
1454  return;
1455 
1456  bool cur_visible = viewData->m_flags & VISIBLE;
1457 
1458  if( cur_visible != aIsVisible )
1459  {
1460  if( aIsVisible )
1461  viewData->m_flags |= VISIBLE;
1462  else
1463  viewData->m_flags &= ~VISIBLE;
1464 
1465  Update( aItem, APPEARANCE | COLOR );
1466  }
1467 }
1468 
1469 
1470 void VIEW::Hide( VIEW_ITEM* aItem, bool aHide )
1471 {
1472  VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1473 
1474  if( !viewData )
1475  return;
1476 
1477  if( !( viewData->m_flags & VISIBLE ) )
1478  return;
1479 
1480  if( aHide )
1481  viewData->m_flags |= HIDDEN;
1482  else
1483  viewData->m_flags &= ~HIDDEN;
1484 
1485  Update( aItem, APPEARANCE );
1486 }
1487 
1488 
1489 bool VIEW::IsVisible( const VIEW_ITEM* aItem ) const
1490 {
1491  const VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1492 
1493  return viewData && ( viewData->m_flags & VISIBLE );
1494 }
1495 
1496 
1497 void VIEW::Update( const VIEW_ITEM* aItem ) const
1498 {
1499  Update( aItem, ALL );
1500 }
1501 
1502 
1503 void VIEW::Update( const VIEW_ITEM* aItem, int aUpdateFlags ) const
1504 {
1505  VIEW_ITEM_DATA* viewData = aItem->viewPrivData();
1506 
1507  if( !viewData )
1508  return;
1509 
1510  assert( aUpdateFlags != NONE );
1511 
1512  viewData->m_requiredUpdate |= aUpdateFlags;
1513 }
1514 
1515 
1516 std::shared_ptr<VIEW_OVERLAY> VIEW::MakeOverlay()
1517 {
1518  std::shared_ptr<VIEW_OVERLAY> overlay( new VIEW_OVERLAY );
1519 
1520  Add( overlay.get() );
1521  return overlay;
1522 }
1523 
1524 
1526 {
1527  if( !m_preview )
1528  return;
1529 
1530  m_preview->Clear();
1531 
1532  for( EDA_ITEM *item : m_ownedItems )
1533  delete item;
1534 
1535  m_ownedItems.clear();
1536  Update( m_preview.get() );
1537 }
1538 
1539 
1541 {
1542  m_preview.reset( new KIGFX::VIEW_GROUP() );
1543  Add( m_preview.get() );
1544 }
1545 
1546 
1547 void VIEW::AddToPreview( EDA_ITEM* aItem, bool aTakeOwnership )
1548 {
1549  Hide( aItem, false );
1550  m_preview->Add( aItem );
1551 
1552  if( aTakeOwnership )
1553  m_ownedItems.push_back( aItem );
1554 
1555  SetVisible( m_preview.get(), true );
1556  Hide( m_preview.get(), false );
1557  Update( m_preview.get() );
1558 }
1559 
1560 
1561 void VIEW::ShowPreview( bool aShow )
1562 {
1563  SetVisible( m_preview.get(), aShow );
1564 }
1565 
1566 
1567 const int VIEW::TOP_LAYER_MODIFIER = -VIEW_MAX_LAYERS;
1568 
1569 } // namespace KIGFX
void Stop()
Save the time when this function was called, and set the counter stane to stop.
Definition: profile.h:85
void Hide(VIEW_ITEM *aItem, bool aHide=true)
Temporarily hide the item in the view (e.g.
Definition: view.cpp:1470
virtual void DrawGroup(int aGroupNumber)
Draw the stored group.
Item is being added to the view.
Definition: view_item.h:56
Item is temporarily hidden (e.g.
Definition: view_item.h:66
int requiredUpdate() const
Return current update flag for an item.
Definition: view.cpp:225
void deleteGroups()
Remove all of the stored group ids.
Definition: view.cpp:156
BOX2D GetViewport() const
Return the current viewport visible area rectangle.
Definition: view.cpp:514
VIEW_ITEM_DATA * m_viewPrivData
Definition: view_item.h:156
void SetViewport(const BOX2D &aViewport)
Set the visible area of the VIEW.
Definition: view.cpp:526
void updateLayers(VIEW_ITEM *aItem)
Determine rendering order of layers. Used in display order sorting function.
Definition: view.cpp:1319
void UpdateAllItemsConditionally(int aUpdateFlags, std::function< bool(VIEW_ITEM *)> aCondition)
Update items in the view according to the given flags and condition.
Definition: view.cpp:1425
CONTAINER & m_cont
Definition: view.cpp:423
void SetLayerOrder(int aLayer, int aRenderingOrder)
Set rendering order of a particular layer.
Definition: view.cpp:640
void SetRequired(int aLayerId, int aRequiredId, bool aRequired=true)
Mark the aRequiredId layer as required for the aLayerId layer.
Definition: view.cpp:392
void updateItemColor(VIEW_ITEM *aItem, int aLayer)
Update all information needed to draw an item.
Definition: view.cpp:1254
bool m_useDrawPriority
The next sequential drawing priority.
Definition: view.h:858
std::unique_ptr< KIGFX::VIEW_GROUP > m_preview
Definition: view.h:800
The Cairo implementation of the graphics abstraction layer.
Definition: color4d.cpp:175
virtual void DeleteGroup(int aGroupNumber)
Delete the group from the memory.
virtual void SetTopLayer(int aLayer, bool aEnabled=true)
Set given layer to be displayed on the top or sets back the default order of layers.
Definition: view.cpp:837
static const int TOP_LAYER_MODIFIER
Flag to respect draw priority when drawing items.
Definition: view.h:855
const MATRIX3x3D & GetScreenWorldMatrix() const
Get the screen <-> world transformation matrix.
void sortLayers()
Clear cached GAL group numbers (ONLY numbers stored in VIEW_ITEMs, not group objects used by GAL)
Definition: view.cpp:1239
int getFlags() const
Definition: view.cpp:67
VECTOR2D ToWorld(const VECTOR2D &aCoord, bool aAbsolute=true) const
Converts a screen space point/vector to a point/vector in world space coordinates.
Definition: view.cpp:451
double msecs(bool aSinceLast=false)
Definition: profile.h:146
coord_type GetTop() const
Definition: box2.h:204
void AddToPreview(EDA_ITEM *aItem, bool aTakeOwnership=true)
Definition: view.cpp:1547
int color
Definition: DXF_plotter.cpp:60
void RecacheAllItems()
Rebuild GAL display lists.
Definition: view.cpp:1380
void UpdateAllItems(int aUpdateFlags)
Update all items in the view according to the given flags.
Definition: view.cpp:1415
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:352
bool operator()(VIEW_ITEM *aItem)
Definition: view.cpp:946
void SetFlip(bool xAxis, bool yAxis)
Sets flipping of the screen.
void InitPreview()
Definition: view.cpp:1540
bool operator()(VIEW_ITEM *aItem)
Definition: view.cpp:1170
GAL * m_gal
Dynamic VIEW (eg.
Definition: view.h:845
bool areRequiredLayersEnabled(int aLayerId) const
Definition: view.cpp:1362
coord_type GetRight() const
Definition: box2.h:199
QUERY_VISITOR(CONTAINER &aCont, int aLayer)
Definition: view.cpp:410
std::set< unsigned int > m_topLayers
Center point of the VIEW (the point at which we are looking at).
Definition: view.h:818
void SetSize(const Vec &size)
Definition: box2.h:212
void clearUpdateFlags()
Mark an item as already updated, so it is not going to be redrawn.
Definition: view.cpp:233
const wxChar *const traceGalProfile
Flag to enable debug output of GAL performance profiling.
void UpdateAllLayersOrder()
Do everything that is needed to apply the rendering order of layers.
Definition: view.cpp:904
Visibility flag has changed.
Definition: view_item.h:52
bool operator()(VIEW_ITEM *aItem)
Definition: view.cpp:1066
coord_type GetBottom() const
Definition: box2.h:200
void SetMirror(bool aMirrorX, bool aMirrorY)
Control the mirroring of the VIEW.
Definition: view.cpp:541
An abstract base class for deriving all objects that can be added to a VIEW.
Definition: view_item.h:81
Color has changed.
Definition: view_item.h:53
All except INITIAL_ADD.
Definition: view_item.h:58
virtual void ComputeWorldScreenMatrix()
Compute the world <-> screen transformation matrix.
A small class to help profiling.
Definition: profile.h:45
virtual VIEW_ITEM * GetItem(unsigned int aIdx) const
Definition: view_group.cpp:87
virtual void SetLayerDepth(double aLayerDepth)
Set the depth of the layer (position on the z-axis)
std::shared_ptr< VIEW_OVERLAY > MakeOverlay()
Definition: view.cpp:1516
bool storesGroups() const
Return information if the item uses at least one group id (ie.
Definition: view.cpp:169
virtual void EnableTopLayer(bool aEnable)
Enable or disable display of the top layer.
Definition: view.cpp:864
void setGroup(int aLayer, int aGroup)
Set a group id for the item and the layer combination.
Definition: view.cpp:127
VECTOR2< T > GetScale() const
Get the scale components of the matrix.
Definition: matrix3x3.h:269
VECTOR2D m_center
Scale of displayed VIEW_ITEMs.
Definition: view.h:821
VIEW * m_view
Current dynamic view the item is assigned to.
Definition: view.cpp:91
bool operator()(VIEW_ITEM *aItem)
Definition: view.cpp:415
static constexpr int VIEW_MAX_LAYERS
maximum number of layers that may be shown
Definition: view.h:700
virtual void EndGroup()
End the group.
Auxiliary rendering target (noncached)
Definition: definitions.h:49
std::shared_ptr< std::vector< VIEW_ITEM * > > m_allItems
The set of layers that are displayed on the top.
Definition: view.h:815
void SortLayers(int aLayers[], int &aCount) const
Change the order of given layer ids, so after sorting the order corresponds to layers rendering order...
Definition: view.cpp:654
int getGroup(int aLayer) const
Return number of the group id for the given layer, or -1 in case it was not cached before.
Definition: view.cpp:110
void ShowPreview(bool aShow=true)
Definition: view.cpp:1561
UPDATE_COLOR_VISITOR(int aLayer, PAINTER *aPainter, GAL *aGal)
Definition: view.cpp:727
double m_minScale
Scale upper limit.
Definition: view.h:830
virtual void ChangeGroupColor(int aGroupNumber, const COLOR4D &aNewColor)
Change the color used to draw the group.
const VECTOR2I & GetScreenPixelSize() const
Return GAL canvas size in pixels.
virtual unsigned int GetSize() const
Return the number of stored items.
Definition: view_group.cpp:81
void SetPrintMode(int aPrintMode)
Set the printing mode.
Definition: view.h:698
int layers[VIEW_MAX_LAYERS]
Definition: view.cpp:982
Contains all the knowledge about how to draw graphical object onto any particular output device.
Definition: painter.h:57
Item needs to be redrawn.
Definition: view_item.h:57
VIEW_ITEM class definition.
int m_drawPriority
Order to draw this item in a layer, lowest first.
Definition: view.cpp:94
void SetCenter(const VECTOR2D &aCenter)
Set the center point of the VIEW (i.e.
Definition: view.cpp:580
UPDATE_DEPTH_VISITOR(int aLayer, int aDepth, GAL *aGal)
Definition: view.cpp:806
#define NULL
VECTOR2< double > VECTOR2D
Definition: vector2d.h:622
virtual void Redraw()
Immediately redraws the whole view.
Definition: view.cpp:1125
void MarkTargetDirty(int aTarget)
Set or clear target 'dirty' flag.
Definition: view.h:574
bool IsTargetDirty(int aTarget) const
Return true if any of layers belonging to the target or the target itself should be redrawn.
Definition: view.h:563
void Clear()
Remove all items from the view.
Definition: view.cpp:1091
bool IsVisible(const VIEW_ITEM *aItem) const
Return information if the item is visible (or not).
Definition: view.cpp:1489
VIEW_ITEM_DATA * viewPrivData() const
Definition: view_item.h:143
bool operator()(VIEW_ITEM *aItem)
Definition: view.cpp:734
virtual int GetTopLayer() const
Definition: view.cpp:828
coord_type GetWidth() const
Definition: box2.h:197
virtual int BeginGroup()
Begin a group.
BOX2< Vec > & Normalize()
Function Normalize ensures that the height ant width are positive.
Definition: box2.h:129
bool Contains(const Vec &aPoint) const
Function Contains.
Definition: box2.h:151
virtual void ClearTarget(RENDER_TARGET aTarget)
Clear the target for rendering.
void SetMaximum()
Definition: box2.h:73
virtual void ViewGetLayers(int aLayers[], int &aCount) const =0
Return the all the layers within the VIEW the object is painted on.
bool m_mirrorX
Vertical flip flag.
Definition: view.h:836
void invalidateItem(VIEW_ITEM *aItem, int aUpdateFlags)
Manage dirty flags & redraw queuing when updating an item.
Definition: view.cpp:1193
void ClearPreview()
Definition: view.cpp:1525
const VECTOR2I & GetScreenPixelSize() const
Return the size of the our rendering area in pixels.
Definition: view.cpp:1157
void reorderGroups(std::unordered_map< int, int > aReorderMap)
Reorder the stored groups (to facilitate reordering of layers).
Definition: view.cpp:182
Extend VIEW_ITEM by possibility of grouping items into a single object.
Definition: view_group.h:46
int id
Layer ID.
Definition: view.h:709
Items that may change while the view stays the same (noncached)
Definition: definitions.h:50
wxLogTrace helper definitions.
void ReorderLayerData(std::unordered_map< int, int > aReorderMap)
Remap the data between layer ids without invalidating that data.
Definition: view.cpp:682
void UpdateItems()
Iterate through the list of items that asked for updating and updates them.
Definition: view.cpp:1397
void markTargetClean(int aTarget)
Definition: view.h:722
GroupPair * m_groups
Definition: view.cpp:101
void updateBbox(VIEW_ITEM *aItem)
Update set of layers that an item occupies.
Definition: view.cpp:1303
PAINTER * m_painter
Interface to #PAINTER that is used to draw items.
Definition: view.h:842
bool m_reverseDrawOrder
A control for printing: m_printMode <= 0 means no printing mode (normal draw mode m_printMode > 0 is ...
Definition: view.h:864
Item is visible (in general)
Definition: view_item.h:65
int m_nextDrawPriority
Flag to reverse the draw order when using draw priority.
Definition: view.h:861
VECTOR2D ToScreen(const VECTOR2D &aCoord, bool aAbsolute=true) const
Convert a world space point/vector to a point/vector in screen space coordinates.
Definition: view.cpp:470
void saveLayers(int *aLayers, int aCount)
Save layers used by the item.
Definition: view.cpp:209
bool operator()(VIEW_ITEM *aItem)
Definition: view.cpp:813
std::vector< VIEW_LAYER > m_layers
Sorted list of pointers to members of m_layers.
Definition: view.h:809
void ClearTopLayers()
Remove all layers from the on-the-top set (they are no longer displayed over the rest of layers).
Definition: view.cpp:889
virtual bool Draw(const VIEW_ITEM *aItem, int aLayer)=0
Takes an instance of VIEW_ITEM and passes it to a function that knows how to draw the item.
void SetEnd(coord_type x, coord_type y)
Definition: box2.h:225
const Vec & GetPosition() const
Definition: box2.h:194
virtual void SetScale(double aScale, VECTOR2D aAnchor={ 0, 0 })
Set the scaling factor, zooming around a given anchor point.
Definition: view.cpp:554
void clearGroupCache()
Definition: view.cpp:1181
double m_maxScale
Horizontal flip flag.
Definition: view.h:833
void UpdateLayerColor(int aLayer)
Apply the new coloring scheme held by RENDER_SETTINGS in case that it has changed.
Definition: view.cpp:752
std::unique_ptr< VIEW > DataReference() const
Return a new VIEW object that shares the same set of VIEW_ITEMs and LAYERs.
Definition: view.cpp:1439
No updates are required.
Definition: view_item.h:51
virtual COLOR4D GetColor(const VIEW_ITEM *aItem, int aLayer) const =0
Returns the color that should be used to draw the specific VIEW_ITEM on the specific layer using curr...
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
CONTAINER::value_type item_type
Definition: view.cpp:408
void redrawRect(const BOX2I &aRect)
Definition: view.cpp:988
bool isRenderable() const
Return if the item should be drawn or not.
Definition: view.cpp:241
std::vector< EDA_ITEM * > m_ownedItems
Whether to use rendering order modifier or not.
Definition: view.h:803
void updateItemGeometry(VIEW_ITEM *aItem, int aLayer)
Update bounding box of an item.
Definition: view.cpp:1273
Board layer functions and definitions.
Main rendering target (cached)
Definition: definitions.h:48
Vec Centre() const
Definition: box2.h:79
bool m_enableOrderModifier
The set of possible displayed layers and its properties.
Definition: view.h:806
static void OnDestroy(VIEW_ITEM *aItem)
Nasty hack, invoked by the destructor of VIEW_ITEM to auto-remove the item from the owning VIEW if th...
Definition: view.cpp:248
#define _(s)
Definition: 3d_actions.cpp:33
BOX2D m_boundary
Scale lower limit.
Definition: view.h:827
static std::shared_ptr< KIGFX::VIEW_OVERLAY > overlay
std::vector< VIEW_LAYER * > m_orderedLayers
Flat list of all items.
Definition: view.h:812
std::pair< VIEW_ITEM *, int > LAYER_ITEM_PAIR
Definition: view.h:72
int GetLayerOrder(int aLayer) const
Return rendering order of a particular layer.
Definition: view.cpp:648
void draw(VIEW_ITEM *aItem, int aLayer, bool aImmediate=false)
Draw an item, but on a specified layers.
Definition: view.cpp:1007
bool IsCached(int aLayer) const
Return true if the layer is cached.
Definition: view.h:581
void SetOrigin(const Vec &pos)
Definition: box2.h:210
virtual bool IsVisible() const
Return true if the GAL canvas is visible on the screen.
void SetZoomFactor(double aZoomFactor)
Set the zoom factor of the scene.
virtual void ChangeGroupDepth(int aGroupNumber, int aDepth)
Change the depth (Z-axis position) of the group.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:150
bool m_mirrorY
PAINTER contains information how do draw items.
Definition: view.h:839
void ClearTargets()
Clear targets that are marked as dirty.
Definition: view.cpp:1106
coord_type GetHeight() const
Definition: box2.h:198
int m_flags
Visibility flags.
Definition: view.cpp:92
void ClearViewPrivData()
Definition: view_item.h:148
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition: view.cpp:1449
void CopySettings(const VIEW *aOtherView)
Copy layers and visibility settings from another view.
Definition: view.cpp:489
double m_scale
View boundaries.
Definition: view.h:824
Layers have changed.
Definition: view_item.h:55
int renderingOrder
Rendering order of this layer.
Definition: view.h:708
void SetLookAtPoint(const VECTOR2D &aPoint)
Set the Point in world space to look at.
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:322
std::pair< int, int > GroupPair
Indexes of cached GAL display lists corresponding to the item (for every layer it.
Definition: view.cpp:97
const Vec & GetSize() const
Definition: box2.h:189
virtual int Query(const BOX2I &aRect, std::vector< LAYER_ITEM_PAIR > &aResult) const
Find all visible items that touch or are within the rectangle aRect.
Definition: view.cpp:428
coord_type GetLeft() const
Definition: box2.h:203
virtual ~VIEW()
Definition: view.cpp:316
VIEW(bool aIsDynamic=true)
Definition: view.cpp:263
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:67
DRAW_ITEM_VISITOR(VIEW *aView, int aLayer, bool aUseDrawPriority, bool aReverseDrawOrder)
Definition: view.cpp:938
const MATRIX3x3D & GetWorldScreenMatrix() const
Get the world <-> screen transformation matrix.
void UpdateAllLayersColor()
Apply the new coloring scheme to all layers.
Definition: view.cpp:773
double GetScale() const
Definition: view.h:263
std::vector< int > m_layers
Stores layer numbers used by the item.
Definition: view.cpp:201
void SetGAL(GAL *aGal)
Assign a rendering device for the VIEW.
Definition: view.cpp:495
int m_requiredUpdate
Flag required for updating.
Definition: view.cpp:93
static bool compareRenderingOrder(VIEW_LAYER *aI, VIEW_LAYER *aJ)
Check if every layer required by the aLayerId layer is enabled.
Definition: view.h:787
virtual void ClearCache()
Delete all data created during caching of graphic items.
virtual void SetTarget(RENDER_TARGET aTarget)
Set the target for rendering.
void MarkDirty()
Force redraw of view on the next rendering.
Definition: view.h:598
virtual double ViewGetLOD(int aLayer, VIEW *aView) const
Return the level of detail (LOD) of the item.
Definition: view_item.h:137
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: view.cpp:1503
std::vector< VIEW_ITEM * > drawItems
Definition: view.cpp:984
void getLayers(int *aLayers, int &aCount) const
Return layer numbers used by the item.
Definition: view.cpp:81
Abstract interface for drawing on a 2D-surface.
Position or shape has changed.
Definition: view_item.h:54
RECACHE_ITEM_VISITOR(VIEW *aView, GAL *aGal, int aLayer)
Definition: view.cpp:1059
virtual void ViewDraw(int aLayer, VIEW *aView) const
Draw the parts of the object belonging to layer aLayer.
Definition: view_item.h:111
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:98
BOX2< Vec > Intersect(const BOX2< Vec > &aRect)
Function Intersect Returns the intersection of this with another rectangle.
Definition: box2.h:268
RENDER_TARGET target
Where the layer should be rendered.
Definition: view.h:710
std::shared_ptr< VIEW_RTREE > items
R-tree indexing all items on this layer.
Definition: view.h:707