diff --git a/InterSpec_resources/static_text/color_theme_dialog_help.xml b/InterSpec_resources/static_text/color_theme_dialog_help.xml index 06f82b00..fe7a9b4c 100644 --- a/InterSpec_resources/static_text/color_theme_dialog_help.xml +++ b/InterSpec_resources/static_text/color_theme_dialog_help.xml @@ -14,7 +14,10 @@ This tool allows you to customize colors on the spectrum and time charts, as wel icon; you can also upload JSON color themes by using the "Upload..." button at the bottom of the tool. The JSON representation is convienient if you would like to use the same color theme on multiple devices.

- +

+When the 'Auto apply "Dark" from OS' checkbox is checked, then whenever the operating system transitions into its "dark" color scheme, then InterSpec will automatically apply the default "Dark" color theme; when the operating system goes back to its default or "light" theme, then your selected color theme will be applied, or if you havent selected a color theme, the "Default" color theme will be used. +There is currently no way to customize the auto-applied dark theme. +

@@ -38,7 +41,7 @@ This tool allows you to customize colors on the spectrum and time charts, as wel
- +
    diff --git a/InterSpec_resources/static_text/images/color_theme_dialog_top.png b/InterSpec_resources/static_text/images/color_theme_dialog_top.png index 183df66f..72a28b7e 100644 Binary files a/InterSpec_resources/static_text/images/color_theme_dialog_top.png and b/InterSpec_resources/static_text/images/color_theme_dialog_top.png differ diff --git a/data/default_preferences.xml b/data/default_preferences.xml index 03627334..0ff69e0e 100644 --- a/data/default_preferences.xml +++ b/data/default_preferences.xml @@ -45,4 +45,5 @@ true true true + true diff --git a/js/InterSpec.js b/js/InterSpec.js index ae9b13b5..870b412e 100644 --- a/js/InterSpec.js +++ b/js/InterSpec.js @@ -395,28 +395,43 @@ function() //Requires {macOS 10.14, iOS 13.0, iPadOS 13.0, Windows 10} and {Chrome 76, Safari 12.1, Firefox 67} + WT_DECLARE_WT_MEMBER -(SetupOsColorThemeChangeJs, Wt::JavaScriptFunction, "SetupOsColorThemeChangeJs", +(DetectOsColorThemeJs, Wt::JavaScriptFunction, "DetectOsColorThemeJs", function(id) { try { - var darkQ = window.matchMedia('(prefers-color-scheme: dark)'); - var lightQ = window.matchMedia('(prefers-color-scheme: light)'); - var noPrefQ = window.matchMedia('(prefers-color-scheme: no-preference)'); - var isSupported = darkQ.matches || lightQ.matches || noPrefQ.matches; - - if( !isSupported ) - throw 'no-support'; + const darkQ = window.matchMedia('(prefers-color-scheme: dark)'); + const lightQ = window.matchMedia('(prefers-color-scheme: light)'); + const noPrefQ = window.matchMedia('(prefers-color-scheme: no-preference)'); if( darkQ.matches ) Wt.emit( id, {name: 'OsColorThemeChange' }, 'dark' ); - - if( lightQ.matches ) + else if( lightQ.matches ) Wt.emit( id, {name: 'OsColorThemeChange' }, 'light' ); - - if( noPrefQ.matches ) + else if( noPrefQ.matches ) Wt.emit( id, {name: 'OsColorThemeChange' }, 'no-preference' ); + else + throw 'no-support'; + }catch(error) + { + Wt.emit( id, {name: 'OsColorThemeChange' }, 'no-support' ); + } +}); + +WT_DECLARE_WT_MEMBER +(SetupOsColorThemeChangeJs, Wt::JavaScriptFunction, "SetupOsColorThemeChangeJs", +function(id) +{ + try + { + const darkQ = window.matchMedia('(prefers-color-scheme: dark)'); + const lightQ = window.matchMedia('(prefers-color-scheme: light)'); + const noPrefQ = window.matchMedia('(prefers-color-scheme: no-preference)'); + + if( !darkQ.matches && !lightQ.matches && !noPrefQ.matches ) + console.warn( 'No matches for color scheme found.' ); darkQ.addListener( function(e){ if( e && e.matches ) @@ -435,7 +450,7 @@ function(id) }catch(error) { - Wt.emit( id, {name: 'OsColorThemeChange' }, 'no-support' ); + console.warn( 'Color theme not supported:', error ); } } ); diff --git a/src/ColorThemeWindow.cpp b/src/ColorThemeWindow.cpp index 5726cee2..4a008918 100644 --- a/src/ColorThemeWindow.cpp +++ b/src/ColorThemeWindow.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -254,6 +255,13 @@ m_apply( nullptr ) WContainerWidget *foot = footer(); AuxWindow::addHelpInFooter( foot, "color-theme-dialog" ); + WCheckBox *autoDarkCb = new WCheckBox( "Auto apply \"Dark\" from OS", foot ); + autoDarkCb->setFloatSide( Wt::Side::Left ); + autoDarkCb->setToolTip( "Apply the \"Dark\" color theme automatically according to" + " the operating systems current value, or when it transisitions." ); + + InterSpecUser::associateWidget(m_interspec->m_user, "AutoDarkFromOs", autoDarkCb, m_interspec); + m_save = new WPushButton( "Save", foot ); m_apply = new WPushButton( "Apply", foot ); m_save->setHiddenKeepsGeometry( true ); diff --git a/src/InterSpec.cpp b/src/InterSpec.cpp index 285dc6d9..ecfc6faf 100644 --- a/src/InterSpec.cpp +++ b/src/InterSpec.cpp @@ -3876,45 +3876,41 @@ void InterSpec::osThemeChange( std::string name ) return; } + //TODO: if( name == "no-support" ), then should hide widgets associated with "AutoDarkFromOs" + try { - const int colorThemIndex = m_user->preferenceValue("ColorThemeIndex", this); - if( colorThemIndex >= 0 ) - return; + const bool autoDark = InterSpecUser::preferenceValue( "AutoDarkFromOs", this ); - const auto oldTheme = ColorTheme::PredefinedColorTheme(-colorThemIndex); - - if( oldTheme != ColorTheme::PredefinedColorTheme::DefaultColorTheme ) - return; - - std::unique_ptr theme; - - if( name == "dark" ) + if( autoDark && (name == "dark") ) { //Check to see if we already have dark applied if( m_colorTheme && SpecUtils::icontains( m_colorTheme->theme_name.toUTF8(), "Dark") ) return; - cout << "Will set to dark" << endl; - theme = ColorTheme::predefinedTheme( ColorTheme::PredefinedColorTheme::DarkColorTheme ); - }else if( name == "light" || name == "default" || name == "no-preference" || name == "no-support" ) + cout << "Will set to dark color theme" << endl; + unique_ptr theme = ColorTheme::predefinedTheme( ColorTheme::PredefinedColorTheme::DarkColorTheme ); + assert( theme ); + if( theme ) + applyColorTheme( make_shared(*theme) ); + }else if( !autoDark || name == "light" || name == "default" || name == "no-preference" || name == "no-support" ) { - //Check to see if we already have light applied - if (m_colorTheme && SpecUtils::icontains(m_colorTheme->theme_name.toUTF8(), "Default")) + if( m_colorTheme + && (m_colorTheme->dbIndex < 0) + && (ColorTheme::PredefinedColorTheme(-m_colorTheme->dbIndex) == ColorTheme::PredefinedColorTheme::DarkColorTheme) ) { - cout << "Already have light color theme applied." << endl; - return; + cout << "Will set to default or user specified color theme, from \"Dark\"." << endl; + + m_colorTheme = nullptr; + applyColorTheme( nullptr ); + }else + { + cout << "Current theme is not \"Dark\", so not setting color theme." << endl; } - - cout << "Will set to default" << endl; - theme = ColorTheme::predefinedTheme( ColorTheme::PredefinedColorTheme::DefaultColorTheme ); } - - if( theme ) - applyColorTheme( make_shared(*theme) ); - }catch(...) + }catch( std::exception &e ) { - cerr << "InterSpec::osThemeChange() caught exception - not doing anything" << endl; + cerr << "InterSpec::osThemeChange() caught exception - not doing anything:" << e.what() << endl; } cout << "Done applying color theme" << endl; @@ -6947,6 +6943,20 @@ void InterSpec::addAboutMenu( Wt::WWidget *parent ) InterSpecUser::associateWidget( m_user, "TabletUseDesktopMenus", checkbox, this ); }//if( is tablet ) + WCheckBox *autoDarkCb = new WCheckBox( " Auto apply \"Dark\" theme" ); + item = subPopup->addWidget( autoDarkCb ); + HelpSystem::attachToolTipOn( item, "Applies the \"Dark\" color theme automatically according to" + " the operating systems current value, or when it transisitions.", + true, HelpSystem::ToolTipPosition::Right ); + InterSpecUser::associateWidget( m_user, "AutoDarkFromOs", autoDarkCb, this ); + + InterSpecUser::addCallbackWhenChanged( m_user, "AutoDarkFromOs", std::bind([](){ + InterSpec *viewer = InterSpec::instance(); + if( viewer ) + viewer->doJavaScript( "try{ Wt.WT.DetectOsColorThemeJs('" + viewer->id() + "'); }" + "catch(e){ console.error('Error with DetectOsColorThemeJs:',e); }" ); + }) ); + item = subPopup->addMenuItem("Color Themes..."); item->triggered().connect(boost::bind(&InterSpec::showColorThemeWindow, this)); @@ -8800,12 +8810,14 @@ std::set InterSpec::validForegroundSamples() const #if( APPLY_OS_COLOR_THEME_FROM_JS && !BUILD_AS_OSX_APP && !IOS && !BUILD_AS_ELECTRON_APP ) void InterSpec::initOsColorThemeChangeDetect() { - m_osColorThemeChange.reset( new JSignal( this, "OsColorThemeChange", true ) ); + m_osColorThemeChange.reset( new JSignal( this, "OsColorThemeChange", false ) ); m_osColorThemeChange->connect( boost::bind( &InterSpec::osThemeChange, this, boost::placeholders::_1 ) ); + LOAD_JAVASCRIPT(wApp, "js/InterSpec.js", "InterSpec", wtjsDetectOsColorThemeJs); LOAD_JAVASCRIPT(wApp, "js/InterSpec.js", "InterSpec", wtjsSetupOsColorThemeChangeJs); + doJavaScript( "Wt.WT.DetectOsColorThemeJs('" + id() + "')" ); doJavaScript( "Wt.WT.SetupOsColorThemeChangeJs('" + id() + "')" ); }//void initOsColorThemeChangeDetect() #endif