InfiniTime.git

commit eb0af22ecf66957b9341521990c49a6d1d5d70e3

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

Watch face settings : disable watch faces that are not available (external resources are not installed).

 src/displayapp/DisplayApp.cpp | 2 
 src/displayapp/screens/CheckboxList.cpp | 14 +++++++---
 src/displayapp/screens/CheckboxList.h | 9 +++++-
 src/displayapp/screens/WatchFaceCasioStyleG7710.cpp | 17 +++++++++++++
 src/displayapp/screens/WatchFaceCasioStyleG7710.h | 2 +
 src/displayapp/screens/WatchFaceInfineat.cpp | 18 +++++++++++++
 src/displayapp/screens/WatchFaceInfineat.h | 2 +
 src/displayapp/screens/settings/SettingWatchFace.cpp | 16 ++++++++++--
 src/displayapp/screens/settings/SettingWatchFace.h | 3 +


diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp
index 4afcd8dc53b68ea4f18184138ae6dd5462af783f..108e380d69d3e9f215ae498833e42cfea345e78e 100644
--- a/src/displayapp/DisplayApp.cpp
+++ b/src/displayapp/DisplayApp.cpp
@@ -390,7 +390,7 @@       currentScreen = std::make_unique(this, settingsController);
       ReturnApp(Apps::QuickSettings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
       break;
     case Apps::SettingWatchFace:
-      currentScreen = std::make_unique<Screens::SettingWatchFace>(this, settingsController);
+      currentScreen = std::make_unique<Screens::SettingWatchFace>(this, settingsController, filesystem);
       ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
       break;
     case Apps::SettingTimeFormat:




diff --git a/src/displayapp/screens/CheckboxList.cpp b/src/displayapp/screens/CheckboxList.cpp
index d97726dd5959b26629d9b6c2f066251f29f933d9..5889c69ae89ff712f156e023959d38b21d304d79 100644
--- a/src/displayapp/screens/CheckboxList.cpp
+++ b/src/displayapp/screens/CheckboxList.cpp
@@ -18,7 +18,7 @@                            const char* optionsTitle,
                            const char* optionsSymbol,
                            uint32_t originalValue,
                            std::function<void(uint32_t)> OnValueChanged,
-                           std::array<const char*, MaxItems> options)
+                           std::array<Item, MaxItems> options)
   : Screen(app), screenID {screenID}, OnValueChanged {std::move(OnValueChanged)}, options {options}, value {originalValue} {
   // Set the background to Black
   lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
@@ -72,9 +72,12 @@   lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER);
   lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0);
 
   for (unsigned int i = 0; i < options.size(); i++) {
-    if (strcmp(options[i], "")) {
+    if (strcmp(options[i].name, "")) {
       cbOption[i] = lv_checkbox_create(container1, nullptr);
-      lv_checkbox_set_text(cbOption[i], options[i]);
+      lv_checkbox_set_text(cbOption[i], options[i].name);
+      if (!options[i].enabled) {
+        lv_checkbox_set_disabled(cbOption[i]);
+      }
       cbOption[i]->user_data = this;
       lv_obj_set_event_cb(cbOption[i], event_handler);
       SetRadioButtonStyle(cbOption[i]);
@@ -94,12 +97,15 @@
 void CheckboxList::UpdateSelected(lv_obj_t* object, lv_event_t event) {
   if (event == LV_EVENT_VALUE_CHANGED) {
     for (unsigned int i = 0; i < options.size(); i++) {
-      if (strcmp(options[i], "")) {
+      if (strcmp(options[i].name, "")) {
         if (object == cbOption[i]) {
           lv_checkbox_set_checked(cbOption[i], true);
           value = MaxItems * screenID + i;
         } else {
           lv_checkbox_set_checked(cbOption[i], false);
+        }
+        if (!options[i].enabled) {
+          lv_checkbox_set_disabled(cbOption[i]);
         }
       }
     }




diff --git a/src/displayapp/screens/CheckboxList.h b/src/displayapp/screens/CheckboxList.h
index f9c3bae05fe0c33cf88936ed42f5884d47dcec42..e9104bfb919e282fb1d1bb844110c39e620d65b7 100644
--- a/src/displayapp/screens/CheckboxList.h
+++ b/src/displayapp/screens/CheckboxList.h
@@ -14,6 +14,11 @@     namespace Screens {
       class CheckboxList : public Screen {
       public:
         static constexpr size_t MaxItems = 4;
+        struct Item {
+          const char* name;
+          bool enabled;
+        };
+
         CheckboxList(const uint8_t screenID,
                      const uint8_t numScreens,
                      DisplayApp* app,
@@ -21,14 +26,14 @@                      const char* optionsTitle,
                      const char* optionsSymbol,
                      uint32_t originalValue,
                      std::function<void(uint32_t)> OnValueChanged,
-                     std::array<const char*, MaxItems> options);
+                     std::array<Item, MaxItems> options);
         ~CheckboxList() override;
         void UpdateSelected(lv_obj_t* object, lv_event_t event);
 
       private:
         const uint8_t screenID;
         std::function<void(uint32_t)> OnValueChanged;
-        std::array<const char*, MaxItems> options;
+        std::array<Item, MaxItems> options;
         std::array<lv_obj_t*, MaxItems> cbOption;
         std::array<lv_point_t, 2> pageIndicatorBasePoints;
         std::array<lv_point_t, 2> pageIndicatorPoints;




diff --git a/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp b/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp
index f9a01abde37168e5370cef1e433e07de8357683e..525c2eebc0ad1302a8f300fa4ab5bcbb7c2210bf 100644
--- a/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp
+++ b/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp
@@ -333,3 +333,20 @@     lv_obj_realign(stepValue);
     lv_obj_realign(stepIcon);
   }
 }
+bool WatchFaceCasioStyleG7710::IsAvailable(Pinetime::Controllers::FS& filesystem) {
+  lfs_file file = {};
+
+  if (filesystem.FileOpen(&file, "/fonts/lv_font_dots_40.bin", LFS_O_RDONLY) < 0) {
+    return false;
+  }
+
+  if (filesystem.FileOpen(&file, "/fonts/7segments_40.bin", LFS_O_RDONLY) < 0) {
+    return false;
+  }
+
+  if (filesystem.FileOpen(&file, "/fonts/7segments_115.bin", LFS_O_RDONLY) < 0) {
+    return false;
+  }
+
+  return true;
+}




diff --git a/src/displayapp/screens/WatchFaceCasioStyleG7710.h b/src/displayapp/screens/WatchFaceCasioStyleG7710.h
index c3821205b4288e3877c07fd228bc96e1840e3496..eb7bb9e819b5863a1517584091470900e00823c9 100644
--- a/src/displayapp/screens/WatchFaceCasioStyleG7710.h
+++ b/src/displayapp/screens/WatchFaceCasioStyleG7710.h
@@ -37,6 +37,8 @@         ~WatchFaceCasioStyleG7710() override;
 
         void Refresh() override;
 
+        static bool IsAvailable(Pinetime::Controllers::FS& filesystem);
+
       private:
         uint8_t displayedHour = -1;
         uint8_t displayedMinute = -1;




diff --git a/src/displayapp/screens/WatchFaceInfineat.cpp b/src/displayapp/screens/WatchFaceInfineat.cpp
index 5822a1e8d00821f80fd6b5998f34b39f4fb4e0d0..01b425da07a351c7d0f929abfbbea076f63ec6b4 100644
--- a/src/displayapp/screens/WatchFaceInfineat.cpp
+++ b/src/displayapp/screens/WatchFaceInfineat.cpp
@@ -609,3 +609,21 @@                                     LV_STATE_DEFAULT,
                                     lv_color_hex(infineatColors.orange[settingsController.GetInfineatColorIndex() * nLines + 7]));
   }
 }
+
+bool WatchFaceInfineat::IsAvailable(Pinetime::Controllers::FS& filesystem) {
+  lfs_file file = {};
+
+  if (filesystem.FileOpen(&file, "/fonts/teko.bin", LFS_O_RDONLY) < 0) {
+    return false;
+  }
+
+  if (filesystem.FileOpen(&file, "/fonts/bebas.bin", LFS_O_RDONLY) < 0) {
+    return false;
+  }
+
+  if (filesystem.FileOpen(&file, "/images/pine_small.bin", LFS_O_RDONLY) < 0) {
+    return false;
+  }
+
+  return true;
+}




diff --git a/src/displayapp/screens/WatchFaceInfineat.h b/src/displayapp/screens/WatchFaceInfineat.h
index 285908e833d10087772ba7aa32ee1e7ce02a4f01..6c3c30bace8bd4ab01d81a6009de84c8f0b68056 100644
--- a/src/displayapp/screens/WatchFaceInfineat.h
+++ b/src/displayapp/screens/WatchFaceInfineat.h
@@ -39,6 +39,8 @@         void CloseMenu();
 
         void Refresh() override;
 
+        static bool IsAvailable(Pinetime::Controllers::FS& filesystem);
+
       private:
         char displayedChar[5] {};
 




diff --git a/src/displayapp/screens/settings/SettingWatchFace.cpp b/src/displayapp/screens/settings/SettingWatchFace.cpp
index 6d47f3a5dc8e47f11c931e4de78ccc1b4198e72f..217f97b8ea7cb6f6c3312f5ba744436e81b09789 100644
--- a/src/displayapp/screens/settings/SettingWatchFace.cpp
+++ b/src/displayapp/screens/settings/SettingWatchFace.cpp
@@ -4,15 +4,20 @@ #include "displayapp/DisplayApp.h"
 #include "displayapp/screens/CheckboxList.h"
 #include "displayapp/screens/Screen.h"
 #include "components/settings/Settings.h"
+#include "displayapp/screens/WatchFaceInfineat.h"
+#include "displayapp/screens/WatchFaceCasioStyleG7710.h"
 
 using namespace Pinetime::Applications::Screens;
 
 constexpr const char* SettingWatchFace::title;
 constexpr const char* SettingWatchFace::symbol;
 
-SettingWatchFace::SettingWatchFace(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& settingsController)
+SettingWatchFace::SettingWatchFace(Pinetime::Applications::DisplayApp* app,
+                                   Pinetime::Controllers::Settings& settingsController,
+                                   Pinetime::Controllers::FS& filesystem)
   : Screen(app),
     settingsController {settingsController},
+    filesystem {filesystem},
     screens {app,
              0,
              {[this]() -> std::unique_ptr<Screen> {
@@ -33,7 +38,8 @@   return screens.OnTouchEvent(event);
 }
 
 std::unique_ptr<Screen> SettingWatchFace::CreateScreen1() {
-  std::array<const char*, 4> watchfaces {"Digital face", "Analog face", "PineTimeStyle", "Terminal"};
+  std::array<Screens::CheckboxList::Item, 4> watchfaces {
+    {{"Digital face", true}, {"Analog face", true}, {"PineTimeStyle", true}, {"Terminal", true}}};
   return std::make_unique<Screens::CheckboxList>(
     0,
     2,
@@ -49,7 +55,11 @@     watchfaces);
 }
 
 std::unique_ptr<Screen> SettingWatchFace::CreateScreen2() {
-  std::array<const char*, 4> watchfaces {"Infineat face", "Casio G7710", "", ""};
+  std::array<Screens::CheckboxList::Item, 4> watchfaces {
+    {{"Infineat face", Applications::Screens::WatchFaceInfineat::IsAvailable(filesystem)},
+     {"Casio G7710", Applications::Screens::WatchFaceCasioStyleG7710::IsAvailable(filesystem)},
+     {"", false},
+     {"", false}}};
   return std::make_unique<Screens::CheckboxList>(
     1,
     2,




diff --git a/src/displayapp/screens/settings/SettingWatchFace.h b/src/displayapp/screens/settings/SettingWatchFace.h
index 7d14554eb2ae5399e179e66abe41b9dacf5bcb11..158397f835071ee3621c7564d2ad13d59268a708 100644
--- a/src/displayapp/screens/settings/SettingWatchFace.h
+++ b/src/displayapp/screens/settings/SettingWatchFace.h
@@ -16,13 +16,14 @@     namespace Screens {
 
       class SettingWatchFace : public Screen {
       public:
-        SettingWatchFace(DisplayApp* app, Pinetime::Controllers::Settings& settingsController);
+        SettingWatchFace(DisplayApp* app, Pinetime::Controllers::Settings& settingsController, Pinetime::Controllers::FS& filesystem);
         ~SettingWatchFace() override;
 
         bool OnTouchEvent(TouchEvents event) override;
 
       private:
         Controllers::Settings& settingsController;
+        Pinetime::Controllers::FS& filesystem;
         ScreenList<2> screens;
 
         static constexpr const char* title = "Watch face";