Audacity  2.2.2
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 
739 #ifdef IMAGE_MAP
740  wxLogDebug( "</map>" );
741 #endif
742 
743  // IF bBinarySave, THEN saving to a normal PNG file.
744  if( bBinarySave )
745  {
746  const wxString &FileName = FileNames::ThemeCachePng();
747 
748  // Perhaps we should prompt the user if they are overwriting
749  // an existing theme cache?
750 #if 0
751  if( wxFileExist( FileName ))
752  {
754  wxString::Format(
755 // _("Theme cache file:\n %s\nalready exists.\nAre you sure you want to replace it?"),
756  FileName )
757  );
758  return;
759  }
760 #endif
761 #if 0
762  // Deliberate policy to use the fast/cheap blocky pixel-multiplication
763  // algorithm, as this introduces no artifacts on repeated scale up/down.
764  ImageCache.Rescale(
765  ImageCache.GetWidth()*4,
766  ImageCache.GetHeight()*4,
767  wxIMAGE_QUALITY_NEAREST );
768 #endif
769  if( !ImageCache.SaveFile( FileName, wxBITMAP_TYPE_PNG ))
770  {
772  wxString::Format(
773  _("Audacity could not write file:\n %s."),
774  FileName ));
775  return;
776  }
778  wxString::Format(
779 /* i18n-hint: A theme is a consistent visual style across an application's
780  graphical user interface, including choices of colors, and similarity of images
781  such as those on button controls. Audacity can load and save alternative
782  themes. */
783  _("Theme written to:\n %s."),
784  FileName ));
785  }
786  // ELSE saving to a C code textual version.
787  else
788  {
789  SourceOutputStream OutStream;
790  const wxString &FileName = FileNames::ThemeCacheAsCee( );
791  if( !OutStream.OpenFile( FileName ))
792  {
794  wxString::Format(
795  _("Audacity could not open file:\n %s\nfor writing."),
796  FileName ));
797  return;
798  }
799  if( !ImageCache.SaveFile(OutStream, wxBITMAP_TYPE_PNG ) )
800  {
802  wxString::Format(
803  _("Audacity could not write images to file:\n %s."),
804  FileName ));
805  return;
806  }
808  wxString::Format(
809  /* i18n-hint "Cee" means the C computer programming language */
810  _("Theme as Cee code written to:\n %s."),
811  FileName ));
812  }
813 }
814 
818 {
820  wxBusyCursor busy;
821 
822  int i;
823  mFlow.Init( ImageCacheWidth );
824  mFlow.mBorderWidth = 1;
825 
826  wxFFile File( FileNames::ThemeCacheHtm(), wxT("wb") );// I'll put in NEW lines explicitly.
827  if( !File.IsOpened() )
828  return;
829 
830  File.Write( wxT("<html>\r\n"));
831  File.Write( wxT("<body bgcolor=\"303030\">\r\n"));
832  wxString Temp = wxString::Format( wxT("<img src=\"ImageCache.png\" width=\"%i\" usemap=\"#map1\">\r\n" ), ImageCacheWidth );
833  File.Write( Temp );
834  File.Write( wxT("<map name=\"map1\">\r\n") );
835 
836  for(i = 0; i < (int)mImages.size(); i++)
837  {
838  wxImage &SrcImage = mImages[i];
840  if( (mBitmapFlags[i] & resFlagInternal)==0)
841  {
842  mFlow.GetNextPosition( SrcImage.GetWidth(), SrcImage.GetHeight());
843  // No href in html. Uses title not alt.
844  wxRect R( mFlow.RectInner() );
845  File.Write( wxString::Format(
846  wxT("<area title=\"Bitmap:%s\" shape=rect coords=\"%i,%i,%i,%i\">\r\n"),
847  mBitmapNames[i],
848  R.GetLeft(), R.GetTop(), R.GetRight(), R.GetBottom()) );
849  }
850  }
851  // Now save the colours.
853  const int iColSize = 10;
854  for(i = 0; i < (int)mColours.size(); i++)
855  {
856  mFlow.GetNextPosition( iColSize, iColSize );
857  // No href in html. Uses title not alt.
858  wxRect R( mFlow.RectInner() );
859  File.Write( wxString::Format( wxT("<area title=\"Colour:%s\" shape=rect coords=\"%i,%i,%i,%i\">\r\n"),
860  mColourNames[i],
861  R.GetLeft(), R.GetTop(), R.GetRight(), R.GetBottom()) );
862  }
863  File.Write( wxT("</map>\r\n") );
864  File.Write( wxT("</body>\r\n"));
865  File.Write( wxT("</html>\r\n"));
866  // File will be closed automatically.
867 }
868 
871 {
873  wxBusyCursor busy;
874 
875  int i;
876  wxFFile File( FileNames::ThemeImageDefsAsCee(), wxT("wb") );
877  if( !File.IsOpened() )
878  return;
879  teResourceFlags PrevFlags = (teResourceFlags)-1;
880  for(i = 0; i < (int)mImages.size(); i++)
881  {
882  wxImage &SrcImage = mImages[i];
883  // No href in html. Uses title not alt.
884  if( PrevFlags != mBitmapFlags[i] )
885  {
886  PrevFlags = (teResourceFlags)mBitmapFlags[i];
887  int t = (int)PrevFlags;
888  wxString Temp;
889  if( t==0 ) Temp = wxT(" resFlagNone ");
890  if( t & resFlagPaired ) Temp += wxT(" resFlagPaired ");
891  if( t & resFlagCursor ) Temp += wxT(" resFlagCursor ");
892  if( t & resFlagNewLine ) Temp += wxT(" resFlagNewLine ");
893  if( t & resFlagInternal ) Temp += wxT(" resFlagInternal ");
894  Temp.Replace( wxT(" "), wxT(" | ") );
895 
896  File.Write( wxString::Format( wxT("\r\n SET_THEME_FLAGS( %s );\r\n"),
897  Temp ));
898  }
899  File.Write( wxString::Format(
900  wxT(" DEFINE_IMAGE( bmp%s, wxImage( %i, %i ), wxT(\"%s\"));\r\n"),
901  mBitmapNames[i],
902  SrcImage.GetWidth(),
903  SrcImage.GetHeight(),
904  mBitmapNames[i]
905  ));
906  }
907 }
908 
909 
911 // Fallback must be an internally supported type,
912 // to guarantee it is found.
913 #ifdef EXPERIMENTAL_DA
914  return themeDark;
915 #else
916  return themeLight;
917 #endif
918 }
919 
921 {
922  wxArrayString aThemes;
923  aThemes.Add( "classic" );
924  aThemes.Add( "dark" );
925  aThemes.Add( "light" );
926  aThemes.Add( "high-contrast" );
927  aThemes.Add( "custom" );
928  int themeIx = aThemes.Index( Name );
929  if( themeIx < 0 )
930  return GetFallbackThemeType();
931  return (teThemeType)themeIx;
932 }
933 
934 
935 
941 bool ThemeBase::ReadImageCache( teThemeType type, bool bOkIfNotFound)
942 {
944  wxImage ImageCache;
945  wxBusyCursor busy;
946 
947  // Ensure we have an alpha channel...
948 // if( !ImageCache.HasAlpha() )
949 // {
950 // ImageCache.InitAlpha();
951 // }
952 
953  gPrefs->Read(wxT("/GUI/BlendThemes"), &bRecolourOnLoad, true);
954 
955  if( type == themeFromFile )
956  {
957  const wxString &FileName = FileNames::ThemeCachePng();
958  if( !wxFileExists( FileName ))
959  {
960  if( bOkIfNotFound )
961  return false; // did not load the images, so return false.
963  wxString::Format(
964  _("Audacity could not find file:\n %s.\nTheme not loaded."),
965  FileName ));
966  return false;
967  }
968  if( !ImageCache.LoadFile( FileName, wxBITMAP_TYPE_PNG ))
969  {
970  /* i18n-hint: Do not translate png. It is the name of a file format.*/
972  wxString::Format(
973  _("Audacity could not load file:\n %s.\nBad png format perhaps?"),
974  FileName ));
975  return false;
976  }
977  }
978  // ELSE we are reading from internal storage.
979  else
980  {
981  size_t ImageSize = 0;
982  const unsigned char * pImage = nullptr;
983  switch( type ){
984  default:
985  case themeClassic :
986  ImageSize = sizeof(ClassicImageCacheAsData);
987  pImage = ClassicImageCacheAsData;
988  break;
989  case themeLight :
990  ImageSize = sizeof(LightImageCacheAsData);
991  pImage = LightImageCacheAsData;
992  break;
993  case themeDark :
994  ImageSize = sizeof(DarkImageCacheAsData);
995  pImage = DarkImageCacheAsData;
996  break;
997  case themeHiContrast :
998  ImageSize = sizeof(HiContrastImageCacheAsData);
1000  break;
1001  }
1002  //wxLogDebug("Reading ImageCache %p size %i", pImage, ImageSize );
1003  wxMemoryInputStream InternalStream( pImage, ImageSize );
1004 
1005  if( !ImageCache.LoadFile( InternalStream, wxBITMAP_TYPE_PNG ))
1006  {
1007  // If we get this message, it means that the data in file
1008  // was not a valid png image.
1009  // Most likely someone edited it by mistake,
1010  // Or some experiment is being tried with NEW formats for it.
1011  AudacityMessageBox(_("Audacity could not read its default theme.\nPlease report the problem."));
1012  return false;
1013  }
1014  //wxLogDebug("Read %i by %i", ImageCache.GetWidth(), ImageCache.GetHeight() );
1015  }
1016 
1017  // Resize a large image down.
1018  if( ImageCache.GetWidth() > ImageCacheWidth ){
1019  int h = ImageCache.GetHeight() * ((1.0*ImageCacheWidth)/ImageCache.GetWidth());
1020  ImageCache.Rescale( ImageCacheWidth, h );
1021  }
1022  int i;
1023  mFlow.Init(ImageCacheWidth);
1024  mFlow.mBorderWidth = 1;
1025  // Load the bitmaps
1026  for(i = 0; i < (int)mImages.size(); i++)
1027  {
1028  wxImage &Image = mImages[i];
1029  mFlow.mFlags = mBitmapFlags[i];
1030  if( (mBitmapFlags[i] & resFlagInternal)==0)
1031  {
1032  mFlow.GetNextPosition( Image.GetWidth(),Image.GetHeight() );
1033  // wxLogDebug(wxT("Copy at %i %i (%i,%i)"), mxPos, myPos, xWidth1, yHeight1 );
1034  Image = GetSubImageWithAlpha( ImageCache, mFlow.RectInner() );
1035  mBitmaps[i] = wxBitmap(Image);
1036  }
1037  }
1038 
1039 // return true; //To not load colours..
1040  // Now load the colours.
1041  int x,y;
1043  wxColour TempColour;
1044  const int iColSize=10;
1045  for(i = 0; i < (int)mColours.size(); i++)
1046  {
1047  mFlow.GetNextPosition( iColSize, iColSize );
1048  mFlow.RectMid( x, y );
1049  // Only change the colour if the alpha is opaque.
1050  // This allows us to add NEW colours more easily.
1051  if( ImageCache.GetAlpha(x,y ) > 128 )
1052  {
1053  TempColour = wxColour(
1054  ImageCache.GetRed( x,y),
1055  ImageCache.GetGreen( x,y),
1056  ImageCache.GetBlue(x,y));
1061  if( TempColour != wxColour(1,1,1) )
1062  mColours[i] = TempColour;
1063  }
1064  }
1065  return true;
1066 }
1067 
1068 void ThemeBase::LoadComponents( bool bOkIfNotFound )
1069 {
1070  // IF directory doesn't exist THEN return early.
1071  if( !wxDirExists( FileNames::ThemeComponentsDir() ))
1072  return;
1073 
1074  wxBusyCursor busy;
1075  int i;
1076  int n=0;
1077  wxString FileName;
1078  for(i = 0; i < (int)mImages.size(); i++)
1079  {
1080 
1081  if( (mBitmapFlags[i] & resFlagInternal)==0)
1082  {
1083  FileName = FileNames::ThemeComponent( mBitmapNames[i] );
1084  if( wxFileExists( FileName ))
1085  {
1086  if( !mImages[i].LoadFile( FileName, wxBITMAP_TYPE_PNG ))
1087  {
1088  /* i18n-hint: Do not translate png. It is the name of a file format.*/
1090  wxString::Format(
1091  _("Audacity could not load file:\n %s.\nBad png format perhaps?"),
1092  FileName ));
1093  return;
1094  }
1099  if( ! mImages[i].HasAlpha() )
1100  {
1101  // wxLogDebug( wxT("File %s lacked alpha"), mBitmapNames[i] );
1102  mImages[i].InitAlpha();
1103  }
1104  mBitmaps[i] = wxBitmap( mImages[i] );
1105  n++;
1106  }
1107  }
1108  }
1109  if( n==0 )
1110  {
1111  if( bOkIfNotFound )
1112  return;
1113  AudacityMessageBox(wxString::Format(_("None of the expected theme component files\n were found in:\n %s."),
1115  }
1116 }
1117 
1119 {
1120  // IF directory doesn't exist THEN create it
1121  if( !wxDirExists( FileNames::ThemeComponentsDir() ))
1122  {
1128 #ifdef __WXMSW__
1129  wxMkDir( FileNames::ThemeComponentsDir().fn_str() );
1130 #else
1131  wxMkDir( FileNames::ThemeComponentsDir().fn_str(), 0700 );
1132 #endif
1133  if( !wxDirExists( FileNames::ThemeComponentsDir() ))
1134  {
1136  wxString::Format(
1137  _("Could not create directory:\n %s"),
1139  return;
1140  }
1141  }
1142 
1143  wxBusyCursor busy;
1144  int i;
1145  int n=0;
1146  wxString FileName;
1147  for(i = 0; i < (int)mImages.size(); i++)
1148  {
1149  if( (mBitmapFlags[i] & resFlagInternal)==0)
1150  {
1151  FileName = FileNames::ThemeComponent( mBitmapNames[i] );
1152  if( wxFileExists( FileName ))
1153  {
1154  ++n;
1155  break;
1156  }
1157  }
1158  }
1159 
1160  if (n > 0)
1161  {
1162  auto result =
1164  wxString::Format(
1165  _("Some required files in:\n %s\nwere already present. Overwrite?"),
1168  wxYES_NO | wxNO_DEFAULT);
1169  if(result == wxNO)
1170  return;
1171  }
1172 
1173  for(i = 0; i < (int)mImages.size(); i++)
1174  {
1175  if( (mBitmapFlags[i] & resFlagInternal)==0)
1176  {
1177  FileName = FileNames::ThemeComponent( mBitmapNames[i] );
1178  if( !mImages[i].SaveFile( FileName, wxBITMAP_TYPE_PNG ))
1179  {
1181  wxString::Format(
1182  _("Audacity could not save file:\n %s"),
1183  FileName ));
1184  return;
1185  }
1186  }
1187  }
1189  wxString::Format(
1190  _("Theme written to:\n %s."),
1192 }
1193 
1194 
1196 {
1197  // false indicates not using standard binary method.
1198  CreateImageCache( false );
1199 }
1200 
1201 wxImage ThemeBase::MakeImageWithAlpha( wxBitmap & Bmp )
1202 {
1203  // BUG in wxWidgets. Conversion from BMP to image does not preserve alpha.
1204  wxImage image( Bmp.ConvertToImage() );
1205  return image;
1206 }
1207 
1208 wxColour & ThemeBase::Colour( int iIndex )
1209 {
1210  wxASSERT( iIndex >= 0 );
1212  return mColours[iIndex];
1213 }
1214 
1215 void ThemeBase::SetBrushColour( wxBrush & Brush, int iIndex )
1216 {
1217  wxASSERT( iIndex >= 0 );
1218  Brush.SetColour( Colour( iIndex ));
1219 }
1220 
1221 void ThemeBase::SetPenColour( wxPen & Pen, int iIndex )
1222 {
1223  wxASSERT( iIndex >= 0 );
1224  Pen.SetColour( Colour( iIndex ));
1225 }
1226 
1227 wxBitmap & ThemeBase::Bitmap( int iIndex )
1228 {
1229  wxASSERT( iIndex >= 0 );
1231  return mBitmaps[iIndex];
1232 }
1233 
1234 wxImage & ThemeBase::Image( int iIndex )
1235 {
1236  wxASSERT( iIndex >= 0 );
1238  return mImages[iIndex];
1239 }
1240 wxSize ThemeBase::ImageSize( int iIndex )
1241 {
1242  wxASSERT( iIndex >= 0 );
1244  wxImage & Image = mImages[iIndex];
1245  return wxSize( Image.GetWidth(), Image.GetHeight());
1246 }
1247 
1248 // The next two functions are for future use.
1249 #if 0
1250 wxCursor & ThemeBase::Cursor( int iIndex )
1251 {
1252  wxASSERT( iIndex >= 0 );
1254  // Purposeful null deref. Function is for future use.
1255  // If anyone tries to use it now they will get an error.
1256  return *(wxCursor*)NULL;
1257 }
1258 
1259 wxFont & ThemeBase::Font( int iIndex )
1260 {
1261  wxASSERT( iIndex >= 0 );
1263  // Purposeful null deref. Function is for future use.
1264  // If anyone tries to use it now they will get an error.
1265  return *(wxFont*)NULL;
1266 }
1267 #endif
1268 
1270 void ThemeBase::ReplaceImage( int iIndex, wxImage * pImage )
1271 {
1272  Image( iIndex ) = *pImage;
1273  Bitmap( iIndex ) = wxBitmap( *pImage );
1274 }
1275 
1276 void ThemeBase::RotateImageInto( int iTo, int iFrom, bool bClockwise )
1277 {
1278  wxImage img(theTheme.Bitmap( iFrom ).ConvertToImage() );
1279  wxImage img2 = img.Rotate90( bClockwise );
1280  ReplaceImage( iTo, &img2 );
1281 }
1282 
1283 BEGIN_EVENT_TABLE(auStaticText, wxWindow)
1284  EVT_PAINT(auStaticText::OnPaint)
1286 
1287 
1288 auStaticText::auStaticText(wxWindow* parent, wxString textIn) :
1289  wxWindow(parent, wxID_ANY)
1290 {
1291  int textWidth, textHeight;
1292 
1293  int fontSize = 11;
1294  #ifdef __WXMSW__
1295  fontSize = 9;
1296  #endif
1297  wxFont font(fontSize, wxDEFAULT, wxNORMAL, wxNORMAL);
1298  GetTextExtent(textIn, &textWidth, &textHeight, NULL, NULL, &font);
1299 
1300  SetFont( font );
1301  SetMinSize( wxSize(textWidth, textHeight) );
1302  SetBackgroundColour( theTheme.Colour( clrMedium));
1303  SetForegroundColour( theTheme.Colour( clrTrackPanelText));
1304  SetName(textIn);
1305  SetLabel(textIn);
1306 }
1307 
1308 void auStaticText::OnPaint(wxPaintEvent & WXUNUSED(evt))
1309 {
1310  wxPaintDC dc(this);
1311  //dc.SetTextForeground( theTheme.Colour( clrTrackPanelText));
1312  dc.DrawText( GetLabel(), 0,0);
1313 }
1314 
1315 
wxRect Rect()
Definition: Theme.cpp:570
void SaveComponents()
Definition: Theme.cpp:1118
wxString AudacityMessageBoxCaptionStr()
void RotateImageInto(int iTo, int iFrom, bool bClockwise)
Definition: Theme.cpp:1276
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:464
AProjectArray gAudacityProjects
Definition: Project.cpp:295
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:281
void EnsureInitialised() override
Definition: Theme.cpp:221
wxSize ImageSize(int iIndex)
Definition: Theme.cpp:1240
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:271
static wxString ThemeComponent(const wxString &Str)
Definition: FileNames.cpp:291
void ReplaceImage(int iIndex, wxImage *pImage)
Replaces both the image and the bitmap.
Definition: Theme.cpp:1270
std::unique_ptr< Character[], freer > MallocString
Definition: MemoryX.h:798
wxCursor & Cursor(int iIndex)
wxBitmap & Bitmap(int iIndex)
Definition: Theme.cpp:1227
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:158
teThemeType ThemeTypeOfTypeName(const wxString &Name)
Definition: Theme.cpp:920
static wxString ThemeImageDefsAsCee()
Definition: FileNames.cpp:276
int mBorderWidth
Definition: Theme.h:78
wxFileConfig * gPrefs
Definition: Prefs.cpp:72
virtual void ApplyUpdatedTheme()
Definition: Project.cpp:1260
wxArrayString mBitmapNames
Definition: Theme.h:148
void SetBrushColour(wxBrush &Brush, int iIndex)
Definition: Theme.cpp:1215
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:1409
void LoadComponents(bool bOkIfNotFound=false)
Definition: Theme.cpp:1068
ToolManager * GetToolManager()
Definition: Project.h:688
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:1234
wxImage MaskedImage(char const **pXpm, char const **pMask)
Definition: Theme.cpp:409
teThemeType GetFallbackThemeType()
Definition: Theme.cpp:910
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"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom"))), OnMoveTrack) void TrackMenuTable::OnSetName(wxCommandEvent &)
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:941
void WriteImageMap()
Definition: Theme.cpp:817
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:266
void OnPaint(wxPaintEvent &evt)
Definition: Theme.cpp:1308
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:261
static bool LoadPreferredTheme()
Definition: Theme.cpp:237
void SaveThemeAsCode()
Definition: Theme.cpp:1195
wxColour & Colour(int iIndex)
Definition: Theme.cpp:1208
wxImage MakeImageWithAlpha(wxBitmap &Bmp)
Definition: Theme.cpp:1201
END_EVENT_TABLE()
void ReCreateButtons()
Definition: Ruler.cpp:2082
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:870
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:1221
std::vector< wxImage > mImages
Definition: Theme.h:146
void RegisterColour(int &iIndex, const wxColour &Clr, const wxString &Name)
Definition: Theme.cpp:495