Audacity 3.2.0
CommonTrackInfo.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3Audacity: A Digital Audio Editor
4
5CommonTrackInfo.cpp
6
7Paul Licameli split from TrackInfo.cpp
8
9********************************************************************/
27#include "CommonTrackInfo.h"
28
29#include <wx/dc.h>
30#include <wx/dcmemory.h>
31
32#include "AColor.h"
33#include "AllThemeResources.h"
34#include "SyncLock.h"
35#include "Theme.h"
36#include "Track.h"
37#include "TrackArt.h"
38#include "TrackControls.h"
40#include "UIHandle.h"
41#include "ViewInfo.h"
43
44#define RANGE(array) std::begin(array), std::end(array)
47
49{
50 static const TCPLines theLines{
53 };
54 return theLines;
55}
56
58{
59 return commonTrackTCPLines();
60}
61
62namespace {
63
64 constexpr auto Padding = 2;
65
66int totalTCPLines( const TCPLines &lines, bool omitLastExtra )
67{
68 int total = 0;
69 int lastExtra = 0;
70 for ( const auto line : lines ) {
71 lastExtra = line.extraSpace;
72 total += line.height + lastExtra;
73 }
74 if (omitLastExtra)
75 total -= lastExtra;
76 return total;
77}
78}
79
80namespace {
81
82// Items for the bottom of the panel, listed bottom-upwards
83// As also with the top items, the extra space is below the item
85 // The '0' avoids impinging on bottom line of TCP
86 // Use -1 if you do want to do so.
89};
91
92// return y value and height
93std::pair< int, int > CalcBottomItemY
94 ( const TCPLines &lines, unsigned iItem, int height )
95{
96 int y = height;
97 auto pLines = lines.begin();
98 while ( pLines != lines.end() &&
99 0 == (pLines->items & iItem) ) {
100 y -= pLines->height + pLines->extraSpace;
101 ++pLines;
102 }
103 if (pLines != lines.end())
104 y -= (pLines->height + pLines->extraSpace );
105 return { y, pLines->height };
106}
107
108}
109
111{
112 unsigned height = Margin * 2;
113 if (!commonTrackTCPLines().empty())
114 height += commonTrackTCPLines().front().height;
115 if (!commonTrackTCPBottomLines.empty())
116 height += commonTrackTCPBottomLines.front().height;
117 // + 1 prevents the top item from disappearing for want of enough space,
118 // according to the rules in HideTopItem.
119 return height + kVerticalPadding + 1;
120}
121
122bool CommonTrackInfo::HideTopItem( const wxRect &rect, const wxRect &subRect,
123 int allowance ) {
124 auto limit = CalcBottomItemY
126 // Return true if the rectangle is even touching the limit
127 // without an overlap. That was the behavior as of 2.1.3.
128 return subRect.y + subRect.height - allowance >= rect.y + limit;
129}
130
132( TrackPanelDrawingContext &context,
133 const wxRect &rect, const Track &track )
134{
135 auto &trackControl = TrackControls::Get(track);
136 const auto &topLines = trackControl.GetTCPLines();
137 const auto &bottomLines = commonTrackTCPBottomLines;
139 ( context, rect, &track, topLines, bottomLines );
140}
141
143( TrackPanelDrawingContext &context,
144 const wxRect &rect_, const Track *pTrack,
145 const std::vector<TCPLine> &topLines, const std::vector<TCPLine> &bottomLines )
146{
147 const auto rect = wxRect(rect_).Deflate(Margin);
148 auto dc = &context.dc;
150 dc->SetTextForeground(theTheme.Colour(clrTrackPanelText));
151
152 {
153 int yy = 0;
154 for ( const auto &line : topLines ) {
155 wxRect itemRect{
156 rect.x, rect.y + yy,
157 rect.width, line.height
158 };
159 if ( !CommonTrackInfo::HideTopItem( rect, itemRect ) &&
160 line.drawFunction )
161 line.drawFunction( context, itemRect, pTrack );
162 yy += line.height + line.extraSpace;
163 }
164 }
165 {
166 int yy = rect.height;
167 for ( const auto &line : bottomLines ) {
168 yy -= line.height + line.extraSpace;
169 if ( line.drawFunction ) {
170 wxRect itemRect{
171 rect.x, rect.y + yy,
172 rect.width, line.height
173 };
174 line.drawFunction( context, itemRect, pTrack );
175 }
176 }
177 }
178}
179
181 TrackPanelDrawingContext &context, const wxRect &bev,
182 const Channel *pChannel, UIHandle *target)
183{
184 auto dc = &context.dc;
185 auto pTrack = pChannel
186 ? dynamic_cast<const Track*>(&pChannel->GetChannelGroup())
187 : nullptr;
188 bool selected = pTrack ? pTrack->GetSelected() : true;
189 bool hit = target && target->FindTrack().get() == pTrack;
190 bool captured = hit && target->IsDragging();
191 bool down = captured && bev.Contains( context.lastState.GetPosition());
192
193 wxMemoryDC memDC;
194
195 if(selected)
196 memDC.SelectObject(theTheme.Bitmap(bmpCloseHover));
197 else if(down)
198 memDC.SelectObject(theTheme.Bitmap(bmpCloseDown));
199 else
200 memDC.SelectObject(theTheme.Bitmap(bmpCloseNormal));
201
202 dc->Blit(bev.GetLeft(), bev.GetRight(), bev.width, bev.height, &memDC, 0, 0);
203
204 AColor::Bevel2(*dc, !down, bev, selected, hit );
205}
206
207namespace
208{
209 void DrawToolButtonBackground(TrackPanelDrawingContext &context, const wxRect& rect, bool captured)
210 {
211 const auto hovered = rect.Contains( context.lastState.GetPosition());
212 if(captured && hovered)
213 AColor::DrawFrame(context.dc, rect, theTheme.Bitmap(bmpHiliteButtonSmall), 11);
214 else if(hovered)
215 AColor::DrawFrame(context.dc, rect, theTheme.Bitmap(bmpHiliteUpButtonSmall), 11);
216 }
217}
218
220( TrackPanelDrawingContext &context,
221 const wxRect &rect, const Track *pTrack )
222{
223 const auto dc = &context.dc;
224
225 const auto target = context.target.get();
226 const auto hit = target && target->FindTrack().get() == pTrack;
227 const auto captured = hit && target->IsDragging();
228
229 { //close button
230 wxRect bev = rect;
231 GetCloseBoxHorizontalBounds( rect, bev );
232
233 DrawToolButtonBackground(context, bev, captured);
234
235 dc->DrawBitmap(theTheme.Bitmap(tcpClose), bev.GetLeftTop());
236 }
237
238 { //track title
239 wxRect bev = rect;
241 const auto titleStr = TrackArt::TruncateText(*dc,
242 pTrack ? pTrack->GetName() : _("Name"), bev.width);
243
245 const auto metrics = dc->GetFontMetrics();
246
247 dc->SetTextForeground( theTheme.Colour( clrTrackPanelText ) );
248 dc->SetTextBackground( wxTRANSPARENT );
249 dc->DrawText(titleStr, bev.x + 2, bev.y + (bev.height - (metrics.ascent + metrics.descent)) / 2);
250
251 }
252
253 { //minimize button
254 const auto minimized =
255 pTrack ? ChannelView::Get(*pTrack->GetChannel(0)).GetMinimized() : false;
256
257 wxRect bev = rect;
259
260 DrawToolButtonBackground(context, bev, captured);
261
262 dc->DrawBitmap(
263 minimized
264 ? theTheme.Bitmap(tcpChevronDown)
265 : theTheme.Bitmap(tcpChevron),
266 bev.GetLeftTop());
267
268 }
269
270 { //track menu button
271 wxRect bev = rect;
272 GetTrackMenuButtonBounds(rect, bev);
273
274 DrawToolButtonBackground(context, bev, captured);
275
276 dc->DrawBitmap(theTheme.Bitmap(tcpEllipses), bev.GetLeftTop());
277 }
278
279}
280
282( TrackPanelDrawingContext &context,
283 const wxRect &rect, const Track *pTrack )
284{
285 auto dc = &context.dc;
286 bool syncLockSelected =
287 pTrack ? SyncLock::IsSyncLockSelected(*pTrack) : true;
288
289 // Draw the sync-lock indicator if this track is in a sync-lock selected group.
290 if (syncLockSelected)
291 {
292 wxRect syncLockIconRect = rect;
293
294 GetSyncLockHorizontalBounds( rect, syncLockIconRect );
295 wxBitmap syncLockBitmap(theTheme.Image(bmpSyncLockIcon));
296 // Icon is 12x12 and syncLockIconRect is 16x16.
297 dc->DrawBitmap(syncLockBitmap,
298 syncLockIconRect.x + 3,
299 syncLockIconRect.y + 2,
300 true);
301 }
302}
303
304void CommonTrackInfo::GetCloseBoxHorizontalBounds( const wxRect & rect, wxRect &dest )
305{
306 dest.x = rect.x;
307 dest.width = ToolButtonSize;
308}
309
310void CommonTrackInfo::GetCloseBoxRect(const wxRect & rect_, wxRect & dest)
311{
312 const auto rect = wxRect(rect_).Deflate(Margin);
313 GetCloseBoxHorizontalBounds( rect, dest );
315 dest.y = rect.y + results.first;
316 dest.height = results.second;
317}
318
319void CommonTrackInfo::GetTrackTitleHorizontalBounds( const wxRect & rect, wxRect &dest )
320{
321 // to right of CloseBoxRect, plus a little more
322 wxRect closeRect;
323 wxRect minRect;
324 GetCloseBoxHorizontalBounds( rect, closeRect );
325 GetMinimizeHorizontalBounds( rect, minRect );
326 dest.x = rect.x + closeRect.width + Padding;
327 dest.width = minRect.x - closeRect.width - closeRect.x;
328}
329
330void CommonTrackInfo::GetTrackTitleRect(const wxRect & rect_, wxRect & dest)
331{
332 const auto rect = wxRect(rect_).Deflate(Margin);
333 GetTrackTitleHorizontalBounds( rect, dest );
335 dest.y = rect.y + results.first;
336 dest.height = results.second;
337}
338
339void CommonTrackInfo::GetSliderHorizontalBounds( const wxRect &rect, wxRect &dest )
340{
341 dest.x = rect.x + (rect.width - kTrackInfoSliderWidth) / 2;
342 dest.width = kTrackInfoSliderWidth;
343}
344
345void CommonTrackInfo::GetTrackMenuButtonBounds(const wxRect& rect, wxRect& dest)
346{
347 dest.x = rect.x + rect.width - ToolButtonSize;
348 dest.width = ToolButtonSize;
349}
350
351void CommonTrackInfo::GetTrackMenuButtonRect(const wxRect& rect_, wxRect& dest)
352{
353 const auto rect = wxRect(rect_).Deflate(Margin);
354 GetTrackMenuButtonBounds(rect, dest);
356 dest.y = rect.y + results.first;
357 dest.height = ToolButtonSize;
358}
359
360void CommonTrackInfo::GetMinimizeHorizontalBounds(const wxRect &rect, wxRect &dest )
361{
362 GetTrackMenuButtonBounds(rect, dest);
363 dest.x -= ToolButtonSize + Padding;
364}
365
366void CommonTrackInfo::GetMinimizeRect(const wxRect & rect_, wxRect &dest)
367{
368 const auto rect = wxRect(rect_).Deflate(Margin);
369
370 GetMinimizeHorizontalBounds( rect, dest );
371 const auto results = CalcItemY
373 dest.y = rect.y + results.first;
374 dest.height = results.second;
375}
376
377void CommonTrackInfo::GetSyncLockHorizontalBounds( const wxRect &rect, wxRect &dest )
378{
379 dest.width = kTrackInfoBtnSize;
380 dest.x = rect.x + rect.width - dest.width;
381}
382
383void CommonTrackInfo::GetSyncLockIconRect(const wxRect & rect_, wxRect &dest)
384{
385 const auto rect = wxRect(rect_).Deflate(Margin);
386 GetSyncLockHorizontalBounds( rect, dest );
387 auto results = CalcBottomItemY
389 dest.y = rect.y + results.first;
390 dest.height = results.second;
391}
392
394{
395 int needed =
397 totalTCPLines( topLines, true ) +
399 return (unsigned) std::max(needed, (int) ChannelView::DefaultHeight);
400}
std::vector< TrackInfo::TCPLine > TCPLines
TrackInfo::TCPLine TCPLine
static const TCPLines & commonTrackTCPLines()
#define RANGE(array)
#define _(s)
Definition: Internat.h:73
THEME_API Theme theTheme
Definition: Theme.cpp:82
declares abstract base class Track, TrackList, and iterators over TrackList
@ kVerticalPadding
Definition: ViewInfo.h:92
@ kTrackInfoSliderWidth
Definition: ViewInfo.h:100
@ kTrackInfoTitleHeight
Definition: ViewInfo.h:96
@ kTrackInfoBtnSize
Definition: ViewInfo.h:98
@ kTrackInfoTitleExtra
Definition: ViewInfo.h:97
static void Bevel2(wxDC &dc, bool up, const wxRect &r, bool bSel=false, bool bHighlight=false)
Definition: AColor.cpp:298
static void DrawFrame(wxDC &dc, const wxRect &r, wxBitmap &bitmap, int mid)
Definition: AColor.cpp:329
std::shared_ptr< ChannelType > GetChannel(size_t iChannel)
Retrieve a channel, cast to the given type.
Definition: Channel.h:320
ChannelGroup & GetChannelGroup()
Channel object's lifetime is assumed to be nested in its Track's.
Definition: Channel.cpp:43
static ChannelView & Get(Channel &channel)
bool GetMinimized() const
Definition: ChannelView.h:69
static bool IsSyncLockSelected(const Track &track)
Definition: SyncLock.cpp:80
wxColour & Colour(int iIndex)
wxImage & Image(int iIndex)
wxBitmap & Bitmap(int iIndex)
static TrackControls & Get(Track &track)
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:110
bool GetSelected() const
Selectedness is always the same for all channels of a group.
Definition: Track.cpp:78
const wxString & GetName() const
Name is always the same for all channels of a group.
Definition: Track.cpp:64
Short-lived drawing and event-handling object associated with a TrackPanelCell.
Definition: UIHandle.h:37
virtual std::shared_ptr< const Track > FindTrack() const =0
virtual bool IsDragging() const
Definition: UIHandle.cpp:57
AUDACITY_DLL_API void GetSliderHorizontalBounds(const wxRect &rect, wxRect &dest)
static constexpr auto ToolButtonSize
AUDACITY_DLL_API void GetSyncLockIconRect(const wxRect &rect, wxRect &dest)
static constexpr auto Margin
AUDACITY_DLL_API void GetCloseBoxHorizontalBounds(const wxRect &rect, wxRect &dest)
AUDACITY_DLL_API void CloseTitleDrawFunction(TrackPanelDrawingContext &context, const wxRect &rect, const Track *pTrack)
AUDACITY_DLL_API void GetTrackTitleRect(const wxRect &rect, wxRect &dest)
AUDACITY_DLL_API void GetSyncLockHorizontalBounds(const wxRect &rect, wxRect &dest)
AUDACITY_DLL_API void SyncLockDrawFunction(TrackPanelDrawingContext &context, const wxRect &rect, const Track *pTrack)
AUDACITY_DLL_API void DrawItems(TrackPanelDrawingContext &context, const wxRect &rect, const Track &track)
AUDACITY_DLL_API void GetTrackMenuButtonBounds(const wxRect &rect, wxRect &dest)
AUDACITY_DLL_API void GetCloseBoxRect(const wxRect &rect, wxRect &dest)
AUDACITY_DLL_API void GetTrackTitleHorizontalBounds(const wxRect &rect, wxRect &dest)
TrackInfo::TCPLines TCPLines
AUDACITY_DLL_API unsigned DefaultTrackHeight(const TCPLines &topLines)
AUDACITY_DLL_API void DrawCloseButton(TrackPanelDrawingContext &context, const wxRect &bev, const Channel *pChannel, UIHandle *target)
AUDACITY_DLL_API void GetTrackMenuButtonRect(const wxRect &rect, wxRect &dest)
AUDACITY_DLL_API void GetMinimizeRect(const wxRect &rect, wxRect &dest)
AUDACITY_DLL_API void GetMinimizeHorizontalBounds(const wxRect &rect, wxRect &dest)
AUDACITY_DLL_API const TCPLines & StaticTCPLines()
AUDACITY_DLL_API unsigned MinimumTrackHeight()
AUDACITY_DLL_API bool HideTopItem(const wxRect &rect, const wxRect &subRect, int allowance=0)
AUDACITY_DLL_API wxString TruncateText(wxDC &dc, const wxString &text, const int maxWidth)
Definition: TrackArt.cpp:173
AUDACITY_DLL_API void SetTrackInfoFont(wxDC *dc)
Definition: TrackInfo.cpp:77
std::vector< TCPLine > TCPLines
Definition: TrackInfo.h:58
AUDACITY_DLL_API std::pair< int, int > CalcItemY(const TCPLines &lines, unsigned iItem)
Definition: TrackInfo.cpp:61
const TrackInfo::TCPLine defaultCommonTrackTCPBottomLines[]
std::pair< int, int > CalcBottomItemY(const TCPLines &lines, unsigned iItem, int height)
int totalTCPLines(const TCPLines &lines, bool omitLastExtra)
void DrawToolButtonBackground(TrackPanelDrawingContext &context, const wxRect &rect, bool captured)