Audacity 3.2.0
Classes | Public Types | Public Member Functions | Static Public Member Functions | Protected Attributes | List of all members
ThemeBase Class Referenceabstract

Theme management - Image loading and saving. More...

#include <Theme.h>

Inheritance diagram for ThemeBase:
[legend]
Collaboration diagram for ThemeBase:
[legend]

Classes

struct  RegisteredTheme
 

Public Types

using NameSet = std::unordered_set< wxString >
 
- Public Types inherited from Observer::Publisher< ThemeChangeMessage >
using message_type = ThemeChangeMessage
 
using CallbackReturn = std::conditional_t< true, void, bool >
 
using Callback = std::function< CallbackReturn(const ThemeChangeMessage &) >
 Type of functions that can be connected to the Publisher. More...
 

Public Member Functions

 ThemeBase (void)
 
 ThemeBase (const ThemeBase &)=delete
 
ThemeBaseoperator= (const ThemeBase &)=delete
 
virtual ~ThemeBase (void)
 
virtual void EnsureInitialised ()=0
 
FilePath GetFilePath ()
 
void SetFilePath (const FilePath &path)
 
void SwitchTheme (teThemeType Theme)
 
void LoadTheme (teThemeType Theme)
 
void RegisterImage (NameSet &allNames, int &flags, int &iIndex, char const **pXpm, const wxString &Name)
 
void RegisterImage (NameSet &allNames, int &flags, int &iIndex, const wxImage &Image, const wxString &Name)
 
void RegisterColour (NameSet &allNames, int &iIndex, const wxColour &Clr, const wxString &Name)
 
teThemeType GetFallbackThemeType ()
 
void CreateImageCache ()
 
bool CreateOneImageCache (teThemeType id, bool bBinarySave)
 
bool ReadImageCache (teThemeType type={}, bool bOkIfNotFound=false)
 
void LoadThemeComponents (bool bOkIfNotFound=false)
 
void LoadOneThemeComponents (teThemeType id, bool bOkIfNotFound=false)
 
void SaveThemeComponents ()
 
bool SaveOneThemeComponents (teThemeType id)
 
void SaveThemeAsCode ()
 
void WriteImageDefs ()
 Writes a series of Macro definitions that can be used in the include file. More...
 
void WriteImageMap ()
 
void WriteOneImageMap (teThemeType id)
 
void RecolourBitmap (int iIndex, wxColour From, wxColour To)
 
int ColourDistance (wxColour &From, wxColour &To)
 
wxColour & Colour (int iIndex)
 
wxBitmap & Bitmap (int iIndex)
 
wxImageImage (int iIndex)
 
wxSize ImageSize (int iIndex)
 
void ReplaceImage (int iIndex, wxImage *pImage)
 
void RotateImageInto (int iTo, int iFrom, bool bClockwise)
 
void SetBrushColour (wxBrush &Brush, int iIndex)
 
void SetPenColour (wxPen &Pen, int iIndex)
 
wxImage MaskedImage (char const **pXpm, char const **pMask)
 
wxImage MakeImageWithAlpha (wxBitmap &Bmp)
 
void DeleteUnusedThemes ()
 
- Public Member Functions inherited from Observer::Publisher< ThemeChangeMessage >
 Publisher (ExceptionPolicy *pPolicy=nullptr, Alloc a={})
 Constructor supporting type-erased custom allocation/deletion. More...
 
 Publisher (Publisher &&)=default
 
Publisheroperator= (Publisher &&)=default
 
Subscription Subscribe (Callback callback)
 Connect a callback to the Publisher; later-connected are called earlier. More...
 
Subscription Subscribe (Object &obj, Return(Object::*callback)(Args...))
 Overload of Subscribe takes an object and pointer-to-member-function. More...
 

Static Public Member Functions

static bool LoadPreferredTheme ()
 

Protected Attributes

FilePath mThemeDir
 
wxArrayString mBitmapNames
 
std::vector< int > mBitmapFlags
 
wxArrayString mColourNames
 
PreferredSystemAppearance mPreferredSystemAppearance { PreferredSystemAppearance::Light }
 
std::map< Identifier, ThemeSetmSets
 
ThemeSetmpSet = nullptr
 

Additional Inherited Members

- Static Public Attributes inherited from Observer::Publisher< ThemeChangeMessage >
static constexpr bool notifies_all
 
- Protected Member Functions inherited from Observer::Publisher< ThemeChangeMessage >
CallbackReturn Publish (const ThemeChangeMessage &message)
 Send a message to connected callbacks. More...
 

Detailed Description

Theme management - Image loading and saving.

Base for the Theme class. ThemeBase is a generic non-Audacity specific class.

See also
Themability of Audacity

Definition at line 116 of file Theme.h.

Member Typedef Documentation

◆ NameSet

using ThemeBase::NameSet = std::unordered_set<wxString>

Definition at line 151 of file Theme.h.

Constructor & Destructor Documentation

◆ ThemeBase() [1/2]

ThemeBase::ThemeBase ( void  )

Definition at line 185 of file Theme.cpp.

186{
187}

◆ ThemeBase() [2/2]

ThemeBase::ThemeBase ( const ThemeBase )
delete

◆ ~ThemeBase()

ThemeBase::~ThemeBase ( void  )
virtual

Definition at line 189 of file Theme.cpp.

190{
191}

Member Function Documentation

◆ Bitmap()

wxBitmap & ThemeBase::Bitmap ( int  iIndex)

◆ Colour()

wxColour & ThemeBase::Colour ( int  iIndex)

Referenced by AboutDialog::AboutDialog(), SelectionBar::AddTitle(), TimeSignatureToolBar::AddTitle(), AlphaBlend(), ProjectWindow::ApplyUpdatedTheme(), ASlider::ASlider(), auStaticText::auStaticText(), AColor::BevelTrackInfo(), CommonTrackInfo::CloseTitleDrawFunction(), CursorColour(), WaveChannelVRulerControls::DoDraw(), AdornedRulerPanel::DoDrawMarks(), AdornedRulerPanel::DoDrawPlayRegion(), AdornedRulerPanel::DoDrawPlayRegionLimits(), LabelTrackView::Draw(), NoteTrackAffordanceControls::Draw(), WaveTrackAffordanceControls::Draw(), TimeTrackVRulerControls::Draw(), RulerUpdater::Label::Draw(), CommonTrackInfo::DrawCloseButton(), anonymous_namespace{TimeTrackView.cpp}::DrawHorzRulerAndCurve(), CommonTrackInfo::DrawItems(), anonymous_namespace{NoteTrackControls.cpp}::DrawLabelControls(), anonymous_namespace{NoteTrackView.cpp}::DrawNoteTrack(), FrequencyPlotDialog::DrawPlot(), LWSlider::DrawToBitmap(), HighlitClipButtonHandle::Highlight(), HtmlColourOfIndex(), AColor::Init(), NumericTextCtrl::Layout(), AudioSetupToolBar::MakeAudioSetupButton(), MixerBoard::MakeButtonBitmap(), audacity::cloud::ShareAudioToolbar::MakeShareAudioButton(), WaveTrackAffordanceControls::MakeTextEditHelper(), anonymous_namespace{SplashDialog.cpp}::MakeWhatsNewText(), CommonTrackInfo::MinimizeSyncLockDrawFunction(), MixerBoard::MixerBoard(), ToolManager::OnIndicatorPaint(), anonymous_namespace{RealtimeEffectPanel.cpp}::RealtimeEffectControl::OnPaint(), EqualizationPanel::OnPaint(), ToolBarResizer::OnPaint(), ToolBar::OnPaint(), ToolDock::OnPaint(), NumericTextCtrl::OnPaint(), EffectAutoDuck::Panel::OnPaint(), EffectCompressorPanel::OnPaint(), EffectScienFilterPanel::OnPaint(), MixerTrackCluster::OnPaint(), MeterPanel::OnPaint(), ToolFrame::OnPaint(), ThemedWindowWrapper< WindowBase >::OnThemeChange(), ThemedButtonWrapper< ButtonBase >::OnThemeChange(), ThemedAButtonWrapper< AButtonBase >::OnThemeChange(), OverlayImage(), FrequencyPlotDialog::Populate(), audacity::cloud::ShareAudioToolbar::Populate(), AudioSetupToolBar::Populate(), ControlToolBar::Populate(), CutCopyPasteToolBar::Populate(), DeviceToolBar::Populate(), EditToolBar::Populate(), MeterToolBar::Populate(), SelectionBar::Populate(), SnappingToolBar::Populate(), SpectralSelectionBar::Populate(), TimeSignatureToolBar::Populate(), ToolsToolBar::Populate(), TranscriptionToolBar::Populate(), AColor::PreComputeGradient(), AdornedRulerPanel::ReCreateButtons(), Ruler::Ruler(), ThemedWindowWrapper< WindowBase >::SetBackgroundColorIndex(), ThemedButtonWrapper< ButtonBase >::SetBackgroundColorIndex(), ThemedAButtonWrapper< AButtonBase >::SetBackgroundColorIndex(), ThemedWindowWrapper< WindowBase >::SetForegroundColorIndex(), ThemedAButtonWrapper< AButtonBase >::SetForegroundColorIndex(), ToolDock::ToolDock(), MixerBoard::UpdatePrefs(), and AColor::UseThemeColour().

◆ ColourDistance()

int ThemeBase::ColourDistance ( wxColour &  From,
wxColour &  To 
)

Definition at line 285 of file Theme.cpp.

285 {
286 return
287 abs( From.Red() - To.Red() )
288 + abs( From.Green() - To.Green() )
289 + abs( From.Blue() - To.Blue() );
290}

Referenced by CursorColour(), and MeterPanel::OnPaint().

Here is the caller graph for this function:

◆ CreateImageCache()

void ThemeBase::CreateImageCache ( )

Definition at line 556 of file Theme.cpp.

557{
558 ValueRestorer cleanup{ mpSet };
559 for (auto &[key, data] : GetThemeCacheLookup())
560 if (!CreateOneImageCache(key.Internal(), true))
561 // Some file failed to save, message was given
562 return;
564/* i18n-hint: A theme is a consistent visual style across an application's
565graphical user interface, including choices of colors, and similarity of images
566such as those on button controls. Audacity can load and save alternative
567themes. */
568 XO("Themes written to:\n %s/*/%s.")
570}
XO("Cut/Copy/Paste")
static const AudacityProject::AttachedObjects::RegisteredFactory key
static ThemeCacheLookup & GetThemeCacheLookup()
Definition: Theme.cpp:196
Abstract base class used in importing a file.
ThemeSet * mpSet
Definition: Theme.h:205
bool CreateOneImageCache(teThemeType id, bool bBinarySave)
Definition: Theme.cpp:572
FilePath GetFilePath()
Definition: Theme.cpp:149
Set a variable temporarily in a scope.
Definition: MemoryX.h:214
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:279
constexpr auto ImageCacheFileName
Definition: Theme.cpp:118

References CreateOneImageCache(), GetFilePath(), GetThemeCacheLookup(), anonymous_namespace{Theme.cpp}::ImageCacheFileName, key, mpSet, BasicUI::ShowMessageBox(), and XO().

Referenced by ThemePrefs::OnSaveThemeCache(), and SwitchTheme().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ CreateOneImageCache()

bool ThemeBase::CreateOneImageCache ( teThemeType  id,
bool  bBinarySave 
)

Definition at line 572 of file Theme.cpp.

573{
574 SwitchTheme( id );
575 auto &resources = *mpSet;
576
578 ImageCache.SetRGB( wxRect( 0,0,ImageCacheWidth, ImageCacheHeight), 1,1,1);//Not-quite black.
579
580 // Ensure we have an alpha channel...
581 if( !ImageCache.HasAlpha() )
582 {
583 ImageCache.InitAlpha();
584 }
585
586 FlowPacker context{ ImageCacheWidth };
587
588//#define IMAGE_MAP
589#ifdef IMAGE_MAP
590 wxLogDebug( wxT("<img src=\"ImageCache.png\" usemap=\"#map1\">" ));
591 wxLogDebug( wxT("<map name=\"map1\">") );
592#endif
593
594 // Save the bitmaps
595 for (size_t i = 0; i < resources.mImages.size() ; ++i)
596 {
597 wxImage &SrcImage = resources.mImages[i];
598 context.mFlags = mBitmapFlags[i];
599 if( !(mBitmapFlags[i] & resFlagInternal) )
600 {
601 context.GetNextPosition( SrcImage.GetWidth(), SrcImage.GetHeight());
602 ImageCache.SetRGB( context.Rect(), 0xf2, 0xb0, 0x27 );
603 if( !(context.mFlags & resFlagSkip) )
604 PasteSubImage( &ImageCache, &SrcImage,
605 context.mxPos + context.mBorderWidth,
606 context.myPos + context.mBorderWidth);
607 else
608 ImageCache.SetRGB( context.RectInner(), 1,1,1);
609#ifdef IMAGE_MAP
610 // No href in html. Uses title not alt.
611 wxRect R( context.Rect() );
612 wxLogDebug( wxT("<area title=\"Bitmap:%s\" shape=rect coords=\"%i,%i,%i,%i\">"),
613 mBitmapNames[i],
614 R.GetLeft(), R.GetTop(), R.GetRight(), R.GetBottom() );
615#endif
616 }
617 }
618
619 // Now save the colours.
620 int x,y;
621
622 context.SetColourGroup();
623 for (size_t i = 0; i < resources.mColours.size(); ++i)
624 {
625 context.GetNextPosition( iColSize, iColSize );
626 wxColour c = resources.mColours[i];
627 ImageCache.SetRGB( context.Rect() , 0xf2, 0xb0, 0x27 );
628 ImageCache.SetRGB( context.RectInner() , c.Red(), c.Green(), c.Blue() );
629
630 // YUCK! No function in wxWidgets to set a rectangle of alpha...
631 for(x=0;x<iColSize;x++)
632 {
633 for(y=0;y<iColSize;y++)
634 {
635 ImageCache.SetAlpha( context.mxPos + x, context.myPos+y, 255);
636 }
637 }
638#ifdef IMAGE_MAP
639 // No href in html. Uses title not alt.
640 wxRect R( context.Rect() );
641 wxLogDebug( wxT("<area title=\"Colour:%s\" shape=rect coords=\"%i,%i,%i,%i\">"),
642 mColourNames[i],
643 R.GetLeft(), R.GetTop(), R.GetRight(), R.GetBottom() );
644#endif
645 }
646#if TEST_CARD
647 for ( unsigned i = 0; i < ImageCacheWidth; ++i)
648 for ( unsigned j = 0; j < ImageCacheHeight; ++j) {
649 int r = j &0xff;
650 int g = i &0xff;
651 int b = (j >> 8) | ((i>>4)&0xf0);
652 wxRect R( i,j, 1, 1);
653 ImageCache.SetRGB( R, r, g, b );
654 ImageCache.SetAlpha( i,j, 255);
655 }
656#endif
657
658#ifdef IMAGE_MAP
659 wxLogDebug( "</map>" );
660#endif
661
662 using namespace BasicUI;
663
664 // IF bBinarySave, THEN saving to a normal PNG file.
665 if( bBinarySave )
666 {
667 auto dir = ThemeSubdir(GetFilePath(), id);
668 auto FileName = wxFileName{ dir, ImageCacheFileName }.GetFullPath();
669
670 // Perhaps we should prompt the user if they are overwriting
671 // an existing theme cache?
672#if 0
673 if( wxFileExists( FileName ))
674 {
675 auto message =
676// XO(
677//"Theme cache file:\n %s\nalready exists.\nAre you sure you want to replace it?")
678// .Format( FileName );
679 TranslatableString{ FileName };
680 ShowMessageBox( message );
681 return false;
682 }
683#endif
684#if 0
685 // Deliberate policy to use the fast/cheap blocky pixel-multiplication
686 // algorithm, as this introduces no artifacts on repeated scale up/down.
687 ImageCache.Rescale(
688 ImageCache.GetWidth()*4,
689 ImageCache.GetHeight()*4,
690 wxIMAGE_QUALITY_NEAREST );
691#endif
692 if( !ImageCache.SaveFile( FileName, wxBITMAP_TYPE_PNG ))
693 {
695 XO("Audacity could not write file:\n %s.")
696 .Format( FileName ));
697 return false;
698 }
699 }
700 // ELSE saving to a C code textual version.
701 else
702 {
703 // Generated header file is not put in the sub-directory for
704 // the theme, but is instead distinguished by a prefix on the file name.
705 // So the header can simply be copied into the source code tree.
706 auto dir = GetFilePath();
707 SourceOutputStream OutStream;
709 auto FileName = wxFileName{ dir, name }.GetFullPath();
710 if( !OutStream.OpenFile( FileName ))
711 {
713 XO("Audacity could not open file:\n %s\nfor writing.")
714 .Format( FileName ));
715 return false;
716 }
717 if( !ImageCache.SaveFile(OutStream, wxBITMAP_TYPE_PNG ) )
718 {
720 XO("Audacity could not write images to file:\n %s.")
721 .Format( FileName ));
722 return false;
723 }
724 }
725 return true;
726}
wxImage(22, 22)
wxT("CloseDown"))
const TranslatableString name
Definition: Distortion.cpp:76
void PasteSubImage(wxImage *background, wxImage *foreground, int xoff, int yoff)
const int ImageCacheWidth
Definition: Theme.cpp:552
const int ImageCacheHeight
Definition: Theme.cpp:554
@ resFlagSkip
Definition: Theme.h:65
@ resFlagInternal
Definition: Theme.h:64
A cursor for iterating the theme bitmap.
Definition: Theme.h:70
Helper class based on wxOutputStream used to get a png file in text format.
Definition: Theme.cpp:493
int OpenFile(const FilePath &Filename)
Opens the file and also adds a standard comment at the start of it.
Definition: Theme.cpp:506
void SwitchTheme(teThemeType Theme)
Definition: Theme.cpp:217
wxArrayString mBitmapNames
Definition: Theme.h:198
wxArrayString mColourNames
Definition: Theme.h:200
std::vector< int > mBitmapFlags
Definition: Theme.h:199
Holds a msgid for the translation catalog; may also bind format arguments.
constexpr auto ThemeCacheFileName
Definition: Theme.cpp:129
FilePath ThemeSubdir(const FilePath &themeDir, Identifier id)
Has the side-effect of ensuring existence of the directory.
Definition: Theme.cpp:106
wxString ThemeFilePrefix(teThemeType id)
Definition: Theme.cpp:96

References GetFilePath(), anonymous_namespace{Theme.cpp}::iColSize, anonymous_namespace{Theme.cpp}::ImageCacheFileName, ImageCacheHeight, ImageCacheWidth, mBitmapFlags, mBitmapNames, mColourNames, mpSet, name, SourceOutputStream::OpenFile(), PasteSubImage(), resFlagInternal, resFlagSkip, BasicUI::ShowMessageBox(), SwitchTheme(), anonymous_namespace{Theme.cpp}::ThemeCacheFileName, anonymous_namespace{Theme.cpp}::ThemeFilePrefix(), anonymous_namespace{Theme.cpp}::ThemeSubdir(), wxImage(), wxT(), and XO().

Referenced by CreateImageCache().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ DeleteUnusedThemes()

void ThemeBase::DeleteUnusedThemes ( )

Referenced by ThemePrefs::Cancel(), GUIPrefs::Commit(), and ThemePrefs::Commit().

Here is the caller graph for this function:

◆ EnsureInitialised()

virtual void ThemeBase::EnsureInitialised ( )
pure virtual

Implemented in Theme.

Referenced by ReadImageCache(), SwitchTheme(), and WriteImageDefs().

Here is the caller graph for this function:

◆ GetFallbackThemeType()

teThemeType ThemeBase::GetFallbackThemeType ( )

Definition at line 831 of file Theme.cpp.

831 {
832// Fallback must be an internally supported type,
833// to guarantee it is found.
834 return "light";
835}

Referenced by ThemePrefs::OnReadThemeInternal(), and SwitchTheme().

Here is the caller graph for this function:

◆ GetFilePath()

FilePath ThemeBase::GetFilePath ( )

Definition at line 149 of file Theme.cpp.

150{
151 if (mThemeDir.empty())
153 wxFileName(FileNames::DataDir(), wxT("Theme")).GetFullPath());
154 return mThemeDir;
155}
FilePath mThemeDir
Definition: Theme.h:196
void SetFilePath(const FilePath &path)
Definition: Theme.cpp:157
FILES_API FilePath DataDir()
Audacity user data directory.

References FileNames::DataDir(), mThemeDir, SetFilePath(), and wxT().

Referenced by CreateImageCache(), CreateOneImageCache(), LoadOneThemeComponents(), ReadImageCache(), WriteImageDefs(), and WriteOneImageMap().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Image()

wxImage & ThemeBase::Image ( int  iIndex)

◆ ImageSize()

wxSize ThemeBase::ImageSize ( int  iIndex)

Referenced by TranscriptionToolBar::AddButton(), ToolBarButtons::CreateButton(), ControlToolBar::MakeAlternateImages(), TranscriptionToolBar::MakeAlternateImages(), ToolBar::MakeButton(), ToolsToolBar::MakeTool(), ReadImageCache(), and AdornedRulerPanel::ReCreateButtons().

Here is the caller graph for this function:

◆ LoadOneThemeComponents()

void ThemeBase::LoadOneThemeComponents ( teThemeType  id,
bool  bOkIfNotFound = false 
)

JKC:

Bug:
(wxWidgets) A png may have been saved with alpha, but when you load it, it comes back with a mask instead! (well I guess it is more efficient). Anyway, we want alpha and not a mask, so we call InitAlpha, and that transfers the mask into the alpha channel, and we're done.

Definition at line 979 of file Theme.cpp.

References details::begin(), anonymous_namespace{Theme.cpp}::ColorFileName, details::end(), TranslatableString::Format(), GetFilePath(), mBitmapFlags, mBitmapNames, mColourNames, mpSet, name, names, resFlagInternal, BasicUI::ShowMessageBox(), str, SwitchTheme(), anonymous_namespace{Theme.cpp}::ThemeComponent(), anonymous_namespace{Theme.cpp}::ThemeComponentsDir(), Verbatim(), and XO().

Referenced by LoadThemeComponents().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ LoadPreferredTheme()

bool ThemeBase::LoadPreferredTheme ( )
static

Definition at line 162 of file Theme.cpp.

163{
166 return true;
167}
static ThemeBase::RegisteredTheme theme
THEME_API Theme theTheme
Definition: Theme.cpp:82
THEME_API ChoiceSetting & GUITheme()
wxString Read() const
Definition: Prefs.cpp:388
An explicitly nonlocalized string, not meant for the user to see.
Definition: Identifier.h:22
void LoadTheme(teThemeType Theme)
Definition: Theme.cpp:255

References GUITheme(), LoadTheme(), ChoiceSetting::Read(), theme, and theTheme.

Referenced by ThemePrefs::Cancel(), GUIPrefs::Commit(), ThemePrefs::Commit(), and AudacityApp::OnInit().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ LoadTheme()

void ThemeBase::LoadTheme ( teThemeType  Theme)

This function is called to load the initial Theme images. It does not though cause the GUI to refresh.

Definition at line 255 of file Theme.cpp.

256{
258
259 // Post-processing steps after loading of the cache
260
261 // Two always overwritten images
262 RotateImageInto( bmpRecordBeside, bmpRecordBelow, false );
263 RotateImageInto( bmpRecordBesideDisabled, bmpRecordBelowDisabled, false );
264
265 // Next line is not required as we haven't yet built the GUI
266 // when this function is (or should be) called.
267 // AColor::ApplyUpdatedImages();
268
269 // The next step doesn't post-process the theme data. It only modifies
270 // system settings. So it is not necessary to make it conditional on
271 // preferences, for avoidance of errors in the use of Theme preferences.
272 // (See commit 2020217)
274}
CallbackReturn Publish(const ThemeChangeMessage &message)
Send a message to connected callbacks.
Definition: Observer.h:207
void RotateImageInto(int iTo, int iFrom, bool bClockwise)
PreferredSystemAppearance mPreferredSystemAppearance
Definition: Theme.h:202
Based on ThemeBase, Theme manages image and icon resources.
Definition: Theme.h:209

References mPreferredSystemAppearance, Observer::Publisher< ThemeChangeMessage >::Publish(), RotateImageInto(), and SwitchTheme().

Referenced by LoadPreferredTheme().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ LoadThemeComponents()

void ThemeBase::LoadThemeComponents ( bool  bOkIfNotFound = false)

Definition at line 972 of file Theme.cpp.

973{
974 ValueRestorer cleanup{ mpSet };
975 for (auto &[key, data] : GetThemeCacheLookup())
976 LoadOneThemeComponents( key.Internal(), bOkIfNotFound );
977}
void LoadOneThemeComponents(teThemeType id, bool bOkIfNotFound=false)
Definition: Theme.cpp:979

References GetThemeCacheLookup(), key, LoadOneThemeComponents(), and mpSet.

Referenced by App::OnInit(), and ThemePrefs::OnLoadThemeComponents().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ MakeImageWithAlpha()

wxImage ThemeBase::MakeImageWithAlpha ( wxBitmap &  Bmp)

◆ MaskedImage()

wxImage ThemeBase::MaskedImage ( char const **  pXpm,
char const **  pMask 
)

Definition at line 292 of file Theme.cpp.

293{
294 wxBitmap Bmp1( pXpm );
295 wxBitmap Bmp2( pMask );
296
297// wxLogDebug( wxT("Image 1: %i Image 2: %i"),
298// Bmp1.GetDepth(), Bmp2.GetDepth() );
299
300 // We want a 24-bit-depth bitmap if all is working, but on some
301 // platforms it might just return -1 (which means best available
302 // or not relevant).
303 // JKC: \todo check that we're not relying on 24 bit elsewhere.
304 wxASSERT( Bmp1.GetDepth()==-1 || Bmp1.GetDepth()==24);
305 wxASSERT( Bmp1.GetDepth()==-1 || Bmp2.GetDepth()==24);
306
307 int i,nBytes;
308 nBytes = Bmp1.GetWidth() * Bmp1.GetHeight();
309 wxImage Img1( Bmp1.ConvertToImage());
310 wxImage Img2( Bmp2.ConvertToImage());
311
312// unsigned char *src = Img1.GetData();
313 unsigned char *mk = Img2.GetData();
314 //wxImage::setAlpha requires memory allocated with malloc, not NEW
316 static_cast<unsigned char*>(malloc( nBytes )) };
317
318 // Extract alpha channel from second XPM.
319 for(i=0;i<nBytes;i++)
320 {
321 alpha[i] = mk[0];
322 mk+=3;
323 }
324
325 Img1.SetAlpha( alpha.release() );
326
327 //dmazzoni: the top line does not work on wxGTK
328 //wxBitmap Result( Img1, 32 );
329 //wxBitmap Result( Img1 );
330
331 return Img1;
332}
std::unique_ptr< Character[], freer > MallocString
Definition: MemoryX.h:148

References wxImage().

Here is the call graph for this function:

◆ operator=()

ThemeBase & ThemeBase::operator= ( const ThemeBase )
delete

◆ ReadImageCache()

bool ThemeBase::ReadImageCache ( teThemeType  type = {},
bool  bOkIfNotFound = false 
)

Reads an image cache including images, cursors and colours.

Parameters
typeif empty means read from an external binary file. otherwise the data is taken from a block of memory.
bOkIfNotFoundif true means do not report absent file.
Returns
true iff we loaded the images.
Todo:
revisit this hack which makes adding NEW colours easier but which prevents a colour of (1,1,1) from being added. find an alternative way to make adding NEW colours easier. e.g. initialise the background to translucent, perhaps.

Definition at line 842 of file Theme.cpp.

843{
844 auto &resources = *mpSet;
846 wxImage ImageCache;
847
848 // Ensure we have an alpha channel...
849// if( !ImageCache.HasAlpha() )
850// {
851// ImageCache.InitAlpha();
852// }
853
854 using namespace BasicUI;
855
856 if( type.empty() || type == "custom" )
857 {
859
860 // Take the image cache file for the theme chosen in preferences
861 auto dir = ThemeSubdir(GetFilePath(), GUITheme().Read());
862 const auto &FileName =
863 wxFileName{ dir, ImageCacheFileName }.GetFullPath();
864 if( !wxFileExists( FileName ))
865 {
866 if( bOkIfNotFound )
867 return false; // did not load the images, so return false.
869 XO("Audacity could not find file:\n %s.\nTheme not loaded.")
870 .Format( FileName ));
871 return false;
872 }
873 if( !ImageCache.LoadFile( FileName, wxBITMAP_TYPE_PNG ))
874 {
876 /* i18n-hint: Do not translate png. It is the name of a file format.*/
877 XO("Audacity could not load file:\n %s.\nBad png format perhaps?")
878 .Format( FileName ));
879 return false;
880 }
881 }
882 // ELSE we are reading from internal storage.
883 else
884 {
885 size_t ImageSize = 0;
886 const unsigned char * pImage = nullptr;
887 auto &lookup = GetThemeCacheLookup();
888 auto iter = lookup.find({type, {}});
889 if (const auto end = lookup.end(); iter == end) {
890 iter = lookup.find({"classic", {}});
891 wxASSERT(iter != end);
892 }
893
894 mPreferredSystemAppearance = iter->second.preferredSystemAppearance;
895
896 ImageSize = iter->second.data.size();
897 if (ImageSize == 0)
898 // This must be the image compiler
899 return true;
900
901 pImage = iter->second.data.data();
902 //wxLogDebug("Reading ImageCache %p size %i", pImage, ImageSize );
903 wxMemoryInputStream InternalStream( pImage, ImageSize );
904
905 if( !ImageCache.LoadFile( InternalStream, wxBITMAP_TYPE_PNG ))
906 {
907 // If we get this message, it means that the data in file
908 // was not a valid png image.
909 // Most likely someone edited it by mistake,
910 // Or some experiment is being tried with NEW formats for it.
912 XO(
913"Audacity could not read its default theme.\nPlease report the problem."));
914 return false;
915 }
916 //wxLogDebug("Read %i by %i", ImageCache.GetWidth(), ImageCache.GetHeight() );
917 }
918
919 // Resize a large image down.
920 if( ImageCache.GetWidth() > ImageCacheWidth ){
921 int h = ImageCache.GetHeight() * ((1.0*ImageCacheWidth)/ImageCache.GetWidth());
922 ImageCache.Rescale( ImageCacheWidth, h );
923 }
924 FlowPacker context{ ImageCacheWidth };
925 // Load the bitmaps
926 for (size_t i = 0; i < resources.mImages.size(); ++i)
927 {
928 wxImage &Image = resources.mImages[i];
929 context.mFlags = mBitmapFlags[i];
930 if( !(mBitmapFlags[i] & resFlagInternal) )
931 {
932 context.GetNextPosition( Image.GetWidth(),Image.GetHeight() );
933 wxRect R = context.RectInner();
934 //wxLogDebug( "[%i, %i, %i, %i, \"%s\"], ", R.x, R.y, R.width, R.height, mBitmapNames[i].c_str() );
935 Image = GetSubImageWithAlpha( ImageCache, context.RectInner() );
936 resources.mBitmaps[i] = wxBitmap(Image);
937 }
938 }
939 if( !ImageCache.HasAlpha() )
940 ImageCache.InitAlpha();
941
942// return true; //To not load colours..
943 // Now load the colours.
944 int x,y;
945 context.SetColourGroup();
946 wxColour TempColour;
947 for (size_t i = 0; i < resources.mColours.size(); ++i)
948 {
949 context.GetNextPosition( iColSize, iColSize );
950 context.RectMid( x, y );
951 wxRect R = context.RectInner();
952 //wxLogDebug( "[%i, %i, %i, %i, \"%s\"], ", R.x, R.y, R.width, R.height, mColourNames[i].c_str() );
953 // Only change the colour if the alpha is opaque.
954 // This allows us to add NEW colours more easily.
955 if( ImageCache.GetAlpha(x,y ) > 128 )
956 {
957 TempColour = wxColour(
958 ImageCache.GetRed( x,y),
959 ImageCache.GetGreen( x,y),
960 ImageCache.GetBlue(x,y));
965 if( TempColour != wxColour(1,1,1) )
966 resources.mColours[i] = TempColour;
967 }
968 }
969 return true;
970}
wxImage GetSubImageWithAlpha(const wxImage &Src, const wxRect &rect)
bool empty() const
Definition: Identifier.h:61
wxImage & Image(int iIndex)
virtual void EnsureInitialised()=0
wxSize ImageSize(int iIndex)
const char * end(const char *str) noexcept
Definition: StringUtils.h:106

References Identifier::empty(), details::end(), EnsureInitialised(), GetFilePath(), GetSubImageWithAlpha(), GetThemeCacheLookup(), GUITheme(), anonymous_namespace{Theme.cpp}::iColSize, Image(), anonymous_namespace{Theme.cpp}::ImageCacheFileName, ImageCacheWidth, ImageSize(), Light, mBitmapFlags, mPreferredSystemAppearance, mpSet, resFlagInternal, BasicUI::ShowMessageBox(), anonymous_namespace{Theme.cpp}::ThemeSubdir(), wxImage(), and XO().

Referenced by SwitchTheme().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ RecolourBitmap()

void ThemeBase::RecolourBitmap ( int  iIndex,
wxColour  From,
wxColour  To 
)

Definition at line 276 of file Theme.cpp.

277{
278 wxImage Image( Bitmap( iIndex ).ConvertToImage() );
279
280 std::unique_ptr<wxImage> pResult = ChangeImageColour(
281 &Image, From, To );
282 ReplaceImage( iIndex, pResult.get() );
283}
std::unique_ptr< wxImage > ChangeImageColour(wxImage *srcImage, wxColour &dstColour)
wxBitmap & Bitmap(int iIndex)
void ReplaceImage(int iIndex, wxImage *pImage)

References Bitmap(), ChangeImageColour(), Image(), ReplaceImage(), and wxImage().

Here is the call graph for this function:

◆ RegisterColour()

void ThemeBase::RegisterColour ( NameSet allNames,
int &  iIndex,
const wxColour &  Clr,
const wxString &  Name 
)

Definition at line 391 of file Theme.cpp.

393{
394 auto &resources = *mpSet;
395 resources.mColours.push_back( Clr );
396 auto index = resources.mColours.size() - 1;
397 if (iIndex == -1) {
398 // First time assignment of global variable identifying a colour
399 iIndex = index;
400 mColourNames.push_back( Name );
401 wxASSERT(allNames.insert(Name).second);
402 }
403 else {
404 // If revisiting for another theme set,
405 // colours should be re-done in the same sequence
406 wxASSERT(iIndex == index);
407 wxASSERT(mColourNames[index] == Name);
408 }
409}
std::vector< wxColour > mColours
Definition: Theme.h:105

References mColourNames, ThemeSet::mColours, and mpSet.

◆ RegisterImage() [1/2]

void ThemeBase::RegisterImage ( NameSet allNames,
int &  flags,
int &  iIndex,
char const **  pXpm,
const wxString &  Name 
)

Definition at line 338 of file Theme.cpp.

340{
341 wxBitmap Bmp( pXpm );
342 wxImage Img( Bmp.ConvertToImage() );
343 // The next line recommended by http://forum.audacityteam.org/viewtopic.php?f=50&t=96765
344 Img.SetMaskColour(0xDE, 0xDE, 0xDE);
345 Img.InitAlpha();
346
347 //dmazzoni: the top line does not work on wxGTK
348 //wxBitmap Bmp2( Img, 32 );
349 //wxBitmap Bmp2( Img );
350
351 RegisterImage( allNames, flags, iIndex, Img, Name );
352}
void RegisterImage(NameSet &allNames, int &flags, int &iIndex, char const **pXpm, const wxString &Name)
Definition: Theme.cpp:338

References RegisterImage(), and wxImage().

Referenced by RegisterImage().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ RegisterImage() [2/2]

void ThemeBase::RegisterImage ( NameSet allNames,
int &  flags,
int &  iIndex,
const wxImage Image,
const wxString &  Name 
)

Definition at line 354 of file Theme.cpp.

356{
357 auto &resources = *mpSet;
358 resources.mImages.push_back( Image );
359
360#ifdef __APPLE__
361 // On Mac, bitmaps with alpha don't work.
362 // So we convert to a mask and use that.
363 // It isn't quite as good, as alpha gives smoother edges.
364 //[Does not affect the large control buttons, as for those we do
365 // the blending ourselves anyway.]
366 wxImage TempImage( Image );
367 TempImage.ConvertAlphaToMask();
368 resources.mBitmaps.push_back( wxBitmap( TempImage ) );
369#else
370 resources.mBitmaps.push_back( wxBitmap( Image ) );
371#endif
372
373 flags &= ~resFlagSkip;
374 auto index = resources.mBitmaps.size() - 1;
375 if (iIndex == -1) {
376 // First time assignment of global variable identifying an image
377 iIndex = index;
378 mBitmapNames.push_back( Name );
379 mBitmapFlags.push_back( flags );
380 wxASSERT(allNames.insert(Name).second);
381 }
382 else {
383 // If revisiting for another theme set,
384 // images should be re-done in the same sequence
385 wxASSERT(iIndex == index);
386 wxASSERT(mBitmapNames[index] == Name);
387 wxASSERT(mBitmapFlags[index] == flags);
388 }
389}
std::vector< wxImage > mImages
Definition: Theme.h:103

References Image(), mBitmapFlags, mBitmapNames, ThemeSet::mImages, mpSet, and wxImage().

Here is the call graph for this function:

◆ ReplaceImage()

void ThemeBase::ReplaceImage ( int  iIndex,
wxImage pImage 
)

Referenced by ToolBar::MakeMacRecoloredImage(), and RecolourBitmap().

Here is the caller graph for this function:

◆ RotateImageInto()

void ThemeBase::RotateImageInto ( int  iTo,
int  iFrom,
bool  bClockwise 
)

Referenced by LoadTheme().

Here is the caller graph for this function:

◆ SaveOneThemeComponents()

bool ThemeBase::SaveOneThemeComponents ( teThemeType  id)

◆ SaveThemeAsCode()

void ThemeBase::SaveThemeAsCode ( )

Referenced by App::OnInit(), and ThemePrefs::OnSaveThemeAsCode().

Here is the caller graph for this function:

◆ SaveThemeComponents()

void ThemeBase::SaveThemeComponents ( )

Referenced by ThemePrefs::OnSaveThemeComponents().

Here is the caller graph for this function:

◆ SetBrushColour()

void ThemeBase::SetBrushColour ( wxBrush &  Brush,
int  iIndex 
)

Referenced by AColor::Init(), NumericTextCtrl::Layout(), NumericTextCtrl::OnPaint(), and TrackArtist::SetColours().

Here is the caller graph for this function:

◆ SetFilePath()

void ThemeBase::SetFilePath ( const FilePath path)

Definition at line 157 of file Theme.cpp.

158{
159 mThemeDir = path;
160}

References mThemeDir.

Referenced by GetFilePath(), and main().

Here is the caller graph for this function:

◆ SetPenColour()

void ThemeBase::SetPenColour ( wxPen &  Pen,
int  iIndex 
)

Referenced by AColor::Init(), NumericTextCtrl::OnPaint(), and TrackArtist::SetColours().

Here is the caller graph for this function:

◆ SwitchTheme()

void ThemeBase::SwitchTheme ( teThemeType  Theme)

Definition at line 217 of file Theme.cpp.

218{
219 // Switch the active theme set
220 mpSet = &mSets[Theme.empty() ? GUITheme().Read() : Theme];
221 auto &resources = *mpSet;
223
224 const bool cbOkIfNotFound = true;
225
226 if( !ReadImageCache( Theme, cbOkIfNotFound ) )
227 {
228 // THEN get the default set.
229 ReadImageCache( GetFallbackThemeType(), !cbOkIfNotFound );
230
231 // JKC: Now we could go on and load the individual images
232 // on top of the default images using the commented out
233 // code that follows...
234 //
235 // However, I think it is better to get the user to
236 // build a NEW image cache, which they can do easily
237 // from the Theme preferences tab.
238#if 0
239 // and now add any available component images.
240 LoadComponents( cbOkIfNotFound );
241
242 // JKC: I'm usure about doing this next step automatically.
243 // Suppose the disk is write protected?
244 // Is having the image cache created automatically
245 // going to confuse users? Do we need version specific names?
246 // and now save the combined image as a cache for later use.
247 // We should load the images a little faster in future as a result.
249#endif
250 }
251}
teThemeType GetFallbackThemeType()
Definition: Theme.cpp:831
std::map< Identifier, ThemeSet > mSets
Definition: Theme.h:204
bool ReadImageCache(teThemeType type={}, bool bOkIfNotFound=false)
Definition: Theme.cpp:842
void CreateImageCache()
Definition: Theme.cpp:556

References CreateImageCache(), EnsureInitialised(), GetFallbackThemeType(), GUITheme(), mpSet, mSets, ChoiceSetting::Read(), and ReadImageCache().

Referenced by CreateOneImageCache(), LoadOneThemeComponents(), LoadTheme(), ThemePrefs::OnLoadThemeCache(), ThemePrefs::OnReadThemeInternal(), and WriteOneImageMap().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ WriteImageDefs()

void ThemeBase::WriteImageDefs ( )

Writes a series of Macro definitions that can be used in the include file.

Definition at line 789 of file Theme.cpp.

790{
791 // The generated image defs macro calls depend only on sizes of images,
792 // not contents, and so there is only one file good across all themes.
793
794 auto &resources = *mpSet;
796
797 wxFFile File( ThemeImageDefsAsCee(GetFilePath()), wxT("wb") );
798 if( !File.IsOpened() )
799 return;
800 teResourceFlags PrevFlags = (teResourceFlags)-1;
801 for (size_t i = 0; i < resources.mImages.size(); ++i)
802 {
803 wxImage &SrcImage = resources.mImages[i];
804 // No href in html. Uses title not alt.
805 if( PrevFlags != mBitmapFlags[i] )
806 {
807 PrevFlags = (teResourceFlags)mBitmapFlags[i];
808 int t = (int)PrevFlags;
809 wxString Temp;
810 if( t==0 ) Temp = wxT(" resFlagNone ");
811 if( t & resFlagPaired ) Temp += wxT(" resFlagPaired ");
812 if( t & resFlagCursor ) Temp += wxT(" resFlagCursor ");
813 if( t & resFlagNewLine ) Temp += wxT(" resFlagNewLine ");
814 if( t & resFlagInternal ) Temp += wxT(" resFlagInternal ");
815 Temp.Replace( wxT(" "), wxT(" | ") );
816
817 File.Write( wxString::Format( wxT("\r\n SET_THEME_FLAGS( %s );\r\n"),
818 Temp ));
819 }
820 File.Write( wxString::Format(
821 wxT(" DEFINE_IMAGE( bmp%s, wxImage( %i, %i ), wxT(\"%s\"));\r\n"),
822 mBitmapNames[i],
823 SrcImage.GetWidth(),
824 SrcImage.GetHeight(),
825 mBitmapNames[i]
826 ));
827 }
828}
teResourceFlags
Definition: Theme.h:59
@ resFlagNewLine
Definition: Theme.h:63
@ resFlagPaired
Definition: Theme.h:61
@ resFlagCursor
Definition: Theme.h:62
FilePath ThemeImageDefsAsCee(const FilePath &themeDir)
Definition: Theme.cpp:124

References EnsureInitialised(), GetFilePath(), mBitmapFlags, mBitmapNames, mpSet, resFlagCursor, resFlagInternal, resFlagNewLine, resFlagPaired, anonymous_namespace{Theme.cpp}::ThemeImageDefsAsCee(), wxImage(), and wxT().

Referenced by ThemePrefs::OnSaveThemeAsCode().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ WriteImageMap()

void ThemeBase::WriteImageMap ( )

Definition at line 728 of file Theme.cpp.

729{
730 ValueRestorer cleanup{ mpSet };
731 for (auto &[key, data] : GetThemeCacheLookup())
732 WriteOneImageMap(key.Internal());
733}
void WriteOneImageMap(teThemeType id)
Definition: Theme.cpp:737

References GetThemeCacheLookup(), key, mpSet, and WriteOneImageMap().

Referenced by ThemePrefs::OnSaveThemeCache().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ WriteOneImageMap()

void ThemeBase::WriteOneImageMap ( teThemeType  id)

Writes an html file with an image map of the ImageCache Very handy for seeing what each part is for.

Definition at line 737 of file Theme.cpp.

738{
739 SwitchTheme( id );
740 auto &resources = *mpSet;
741
742 FlowPacker context{ ImageCacheWidth };
743
744 auto dir = ThemeSubdir(GetFilePath(), id);
745 auto FileName = wxFileName{ dir, ImageMapFileName }.GetFullPath();
746 wxFFile File( FileName, wxT("wb") );// I'll put in NEW lines explicitly.
747 if( !File.IsOpened() )
748 return;
749
750 File.Write( wxT("<html>\r\n"));
751 File.Write( wxT("<body bgcolor=\"303030\">\r\n"));
752 wxString Temp = wxString::Format( wxT("<img src=\"ImageCache.png\" width=\"%i\" usemap=\"#map1\">\r\n" ), ImageCacheWidth );
753 File.Write( Temp );
754 File.Write( wxT("<map name=\"map1\">\r\n") );
755
756 for (size_t i = 0; i < resources.mImages.size(); ++i)
757 {
758 wxImage &SrcImage = resources.mImages[i];
759 context.mFlags = mBitmapFlags[i];
760 if( !(mBitmapFlags[i] & resFlagInternal) )
761 {
762 context.GetNextPosition( SrcImage.GetWidth(), SrcImage.GetHeight());
763 // No href in html. Uses title not alt.
764 wxRect R( context.RectInner() );
765 File.Write( wxString::Format(
766 wxT("<area title=\"Bitmap:%s\" shape=rect coords=\"%i,%i,%i,%i\">\r\n"),
767 mBitmapNames[i],
768 R.GetLeft(), R.GetTop(), R.GetRight(), R.GetBottom()) );
769 }
770 }
771 // Now save the colours.
772 context.SetColourGroup();
773 for (size_t i = 0; i < resources.mColours.size(); ++i)
774 {
775 context.GetNextPosition( iColSize, iColSize );
776 // No href in html. Uses title not alt.
777 wxRect R( context.RectInner() );
778 File.Write( wxString::Format( wxT("<area title=\"Colour:%s\" shape=rect coords=\"%i,%i,%i,%i\">\r\n"),
779 mColourNames[i],
780 R.GetLeft(), R.GetTop(), R.GetRight(), R.GetBottom()) );
781 }
782 File.Write( wxT("</map>\r\n") );
783 File.Write( wxT("</body>\r\n"));
784 File.Write( wxT("</html>\r\n"));
785 // File will be closed automatically.
786}
constexpr auto ImageMapFileName
Definition: Theme.cpp:120

References GetFilePath(), anonymous_namespace{Theme.cpp}::iColSize, ImageCacheWidth, anonymous_namespace{Theme.cpp}::ImageMapFileName, mBitmapFlags, mBitmapNames, mColourNames, mpSet, resFlagInternal, SwitchTheme(), anonymous_namespace{Theme.cpp}::ThemeSubdir(), wxImage(), and wxT().

Referenced by WriteImageMap().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ mBitmapFlags

std::vector<int> ThemeBase::mBitmapFlags
protected

◆ mBitmapNames

wxArrayString ThemeBase::mBitmapNames
protected

◆ mColourNames

wxArrayString ThemeBase::mColourNames
protected

◆ mPreferredSystemAppearance

PreferredSystemAppearance ThemeBase::mPreferredSystemAppearance { PreferredSystemAppearance::Light }
protected

Definition at line 202 of file Theme.h.

Referenced by LoadTheme(), and ReadImageCache().

◆ mpSet

ThemeSet* ThemeBase::mpSet = nullptr
protected

◆ mSets

std::map<Identifier, ThemeSet> ThemeBase::mSets
protected

Definition at line 204 of file Theme.h.

Referenced by SwitchTheme().

◆ mThemeDir

FilePath ThemeBase::mThemeDir
protected

Definition at line 196 of file Theme.h.

Referenced by GetFilePath(), and SetFilePath().


The documentation for this class was generated from the following files: