InfiniTime.git

commit 39bc166e549e8ccae75468aa2dd3613d51f54e27

Author: Jean-François Milants <jf@codingfield.com>

Watch face selection at build time

Watch faces can now be selected at buid time. It's implemented in a similar way than the selection of user apps, using a list of watch face description that is generated at build time (consteval, constexpr)

 src/CMakeLists.txt | 3 
 src/components/settings/Settings.h | 2 
 src/displayapp/Apps.h | 29 ++
 src/displayapp/DisplayApp.cpp | 48 ++--
 src/displayapp/UserApps.h | 25 ++
 src/displayapp/WatchFaces.h | 14 -
 src/displayapp/screens/Clock.cpp | 133 --------------
 src/displayapp/screens/Clock.h | 63 ------
 src/displayapp/screens/WatchFaceAnalog.h | 18 +
 src/displayapp/screens/WatchFaceCasioStyleG7710.h | 23 ++
 src/displayapp/screens/WatchFaceDigital.h | 21 ++
 src/displayapp/screens/WatchFaceInfineat.h | 22 ++
 src/displayapp/screens/WatchFacePineTimeStyle.h | 21 ++
 src/displayapp/screens/WatchFaceTerminal.h | 21 ++
 src/displayapp/screens/settings/SettingWatchFace.cpp | 9 
 src/displayapp/screens/settings/SettingWatchFace.h | 23 -


diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 4207161e36435123580ea333187743fabd6174de..9a993e0281ede3a9f20c714a15c6c186f89c1237 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -373,7 +373,6 @@         BootloaderVersion.cpp
         logging/NrfLogger.cpp
         displayapp/DisplayApp.cpp
         displayapp/screens/Screen.cpp
-        displayapp/screens/Clock.cpp
         displayapp/screens/Tile.cpp
         displayapp/screens/InfiniPaint.cpp
         displayapp/screens/Paddle.cpp
@@ -597,7 +596,6 @@         displayapp/DisplayApp.h
         displayapp/Messages.h
         displayapp/TouchEvents.h
         displayapp/screens/Screen.h
-        displayapp/screens/Clock.h
         displayapp/screens/Tile.h
         displayapp/screens/InfiniPaint.h
         displayapp/screens/StopWatch.h
@@ -613,7 +611,6 @@         displayapp/screens/FirmwareValidation.h
         displayapp/screens/ApplicationList.h
         displayapp/screens/CheckboxList.h
         displayapp/Apps.h
-        displayapp/WatchFaces.h
         displayapp/screens/Notifications.h
         displayapp/screens/HeartRate.h
         displayapp/screens/Metronome.h




diff --git a/src/components/settings/Settings.h b/src/components/settings/Settings.h
index 81cf4923323666341e8a9813e69a0998eec7d069..c9a0b799ce97a80df05826e755b283388a5a644c 100644
--- a/src/components/settings/Settings.h
+++ b/src/components/settings/Settings.h
@@ -3,7 +3,7 @@ #include 
 #include <bitset>
 #include "components/brightness/BrightnessController.h"
 #include "components/fs/FS.h"
-#include "displayapp/WatchFaces.h"
+#include "displayapp/Apps.h"
 
 namespace Pinetime {
   namespace Controllers {




diff --git a/src/displayapp/Apps.h b/src/displayapp/Apps.h
index f65fd2cf5174e3031c99d91ee47473b033ac0e31..097b530ebb0bef9d8caef44eca1faabcf149c46d 100644
--- a/src/displayapp/Apps.h
+++ b/src/displayapp/Apps.h
@@ -1,9 +1,10 @@
 #pragma once
 #include <cstddef>
+#include <cstdint>
 
 namespace Pinetime {
   namespace Applications {
-    enum class Apps {
+    enum class Apps : uint8_t {
       None,
       Launcher,
       Clock,
@@ -42,14 +43,31 @@       Error,
       Weather
     };
 
+    enum class WatchFace : uint8_t {
+      Digital = 0,
+      Analog = 1,
+      PineTimeStyle = 2,
+      Terminal = 3,
+      Infineat = 4,
+      CasioStyleG7710 = 5,
+    };
+
     template <Apps>
     struct AppTraits {};
+
+    template <WatchFace>
+    struct WatchFaceTraits {};
 
     template <Apps... As>
     struct TypeList {
       static constexpr size_t Count = sizeof...(As);
     };
 
+    template <WatchFace... Ws>
+    struct WatchFaceTypeList {
+      static constexpr size_t Count = sizeof...(Ws);
+    };
+
     using UserAppTypes = TypeList<Apps::StopWatch,
                                   Apps::Alarm,
                                   Apps::Timer,
@@ -66,5 +84,14 @@                                   Apps::Weather,
                                   Apps::Motion
                                   */
                                   >;
+
+    using UserWatchFaceTypes = WatchFaceTypeList<WatchFace::Digital,
+                                                 WatchFace::Analog,
+                                                 WatchFace::PineTimeStyle,
+                                                 WatchFace::Terminal,
+                                                 WatchFace::Infineat,
+                                                 WatchFace::CasioStyleG7710>;
+
+    static_assert(UserWatchFaceTypes::Count >= 1);
   }
 }




diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp
index 98be6324a9d21f49aab388190ee17eccdf3c6b03..3b34d7b8730ef358d0ba54cf4963c6caaded14d7 100644
--- a/src/displayapp/DisplayApp.cpp
+++ b/src/displayapp/DisplayApp.cpp
@@ -11,7 +11,6 @@ #include "components/ble/NotificationManager.h"
 #include "components/motion/MotionController.h"
 #include "components/motor/MotorController.h"
 #include "displayapp/screens/ApplicationList.h"
-#include "displayapp/screens/Clock.h"
 #include "displayapp/screens/FirmwareUpdate.h"
 #include "displayapp/screens/FirmwareValidation.h"
 #include "displayapp/screens/InfiniPaint.h"
@@ -435,17 +434,17 @@                                                                  dateTimeController,
                                                                  filesystem,
                                                                  std::move(apps));
     } break;
-    case Apps::Clock:
-      currentScreen = std::make_unique<Screens::Clock>(dateTimeController,
-                                                       batteryController,
-                                                       bleController,
-                                                       notificationManager,
-                                                       settingsController,
-                                                       heartRateController,
-                                                       motionController,
-                                                       systemTask->nimble().weather(),
-                                                       filesystem);
-      break;
+    case Apps::Clock: {
+      const auto* watchFace =
+        std::find_if(userWatchFaces.begin(), userWatchFaces.end(), [this](const WatchFaceDescription& watchfaceDescription) {
+          return watchfaceDescription.watchFace == settingsController.GetWatchFace();
+        });
+      if (watchFace != userWatchFaces.end())
+        currentScreen.reset(watchFace->create(controllers));
+      else {
+        currentScreen.reset(userWatchFaces[0].create(controllers));
+      }
+    } break;
     case Apps::Error:
       currentScreen = std::make_unique<Screens::Error>(bootError);
       break;
@@ -489,9 +488,14 @@       break;
     case Apps::Settings:
       currentScreen = std::make_unique<Screens::Settings>(this, settingsController);
       break;
-    case Apps::SettingWatchFace:
-      currentScreen = std::make_unique<Screens::SettingWatchFace>(this, settingsController, filesystem);
-      break;
+    case Apps::SettingWatchFace: {
+      std::array<Screens::CheckboxList::Item, UserWatchFaceTypes::Count> items;
+      int i = 0;
+      for (const auto& userWatchFace : userWatchFaces) {
+        items[i++] = Screens::CheckboxList::Item {userWatchFace.name, userWatchFace.isAvailable(controllers.filesystem)};
+      }
+      currentScreen = std::make_unique<Screens::SettingWatchFace>(this, std::move(items), settingsController, filesystem);
+    } break;
     case Apps::SettingTimeFormat:
       currentScreen = std::make_unique<Screens::SettingTimeFormat>(settingsController);
       break;
@@ -536,18 +540,10 @@     default: {
       const auto* d = std::find_if(userApps.begin(), userApps.end(), [app](const AppDescription& appDescription) {
         return appDescription.app == app;
       });
-      if (d != userApps.end())
+      if (d != userApps.end()) {
         currentScreen.reset(d->create(controllers));
-      else {
-        currentScreen = std::make_unique<Screens::Clock>(dateTimeController,
-                                                         batteryController,
-                                                         bleController,
-                                                         notificationManager,
-                                                         settingsController,
-                                                         heartRateController,
-                                                         motionController,
-                                                         systemTask->nimble().weather(),
-                                                         filesystem);
+      } else {
+        currentScreen.reset(userWatchFaces[0].create(controllers));
       }
       break;
     }




diff --git a/src/displayapp/UserApps.h b/src/displayapp/UserApps.h
index 0ed9d602940b195b5419d1663e4e8c4982e4c609..cb6d57795dacca57ccc47a78c805ca7883104f81 100644
--- a/src/displayapp/UserApps.h
+++ b/src/displayapp/UserApps.h
@@ -7,7 +7,12 @@ #include "displayapp/screens/Timer.h"
 #include "displayapp/screens/Twos.h"
 #include "displayapp/screens/Tile.h"
 #include "displayapp/screens/ApplicationList.h"
-#include "displayapp/screens/Clock.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"
 
 namespace Pinetime {
   namespace Applications {
@@ -21,9 +26,21 @@       const char* icon;
       Screens::Screen* (*create)(AppControllers& controllers);
     };
 
+    struct WatchFaceDescription {
+      WatchFace watchFace;
+      const char* name;
+      Screens::Screen* (*create)(AppControllers& controllers);
+      bool (*isAvailable)(Controllers::FS& fileSystem);
+    };
+
     template <Apps t>
     consteval AppDescription CreateAppDescription() {
       return {AppTraits<t>::app, AppTraits<t>::icon, &AppTraits<t>::Create};
+    }
+
+    template <WatchFace t>
+    consteval WatchFaceDescription CreateWatchFaceDescription() {
+      return {WatchFaceTraits<t>::watchFace, WatchFaceTraits<t>::name, &WatchFaceTraits<t>::Create, &WatchFaceTraits<t>::IsAvailable};
     }
 
     template <template <Apps...> typename T, Apps... ts>
@@ -31,6 +48,12 @@     consteval std::array CreateAppDescriptions(T) {
       return {CreateAppDescription<ts>()...};
     }
 
+    template <template <WatchFace...> typename T, WatchFace... ts>
+    consteval std::array<WatchFaceDescription, sizeof...(ts)> CreateWatchFaceDescriptions(T<ts...>) {
+      return {CreateWatchFaceDescription<ts>()...};
+    }
+
     constexpr auto userApps = CreateAppDescriptions(UserAppTypes {});
+    constexpr auto userWatchFaces = CreateWatchFaceDescriptions(UserWatchFaceTypes {});
   }
 }




diff --git a/src/displayapp/WatchFaces.h b/src/displayapp/WatchFaces.h
deleted file mode 100644
index 2982347aa13cf2dcbdaf068134993dbc2d5a7f10..0000000000000000000000000000000000000000
--- a/src/displayapp/WatchFaces.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#pragma once
-
-namespace Pinetime {
-  namespace Applications {
-    enum class WatchFace : uint8_t {
-      Digital = 0,
-      Analog = 1,
-      PineTimeStyle = 2,
-      Terminal = 3,
-      Infineat = 4,
-      CasioStyleG7710 = 5,
-    };
-  }
-}




diff --git a/src/displayapp/screens/Clock.cpp b/src/displayapp/screens/Clock.cpp
deleted file mode 100644
index 4219b090db3b9b0c8d78a44aa967a7d8a7f1e0db..0000000000000000000000000000000000000000
--- a/src/displayapp/screens/Clock.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-#include "displayapp/screens/Clock.h"
-
-#include <lvgl/lvgl.h>
-#include "components/battery/BatteryController.h"
-#include "components/motion/MotionController.h"
-#include "components/ble/BleController.h"
-#include "components/ble/NotificationManager.h"
-#include "components/settings/Settings.h"
-#include "displayapp/DisplayApp.h"
-#include "displayapp/screens/WatchFaceDigital.h"
-#include "displayapp/screens/WatchFaceTerminal.h"
-#include "displayapp/screens/WatchFaceInfineat.h"
-#include "displayapp/screens/WatchFaceAnalog.h"
-#include "displayapp/screens/WatchFacePineTimeStyle.h"
-#include "displayapp/screens/WatchFaceCasioStyleG7710.h"
-
-using namespace Pinetime::Applications::Screens;
-using namespace Pinetime::Applications;
-
-Clock::Clock(Controllers::DateTime& dateTimeController,
-             const Controllers::Battery& batteryController,
-             const Controllers::Ble& bleController,
-             Controllers::NotificationManager& notificationManager,
-             Controllers::Settings& settingsController,
-             Controllers::HeartRateController& heartRateController,
-             Controllers::MotionController& motionController,
-             Controllers::WeatherService& weatherService,
-             Controllers::FS& filesystem)
-  : dateTimeController {dateTimeController},
-    batteryController {batteryController},
-    bleController {bleController},
-    notificationManager {notificationManager},
-    settingsController {settingsController},
-    heartRateController {heartRateController},
-    motionController {motionController},
-    weatherService {weatherService},
-    filesystem {filesystem},
-    screen {[this, &settingsController]() {
-      switch (settingsController.GetWatchFace()) {
-        case WatchFace::Digital:
-          return WatchFaceDigitalScreen();
-          break;
-        case WatchFace::Analog:
-          return WatchFaceAnalogScreen();
-          break;
-        case WatchFace::PineTimeStyle:
-          return WatchFacePineTimeStyleScreen();
-          break;
-        case WatchFace::Terminal:
-          return WatchFaceTerminalScreen();
-          break;
-        case WatchFace::Infineat:
-          return WatchFaceInfineatScreen();
-          break;
-        case WatchFace::CasioStyleG7710:
-          return WatchFaceCasioStyleG7710();
-          break;
-      }
-      return WatchFaceDigitalScreen();
-    }()} {
-  settingsController.SetAppMenu(0);
-}
-
-Clock::~Clock() {
-  lv_obj_clean(lv_scr_act());
-}
-
-bool Clock::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
-  return screen->OnTouchEvent(event);
-}
-
-bool Clock::OnButtonPushed() {
-  return screen->OnButtonPushed();
-}
-
-std::unique_ptr<Screen> Clock::WatchFaceDigitalScreen() {
-  return std::make_unique<Screens::WatchFaceDigital>(dateTimeController,
-                                                     batteryController,
-                                                     bleController,
-                                                     notificationManager,
-                                                     settingsController,
-                                                     heartRateController,
-                                                     motionController);
-}
-
-std::unique_ptr<Screen> Clock::WatchFaceAnalogScreen() {
-  return std::make_unique<Screens::WatchFaceAnalog>(dateTimeController,
-                                                    batteryController,
-                                                    bleController,
-                                                    notificationManager,
-                                                    settingsController);
-}
-
-std::unique_ptr<Screen> Clock::WatchFacePineTimeStyleScreen() {
-  return std::make_unique<Screens::WatchFacePineTimeStyle>(dateTimeController,
-                                                           batteryController,
-                                                           bleController,
-                                                           notificationManager,
-                                                           settingsController,
-                                                           motionController,
-                                                           weatherService);
-}
-
-std::unique_ptr<Screen> Clock::WatchFaceTerminalScreen() {
-  return std::make_unique<Screens::WatchFaceTerminal>(dateTimeController,
-                                                      batteryController,
-                                                      bleController,
-                                                      notificationManager,
-                                                      settingsController,
-                                                      heartRateController,
-                                                      motionController);
-}
-
-std::unique_ptr<Screen> Clock::WatchFaceInfineatScreen() {
-  return std::make_unique<Screens::WatchFaceInfineat>(dateTimeController,
-                                                      batteryController,
-                                                      bleController,
-                                                      notificationManager,
-                                                      settingsController,
-                                                      motionController,
-                                                      filesystem);
-}
-
-std::unique_ptr<Screen> Clock::WatchFaceCasioStyleG7710() {
-  return std::make_unique<Screens::WatchFaceCasioStyleG7710>(dateTimeController,
-                                                             batteryController,
-                                                             bleController,
-                                                             notificationManager,
-                                                             settingsController,
-                                                             heartRateController,
-                                                             motionController,
-                                                             filesystem);
-}




diff --git a/src/displayapp/screens/Clock.h b/src/displayapp/screens/Clock.h
deleted file mode 100644
index e67c0260f43c20d3575fc3923ddc646f4fcad0f8..0000000000000000000000000000000000000000
--- a/src/displayapp/screens/Clock.h
+++ /dev/null
@@ -1,63 +0,0 @@
-#pragma once
-
-#include <chrono>
-#include <cstdint>
-#include <memory>
-#include "displayapp/Controllers.h"
-#include "displayapp/screens/Screen.h"
-#include "displayapp/Apps.h"
-#include "Symbols.h"
-
-namespace Pinetime {
-  namespace Controllers {
-    class Settings;
-    class Battery;
-    class Ble;
-    class NotificationManager;
-    class MotionController;
-    class DateTime;
-    class HeartRateController;
-    class WeatherService;
-    class FS;
-  }
-
-  namespace Applications {
-    namespace Screens {
-      class Clock : public Screen {
-      public:
-        Clock(Controllers::DateTime& dateTimeController,
-              const Controllers::Battery& batteryController,
-              const Controllers::Ble& bleController,
-              Controllers::NotificationManager& notificationManager,
-              Controllers::Settings& settingsController,
-              Controllers::HeartRateController& heartRateController,
-              Controllers::MotionController& motionController,
-              Controllers::WeatherService& weatherService,
-              Controllers::FS& filesystem);
-        ~Clock() override;
-
-        bool OnTouchEvent(TouchEvents event) override;
-        bool OnButtonPushed() override;
-
-      private:
-        Controllers::DateTime& dateTimeController;
-        const Controllers::Battery& batteryController;
-        const Controllers::Ble& bleController;
-        Controllers::NotificationManager& notificationManager;
-        Controllers::Settings& settingsController;
-        Controllers::HeartRateController& heartRateController;
-        Controllers::MotionController& motionController;
-        Controllers::WeatherService& weatherService;
-        Controllers::FS& filesystem;
-
-        std::unique_ptr<Screen> screen;
-        std::unique_ptr<Screen> WatchFaceDigitalScreen();
-        std::unique_ptr<Screen> WatchFaceAnalogScreen();
-        std::unique_ptr<Screen> WatchFacePineTimeStyleScreen();
-        std::unique_ptr<Screen> WatchFaceTerminalScreen();
-        std::unique_ptr<Screen> WatchFaceInfineatScreen();
-        std::unique_ptr<Screen> WatchFaceCasioStyleG7710();
-      };
-    }
-  }
-}




diff --git a/src/displayapp/screens/WatchFaceAnalog.h b/src/displayapp/screens/WatchFaceAnalog.h
index 7e83cfcb14a79adbe4566c0781089dee0e37eb65..89ad4e134603e986a5aa804e53d0402777dd2400 100644
--- a/src/displayapp/screens/WatchFaceAnalog.h
+++ b/src/displayapp/screens/WatchFaceAnalog.h
@@ -88,5 +88,23 @@
         lv_task_t* taskRefresh;
       };
     }
+
+    template <>
+    struct WatchFaceTraits<WatchFace::Analog> {
+      static constexpr WatchFace watchFace = WatchFace::Analog;
+      static constexpr const char* name = "Analog face";
+
+      static Screens::Screen* Create(AppControllers& controllers) {
+        return new Screens::WatchFaceAnalog(controllers.dateTimeController,
+                                            controllers.batteryController,
+                                            controllers.bleController,
+                                            controllers.notificationManager,
+                                            controllers.settingsController);
+      };
+
+      static bool IsAvailable(Pinetime::Controllers::FS& /*filesystem*/) {
+        return true;
+      }
+    };
   }
 }




diff --git a/src/displayapp/screens/WatchFaceCasioStyleG7710.h b/src/displayapp/screens/WatchFaceCasioStyleG7710.h
index f84db7b548bb184fa6afe663922e649f26dd2be4..7f71a21fb98ac89465360426df94a10205813320 100644
--- a/src/displayapp/screens/WatchFaceCasioStyleG7710.h
+++ b/src/displayapp/screens/WatchFaceCasioStyleG7710.h
@@ -5,10 +5,12 @@ #include 
 #include <chrono>
 #include <cstdint>
 #include <memory>
+#include <displayapp/Controllers.h>
 #include "displayapp/screens/Screen.h"
 #include "components/datetime/DateTimeController.h"
 #include "components/ble/BleController.h"
 #include "utility/DirtyValue.h"
+#include "displayapp/Apps.h"
 
 namespace Pinetime {
   namespace Controllers {
@@ -100,5 +102,26 @@         lv_font_t* font_segment40 = nullptr;
         lv_font_t* font_segment115 = nullptr;
       };
     }
+
+    template <>
+    struct WatchFaceTraits<WatchFace::CasioStyleG7710> {
+      static constexpr WatchFace watchFace = WatchFace::CasioStyleG7710;
+      static constexpr const char* name = "Casio G7710";
+
+      static Screens::Screen* Create(AppControllers& controllers) {
+        return new Screens::WatchFaceCasioStyleG7710(controllers.dateTimeController,
+                                                     controllers.batteryController,
+                                                     controllers.bleController,
+                                                     controllers.notificationManager,
+                                                     controllers.settingsController,
+                                                     controllers.heartRateController,
+                                                     controllers.motionController,
+                                                     controllers.filesystem);
+      };
+
+      static bool IsAvailable(Pinetime::Controllers::FS& filesystem) {
+        return Screens::WatchFaceCasioStyleG7710::IsAvailable(filesystem);
+      }
+    };
   }
 }




diff --git a/src/displayapp/screens/WatchFaceDigital.h b/src/displayapp/screens/WatchFaceDigital.h
index f2409880e981b4eeb17b816c713fe51c466d370a..a124a1c56212501189edaad2fc54faf22a937f2e 100644
--- a/src/displayapp/screens/WatchFaceDigital.h
+++ b/src/displayapp/screens/WatchFaceDigital.h
@@ -9,6 +9,7 @@ #include "components/datetime/DateTimeController.h"
 #include "components/ble/BleController.h"
 #include "displayapp/widgets/StatusIcons.h"
 #include "utility/DirtyValue.h"
+#include "displayapp/Apps.h"
 
 namespace Pinetime {
   namespace Controllers {
@@ -71,5 +72,25 @@         lv_task_t* taskRefresh;
         Widgets::StatusIcons statusIcons;
       };
     }
+
+    template <>
+    struct WatchFaceTraits<WatchFace::Digital> {
+      static constexpr WatchFace watchFace = WatchFace::Digital;
+      static constexpr const char* name = "Digital face";
+
+      static Screens::Screen* Create(AppControllers& controllers) {
+        return new Screens::WatchFaceDigital(controllers.dateTimeController,
+                                             controllers.batteryController,
+                                             controllers.bleController,
+                                             controllers.notificationManager,
+                                             controllers.settingsController,
+                                             controllers.heartRateController,
+                                             controllers.motionController);
+      };
+
+      static bool IsAvailable(Pinetime::Controllers::FS& /*filesystem*/) {
+        return true;
+      }
+    };
   }
 }




diff --git a/src/displayapp/screens/WatchFaceInfineat.h b/src/displayapp/screens/WatchFaceInfineat.h
index 33532abb8e910da8d66a833fb8c9a4124e662165..bd8862d509845449fc3b0bd5d272d6c261dd19a8 100644
--- a/src/displayapp/screens/WatchFaceInfineat.h
+++ b/src/displayapp/screens/WatchFaceInfineat.h
@@ -4,9 +4,11 @@ #include 
 #include <chrono>
 #include <cstdint>
 #include <memory>
+#include <displayapp/Controllers.h>
 #include "displayapp/screens/Screen.h"
 #include "components/datetime/DateTimeController.h"
 #include "utility/DirtyValue.h"
+#include "displayapp/Apps.h"
 
 namespace Pinetime {
   namespace Controllers {
@@ -98,5 +100,25 @@         lv_font_t* font_teko = nullptr;
         lv_font_t* font_bebas = nullptr;
       };
     }
+
+    template <>
+    struct WatchFaceTraits<WatchFace::Infineat> {
+      static constexpr WatchFace watchFace = WatchFace::Infineat;
+      static constexpr const char* name = "Infineat face";
+
+      static Screens::Screen* Create(AppControllers& controllers) {
+        return new Screens::WatchFaceInfineat(controllers.dateTimeController,
+                                              controllers.batteryController,
+                                              controllers.bleController,
+                                              controllers.notificationManager,
+                                              controllers.settingsController,
+                                              controllers.motionController,
+                                              controllers.filesystem);
+      };
+
+      static bool IsAvailable(Pinetime::Controllers::FS& filesystem) {
+        return Screens::WatchFaceInfineat::IsAvailable(filesystem);
+      }
+    };
   }
 }




diff --git a/src/displayapp/screens/WatchFacePineTimeStyle.h b/src/displayapp/screens/WatchFacePineTimeStyle.h
index e157bb2cd2ce682f42b45d35fa3233c41710be75..dd079fed8bfef99b767dd0a104f43a00b25145bd 100644
--- a/src/displayapp/screens/WatchFacePineTimeStyle.h
+++ b/src/displayapp/screens/WatchFacePineTimeStyle.h
@@ -4,6 +4,7 @@ #include 
 #include <chrono>
 #include <cstdint>
 #include <memory>
+#include <displayapp/Controllers.h>
 #include "displayapp/screens/Screen.h"
 #include "displayapp/screens/BatteryIcon.h"
 #include "displayapp/Colors.h"
@@ -121,5 +122,25 @@
         lv_task_t* taskRefresh;
       };
     }
+
+    template <>
+    struct WatchFaceTraits<WatchFace::PineTimeStyle> {
+      static constexpr WatchFace watchFace = WatchFace::PineTimeStyle;
+      static constexpr const char* name = "PineTimeStyle";
+
+      static Screens::Screen* Create(AppControllers& controllers) {
+        return new Screens::WatchFacePineTimeStyle(controllers.dateTimeController,
+                                                   controllers.batteryController,
+                                                   controllers.bleController,
+                                                   controllers.notificationManager,
+                                                   controllers.settingsController,
+                                                   controllers.motionController,
+                                                   *controllers.weatherController);
+      };
+
+      static bool IsAvailable(Pinetime::Controllers::FS& /*filesystem*/) {
+        return true;
+      }
+    };
   }
 }




diff --git a/src/displayapp/screens/WatchFaceTerminal.h b/src/displayapp/screens/WatchFaceTerminal.h
index d08a146b065d634a8772e1ad1f08e8aeb43de25a..ce22005fb9619df2d35d8097553fa7c6489c803f 100644
--- a/src/displayapp/screens/WatchFaceTerminal.h
+++ b/src/displayapp/screens/WatchFaceTerminal.h
@@ -4,6 +4,7 @@ #include 
 #include <chrono>
 #include <cstdint>
 #include <memory>
+#include <displayapp/Controllers.h>
 #include "displayapp/screens/Screen.h"
 #include "components/datetime/DateTimeController.h"
 #include "utility/DirtyValue.h"
@@ -68,5 +69,25 @@
         lv_task_t* taskRefresh;
       };
     }
+
+    template <>
+    struct WatchFaceTraits<WatchFace::Terminal> {
+      static constexpr WatchFace watchFace = WatchFace::Terminal;
+      static constexpr const char* name = "Terminal";
+
+      static Screens::Screen* Create(AppControllers& controllers) {
+        return new Screens::WatchFaceTerminal(controllers.dateTimeController,
+                                              controllers.batteryController,
+                                              controllers.bleController,
+                                              controllers.notificationManager,
+                                              controllers.settingsController,
+                                              controllers.heartRateController,
+                                              controllers.motionController);
+      };
+
+      static bool IsAvailable(Pinetime::Controllers::FS& /*filesystem*/) {
+        return true;
+      }
+    };
   }
 }




diff --git a/src/displayapp/screens/settings/SettingWatchFace.cpp b/src/displayapp/screens/settings/SettingWatchFace.cpp
index 5498d06792363ab5281d82c30d60ce19c1bbd08c..f052573c366b935395fe841105bdf86cefb1506b 100644
--- a/src/displayapp/screens/settings/SettingWatchFace.cpp
+++ b/src/displayapp/screens/settings/SettingWatchFace.cpp
@@ -3,7 +3,6 @@ #include 
 #include "displayapp/DisplayApp.h"
 #include "displayapp/screens/Screen.h"
 #include "components/settings/Settings.h"
-#include "displayapp/WatchFaces.h"
 
 using namespace Pinetime::Applications::Screens;
 
@@ -21,9 +20,11 @@   return screens;
 }
 
 SettingWatchFace::SettingWatchFace(Pinetime::Applications::DisplayApp* app,
+                                   std::array<Screens::CheckboxList::Item, UserWatchFaceTypes::Count>&& watchfaceItems,
                                    Pinetime::Controllers::Settings& settingsController,
                                    Pinetime::Controllers::FS& filesystem)
   : app {app},
+    watchfaceItems {std::move(watchfaceItems)},
     settingsController {settingsController},
     filesystem {filesystem},
     screens {app, 0, CreateScreenList(), Screens::ScreenListModes::UpDown} {
@@ -40,7 +41,11 @@
 std::unique_ptr<Screen> SettingWatchFace::CreateScreen(unsigned int screenNum) const {
   std::array<Screens::CheckboxList::Item, settingsPerScreen> watchfacesOnThisScreen;
   for (int i = 0; i < settingsPerScreen; i++) {
-    watchfacesOnThisScreen[i] = watchfaces[screenNum * settingsPerScreen + i];
+    if (i + (screenNum * settingsPerScreen) >= watchfaceItems.size()) {
+      watchfacesOnThisScreen[i] = {"", false};
+    } else {
+      watchfacesOnThisScreen[i] = watchfaceItems[i + (screenNum * settingsPerScreen)];
+    }
   }
 
   return std::make_unique<Screens::CheckboxList>(




diff --git a/src/displayapp/screens/settings/SettingWatchFace.h b/src/displayapp/screens/settings/SettingWatchFace.h
index 45a50e3d0bca4f44fc36d71a2b76ddc30cea8566..66559c73cbbde25b40c0c2e0fcd3fe8140fcbb39 100644
--- a/src/displayapp/screens/settings/SettingWatchFace.h
+++ b/src/displayapp/screens/settings/SettingWatchFace.h
@@ -19,7 +19,10 @@     namespace Screens {
 
       class SettingWatchFace : public Screen {
       public:
-        SettingWatchFace(DisplayApp* app, Pinetime::Controllers::Settings& settingsController, Pinetime::Controllers::FS& filesystem);
+        SettingWatchFace(DisplayApp* app,
+                         std::array<Screens::CheckboxList::Item, UserWatchFaceTypes::Count>&& watchfaceItems,
+                         Pinetime::Controllers::Settings& settingsController,
+                         Pinetime::Controllers::FS& filesystem);
         ~SettingWatchFace() override;
 
         bool OnTouchEvent(TouchEvents event) override;
@@ -29,26 +32,16 @@         DisplayApp* app;
         auto CreateScreenList() const;
         std::unique_ptr<Screen> CreateScreen(unsigned int screenNum) const;
 
+        static constexpr int settingsPerScreen = 4;
+        std::array<Screens::CheckboxList::Item, UserWatchFaceTypes::Count> watchfaceItems;
+        static constexpr int nScreens = UserWatchFaceTypes::Count > 0 ? (UserWatchFaceTypes ::Count - 1) / settingsPerScreen + 1 : 1;
+
         Controllers::Settings& settingsController;
         Pinetime::Controllers::FS& filesystem;
 
         static constexpr const char* title = "Watch face";
         static constexpr const char* symbol = Symbols::home;
 
-        static constexpr int settingsPerScreen = 4;
-
-        // Increment this when more space is needed
-        static constexpr int nScreens = 2;
-
-        std::array<Screens::CheckboxList::Item, settingsPerScreen * nScreens> watchfaces {
-          {{"Digital face", true},
-           {"Analog face", true},
-           {"PineTimeStyle", true},
-           {"Terminal", true},
-           {"Infineat face", Applications::Screens::WatchFaceInfineat::IsAvailable(filesystem)},
-           {"Casio G7710", Applications::Screens::WatchFaceCasioStyleG7710::IsAvailable(filesystem)},
-           {"", false},
-           {"", false}}};
         ScreenList<nScreens> screens;
       };
     }