Audacity 3.2.0
Functions | Variables
TrackArt Namespace Reference

Functions

AUDACITY_DLL_API wxRect DrawClipAffordance (wxDC &dc, const wxRect &affordanceRect, const wxString &title, bool highlight=false, bool selected=false)
 
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 419 of file TrackArt.cpp.

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

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,
const wxString &  title,
bool  highlight = false,
bool  selected = false 
)

Definition at line 191 of file TrackArt.cpp.

192{
193 //To make sure that roundings do not overlap each other
194 auto clipFrameRadius = std::min(ClipFrameRadius, rect.width / 2);
195
196 wxRect clipRect;
197 bool hasClipRect = dc.GetClippingBox(clipRect);
198 //Fix #1689: visual glitches appear on attempt to draw a rectangle
199 //larger than 0x7FFFFFF pixels wide (value was discovered
200 //by manual testing, and maybe depends on OS being used), but
201 //it's very unlikely that such huge rectangle will be ever fully visible
202 //on the screen, so we can safely reduce its size to be slightly larger than
203 //clipping rectangle, and avoid that problem
204 auto drawingRect = rect;
205 if (hasClipRect)
206 {
207 //to make sure that rounding happends outside the clipping rectangle
208 drawingRect.SetLeft(std::max(rect.GetLeft(), clipRect.GetLeft() - clipFrameRadius - 1));
209 drawingRect.SetRight(std::min(rect.GetRight(), clipRect.GetRight() + clipFrameRadius + 1));
210 }
211
212 if (selected)
213 {
214 wxRect strokeRect{
215 drawingRect.x - ClipSelectionStrokeSize,
216 drawingRect.y,
217 drawingRect.width + ClipSelectionStrokeSize * 2,
218 drawingRect.height + clipFrameRadius };
219 dc.SetBrush(*wxTRANSPARENT_BRUSH);
220 AColor::UseThemeColour(&dc, clrClipAffordanceStroke, clrClipAffordanceStroke);
221 dc.DrawRoundedRectangle(strokeRect, clipFrameRadius);
222 }
223
224 AColor::UseThemeColour(&dc, highlight ? clrClipAffordanceActiveBrush : clrClipAffordanceInactiveBrush, clrClipAffordanceOutlinePen);
225 dc.DrawRoundedRectangle(
226 wxRect(
227 drawingRect.x,
228 drawingRect.y + ClipSelectionStrokeSize,
229 drawingRect.width,
230 drawingRect.height + clipFrameRadius
231 ), clipFrameRadius
232 );
233
234 auto titleRect = hasClipRect ?
235 //avoid drawing text outside the clipping rectangle if possible
236 GetAffordanceTitleRect(rect.Intersect(clipRect)) :
238
239 if (!title.empty())
240 {
241 auto truncatedTitle = TrackArt::TruncateText(dc, title, titleRect.GetWidth());
242 if (!truncatedTitle.empty())
243 {
244 auto hAlign = wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft ? wxALIGN_RIGHT : wxALIGN_LEFT;
245 dc.DrawLabel(truncatedTitle, titleRect, hAlign | wxALIGN_CENTER_VERTICAL);
246 }
247 else
248 return { };
249 }
250 return titleRect;
251}
int min(int a, int b)
static const auto title
static constexpr int ClipSelectionStrokeSize
Definition: TrackArt.cpp:25
static void UseThemeColour(wxDC *dc, int iBrush, int iPen=-1, int alpha=255)
Definition: AColor.cpp:349
AUDACITY_DLL_API wxString TruncateText(wxDC &dc, const wxString &text, const int maxWidth)
Definition: TrackArt.cpp:156
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(), title, TruncateText(), 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 253 of file TrackArt.cpp.

254{
255 dc.SetBrush(*wxTRANSPARENT_BRUSH);
256 {
257 AColor::UseThemeColour(&dc, -1, clrClipAffordanceOutlinePen);
258 AColor::Line(dc,
259 clipRect.GetLeft(), clipRect.GetTop(),
260 clipRect.GetLeft(), clipRect.GetBottom());
261 AColor::Line(dc,
262 clipRect.GetRight(), clipRect.GetTop(),
263 clipRect.GetRight(), clipRect.GetBottom());
264 }
265 if(selected)
266 {
267 if constexpr (ClipSelectionStrokeSize == 1)
268 {
269 AColor::UseThemeColour(&dc, -1, clrClipAffordanceStroke);
270 AColor::Line(dc,
271 clipRect.GetLeft() - ClipSelectionStrokeSize, clipRect.GetTop(),
272 clipRect.GetLeft() - ClipSelectionStrokeSize, clipRect.GetBottom());
273 AColor::Line(dc,
274 clipRect.GetRight() + ClipSelectionStrokeSize, clipRect.GetTop(),
275 clipRect.GetRight() + ClipSelectionStrokeSize, clipRect.GetBottom());
276 }
277 else if constexpr (ClipSelectionStrokeSize > 1)
278 {
279 AColor::UseThemeColour(&dc, clrClipAffordanceStroke, clrClipAffordanceStroke);
280 dc.DrawRectangle(wxRect(
281 clipRect.GetLeft() - ClipSelectionStrokeSize, clipRect.GetTop(),
282 ClipSelectionStrokeSize, clipRect.GetHeight()));
283 dc.DrawRectangle(wxRect(
284 clipRect.GetRight() + 1, clipRect.GetTop(),
285 ClipSelectionStrokeSize, clipRect.GetHeight()));
286 }
287 }
288}
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 290 of file TrackArt.cpp.

291{
292 AColor::UseThemeColour(&dc, clrClipAffordanceOutlinePen);
293 dc.DrawRectangle(rect);
294}

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:

◆ DrawCursor()

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

Definition at line 498 of file TrackArt.cpp.

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

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

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

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

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

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

References str.

Referenced by DrawClipAffordance().

Here is the caller graph for this function:

Variable Documentation

◆ ClipFrameRadius

constexpr int TrackArt::ClipFrameRadius { 6 }
staticconstexpr