Audacity  3.0.3
Theme.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  Theme.cpp
6 
7  James Crook
8 
9  Audacity is free software.
10  This file is licensed under the wxWidgets license, see License.txt
11 
12 ********************************************************************//*****************************************************************//*****************************************************************//*****************************************************************//*****************************************************************//*****************************************************************/
61 
62 
63 #include "Theme.h"
64 
65 
66 
67 #include <wx/wxprec.h>
68 #include <wx/dcclient.h>
69 #include <wx/image.h>
70 #include <wx/file.h>
71 #include <wx/ffile.h>
72 #include <wx/mstream.h>
73 #include <wx/settings.h>
74 
75 #include "AllThemeResources.h" // can remove this later, only needed for 'XPMS_RETIRED'.
76 #include "BasicUI.h"
77 #include "FileNames.h"
78 #include "Prefs.h"
79 #include "ImageManipulation.h"
80 #include "Internat.h"
81 #include "MemoryX.h"
83 
84 // JKC: First get the MAC specific images.
85 // As we've disabled USE_AQUA_THEME, we need to name each file we use.
86 //
87 // JKC: Mac Hackery.
88 // These #defines are very temporary. We want to ensure the Mac XPM names don't collide with
89 // the PC XPM names, so we do some #defines and later undo them.
90 // Use the same trick wherever we need to avoid name collisions.
91 
92 // All this will vanish when the XPMs are eliminated.
93 
94 // Indeed XPMS_RETIRED the #ifndef ensures we're already not using any of it.
95 #ifndef XPMS_RETIRED
96 
97 
98 // This step should mean that we get PC/Linux images only
99 // except where we EXPLICITLY request otherwise.
100 #undef USE_AQUA_THEME
101 
102 // This step ensures we treat the cursors as 32x32 even on Mac.
103 // We're not yet creating the cursors from the theme, so
104 // all this ensures is that the sizing on PC and Mac stays in step.
105 #define CURSORS_SIZE32
106 
107 
108 #define DownButton MacDownButton
109 #define HiliteButton MacHiliteButton
110 #define UpButton MacUpButton
111 #define Down MacDown
112 #define Hilite MacHilite
113 #define Up MacUp
114 #define Slider MacSlider
115 #define SliderThumb MacSliderThumb
116 
117 
118 #include "../images/Aqua/HiliteButtonSquare.xpm"
119 #include "../images/Aqua/UpButtonSquare.xpm"
120 #include "../images/Aqua/DownButtonSquare.xpm"
121 #include "../images/Aqua/Slider.xpm"
122 #include "../images/Aqua/SliderThumb.xpm"
123 #include "../images/Aqua/Down.xpm"
124 #include "../images/Aqua/Hilite.xpm"
125 #include "../images/Aqua/Up.xpm"
126 
127 #if 0
128 // These ones aren't used...
129 #include "../images/Aqua/DownButtonStripes.xpm"
130 #include "../images/Aqua/DownButtonWhite.xpm"
131 #include "../images/Aqua/HiliteButtonStripes.xpm"
132 #include "../images/Aqua/HiliteButtonWhite.xpm"
133 #include "../images/Aqua/UpButtonStripes.xpm"
134 #include "../images/Aqua/UpButtonWhite.xpm"
135 #endif
136 
137 #undef DownButton
138 #undef UpButton
139 #undef HiliteButton
140 #undef Down
141 #undef Hilite
142 #undef Up
143 #undef Slider
144 #undef SliderThumb
145 
146 
147 
148 //-- OK now on to includes for Linux/PC images.
149 
150 #include "../images/PostfishButtons.h"
151 #include "../images/ControlButtons.h"
152 #define HAVE_SHARED_BUTTONS
153 #include "../images/EditButtons.h"
154 #include "../images/MixerImages.h"
155 #include "../images/Cursors.h"
156 #include "../images/ToolBarButtons.h"
157 #include "../images/TranscriptionButtons.h"
158 #include "../images/ToolsButtons.h"
159 
160 #include "../images/ExpandingToolBar/ToolBarToggle.xpm"
161 #include "../images/ExpandingToolBar/ToolBarTarget.xpm"
162 #include "../images/ExpandingToolBar/ToolBarGrabber.xpm"
163 
164 #define Slider VolumeSlider
165 #define SliderThumb VolumeSliderThumb
166 #include "../images/ControlButtons/Slider.xpm"
167 #include "../images/ControlButtons/SliderThumb.xpm"
168 #undef Slider
169 #undef SliderThumb
170 
171 // A different slider's thumb.
172 #include "../images/SliderThumb.xpm"
173 #include "../images/SliderThumbAlpha.xpm"
174 
175 // Include files to get the default images
176 //#include "../images/Aqua.xpm"
177 #include "../images/Arrow.xpm"
178 #include "../images/GlyphImages.h"
179 #include "../images/UploadImages.h"
180 
181 #include "../images/AudacityLogoWithName.xpm"
182 //#include "../images/AudacityLogo.xpm"
183 #include "../images/AudacityLogo48x48.xpm"
184 #endif
185 
186 
187 // Include the ImageCache...
188 
189 static const unsigned char DarkImageCacheAsData[] = {
190 #include "DarkThemeAsCeeCode.h"
191 };
192 static const unsigned char LightImageCacheAsData[] = {
193 #include "LightThemeAsCeeCode.h"
194 };
195 static const unsigned char ClassicImageCacheAsData[] = {
196 #include "ClassicThemeAsCeeCode.h"
197 };
198 static const unsigned char HiContrastImageCacheAsData[] = {
200 };
201 
202 // theTheme is a global variable.
203 AUDACITY_DLL_API Theme theTheme;
204 
206 {
207  mbInitialised=false;
208 }
209 
211 {
212 }
213 
214 
216 {
217  if( mbInitialised )
218  return;
219  RegisterImages();
220  RegisterColours();
221 
222 #ifdef EXPERIMENTAL_EXTRA_THEME_RESOURCES
223  extern void RegisterExtraThemeResources();
224  RegisterExtraThemeResources();
225 #endif
226 
228 
229 }
230 
232 {
233 // DA: Default themes differ.
234  auto theme = GUITheme.Read();
235 
237  return true;
238 }
239 
241 {
242  if( mbInitialised )
243  return;
244  mbInitialised = true;
245 
246 // This initialises the variables e.g
247 // RegisterImage( bmpRecordButton, some image, wxT("RecordButton"));
248 #define THEME_INITS
249 #include "AllThemeResources.h"
250 
251 
252 }
253 
254 
256 {
257 }
258 
260 {
261  bRecolourOnLoad = false;
262  bIsUsingSystemTextColour = false;
263 }
264 
266 {
267 }
268 
272 {
274  const bool cbOkIfNotFound = true;
275 
276  if( !ReadImageCache( Theme, cbOkIfNotFound ) )
277  {
278  // THEN get the default set.
279  ReadImageCache( GetFallbackThemeType(), !cbOkIfNotFound );
280 
281  // JKC: Now we could go on and load the individual images
282  // on top of the default images using the commented out
283  // code that follows...
284  //
285  // However, I think it is better to get the user to
286  // build a NEW image cache, which they can do easily
287  // from the Theme preferences tab.
288 #if 0
289  // and now add any available component images.
290  LoadComponents( cbOkIfNotFound );
291 
292  // JKC: I'm usure about doing this next step automatically.
293  // Suppose the disk is write protected?
294  // Is having the image cache created automatically
295  // going to confuse users? Do we need version specific names?
296  // and now save the combined image as a cache for later use.
297  // We should load the images a little faster in future as a result.
299 #endif
300  }
301 
302  RotateImageInto( bmpRecordBeside, bmpRecordBelow, false );
303  RotateImageInto( bmpRecordBesideDisabled, bmpRecordBelowDisabled, false );
304 
305  if( bRecolourOnLoad )
306  RecolourTheme();
307 
308  wxColor Back = theTheme.Colour( clrTrackInfo );
309  wxColor CurrentText = theTheme.Colour( clrTrackPanelText );
310  wxColor DesiredText = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT );
311 
312  int TextColourDifference = ColourDistance( CurrentText, DesiredText );
313 
314  bIsUsingSystemTextColour = ( TextColourDifference == 0 );
315  // Theming is very accepting of alternative text colours. They just need to
316  // have decent contrast to the background colour, if we're blending themes.
318  int ContrastLevel = ColourDistance( Back, DesiredText );
319  bIsUsingSystemTextColour = bRecolourOnLoad && (ContrastLevel > 250);
321  Colour( clrTrackPanelText ) = DesiredText;
322  }
323  bRecolourOnLoad = false;
324 
325  // Next line is not required as we haven't yet built the GUI
326  // when this function is (or should be) called.
327  // ApplyUpdatedImages();
328 }
329 
330 void ThemeBase::RecolourBitmap( int iIndex, wxColour From, wxColour To )
331 {
332  wxImage Image( Bitmap( iIndex ).ConvertToImage() );
333 
334  std::unique_ptr<wxImage> pResult = ChangeImageColour(
335  &Image, From, To );
336  ReplaceImage( iIndex, pResult.get() );
337 }
338 
339 int ThemeBase::ColourDistance( wxColour & From, wxColour & To ){
340  return
341  abs( From.Red() - To.Red() )
342  + abs( From.Green() - To.Green() )
343  + abs( From.Blue() - To.Blue() );
344 }
345 
346 // This function coerces a theme to be more like the system colours.
347 // Only used for built in themes. For custom themes a user
348 // will choose a better theme for them and just not use a mismatching one.
350 {
351  wxColour From = Colour( clrMedium );
352 #if defined( __WXGTK__ )
353  wxColour To = wxSystemSettings::GetColour( wxSYS_COLOUR_BACKGROUND );
354 #else
355  wxColour To = wxSystemSettings::GetColour( wxSYS_COLOUR_3DFACE );
356 #endif
357  // only recolour if recolouring is slight.
358  int d = ColourDistance( From, To );
359 
360  // Don't recolour if difference is too big.
361  if( d > 120 )
362  return;
363 
364  // A minor tint difference from standard does not need
365  // to be recouloured either. Includes case of d==0 which is nothing
366  // needs to be done.
367  if( d < 40 )
368  return;
369 
370  Colour( clrMedium ) = To;
371  RecolourBitmap( bmpUpButtonLarge, From, To );
372  RecolourBitmap( bmpDownButtonLarge, From, To );
373  RecolourBitmap( bmpHiliteButtonLarge, From, To );
374  RecolourBitmap( bmpUpButtonSmall, From, To );
375  RecolourBitmap( bmpDownButtonSmall, From, To );
376  RecolourBitmap( bmpHiliteButtonSmall, From, To );
377 
378  Colour( clrTrackInfo ) = To;
379  RecolourBitmap( bmpUpButtonExpand, From, To );
380 }
381 
382 wxImage ThemeBase::MaskedImage( char const ** pXpm, char const ** pMask )
383 {
384  wxBitmap Bmp1( pXpm );
385  wxBitmap Bmp2( pMask );
386 
387 // wxLogDebug( wxT("Image 1: %i Image 2: %i"),
388 // Bmp1.GetDepth(), Bmp2.GetDepth() );
389 
390  // We want a 24-bit-depth bitmap if all is working, but on some
391  // platforms it might just return -1 (which means best available
392  // or not relevant).
393  // JKC: \todo check that we're not relying on 24 bit elsewhere.
394  wxASSERT( Bmp1.GetDepth()==-1 || Bmp1.GetDepth()==24);
395  wxASSERT( Bmp1.GetDepth()==-1 || Bmp2.GetDepth()==24);
396 
397  int i,nBytes;
398  nBytes = Bmp1.GetWidth() * Bmp1.GetHeight();
399  wxImage Img1( Bmp1.ConvertToImage());
400  wxImage Img2( Bmp2.ConvertToImage());
401 
402 // unsigned char *src = Img1.GetData();
403  unsigned char *mk = Img2.GetData();
404  //wxImage::setAlpha requires memory allocated with malloc, not NEW
406  static_cast<unsigned char*>(malloc( nBytes )) };
407 
408  // Extract alpha channel from second XPM.
409  for(i=0;i<nBytes;i++)
410  {
411  alpha[i] = mk[0];
412  mk+=3;
413  }
414 
415  Img1.SetAlpha( alpha.release() );
416 
417  //dmazzoni: the top line does not work on wxGTK
418  //wxBitmap Result( Img1, 32 );
419  //wxBitmap Result( Img1 );
420 
421  return Img1;
422 }
423 
424 // Legacy function to allow use of an XPM where no theme image was defined.
425 // Bit depth and mask needs review.
426 // Note that XPMs don't offer translucency, so unsuitable for a round shape overlay,
427 // for example.
428 void ThemeBase::RegisterImage( int &iIndex, char const ** pXpm, const wxString & Name )
429 {
430  wxASSERT( iIndex == -1 ); // Don't initialise same bitmap twice!
431  wxBitmap Bmp( pXpm );
432  wxImage Img( Bmp.ConvertToImage() );
433  // The next line recommended by http://forum.audacityteam.org/viewtopic.php?f=50&t=96765
434  Img.SetMaskColour(0xDE, 0xDE, 0xDE);
435  Img.InitAlpha();
436 
437  //dmazzoni: the top line does not work on wxGTK
438  //wxBitmap Bmp2( Img, 32 );
439  //wxBitmap Bmp2( Img );
440 
441  RegisterImage( iIndex, Img, Name );
442 }
443 
444 void ThemeBase::RegisterImage( int &iIndex, const wxImage &Image, const wxString & Name )
445 {
446  wxASSERT( iIndex == -1 ); // Don't initialise same bitmap twice!
447  mImages.push_back( Image );
448 
449 #ifdef __APPLE__
450  // On Mac, bitmaps with alpha don't work.
451  // So we convert to a mask and use that.
452  // It isn't quite as good, as alpha gives smoother edges.
453  //[Does not affect the large control buttons, as for those we do
454  // the blending ourselves anyway.]
455  wxImage TempImage( Image );
456  TempImage.ConvertAlphaToMask();
457  mBitmaps.push_back( wxBitmap( TempImage ) );
458 #else
459  mBitmaps.push_back( wxBitmap( Image ) );
460 #endif
461 
462  mBitmapNames.push_back( Name );
463  mBitmapFlags.push_back( mFlow.mFlags );
465  iIndex = mBitmaps.size() - 1;
466 }
467 
468 void ThemeBase::RegisterColour( int &iIndex, const wxColour &Clr, const wxString & Name )
469 {
470  wxASSERT( iIndex == -1 ); // Don't initialise same colour twice!
471  mColours.push_back( Clr );
472  mColourNames.push_back( Name );
473  iIndex = mColours.size() - 1;
474 }
475 
476 void FlowPacker::Init(int width)
477 {
479  mOldFlags = mFlags;
480  mxCacheWidth = width;
481 
482  myPos = 0;
483  myPosBase =0;
484  myHeight = 0;
485  iImageGroupSize = 1;
486  SetNewGroup(1);
487  mBorderWidth = 0;
488 }
489 
490 void FlowPacker::SetNewGroup( int iGroupSize )
491 {
493  mxPos =0;
494  mOldFlags = mFlags;
495  iImageGroupSize = iGroupSize;
496  iImageGroupIndex = -1;
497  mComponentWidth=0;
498 }
499 
501 {
502  myPosBase = 750;
503  mxPos =0;
504  mOldFlags = mFlags;
505  iImageGroupSize = 1;
506  iImageGroupIndex = -1;
507  mComponentWidth=0;
508  myHeight = 11;
509 }
510 
511 void FlowPacker::GetNextPosition( int xSize, int ySize )
512 {
513  xSize += 2*mBorderWidth;
514  ySize += 2*mBorderWidth;
515  // if the height has increased, then we are on a NEW group.
516  if(( ySize > myHeight )||(((mFlags ^ mOldFlags )& ~resFlagSkip)!=0))
517  {
518  SetNewGroup( ((mFlags & resFlagPaired)!=0) ? 2 : 1 );
519  myHeight = ySize;
520 // mFlags &= ~resFlagNewLine;
521 // mOldFlags = mFlags;
522  }
523 
526  {
527  iImageGroupIndex = 0;
529  }
530 
531  if(mxPos > (mxCacheWidth - xSize ))
532  {
535  myHeight = ySize;
536  }
538 
539  mComponentWidth = xSize;
540  mComponentHeight = ySize;
541 }
542 
544 {
545  return wxRect( mxPos, myPos, mComponentWidth, mComponentHeight);
546 }
547 
549 {
550  return Rect().Deflate( mBorderWidth, mBorderWidth );
551 }
552 
553 void FlowPacker::RectMid( int &x, int &y )
554 {
555  x = mxPos + mComponentWidth/2;
556  y = myPos + mComponentHeight/2;
557 }
558 
559 
565 class SourceOutputStream final : public wxOutputStream
566 {
567 public:
569  int OpenFile(const FilePath & Filename);
570  virtual ~SourceOutputStream();
571 
572 protected:
573  size_t OnSysWrite(const void *buffer, size_t bufsize) override;
574  wxFile File;
575  int nBytes;
576 };
577 
580 {
581  nBytes = 0;
582  bool bOk;
583  bOk = File.Open( Filename, wxFile::write );
584  if( bOk )
585  {
586 // DA: Naming of output sourcery
587 #ifdef EXPERIMENTAL_DA
588  File.Write( wxT("/// @file DarkThemeAsCeeCode.h\r\n") );
589 #else
590  File.Write( wxT("/// @file ThemeAsCeeCode.h\r\n") );
591 #endif
592  File.Write( wxT("/// @brief This file was Auto-Generated.\r\n") );
593  File.Write( wxT("///\r\n") );
594  File.Write( wxT("/// It is included by Theme.cpp.\r\n") );
595  File.Write( wxT("/// Only check this into Git if you've read and understood the guidelines!\r\n\r\n ") );
596  }
597  return bOk;
598 }
599 
602 size_t SourceOutputStream::OnSysWrite(const void *buffer, size_t bufsize)
603 {
604  wxString Temp;
605  for(int i=0;i<(int)bufsize;i++)
606  {
607  // Write one byte with a comma
608  Temp = wxString::Format( wxT("%i,"),(int)(((unsigned char*)buffer)[i]) );
609  File.Write( Temp );
610  nBytes++;
611  // New line if more than 20 bytes written since last time.
612  if( (nBytes %20)==0 )
613  {
614  File.Write( wxT("\r\n "));
615  }
616  }
617  return bufsize;
618 }
619 
622 {
623  File.Write( wxT("\r\n") );
624  File.Close();
625 }
626 
627 
628 // Must be wide enough for bmpAudacityLogo. Use double width + 10.
629 const int ImageCacheWidth = 440;
630 
631 const int ImageCacheHeight = 836;
632 
633 void ThemeBase::CreateImageCache( bool bBinarySave )
634 {
636  wxBusyCursor busy;
637 
638  wxImage ImageCache( ImageCacheWidth, ImageCacheHeight );
639  ImageCache.SetRGB( wxRect( 0,0,ImageCacheWidth, ImageCacheHeight), 1,1,1);//Not-quite black.
640 
641  // Ensure we have an alpha channel...
642  if( !ImageCache.HasAlpha() )
643  {
644  ImageCache.InitAlpha();
645  }
646 
647  int i;
648 
650  mFlow.mBorderWidth =1;
651 
652 //#define IMAGE_MAP
653 #ifdef IMAGE_MAP
654  wxLogDebug( wxT("<img src=\"ImageCache.png\" usemap=\"#map1\">" ));
655  wxLogDebug( wxT("<map name=\"map1\">") );
656 #endif
657 
658  // Save the bitmaps
659  for(i = 0;i < (int)mImages.size();i++)
660  {
661  wxImage &SrcImage = mImages[i];
663  if( (mBitmapFlags[i] & resFlagInternal)==0)
664  {
665  mFlow.GetNextPosition( SrcImage.GetWidth(), SrcImage.GetHeight());
666  ImageCache.SetRGB( mFlow.Rect(), 0xf2, 0xb0, 0x27 );
667  if( (mFlow.mFlags & resFlagSkip) == 0 )
668  PasteSubImage( &ImageCache, &SrcImage,
671  else
672  ImageCache.SetRGB( mFlow.RectInner(), 1,1,1);
673 #ifdef IMAGE_MAP
674  // No href in html. Uses title not alt.
675  wxRect R( mFlow.Rect() );
676  wxLogDebug( wxT("<area title=\"Bitmap:%s\" shape=rect coords=\"%i,%i,%i,%i\">"),
677  mBitmapNames[i],
678  R.GetLeft(), R.GetTop(), R.GetRight(), R.GetBottom() );
679 #endif
680  }
681  }
682 
683  // Now save the colours.
684  int x,y;
685 
687  const int iColSize = 10;
688  for(i = 0; i < (int)mColours.size(); i++)
689  {
690  mFlow.GetNextPosition( iColSize, iColSize );
691  wxColour c = mColours[i];
692  ImageCache.SetRGB( mFlow.Rect() , 0xf2, 0xb0, 0x27 );
693  ImageCache.SetRGB( mFlow.RectInner() , c.Red(), c.Green(), c.Blue() );
694 
695  // YUCK! No function in wxWidgets to set a rectangle of alpha...
696  for(x=0;x<iColSize;x++)
697  {
698  for(y=0;y<iColSize;y++)
699  {
700  ImageCache.SetAlpha( mFlow.mxPos + x, mFlow.myPos+y, 255);
701  }
702  }
703 #ifdef IMAGE_MAP
704  // No href in html. Uses title not alt.
705  wxRect R( mFlow.Rect() );
706  wxLogDebug( wxT("<area title=\"Colour:%s\" shape=rect coords=\"%i,%i,%i,%i\">"),
707  mColourNames[i],
708  R.GetLeft(), R.GetTop(), R.GetRight(), R.GetBottom() );
709 #endif
710  }
711 #if TEST_CARD
712  int j;
713  for(i=0;i<ImageCacheWidth;i++)
714  for(j=0;j<ImageCacheHeight;j++){
715  int r = j &0xff;
716  int g = i &0xff;
717  int b = (j >> 8) | ((i>>4)&0xf0);
718  wxRect R( i,j, 1, 1);
719  ImageCache.SetRGB( R, r, g, b );
720  ImageCache.SetAlpha( i,j, 255);
721  }
722 #endif
723 
724 #ifdef IMAGE_MAP
725  wxLogDebug( "</map>" );
726 #endif
727 
728  // IF bBinarySave, THEN saving to a normal PNG file.
729  if( bBinarySave )
730  {
731  const auto &FileName = FileNames::ThemeCachePng();
732 
733  // Perhaps we should prompt the user if they are overwriting
734  // an existing theme cache?
735 #if 0
736  if( wxFileExists( FileName ))
737  {
738  auto message =
739 // XO(
740 //"Theme cache file:\n %s\nalready exists.\nAre you sure you want to replace it?")
741 // .Format( FileName );
742  TranslatableString{ FileName };
743  AudacityMessageBox( message );
744  return;
745  }
746 #endif
747 #if 0
748  // Deliberate policy to use the fast/cheap blocky pixel-multiplication
749  // algorithm, as this introduces no artifacts on repeated scale up/down.
750  ImageCache.Rescale(
751  ImageCache.GetWidth()*4,
752  ImageCache.GetHeight()*4,
753  wxIMAGE_QUALITY_NEAREST );
754 #endif
755  if( !ImageCache.SaveFile( FileName, wxBITMAP_TYPE_PNG ))
756  {
758  XO("Audacity could not write file:\n %s.")
759  .Format( FileName ));
760  return;
761  }
763 /* i18n-hint: A theme is a consistent visual style across an application's
764  graphical user interface, including choices of colors, and similarity of images
765  such as those on button controls. Audacity can load and save alternative
766  themes. */
767  XO("Theme written to:\n %s.")
768  .Format( FileName ));
769  }
770  // ELSE saving to a C code textual version.
771  else
772  {
773  SourceOutputStream OutStream;
774  const auto &FileName = FileNames::ThemeCacheAsCee( );
775  if( !OutStream.OpenFile( FileName ))
776  {
778  XO("Audacity could not open file:\n %s\nfor writing.")
779  .Format( FileName ));
780  return;
781  }
782  if( !ImageCache.SaveFile(OutStream, wxBITMAP_TYPE_PNG ) )
783  {
785  XO("Audacity could not write images to file:\n %s.")
786  .Format( FileName ));
787  return;
788  }
790  /* i18n-hint "Cee" means the C computer programming language */
791  XO("Theme as Cee code written to:\n %s.")
792  .Format( FileName ));
793  }
794 }
795 
799 {
801  wxBusyCursor busy;
802 
803  int i;
805  mFlow.mBorderWidth = 1;
806 
807  wxFFile File( FileNames::ThemeCacheHtm(), wxT("wb") );// I'll put in NEW lines explicitly.
808  if( !File.IsOpened() )
809  return;
810 
811  File.Write( wxT("<html>\r\n"));
812  File.Write( wxT("<body bgcolor=\"303030\">\r\n"));
813  wxString Temp = wxString::Format( wxT("<img src=\"ImageCache.png\" width=\"%i\" usemap=\"#map1\">\r\n" ), ImageCacheWidth );
814  File.Write( Temp );
815  File.Write( wxT("<map name=\"map1\">\r\n") );
816 
817  for(i = 0; i < (int)mImages.size(); i++)
818  {
819  wxImage &SrcImage = mImages[i];
821  if( (mBitmapFlags[i] & resFlagInternal)==0)
822  {
823  mFlow.GetNextPosition( SrcImage.GetWidth(), SrcImage.GetHeight());
824  // No href in html. Uses title not alt.
825  wxRect R( mFlow.RectInner() );
826  File.Write( wxString::Format(
827  wxT("<area title=\"Bitmap:%s\" shape=rect coords=\"%i,%i,%i,%i\">\r\n"),
828  mBitmapNames[i],
829  R.GetLeft(), R.GetTop(), R.GetRight(), R.GetBottom()) );
830  }
831  }
832  // Now save the colours.
834  const int iColSize = 10;
835  for(i = 0; i < (int)mColours.size(); i++)
836  {
837  mFlow.GetNextPosition( iColSize, iColSize );
838  // No href in html. Uses title not alt.
839  wxRect R( mFlow.RectInner() );
840  File.Write( wxString::Format( wxT("<area title=\"Colour:%s\" shape=rect coords=\"%i,%i,%i,%i\">\r\n"),
841  mColourNames[i],
842  R.GetLeft(), R.GetTop(), R.GetRight(), R.GetBottom()) );
843  }
844  File.Write( wxT("</map>\r\n") );
845  File.Write( wxT("</body>\r\n"));
846  File.Write( wxT("</html>\r\n"));
847  // File will be closed automatically.
848 }
849 
852 {
854  wxBusyCursor busy;
855 
856  int i;
857  wxFFile File( FileNames::ThemeImageDefsAsCee(), wxT("wb") );
858  if( !File.IsOpened() )
859  return;
860  teResourceFlags PrevFlags = (teResourceFlags)-1;
861  for(i = 0; i < (int)mImages.size(); i++)
862  {
863  wxImage &SrcImage = mImages[i];
864  // No href in html. Uses title not alt.
865  if( PrevFlags != mBitmapFlags[i] )
866  {
867  PrevFlags = (teResourceFlags)mBitmapFlags[i];
868  int t = (int)PrevFlags;
869  wxString Temp;
870  if( t==0 ) Temp = wxT(" resFlagNone ");
871  if( t & resFlagPaired ) Temp += wxT(" resFlagPaired ");
872  if( t & resFlagCursor ) Temp += wxT(" resFlagCursor ");
873  if( t & resFlagNewLine ) Temp += wxT(" resFlagNewLine ");
874  if( t & resFlagInternal ) Temp += wxT(" resFlagInternal ");
875  Temp.Replace( wxT(" "), wxT(" | ") );
876 
877  File.Write( wxString::Format( wxT("\r\n SET_THEME_FLAGS( %s );\r\n"),
878  Temp ));
879  }
880  File.Write( wxString::Format(
881  wxT(" DEFINE_IMAGE( bmp%s, wxImage( %i, %i ), wxT(\"%s\"));\r\n"),
882  mBitmapNames[i],
883  SrcImage.GetWidth(),
884  SrcImage.GetHeight(),
885  mBitmapNames[i]
886  ));
887  }
888 }
889 
890 
892 // Fallback must be an internally supported type,
893 // to guarantee it is found.
894 #ifdef EXPERIMENTAL_DA
895  return themeDark;
896 #else
897  return themeLight;
898 #endif
899 }
900 
902 {
903  static const wxArrayStringEx aThemes{
904  "classic" ,
905  "dark" ,
906  "light" ,
907  "high-contrast" ,
908  "custom" ,
909  };
910  int themeIx = make_iterator_range( aThemes ).index( Name );
911  if( themeIx < 0 )
912  return GetFallbackThemeType();
913  return (teThemeType)themeIx;
914 }
915 
916 
917 
923 bool ThemeBase::ReadImageCache( teThemeType type, bool bOkIfNotFound)
924 {
926  wxImage ImageCache;
927  wxBusyCursor busy;
928 
929  // Ensure we have an alpha channel...
930 // if( !ImageCache.HasAlpha() )
931 // {
932 // ImageCache.InitAlpha();
933 // }
934 
935  gPrefs->Read(wxT("/GUI/BlendThemes"), &bRecolourOnLoad, true);
936 
937  if( type == themeFromFile )
938  {
939  const auto &FileName = FileNames::ThemeCachePng();
940  if( !wxFileExists( FileName ))
941  {
942  if( bOkIfNotFound )
943  return false; // did not load the images, so return false.
945  XO("Audacity could not find file:\n %s.\nTheme not loaded.")
946  .Format( FileName ));
947  return false;
948  }
949  if( !ImageCache.LoadFile( FileName, wxBITMAP_TYPE_PNG ))
950  {
952  /* i18n-hint: Do not translate png. It is the name of a file format.*/
953  XO("Audacity could not load file:\n %s.\nBad png format perhaps?")
954  .Format( FileName ));
955  return false;
956  }
957  }
958  // ELSE we are reading from internal storage.
959  else
960  {
961  size_t ImageSize = 0;
962  const unsigned char * pImage = nullptr;
963  switch( type ){
964  default:
965  case themeClassic :
967  pImage = ClassicImageCacheAsData;
968  break;
969  case themeLight :
971  pImage = LightImageCacheAsData;
972  break;
973  case themeDark :
975  pImage = DarkImageCacheAsData;
976  break;
977  case themeHiContrast :
980  break;
981  }
982  //wxLogDebug("Reading ImageCache %p size %i", pImage, ImageSize );
983  wxMemoryInputStream InternalStream( pImage, ImageSize );
984 
985  if( !ImageCache.LoadFile( InternalStream, wxBITMAP_TYPE_PNG ))
986  {
987  // If we get this message, it means that the data in file
988  // was not a valid png image.
989  // Most likely someone edited it by mistake,
990  // Or some experiment is being tried with NEW formats for it.
992  XO(
993 "Audacity could not read its default theme.\nPlease report the problem."));
994  return false;
995  }
996  //wxLogDebug("Read %i by %i", ImageCache.GetWidth(), ImageCache.GetHeight() );
997  }
998 
999  // Resize a large image down.
1000  if( ImageCache.GetWidth() > ImageCacheWidth ){
1001  int h = ImageCache.GetHeight() * ((1.0*ImageCacheWidth)/ImageCache.GetWidth());
1002  ImageCache.Rescale( ImageCacheWidth, h );
1003  }
1004  int i;
1006  mFlow.mBorderWidth = 1;
1007  // Load the bitmaps
1008  for(i = 0; i < (int)mImages.size(); i++)
1009  {
1010  wxImage &Image = mImages[i];
1011  mFlow.mFlags = mBitmapFlags[i];
1012  if( (mBitmapFlags[i] & resFlagInternal)==0)
1013  {
1014  mFlow.GetNextPosition( Image.GetWidth(),Image.GetHeight() );
1015  wxRect R = mFlow.RectInner();
1016  //wxLogDebug( "[%i, %i, %i, %i, \"%s\"], ", R.x, R.y, R.width, R.height, mBitmapNames[i].c_str() );
1017  Image = GetSubImageWithAlpha( ImageCache, mFlow.RectInner() );
1018  mBitmaps[i] = wxBitmap(Image);
1019  }
1020  }
1021  if( !ImageCache.HasAlpha() )
1022  ImageCache.InitAlpha();
1023 
1024 // return true; //To not load colours..
1025  // Now load the colours.
1026  int x,y;
1028  wxColour TempColour;
1029  const int iColSize=10;
1030  for(i = 0; i < (int)mColours.size(); i++)
1031  {
1032  mFlow.GetNextPosition( iColSize, iColSize );
1033  mFlow.RectMid( x, y );
1034  wxRect R = mFlow.RectInner();
1035  //wxLogDebug( "[%i, %i, %i, %i, \"%s\"], ", R.x, R.y, R.width, R.height, mColourNames[i].c_str() );
1036  // Only change the colour if the alpha is opaque.
1037  // This allows us to add NEW colours more easily.
1038  if( ImageCache.GetAlpha(x,y ) > 128 )
1039  {
1040  TempColour = wxColour(
1041  ImageCache.GetRed( x,y),
1042  ImageCache.GetGreen( x,y),
1043  ImageCache.GetBlue(x,y));
1048  if( TempColour != wxColour(1,1,1) )
1049  mColours[i] = TempColour;
1050  }
1051  }
1052  return true;
1053 }
1054 
1055 void ThemeBase::LoadComponents( bool bOkIfNotFound )
1056 {
1057  // IF directory doesn't exist THEN return early.
1058  if( !wxDirExists( FileNames::ThemeComponentsDir() ))
1059  return;
1060 
1061  wxBusyCursor busy;
1062  int i;
1063  int n=0;
1064  FilePath FileName;
1065  for(i = 0; i < (int)mImages.size(); i++)
1066  {
1067 
1068  if( (mBitmapFlags[i] & resFlagInternal)==0)
1069  {
1070  FileName = FileNames::ThemeComponent( mBitmapNames[i] );
1071  if( wxFileExists( FileName ))
1072  {
1073  if( !mImages[i].LoadFile( FileName, wxBITMAP_TYPE_PNG ))
1074  {
1076  XO(
1077  /* i18n-hint: Do not translate png. It is the name of a file format.*/
1078 "Audacity could not load file:\n %s.\nBad png format perhaps?")
1079  .Format( FileName ));
1080  return;
1081  }
1086  if( ! mImages[i].HasAlpha() )
1087  {
1088  // wxLogDebug( wxT("File %s lacked alpha"), mBitmapNames[i] );
1089  mImages[i].InitAlpha();
1090  }
1091  mBitmaps[i] = wxBitmap( mImages[i] );
1092  n++;
1093  }
1094  }
1095  }
1096  if( n==0 )
1097  {
1098  if( bOkIfNotFound )
1099  return;
1101  XO(
1102 "None of the expected theme component files\n were found in:\n %s.")
1104  }
1105 }
1106 
1108 {
1109  // IF directory doesn't exist THEN create it
1110  if( !wxDirExists( FileNames::ThemeComponentsDir() ))
1111  {
1117 #ifdef __WXMSW__
1118  wxMkDir( FileNames::ThemeComponentsDir().fn_str() );
1119 #else
1120  wxMkDir( FileNames::ThemeComponentsDir().fn_str(), 0700 );
1121 #endif
1122  if( !wxDirExists( FileNames::ThemeComponentsDir() ))
1123  {
1125  XO("Could not create directory:\n %s")
1127  return;
1128  }
1129  }
1130 
1131  wxBusyCursor busy;
1132  int i;
1133  int n=0;
1134  FilePath FileName;
1135  for(i = 0; i < (int)mImages.size(); i++)
1136  {
1137  if( (mBitmapFlags[i] & resFlagInternal)==0)
1138  {
1139  FileName = FileNames::ThemeComponent( mBitmapNames[i] );
1140  if( wxFileExists( FileName ))
1141  {
1142  ++n;
1143  break;
1144  }
1145  }
1146  }
1147 
1148  using namespace BasicUI;
1149 
1150  if (n > 0)
1151  {
1152  auto result =
1154  XO(
1155 "Some required files in:\n %s\nwere already present. Overwrite?")
1158  .ButtonStyle(Button::YesNo)
1159  .DefaultIsNo());
1160  if (result == MessageBoxResult::No)
1161  return;
1162  }
1163 
1164  for(i = 0; i < (int)mImages.size(); i++)
1165  {
1166  if( (mBitmapFlags[i] & resFlagInternal)==0)
1167  {
1168  FileName = FileNames::ThemeComponent( mBitmapNames[i] );
1169  if( !mImages[i].SaveFile( FileName, wxBITMAP_TYPE_PNG ))
1170  {
1172  XO("Audacity could not save file:\n %s")
1173  .Format( FileName ));
1174  return;
1175  }
1176  }
1177  }
1179  XO("Theme written to:\n %s.")
1181 }
1182 
1183 
1185 {
1186  // false indicates not using standard binary method.
1187  CreateImageCache( false );
1188 }
1189 
1190 wxImage ThemeBase::MakeImageWithAlpha( wxBitmap & Bmp )
1191 {
1192  // BUG in wxWidgets. Conversion from BMP to image does not preserve alpha.
1193  wxImage image( Bmp.ConvertToImage() );
1194  return image;
1195 }
1196 
1197 wxColour & ThemeBase::Colour( int iIndex )
1198 {
1199  wxASSERT( iIndex >= 0 );
1201  return mColours[iIndex];
1202 }
1203 
1204 void ThemeBase::SetBrushColour( wxBrush & Brush, int iIndex )
1205 {
1206  wxASSERT( iIndex >= 0 );
1207  Brush.SetColour( Colour( iIndex ));
1208 }
1209 
1210 void ThemeBase::SetPenColour( wxPen & Pen, int iIndex )
1211 {
1212  wxASSERT( iIndex >= 0 );
1213  Pen.SetColour( Colour( iIndex ));
1214 }
1215 
1216 wxBitmap & ThemeBase::Bitmap( int iIndex )
1217 {
1218  wxASSERT( iIndex >= 0 );
1220  return mBitmaps[iIndex];
1221 }
1222 
1223 wxImage & ThemeBase::Image( int iIndex )
1224 {
1225  wxASSERT( iIndex >= 0 );
1227  return mImages[iIndex];
1228 }
1229 wxSize ThemeBase::ImageSize( int iIndex )
1230 {
1231  wxASSERT( iIndex >= 0 );
1233  wxImage & Image = mImages[iIndex];
1234  return wxSize( Image.GetWidth(), Image.GetHeight());
1235 }
1236 
1237 // The next two functions are for future use.
1238 #if 0
1239 wxCursor & ThemeBase::Cursor( int iIndex )
1240 {
1241  wxASSERT( iIndex >= 0 );
1243  // Purposeful null deref. Function is for future use.
1244  // If anyone tries to use it now they will get an error.
1245  return *(wxCursor*)NULL;
1246 }
1247 
1248 wxFont & ThemeBase::Font( int iIndex )
1249 {
1250  wxASSERT( iIndex >= 0 );
1252  // Purposeful null deref. Function is for future use.
1253  // If anyone tries to use it now they will get an error.
1254  return *(wxFont*)NULL;
1255 }
1256 #endif
1257 
1259 void ThemeBase::ReplaceImage( int iIndex, wxImage * pImage )
1260 {
1261  Image( iIndex ) = *pImage;
1262  Bitmap( iIndex ) = wxBitmap( *pImage );
1263 }
1264 
1265 void ThemeBase::RotateImageInto( int iTo, int iFrom, bool bClockwise )
1266 {
1267  wxImage img(theTheme.Bitmap( iFrom ).ConvertToImage() );
1268  wxImage img2 = img.Rotate90( bClockwise );
1269  ReplaceImage( iTo, &img2 );
1270 }
1271 
1272 BEGIN_EVENT_TABLE(auStaticText, wxWindow)
1273  EVT_PAINT(auStaticText::OnPaint)
1274  EVT_ERASE_BACKGROUND(auStaticText::OnErase)
1276 
1277 
1278 auStaticText::auStaticText(wxWindow* parent, wxString textIn) :
1279  wxWindow(parent, wxID_ANY)
1280 {
1281  int textWidth, textHeight;
1282 
1283  int fontSize = 11;
1284  #ifdef __WXMSW__
1285  fontSize = 9;
1286  #endif
1287  wxFont font(fontSize, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
1288  GetTextExtent(textIn, &textWidth, &textHeight, NULL, NULL, &font);
1289 
1290  SetFont( font );
1291  SetMinSize( wxSize(textWidth, textHeight) );
1292  SetBackgroundColour( theTheme.Colour( clrMedium));
1293  SetForegroundColour( theTheme.Colour( clrTrackPanelText));
1294  SetName(textIn);
1295  SetLabel(textIn);
1296 }
1297 
1298 void auStaticText::OnPaint(wxPaintEvent & WXUNUSED(evt))
1299 {
1300  wxPaintDC dc(this);
1301  //dc.SetTextForeground( theTheme.Colour( clrTrackPanelText));
1302  dc.Clear();
1303  dc.DrawText( GetLabel(), 0,0);
1304 }
1305 
1306 constexpr int defaultTheme =
1307 #ifdef EXPERIMENTAL_DA
1308  2 // "dark"
1309 #else
1310  1 // "light"
1311 #endif
1312 ;
1313 
1315  wxT("/GUI/Theme"),
1316  {
1317  ByColumns,
1318  {
1319  /* i18n-hint: describing the "classic" or traditional
1320  appearance of older versions of Audacity */
1321  XO("Classic") ,
1322  /* i18n-hint: Light meaning opposite of dark */
1323  XO("Light") ,
1324  XO("Dark") ,
1325  /* i18n-hint: greater difference between foreground and
1326  background colors */
1327  XO("High Contrast") ,
1328  /* i18n-hint: user defined */
1329  XO("Custom") ,
1330  },
1331  {
1332  wxT("classic") ,
1333  wxT("light") ,
1334  wxT("dark") ,
1335  wxT("high-contrast") ,
1336  wxT("custom") ,
1337  }
1338  },
1339  defaultTheme
1340 };
1341 
FlowPacker::mxCacheWidth
int mxCacheWidth
Definition: Theme.h:91
TranslatableString
Holds a msgid for the translation catalog; may also bind format arguments.
Definition: TranslatableString.h:32
ImageCacheWidth
const int ImageCacheWidth
Definition: Theme.cpp:629
ClassicImageCacheAsData
static const unsigned char ClassicImageCacheAsData[]
Definition: Theme.cpp:195
FlowPacker::mxPos
int mxPos
Definition: Theme.h:80
FlowPacker::iImageGroupIndex
int iImageGroupIndex
Definition: Theme.h:87
GUITheme
ChoiceSetting GUITheme
Definition: Theme.cpp:1314
SourceOutputStream::OpenFile
int OpenFile(const FilePath &Filename)
Opens the file and also adds a standard comment at the start of it.
Definition: Theme.cpp:579
ThemeBase::mImages
std::vector< wxImage > mImages
Definition: Theme.h:152
FlowPacker::mComponentWidth
int mComponentWidth
Definition: Theme.h:93
BasicUI::MessageBoxOptions
Definition: BasicUI.h:91
resFlagPaired
@ resFlagPaired
Definition: Theme.h:47
ThemeBase::SaveComponents
void SaveComponents()
Definition: Theme.cpp:1107
FlowPacker::RectInner
wxRect RectInner()
Definition: Theme.cpp:548
teResourceFlags
teResourceFlags
Definition: Theme.h:45
make_iterator_range
IteratorRange< Iterator > make_iterator_range(const Iterator &i1, const Iterator &i2)
Definition: MemoryX.h:549
ThemeBase::bRecolourOnLoad
bool bRecolourOnLoad
Definition: Theme.h:135
ThemeBase::RotateImageInto
void RotateImageInto(int iTo, int iFrom, bool bClockwise)
Definition: Theme.cpp:1265
SourceOutputStream::File
wxFile File
Definition: Theme.cpp:574
AudacityMessageBox
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
Definition: AudacityMessageBox.cpp:17
ThemeBase::CreateImageCache
void CreateImageCache(bool bBinarySave=true)
Definition: Theme.cpp:633
gPrefs
FileConfig * gPrefs
Definition: Prefs.cpp:70
ThemeBase::ColourDistance
int ColourDistance(wxColour &From, wxColour &To)
Definition: Theme.cpp:339
AllThemeResources.h
BasicUI::ShowMessageBox
MessageBoxResult ShowMessageBox(const TranslatableString &message, MessageBoxOptions options={})
Show a modal message box with either Ok or Yes and No, and optionally Cancel.
Definition: BasicUI.h:248
defaultTheme
constexpr int defaultTheme
Definition: Theme.cpp:1306
Theme
Based on ThemeBase, Theme manages image and icon resources.
Definition: Theme.h:164
ThemeBase::mBitmaps
std::vector< wxBitmap > mBitmaps
Definition: Theme.h:153
Format
Abstract base class used in importing a file.
resFlagSkip
@ resFlagSkip
Definition: Theme.h:51
Theme::RegisterImages
void RegisterImages()
Definition: Theme.cpp:240
ClassicThemeAsCeeCode.h
FlowPacker::Init
void Init(int width)
Definition: Theme.cpp:476
MallocString
std::unique_ptr< Character[], freer > MallocString
Definition: MemoryX.h:274
XO
#define XO(s)
Definition: Internat.h:31
BasicUI::MessageBoxOptions::ButtonStyle
MessageBoxOptions && ButtonStyle(Button style) &&
Definition: BasicUI.h:104
FlowPacker::mBorderWidth
int mBorderWidth
Definition: Theme.h:83
FileNames::ThemeImageDefsAsCee
FILES_API FilePath ThemeImageDefsAsCee()
FileNames::ThemeCachePng
FILES_API FilePath ThemeCachePng()
HiContrastThemeAsCeeCode.h
ThemeBase::ImageSize
wxSize ImageSize(int iIndex)
Definition: Theme.cpp:1229
SourceOutputStream::nBytes
int nBytes
Definition: Theme.cpp:575
FlowPacker::iImageGroupSize
int iImageGroupSize
Definition: Theme.h:86
SourceOutputStream::~SourceOutputStream
virtual ~SourceOutputStream()
Destructor. We close our text stream in here.
Definition: Theme.cpp:621
wxArrayStringEx
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
Definition: wxArrayStringEx.h:18
ThemeBase::ReplaceImage
void ReplaceImage(int iIndex, wxImage *pImage)
Replaces both the image and the bitmap.
Definition: Theme.cpp:1259
themeHiContrast
@ themeHiContrast
Definition: Theme.h:59
PasteSubImage
void PasteSubImage(wxImage *background, wxImage *foreground, int xoff, int yoff)
Definition: ImageManipulation.cpp:318
FlowPacker::mFlags
int mFlags
Definition: Theme.h:79
ThemeBase::Cursor
wxCursor & Cursor(int iIndex)
ThemeBase::Bitmap
wxBitmap & Bitmap(int iIndex)
Definition: Theme.cpp:1216
SourceOutputStream
Helper class based on wxOutputStream used to get a png file in text format.
Definition: Theme.cpp:566
resFlagInternal
@ resFlagInternal
Definition: Theme.h:50
ThemeBase::mColours
std::vector< wxColour > mColours
Definition: Theme.h:157
themeFromFile
@ themeFromFile
Definition: Theme.h:60
FlowPacker::SetColourGroup
void SetColourGroup()
Definition: Theme.cpp:500
ChoiceSetting
Definition: Prefs.h:267
ThemeBase::mBitmapNames
wxArrayString mBitmapNames
Definition: Theme.h:154
auStaticText::OnErase
void OnErase(wxEraseEvent &event)
Definition: Theme.h:188
FilePath
wxString FilePath
Definition: Project.h:20
Theme::EnsureInitialised
void EnsureInitialised() override
Definition: Theme.cpp:215
Theme::RegisterColours
void RegisterColours()
Definition: Theme.cpp:255
ThemeBase::mColourNames
wxArrayString mColourNames
Definition: Theme.h:158
ThemeBase::~ThemeBase
virtual ~ThemeBase(void)
Definition: Theme.cpp:265
ThemeBase::LoadComponents
void LoadComponents(bool bOkIfNotFound=false)
Definition: Theme.cpp:1055
FlowPacker::GetNextPosition
void GetNextPosition(int xSize, int ySize)
Definition: Theme.cpp:511
ThemeBase::ThemeTypeOfTypeName
teThemeType ThemeTypeOfTypeName(const wxString &Name)
Definition: Theme.cpp:901
Theme.h
FlowPacker::mOldFlags
int mOldFlags
Definition: Theme.h:88
ImageCacheHeight
const int ImageCacheHeight
Definition: Theme.cpp:631
HiContrastImageCacheAsData
static const unsigned char HiContrastImageCacheAsData[]
Definition: Theme.cpp:198
ThemeBase::RegisterImage
void RegisterImage(int &iIndex, char const **pXpm, const wxString &Name)
Definition: Theme.cpp:428
ThemeBase::SetBrushColour
void SetBrushColour(wxBrush &Brush, int iIndex)
Definition: Theme.cpp:1204
FlowPacker::myHeight
int myHeight
Definition: Theme.h:82
ThemeBase::Image
wxImage & Image(int iIndex)
Definition: Theme.cpp:1223
FlowPacker::myPosBase
int myPosBase
Definition: Theme.h:89
ThemeBase::MaskedImage
wxImage MaskedImage(char const **pXpm, char const **pMask)
Definition: Theme.cpp:382
DarkThemeAsCeeCode.h
ThemeBase::GetFallbackThemeType
teThemeType GetFallbackThemeType()
Definition: Theme.cpp:891
themeDark
@ themeDark
Definition: Theme.h:57
ChangeImageColour
std::unique_ptr< wxImage > ChangeImageColour(wxImage *srcImage, wxColour &dstColour)
Definition: ImageManipulation.cpp:37
FlowPacker::RectMid
void RectMid(int &x, int &y)
Definition: Theme.cpp:553
Theme::~Theme
~Theme(void)
Definition: Theme.cpp:210
FileNames::ThemeComponentsDir
FILES_API FilePath ThemeComponentsDir()
ThemeBase::RecolourTheme
void RecolourTheme()
Definition: Theme.cpp:349
ThemeBase::EnsureInitialised
virtual void EnsureInitialised()=0
ThemeBase::ThemeBase
ThemeBase(void)
Definition: Theme.cpp:259
ThemeBase::LoadTheme
void LoadTheme(teThemeType Theme)
Definition: Theme.cpp:271
LightImageCacheAsData
static const unsigned char LightImageCacheAsData[]
Definition: Theme.cpp:192
FileNames::ThemeCacheAsCee
FILES_API FilePath ThemeCacheAsCee()
BasicUI.h
Toolkit-neutral facade for basic user interface services.
Internat.h
ChoiceSetting::Read
wxString Read() const
Definition: Prefs.cpp:282
auStaticText::OnPaint
void OnPaint(wxPaintEvent &evt)
Definition: Theme.cpp:1298
ThemeBase::ReadImageCache
bool ReadImageCache(teThemeType type=themeFromFile, bool bOkIfNotFound=false)
Definition: Theme.cpp:923
ThemeBase::WriteImageMap
void WriteImageMap()
Definition: Theme.cpp:798
ThemeBase::bIsUsingSystemTextColour
bool bIsUsingSystemTextColour
Definition: Theme.h:136
themeClassic
@ themeClassic
Definition: Theme.h:56
auStaticText
is like wxStaticText, except it can be themed. wxStaticText can't be.
Definition: Theme.h:183
BasicUI
Definition: Export.h:39
MemoryX.h
FlowPacker::myPos
int myPos
Definition: Theme.h:81
GetSubImageWithAlpha
wxImage GetSubImageWithAlpha(const wxImage &Src, const wxRect &rect)
Definition: ImageManipulation.cpp:375
FlowPacker::mComponentHeight
int mComponentHeight
Definition: Theme.h:94
ThemeBase::mFlow
FlowPacker mFlow
Definition: Theme.h:159
FileNames.h
AudacityMessageBox.h
DarkImageCacheAsData
static const unsigned char DarkImageCacheAsData[]
Definition: Theme.cpp:189
SourceOutputStream::OnSysWrite
size_t OnSysWrite(const void *buffer, size_t bufsize) override
Definition: Theme.cpp:602
teThemeType
teThemeType
Definition: Theme.h:55
ThemeBase::RecolourBitmap
void RecolourBitmap(int iIndex, wxColour From, wxColour To)
Definition: Theme.cpp:330
ThemeBase::SaveThemeAsCode
void SaveThemeAsCode()
Definition: Theme.cpp:1184
ThemeBase::Colour
wxColour & Colour(int iIndex)
Definition: Theme.cpp:1197
FlowPacker::SetNewGroup
void SetNewGroup(int iGroupSize)
Definition: Theme.cpp:490
ThemeBase::MakeImageWithAlpha
wxImage MakeImageWithAlpha(wxBitmap &Bmp)
Definition: Theme.cpp:1190
FileNames::ThemeComponent
FILES_API FilePath ThemeComponent(const wxString &Str)
LightThemeAsCeeCode.h
ThemeBase::WriteImageDefs
void WriteImageDefs()
Writes a series of Macro definitions that can be used in the include file.
Definition: Theme.cpp:851
theTheme
AUDACITY_DLL_API Theme theTheme
Definition: Theme.cpp:203
ThemeBase::mBitmapFlags
std::vector< int > mBitmapFlags
Definition: Theme.h:155
themeLight
@ themeLight
Definition: Theme.h:58
FlowPacker::Rect
wxRect Rect()
Definition: Theme.cpp:543
Prefs.h
ByColumns
ByColumns_t ByColumns
Definition: Prefs.cpp:420
ThemeBase::LoadPreferredTheme
static bool LoadPreferredTheme()
Definition: Theme.cpp:231
SourceOutputStream::SourceOutputStream
SourceOutputStream()
Definition: Theme.cpp:568
FileNames::ThemeCacheHtm
FILES_API FilePath ThemeCacheHtm()
resFlagCursor
@ resFlagCursor
Definition: Theme.h:48
ThemeBase::SetPenColour
void SetPenColour(wxPen &Pen, int iIndex)
Definition: Theme.cpp:1210
END_EVENT_TABLE
END_EVENT_TABLE()
ThemeBase::RegisterColour
void RegisterColour(int &iIndex, const wxColour &Clr, const wxString &Name)
Definition: Theme.cpp:468
resFlagNewLine
@ resFlagNewLine
Definition: Theme.h:49
ImageManipulation.h
Theme::mbInitialised
bool mbInitialised
Definition: Theme.h:173
Theme::Theme
Theme(void)
Definition: Theme.cpp:205
ThemeBase::Font
wxFont & Font(int iIndex)