Audacity 3.2.0
Functions | Variables
TrackArt Namespace Reference

Functions

AUDACITY_DLL_API wxRect DrawClipAffordance (wxDC &dc, const wxRect &clipRect, bool highlight=false, bool selected=false)
 
AUDACITY_DLL_API bool DrawClipTitle (wxDC &dc, const wxRect &affordanceRect, const wxString &title)
 
AUDACITY_DLL_API void DrawClipEdges (wxDC &dc, const wxRect &clipRect, bool selected=false)
 
AUDACITY_DLL_API void DrawClipFolded (wxDC &dc, const wxRect &rect)
 
AUDACITY_DLL_API void DrawSyncLockTiles (TrackPanelDrawingContext &context, const wxRect &rect)
 
AUDACITY_DLL_API void DrawBackgroundWithSelection (TrackPanelDrawingContext &context, const wxRect &rect, const Channel &channel, const wxBrush &selBrush, const wxBrush &unselBrush, bool useSelection=true, bool useBeatsAlternateColor=false)
 Helper: draws background with selection rect. More...
 
AUDACITY_DLL_API void DrawCursor (TrackPanelDrawingContext &context, const wxRect &rect, const Track *track)
 
AUDACITY_DLL_API void DrawNegativeOffsetTrackArrows (TrackPanelDrawingContext &context, const wxRect &rect)
 
AUDACITY_DLL_API wxString TruncateText (wxDC &dc, const wxString &text, const int maxWidth)
 
AUDACITY_DLL_API void DrawSnapLines (wxDC *dc, wxInt64 snap0, wxInt64 snap1)
 

Variables

static constexpr int ClipFrameRadius { 6 }
 

Function Documentation

◆ DrawBackgroundWithSelection()

void TrackArt::DrawBackgroundWithSelection ( TrackPanelDrawingContext context,
const wxRect &  rect,
const Channel channel,
const wxBrush &  selBrush,
const wxBrush &  unselBrush,
bool  useSelection = true,
bool  useBeatsAlternateColor = false 
)

Helper: draws background with selection rect.

Parameters
useBeatsAlternateColoris only meaningful in Beats mode

Definition at line 648 of file TrackArt.cpp.

652{
653 const auto dc = &context.dc;
654 const auto artist = TrackArtist::Get( context );
655 const auto &selectedRegion = *artist->pSelectedRegion;
656 const auto& zoomInfo = *artist->pZoomInfo;
657
658
659 //MM: Draw background. We should optimize that a bit more.
660 const double sel0 = useSelection ? selectedRegion.t0() : 0.0;
661 const double sel1 = useSelection ? selectedRegion.t1() : 0.0;
662
663 auto pTrack = dynamic_cast<const Track*>(&channel.GetChannelGroup());
664 if (!pTrack)
665 return;
666 auto &track = *pTrack;
667 BeatsGridlinePainter gridlinePainter(zoomInfo, GetProject(track));
668
669 dc->SetPen(*wxTRANSPARENT_PEN);
670
671 const auto& beatStrongBrush = artist->beatStrongBrush[useBeatsAlternateColor];
672 const auto& beatStrongSelBrush = artist->beatStrongSelBrush[useBeatsAlternateColor];
673 const auto& beatWeakBrush = artist->beatWeakBrush[useBeatsAlternateColor];
674 const auto& beatWeakSelBrush = artist->beatWeakSelBrush[useBeatsAlternateColor];
675 const auto& beatSepearatorPen = artist->beatSepearatorPen[useBeatsAlternateColor];
676 const auto& barSepearatorPen = artist->barSepearatorPen[useBeatsAlternateColor];
677
678 auto drawBgRect = [dc, &gridlinePainter, &rect](
679 const wxBrush& regularBrush,
680 const wxBrush& beatStrongBrush,
681 const wxBrush& beatWeakBrush, const wxRect& subRect)
682 {
683 if (!gridlinePainter.enabled)
684 {
685 // Track not selected; just draw background
686 dc->SetBrush(regularBrush);
687 dc->DrawRectangle(subRect);
688 }
689 else
690 {
691 gridlinePainter.DrawBackground(
692 *dc, subRect, rect, beatStrongBrush, beatWeakBrush);
693 }
694 };
695
697 // Rectangles before, within, after the selection
698 wxRect before = rect;
699 wxRect within = rect;
700 wxRect after = rect;
701
702 before.width = (int)(zoomInfo.TimeToPosition(sel0) );
703 if (before.GetRight() > rect.GetRight()) {
704 before.width = rect.width;
705 }
706
707 if (before.width > 0) {
708 drawBgRect(unselBrush, beatStrongBrush, beatWeakBrush, before);
709
710 within.x = 1 + before.GetRight();
711 }
712 within.width = rect.x + (int)(zoomInfo.TimeToPosition(sel1) ) - within.x -1;
713
714 if (within.GetRight() > rect.GetRight()) {
715 within.width = 1 + rect.GetRight() - within.x;
716 }
717
718 // Bug 2389 - Selection can disappear
719 // This handles case where no waveform is visible.
720 if (within.width < 1)
721 within.width = 1;
722
723 if (within.width > 0) {
724 if (track.GetSelected()) {
725 drawBgRect(selBrush, beatStrongSelBrush, beatWeakSelBrush, within);
726 }
727 else {
728 // Per condition above, track must be sync-lock selected
729 drawBgRect(
730 unselBrush, beatStrongBrush, beatWeakBrush, within);
731 DrawSyncLockTiles( context, within );
732 }
733
734 after.x = 1 + within.GetRight();
735 }
736 else {
737 // `within` not drawn; start where it would have gone
738 after.x = within.x;
739 }
740
741 after.width = 1 + rect.GetRight() - after.x;
742 if (after.width > 0)
743 drawBgRect(
744 unselBrush, beatStrongBrush, beatWeakBrush, after);
745 }
746 else
747 {
748 drawBgRect(
749 unselBrush, beatStrongBrush, beatWeakBrush, rect);
750 }
751
752 if (gridlinePainter.enabled)
753 gridlinePainter.DrawSeparators(*dc, rect, beatSepearatorPen, barSepearatorPen);
754}
bool within(A a, B b, DIST d)
Definition: TrackPanel.cpp:170
ChannelGroup & GetChannelGroup()
Channel object's lifetime is assumed to be nested in its Track's.
Definition: Channel.cpp:43
static bool IsSelectedOrSyncLockSelected(const Track &track)
Definition: SyncLock.cpp:104
static TrackArtist * Get(TrackPanelDrawingContext &)
Definition: TrackArtist.cpp:81
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:110
AUDACITY_DLL_API void DrawSyncLockTiles(TrackPanelDrawingContext &context, const wxRect &rect)
Definition: TrackArt.cpp:365
const AudacityProject & GetProject(const Track &track)
Definition: TrackArt.cpp:479

References TrackPanelDrawingContext::dc, DrawSyncLockTiles(), TrackArtist::Get(), Channel::GetChannelGroup(), anonymous_namespace{TrackArt.cpp}::GetProject(), SyncLock::IsSelectedOrSyncLockSelected(), ZoomInfo::TimeToPosition(), and within().

Referenced by SpectrumView::DoDraw(), WaveformView::DoDraw(), LabelTrackView::Draw(), NoteTrackAffordanceControls::Draw(), NoteTrackView::Draw(), and WaveTrackAffordanceControls::Draw().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ DrawClipAffordance()

wxRect TrackArt::DrawClipAffordance ( wxDC &  dc,
const wxRect &  clipRect,
bool  highlight = false,
bool  selected = false 
)

Definition at line 223 of file TrackArt.cpp.

225{
226 //To make sure that roundings do not overlap each other
227 auto clipFrameRadius = std::min(ClipFrameRadius, clipRect.width / 2);
228
229 std::optional<wxRect> clippedClipRect;
230 const auto affordanceRect =
231 ::GetClipAffordanceRect(dc, clipRect, clippedClipRect);
232 //Fix #1689: visual glitches appear on attempt to draw a rectangle
233 //larger than 0x7FFFFFF pixels wide (value was discovered
234 //by manual testing, and maybe depends on OS being used), but
235 //it's very unlikely that such huge rectangle will be ever fully visible
236 //on the screen, so we can safely reduce its size to be slightly larger than
237 //clipping rectangle, and avoid that problem
238 auto drawingRect = clipRect;
239 if (clippedClipRect)
240 {
241 //to make sure that rounding happends outside the clipping rectangle
242 drawingRect.SetLeft(std::max(
243 clipRect.GetLeft(),
244 clippedClipRect->GetLeft() - clipFrameRadius - 1));
245 drawingRect.SetRight(std::min(
246 clipRect.GetRight(),
247 clippedClipRect->GetRight() + clipFrameRadius + 1));
248 }
249
250 if (selected)
251 {
252 wxRect strokeRect{
253 drawingRect.x - ClipSelectionStrokeSize,
254 drawingRect.y,
255 drawingRect.width + ClipSelectionStrokeSize * 2,
256 drawingRect.height + clipFrameRadius };
257 dc.SetBrush(*wxTRANSPARENT_BRUSH);
258 AColor::UseThemeColour(&dc, clrClipAffordanceStroke, clrClipAffordanceStroke);
259 dc.DrawRoundedRectangle(strokeRect, clipFrameRadius);
260 }
261
262 AColor::UseThemeColour(&dc, highlight ? clrClipAffordanceActiveBrush : clrClipAffordanceInactiveBrush, clrClipAffordanceOutlinePen);
263 dc.DrawRoundedRectangle(
264 wxRect(
265 drawingRect.x,
266 drawingRect.y + ClipSelectionStrokeSize,
267 drawingRect.width,
268 drawingRect.height + clipFrameRadius
269 ), clipFrameRadius
270 );
271
272 return affordanceRect;
273}
int min(int a, int b)
static constexpr int ClipSelectionStrokeSize
Definition: TrackArt.cpp:38
static void UseThemeColour(wxDC *dc, int iBrush, int iPen=-1, int alpha=255)
Definition: AColor.cpp:354
static constexpr int ClipFrameRadius
Definition: TrackArt.h:24
wxRect GetClipAffordanceRect(wxDC &dc, const wxRect &clipRect, std::optional< wxRect > &clippedClipRect)
Definition: TrackArt.cpp:209

References ClipFrameRadius, ClipSelectionStrokeSize, anonymous_namespace{TrackArt.cpp}::GetClipAffordanceRect(), min(), and AColor::UseThemeColour().

Referenced by NoteTrackAffordanceControls::Draw(), and WaveTrackAffordanceControls::Draw().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ DrawClipEdges()

void TrackArt::DrawClipEdges ( wxDC &  dc,
const wxRect &  clipRect,
bool  selected = false 
)

Definition at line 309 of file TrackArt.cpp.

310{
311 dc.SetBrush(*wxTRANSPARENT_BRUSH);
312 {
313 AColor::UseThemeColour(&dc, -1, clrClipAffordanceOutlinePen);
314 AColor::Line(dc,
315 clipRect.GetLeft(), clipRect.GetTop(),
316 clipRect.GetLeft(), clipRect.GetBottom());
317 AColor::Line(dc,
318 clipRect.GetRight(), clipRect.GetTop(),
319 clipRect.GetRight(), clipRect.GetBottom());
320 }
321 if(selected)
322 {
323 if constexpr (ClipSelectionStrokeSize == 1)
324 {
325 AColor::UseThemeColour(&dc, -1, clrClipAffordanceStroke);
326 AColor::Line(dc,
327 clipRect.GetLeft() - ClipSelectionStrokeSize, clipRect.GetTop(),
328 clipRect.GetLeft() - ClipSelectionStrokeSize, clipRect.GetBottom());
329 AColor::Line(dc,
330 clipRect.GetRight() + ClipSelectionStrokeSize, clipRect.GetTop(),
331 clipRect.GetRight() + ClipSelectionStrokeSize, clipRect.GetBottom());
332 }
333 else if constexpr (ClipSelectionStrokeSize > 1)
334 {
335 AColor::UseThemeColour(&dc, clrClipAffordanceStroke, clrClipAffordanceStroke);
336 dc.DrawRectangle(wxRect(
337 clipRect.GetLeft() - ClipSelectionStrokeSize, clipRect.GetTop(),
338 ClipSelectionStrokeSize, clipRect.GetHeight()));
339 dc.DrawRectangle(wxRect(
340 clipRect.GetRight() + 1, clipRect.GetTop(),
341 ClipSelectionStrokeSize, clipRect.GetHeight()));
342 }
343 }
344}
static void Line(wxDC &dc, wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
Definition: AColor.cpp:194

References ClipSelectionStrokeSize, AColor::Line(), and AColor::UseThemeColour().

Referenced by anonymous_namespace{SpectrumView.cpp}::DrawClipSpectrum(), anonymous_namespace{WaveformView.cpp}::DrawClipWaveform(), and anonymous_namespace{NoteTrackView.cpp}::DrawNoteTrack().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ DrawClipFolded()

void TrackArt::DrawClipFolded ( wxDC &  dc,
const wxRect &  rect 
)

Definition at line 346 of file TrackArt.cpp.

347{
348 AColor::UseThemeColour(&dc, clrClipAffordanceOutlinePen);
349 dc.DrawRectangle(rect);
350}

References AColor::UseThemeColour().

Referenced by WaveTrackAffordanceControls::Draw(), anonymous_namespace{SpectrumView.cpp}::DrawClipSpectrum(), and anonymous_namespace{WaveformView.cpp}::DrawClipWaveform().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ DrawClipTitle()

bool TrackArt::DrawClipTitle ( wxDC &  dc,
const wxRect &  affordanceRect,
const wxString &  title 
)

Definition at line 289 of file TrackArt.cpp.

291{
292 if (affordanceRect.IsEmpty())
293 return false;
294 else if (title.empty())
295 return true;
296 const auto truncatedTitle = ::GetTruncatedTitle(dc, title, affordanceRect);
297 if (truncatedTitle.empty())
298 return false;
299 const auto titleRect =
300 GetClipTruncatedTitleRect(dc, affordanceRect, truncatedTitle);
301 const auto alignLeft =
302 wxTheApp->GetLayoutDirection() == wxLayout_LeftToRight;
303 dc.DrawLabel(
304 truncatedTitle, titleRect,
305 (alignLeft ? wxALIGN_LEFT : wxALIGN_RIGHT) | wxALIGN_CENTER_VERTICAL);
306 return true;
307}
static const auto title
wxString GetTruncatedTitle(wxDC &dc, const wxString &title, const wxRect &affordanceRect)
Definition: TrackArt.cpp:56
wxRect GetClipTruncatedTitleRect(wxDC &dc, const wxRect &affordanceRect, const wxString &title)
Definition: TrackArt.cpp:277

References anonymous_namespace{TrackArt.cpp}::GetClipTruncatedTitleRect(), anonymous_namespace{TrackArt.cpp}::GetTruncatedTitle(), and title.

Referenced by NoteTrackAffordanceControls::Draw(), and WaveTrackAffordanceControls::Draw().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ DrawCursor()

void TrackArt::DrawCursor ( TrackPanelDrawingContext context,
const wxRect &  rect,
const Track track 
)

Definition at line 756 of file TrackArt.cpp.

758{
759 const auto dc = &context.dc;
760 const auto artist = TrackArtist::Get(context);
761 const auto& selectedRegion = *artist->pSelectedRegion;
762
763 if (selectedRegion.isPoint())
764 {
765 const auto& zoomInfo = *artist->pZoomInfo;
766 auto x = static_cast<int>(zoomInfo.TimeToPosition(selectedRegion.t0(), rect.x));
767 if (x >= rect.GetLeft() && x <= rect.GetRight())
768 {
770 AColor::Line(*dc, x, rect.GetTop(), x, rect.GetBottom());
771 }
772 }
773}
static void CursorColor(wxDC *dc)
Definition: AColor.cpp:437

References AColor::CursorColor(), TrackPanelDrawingContext::dc, TrackArtist::Get(), AColor::Line(), and ZoomInfo::TimeToPosition().

Referenced by anonymous_namespace{TrackPanel.cpp}::ChannelStack::Draw().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ DrawNegativeOffsetTrackArrows()

void TrackArt::DrawNegativeOffsetTrackArrows ( TrackPanelDrawingContext context,
const wxRect &  rect 
)

Definition at line 143 of file TrackArt.cpp.

145{
146 auto &dc = context.dc;
147
148 // Draws two black arrows on the left side of the track to
149 // indicate the user that the track has been time-shifted
150 // to the left beyond t=0.0.
151
152 dc.SetPen(*wxBLACK_PEN);
153 AColor::Line(dc,
154 rect.x + 2, rect.y + 6,
155 rect.x + 8, rect.y + 6);
156 AColor::Line(dc,
157 rect.x + 2, rect.y + 6,
158 rect.x + 6, rect.y + 2);
159 AColor::Line(dc,
160 rect.x + 2, rect.y + 6,
161 rect.x + 6, rect.y + 10);
162 AColor::Line(dc,
163 rect.x + 2, rect.y + rect.height - 8,
164 rect.x + 8, rect.y + rect.height - 8);
165 AColor::Line(dc,
166 rect.x + 2, rect.y + rect.height - 8,
167 rect.x + 6, rect.y + rect.height - 4);
168 AColor::Line(dc,
169 rect.x + 2, rect.y + rect.height - 8,
170 rect.x + 6, rect.y + rect.height - 12);
171}

References TrackPanelDrawingContext::dc, and AColor::Line().

Referenced by anonymous_namespace{WaveformView.cpp}::DrawClipWaveform(), and anonymous_namespace{NoteTrackView.cpp}::DrawNoteTrack().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ DrawSnapLines()

void TrackArt::DrawSnapLines ( wxDC *  dc,
wxInt64  snap0,
wxInt64  snap1 
)

Definition at line 775 of file TrackArt.cpp.

776{
778 if (snap0 >= 0)
779 AColor::Line(*dc, (int)snap0, 0, (int)snap0, 30000);
780 if (snap1 >= 0)
781 AColor::Line(*dc, (int)snap1, 0, (int)snap1, 30000);
782}
static void SnapGuidePen(wxDC *dc)
Definition: AColor.cpp:462

References AColor::Line(), and AColor::SnapGuidePen().

Referenced by AdjustClipBorder::Draw(), SelectHandle::Draw(), and TimeShiftHandle::Draw().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ DrawSyncLockTiles()

void TrackArt::DrawSyncLockTiles ( TrackPanelDrawingContext context,
const wxRect &  rect 
)

Definition at line 365 of file TrackArt.cpp.

367{
368 const auto dc = &context.dc;
369
370 wxBitmap syncLockBitmap(theTheme.Image(bmpSyncLockSelTile));
371
372 // Grid spacing is a bit smaller than actual image size
373 int gridW = syncLockBitmap.GetWidth() - 6;
374 int gridH = syncLockBitmap.GetHeight() - 8;
375
376 // Horizontal position within the grid, modulo its period
377 int blockX = (rect.x / gridW) % 5;
378
379 // Amount to offset drawing of first column
380 int xOffset = rect.x % gridW;
381 if (xOffset < 0) xOffset += gridW;
382
383 // Check if we're missing an extra column to the left (this can happen
384 // because the tiles are bigger than the grid spacing)
385 bool extraCol = false;
386 if (syncLockBitmap.GetWidth() - gridW > xOffset) {
387 extraCol = true;
388 xOffset += gridW;
389 blockX = (blockX - 1) % 5;
390 }
391 // Make sure blockX is non-negative
392 if (blockX < 0) blockX += 5;
393
394 int xx = 0;
395 while (xx < rect.width) {
396 int width = syncLockBitmap.GetWidth() - xOffset;
397 if (xx + width > rect.width)
398 width = rect.width - xx;
399
400 //
401 // Draw each row in this column
402 //
403
404 // Vertical position in the grid, modulo its period
405 int blockY = (rect.y / gridH) % 5;
406
407 // Amount to offset drawing of first row
408 int yOffset = rect.y % gridH;
409 if (yOffset < 0) yOffset += gridH;
410
411 // Check if we're missing an extra row on top (this can happen because
412 // the tiles are bigger than the grid spacing)
413 bool extraRow = false;
414 if (syncLockBitmap.GetHeight() - gridH > yOffset) {
415 extraRow = true;
416 yOffset += gridH;
417 blockY = (blockY - 1) % 5;
418 }
419 // Make sure blockY is non-negative
420 if (blockY < 0) blockY += 5;
421
422 int yy = 0;
423 while (yy < rect.height)
424 {
425 int height = syncLockBitmap.GetHeight() - yOffset;
426 if (yy + height > rect.height)
427 height = rect.height - yy;
428
429 // AWD: draw blocks according to our pattern
430 if ((blockX == 0 && blockY == 0) || (blockX == 2 && blockY == 1) ||
431 (blockX == 4 && blockY == 2) || (blockX == 1 && blockY == 3) ||
432 (blockX == 3 && blockY == 4))
433 {
434
435 // Do we need to get a sub-bitmap?
436 if (width != syncLockBitmap.GetWidth() || height != syncLockBitmap.GetHeight()) {
437 wxBitmap subSyncLockBitmap =
438 syncLockBitmap.GetSubBitmap(wxRect(xOffset, yOffset, width, height));
439 dc->DrawBitmap(subSyncLockBitmap, rect.x + xx, rect.y + yy, true);
440 }
441 else {
442 dc->DrawBitmap(syncLockBitmap, rect.x + xx, rect.y + yy, true);
443 }
444 }
445
446 // Updates for next row
447 if (extraRow) {
448 // Second offset row, still at y = 0; no more extra rows
449 yOffset -= gridH;
450 extraRow = false;
451 }
452 else {
453 // Move on in y, no more offset rows
454 yy += gridH - yOffset;
455 yOffset = 0;
456 }
457 blockY = (blockY + 1) % 5;
458 }
459
460 // Updates for next column
461 if (extraCol) {
462 // Second offset column, still at x = 0; no more extra columns
463 xOffset -= gridW;
464 extraCol = false;
465 }
466 else {
467 // Move on in x, no more offset rows
468 xx += gridW - xOffset;
469 xOffset = 0;
470 }
471 blockX = (blockX + 1) % 5;
472 }
473}
THEME_API Theme theTheme
Definition: Theme.cpp:82
wxImage & Image(int iIndex)

References TrackPanelDrawingContext::dc, ThemeBase::Image(), and theTheme.

Referenced by DrawBackgroundWithSelection(), and anonymous_namespace{WaveformView.cpp}::DrawWaveformBackground().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ TruncateText()

wxString TrackArt::TruncateText ( wxDC &  dc,
const wxString &  text,
const int  maxWidth 
)

Definition at line 173 of file TrackArt.cpp.

174{
175 static const wxString ellipsis = "\u2026";
176
177 if (dc.GetTextExtent(text).GetWidth() <= maxWidth)
178 return text;
179
180 auto left = 0;
181 //no need to check text + '...'
182 auto right = static_cast<int>(text.Length() - 2);
183
184 while (left <= right)
185 {
186 auto middle = (left + right) / 2;
187 auto str = text.SubString(0, middle).Trim() + ellipsis;
188 auto strWidth = dc.GetTextExtent(str).GetWidth();
189 if (strWidth < maxWidth)
190 //if left == right (== middle), then exit loop
191 //with right equals to the last known index for which
192 //strWidth < maxWidth
193 left = middle + 1;
194 else if (strWidth > maxWidth)
195 //if right == left (== middle), then exit loop with
196 //right equals to (left - 1), which is the last known
197 //index for which (strWidth < maxWidth) or -1
198 right = middle - 1;
199 else
200 return str;
201 }
202 if (right >= 0)
203 return text.SubString(0, right).Trim() + ellipsis;
204
205 return wxEmptyString;
206}
#define str(a)

References str.

Referenced by CommonTrackInfo::CloseTitleDrawFunction(), anonymous_namespace{TrackArt.cpp}::GetTruncatedTitle(), and AButton::OnPaint().

Here is the caller graph for this function:

Variable Documentation

◆ ClipFrameRadius

constexpr int TrackArt::ClipFrameRadius { 6 }
staticconstexpr