Compare commits
	
		
			7 Commits
		
	
	
		
			wb/fuzzy-n
			...
			wb/roman
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| b6ae30166b | |||
| d8c3624f6f | |||
|   | 20a5fef84c | ||
|   | 77667c6391 | ||
|   | 6c20c2992b | ||
|   | 5535fa6af7 | ||
|   | 796e8f1ada | 
							
								
								
									
										5
									
								
								.github/workflows/main.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.github/workflows/main.yml
									
									
									
									
										vendored
									
									
								
							| @ -3,7 +3,7 @@ name: CI | ||||
| # Run this workflow whenever the build may be affected | ||||
| on: | ||||
|   push: | ||||
|     branches: [ main, wb/fuzzy, wb/fuzzy-norm ] | ||||
|     branches: [ main, 'wb/*' ] | ||||
|     paths-ignore: | ||||
|       - 'doc/**' | ||||
|       - '**.md' | ||||
| @ -88,6 +88,9 @@ jobs: | ||||
|         git clone https://github.com/InfiniTimeOrg/InfiniSim.git --depth 1 --branch main | ||||
|         git -C InfiniSim submodule update --init lv_drivers | ||||
| 
 | ||||
|     - name: Add sunset lib to InfiniSim | ||||
|       run: patch -i docker/infinisim-cmake.patch InfiniSim/CMakeLists.txt | ||||
| 
 | ||||
|     - name: CMake | ||||
|       # disable BUILD_RESOURCES as this is already done when building the firmware | ||||
|       run:  | | ||||
|  | ||||
							
								
								
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							| @ -10,3 +10,6 @@ | ||||
| [submodule "src/libs/arduinoFFT"] | ||||
| 	path = src/libs/arduinoFFT | ||||
| 	url = https://github.com/kosme/arduinoFFT.git | ||||
| [submodule "src/libs/sunset"] | ||||
| 	path = src/libs/sunset | ||||
| 	url = https://github.com/buelowp/sunset.git | ||||
|  | ||||
| @ -4,6 +4,15 @@ | ||||
| 
 | ||||
| Fast open-source firmware for the [PineTime smartwatch](https://www.pine64.org/pinetime/) with many features, written in modern C++. | ||||
| 
 | ||||
| ## Roman Time | ||||
| 
 | ||||
| This branch contains a sundial that tries to approximate a Roman sundial | ||||
| as if it was mounted on a south-facing wall (i.e. rotates counterclockwise). | ||||
| 
 | ||||
| It's activated by selecting the Analog face and Fuzzy time format. | ||||
| 
 | ||||
| Based on (Sudrien's Roman watch face)[https://github.com/Sudrien/watchy_romantime] | ||||
| 
 | ||||
| ## New to InfiniTime? | ||||
| 
 | ||||
| - [Getting started with InfiniTime](doc/gettingStarted/gettingStarted-1.0.md) | ||||
|  | ||||
							
								
								
									
										19
									
								
								docker/infinisim-cmake.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								docker/infinisim-cmake.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| diff --git a/CMakeLists.txt b/CMakeLists.txt
 | ||||
| index edd6748..641b74a 100644
 | ||||
| --- a/CMakeLists.txt
 | ||||
| +++ b/CMakeLists.txt
 | ||||
| @@ -243,6 +243,14 @@ add_library(littlefs STATIC
 | ||||
|  target_include_directories(littlefs PUBLIC "${InfiniTime_DIR}/src/libs/littlefs") | ||||
|  target_link_libraries(infinisim PRIVATE littlefs) | ||||
|   | ||||
| +# sunset
 | ||||
| +add_library(sunset STATIC
 | ||||
| +  ${InfiniTime_DIR}/src/libs/sunset/src/sunset.h
 | ||||
| +  ${InfiniTime_DIR}/src/libs/sunset/src/sunset.cpp
 | ||||
| +)
 | ||||
| +target_include_directories(sunset PUBLIC "${InfiniTime_DIR}/src/libs/sunset")
 | ||||
| +target_link_libraries(infinisim PRIVATE sunset)
 | ||||
| +
 | ||||
|  # QCBOR | ||||
|  add_library(QCBOR STATIC | ||||
|    ${InfiniTime_DIR}/src/libs/QCBOR/src/ieee754.c | ||||
| @ -174,6 +174,11 @@ set(LITTLEFS_SRC | ||||
|         libs/littlefs/lfs.c | ||||
|         ) | ||||
| 
 | ||||
| set(SUNSET_SRC | ||||
|         libs/sunset/src/sunset.h | ||||
|         libs/sunset/src/sunset.cpp | ||||
|         ) | ||||
| 
 | ||||
| set(LVGL_SRC | ||||
|         libs/lv_conf.h | ||||
|         libs/lvgl/lvgl.h | ||||
| @ -412,6 +417,7 @@ list(APPEND SOURCE_FILES | ||||
|         displayapp/screens/settings/SettingSetDateTime.cpp | ||||
|         displayapp/screens/settings/SettingSetDate.cpp | ||||
|         displayapp/screens/settings/SettingSetTime.cpp | ||||
|         displayapp/screens/settings/SettingLocation.cpp | ||||
|         displayapp/screens/settings/SettingChimes.cpp | ||||
|         displayapp/screens/settings/SettingShakeThreshold.cpp | ||||
|         displayapp/screens/settings/SettingBluetooth.cpp | ||||
| @ -897,13 +903,25 @@ target_compile_options(littlefs PRIVATE | ||||
|         $<$<COMPILE_LANGUAGE:ASM>: ${ASM_FLAGS}> | ||||
|         ) | ||||
| 
 | ||||
| # SUNSET_SRC | ||||
| add_library(sunset STATIC ${SUNSET_SRC}) | ||||
| target_include_directories(sunset SYSTEM PUBLIC . ../) | ||||
| target_include_directories(sunset SYSTEM PUBLIC ${INCLUDES_FROM_LIBS}) | ||||
| target_compile_options(sunset PRIVATE | ||||
|         ${COMMON_FLAGS} | ||||
|         $<$<CONFIG:DEBUG>: ${DEBUG_FLAGS}> | ||||
|         $<$<CONFIG:RELEASE>: ${RELEASE_FLAGS}> | ||||
|         $<$<COMPILE_LANGUAGE:CXX>: ${CXX_FLAGS}> | ||||
|         $<$<COMPILE_LANGUAGE:ASM>: ${ASM_FLAGS}> | ||||
|         ) | ||||
| 
 | ||||
| # Build autonomous binary (without support for bootloader) | ||||
| set(EXECUTABLE_NAME "pinetime-app") | ||||
| set(EXECUTABLE_FILE_NAME ${EXECUTABLE_NAME}-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}) | ||||
| set(NRF5_LINKER_SCRIPT "${CMAKE_SOURCE_DIR}/gcc_nrf52.ld") | ||||
| add_executable(${EXECUTABLE_NAME} ${SOURCE_FILES}) | ||||
| set_target_properties(${EXECUTABLE_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_FILE_NAME}) | ||||
| target_link_libraries(${EXECUTABLE_NAME} nimble nrf-sdk lvgl littlefs infinitime_fonts infinitime_apps) | ||||
| target_link_libraries(${EXECUTABLE_NAME} nimble nrf-sdk lvgl littlefs sunset infinitime_fonts infinitime_apps) | ||||
| target_compile_options(${EXECUTABLE_NAME} PUBLIC | ||||
|         ${COMMON_FLAGS} | ||||
|         ${WARNING_FLAGS} | ||||
| @ -937,7 +955,7 @@ set(IMAGE_MCUBOOT_FILE_NAME_BIN ${EXECUTABLE_MCUBOOT_NAME}-image-${pinetime_VERS | ||||
| set(DFU_MCUBOOT_FILE_NAME ${EXECUTABLE_MCUBOOT_NAME}-dfu-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.zip) | ||||
| set(NRF5_LINKER_SCRIPT_MCUBOOT "${CMAKE_SOURCE_DIR}/gcc_nrf52-mcuboot.ld") | ||||
| add_executable(${EXECUTABLE_MCUBOOT_NAME} ${SOURCE_FILES}) | ||||
| target_link_libraries(${EXECUTABLE_MCUBOOT_NAME} nimble nrf-sdk lvgl littlefs infinitime_fonts infinitime_apps) | ||||
| target_link_libraries(${EXECUTABLE_MCUBOOT_NAME} nimble nrf-sdk lvgl littlefs sunset infinitime_fonts infinitime_apps) | ||||
| set_target_properties(${EXECUTABLE_MCUBOOT_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_MCUBOOT_FILE_NAME}) | ||||
| target_compile_options(${EXECUTABLE_MCUBOOT_NAME} PUBLIC | ||||
|         ${COMMON_FLAGS} | ||||
| @ -979,7 +997,7 @@ endif() | ||||
| set(EXECUTABLE_RECOVERY_NAME "pinetime-recovery") | ||||
| set(EXECUTABLE_RECOVERY_FILE_NAME ${EXECUTABLE_RECOVERY_NAME}-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}) | ||||
| add_executable(${EXECUTABLE_RECOVERY_NAME} ${RECOVERY_SOURCE_FILES}) | ||||
| target_link_libraries(${EXECUTABLE_RECOVERY_NAME} nimble nrf-sdk littlefs infinitime_fonts infinitime_apps) | ||||
| target_link_libraries(${EXECUTABLE_RECOVERY_NAME} nimble nrf-sdk littlefs sunset infinitime_fonts infinitime_apps) | ||||
| set_target_properties(${EXECUTABLE_RECOVERY_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_RECOVERY_FILE_NAME}) | ||||
| target_compile_definitions(${EXECUTABLE_RECOVERY_NAME} PUBLIC "PINETIME_IS_RECOVERY") | ||||
| target_compile_options(${EXECUTABLE_RECOVERY_NAME} PUBLIC | ||||
| @ -1011,7 +1029,7 @@ set(IMAGE_RECOVERY_MCUBOOT_FILE_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_NAME}-image-$ | ||||
| set(IMAGE_RECOVERY_MCUBOOT_FILE_NAME_HEX ${IMAGE_RECOVERY_MCUBOOT_FILE_NAME}.hex) | ||||
| set(DFU_RECOVERY_MCUBOOT_FILE_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_NAME}-dfu-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.zip) | ||||
| add_executable(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} ${RECOVERY_SOURCE_FILES}) | ||||
| target_link_libraries(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} nimble nrf-sdk littlefs infinitime_fonts infinitime_apps) | ||||
| target_link_libraries(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} nimble nrf-sdk littlefs sunset infinitime_fonts infinitime_apps) | ||||
| set_target_properties(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_FILE_NAME}) | ||||
| target_compile_definitions(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PUBLIC "PINETIME_IS_RECOVERY") | ||||
| target_compile_options(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PUBLIC | ||||
|  | ||||
| @ -50,6 +50,12 @@ namespace Pinetime { | ||||
|         int colorIndex = 0; | ||||
|       }; | ||||
| 
 | ||||
|       struct Location { | ||||
|         int16_t latitude; | ||||
|         int16_t longitude; | ||||
|         int8_t tzOffset; | ||||
|       }; | ||||
| 
 | ||||
|       Settings(Pinetime::Controllers::FS& fs); | ||||
| 
 | ||||
|       Settings(const Settings&) = delete; | ||||
| @ -275,6 +281,21 @@ namespace Pinetime { | ||||
|         return settings.stepsGoal; | ||||
|       }; | ||||
| 
 | ||||
|       void SetLocation(Location loc) { | ||||
|         if ( | ||||
|           loc.latitude != settings.location.latitude || | ||||
|           loc.longitude != settings.location.longitude || | ||||
|           loc.tzOffset != settings.location.tzOffset | ||||
|           ) { | ||||
|           settingsChanged = true; | ||||
|         } | ||||
|         settings.location = loc; | ||||
|       }; | ||||
| 
 | ||||
|       Location GetLocation() const { | ||||
|         return settings.location; | ||||
|       }; | ||||
| 
 | ||||
|       void SetBleRadioEnabled(bool enabled) { | ||||
|         bleRadioEnabled = enabled; | ||||
|       }; | ||||
| @ -308,6 +329,7 @@ namespace Pinetime { | ||||
|         uint16_t shakeWakeThreshold = 150; | ||||
| 
 | ||||
|         Controllers::BrightnessController::Levels brightLevel = Controllers::BrightnessController::Levels::Medium; | ||||
|         Location location = {(int16_t)0,(int16_t)0,(int8_t)0}; | ||||
|       }; | ||||
| 
 | ||||
|       SettingsData settings; | ||||
|  | ||||
| @ -44,6 +44,7 @@ | ||||
| #include "displayapp/screens/settings/SettingDisplay.h" | ||||
| #include "displayapp/screens/settings/SettingSteps.h" | ||||
| #include "displayapp/screens/settings/SettingSetDateTime.h" | ||||
| #include "displayapp/screens/settings/SettingLocation.h" | ||||
| #include "displayapp/screens/settings/SettingChimes.h" | ||||
| #include "displayapp/screens/settings/SettingShakeThreshold.h" | ||||
| #include "displayapp/screens/settings/SettingBluetooth.h" | ||||
| @ -514,6 +515,9 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio | ||||
|     case Apps::SettingSetDateTime: | ||||
|       currentScreen = std::make_unique<Screens::SettingSetDateTime>(this, dateTimeController, settingsController); | ||||
|       break; | ||||
|     case Apps::SettingLocation: | ||||
|       currentScreen = std::make_unique<Screens::SettingLocation>(settingsController); | ||||
|       break; | ||||
|     case Apps::SettingChimes: | ||||
|       currentScreen = std::make_unique<Screens::SettingChimes>(settingsController); | ||||
|       break; | ||||
|  | ||||
| @ -37,6 +37,7 @@ namespace Pinetime { | ||||
|       SettingWakeUp, | ||||
|       SettingSteps, | ||||
|       SettingSetDateTime, | ||||
|       SettingLocation, | ||||
|       SettingChimes, | ||||
|       SettingShakeThreshold, | ||||
|       SettingBluetooth, | ||||
|  | ||||
| @ -1,22 +1,27 @@ | ||||
| #include "displayapp/screens/WatchFaceAnalog.h" | ||||
| #include <cmath> | ||||
| #include <lvgl/lvgl.h> | ||||
| // #include <nrf_log.h>
 | ||||
| #include "displayapp/screens/BatteryIcon.h" | ||||
| #include "displayapp/screens/BleIcon.h" | ||||
| #include "displayapp/screens/Symbols.h" | ||||
| #include "displayapp/screens/NotificationIcon.h" | ||||
| #include "components/settings/Settings.h" | ||||
| #include "displayapp/InfiniTimeTheme.h" | ||||
| #include "sunset/src/sunset.h" | ||||
| 
 | ||||
| using namespace Pinetime::Applications::Screens; | ||||
| 
 | ||||
| namespace { | ||||
|   constexpr int16_t HourLength = 70; | ||||
|   int16_t HourLength = 70; | ||||
|   constexpr int16_t MinuteLength = 90; | ||||
|   constexpr int16_t SecondLength = 110; | ||||
|   constexpr int16_t SunDialVerticalOffset = 40; | ||||
| 
 | ||||
|   // sin(90) = 1 so the value of _lv_trigo_sin(90) is the scaling factor
 | ||||
|   const auto LV_TRIG_SCALE = _lv_trigo_sin(90); | ||||
|   const lv_color_t DARK_GRAY = lv_color_make(48, 48, 48); | ||||
|   const lv_color_t DARK_ORANGE = lv_color_make(48, 26, 0); | ||||
| 
 | ||||
|   int16_t Cosine(int16_t angle) { | ||||
|     return _lv_trigo_sin(angle + 90); | ||||
| @ -39,6 +44,15 @@ namespace { | ||||
|                        .y = CoordinateYRelocate(radius * static_cast<int32_t>(Cosine(angle)) / LV_TRIG_SCALE)}; | ||||
|   } | ||||
| 
 | ||||
|   int16_t CoordinateYRelocateSundial(int16_t y) { | ||||
|     return std::abs(y - SunDialVerticalOffset); | ||||
|   } | ||||
| 
 | ||||
|   lv_point_t CoordinateRelocateSundial(int16_t radius, int16_t angle) { | ||||
|     return lv_point_t {.x = CoordinateXRelocate(radius * static_cast<int32_t>(Sine(angle)) / LV_TRIG_SCALE), | ||||
|                        .y = CoordinateYRelocateSundial(radius * static_cast<int32_t>(Cosine(angle)) / LV_TRIG_SCALE)}; | ||||
|   } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| WatchFaceAnalog::WatchFaceAnalog(Controllers::DateTime& dateTimeController, | ||||
| @ -58,41 +72,68 @@ WatchFaceAnalog::WatchFaceAnalog(Controllers::DateTime& dateTimeController, | ||||
|   sMinute = 99; | ||||
|   sSecond = 99; | ||||
| 
 | ||||
|   minor_scales = lv_linemeter_create(lv_scr_act(), nullptr); | ||||
|   lv_linemeter_set_scale(minor_scales, 300, 51); | ||||
|   lv_linemeter_set_angle_offset(minor_scales, 180); | ||||
|   lv_obj_set_size(minor_scales, 240, 240); | ||||
|   lv_obj_align(minor_scales, nullptr, LV_ALIGN_CENTER, 0, 0); | ||||
|   lv_obj_set_style_local_bg_opa(minor_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP); | ||||
|   lv_obj_set_style_local_scale_width(minor_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 4); | ||||
|   lv_obj_set_style_local_scale_end_line_width(minor_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 1); | ||||
|   lv_obj_set_style_local_scale_end_color(minor_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY); | ||||
|   location = settingsController.GetLocation(); | ||||
| 
 | ||||
|   major_scales = lv_linemeter_create(lv_scr_act(), nullptr); | ||||
|   lv_linemeter_set_scale(major_scales, 300, 11); | ||||
|   lv_linemeter_set_angle_offset(major_scales, 180); | ||||
|   lv_obj_set_size(major_scales, 240, 240); | ||||
|   lv_obj_align(major_scales, nullptr, LV_ALIGN_CENTER, 0, 0); | ||||
|   lv_obj_set_style_local_bg_opa(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP); | ||||
|   lv_obj_set_style_local_scale_width(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 6); | ||||
|   lv_obj_set_style_local_scale_end_line_width(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 4); | ||||
|   lv_obj_set_style_local_scale_end_color(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); | ||||
|   // begin sundial watch face
 | ||||
|   if (settingsController.GetClockType() == Controllers::Settings::ClockType::Fuzzy) { | ||||
|     major_scales = lv_linemeter_create(lv_scr_act(), nullptr); | ||||
|     lv_linemeter_set_scale(major_scales, 165, 11); | ||||
|     lv_linemeter_set_angle_offset(major_scales, 180); | ||||
|     lv_obj_set_size(major_scales, 240, 240); | ||||
|     lv_obj_align(major_scales, nullptr, LV_ALIGN_IN_TOP_MID, 0, -LV_HOR_RES/2+SunDialVerticalOffset); | ||||
|     lv_obj_set_style_local_bg_opa(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP); | ||||
|     lv_obj_set_style_local_scale_width(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 40); | ||||
|     lv_obj_set_style_local_scale_end_line_width(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 1); | ||||
|     lv_obj_set_style_local_scale_end_color(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); | ||||
| 
 | ||||
|   large_scales = lv_linemeter_create(lv_scr_act(), nullptr); | ||||
|   lv_linemeter_set_scale(large_scales, 180, 3); | ||||
|   lv_linemeter_set_angle_offset(large_scales, 180); | ||||
|   lv_obj_set_size(large_scales, 240, 240); | ||||
|   lv_obj_align(large_scales, nullptr, LV_ALIGN_CENTER, 0, 0); | ||||
|   lv_obj_set_style_local_bg_opa(large_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP); | ||||
|   lv_obj_set_style_local_scale_width(large_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 20); | ||||
|   lv_obj_set_style_local_scale_end_line_width(large_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 4); | ||||
|   lv_obj_set_style_local_scale_end_color(large_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA); | ||||
|     one = lv_label_create(lv_scr_act(), NULL); | ||||
|     lv_label_set_align(one, LV_LABEL_ALIGN_LEFT); | ||||
|     lv_label_set_text(one, "I"); | ||||
|     lv_obj_align(one, NULL, LV_ALIGN_IN_TOP_LEFT, 20, SunDialVerticalOffset-20); | ||||
|     lv_obj_set_style_local_text_color(one, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); | ||||
| 
 | ||||
|   twelve = lv_label_create(lv_scr_act(), nullptr); | ||||
|   lv_label_set_align(twelve, LV_LABEL_ALIGN_CENTER); | ||||
|   lv_label_set_text_static(twelve, "12"); | ||||
|   lv_obj_set_pos(twelve, 110, 10); | ||||
|   lv_obj_set_style_local_text_color(twelve, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA); | ||||
|     twelve = lv_label_create(lv_scr_act(), NULL); | ||||
|     lv_label_set_align(twelve, LV_LABEL_ALIGN_RIGHT); | ||||
|     lv_label_set_text(twelve, "XII"); | ||||
|     lv_obj_align(twelve, NULL, LV_ALIGN_IN_TOP_RIGHT, -20, SunDialVerticalOffset-20); | ||||
|     lv_obj_set_style_local_text_color(twelve, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); | ||||
|   } else { | ||||
|     minor_scales = lv_linemeter_create(lv_scr_act(), nullptr); | ||||
|     lv_linemeter_set_scale(minor_scales, 300, 51); | ||||
|     lv_linemeter_set_angle_offset(minor_scales, 180); | ||||
|     lv_obj_set_size(minor_scales, 240, 240); | ||||
|     lv_obj_align(minor_scales, nullptr, LV_ALIGN_CENTER, 0, 0); | ||||
|     lv_obj_set_style_local_bg_opa(minor_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP); | ||||
|     lv_obj_set_style_local_scale_width(minor_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 4); | ||||
|     lv_obj_set_style_local_scale_end_line_width(minor_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 1); | ||||
|     lv_obj_set_style_local_scale_end_color(minor_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY); | ||||
| 
 | ||||
|     major_scales = lv_linemeter_create(lv_scr_act(), nullptr); | ||||
|     lv_linemeter_set_scale(major_scales, 300, 11); | ||||
|     lv_linemeter_set_angle_offset(major_scales, 180); | ||||
|     lv_obj_set_size(major_scales, 240, 240); | ||||
|     lv_obj_align(major_scales, nullptr, LV_ALIGN_CENTER, 0, 0); | ||||
|     lv_obj_set_style_local_bg_opa(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP); | ||||
|     lv_obj_set_style_local_scale_width(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 6); | ||||
|     lv_obj_set_style_local_scale_end_line_width(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 4); | ||||
|     lv_obj_set_style_local_scale_end_color(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); | ||||
| 
 | ||||
|     large_scales = lv_linemeter_create(lv_scr_act(), nullptr); | ||||
|     lv_linemeter_set_scale(large_scales, 180, 3); | ||||
|     lv_linemeter_set_angle_offset(large_scales, 180); | ||||
|     lv_obj_set_size(large_scales, 240, 240); | ||||
|     lv_obj_align(large_scales, nullptr, LV_ALIGN_CENTER, 0, 0); | ||||
|     lv_obj_set_style_local_bg_opa(large_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP); | ||||
|     lv_obj_set_style_local_scale_width(large_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 20); | ||||
|     lv_obj_set_style_local_scale_end_line_width(large_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 4); | ||||
|     lv_obj_set_style_local_scale_end_color(large_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA); | ||||
| 
 | ||||
|     twelve = lv_label_create(lv_scr_act(), nullptr); | ||||
|     lv_label_set_align(twelve, LV_LABEL_ALIGN_CENTER); | ||||
|     lv_label_set_text_static(twelve, "12"); | ||||
|     lv_obj_set_pos(twelve, 110, 10); | ||||
|     lv_obj_set_style_local_text_color(twelve, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA); | ||||
|   } | ||||
| 
 | ||||
|   batteryIcon.Create(lv_scr_act()); | ||||
|   lv_obj_align(batteryIcon.GetObject(), nullptr, LV_ALIGN_IN_TOP_RIGHT, 0, 0); | ||||
| @ -111,7 +152,6 @@ WatchFaceAnalog::WatchFaceAnalog(Controllers::DateTime& dateTimeController, | ||||
|   lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0); | ||||
| 
 | ||||
|   // Date - Day / Week day
 | ||||
| 
 | ||||
|   label_date_day = lv_label_create(lv_scr_act(), nullptr); | ||||
|   lv_obj_set_style_local_text_color(label_date_day, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::orange); | ||||
|   lv_label_set_text_fmt(label_date_day, "%s\n%02i", dateTimeController.DayOfWeekShortToString(), dateTimeController.Day()); | ||||
| @ -171,12 +211,78 @@ WatchFaceAnalog::~WatchFaceAnalog() { | ||||
|   lv_obj_clean(lv_scr_act()); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void WatchFaceAnalog::drawWatchFaceModeNight(){ | ||||
|   uint8_t hour = dateTimeController.Hours(); | ||||
|   uint8_t minute = dateTimeController.Minutes(); | ||||
| 
 | ||||
|   if (sHour != hour || sMinute != minute) { | ||||
|     // sun.setPosition(settings.lat.toFloat(), settings.lon.toFloat(), settings.gmtOffset / 3600);
 | ||||
|     sun.setPosition((float)location.latitude, (float)location.longitude, location.tzOffset); | ||||
| 
 | ||||
|     //from minutes past midnight
 | ||||
|     sun.setCurrentDate(dateTimeController.Year(), static_cast<uint8_t>(dateTimeController.Month())+1, dateTimeController.Day()); | ||||
|     sun.setTZOffset(location.tzOffset); | ||||
| 
 | ||||
|     minutesSunrise = sun.calcSunrise(); //360;
 | ||||
|     minutesSunset = sun.calcSunset(); //1080;
 | ||||
|     minutesDaytime = (minutesSunset - minutesSunrise); | ||||
|     minutesNighttime = (1440 - minutesDaytime); | ||||
| 
 | ||||
|     minutesBeforeSunset = minutesSunset - (hour * 60 + minute); // i.e.zero degrees
 | ||||
|     HourLength = 90; // sundial hand length
 | ||||
| 
 | ||||
|     int16_t hourAngle; | ||||
| 
 | ||||
|     if(minutesBeforeSunset > 0 && minutesBeforeSunset < minutesDaytime) { // day (after sunrise)
 | ||||
|       hourAngle = 180.0 * minutesBeforeSunset / minutesDaytime + 90; | ||||
|     } else { // night (before sunrise or after sunset)
 | ||||
|       lv_style_set_line_color(&hour_line_style, LV_STATE_DEFAULT, DARK_GRAY); | ||||
|       lv_style_set_line_color(&hour_line_style_trace, LV_STATE_DEFAULT, DARK_GRAY); | ||||
|       lv_obj_set_style_local_scale_end_color(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, DARK_GRAY); | ||||
|       lv_obj_set_style_local_text_color(label_date_day, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, DARK_ORANGE); | ||||
|       lv_obj_set_style_local_text_color(one, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, DARK_GRAY); | ||||
|       lv_obj_set_style_local_text_color(twelve, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, DARK_GRAY); | ||||
| 
 | ||||
|       if(minutesBeforeSunset > minutesDaytime) { // before sunrise
 | ||||
|         hourAngle = 180.0 * (minutesBeforeSunset - minutesDaytime) / minutesNighttime + 90; | ||||
|       } else { // after sunset
 | ||||
|         hourAngle = 180 + 180.0 * minutesBeforeSunset / minutesNighttime + 90; | ||||
|       } | ||||
|     } | ||||
|   /*NRF_LOG_INFO("a: %d, la: %f, lo: %f, ri: %d, se: %d, be: %d",
 | ||||
|     hourAngle, | ||||
|     (float)location.latitude, | ||||
|     (float)location.longitude, | ||||
|     minutesSunrise, | ||||
|     minutesSunset, | ||||
|     minutesBeforeSunset);*/ | ||||
| 
 | ||||
|     sHour = hour; | ||||
|     sMinute = minute; | ||||
| 
 | ||||
|     hour_point_trace[0] = CoordinateRelocateSundial(HourLength*.75, hourAngle); | ||||
|     hour_point_trace[1] = CoordinateRelocateSundial(HourLength, hourAngle); | ||||
| 
 | ||||
|     hour_point[0] = CoordinateRelocateSundial(0, hourAngle); | ||||
|     hour_point[1] = CoordinateRelocateSundial(HourLength*.75, hourAngle); | ||||
| 
 | ||||
|     lv_line_set_points(hour_body, hour_point, 2); | ||||
|     lv_line_set_points(hour_body_trace, hour_point_trace, 2); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void WatchFaceAnalog::UpdateClock() { | ||||
|   if (settingsController.GetClockType() == Controllers::Settings::ClockType::Fuzzy) { | ||||
|     drawWatchFaceModeNight(); | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   uint8_t hour = dateTimeController.Hours(); | ||||
|   uint8_t minute = dateTimeController.Minutes(); | ||||
|   uint8_t second = dateTimeController.Seconds(); | ||||
| 
 | ||||
|   if (sMinute != minute) { | ||||
|   if (minute>99 && sMinute != minute) { // disable
 | ||||
|     auto const angle = minute * 6; | ||||
|     minute_point[0] = CoordinateRelocate(30, angle); | ||||
|     minute_point[1] = CoordinateRelocate(MinuteLength, angle); | ||||
| @ -203,7 +309,8 @@ void WatchFaceAnalog::UpdateClock() { | ||||
|     lv_line_set_points(hour_body_trace, hour_point_trace, 2); | ||||
|   } | ||||
| 
 | ||||
|   if (sSecond != second) { | ||||
| 
 | ||||
|   if (second>99 && sSecond != second) { // disable
 | ||||
|     sSecond = second; | ||||
|     auto const angle = second * 6; | ||||
| 
 | ||||
| @ -258,7 +365,18 @@ void WatchFaceAnalog::Refresh() { | ||||
| 
 | ||||
|     currentDate = std::chrono::time_point_cast<days>(currentDateTime.Get()); | ||||
|     if (currentDate.IsUpdated()) { | ||||
|       lv_label_set_text_fmt(label_date_day, "%s\n%02i", dateTimeController.DayOfWeekShortToString(), dateTimeController.Day()); | ||||
|       if (settingsController.GetClockType() == Controllers::Settings::ClockType::Fuzzy) { | ||||
|         char const* MonthsString[] = {"--", "IANUARIUS","FEBRUARIUS","MARTIUS","APRILIS","MARTIUSIUNIUS","QUINTILIS","SEXTILIS","SEPTEMBER","OCTOBER","NOVEMBER","DECEMBER"}; | ||||
|         char const* DaysString[] = {"--", "LUNAE", "MARTIS", "MERCURII", "IOVIS", "VENERIS", "SATURNI", "SOLIS"}; | ||||
|         char const* RomanNumeralsString[] = {"--", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII"}; | ||||
|         lv_label_set_text_fmt(label_date_day, "%s\n%s %s", | ||||
|           DaysString[static_cast<uint8_t>(dateTimeController.DayOfWeek())], | ||||
|           RomanNumeralsString[static_cast<uint8_t>(dateTimeController.Day())], | ||||
|           MonthsString[static_cast<uint8_t>(dateTimeController.Month())]); | ||||
|         lv_obj_align(label_date_day, nullptr, LV_ALIGN_IN_BOTTOM_MID, 0, -20); | ||||
|       } else { | ||||
|         lv_label_set_text_fmt(label_date_day, "%s\n%02i", dateTimeController.DayOfWeekShortToString(), dateTimeController.Day()); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| } | ||||
| @ -11,6 +11,7 @@ | ||||
| #include "components/ble/NotificationManager.h" | ||||
| #include "displayapp/screens/BatteryIcon.h" | ||||
| #include "utility/DirtyValue.h" | ||||
| #include "sunset/src/sunset.h" | ||||
| 
 | ||||
| namespace Pinetime { | ||||
|   namespace Controllers { | ||||
| @ -49,6 +50,7 @@ namespace Pinetime { | ||||
|         lv_obj_t* minor_scales; | ||||
|         lv_obj_t* major_scales; | ||||
|         lv_obj_t* large_scales; | ||||
|         lv_obj_t* one; | ||||
|         lv_obj_t* twelve; | ||||
| 
 | ||||
|         lv_obj_t* hour_body; | ||||
| @ -76,12 +78,21 @@ namespace Pinetime { | ||||
| 
 | ||||
|         BatteryIcon batteryIcon; | ||||
| 
 | ||||
|         Controllers::Settings::Location location; | ||||
|         SunSet sun; | ||||
|         int16_t minutesSunrise; | ||||
|         int16_t minutesSunset; | ||||
|         int16_t minutesDaytime; | ||||
|         int16_t minutesNighttime; | ||||
|         int16_t minutesBeforeSunset; | ||||
| 
 | ||||
|         const Controllers::DateTime& dateTimeController; | ||||
|         const Controllers::Battery& batteryController; | ||||
|         const Controllers::Ble& bleController; | ||||
|         Controllers::NotificationManager& notificationManager; | ||||
|         Controllers::Settings& settingsController; | ||||
| 
 | ||||
|         void drawWatchFaceModeNight(); | ||||
|         void UpdateClock(); | ||||
|         void SetBatteryIcon(); | ||||
| 
 | ||||
|  | ||||
| @ -28,6 +28,8 @@ WatchFaceDigital::WatchFaceDigital(Controllers::DateTime& dateTimeController, | ||||
|     motionController {motionController}, | ||||
|     statusIcons(batteryController, bleController) { | ||||
| 
 | ||||
|   sHour = 99; | ||||
|   sMinute = 99; | ||||
|   statusIcons.Create(); | ||||
| 
 | ||||
|   notificationIcon = lv_label_create(lv_scr_act(), nullptr); | ||||
| @ -40,14 +42,18 @@ WatchFaceDigital::WatchFaceDigital(Controllers::DateTime& dateTimeController, | ||||
|   lv_obj_set_style_local_text_color(label_date, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x999999)); | ||||
| 
 | ||||
|   label_time = lv_label_create(lv_scr_act(), nullptr); | ||||
|   lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, 0, 0); | ||||
|   if (settingsController.GetClockType() == Controllers::Settings::ClockType::Fuzzy) { | ||||
|     lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); | ||||
|     lv_obj_set_style_local_text_font(label_time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); | ||||
|   } else if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) { | ||||
|     lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, 0, 0); | ||||
|     lv_obj_set_style_local_text_font(label_time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_extrabold_compressed); | ||||
|   } else { | ||||
|     lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); | ||||
|     lv_obj_set_style_local_text_font(label_time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_extrabold_compressed); | ||||
|   } | ||||
| 
 | ||||
|   lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, 0, 0); | ||||
| 
 | ||||
|   label_time_ampm = lv_label_create(lv_scr_act(), nullptr); | ||||
|   lv_label_set_text_static(label_time_ampm, ""); | ||||
|   lv_obj_align(label_time_ampm, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, -30, -55); | ||||
| @ -89,51 +95,63 @@ void WatchFaceDigital::Refresh() { | ||||
|     lv_label_set_text_static(notificationIcon, NotificationIcon::GetIcon(notificationState.Get())); | ||||
|   } | ||||
| 
 | ||||
|   currentDateTime = std::chrono::time_point_cast<std::chrono::minutes>(dateTimeController.CurrentDateTime()); | ||||
|   currentDateTime = dateTimeController.CurrentDateTime(); | ||||
| 
 | ||||
|   if (currentDateTime.IsUpdated()) { | ||||
| 
 | ||||
|     uint8_t hour = dateTimeController.Hours(); | ||||
|     uint8_t minute = dateTimeController.Minutes(); | ||||
| 
 | ||||
|     /* Begin difference from WatchFaceDigital*/ | ||||
|     if (settingsController.GetClockType() == Controllers::Settings::ClockType::Fuzzy) { | ||||
|       std::string hourStr, timeStr; | ||||
|       hour = hour % 12; // 12 becomes 0, 13 becomes 1
 | ||||
|       auto sector = minute / 15 + (minute % 15 > 7); | ||||
|       // advance the hour modulo 12 and reset the minutes if we're close to the top
 | ||||
|       // so we get "quarter to $hour+1" instead of needing "three quarters past $hour"
 | ||||
|       if (sector > 3) { | ||||
|         hour = (hour + 1) % 12; | ||||
|         sector = 0; | ||||
|       } | ||||
|     if (sHour != hour || sMinute != minute || forceRefresh == true) { | ||||
|       forceRefresh = false; | ||||
|       sHour = hour; | ||||
|       sMinute = minute; | ||||
| 
 | ||||
|       timeStr = timeSectors[sector]; | ||||
|       if (timeStr.find("%1") != std::string::npos) { | ||||
|         hour = (hour + 1) % 12; | ||||
|       } | ||||
|       //hourStr = std::string("#") + timeAccent + " " + hourNames[hour] + "#";
 | ||||
|       hourStr = hourNames[hour]; | ||||
|       timeStr.replace(timeStr.find("%"), 2, hourStr); | ||||
|       /* Begin difference from WatchFaceDigital*/ | ||||
|       if (settingsController.GetClockType() == Controllers::Settings::ClockType::Fuzzy) { | ||||
|         std::string hourStr, timeStr; | ||||
|         hour = hour % 12; // 12 becomes 0, 13 becomes 1
 | ||||
|         auto sector = minute / 15 + (minute % 15 > 7); | ||||
|         // advance the hour modulo 12 and reset the minutes if we're close to the top
 | ||||
|         // so we get "quarter to $hour+1" instead of needing "three quarters past $hour"
 | ||||
|         if (sector > 3) { | ||||
|           hour = (hour + 1) % 12; | ||||
|           sector = 0; | ||||
|         } | ||||
| 
 | ||||
|       lv_label_set_text(label_time, timeStr.c_str()); | ||||
|       lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); | ||||
|     /* End difference from WatchFaceDigital*/ | ||||
|     } else if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) { | ||||
|       char ampmChar[3] = "AM"; | ||||
|       if (hour == 0) { | ||||
|         hour = 12; | ||||
|       } else if (hour == 12) { | ||||
|         ampmChar[0] = 'P'; | ||||
|       } else if (hour > 12) { | ||||
|         hour = hour - 12; | ||||
|         ampmChar[0] = 'P'; | ||||
|         timeStr = timeSectors[sector]; | ||||
|         if (timeStr.find("%1") != std::string::npos) { | ||||
|           hour = (hour + 1) % 12; | ||||
|         } | ||||
|         //hourStr = std::string("#") + timeAccent + " " + hourNames[hour] + "#";
 | ||||
|         hourStr = hourNames[hour]; | ||||
|         timeStr.replace(timeStr.find("%"), 2, hourStr); | ||||
| 
 | ||||
|         lv_label_set_text(label_time_ampm, ""); | ||||
|         lv_label_set_text(label_time, timeStr.c_str()); | ||||
|         lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_CENTER, 0, -10); | ||||
|         lv_obj_set_style_local_text_font(label_time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); | ||||
|       /* End difference from WatchFaceDigital*/ | ||||
|       } else if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) { | ||||
|         char ampmChar[3] = "AM"; | ||||
|         if (hour == 0) { | ||||
|           hour = 12; | ||||
|         } else if (hour == 12) { | ||||
|           ampmChar[0] = 'P'; | ||||
|         } else if (hour > 12) { | ||||
|           hour = hour - 12; | ||||
|           ampmChar[0] = 'P'; | ||||
|         } | ||||
|         lv_label_set_text(label_time_ampm, ampmChar); | ||||
|         lv_label_set_text_fmt(label_time, "%2d:%02d", hour, minute); | ||||
|         lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, 0, 0); | ||||
|         lv_obj_set_style_local_text_font(label_time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_extrabold_compressed); | ||||
|       } else { | ||||
|         lv_label_set_text_fmt(label_time, "%02d:%02d", hour, minute); | ||||
|         lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); | ||||
|         lv_obj_set_style_local_text_font(label_time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_extrabold_compressed); | ||||
|       } | ||||
|       lv_label_set_text(label_time_ampm, ampmChar); | ||||
|       lv_label_set_text_fmt(label_time, "%2d:%02d", hour, minute); | ||||
|       lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, 0, 0); | ||||
|     } else { | ||||
|       lv_label_set_text_fmt(label_time, "%02d:%02d", hour, minute); | ||||
|       lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); | ||||
|       lv_obj_realign(label_time); | ||||
|     } | ||||
| 
 | ||||
|     currentDate = std::chrono::time_point_cast<days>(currentDateTime.Get()); | ||||
| @ -182,6 +200,22 @@ void WatchFaceDigital::Refresh() { | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| bool WatchFaceDigital::OnTouchEvent(Pinetime::Applications::TouchEvents event) { | ||||
|   if ((event == Pinetime::Applications::TouchEvents::LongTap)) { | ||||
|     Pinetime::Controllers::Settings::ClockType clockType = settingsController.GetClockType(); | ||||
|     if (clockType == Pinetime::Controllers::Settings::ClockType::Fuzzy) { | ||||
|       settingsController.SetClockType(Pinetime::Controllers::Settings::ClockType::H12); | ||||
|     } else { | ||||
|       settingsController.SetClockType(Pinetime::Controllers::Settings::ClockType::Fuzzy); | ||||
|     } | ||||
|     settingsController.SaveSettings(); | ||||
|     forceRefresh=true; | ||||
|     WatchFaceDigital::Refresh(); | ||||
|     return true; | ||||
|   } | ||||
|   return false; | ||||
| } | ||||
| 
 | ||||
| /* Inspired by XFCE4-panel's fuzzy clock.
 | ||||
|  * | ||||
|  *      https://salsa.debian.org/xfce-team/desktop/xfce4-panel/-/blob/debian/master/plugins/clock/clock-fuzzy.c
 | ||||
|  | ||||
| @ -35,9 +35,11 @@ namespace Pinetime { | ||||
|                          Controllers::MotionController& motionController); | ||||
|         ~WatchFaceDigital() override; | ||||
| 
 | ||||
|         bool OnTouchEvent(TouchEvents event) override; | ||||
|         void Refresh() override; | ||||
| 
 | ||||
|       private: | ||||
|         uint8_t sHour, sMinute; | ||||
|         uint8_t displayedHour = -1; | ||||
|         uint8_t displayedMinute = -1; | ||||
|         static const char* timeSectors[4]; | ||||
| @ -47,7 +49,7 @@ namespace Pinetime { | ||||
|         Utility::DirtyValue<bool> powerPresent {}; | ||||
|         Utility::DirtyValue<bool> bleState {}; | ||||
|         Utility::DirtyValue<bool> bleRadioEnabled {}; | ||||
|         Utility::DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::minutes>> currentDateTime {}; | ||||
|         Utility::DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>> currentDateTime; | ||||
|         Utility::DirtyValue<uint32_t> stepCount {}; | ||||
|         Utility::DirtyValue<uint8_t> heartbeat {}; | ||||
|         Utility::DirtyValue<bool> heartbeatRunning {}; | ||||
| @ -71,6 +73,7 @@ namespace Pinetime { | ||||
|         Controllers::MotionController& motionController; | ||||
| 
 | ||||
|         lv_task_t* taskRefresh; | ||||
|         bool forceRefresh=false; | ||||
|         Widgets::StatusIcons statusIcons; | ||||
|       }; | ||||
|     } | ||||
|  | ||||
							
								
								
									
										69
									
								
								src/displayapp/screens/settings/SettingLocation.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								src/displayapp/screens/settings/SettingLocation.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,69 @@ | ||||
| #include "displayapp/screens/settings/SettingLocation.h" | ||||
| #include <lvgl/lvgl.h> | ||||
| #include <nrf_log.h> | ||||
| #include "displayapp/DisplayApp.h" | ||||
| #include "displayapp/screens/Symbols.h" | ||||
| #include "components/settings/Settings.h" | ||||
| #include "displayapp/InfiniTimeTheme.h" | ||||
| 
 | ||||
| using namespace Pinetime::Applications::Screens; | ||||
| 
 | ||||
| namespace { | ||||
|   constexpr int16_t POS_Y_TEXT = 25; | ||||
| 
 | ||||
|   void ValueChangedHandler(void* userData) { | ||||
|     auto* screen = static_cast<SettingLocation*>(userData); | ||||
|     screen->UpdateScreen(); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| SettingLocation::SettingLocation(Pinetime::Controllers::Settings& settingsController) | ||||
|   : settingsController {settingsController} { | ||||
| 
 | ||||
|   lv_obj_t* title = lv_label_create(lv_scr_act(), nullptr); | ||||
|   lv_label_set_text_static(title, "Set location\n(lat/long/tz)"); | ||||
|   lv_label_set_align(title, LV_LABEL_ALIGN_CENTER); | ||||
|   lv_obj_align(title, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 15, 15); | ||||
| 
 | ||||
|   lv_obj_t* icon = lv_label_create(lv_scr_act(), nullptr); | ||||
|   lv_obj_set_style_local_text_color(icon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE); | ||||
|   lv_label_set_text_static(icon, Symbols::map); | ||||
|   lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER); | ||||
|   lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0); | ||||
| 
 | ||||
|   Controllers::Settings::Location loc = settingsController.GetLocation(); | ||||
| 
 | ||||
|   latCounter.Create(); | ||||
|   latCounter.SetWidth(80); | ||||
|   latCounter.SetValue(loc.latitude); | ||||
|   lv_obj_align(latCounter.GetObject(), nullptr, LV_ALIGN_CENTER, -90, POS_Y_TEXT); | ||||
|   latCounter.SetValueChangedEventCallback(this, ValueChangedHandler); | ||||
| 
 | ||||
|   longCounter.Create(); | ||||
|   longCounter.SetWidth(110); | ||||
|   longCounter.SetValue(loc.longitude); | ||||
|   lv_obj_align(longCounter.GetObject(), nullptr, LV_ALIGN_CENTER, -5, POS_Y_TEXT); | ||||
|   longCounter.SetValueChangedEventCallback(this, ValueChangedHandler); | ||||
| 
 | ||||
|   tzCounter.Create(); | ||||
|   tzCounter.SetWidth(60); | ||||
|   tzCounter.SetValue(loc.tzOffset); | ||||
|   lv_obj_align(tzCounter.GetObject(), nullptr, LV_ALIGN_CENTER, 75, POS_Y_TEXT); | ||||
|   tzCounter.SetValueChangedEventCallback(this, ValueChangedHandler); | ||||
| 
 | ||||
|   UpdateScreen(); | ||||
| } | ||||
| 
 | ||||
| SettingLocation::~SettingLocation() { | ||||
|   lv_obj_clean(lv_scr_act()); | ||||
|   settingsController.SaveSettings(); | ||||
| } | ||||
| 
 | ||||
| void SettingLocation::UpdateScreen() { | ||||
|   Controllers::Settings::Location loc = { | ||||
|     latitude: (int16_t)latCounter.GetValue(), | ||||
|     longitude: (int16_t)longCounter.GetValue(), | ||||
|     tzOffset: (int8_t)tzCounter.GetValue(), | ||||
|   }; | ||||
|   settingsController.SetLocation(loc); | ||||
| } | ||||
							
								
								
									
										31
									
								
								src/displayapp/screens/settings/SettingLocation.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/displayapp/screens/settings/SettingLocation.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <cstdint> | ||||
| #include <lvgl/lvgl.h> | ||||
| #include "components/datetime/DateTimeController.h" | ||||
| #include "components/settings/Settings.h" | ||||
| #include "displayapp/widgets/Counter.h" | ||||
| #include "displayapp/screens/Screen.h" | ||||
| #include "displayapp/widgets/DotIndicator.h" | ||||
| #include "displayapp/screens/settings/SettingSetDateTime.h" | ||||
| 
 | ||||
| namespace Pinetime { | ||||
|   namespace Applications { | ||||
|     namespace Screens { | ||||
|       class SettingLocation : public Screen { | ||||
|       public: | ||||
|         SettingLocation(Pinetime::Controllers::Settings& settingsController); | ||||
|         ~SettingLocation() override; | ||||
| 
 | ||||
|         void UpdateScreen(); | ||||
| 
 | ||||
|       private: | ||||
|         Controllers::Settings& settingsController; | ||||
| 
 | ||||
|         Widgets::Counter latCounter = Widgets::Counter(-90, 90, jetbrains_mono_42); | ||||
|         Widgets::Counter longCounter = Widgets::Counter(-180, 180, jetbrains_mono_42); | ||||
|         Widgets::Counter tzCounter = Widgets::Counter(-12, 12, jetbrains_mono_42); | ||||
|       }; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @ -39,6 +39,7 @@ namespace Pinetime { | ||||
| 
 | ||||
|           {Symbols::shoe, "Steps", Apps::SettingSteps}, | ||||
|           {Symbols::clock, "Date&Time", Apps::SettingSetDateTime}, | ||||
|           {Symbols::map, "Location", Apps::SettingLocation}, | ||||
|           {Symbols::cloudSunRain, "Weather", Apps::SettingWeatherFormat}, | ||||
|           {Symbols::batteryHalf, "Battery", Apps::BatteryInfo}, | ||||
| 
 | ||||
|  | ||||
| @ -136,8 +136,7 @@ void Counter::Create() { | ||||
| 
 | ||||
|   static constexpr uint8_t padding = 5; | ||||
|   const uint8_t width = std::max(lv_obj_get_width(number) + padding * 2, 58); | ||||
|   static constexpr uint8_t btnHeight = 50; | ||||
|   const uint8_t containerHeight = btnHeight * 2 + lv_obj_get_height(number) + padding * 2; | ||||
|   containerHeight = btnHeight * 2 + lv_obj_get_height(number) + padding * 2; | ||||
| 
 | ||||
|   lv_obj_set_size(counterContainer, width, containerHeight); | ||||
| 
 | ||||
|  | ||||
| @ -18,6 +18,15 @@ namespace Pinetime { | ||||
|         void EnableMonthMode(); | ||||
|         void SetMax(int newMax); | ||||
|         void SetValueChangedEventCallback(void* userData, void (*handler)(void* userData)); | ||||
|         void SetWidth(uint8_t width) { | ||||
|           lv_obj_set_size(counterContainer, width, containerHeight); | ||||
|           lv_obj_set_size(upBtn, width, btnHeight); | ||||
|           lv_obj_set_size(downBtn, width, btnHeight); | ||||
|           linePoints[0] = {0, 0}; | ||||
|           linePoints[1] = {width, 0}; | ||||
|           lv_line_set_points(upperLine, linePoints, 2); | ||||
|           lv_line_set_points(lowerLine, linePoints, 2); | ||||
|         } | ||||
| 
 | ||||
|         int GetValue() const { | ||||
|           return value; | ||||
| @ -42,6 +51,8 @@ namespace Pinetime { | ||||
|         int max; | ||||
|         int value; | ||||
|         const int leadingZeroCount; | ||||
|         uint8_t containerHeight; | ||||
|         static constexpr uint8_t btnHeight = 50; | ||||
|         bool twelveHourMode = false; | ||||
|         bool monthMode = false; | ||||
|         lv_font_t& font; | ||||
|  | ||||
							
								
								
									
										1
									
								
								src/libs/sunset
									
									
									
									
									
										Submodule
									
								
							
							
								
								
								
								
								
								
									
									
								
							
						
						
									
										1
									
								
								src/libs/sunset
									
									
									
									
									
										Submodule
									
								
							| @ -0,0 +1 @@ | ||||
| Subproject commit 4b08734eb8856154d7226bfdced91a571fb6a64b | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user