2018-01-06 13:03:48 +00:00
/**********************************************************************
Audacity : A Digital Audio Editor
Contrast . cpp
\ class ContrastDialog
\ brief Dialog used for Contrast menu item
*/ /*******************************************************************/
# include "../Audacity.h"
# include "Contrast.h"
# include "../WaveTrack.h"
# include "../Prefs.h"
# include "../Project.h"
# include "../ShuttleGui.h"
# include "../FileNames.h"
# include "../widgets/LinkingHtmlWindow.h"
# include "../widgets/HelpSystem.h"
# include "../widgets/NumericTextCtrl.h"
# include "../widgets/ErrorDialog.h"
# include <cmath>
# include <limits>
# if defined(__WXMSW__) && !defined(__CYGWIN__)
# include <float.h>
# define finite(x) _finite(x)
# endif
# include <wx/filedlg.h>
# include <wx/valtext.h>
# include <wx/log.h>
# include "../PlatformCompatibility.h"
# define DB_MAX_LIMIT 0.0 // Audio is massively distorted.
# define WCAG2_PASS 20.0 // dB difference required to pass WCAG2 test.
bool ContrastDialog : : GetDB ( float & dB )
{
float rms = float ( 0.0 ) ;
int numberSelecteTracks = 0 ;
// For stereo tracks: sqrt((mean(L)+mean(R))/2)
bool isStereo = false ;
double meanSq = 0.0 ;
AudacityProject * p = GetActiveProject ( ) ;
SelectedTrackListOfKindIterator iter ( Track : : Wave , p - > GetTracks ( ) ) ;
WaveTrack * t = ( WaveTrack * ) iter . First ( ) ;
while ( t ) {
numberSelecteTracks + + ;
if ( numberSelecteTracks > 1 & & ! isStereo ) {
AudacityMessageDialog m ( NULL , _ ( " You can only measure one track at a time. " ) , _ ( " Error " ) , wxOK ) ;
m . ShowModal ( ) ;
return false ;
}
isStereo = t - > GetLinked ( ) ;
wxASSERT ( mT0 < = mT1 ) ;
// Ignore whitespace beyond ends of track.
if ( mT0 < t - > GetStartTime ( ) )
mT0 = t - > GetStartTime ( ) ;
if ( mT1 > t - > GetEndTime ( ) )
mT1 = t - > GetEndTime ( ) ;
auto SelT0 = t - > TimeToLongSamples ( mT0 ) ;
auto SelT1 = t - > TimeToLongSamples ( mT1 ) ;
if ( SelT0 > SelT1 )
{
AudacityMessageDialog m ( NULL , _ ( " Invalid audio selection. \n Please ensure that audio is selected. " ) , _ ( " Error " ) , wxOK ) ;
m . ShowModal ( ) ;
return false ;
}
if ( SelT0 = = SelT1 )
{
AudacityMessageDialog m ( NULL , _ ( " Nothing to measure. \n Please select a section of a track. " ) , _ ( " Error " ) , wxOK ) ;
m . ShowModal ( ) ;
return false ;
}
// Don't throw in this analysis dialog
rms = ( ( WaveTrack * ) t ) - > GetRMS ( mT0 , mT1 , false ) ;
meanSq + = rms * rms ;
t = ( WaveTrack * ) iter . Next ( ) ;
}
// TODO: This works for stereo, provided the audio clips are in both channels.
// We should really count gaps between clips as silence.
rms = ( meanSq > 0.0 ) ? sqrt ( meanSq / ( double ) numberSelecteTracks ) : 0.0 ;
if ( numberSelecteTracks = = 0 ) {
AudacityMessageDialog m ( NULL , _ ( " Please select an audio track. " ) , _ ( " Error " ) , wxOK ) ;
m . ShowModal ( ) ;
return false ;
}
// Gives warning C4056, Overflow in floating-point constant arithmetic
// -INFINITY is intentional here.
// Looks like we are stuck with this warning, as
// #pragma warning( disable : 4056)
// even around the whole function does not disable it successfully.
dB = ( rms = = 0.0 ) ? - INFINITY : LINEAR_TO_DB ( rms ) ;
return true ;
}
void ContrastDialog : : SetStartAndEndTime ( )
{
AudacityProject * p = GetActiveProject ( ) ;
mT0 = p - > mViewInfo . selectedRegion . t0 ( ) ;
mT1 = p - > mViewInfo . selectedRegion . t1 ( ) ;
}
// WDR: class implementations
//----------------------------------------------------------------------------
// ContrastDialog
//----------------------------------------------------------------------------
// WDR: event table for ContrastDialog
enum {
ID_BUTTON_USECURRENTF = 10001 ,
ID_BUTTON_USECURRENTB ,
//ID_BUTTON_GETURL,
ID_BUTTON_EXPORT ,
ID_BUTTON_RESET ,
//ID_BUTTON_CLOSE,
ID_FOREGROUNDSTART_T ,
ID_FOREGROUNDEND_T ,
ID_BACKGROUNDSTART_T ,
ID_BACKGROUNDEND_T ,
ID_FOREGROUNDDB_TEXT ,
ID_BACKGROUNDDB_TEXT ,
ID_RESULTS_TEXT ,
ID_RESULTSDB_TEXT
} ;
BEGIN_EVENT_TABLE ( ContrastDialog , wxDialogWrapper )
EVT_BUTTON ( ID_BUTTON_USECURRENTF , ContrastDialog : : OnGetForeground )
EVT_BUTTON ( ID_BUTTON_USECURRENTB , ContrastDialog : : OnGetBackground )
EVT_BUTTON ( wxID_HELP , ContrastDialog : : OnGetURL )
EVT_BUTTON ( ID_BUTTON_EXPORT , ContrastDialog : : OnExport )
EVT_BUTTON ( ID_BUTTON_RESET , ContrastDialog : : OnReset )
EVT_BUTTON ( wxID_CANCEL , ContrastDialog : : OnClose )
END_EVENT_TABLE ( )
/* i18n-hint: WCAG2 is the 'Web Content Accessibility Guidelines (WCAG) 2.0', see http://www.w3.org/TR/WCAG20/ */
ContrastDialog : : ContrastDialog ( wxWindow * parent , wxWindowID id ,
const wxString & title ,
const wxPoint & pos ) :
wxDialogWrapper ( parent , id , title , pos , wxDefaultSize ,
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX )
{
SetName ( GetTitle ( ) ) ;
mT0 = 0.0 ;
mT1 = 0.0 ;
foregrounddB = 0.0 ;
backgrounddB = 0.0 ;
mForegroundIsDefined = false ;
mBackgroundIsDefined = false ;
// NULL out the control members until the controls are created.
mForegroundStartT = NULL ;
mForegroundEndT = NULL ;
mBackgroundStartT = NULL ;
mBackgroundEndT = NULL ;
wxTextValidator vld ( wxFILTER_NUMERIC ) ;
wxString number ;
AudacityProject * p = GetActiveProject ( ) ;
mProjectRate = p - > GetRate ( ) ;
ShuttleGui S ( this , eIsCreating ) ;
S . SetBorder ( 5 ) ;
S . StartHorizontalLay ( wxCENTER , false ) ;
{
/* i18n-hint: RMS abbreviates root mean square, a certain averaging method */
S . AddTitle ( _ ( " Contrast Analyzer, for measuring RMS volume differences between two selections of audio. " ) ) ;
}
S . EndHorizontalLay ( ) ;
S . StartStatic ( _ ( " Parameters " ) ) ;
{
S . StartMultiColumn ( 5 , wxEXPAND ) ;
{
// Headings
S . AddFixedText ( { } ) ; // spacer
S . AddFixedText ( _ ( " Start " ) ) ;
S . AddFixedText ( _ ( " End " ) ) ;
S . AddFixedText ( { } ) ; // spacer
S . AddFixedText ( _ ( " Volume " ) ) ;
//Foreground
S . AddFixedText ( _ ( " &Foreground: " ) , false ) ;
if ( S . GetMode ( ) = = eIsCreating )
{
mForegroundStartT = safenew
NumericTextCtrl ( NumericConverter : : TIME , this ,
ID_FOREGROUNDSTART_T ,
_ ( " hh:mm:ss + hundredths " ) ,
0.0 ,
mProjectRate ,
wxDefaultPosition ,
wxDefaultSize ,
true ) ;
mForegroundStartT - > SetName ( _ ( " Foreground start time " ) ) ;
mForegroundStartT - > EnableMenu ( false ) ;
mForegroundStartT - > SetReadOnly ( true ) ;
}
S . AddWindow ( mForegroundStartT ) ;
if ( S . GetMode ( ) = = eIsCreating )
{
mForegroundEndT = safenew
NumericTextCtrl ( NumericConverter : : TIME , this ,
ID_FOREGROUNDEND_T ,
_ ( " hh:mm:ss + hundredths " ) ,
0.0 ,
mProjectRate ,
wxDefaultPosition ,
wxDefaultSize ,
true ) ;
mForegroundEndT - > SetName ( _ ( " Foreground end time " ) ) ;
mForegroundEndT - > EnableMenu ( false ) ;
mForegroundEndT - > SetReadOnly ( true ) ;
}
S . AddWindow ( mForegroundEndT ) ;
m_pButton_UseCurrentF = S . Id ( ID_BUTTON_USECURRENTF ) . AddButton ( _ ( " &Measure selection " ) ) ;
mForegroundRMSText = S . Id ( ID_FOREGROUNDDB_TEXT ) . AddTextBox ( { } , wxT ( " " ) , 17 ) ;
mForegroundRMSText - > Connect ( wxEVT_KEY_DOWN , wxKeyEventHandler ( ContrastDialog : : OnChar ) ) ;
//Background
S . AddFixedText ( _ ( " &Background: " ) ) ;
if ( S . GetMode ( ) = = eIsCreating )
{
mBackgroundStartT = safenew
NumericTextCtrl ( NumericConverter : : TIME , this ,
ID_BACKGROUNDSTART_T ,
_ ( " hh:mm:ss + hundredths " ) ,
0.0 ,
mProjectRate ,
wxDefaultPosition ,
wxDefaultSize ,
true ) ;
mBackgroundStartT - > SetName ( _ ( " Background start time " ) ) ;
mBackgroundStartT - > EnableMenu ( false ) ;
mBackgroundStartT - > SetReadOnly ( true ) ;
}
S . AddWindow ( mBackgroundStartT ) ;
if ( S . GetMode ( ) = = eIsCreating )
{
mBackgroundEndT = safenew
NumericTextCtrl ( NumericConverter : : TIME , this ,
ID_BACKGROUNDEND_T ,
_ ( " hh:mm:ss + hundredths " ) ,
0.0 ,
mProjectRate ,
wxDefaultPosition ,
wxDefaultSize ,
true ) ;
mBackgroundEndT - > SetName ( _ ( " Background end time " ) ) ;
mBackgroundEndT - > EnableMenu ( false ) ;
mBackgroundEndT - > SetReadOnly ( true ) ;
}
S . AddWindow ( mBackgroundEndT ) ;
m_pButton_UseCurrentB = S . Id ( ID_BUTTON_USECURRENTB ) . AddButton ( _ ( " Mea&sure selection " ) ) ;
mBackgroundRMSText = S . Id ( ID_BACKGROUNDDB_TEXT ) . AddTextBox ( { } , wxT ( " " ) , 17 ) ;
mBackgroundRMSText - > Connect ( wxEVT_KEY_DOWN , wxKeyEventHandler ( ContrastDialog : : OnChar ) ) ;
}
S . EndMultiColumn ( ) ;
}
S . EndStatic ( ) ;
//Result
S . StartStatic ( _ ( " Result " ) ) ;
{
S . StartMultiColumn ( 3 , wxCENTER ) ;
{
S . AddFixedText ( _ ( " Co&ntrast Result: " ) ) ;
mPassFailText = S . Id ( ID_RESULTS_TEXT ) . AddTextBox ( { } , wxT ( " " ) , 50 ) ;
mPassFailText - > Connect ( wxEVT_KEY_DOWN , wxKeyEventHandler ( ContrastDialog : : OnChar ) ) ;
m_pButton_Reset = S . Id ( ID_BUTTON_RESET ) . AddButton ( _ ( " R&eset " ) ) ;
S . AddFixedText ( _ ( " &Difference: " ) ) ;
mDiffText = S . Id ( ID_RESULTSDB_TEXT ) . AddTextBox ( { } , wxT ( " " ) , 50 ) ;
mDiffText - > Connect ( wxEVT_KEY_DOWN , wxKeyEventHandler ( ContrastDialog : : OnChar ) ) ;
m_pButton_Export = S . Id ( ID_BUTTON_EXPORT ) . AddButton ( _ ( " E&xport... " ) ) ;
}
S . EndMultiColumn ( ) ;
}
S . EndStatic ( ) ;
S . AddStandardButtons ( eCloseButton | eHelpButton ) ;
#if 0
S . StartMultiColumn ( 3 , wxEXPAND ) ;
{
S . SetStretchyCol ( 1 ) ;
m_pButton_GetURL = S . Id ( ID_BUTTON_GETURL ) . AddButton ( _ ( " &Help " ) ) ;
S . AddFixedText ( wxT ( " " ) ) ; // spacer
m_pButton_Close = S . Id ( ID_BUTTON_CLOSE ) . AddButton ( _ ( " &Close " ) ) ;
}
S . EndMultiColumn ( ) ;
# endif
Layout ( ) ;
Fit ( ) ;
SetMinSize ( GetSize ( ) ) ;
Center ( ) ;
}
ContrastDialog : : ~ ContrastDialog ( )
{
mForegroundRMSText - > Disconnect ( wxEVT_KEY_DOWN , wxKeyEventHandler ( ContrastDialog : : OnChar ) ) ;
mBackgroundRMSText - > Disconnect ( wxEVT_KEY_DOWN , wxKeyEventHandler ( ContrastDialog : : OnChar ) ) ;
mPassFailText - > Disconnect ( wxEVT_KEY_DOWN , wxKeyEventHandler ( ContrastDialog : : OnChar ) ) ;
mDiffText - > Disconnect ( wxEVT_KEY_DOWN , wxKeyEventHandler ( ContrastDialog : : OnChar ) ) ;
}
void ContrastDialog : : OnGetURL ( wxCommandEvent & WXUNUSED ( event ) )
{
// Original help page is back on-line (March 2016), but the manual should be more reliable.
// http://www.eramp.com/WCAG_2_audio_contrast_tool_help.htm
HelpSystem : : ShowHelp ( this , wxT ( " Contrast " ) ) ;
}
void ContrastDialog : : OnClose ( wxCommandEvent & WXUNUSED ( event ) )
{
wxCommandEvent dummyEvent ;
OnReset ( dummyEvent ) ;
Show ( false ) ;
}
void ContrastDialog : : OnGetForeground ( wxCommandEvent & /*event*/ )
{
AudacityProject * p = GetActiveProject ( ) ;
SelectedTrackListOfKindIterator iter ( Track : : Wave , p - > GetTracks ( ) ) ;
for ( Track * t = iter . First ( ) ; t ; t = iter . Next ( ) ) {
mForegroundStartT - > SetValue ( p - > mViewInfo . selectedRegion . t0 ( ) ) ;
mForegroundEndT - > SetValue ( p - > mViewInfo . selectedRegion . t1 ( ) ) ;
}
SetStartAndEndTime ( ) ;
mForegroundIsDefined = GetDB ( foregrounddB ) ;
m_pButton_UseCurrentF - > SetFocus ( ) ;
results ( ) ;
}
void ContrastDialog : : OnGetBackground ( wxCommandEvent & /*event*/ )
{
AudacityProject * p = GetActiveProject ( ) ;
SelectedTrackListOfKindIterator iter ( Track : : Wave , p - > GetTracks ( ) ) ;
for ( Track * t = iter . First ( ) ; t ; t = iter . Next ( ) ) {
mBackgroundStartT - > SetValue ( p - > mViewInfo . selectedRegion . t0 ( ) ) ;
mBackgroundEndT - > SetValue ( p - > mViewInfo . selectedRegion . t1 ( ) ) ;
}
SetStartAndEndTime ( ) ;
mBackgroundIsDefined = GetDB ( backgrounddB ) ;
m_pButton_UseCurrentB - > SetFocus ( ) ;
results ( ) ;
}
namespace {
// PRL: I gathered formatting into these functions, and eliminated some
// repetitions, and removed the redundant word "Average" as applied to RMS.
// Should these variations in formats be collapsed further?
// Pass nullptr when value is not yet defined
wxString FormatRMSMessage ( float * pValue )
{
/* i18n-hint: RMS abbreviates root mean square, a certain averaging method */
wxString format0 { _ ( " RMS = %s. " ) } ;
/* i18n-hint: dB abbreviates decibels */
wxString format1 { _ ( " %s dB " ) } ;
wxString value ;
if ( pValue )
if ( fabs ( * pValue ) ! = std : : numeric_limits < float > : : infinity ( ) ) {
auto number = wxString : : Format ( _ ( " %.2f " ) , * pValue ) ;
value = wxString : : Format ( format1 , number ) ;
}
else
value = _ ( " zero " ) ;
else
value = wxString : : Format ( format1 , " " ) ;
return wxString : : Format ( format0 , value ) ;
}
wxString FormatDifference ( float diffdB )
{
if ( diffdB ! = diffdB ) // test for NaN, reliant on IEEE implementation
return _ ( " indeterminate " ) ;
else {
if ( diffdB ! = std : : numeric_limits < float > : : infinity ( ) )
/* i18n-hint: dB abbreviates decibels */
/* i18n-hint: RMS abbreviates root mean square, a certain averaging method */
return wxString : : Format ( _ ( " %.2f dB RMS " ) , diffdB ) ;
else
/* i18n-hint: dB abbreviates decibels */
return _ ( " Infinite dB difference " ) ;
}
}
wxString FormatDifferenceForExport ( float diffdB )
{
if ( diffdB ! = diffdB ) //test for NaN, reliant on IEEE implementation
return _ ( " Difference is indeterminate. " ) ;
else
if ( fabs ( diffdB ) ! = std : : numeric_limits < float > : : infinity ( ) )
/* i18n-hint: dB abbreviates decibels */
/* i18n-hint: RMS abbreviates root mean square, a certain averaging method */
return wxString : : Format ( _ ( " Difference = %.2f RMS dB. " ) , diffdB ) ;
else
/* i18n-hint: dB abbreviates decibels */
/* i18n-hint: RMS abbreviates root mean square, a certain averaging method */
return _ ( " Difference = infinite RMS dB. " ) ;
}
}
void ContrastDialog : : results ( )
{
mPassFailText - > SetName ( wxT ( " " ) ) ;
mPassFailText - > ChangeValue ( wxT ( " " ) ) ;
mDiffText - > ChangeValue ( wxT ( " " ) ) ;
// foreground and background defined.
if ( mForegroundIsDefined & & mBackgroundIsDefined ) {
float diffdB = std : : fabs ( foregrounddB - backgrounddB ) ;
if ( foregrounddB > DB_MAX_LIMIT ) {
mPassFailText - > ChangeValue ( _ ( " Foreground level too high " ) ) ;
}
else if ( backgrounddB > DB_MAX_LIMIT ) {
mPassFailText - > ChangeValue ( _ ( " Background level too high " ) ) ;
}
else if ( backgrounddB > foregrounddB ) {
mPassFailText - > ChangeValue ( _ ( " Background higher than foreground " ) ) ;
}
else if ( diffdB > WCAG2_PASS ) {
/* i18n-hint: WCAG abbreviates Web Content Accessibility Guidelines */
mPassFailText - > ChangeValue ( _ ( " WCAG2 Pass " ) ) ;
}
else {
/* i18n-hint: WCAG abbreviates Web Content Accessibility Guidelines */
mPassFailText - > ChangeValue ( _ ( " WCAG2 Fail " ) ) ;
}
/* i18n-hint: i.e. difference in loudness at the moment. */
mDiffText - > SetName ( _ ( " Current difference " ) ) ;
mDiffText - > ChangeValue ( FormatDifference ( diffdB ) ) ;
}
if ( mForegroundIsDefined ) {
mForegroundRMSText - > SetName ( _ ( " Measured foreground level " ) ) ; // Read by screen-readers
if ( std : : isinf ( - foregrounddB ) )
mForegroundRMSText - > ChangeValue ( _ ( " zero " ) ) ;
else
mForegroundRMSText - > ChangeValue ( wxString : : Format ( _ ( " %.2f dB " ) , foregrounddB ) ) ; // i18n-hint: short form of 'decibels'
}
else {
mForegroundRMSText - > SetName ( _ ( " No foreground measured " ) ) ; // Read by screen-readers
mForegroundRMSText - > ChangeValue ( wxT ( " " ) ) ;
mPassFailText - > ChangeValue ( _ ( " Foreground not yet measured " ) ) ;
}
if ( mBackgroundIsDefined ) {
mBackgroundRMSText - > SetName ( _ ( " Measured background level " ) ) ;
if ( std : : isinf ( - backgrounddB ) )
mBackgroundRMSText - > ChangeValue ( _ ( " zero " ) ) ;
else
mBackgroundRMSText - > ChangeValue ( wxString : : Format ( _ ( " %.2f dB " ) , backgrounddB ) ) ;
}
else {
mBackgroundRMSText - > SetName ( _ ( " No background measured " ) ) ;
mBackgroundRMSText - > ChangeValue ( wxT ( " " ) ) ;
mPassFailText - > ChangeValue ( _ ( " Background not yet measured " ) ) ;
}
}
void ContrastDialog : : OnExport ( wxCommandEvent & WXUNUSED ( event ) )
{
// TODO: Handle silence checks better (-infinity dB)
AudacityProject * project = GetActiveProject ( ) ;
wxString fName = wxT ( " contrast.txt " ) ;
fName = FileNames : : SelectFile ( FileNames : : Operation : : Export ,
_ ( " Export Contrast Result As: " ) ,
wxEmptyString ,
fName ,
wxT ( " txt " ) ,
wxT ( " *.txt " ) ,
wxFD_SAVE | wxRESIZE_BORDER ,
this ) ;
if ( fName = = wxT ( " " ) )
return ;
wxTextFile f ( fName ) ;
# ifdef __WXMAC__
wxFile { } . Create ( fName ) ;
# else
f . Create ( ) ;
# endif
f . Open ( ) ;
if ( ! f . IsOpened ( ) ) {
AudacityMessageBox (
wxString : : Format ( _ ( " Couldn't write to file: %s " ) , fName ) ) ;
return ;
}
f . AddLine ( wxT ( " =================================== " ) ) ;
/* i18n-hint: WCAG abbreviates Web Content Accessibility Guidelines */
f . AddLine ( _ ( " WCAG 2.0 Success Criteria 1.4.7 Contrast Results " ) ) ;
f . AddLine ( wxT ( " " ) ) ;
f . AddLine ( wxString : : Format ( _ ( " Filename = %s. " ) , project - > GetFileName ( ) ) ) ;
f . AddLine ( wxT ( " " ) ) ;
f . AddLine ( _ ( " Foreground " ) ) ;
float t = ( float ) mForegroundStartT - > GetValue ( ) ;
int h = ( int ) ( t / 3600 ) ; // there must be a standard function for this!
int m = ( int ) ( ( t - h * 3600 ) / 60 ) ;
float s = t - h * 3600.0 - m * 60.0 ;
f . AddLine ( wxString : : Format ( _ ( " Time started = %2d hour(s), %2d minute(s), %.2f seconds. " ) , h , m , s ) ) ;
t = ( float ) mForegroundEndT - > GetValue ( ) ;
h = ( int ) ( t / 3600 ) ;
m = ( int ) ( ( t - h * 3600 ) / 60 ) ;
s = t - h * 3600.0 - m * 60.0 ;
f . AddLine ( wxString : : Format ( _ ( " Time ended = %2d hour(s), %2d minute(s), %.2f seconds. " ) , h , m , s ) ) ;
f . AddLine ( FormatRMSMessage ( mForegroundIsDefined ? & foregrounddB : nullptr ) ) ;
f . AddLine ( wxT ( " " ) ) ;
f . AddLine ( _ ( " Background " ) ) ;
t = ( float ) mBackgroundStartT - > GetValue ( ) ;
h = ( int ) ( t / 3600 ) ;
m = ( int ) ( ( t - h * 3600 ) / 60 ) ;
s = t - h * 3600.0 - m * 60.0 ;
f . AddLine ( wxString : : Format ( _ ( " Time started = %2d hour(s), %2d minute(s), %.2f seconds. " ) , h , m , s ) ) ;
t = ( float ) mBackgroundEndT - > GetValue ( ) ;
h = ( int ) ( t / 3600 ) ;
m = ( int ) ( ( t - h * 3600 ) / 60 ) ;
s = t - h * 3600.0 - m * 60.0 ;
f . AddLine ( wxString : : Format ( _ ( " Time ended = %2d hour(s), %2d minute(s), %.2f seconds. " ) , h , m , s ) ) ;
f . AddLine ( FormatRMSMessage ( mBackgroundIsDefined ? & backgrounddB : nullptr ) ) ;
f . AddLine ( wxT ( " " ) ) ;
f . AddLine ( _ ( " Results " ) ) ;
float diffdB = foregrounddB - backgrounddB ;
f . AddLine ( FormatDifferenceForExport ( diffdB ) ) ;
if ( diffdB > 20. )
f . AddLine ( _ ( " Success Criteria 1.4.7 of WCAG 2.0: Pass " ) ) ;
else
f . AddLine ( _ ( " Success Criteria 1.4.7 of WCAG 2.0: Fail " ) ) ;
f . AddLine ( wxT ( " " ) ) ;
f . AddLine ( _ ( " Data gathered " ) ) ;
wxString sNow ;
wxDateTime now = wxDateTime : : Now ( ) ;
int year = now . GetYear ( ) ;
wxDateTime : : Month month = now . GetMonth ( ) ;
wxString monthName = now . GetMonthName ( month ) ;
int dom = now . GetDay ( ) ;
int hour = now . GetHour ( ) ;
int minute = now . GetMinute ( ) ;
int second = now . GetSecond ( ) ;
sNow = wxString : : Format ( wxT ( " %d %s %02d %02dh %02dm %02ds " ) ,
dom , monthName , year , hour , minute , second ) ;
f . AddLine ( sNow ) ;
f . AddLine ( wxT ( " =================================== " ) ) ;
f . AddLine ( wxT ( " " ) ) ;
# ifdef __WXMAC__
f . Write ( wxTextFileType_Mac ) ;
# else
f . Write ( ) ;
# endif
f . Close ( ) ;
}
void ContrastDialog : : OnReset ( wxCommandEvent & /*event*/ )
{
mForegroundStartT - > SetValue ( 0.0 ) ;
mForegroundEndT - > SetValue ( 0.0 ) ;
mBackgroundStartT - > SetValue ( 0.0 ) ;
mBackgroundEndT - > SetValue ( 0.0 ) ;
mForegroundIsDefined = false ;
mBackgroundIsDefined = false ;
mForegroundRMSText - > SetName ( _ ( " No foreground measured " ) ) ; // Read by screen-readers
mBackgroundRMSText - > SetName ( _ ( " No background measured " ) ) ;
mForegroundRMSText - > ChangeValue ( wxT ( " " ) ) ; // Displayed value
mBackgroundRMSText - > ChangeValue ( wxT ( " " ) ) ;
mPassFailText - > ChangeValue ( wxT ( " " ) ) ;
mDiffText - > ChangeValue ( wxT ( " " ) ) ;
}
void ContrastDialog : : OnChar ( wxKeyEvent & event )
{
// Is this still required?
if ( event . GetKeyCode ( ) = = WXK_TAB ) {
event . Skip ( ) ;
return ;
}
event . Skip ( false ) ;
return ;
}