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