Audacity 3.2.0
Functions | Variables
TrackArt Namespace Reference

Functions

AUDACITY_DLL_API wxRect DrawClipAffordance (wxDC &dc, const wxRect &affordanceRect, bool highlight=false, bool selected=false)
 
AUDACITY_DLL_API bool DrawClipTitle (wxDC &dc, const wxRect &titleRect, 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 Track *track, const wxBrush &selBrush, const wxBrush &unselBrush, bool useSelection=true)
 
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)
 

Variables

static constexpr int ClipFrameRadius { 6 }
 

Function Documentation

◆ DrawBackgroundWithSelection()

void TrackArt::DrawBackgroundWithSelection ( TrackPanelDrawingContext context,
const wxRect &  rect,
const Track track,
const wxBrush &  selBrush,
const wxBrush &  unselBrush,
bool  useSelection = true 
)

Definition at line 422 of file TrackArt.cpp.

426{
427 const auto dc = &context.dc;
428 const auto artist = TrackArtist::Get( context );
429 const auto &selectedRegion = *artist->pSelectedRegion;
430 const auto &zoomInfo = *artist->pZoomInfo;
431
432 //MM: Draw background. We should optimize that a bit more.
433 const double sel0 = useSelection ? selectedRegion.t0() : 0.0;
434 const double sel1 = useSelection ? selectedRegion.t1() : 0.0;
435
436 dc->SetPen(*wxTRANSPARENT_PEN);
438 {
439 // Rectangles before, within, after the selection
440 wxRect before = rect;
441 wxRect within = rect;
442 wxRect after = rect;
443
444 before.width = (int)(zoomInfo.TimeToPosition(sel0) );
445 if (before.GetRight() > rect.GetRight()) {
446 before.width = rect.width;
447 }
448
449 if (before.width > 0) {
450 dc->SetBrush(unselBrush);
451 dc->DrawRectangle(before);
452
453 within.x = 1 + before.GetRight();
454 }
455 within.width = rect.x + (int)(zoomInfo.TimeToPosition(sel1) ) - within.x -1;
456
457 if (within.GetRight() > rect.GetRight()) {
458 within.width = 1 + rect.GetRight() - within.x;
459 }
460
461 // Bug 2389 - Selection can disappear
462 // This handles case where no waveform is visible.
463 if (within.width < 1)
464 {
465 within.width = 1;
466 }
467
468 if (within.width > 0) {
469 if (track->GetSelected()) {
470 dc->SetBrush(selBrush);
471 dc->DrawRectangle(within);
472 }
473 else {
474 // Per condition above, track must be sync-lock selected
475 dc->SetBrush(unselBrush);
476 dc->DrawRectangle(within);
477 DrawSyncLockTiles( context, within );
478 }
479
480 after.x = 1 + within.GetRight();
481 }
482 else {
483 // `within` not drawn; start where it would have gone
484 after.x = within.x;
485 }
486
487 after.width = 1 + rect.GetRight() - after.x;
488 if (after.width > 0) {
489 dc->SetBrush(unselBrush);
490 dc->DrawRectangle(after);
491 }
492 }
493 else
494 {
495 // Track not selected; just draw background
496 dc->SetBrush(unselBrush);
497 dc->DrawRectangle(rect);
498 }
499}
bool within(A a, B b, DIST d)
Definition: TrackPanel.cpp:167
static bool IsSelectedOrSyncLockSelected(const Track *pTrack)
Definition: SyncLock.cpp:112
static TrackArtist * Get(TrackPanelDrawingContext &)
Definition: TrackArtist.cpp:69
bool GetSelected() const
Definition: Track.h:470
AUDACITY_DLL_API void DrawSyncLockTiles(TrackPanelDrawingContext &context, const wxRect &rect)
Definition: TrackArt.cpp:312

References TrackPanelDrawingContext::dc, DrawSyncLockTiles(), TrackArtist::Get(), Track::GetSelected(), SyncLock::IsSelectedOrSyncLockSelected(), 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 &  affordanceRect,
bool  highlight = false,
bool  selected = false 
)

Definition at line 188 of file TrackArt.cpp.

189{
190 //To make sure that roundings do not overlap each other
191 auto clipFrameRadius = std::min(ClipFrameRadius, rect.width / 2);
192
193 wxRect clipRect;
194 bool hasClipRect = dc.GetClippingBox(clipRect);
195 //Fix #1689: visual glitches appear on attempt to draw a rectangle
196 //larger than 0x7FFFFFF pixels wide (value was discovered
197 //by manual testing, and maybe depends on OS being used), but
198 //it's very unlikely that such huge rectangle will be ever fully visible
199 //on the screen, so we can safely reduce its size to be slightly larger than
200 //clipping rectangle, and avoid that problem
201 auto drawingRect = rect;
202 if (hasClipRect)
203 {
204 //to make sure that rounding happends outside the clipping rectangle
205 drawingRect.SetLeft(std::max(rect.GetLeft(), clipRect.GetLeft() - clipFrameRadius - 1));
206 drawingRect.SetRight(std::min(rect.GetRight(), clipRect.GetRight() + clipFrameRadius + 1));
207 }
208
209 if (selected)
210 {
211 wxRect strokeRect{
212 drawingRect.x - ClipSelectionStrokeSize,
213 drawingRect.y,
214 drawingRect.width + ClipSelectionStrokeSize * 2,
215 drawingRect.height + clipFrameRadius };
216 dc.SetBrush(*wxTRANSPARENT_BRUSH);
217 AColor::UseThemeColour(&dc, clrClipAffordanceStroke, clrClipAffordanceStroke);
218 dc.DrawRoundedRectangle(strokeRect, clipFrameRadius);
219 }
220
221 AColor::UseThemeColour(&dc, highlight ? clrClipAffordanceActiveBrush : clrClipAffordanceInactiveBrush, clrClipAffordanceOutlinePen);
222 dc.DrawRoundedRectangle(
223 wxRect(
224 drawingRect.x,
225 drawingRect.y + ClipSelectionStrokeSize,
226 drawingRect.width,
227 drawingRect.height + clipFrameRadius
228 ), clipFrameRadius
229 );
230
231 auto titleRect = hasClipRect ?
232 //avoid drawing text outside the clipping rectangle if possible
233 GetAffordanceTitleRect(rect.Intersect(clipRect)) :
235
236 return titleRect;
237}
int min(int a, int b)
static constexpr int ClipSelectionStrokeSize
Definition: TrackArt.cpp:25
static void UseThemeColour(wxDC *dc, int iBrush, int iPen=-1, int alpha=255)
Definition: AColor.cpp:372
static constexpr int ClipFrameRadius
Definition: TrackArt.h:22
wxRect GetAffordanceTitleRect(const wxRect &rect)
Definition: TrackArt.cpp:32

References ClipFrameRadius, ClipSelectionStrokeSize, anonymous_namespace{TrackArt.cpp}::GetAffordanceTitleRect(), 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 256 of file TrackArt.cpp.

257{
258 dc.SetBrush(*wxTRANSPARENT_BRUSH);
259 {
260 AColor::UseThemeColour(&dc, -1, clrClipAffordanceOutlinePen);
261 AColor::Line(dc,
262 clipRect.GetLeft(), clipRect.GetTop(),
263 clipRect.GetLeft(), clipRect.GetBottom());
264 AColor::Line(dc,
265 clipRect.GetRight(), clipRect.GetTop(),
266 clipRect.GetRight(), clipRect.GetBottom());
267 }
268 if(selected)
269 {
270 if constexpr (ClipSelectionStrokeSize == 1)
271 {
272 AColor::UseThemeColour(&dc, -1, clrClipAffordanceStroke);
273 AColor::Line(dc,
274 clipRect.GetLeft() - ClipSelectionStrokeSize, clipRect.GetTop(),
275 clipRect.GetLeft() - ClipSelectionStrokeSize, clipRect.GetBottom());
276 AColor::Line(dc,
277 clipRect.GetRight() + ClipSelectionStrokeSize, clipRect.GetTop(),
278 clipRect.GetRight() + ClipSelectionStrokeSize, clipRect.GetBottom());
279 }
280 else if constexpr (ClipSelectionStrokeSize > 1)
281 {
282 AColor::UseThemeColour(&dc, clrClipAffordanceStroke, clrClipAffordanceStroke);
283 dc.DrawRectangle(wxRect(
284 clipRect.GetLeft() - ClipSelectionStrokeSize, clipRect.GetTop(),
285 ClipSelectionStrokeSize, clipRect.GetHeight()));
286 dc.DrawRectangle(wxRect(
287 clipRect.GetRight() + 1, clipRect.GetTop(),
288 ClipSelectionStrokeSize, clipRect.GetHeight()));
289 }
290 }
291}
static void Line(wxDC &dc, wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
Definition: AColor.cpp:187

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 293 of file TrackArt.cpp.

294{
295 AColor::UseThemeColour(&dc, clrClipAffordanceOutlinePen);
296 dc.DrawRectangle(rect);
297}

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 &  titleRect,
const wxString &  title 
)

Definition at line 239 of file TrackArt.cpp.

240{
241 if(titleRect.IsEmpty())
242 return false;
243 if(title.empty())
244 return true;
245
246 auto truncatedTitle = TrackArt::TruncateText(dc, title, titleRect.GetWidth());
247 if (!truncatedTitle.empty())
248 {
249 auto hAlign = wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft ? wxALIGN_RIGHT : wxALIGN_LEFT;
250 dc.DrawLabel(truncatedTitle, titleRect, hAlign | wxALIGN_CENTER_VERTICAL);
251 return true;
252 }
253 return false;
254}
static const auto title
AUDACITY_DLL_API wxString TruncateText(wxDC &dc, const wxString &text, const int maxWidth)
Definition: TrackArt.cpp:153

References title, and TruncateText().

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 501 of file TrackArt.cpp.

503{
504 const auto dc = &context.dc;
505 const auto artist = TrackArtist::Get(context);
506 const auto& selectedRegion = *artist->pSelectedRegion;
507
508 if (selectedRegion.isPoint())
509 {
510 const auto& zoomInfo = *artist->pZoomInfo;
511 auto x = static_cast<int>(zoomInfo.TimeToPosition(selectedRegion.t0(), rect.x));
512 if (x >= rect.GetLeft() && x <= rect.GetRight())
513 {
515 AColor::Line(*dc, x, rect.GetTop(), x, rect.GetBottom());
516 }
517 }
518}
static void CursorColor(wxDC *dc)
Definition: AColor.cpp:463

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

Referenced by anonymous_namespace{TrackPanel.cpp}::ChannelGroup::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 123 of file TrackArt.cpp.

125{
126 auto &dc = context.dc;
127
128 // Draws two black arrows on the left side of the track to
129 // indicate the user that the track has been time-shifted
130 // to the left beyond t=0.0.
131
132 dc.SetPen(*wxBLACK_PEN);
133 AColor::Line(dc,
134 rect.x + 2, rect.y + 6,
135 rect.x + 8, rect.y + 6);
136 AColor::Line(dc,
137 rect.x + 2, rect.y + 6,
138 rect.x + 6, rect.y + 2);
139 AColor::Line(dc,
140 rect.x + 2, rect.y + 6,
141 rect.x + 6, rect.y + 10);
142 AColor::Line(dc,
143 rect.x + 2, rect.y + rect.height - 8,
144 rect.x + 8, rect.y + rect.height - 8);
145 AColor::Line(dc,
146 rect.x + 2, rect.y + rect.height - 8,
147 rect.x + 6, rect.y + rect.height - 4);
148 AColor::Line(dc,
149 rect.x + 2, rect.y + rect.height - 8,
150 rect.x + 6, rect.y + rect.height - 12);
151}

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:

◆ DrawSyncLockTiles()

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

Definition at line 312 of file TrackArt.cpp.

314{
315 const auto dc = &context.dc;
316
317 wxBitmap syncLockBitmap(theTheme.Image(bmpSyncLockSelTile));
318
319 // Grid spacing is a bit smaller than actual image size
320 int gridW = syncLockBitmap.GetWidth() - 6;
321 int gridH = syncLockBitmap.GetHeight() - 8;
322
323 // Horizontal position within the grid, modulo its period
324 int blockX = (rect.x / gridW) % 5;
325
326 // Amount to offset drawing of first column
327 int xOffset = rect.x % gridW;
328 if (xOffset < 0) xOffset += gridW;
329
330 // Check if we're missing an extra column to the left (this can happen
331 // because the tiles are bigger than the grid spacing)
332 bool extraCol = false;
333 if (syncLockBitmap.GetWidth() - gridW > xOffset) {
334 extraCol = true;
335 xOffset += gridW;
336 blockX = (blockX - 1) % 5;
337 }
338 // Make sure blockX is non-negative
339 if (blockX < 0) blockX += 5;
340
341 int xx = 0;
342 while (xx < rect.width) {
343 int width = syncLockBitmap.GetWidth() - xOffset;
344 if (xx + width > rect.width)
345 width = rect.width - xx;
346
347 //
348 // Draw each row in this column
349 //
350
351 // Vertical position in the grid, modulo its period
352 int blockY = (rect.y / gridH) % 5;
353
354 // Amount to offset drawing of first row
355 int yOffset = rect.y % gridH;
356 if (yOffset < 0) yOffset += gridH;
357
358 // Check if we're missing an extra row on top (this can happen because
359 // the tiles are bigger than the grid spacing)
360 bool extraRow = false;
361 if (syncLockBitmap.GetHeight() - gridH > yOffset) {
362 extraRow = true;
363 yOffset += gridH;
364 blockY = (blockY - 1) % 5;
365 }
366 // Make sure blockY is non-negative
367 if (blockY < 0) blockY += 5;
368
369 int yy = 0;
370 while (yy < rect.height)
371 {
372 int height = syncLockBitmap.GetHeight() - yOffset;
373 if (yy + height > rect.height)
374 height = rect.height - yy;
375
376 // AWD: draw blocks according to our pattern
377 if ((blockX == 0 && blockY == 0) || (blockX == 2 && blockY == 1) ||
378 (blockX == 4 && blockY == 2) || (blockX == 1 && blockY == 3) ||
379 (blockX == 3 && blockY == 4))
380 {
381
382 // Do we need to get a sub-bitmap?
383 if (width != syncLockBitmap.GetWidth() || height != syncLockBitmap.GetHeight()) {
384 wxBitmap subSyncLockBitmap =
385 syncLockBitmap.GetSubBitmap(wxRect(xOffset, yOffset, width, height));
386 dc->DrawBitmap(subSyncLockBitmap, rect.x + xx, rect.y + yy, true);
387 }
388 else {
389 dc->DrawBitmap(syncLockBitmap, rect.x + xx, rect.y + yy, true);
390 }
391 }
392
393 // Updates for next row
394 if (extraRow) {
395 // Second offset row, still at y = 0; no more extra rows
396 yOffset -= gridH;
397 extraRow = false;
398 }
399 else {
400 // Move on in y, no more offset rows
401 yy += gridH - yOffset;
402 yOffset = 0;
403 }
404 blockY = (blockY + 1) % 5;
405 }
406
407 // Updates for next column
408 if (extraCol) {
409 // Second offset column, still at x = 0; no more extra columns
410 xOffset -= gridW;
411 extraCol = false;
412 }
413 else {
414 // Move on in x, no more offset rows
415 xx += gridW - xOffset;
416 xOffset = 0;
417 }
418 blockX = (blockX + 1) % 5;
419 }
420}
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 153 of file TrackArt.cpp.

154{
155 static const wxString ellipsis = "\u2026";
156
157 if (dc.GetTextExtent(text).GetWidth() <= maxWidth)
158 return text;
159
160 auto left = 0;
161 //no need to check text + '...'
162 auto right = static_cast<int>(text.Length() - 2);
163
164 while (left <= right)
165 {
166 auto middle = (left + right) / 2;
167 auto str = text.SubString(0, middle).Trim() + ellipsis;
168 auto strWidth = dc.GetTextExtent(str).GetWidth();
169 if (strWidth < maxWidth)
170 //if left == right (== middle), then exit loop
171 //with right equals to the last known index for which
172 //strWidth < maxWidth
173 left = middle + 1;
174 else if (strWidth > maxWidth)
175 //if right == left (== middle), then exit loop with
176 //right equals to (left - 1), which is the last known
177 //index for which (strWidth < maxWidth) or -1
178 right = middle - 1;
179 else
180 return str;
181 }
182 if (right >= 0)
183 return text.SubString(0, right).Trim() + ellipsis;
184
185 return wxEmptyString;
186}
#define str(a)

References str.

Referenced by DrawClipTitle(), and AButton::OnPaint().

Here is the caller graph for this function:

Variable Documentation

◆ ClipFrameRadius

constexpr int TrackArt::ClipFrameRadius { 6 }
staticconstexpr