Audacity 3.2.0
AColor.cpp
Go to the documentation of this file.
1
2/**********************************************************************
3
4 Audacity: A Digital Audio Editor
5
6 AColor.cpp
7
8 Dominic Mazzoni
9
10
11********************************************************************//********************************************************************/
19
20#include "AColor.h"
21#include "AColorResources.h"
22
23#include <wx/colour.h>
24#include <wx/dc.h>
25#include <wx/dcmemory.h>
26#include <wx/graphics.h>
27#include <wx/settings.h>
28#include <wx/utils.h>
29
30#include "AllThemeResources.h"
31#include "Theme.h"
32
33bool AColor::inited = false;
34wxBrush AColor::lightBrush[2];
35wxBrush AColor::mediumBrush[2];
36wxBrush AColor::darkBrush[2];
37wxPen AColor::lightPen[2];
38wxPen AColor::mediumPen[2];
39wxPen AColor::darkPen[2];
40
42wxBrush AColor::indicatorBrush[2];
44// wxPen AColor::playRegionPen[2];
46
47wxBrush AColor::muteBrush[2];
48wxBrush AColor::soloBrush;
49
51
55
67
70
71// The spare pen and brush possibly help us cut down on the
72// number of pens and brushes we need.
74wxBrush AColor::spareBrush;
75
76wxPen AColor::uglyPen;
77wxBrush AColor::uglyBrush;
78
79namespace
80{
81 //Simplified variation of nine patch scale drawing
82 //https://en.wikipedia.org/wiki/9-slice_scaling
83 //Bitmap and rect expected to have at least 3px in both directions
84 void DrawNinePatch(wxDC& dc, wxBitmap& bitmap, const wxRect& r)
85 {
86 wxMemoryDC memDC;
87 memDC.SelectObject(bitmap);
88
89 // image slices
90
91 const auto uw0 = bitmap.GetWidth() / 2;
92 const auto uw1 = 1;
93 const auto uw2 = bitmap.GetWidth() - uw0 - uw1;
94
95 const auto vh0 = bitmap.GetHeight() / 2;
96 const auto vh1 = 1;
97 const auto vh2 = bitmap.GetHeight() - vh1 - vh0;
98
99 const auto u0 = 0;
100 const auto u1 = uw0;
101 const auto u2 = uw0 + uw1;
102
103 const auto v0 = 0;
104 const auto v1 = vh0;
105 const auto v2 = vh0 + vh1;
106
107 //Button geometry
108
109 const auto xw0 = std::min(uw0, r.width / 2);
110 const auto xw2 = std::min(uw2, r.width / 2);
111 const auto xw1 = r.width - xw0 - xw2;
112
113 const auto yh0 = std::min(vh0, r.height / 2);
114 const auto yh2 = std::min(vh2, r.height / 2);
115 const auto yh1 = r.height - yh0 - yh2;
116
117 const auto x0 = r.x;
118 const auto x1 = r.x + xw0;
119 const auto x2 = r.x + xw0 + xw1;
120
121 const auto y0 = r.y;
122 const auto y1 = r.y + yh0;
123 const auto y2 = r.y + yh0 + yh1;
124
125 dc.StretchBlit(x0, y0, xw0, yh0, &memDC, u0, v0, uw0, vh0, wxCOPY, true);
126 dc.StretchBlit(x1, y0, xw1, yh0, &memDC, u1, v0, uw1, vh0, wxCOPY, true);
127 dc.StretchBlit(x2, y0, xw2, yh0, &memDC, u2, v0, uw2, vh0, wxCOPY, true);
128
129 dc.StretchBlit(x0, y1, xw0, yh1, &memDC, u0, v1, uw0, vh1, wxCOPY, true);
130 dc.StretchBlit(x1, y1, xw1, yh1, &memDC, u1, v1, uw1, vh1, wxCOPY, true);
131 dc.StretchBlit(x2, y1, xw2, yh1, &memDC, u2, v1, uw2, vh1, wxCOPY, true);
132
133 dc.StretchBlit(x0, y2, xw0, yh2, &memDC, u0, v2, uw0, vh2, wxCOPY, true);
134 dc.StretchBlit(x1, y2, xw1, yh2, &memDC, u1, v2, uw1, vh2, wxCOPY, true);
135 dc.StretchBlit(x2, y2, xw2, yh2, &memDC, u2, v2, uw2, vh2, wxCOPY, true);
136 }
137
138 int GetButtonImageIndex(bool up, bool selected, bool highlight)
139 {
140 // There are eight button states in the TCP.
141 // A theme might not differentiate among them all. That's up to
142 // the theme designer.
143 // Button highlighted (i.e. hovered over) or not.
144 // Track selected or not
145 // Button up or down.
146 // Highlight in most themes is lighter than not highlighted.
147 if ( highlight && selected)
148 return up ? bmpHiliteUpButtonExpandSel : bmpHiliteButtonExpandSel;
149 if ( highlight )
150 return up ? bmpHiliteUpButtonExpand : bmpHiliteButtonExpand;
151 if( selected )
152 return up ? bmpUpButtonExpandSel : bmpDownButtonExpandSel;
153 return up ? bmpUpButtonExpand : bmpDownButtonExpand;
154 }
155}
156
157//
158// Draw an upward or downward pointing arrow.
159//
160void AColor::Arrow(wxDC & dc, wxCoord x, wxCoord y, int width, bool down)
161{
162 if (width & 0x01) {
163 width--;
164 }
165
166 wxPoint pt[3];
167 int half = width / 2;
168
169 if (down) {
170 pt[0].x = 0; pt[0].y = 0;
171 pt[1].x = width; pt[1].y = 0;
172 pt[2].x = half; pt[2].y = half;
173 }
174 else {
175 pt[0].x = 0; pt[0].y = half;
176 pt[1].x = half; pt[1].y = 0;
177 pt[2].x = width; pt[2].y = half;
178 }
179
180 dc.DrawPolygon(3, pt, x, y);
181}
182
183//
184// Draw a line, inclusive of endpoints,
185// compensating for differences in wxWidgets versions across platforms
186//
187void AColor::Line(wxDC & dc, wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
188{
189 const wxPoint points[] { { x1, y1 }, { x2, y2 } };
190 Lines( dc, 2, points );
191}
192
193// Draw lines, INCLUSIVE of all endpoints
194void AColor::Lines(wxDC &dc, size_t nPoints, const wxPoint points[])
195{
196 if ( nPoints <= 1 ) {
197 if (nPoints == 1)
198 dc.DrawPoint( points[0] );
199 return;
200 }
201
202 for (size_t ii = 0; ii < nPoints - 1; ++ii) {
203 const auto &p1 = points[ii];
204 const auto &p2 = points[ii + 1];
205
206 // As of 2.8.9 (possibly earlier), wxDC::DrawLine() on the Mac draws the
207 // last point since it is now based on the NEW wxGraphicsContext system.
208 // Make the other platforms do the same thing since the other platforms
209 // "may" follow they get wxGraphicsContext going.
210
211 // PRL: as of 3.1.1, I still observe that on Mac, the last point is
212 // included, contrary to what documentation says. Also that on Windows,
213 // sometimes it is the first point that is excluded.
214
215#if defined(__WXMAC__) || defined(__WXGTK3__)
216 dc.DrawLine(p1, p2);
217#else
218 dc.DrawPoint(p1);
219 if ( p1 != p2 ) {
220 dc.DrawLine(p1, p2);
221 }
222#endif
223 }
224
225#if defined(__WXMAC__) || defined(__WXGTK3__)
226 ;
227#else
228 dc.DrawPoint( points[ nPoints - 1 ] );
229#endif
230}
231
232//
233// Draws a focus rectangle (Taken directly from wxWidgets source)
234//
235void AColor::DrawFocus(wxDC & dc, wxRect & rect)
236{
237 // draw the pixels manually: note that to behave in the same manner as
238 // DrawRect(), we must exclude the bottom and right borders from the
239 // rectangle
240 wxCoord x1 = rect.GetLeft(),
241 y1 = rect.GetTop(),
242 x2 = rect.GetRight(),
243 y2 = rect.GetBottom();
244
245 // -1 for brush, so it just sets the pen colour, and does not change the brush.
246 UseThemeColour( &dc, -1, clrTrackPanelText );
247
248 wxCoord z;
249 for ( z = x1 + 1; z < x2; z += 2 )
250 dc.DrawPoint(z, y1);
251
252 wxCoord shift = z == x2 ? 0 : 1;
253 for ( z = y1 + shift; z < y2; z += 2 )
254 dc.DrawPoint(x2, z);
255
256 shift = z == y2 ? 0 : 1;
257 for ( z = x2 - shift; z > x1; z -= 2 )
258 dc.DrawPoint(z, y2);
259
260 shift = z == x1 ? 0 : 1;
261 for ( z = y2 - shift; z > y1; z -= 2 )
262 dc.DrawPoint(x1, z);
263
264}
265
266void AColor::Bevel(wxDC & dc, bool up, const wxRect & r)
267{
268 if (up)
269 AColor::Light(&dc, false);
270 else
271 AColor::Dark(&dc, false);
272
273 AColor::Line(dc, r.x, r.y, r.x + r.width, r.y);
274 AColor::Line(dc, r.x, r.y, r.x, r.y + r.height);
275
276 if (!up)
277 AColor::Light(&dc, false);
278 else
279 AColor::Dark(&dc, false);
280
281 AColor::Line(dc, r.x + r.width, r.y, r.x + r.width, r.y + r.height);
282 AColor::Line(dc, r.x, r.y + r.height, r.x + r.width, r.y + r.height);
283}
284
285void AColor::ButtonStretch(wxDC& dc, bool up, const wxRect& r, bool selected, bool highlight)
286{
288 dc,
289 theTheme.Bitmap(GetButtonImageIndex(up, selected, highlight)),
290 r
291 );
292}
293
294void AColor::Bevel2(wxDC & dc, bool up, const wxRect & r, bool bSel, bool bHighlight)
295{
296 auto& Bmp = theTheme.Bitmap( GetButtonImageIndex(up, bSel, bHighlight) );
297 wxMemoryDC memDC;
298 memDC.SelectObject(Bmp);
299
300 int h = std::min(r.height, Bmp.GetHeight());
301
302 dc.Blit( r.x,r.y,r.width/2, h, &memDC, 0, 0, wxCOPY, true );
303 int r2 = r.width - r.width/2;
304 dc.Blit( r.x+r.width/2,r.y,r2, h, &memDC,
305 Bmp.GetWidth() - r2, 0, wxCOPY, true );
306}
307
308void AColor::DrawHStretch(wxDC& dc, const wxRect& rect, wxBitmap& bitmap)
309{
310 wxMemoryDC srcDC;
311 srcDC.SelectObject(bitmap);
312
313 const auto sh = bitmap.GetHeight();
314 const auto dh = rect.height;
315 const auto w0 = std::min((bitmap.GetWidth() - 1) / 2, rect.width / 2);
316 const auto dx0 = rect.x;
317 const auto dx1 = rect.x + w0;
318 const auto dx2 = rect.x + rect.width - w0;
319
320 dc.StretchBlit(dx0, rect.y, w0, dh, &srcDC, 0, 0, w0, sh);
321 dc.StretchBlit(dx1, rect.y, rect.width - w0 * 2, dh, &srcDC, w0, 0, 1, sh);
322 dc.StretchBlit(dx2, rect.y, w0, dh, &srcDC, bitmap.GetWidth() - w0, 0, w0, sh);
323}
324
325void AColor::DrawFrame(wxDC& dc, const wxRect& r, wxBitmap& bitmap)
326{
327 DrawNinePatch(dc, bitmap, r);
328}
329
330
331wxColour AColor::Blend( const wxColour & c1, const wxColour & c2 )
332{
333 wxColour c3(
334 (c1.Red() + c2.Red())/2,
335 (c1.Green() + c2.Green())/2,
336 (c1.Blue() + c2.Blue())/2);
337 return c3;
338}
339
340void AColor::BevelTrackInfo(wxDC & dc, bool up, const wxRect & r, bool highlight)
341{
342#ifndef EXPERIMENTAL_THEMING
343 Bevel( dc, up, r );
344#else
345 // Note that the actually drawn rectangle extends one pixel right of and
346 // below the given
347
348 wxColour col;
349 col = Blend( theTheme.Colour( clrTrackInfo ), up ? wxColour( 255,255,255):wxColour(0,0,0));
350
351 wxPen pen( highlight ? uglyPen : col );
352 dc.SetPen( pen );
353
354 dc.DrawLine(r.x, r.y, r.x + r.width, r.y);
355 dc.DrawLine(r.x, r.y, r.x, r.y + r.height);
356
357 col = Blend( theTheme.Colour( clrTrackInfo ), up ? wxColour(0,0,0): wxColour(255,255,255));
358
359 pen.SetColour( col );
360 dc.SetPen( highlight ? uglyPen : pen );
361
362 dc.DrawLine(r.x + r.width, r.y, r.x + r.width, r.y + r.height);
363 dc.DrawLine(r.x, r.y + r.height, r.x + r.width, r.y + r.height);
364#endif
365}
366
367// Set colour of and select brush and pen.
368// Use -1 to omit brush or pen.
369// If pen omitted, then the same colour as the brush will be used.
370// alpha for the brush is normally 255, but if set will make a difference
371// on mac (only) currently.
372void AColor::UseThemeColour( wxDC * dc, int iBrush, int iPen, int alpha )
373{
374 if (!inited)
375 Init();
376 // do nothing if no colours set.
377 if( (iBrush == -1) && ( iPen ==-1))
378 return;
379 wxColour col = wxColour(0,0,0);
380 if( iBrush !=-1 ){
381 col = theTheme.Colour( iBrush );
382 col.Set( col.Red(), col.Green(), col.Blue(), alpha);
383 spareBrush.SetColour( col );
384 dc->SetBrush( spareBrush );
385 }
386 if( iPen != -1)
387 col = theTheme.Colour( iPen );
388 sparePen.SetColour( col );
389 dc->SetPen( sparePen );
390}
391
392void AColor::UseThemeColour( wxGraphicsContext * gc, int iBrush, int iPen, int alpha )
393{
394 if (!inited)
395 Init();
396 // do nothing if no colours set.
397 if( (iBrush == -1) && ( iPen ==-1))
398 return;
399 wxColour col = wxColour(0,0,0);
400 if( iBrush !=-1 ){
401 col = theTheme.Colour( iBrush );
402 col.Set( col.Red(), col.Green(), col.Blue(), alpha);
403 spareBrush.SetColour( col );
404 gc->SetBrush( spareBrush );
405 }
406 if( iPen != -1)
407 col = theTheme.Colour( iPen );
408 sparePen.SetColour( col );
409 gc->SetPen( sparePen );
410}
411
412
413void AColor::Light(wxDC * dc, bool selected, bool highlight)
414{
415 if (!inited)
416 Init();
417 int index = (int) selected;
418 auto &brush = highlight ? AColor::uglyBrush : lightBrush[index];
419 dc->SetBrush( brush );
420 auto &pen = highlight ? AColor::uglyPen : lightPen[index];
421 dc->SetPen( pen );
422}
423
424void AColor::Medium(wxDC * dc, bool selected)
425{
426 if (!inited)
427 Init();
428 int index = (int) selected;
429 dc->SetBrush(mediumBrush[index]);
430 dc->SetPen(mediumPen[index]);
431}
432
433void AColor::MediumTrackInfo(wxDC * dc, bool selected)
434{
435#ifdef EXPERIMENTAL_THEMING
436 UseThemeColour( dc, selected ? clrTrackInfoSelected : clrTrackInfo );
437#else
438 Medium( dc, selected );
439#endif
440}
441
442
443void AColor::Dark(wxDC * dc, bool selected, bool highlight)
444{
445 if (!inited)
446 Init();
447 int index = (int) selected;
448 auto &brush = highlight ? AColor::uglyBrush : darkBrush[index];
449 dc->SetBrush( brush );
450 auto &pen = highlight ? AColor::uglyPen : darkPen[index];
451 dc->SetPen( pen );
452}
453
454void AColor::TrackPanelBackground(wxDC * dc, bool selected)
455{
456#ifdef EXPERIMENTAL_THEMING
457 UseThemeColour( dc, selected ? clrMediumSelected : clrTrackBackground );
458#else
459 Dark( dc, selected );
460#endif
461}
462
463void AColor::CursorColor(wxDC * dc)
464{
465 if (!inited)
466 Init();
467
468 dc->SetLogicalFunction(wxCOPY);
469 dc->SetPen(cursorPen);
470}
471
472void AColor::IndicatorColor(wxDC * dc, bool bIsNotRecording)
473{
474 if (!inited)
475 Init();
476 int index = (int) bIsNotRecording;
477 dc->SetPen(indicatorPen[index]);
478 dc->SetBrush(indicatorBrush[index]);
479}
480
481void AColor::TrackFocusPen(wxDC * dc, int level)
482{
483 if (!inited)
484 Init();
485 dc->SetPen(trackFocusPens[level]);
486}
487
488void AColor::SnapGuidePen(wxDC * dc)
489{
490 if (!inited)
491 Init();
492 dc->SetPen(snapGuidePen);
493}
494
495void AColor::Mute(wxDC * dc, bool on, bool selected, bool soloing)
496{
497 if (!inited)
498 Init();
499 int index = (int) selected;
500 if (on) {
501 dc->SetPen(*wxBLACK_PEN);
502 dc->SetBrush(muteBrush[(int) soloing]);
503 }
504 else {
505 dc->SetPen(*wxTRANSPARENT_PEN);
506 dc->SetBrush(mediumBrush[index]);
507 }
508}
509
510void AColor::Solo(wxDC * dc, bool on, bool selected)
511{
512 if (!inited)
513 Init();
514 int index = (int) selected;
515 if (on) {
516 dc->SetPen(*wxBLACK_PEN);
517 dc->SetBrush(soloBrush);
518 }
519 else {
520 dc->SetPen(*wxTRANSPARENT_PEN);
521 dc->SetBrush(mediumBrush[index]);
522 }
523}
524
526
528{
529 inited=false;
530 Init();
533}
534
535wxColour InvertOfColour( const wxColour & c )
536{
537 return wxColour( 255-c.Red(), 255-c.Green(), 255-c.Blue() );
538}
539
540// Fix up the cursor colour, if it is 'unacceptable'.
541// Unacceptable if it is too close to the background colour.
542wxColour CursorColour( )
543{
544 wxColour cCursor = theTheme.Colour( clrCursorPen );
545 wxColour cBack = theTheme.Colour( clrMedium );
546
547 int d = theTheme.ColourDistance( cCursor, cBack );
548
549 // Pen colour is fine, if there is plenty of contrast.
550 if( d > 200 )
551 return theTheme.Colour( clrCursorPen );
552
553 // otherwise return same colour as a selection.
554 return theTheme.Colour( clrSelected );
555}
556
558{
559 if (inited)
560 return;
561
562 wxColour light = theTheme.Colour( clrLight );
563 // wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT);
564 wxColour med = theTheme.Colour( clrMedium );
565 // wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
566 wxColour dark = theTheme.Colour( clrDark );
567 // wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW);
568
569 wxColour lightSelected = theTheme.Colour( clrLightSelected );
570 wxColour medSelected = theTheme.Colour( clrMediumSelected );
571 wxColour darkSelected = theTheme.Colour( clrDarkSelected );
572
573
574 clippingPen.SetColour(0xCC, 0x11, 0x00);
575
576 theTheme.SetPenColour( envelopePen, clrEnvelope );
577 theTheme.SetPenColour( WideEnvelopePen, clrEnvelope );
578 theTheme.SetBrushColour( envelopeBrush, clrEnvelope );
579
580 WideEnvelopePen.SetWidth( 3 );
581
582 theTheme.SetBrushColour( labelTextNormalBrush, clrLabelTextNormalBrush );
583 theTheme.SetBrushColour( labelTextEditBrush, clrLabelTextEditBrush );
584 theTheme.SetBrushColour( labelUnselectedBrush, clrLabelUnselectedBrush );
585 theTheme.SetBrushColour( labelSelectedBrush, clrLabelSelectedBrush );
587 theTheme.SetPenColour( labelUnselectedPen, clrLabelUnselectedPen );
588 theTheme.SetPenColour( labelSelectedPen, clrLabelSelectedPen );
589 theTheme.SetPenColour( labelSyncLockSelPen, clrSyncLockSel );
590 theTheme.SetPenColour( labelSurroundPen, clrLabelSurroundPen );
591
592 // These colors were modified to avoid using reserved colors red and green
593 // for the buttons.
594 theTheme.SetBrushColour( muteBrush[0], clrMuteButtonActive);
595 theTheme.SetBrushColour( muteBrush[1], clrMuteButtonVetoed);
596 theTheme.SetBrushColour( soloBrush, clrMuteButtonActive);
597
598 cursorPen.SetColour( CursorColour() );
599 theTheme.SetPenColour( indicatorPen[0], clrRecordingPen);
600 theTheme.SetPenColour( indicatorPen[1], clrPlaybackPen);
601 theTheme.SetBrushColour( indicatorBrush[0], clrRecordingBrush);
602 theTheme.SetBrushColour( indicatorBrush[1], clrPlaybackBrush);
603
604 theTheme.SetBrushColour( playRegionBrush[0],clrRulerRecordingBrush);
605 // theTheme.SetPenColour( playRegionPen[0], clrRulerRecordingPen);
606 // theTheme.SetBrushColour( playRegionBrush[1],clrRulerPlaybackBrush);
607 // theTheme.SetPenColour( playRegionPen[1], clrRulerPlaybackPen);
608
609 //Determine tooltip color
610 tooltipPen.SetColour( wxSystemSettingsNative::GetColour(wxSYS_COLOUR_INFOTEXT) );
611 tooltipBrush.SetColour( wxSystemSettingsNative::GetColour(wxSYS_COLOUR_INFOBK) );
612
613 uglyPen.SetColour( wxColour{ 0, 255, 0 } ); // saturated green
614 uglyBrush.SetColour( wxColour{ 255, 0, 255 } ); // saturated magenta
615
616 // A tiny gradient of yellow surrounding the current focused track
617 theTheme.SetPenColour( trackFocusPens[0], clrTrackFocus0);
618 theTheme.SetPenColour( trackFocusPens[1], clrTrackFocus1);
619 theTheme.SetPenColour( trackFocusPens[2], clrTrackFocus2);
620
621 // A vertical line indicating that the selection or sliding has
622 // been snapped to the nearest boundary.
623 theTheme.SetPenColour( snapGuidePen, clrSnapGuide);
624
625 // unselected
626 lightBrush[0].SetColour(light);
627 mediumBrush[0].SetColour(med);
628 darkBrush[0].SetColour(dark);
629 lightPen[0].SetColour(light);
630 mediumPen[0].SetColour(med);
631 darkPen[0].SetColour(dark);
632
633 // selected
634 lightBrush[1].SetColour(lightSelected);
635 mediumBrush[1].SetColour(medSelected);
636 darkBrush[1].SetColour(darkSelected);
637 lightPen[1].SetColour(lightSelected);
638 mediumPen[1].SetColour(medSelected);
639 darkPen[1].SetColour(darkSelected);
640
641 inited = true;
642}
643
644// These colours are chosen so that black text shows up OK on them.
645const int AColor_midicolors[16][3] = {
646 {255, 102, 102}, // 1=salmon
647 {204, 0, 0}, // 2=red
648 {255, 117, 23}, // 3=orange
649 {255, 255, 0}, // 4=yellow
650 {0, 204, 0}, // 5=green
651 {0, 204, 204}, // 6=turquoise
652 {125, 125, 255}, // 7=blue
653 {153, 0, 255}, // 8=blue-violet
654
655 {140, 97, 54}, // 9=brown
656 {120, 120, 120}, // 10=gray (drums)
657 {255, 175, 40}, // 11=lt orange
658 {102, 255, 102}, // 12=lt green
659 {153, 255, 255}, // 13=lt turquoise
660 {190, 190, 255}, // 14=lt blue
661 {204, 102, 255}, // 15=lt blue-violet
662 {255, 51, 204} // 16=lt red-violet
663};
664
665void AColor::MIDIChannel(wxDC * dc, int channel /* 1 - 16 */ )
666{
667 if (channel >= 1 && channel <= 16) {
668 const int *colors = AColor_midicolors[channel - 1];
669
670 dc->SetPen(wxPen(wxColour(colors[0],
671 colors[1], colors[2]), 1, wxPENSTYLE_SOLID));
672 dc->SetBrush(wxBrush(wxColour(colors[0],
673 colors[1], colors[2]), wxBRUSHSTYLE_SOLID));
674 } else {
675 dc->SetPen(wxPen(wxColour(153, 153, 153), 1, wxPENSTYLE_SOLID));
676 dc->SetBrush(wxBrush(wxColour(153, 153, 153), wxBRUSHSTYLE_SOLID));
677 }
678
679}
680
681void AColor::LightMIDIChannel(wxDC * dc, int channel /* 1 - 16 */ )
682{
683 if (channel >= 1 && channel <= 16) {
684 const int *colors = AColor_midicolors[channel - 1];
685
686 dc->SetPen(wxPen(wxColour(127 + colors[0] / 2,
687 127 + colors[1] / 2,
688 127 + colors[2] / 2), 1, wxPENSTYLE_SOLID));
689 dc->SetBrush(wxBrush(wxColour(127 + colors[0] / 2,
690 127 + colors[1] / 2,
691 127 + colors[2] / 2), wxBRUSHSTYLE_SOLID));
692 } else {
693 dc->SetPen(wxPen(wxColour(204, 204, 204), 1, wxPENSTYLE_SOLID));
694 dc->SetBrush(wxBrush(wxColour(204, 204, 204), wxBRUSHSTYLE_SOLID));
695 }
696
697}
698
699void AColor::DarkMIDIChannel(wxDC * dc, int channel /* 1 - 16 */ )
700{
701 if (channel >= 1 && channel <= 16) {
702 const int *colors = AColor_midicolors[channel - 1];
703
704 dc->SetPen(wxPen(wxColour(colors[0] / 2,
705 colors[1] / 2,
706 colors[2] / 2), 1, wxPENSTYLE_SOLID));
707 dc->SetBrush(wxBrush(wxColour(colors[0] / 2,
708 colors[1] / 2,
709 colors[2] / 2), wxBRUSHSTYLE_SOLID));
710 } else {
711 dc->SetPen(wxPen(wxColour(102, 102, 102), 1, wxPENSTYLE_SOLID));
712 dc->SetBrush(wxBrush(wxColour(102, 102, 102), wxBRUSHSTYLE_SOLID));
713 }
714
715}
716
717
718
719unsigned char AColor::gradient_pre[ColorGradientTotal][colorSchemes][gradientSteps][3];
720
722 if (gradient_inited) return;
723 gradient_inited = 1;
724
725 // Keep in correspondence with enum SpectrogramSettings::ColorScheme
726
727 // colorScheme 0: Color (New)
728 std::copy_n(&specColormap[0][0], gradientSteps * 3, &gradient_pre[ColorGradientUnselected][0][0][0]);
729 std::copy_n(&selColormap[0][0], gradientSteps * 3, &gradient_pre[ColorGradientTimeSelected][0][0][0]);
731 std::fill_n(&gradient_pre[ColorGradientEdge][0][0][0], gradientSteps * 3, 0);
732
733
734 for (int selected = 0; selected < ColorGradientTotal; selected++) {
735 // Get color scheme from Theme
736 const int gsteps = 4;
737 float gradient[gsteps + 1][3];
738 theTheme.Colour( clrSpectro1 ) = theTheme.Colour( clrUnselected );
739 theTheme.Colour( clrSpectro1Sel ) = theTheme.Colour( clrSelected );
740 int clrFirst = (selected == ColorGradientUnselected ) ? clrSpectro1 : clrSpectro1Sel;
741 for(int j=0;j<(gsteps+1);j++){
742 wxColour c = theTheme.Colour( clrFirst+j );
743 gradient[ j] [0] = c.Red()/255.0;
744 gradient[ j] [1] = c.Green()/255.0;
745 gradient[ j] [2] = c.Blue()/255.0;
746 }
747
748 // colorScheme 1: Color (from theme)
749 for (int i = 0; i<gradientSteps; i++) {
750 float r, g, b;
751 float value = float(i)/gradientSteps;
752
753 int left = (int)(value * gsteps);
754 int right = (left == gsteps ? gsteps : left + 1);
755
756 float rweight = (value * gsteps) - left;
757 float lweight = 1.0 - rweight;
758
759 r = (gradient[left][0] * lweight) + (gradient[right][0] * rweight);
760 g = (gradient[left][1] * lweight) + (gradient[right][1] * rweight);
761 b = (gradient[left][2] * lweight) + (gradient[right][2] * rweight);
762
763 switch (selected) {
765 // not dimmed
766 break;
767
769 float temp;
770 temp = r;
771 r = g;
772 g = b;
773 b = temp;
774 break;
775
777 // partly dimmed
778 r *= 0.75f;
779 g *= 0.75f;
780 b *= 0.75f;
781 break;
782
783
784 // For now edge colour is just black (or white if grey-scale)
785 // Later we might invert or something else funky.
787 // fully dimmed
788 r = 0;
789 g = 0;
790 b = 0;
791 break;
792 }
793 gradient_pre[selected][1][i][0] = (unsigned char) (255 * r);
794 gradient_pre[selected][1][i][1] = (unsigned char) (255 * g);
795 gradient_pre[selected][1][i][2] = (unsigned char) (255 * b);
796 }
797
798 // colorScheme 3: Inverse Grayscale
799 for (int i = 0; i < gradientSteps; i++) {
800 float r, g, b;
801 float value = float(i) / gradientSteps;
802
803 r = g = b = value;
804
805 switch (selected) {
807 // not dimmed
808 break;
809
811 // else fall through to SAME grayscale colour as normal selection.
812 // The white lines show it up clearly enough.
813
815 // partly dimmed
816 r = r * 0.75f + 0.25f;
817 g = g * 0.75f + 0.25f;
818 b = b * 0.75f + 0.25f;
819 break;
820
822 r = 1.0f;
823 g = 1.0f;
824 b = 1.0f;
825 break;
826 }
827 gradient_pre[selected][3][i][0] = (unsigned char)(255 * r);
828 gradient_pre[selected][3][i][1] = (unsigned char)(255 * g);
829 gradient_pre[selected][3][i][2] = (unsigned char)(255 * b);
830 }
831
832 // colorScheme 2: Grayscale (=Old grayscale)
833 for (int i = 0; i<gradientSteps; i++) {
834 float r, g, b;
835 float value = float(i)/gradientSteps;
836
837 r = g = b = 0.84 - 0.84 * value;
838
839 switch (selected) {
841 // not dimmed
842 break;
843
845 // else fall through to SAME grayscale colour as normal selection.
846 // The white lines show it up clearly enough.
847
849 // partly dimmed
850 r *= 0.75f;
851 g *= 0.75f;
852 b *= 0.75f;
853 break;
854
855
856 // For now edge colour is just black (or white if grey-scale)
857 // Later we might invert or something else funky.
859 // fully dimmed
860 r = 1.0f;
861 g = 1.0f;
862 b = 1.0f;
863 break;
864 }
865 gradient_pre[selected][2][i][0] = (unsigned char) (255 * r);
866 gradient_pre[selected][2][i][1] = (unsigned char) (255 * g);
867 gradient_pre[selected][2][i][2] = (unsigned char) (255 * b);
868 }
869 }
870}
871
873{
874 ReInit();
875 theTheme.Publish({});
876}
wxColour InvertOfColour(const wxColour &c)
Definition: AColor.cpp:535
wxColour CursorColour()
Definition: AColor.cpp:542
const int AColor_midicolors[16][3]
Definition: AColor.cpp:645
const unsigned char specColormap[256][3]
const unsigned char freqSelColormap[256][3]
const unsigned char selColormap[256][3]
int min(int a, int b)
THEME_API Theme theTheme
Definition: Theme.cpp:82
static wxBrush mediumBrush[2]
Definition: AColor.h:98
static void Arrow(wxDC &dc, wxCoord x, wxCoord y, int width, bool down=true)
Definition: AColor.cpp:160
static wxBrush labelSelectedBrush
Definition: AColor.h:122
static wxBrush darkBrush[2]
Definition: AColor.h:99
static void Solo(wxDC *dc, bool on, bool selected)
Definition: AColor.cpp:510
static void Bevel2(wxDC &dc, bool up, const wxRect &r, bool bSel=false, bool bHighlight=false)
Definition: AColor.cpp:294
static wxPen trackFocusPens[3]
Definition: AColor.h:129
static wxPen clippingPen
Definition: AColor.h:113
static wxPen WideEnvelopePen
Definition: AColor.h:116
static void IndicatorColor(wxDC *dc, bool bIsNotRecording)
Definition: AColor.cpp:472
static wxPen sparePen
Definition: AColor.h:145
static void Mute(wxDC *dc, bool on, bool selected, bool soloing)
Definition: AColor.cpp:495
static void Line(wxDC &dc, wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
Definition: AColor.cpp:187
@ ColorGradientTotal
Definition: AColor.h:34
@ ColorGradientUnselected
Definition: AColor.h:29
@ ColorGradientTimeAndFrequencySelected
Definition: AColor.h:31
@ ColorGradientEdge
Definition: AColor.h:32
@ ColorGradientTimeSelected
Definition: AColor.h:30
static wxColour Blend(const wxColour &c1, const wxColour &c2)
Definition: AColor.cpp:331
static void PreComputeGradient()
Definition: AColor.cpp:721
static wxBrush uglyBrush
Definition: AColor.h:142
static bool inited
Definition: AColor.h:147
static wxBrush lightBrush[2]
Definition: AColor.h:97
static wxBrush playRegionBrush[1]
Definition: AColor.h:108
static void SnapGuidePen(wxDC *dc)
Definition: AColor.cpp:488
static void CursorColor(wxDC *dc)
Definition: AColor.cpp:463
static void Lines(wxDC &dc, size_t nPoints, const wxPoint points[])
Definition: AColor.cpp:194
static wxPen labelSurroundPen
Definition: AColor.h:127
static void Bevel(wxDC &dc, bool up, const wxRect &r)
Definition: AColor.cpp:266
static wxBrush muteBrush[2]
Definition: AColor.h:110
static wxPen cursorPen
Definition: AColor.h:104
static void Light(wxDC *dc, bool selected, bool highlight=false)
Definition: AColor.cpp:413
static void LightMIDIChannel(wxDC *dc, int channel)
Definition: AColor.cpp:681
static void ReInit()
Definition: AColor.cpp:527
static wxPen tooltipPen
Definition: AColor.h:132
static wxPen lightPen[2]
Definition: AColor.h:100
static wxPen mediumPen[2]
Definition: AColor.h:101
static void MediumTrackInfo(wxDC *dc, bool selected)
Definition: AColor.cpp:433
static void ApplyUpdatedImages()
Definition: AColor.cpp:872
static wxBrush envelopeBrush
Definition: AColor.h:117
static wxBrush labelTextNormalBrush
Definition: AColor.h:119
static wxBrush labelTextEditBrush
Definition: AColor.h:120
static wxPen uglyPen
Definition: AColor.h:141
static const int gradientSteps
Definition: AColor.h:137
static void DrawHStretch(wxDC &dc, const wxRect &rect, wxBitmap &bitmap)
Definition: AColor.cpp:308
static void Init()
Definition: AColor.cpp:557
static void Dark(wxDC *dc, bool selected, bool highlight=false)
Definition: AColor.cpp:443
static void Medium(wxDC *dc, bool selected)
Definition: AColor.cpp:424
static void ButtonStretch(wxDC &dc, bool up, const wxRect &r, bool selected=false, bool highlight=false)
Draw a button that fills a given rect.
Definition: AColor.cpp:285
static wxBrush labelSyncLockSelBrush
Definition: AColor.h:123
static wxPen envelopePen
Definition: AColor.h:115
static unsigned char gradient_pre[ColorGradientTotal][colorSchemes][gradientSteps][3]
Definition: AColor.h:138
static wxPen labelSelectedPen
Definition: AColor.h:125
static wxBrush tooltipBrush
Definition: AColor.h:133
static void MIDIChannel(wxDC *dc, int channel)
Definition: AColor.cpp:665
static wxBrush indicatorBrush[2]
Definition: AColor.h:106
static void TrackFocusPen(wxDC *dc, int level)
Definition: AColor.cpp:481
static void BevelTrackInfo(wxDC &dc, bool up, const wxRect &r, bool highlight=false)
Definition: AColor.cpp:340
static void TrackPanelBackground(wxDC *dc, bool selected)
Definition: AColor.cpp:454
static wxBrush soloBrush
Definition: AColor.h:111
static wxBrush labelUnselectedBrush
Definition: AColor.h:121
static wxPen darkPen[2]
Definition: AColor.h:102
static void DrawFrame(wxDC &dc, const wxRect &r, wxBitmap &bitmap)
Definition: AColor.cpp:325
static wxPen snapGuidePen
Definition: AColor.h:130
static wxPen indicatorPen[2]
Definition: AColor.h:105
static wxBrush spareBrush
Definition: AColor.h:146
static void UseThemeColour(wxDC *dc, int iBrush, int iPen=-1, int alpha=255)
Definition: AColor.cpp:372
static void DarkMIDIChannel(wxDC *dc, int channel)
Definition: AColor.cpp:699
static void DrawFocus(wxDC &dc, wxRect &r)
Definition: AColor.cpp:235
static wxPen labelUnselectedPen
Definition: AColor.h:124
static bool gradient_inited
Definition: AColor.h:135
static wxPen labelSyncLockSelPen
Definition: AColor.h:126
CallbackReturn Publish(const Message &message)
Send a message to connected callbacks.
Definition: Observer.h:207
wxColour & Colour(int iIndex)
void SetBrushColour(wxBrush &Brush, int iIndex)
wxBitmap & Bitmap(int iIndex)
int ColourDistance(wxColour &From, wxColour &To)
Definition: Theme.cpp:307
void SetPenColour(wxPen &Pen, int iIndex)
void DrawNinePatch(wxDC &dc, wxBitmap &bitmap, const wxRect &r)
Definition: AColor.cpp:84
int GetButtonImageIndex(bool up, bool selected, bool highlight)
Definition: AColor.cpp:138