Audacity  3.0.3
OverlayPanel.cpp
Go to the documentation of this file.
1 //
2 // OverlayPanel.cpp
3 // Audacity
4 //
5 // Created by Paul Licameli on 5/7/16.
6 //
7 //
8 
9 
10 #include "OverlayPanel.h"
11 
12 #include "Overlay.h"
13 #include "MemoryX.h"
14 #include <algorithm>
15 #include <wx/dcclient.h>
16 
17 OverlayPanel::OverlayPanel(wxWindow * parent, wxWindowID id,
18  const wxPoint & pos,
19  const wxSize & size,
20  long style)
21 : BackedPanel(parent, id, pos, size, style)
22 {}
23 
24 void OverlayPanel::AddOverlay( const std::weak_ptr<Overlay> &pOverlay)
25 {
26  if (pOverlay.expired())
27  return;
28  Compress();
29  auto iter = std::lower_bound( mOverlays.begin(), mOverlays.end(),
30  pOverlay.lock()->SequenceNumber(),
31  []( const OverlayPtr &p, unsigned value ) {
32  return p.expired() || p.lock()->SequenceNumber() < value;
33  }
34  );
35  mOverlays.insert(iter, pOverlay);
36 }
37 
39 {
40  mOverlays.clear();
41 }
42 
43 void OverlayPanel::DrawOverlays(bool repaint_all, wxDC *pDC)
44 {
45  if ( !IsShownOnScreen() )
46  return;
47 
48  size_t n_pairs = mOverlays.size();
49 
50  using Pair = std::pair<wxRect, bool /*out of date?*/>;
51  std::vector< Pair > pairs;
52  pairs.reserve(n_pairs);
53 
54  // First...
55  Compress();
56  // ... then assume pointers are not expired
57 
58  // Find out the rectangles and outdatedness for each overlay
59  wxSize size(GetBackingDC().GetSize());
60  for (const auto pOverlay : mOverlays)
61  pairs.push_back( pOverlay.lock()->GetRectangle(size) );
62 
63  // See what requires redrawing. If repainting, all.
64  // If not, then whatever is outdated, and whatever will be damaged by
65  // undrawing.
66  // By redrawing only what needs it, we avoid flashing things like
67  // the cursor that are drawn with invert, and also avoid
68  // unnecessary work.
69 
70  // But first, a quick exit test.
71  bool some_overlays_need_repainting =
72  repaint_all ||
73  std::any_of( pairs.begin(), pairs.end(),
74  []( const Pair &pair ){ return pair.second; } );
75 
76  if (!some_overlays_need_repainting) {
77  // This function (OverlayPanel::DrawOverlays()) is called at
78  // fairly high frequency through a timer in TrackPanel. In case
79  // there is nothing to do, we exit early because creating the
80  // wxClientDC below is expensive, at least on Linux.
81  return;
82  }
83 
84  if (!repaint_all) {
85  // For each overlay that needs update, any other overlay whose
86  // rectangle intersects it will also need update.
87  bool done;
88  do {
89  done = true;
90  for (size_t ii = 0; ii < n_pairs - 1; ++ii) {
91  for (size_t jj = ii + 1; jj < n_pairs; ++jj) {
92  if (pairs[ii].second != pairs[jj].second &&
93  pairs[ii].first.Intersects(pairs[jj].first)) {
94  done = false;
95  pairs[ii].second = pairs[jj].second = true;
96  }
97  }
98  }
99  } while (!done);
100  }
101 
103  auto &dc = pDC ? *pDC : (myDC.emplace(this), *myDC);
104 
105  // Erase
106  auto it2 = pairs.begin();
107  for (auto pOverlay : mOverlays) {
108  if (repaint_all || it2->second)
109  pOverlay.lock()->Erase(dc, GetBackingDC());
110  ++it2;
111  }
112 
113  // Draw
114  it2 = pairs.begin();
115  for (auto pOverlay : mOverlays) {
116  if (repaint_all || it2->second) {
117  // Guarantee a clean state of the dc each pass:
118  ADCChanger changer{ &dc };
119 
120  pOverlay.lock()->Draw(*this, dc);
121  }
122  ++it2;
123  }
124 }
125 
127 {
128  // remove any expired pointers
129  auto begin = mOverlays.begin();
130  auto end = mOverlays.end();
131  auto newEnd = std::remove_if( begin, end,
132  []( const std::weak_ptr<Overlay> &pOverlay ){
133  return pOverlay.expired(); } );
134  if ( end != newEnd )
135  mOverlays.resize( newEnd - begin );
136 }
137 
138 BEGIN_EVENT_TABLE(OverlayPanel, BackedPanel)
140 
141 // Maybe this class needs a better home
142 void DCUnchanger::operator () (wxDC *pDC) const
143 {
144  if (pDC) {
145  pDC->SetPen(pen);
146  pDC->SetBrush(brush);
147  pDC->SetLogicalFunction(wxRasterOperationMode(logicalOperation));
148  }
149 }
150 
152  : Base{ pDC, ::DCUnchanger{ pDC->GetBrush(), pDC->GetPen(),
153  long(pDC->GetLogicalFunction()) } }
154 {}
size
size_t size
Definition: ffmpeg-2.3.6-single-header.h:412
Optional::emplace
X & emplace(Args &&... args)
Definition: MemoryX.h:193
Overlay::SequenceNumber
virtual unsigned SequenceNumber() const =0
This number determines an ordering of overlays, so that those with higher numbers overpaint those wit...
Optional
Like a smart pointer, allows for object to not exist (nullptr)
Definition: MemoryX.h:144
OverlayPanel::OverlayPanel
OverlayPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, long style=wxTAB_TRAVERSAL|wxNO_BORDER)
Definition: OverlayPanel.cpp:17
OverlayPanel.h
OverlayPanel::Compress
void Compress()
Definition: OverlayPanel.cpp:126
BackedPanel::GetBackingDC
wxDC & GetBackingDC()
Definition: BackedPanel.cpp:30
DCUnchanger
Used to restore pen, brush and logical-op in a DC back to what they were.
Definition: OverlayPanel.h:54
ADCChanger::Base
std::unique_ptr< wxDC, ::DCUnchanger > Base
Definition: OverlayPanel.h:73
wxRasterOperationMode
#define wxRasterOperationMode
Definition: ImageRoll.h:21
ADCChanger
Makes temporary drawing context changes that you back out of, RAII style.
Definition: OverlayPanel.h:72
OverlayPanel::OverlayPtr
std::weak_ptr< Overlay > OverlayPtr
Definition: OverlayPanel.h:43
anonymous_namespace{ProjectFileManager.cpp}::Pair
std::pair< const char *, const char * > Pair
Definition: ProjectFileManager.cpp:106
ADCChanger::ADCChanger
ADCChanger()
Definition: OverlayPanel.h:75
id
int id
Definition: WaveTrackControls.cpp:577
MemoryX.h
OverlayPanel
Definition: OverlayPanel.h:18
BackedPanel
BackedPanel is for a panel that consists of a bitmap with something drawn over it....
Definition: BackedPanel.h:19
OverlayPanel::AddOverlay
void AddOverlay(const std::weak_ptr< Overlay > &pOverlay)
Definition: OverlayPanel.cpp:24
OverlayPanel::DrawOverlays
void DrawOverlays(bool repaint_all, wxDC *pDC=nullptr)
Definition: OverlayPanel.cpp:43
END_EVENT_TABLE
END_EVENT_TABLE()
OverlayPanel::mOverlays
std::vector< OverlayPtr > mOverlays
Definition: OverlayPanel.h:46
OverlayPanel::ClearOverlays
void ClearOverlays()
Definition: OverlayPanel.cpp:38
Overlay.h