diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fd8ece62a6..00f56d1060 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -28,6 +28,7 @@ endif () set(CMAKE_OSX_SYSROOT "/") set(CMAKE_OSX_DEPLOYMENT_TARGET "") +add_subdirectory(displayapp) set(SDK_SOURCE_FILES # Startup @@ -420,12 +421,7 @@ list(APPEND SOURCE_FILES displayapp/screens/settings/SettingBluetooth.cpp ## Watch faces - displayapp/screens/WatchFaceAnalog.cpp - displayapp/screens/WatchFaceDigital.cpp - displayapp/screens/WatchFaceInfineat.cpp - displayapp/screens/WatchFaceTerminal.cpp - displayapp/screens/WatchFacePineTimeStyle.cpp - displayapp/screens/WatchFaceCasioStyleG7710.cpp + ${WATCHFACE_SOURCES} ## @@ -848,8 +844,6 @@ target_compile_options(infinitime_fonts PUBLIC $<$: ${ASM_FLAGS}> ) -add_subdirectory(displayapp/apps) - # NRF SDK add_library(nrf-sdk STATIC ${SDK_SOURCE_FILES}) target_include_directories(nrf-sdk SYSTEM PUBLIC . ../) diff --git a/src/components/settings/Settings.h b/src/components/settings/Settings.h index 063120774a..a3a7a358c6 100644 --- a/src/components/settings/Settings.h +++ b/src/components/settings/Settings.h @@ -1,9 +1,12 @@ #pragma once #include #include +#include +#include #include "components/brightness/BrightnessController.h" #include "components/fs/FS.h" -#include "displayapp/apps/Apps.h" +#include "displayapp/Apps.h" +#include "displayapp/WatchFaces.h" namespace Pinetime { namespace Controllers { @@ -60,15 +63,18 @@ namespace Pinetime { void Init(); void SaveSettings(); - void SetWatchFace(Pinetime::Applications::WatchFace face) { - if (face != settings.watchFace) { + void SetWatchFace(const char* face) { + const char* currentWatchFace = settings.watchFace.data(); + if (std::strcmp(face, currentWatchFace) != 0) { settingsChanged = true; + auto len = std::min(std::strlen(face), Pinetime::Applications::MaxWatchFaceNameSize); + std::memcpy(settings.watchFace.data(), face, len); + settings.watchFace[len] = 0; } - settings.watchFace = face; }; - Pinetime::Applications::WatchFace GetWatchFace() const { - return settings.watchFace; + const char* GetWatchFace() const { + return settings.watchFace.data(); }; void SetChimeOption(ChimesOption chimeOption) { @@ -297,7 +303,7 @@ namespace Pinetime { WeatherFormat weatherFormat = WeatherFormat::Metric; Notification notificationStatus = Notification::On; - Pinetime::Applications::WatchFace watchFace = Pinetime::Applications::WatchFace::Digital; + std::array watchFace = {0}; ChimesOption chimesOption = ChimesOption::None; PineTimeStyle PTS; diff --git a/src/displayapp/apps/Apps.h.in b/src/displayapp/Apps.h.in similarity index 69% rename from src/displayapp/apps/Apps.h.in rename to src/displayapp/Apps.h.in index 2104a267c0..91d498c8a0 100644 --- a/src/displayapp/apps/Apps.h.in +++ b/src/displayapp/Apps.h.in @@ -45,35 +45,14 @@ namespace Pinetime { Error }; - enum class WatchFace : uint8_t { - Digital, - Analog, - PineTimeStyle, - Terminal, - Infineat, - CasioStyleG7710, - }; - template struct AppTraits {}; - template - struct WatchFaceTraits {}; - template struct TypeList { static constexpr size_t Count = sizeof...(As); }; using UserAppTypes = TypeList<@USERAPP_TYPES@>; - - template - struct WatchFaceTypeList { - static constexpr size_t Count = sizeof...(Ws); - }; - - using UserWatchFaceTypes = WatchFaceTypeList<@WATCHFACE_TYPES@>; - - static_assert(UserWatchFaceTypes::Count >= 1); } } diff --git a/src/displayapp/CMakeLists.txt b/src/displayapp/CMakeLists.txt new file mode 100644 index 0000000000..5f9b737b82 --- /dev/null +++ b/src/displayapp/CMakeLists.txt @@ -0,0 +1,66 @@ +if(DEFINED ENABLE_USERAPPS) + set(USERAPP_TYPES ${ENABLE_USERAPPS} CACHE STRING "List of user apps to build into the firmware") +else () + set(DEFAULT_USER_APP_TYPES "Apps::StopWatch") + set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Alarm") + set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Timer") + set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Steps") + set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::HeartRate") + set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Music") + set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Paint") + set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Paddle") + set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Twos") + set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Dice") + set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Metronome") + set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Navigation") + set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Weather") + #set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Motion") + set(USERAPP_TYPES "${DEFAULT_USER_APP_TYPES}" CACHE STRING "List of user apps to build into the firmware") +endif () + +if(NOT DEFINED DEFAULT_WATCHFACE_NAMES ) + set(DEFAULT_WATCHFACE_NAMES "digital;analog;pinetimestyle;terminal;infineat;casioStyleG7710") +endif() +message("WATCH FACES\n-----------") +foreach(item ${DEFAULT_WATCHFACE_NAMES}) + if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/watchfaces/${item}) + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/watchfaces/${item}) + message(" * Watch face ${INFINITIME_WATCHFACE_NAME} enabled!") + list(APPEND DEFAULT_WATCHFACE_TYPES "${INFINITIME_WATCHFACE_NAMESPACE}") + list(APPEND WATCHFACE_SOURCES_LIST "${INFINITIME_WATCHFACE_SOURCES}") + string(APPEND WATCHFACE_INCLUDE "#include \"${INFINITIME_WATCHFACE_INCLUDES}\"\n") + endif() +endforeach() +set(WATCHFACE_SOURCES ${WATCHFACE_SOURCES_LIST} PARENT_SCOPE) + +# Generate the list of watchface types necessary to instantiate WatchFaceTypeList<> needed in WatchFace.h +set(FIRST_ITERATION TRUE) +foreach (watchface IN LISTS DEFAULT_WATCHFACE_TYPES) + if (${FIRST_ITERATION}) + string(APPEND WATCHFACE_TYPES "${watchface}") + set(FIRST_ITERATION FALSE) + else () + string(APPEND WATCHFACE_TYPES ", ${watchface}") + endif () +endforeach () + +# Generate the forward declarations needed in WatchFace.h +foreach (w IN LISTS DEFAULT_WATCHFACE_TYPES) + string(FIND ${w} "::" classIndex REVERSE) + string(LENGTH ${w} watchfaceFullLength) + math(EXPR watchfaceLength "${watchfaceFullLength} - (${classIndex} + 2)") + math(EXPR beginIndex "${classIndex}+2") + string(SUBSTRING ${w} ${beginIndex} ${watchfaceLength} className) + string(SUBSTRING ${w} 0 ${classIndex} namespaceName) + string(APPEND WATCHFACE_NAMESPACE "namespace ${namespaceName} { class ${className}; }\n") +endforeach () + +add_library(infinitime_apps INTERFACE) +target_sources(infinitime_apps INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/Apps.h") +target_include_directories(infinitime_apps INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/") +target_include_directories(infinitime_apps INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/../") + +# Generate the list of user apps to be compiled into the firmware +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Apps.h.in ${CMAKE_CURRENT_BINARY_DIR}/Apps.h) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/WatchFaces.h.in ${CMAKE_CURRENT_BINARY_DIR}/WatchFaces.h) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/UserApps.h.in ${CMAKE_CURRENT_BINARY_DIR}/UserApps.h) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index f3f0bd934b..62e8646fb6 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -439,7 +439,7 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio case Apps::Clock: { const auto* watchFace = std::find_if(userWatchFaces.begin(), userWatchFaces.end(), [this](const WatchFaceDescription& watchfaceDescription) { - return watchfaceDescription.watchFace == settingsController.GetWatchFace(); + return std::strcmp(watchfaceDescription.name, settingsController.GetWatchFace()) == 0; }); if (watchFace != userWatchFaces.end()) currentScreen.reset(watchFace->create(controllers)); @@ -494,8 +494,7 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio std::array items; int i = 0; for (const auto& userWatchFace : userWatchFaces) { - items[i++] = - Screens::SettingWatchFace::Item {userWatchFace.name, userWatchFace.watchFace, userWatchFace.isAvailable(controllers.filesystem)}; + items[i++] = Screens::SettingWatchFace::Item {userWatchFace.name, userWatchFace.isAvailable(controllers.filesystem)}; } currentScreen = std::make_unique(this, std::move(items), settingsController, filesystem); } break; diff --git a/src/displayapp/DisplayApp.h b/src/displayapp/DisplayApp.h index 96bce4dd1d..349ca01424 100644 --- a/src/displayapp/DisplayApp.h +++ b/src/displayapp/DisplayApp.h @@ -4,7 +4,7 @@ #include #include #include -#include "displayapp/apps/Apps.h" +#include "displayapp/Apps.h" #include "displayapp/LittleVgl.h" #include "displayapp/TouchEvents.h" #include "components/brightness/BrightnessController.h" diff --git a/src/displayapp/UserApps.h b/src/displayapp/UserApps.h.in similarity index 67% rename from src/displayapp/UserApps.h rename to src/displayapp/UserApps.h.in index 67bbfa7d41..3e20dd20b6 100644 --- a/src/displayapp/UserApps.h +++ b/src/displayapp/UserApps.h.in @@ -1,19 +1,13 @@ #pragma once -#include "displayapp/apps/Apps.h" -#include "Controllers.h" +#include "displayapp/Apps.h" +#include "displayapp/Controllers.h" #include "displayapp/screens/Alarm.h" #include "displayapp/screens/Dice.h" #include "displayapp/screens/Timer.h" #include "displayapp/screens/Twos.h" #include "displayapp/screens/Tile.h" -#include "displayapp/screens/ApplicationList.h" -#include "displayapp/screens/WatchFaceDigital.h" -#include "displayapp/screens/WatchFaceAnalog.h" -#include "displayapp/screens/WatchFaceCasioStyleG7710.h" -#include "displayapp/screens/WatchFaceInfineat.h" -#include "displayapp/screens/WatchFacePineTimeStyle.h" -#include "displayapp/screens/WatchFaceTerminal.h" +@WATCHFACE_INCLUDE@ namespace Pinetime { namespace Applications { @@ -28,7 +22,6 @@ namespace Pinetime { }; struct WatchFaceDescription { - WatchFace watchFace; const char* name; Screens::Screen* (*create)(AppControllers& controllers); bool (*isAvailable)(Controllers::FS& fileSystem); @@ -39,9 +32,11 @@ namespace Pinetime { return {AppTraits::app, AppTraits::icon, &AppTraits::Create}; } - template + template consteval WatchFaceDescription CreateWatchFaceDescription() { - return {WatchFaceTraits::watchFace, WatchFaceTraits::name, &WatchFaceTraits::Create, &WatchFaceTraits::IsAvailable}; + static_assert(std::char_traits::length(WatchFaceTraits::name) < 16, + "The name of the watch faces is limited to 15 characters max"); + return {WatchFaceTraits::name, &WatchFaceTraits::Create, &WatchFaceTraits::IsAvailable}; } template