diff options
38 files changed, 685 insertions, 266 deletions
diff --git a/.devcontainer/build.sh b/.devcontainer/build.sh index 5dcdf91d..3d8aecbf 100644 --- a/.devcontainer/build.sh +++ b/.devcontainer/build.sh @@ -60,7 +60,6 @@ CmakeGenerate() { cmake -G "Unix Makefiles" \ -DCMAKE_BUILD_TYPE=$BUILD_TYPE \ - -DUSE_OPENOCD=1 \ -DARM_NONE_EABI_TOOLCHAIN_PATH="$TOOLS_DIR/$GCC_ARM_VER" \ -DNRF5_SDK_PATH="$TOOLS_DIR/$NRF_SDK_VER" \ "$SOURCES_DIR" diff --git a/CMakeLists.txt b/CMakeLists.txt index be8ef41f..75a6baa5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,28 +24,6 @@ if (NOT NRF5_SDK_PATH) message(FATAL_ERROR "The path to the NRF52 SDK must be specified on the command line (add -DNRF5_SDK_PATH=<path>") endif () -if(USE_JLINK) - if (NOT NRFJPROG) - message(FATAL_ERROR "the path to the tool nrfjprog must be specified on the command line (add -DNRFJPROG=<path>") - endif () -endif() - -if(USE_GDB_CLIENT) - if(NOT GDB_CLIENT_BIN_PATH) - set(GDB_CLIENT_BIN_PATH "arm-none-eabi-gdb") - endif() - - if(NOT GDB_CLIENT_TARGET_REMOTE) - message(FATAL_ERROR "The GDB target must be specified (add -DGDB_CLIENT_TARGET_REMOTE=<target>") - endif() -endif() - -if(USE_OPENOCD) - if(NOT OPENOCD_BIN_PATH) - set(OPENOCD_BIN_PATH "openocd") - endif() -endif() - if(DEFINED USE_DEBUG_PINS AND USE_DEBUG_PINS) add_definitions(-DUSE_DEBUG_PINS) endif() @@ -54,6 +32,10 @@ if(BUILD_DFU) set(BUILD_DFU true) endif() +if(BUILD_RESOURCES) + set(BUILD_RESOURCES true) +endif() + set(TARGET_DEVICE "PINETIME" CACHE STRING "Target device") set_property(CACHE TARGET_DEVICE PROPERTY STRINGS PINETIME MOY-TFK5 MOY-TIN5 MOY-TON5 MOY-UNK) @@ -77,17 +59,6 @@ message(" * Toolchain : " ${ARM_NONE_EABI_TOOLCHAIN_PATH}) message(" * GitRef(S) : " ${PROJECT_GIT_COMMIT_HASH}) message(" * NRF52 SDK : " ${NRF5_SDK_PATH}) message(" * Target device : " ${TARGET_DEVICE}) -set(PROGRAMMER "???") -if(USE_JLINK) - message(" * Programmer/debugger : JLINK") - message(" * NrfJprog : " ${NRFJPROG}) -elseif(USE_GDB_CLIENT) - message(" * Programmer/debugger : GDB Client") - message(" * GDB Client path : " ${GDB_CLIENT_BIN_PATH}) - message(" * GDB Target : " ${GDB_CLIENT_TARGET_REMOTE}) -elseif(USE_OPENOCD) - message(" * Programmer/debugger : OpenOCD Client") -endif() if(USE_DEBUG_PINS) message(" * Debug pins : Enabled") else() @@ -98,6 +69,11 @@ if(BUILD_DFU) else() message(" * Build DFU (using adafruit-nrfutil) : Disabled") endif() +if(BUILD_RESOURCES) + message(" * Build resources : Enabled") +else() + message(" * Build resources : Disabled") +endif() set(VERSION_EDIT_WARNING "// Do not edit this file, it is automatically generated by CMAKE!") configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/Version.h.in ${CMAKE_CURRENT_BINARY_DIR}/src/Version.h) diff --git a/cmake-nRF5x/CMake_nRF5x.cmake b/cmake-nRF5x/CMake_nRF5x.cmake index 9bf63f2a..95f1fdb6 100755 --- a/cmake-nRF5x/CMake_nRF5x.cmake +++ b/cmake-nRF5x/CMake_nRF5x.cmake @@ -229,24 +229,6 @@ macro(nRF5x_setup) "${NRF5_SDK_PATH}/modules/nrfx/drivers/src/nrfx_twi.c" ) - # adds target for erasing - if(USE_JLINK) - add_custom_target(FLASH_ERASE - COMMAND ${NRFJPROG} --eraseall -f ${NRF_TARGET} - COMMENT "erasing flashing" - ) - elseif(USE_GDB_CLIENT) - add_custom_target(FLASH_ERASE - COMMAND ${GDB_CLIENT_BIN_PATH} -nx --batch -ex 'target extended-remote ${GDB_CLIENT_TARGET_REMOTE}' -ex 'monitor swdp_scan' -ex 'attach 1' -ex 'mon erase_mass' - COMMENT "erasing flashing" - ) - elseif(USE_OPENOCD) - add_custom_target(FLASH_ERASE - COMMAND ${OPENOCD_BIN_PATH} -f interface/stlink.cfg -c 'transport select hla_swd' -f target/nrf52.cfg -c init -c halt -c 'nrf5 mass_erase' -c reset -c shutdown - COMMENT "erasing flashing" - ) - endif() - if(${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Darwin") set(TERMINAL "open") elseif(${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Windows") @@ -255,16 +237,6 @@ macro(nRF5x_setup) set(TERMINAL "gnome-terminal") endif() - if(USE_JLINK) - add_custom_target(START_JLINK - COMMAND ${TERMINAL} "${DIR_OF_nRF5x_CMAKE}/runJLinkGDBServer-${NRF_TARGET}" - COMMAND ${TERMINAL} "${DIR_OF_nRF5x_CMAKE}/runJLinkExe-${NRF_TARGET}" - COMMAND sleep 2s - COMMAND ${TERMINAL} "${DIR_OF_nRF5x_CMAKE}/runJLinkRTTClient" - COMMENT "started JLink commands" - ) - endif() - endmacro(nRF5x_setup) # adds a target for comiling and flashing an executable @@ -282,29 +254,6 @@ macro(nRF5x_addExecutable EXECUTABLE_NAME SOURCE_FILES) COMMAND ${CMAKE_OBJCOPY} -O ihex ${EXECUTABLE_NAME}.out "${EXECUTABLE_NAME}.hex" COMMENT "post build steps for ${EXECUTABLE_NAME}") - # custom target for flashing the board - if(USE_JLINK) - add_custom_target("FLASH_${EXECUTABLE_NAME}" - DEPENDS ${EXECUTABLE_NAME} - COMMAND ${NRFJPROG} --program ${EXECUTABLE_NAME}.hex -f ${NRF_TARGET} --sectorerase - COMMAND sleep 0.5s - COMMAND ${NRFJPROG} --reset -f ${NRF_TARGET} - COMMENT "flashing ${EXECUTABLE_NAME}.hex" - ) - elseif(USE_GDB_CLIENT) - add_custom_target("FLASH_${EXECUTABLE_NAME}" - DEPENDS ${EXECUTABLE_NAME} - COMMAND ${GDB_CLIENT_BIN_PATH} -nx --batch -ex 'target extended-remote ${GDB_CLIENT_TARGET_REMOTE}' -ex 'monitor swdp_scan' -ex 'attach 1' -ex 'load' -ex 'kill' ${EXECUTABLE_NAME}.hex - COMMENT "flashing ${EXECUTABLE_NAME}.hex" - ) - elseif(USE_OPENOCD) - add_custom_target("FLASH_${EXECUTABLE_NAME}" - DEPENDS ${EXECUTABLE_NAME} - COMMAND ${OPENOCD_BIN_PATH} -c "tcl_port disabled" -c "gdb_port 3333" -c "telnet_port 4444" -f interface/stlink.cfg -c 'transport select hla_swd' -f target/nrf52.cfg -c "program \"${EXECUTABLE_NAME}.hex\"" -c reset -c shutdown - COMMENT "flashing ${EXECUTABLE_NAME}.hex" - ) - endif() - endmacro() # adds app-level scheduler library diff --git a/doc/buildAndProgram.md b/doc/buildAndProgram.md index 58d0f72e..78bea1b4 100644 --- a/doc/buildAndProgram.md +++ b/doc/buildAndProgram.md @@ -40,12 +40,9 @@ CMake configures the project according to variables you specify the command line ----------|-------------|--------| **ARM_NONE_EABI_TOOLCHAIN_PATH**|path to the toolchain directory|`-DARM_NONE_EABI_TOOLCHAIN_PATH=/home/jf/nrf52/gcc-arm-none-eabi-10.3-2021.10/`| **NRF5_SDK_PATH**|path to the NRF52 SDK|`-DNRF5_SDK_PATH=/home/jf/nrf52/Pinetime/sdk`| -**USE_JLINK, USE_GDB_CLIENT and USE_OPENOCD**|Enable *JLink* mode, *GDB Client* (Black Magic Probe) mode or *OpenOCD* mode (set the one you want to use to `1`)|`-DUSE_JLINK=1` **CMAKE_BUILD_TYPE (\*)**| Build type (Release or Debug). Release is applied by default if this variable is not specified.|`-DCMAKE_BUILD_TYPE=Debug` -**NRFJPROG**|Path to the NRFJProg executable. Used only if `USE_JLINK` is 1.|`-DNRFJPROG=/opt/nrfjprog/nrfjprog` -**GDB_CLIENT_BIN_PATH**|Path to arm-none-eabi-gdb executable. Used only if `USE_GDB_CLIENT` is 1.|`-DGDB_CLIENT_BIN_PATH=/home/jf/nrf52/gcc-arm-none-eabi-9-2019-q4-major/bin/arm-none-eabi-gdb` -**GDB_CLIENT_TARGET_REMOTE**|Target remote connection string. Used only if `USE_GDB_CLIENT` is 1.|`-DGDB_CLIENT_TARGET_REMOTE=/dev/ttyACM0` **BUILD_DFU (\*\*)**|Build DFU files while building (needs [adafruit-nrfutil](https://github.com/adafruit/Adafruit_nRF52_nrfutil)).|`-DBUILD_DFU=1` +**BUILD_RESOURCES (\*\*)**| Generate external resource while building (needs [lv_font_conv](https://github.com/lvgl/lv_font_conv) and [lv_img_conv](https://github.com/lvgl/lv_img_conv). |`-DBUILD_RESOURCES=1` **TARGET_DEVICE**|Target device, used for hardware configuration. Allowed: `PINETIME, MOY-TFK5, MOY-TIN5, MOY-TON5, MOY-UNK`|`-DTARGET_DEVICE=PINETIME` (Default) #### (\*) Note about **CMAKE_BUILD_TYPE** @@ -56,30 +53,16 @@ The *Debug* mode disables all optimizations, which makes the code easier to debu #### (\*\*) Note about **BUILD_DFU** DFU files are the files you'll need to install your build of InfiniTime using OTA (over-the-air) mechanism. To generate the DFU file, the Python tool [adafruit-nrfutil](https://github.com/adafruit/Adafruit_nRF52_nrfutil) is needed on your system. Check that this tool is properly installed before enabling this option. -#### CMake command line for JLink +#### CMake command ``` -cmake -DARM_NONE_EABI_TOOLCHAIN_PATH=... -DNRF5_SDK_PATH=... -DUSE_JLINK=1 -DNRFJPROG=... ../ -``` - -#### CMake command line for GDB Client (Black Magic Probe) - -``` -cmake -DARM_NONE_EABI_TOOLCHAIN_PATH=... -DNRF5_SDK_PATH=... -DUSE_GDB_CLIENT=1 -DGDB_CLIENT_BIN_PATH=... -DGDB_CLIENT_TARGET_REMOTE=... ../ -``` - -#### CMake command line for OpenOCD - -``` -cmake -DARM_NONE_EABI_TOOLCHAIN_PATH=... -DNRF5_SDK_PATH=... -DUSE_OPENOCD=1 -DGDB_CLIENT_BIN_PATH=[optional] ../ +cmake -DARM_NONE_EABI_TOOLCHAIN_PATH=... -DNRF5_SDK_PATH=... ``` ### Build the project During the project generation, CMake created the following targets: -- **FLASH_ERASE** : mass erase the flash memory of the NRF52. -- **FLASH_pinetime-app** : flash the firmware into the NRF52. - **pinetime-app** : build the standalone (without bootloader support) version of the firmware. - **pinetime-recovery** : build the standalone recovery version of infinitime (light firmware that only supports OTA and basic UI) - **pinetime-recovery-loader** : build the standalone tool that flashes the recovery firmware into the external SPI flash @@ -107,24 +90,6 @@ Binary files are generated into the folder `src`: The same files are generated for **pinetime-recovery** and **pinetime-recoveryloader** -### Program and run - -#### Using CMake targets - -These target have been configured during the project generation by CMake according to the parameters you provided to the command line. - -Mass erase: - -``` -make FLASH_ERASE -``` - -Flash the application: - -``` -make FLASH_pinetime-app -``` - ### How to generate files needed by the factory These files are needed by the Pine64 factory to flash InfiniTime as the default firmware on the PineTimes. diff --git a/doc/code/Apps.md b/doc/code/Apps.md index c756a8b4..ad0f0403 100644 --- a/doc/code/Apps.md +++ b/doc/code/Apps.md @@ -99,7 +99,7 @@ Now, go to the function `DisplayApp::LoadApp` and add another case to the switch The case will be the id you gave your app earlier. If your app needs any additional arguments, this is the place to pass them. -If you want to add your app in the app launcher, add your app in [displayapp/screens/ApplicationList.cpp](/src/displayapp/screens/ApplicationList.cpp) to one of the `CreateScreen` functions, or add another `CreateScreen` function if there are no empty spaces for your app. If your app is a setting, do the same procedure in [displayapp/screens/settings/Settings.cpp](/src/displayapp/screens/settings/Settings.cpp). +If you want to add your app in the app launcher, add your app in [displayapp/screens/ApplicationList.h](/src/displayapp/screens/ApplicationList.h) to the array containing the applications and their corresponding symbol. If your app is a setting, do the same procedure in [displayapp/screens/settings/Settings.h](/src/displayapp/screens/settings/Settings.h). You should now be able to [build](../buildAndProgram.md) the firmware and flash it to your PineTime. Yay! diff --git a/docker/Dockerfile b/docker/Dockerfile index f2d187d0..927160db 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -22,6 +22,12 @@ RUN apt-get update -qq \ python3-dev \ git \ apt-utils \ + pkg-config \ + libpixman-1-dev \ + libcairo2-dev \ + libpango-1.0-0 \ + ibpango1.0-dev \ + libpangocairo-1.0-0 \ && curl -sL https://deb.nodesource.com/setup_18.x | bash - \ && apt-get install -y nodejs \ && rm -rf /var/cache/apt/* /var/lib/apt/lists/*; @@ -33,6 +39,10 @@ RUN pip3 install -Iv cryptography==3.3 RUN pip3 install cbor RUN npm i lv_font_conv@1.5.2 -g +RUN npm i ts-node@10.9.1 -g +RUN npm i @swc/core -g +RUN npm i lv_img_conv@0.3.0 -g + # build.sh knows how to compile COPY build.sh /opt/ diff --git a/docker/build.sh b/docker/build.sh index 663390c4..07e0d17e 100755 --- a/docker/build.sh +++ b/docker/build.sh @@ -11,6 +11,10 @@ export SOURCES_DIR="${SOURCES_DIR:=/sources}" export BUILD_DIR="${BUILD_DIR:=$SOURCES_DIR/build}" export OUTPUT_DIR="${OUTPUT_DIR:=$SOURCES_DIR/build/output}" +# Specify a folder with read/write access to NPM +export NPM_DIR="$BUILD_DIR/npm" +export npm_config_cache="${NPM_DIR}" + export BUILD_TYPE=${BUILD_TYPE:=Release} export GCC_ARM_VER=${GCC_ARM_VER:="10.3-2021.10"} export NRF_SDK_VER=${NRF_SDK_VER:="nRF5_SDK_15.3.0_59ac345"} @@ -59,10 +63,10 @@ CmakeGenerate() { -S "$SOURCES_DIR" \ -B "$BUILD_DIR" \ -DCMAKE_BUILD_TYPE=$BUILD_TYPE \ - -DUSE_OPENOCD=1 \ -DARM_NONE_EABI_TOOLCHAIN_PATH="$TOOLS_DIR/$GCC_ARM_PATH" \ -DNRF5_SDK_PATH="$TOOLS_DIR/$NRF_SDK_VER" \ - -DBUILD_DFU=1 + -DBUILD_DFU=1 \ + -DBUILD_RESOURCES=1 } CmakeBuild() { diff --git a/docker/post_build.sh.in b/docker/post_build.sh.in index 8c94471a..5d82f3be 100755 --- a/docker/post_build.sh.in +++ b/docker/post_build.sh.in @@ -15,6 +15,8 @@ cp "$BUILD_DIR/src/pinetime-mcuboot-app-dfu-$PROJECT_VERSION.zip" "$OUTPUT_DIR/p cp "$BUILD_DIR/src/pinetime-mcuboot-recovery-loader-image-$PROJECT_VERSION.bin" "$OUTPUT_DIR/pinetime-mcuboot-recovery-loader-image-$PROJECT_VERSION.bin" cp "$BUILD_DIR/src/pinetime-mcuboot-recovery-loader-dfu-$PROJECT_VERSION.zip" "$OUTPUT_DIR/pinetime-mcuboot-recovery-loader-dfu-$PROJECT_VERSION.zip" +cp "$BUILD_DIR/src/resources/infinitime-resources-$PROJECT_VERSION.zip" "$OUTPUT_DIR/infinitime-resources-$PROJECT_VERSION.zip" + mkdir -p "$OUTPUT_DIR/src" cp $BUILD_DIR/src/*.bin "$OUTPUT_DIR/src/" cp $BUILD_DIR/src/*.hex "$OUTPUT_DIR/src/" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index db4a8e2a..51390299 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -940,6 +940,10 @@ add_custom_command(TARGET ${EXECUTABLE_NAME} COMMAND ${CMAKE_OBJCOPY} -O ihex ${EXECUTABLE_FILE_NAME}.out "${EXECUTABLE_FILE_NAME}.hex" COMMENT "post build steps for ${EXECUTABLE_FILE_NAME}") +if(BUILD_RESOURCES) + add_dependencies(${EXECUTABLE_NAME} GenerateResources) +endif() + # Build binary intended to be used by bootloader set(EXECUTABLE_MCUBOOT_NAME "pinetime-mcuboot-app") set(EXECUTABLE_MCUBOOT_FILE_NAME ${EXECUTABLE_MCUBOOT_NAME}-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}) @@ -973,6 +977,10 @@ add_custom_command(TARGET ${EXECUTABLE_MCUBOOT_NAME} COMMENT "post build steps for ${EXECUTABLE_MCUBOOT_FILE_NAME}" ) +if(BUILD_RESOURCES) + add_dependencies(${EXECUTABLE_MCUBOOT_NAME} GenerateResources) +endif() + if(BUILD_DFU) add_custom_command(TARGET ${EXECUTABLE_MCUBOOT_NAME} POST_BUILD @@ -1127,68 +1135,7 @@ if(BUILD_DFU) ) endif() +if(BUILD_RESOURCES) + add_subdirectory(resources) +endif() -# FLASH -if (USE_JLINK) - add_custom_target(FLASH_ERASE - COMMAND ${NRFJPROG} --eraseall -f ${NRF_TARGET} - COMMENT "erasing flashing" - ) - add_custom_target("FLASH_${EXECUTABLE_NAME}" - DEPENDS ${EXECUTABLE_NAME} - COMMAND ${NRFJPROG} --program ${EXECUTABLE_FILE_NAME}.hex -f ${NRF_TARGET} --sectorerase - COMMAND sleep 0.5s - COMMAND ${NRFJPROG} --reset -f ${NRF_TARGET} - COMMENT "flashing ${EXECUTABLE_FILE_NAME}.hex" - ) - -elseif (USE_GDB_CLIENT) - add_custom_target(FLASH_ERASE - COMMAND ${GDB_CLIENT_BIN_PATH} -nx --batch -ex 'target extended-remote ${GDB_CLIENT_TARGET_REMOTE}' -ex 'monitor swdp_scan' -ex 'attach 1' -ex 'mon erase_mass' - COMMENT "erasing flashing" - ) - add_custom_target("FLASH_${EXECUTABLE_NAME}" - DEPENDS ${EXECUTABLE_NAME} - COMMAND ${GDB_CLIENT_BIN_PATH} -nx --batch -ex 'target extended-remote ${GDB_CLIENT_TARGET_REMOTE}' -ex 'monitor swdp_scan' -ex 'attach 1' -ex 'load' -ex 'kill' ${EXECUTABLE_FILE_NAME}.hex - COMMENT "flashing ${EXECUTABLE_FILE_NAME}.hex" - ) -elseif (USE_OPENOCD) - if (USE_CMSIS_DAP) - add_custom_target(FLASH_ERASE - COMMAND ${OPENOCD_BIN_PATH} -c 'source [find interface/cmsis-dap.cfg]' -c 'transport select swd' - -c 'source [find target/nrf52.cfg]' - -c 'init' - -c 'halt' - -c 'nrf5 mass_erase' - -c 'halt' - -c 'reset' - -c 'exit' - COMMENT "erasing flashing" - ) - add_custom_target("FLASH_${EXECUTABLE_NAME}" - DEPENDS ${EXECUTABLE_NAME} - COMMAND ${OPENOCD_BIN_PATH} - -c 'tcl_port disabled' - -c 'gdb_port 3333' - -c 'telnet_port 4444' - -c 'source [find interface/cmsis-dap.cfg]' - -c 'transport select swd' - -c 'source [find target/nrf52.cfg]' - -c 'halt' - -c "program \"${EXECUTABLE_FILE_NAME}.hex\"" - -c 'reset' - -c 'shutdown' - COMMENT "flashing ${EXECUTABLE_BIN_NAME}.hex" - ) - else () - add_custom_target(FLASH_ERASE - COMMAND ${OPENOCD_BIN_PATH} -f interface/stlink.cfg -c 'transport select hla_swd' -f target/nrf52.cfg -c init -c halt -c 'nrf5 mass_erase' -c reset -c shutdown - COMMENT "erasing flashing" - ) - add_custom_target("FLASH_${EXECUTABLE_NAME}" - DEPENDS ${EXECUTABLE_NAME} - COMMAND ${OPENOCD_BIN_PATH} -c "tcl_port disabled" -c "gdb_port 3333" -c "telnet_port 4444" -f interface/stlink.cfg -c 'transport select hla_swd' -f target/nrf52.cfg -c "program \"${EXECUTABLE_FILE_NAME}.hex\"" -c reset -c shutdown - COMMENT "flashing ${EXECUTABLE_FILE_NAME}.hex" - ) - endif () -endif () diff --git a/src/components/settings/Settings.h b/src/components/settings/Settings.h index 478408f6..1262eb88 100644 --- a/src/components/settings/Settings.h +++ b/src/components/settings/Settings.h @@ -34,7 +34,8 @@ namespace Pinetime { Navy, Magenta, Purple, - Orange + Orange, + Pink }; struct PineTimeStyle { Colors ColorTime = Colors::Teal; diff --git a/src/displayapp/Colors.cpp b/src/displayapp/Colors.cpp index 106c5163..2e9790eb 100644 --- a/src/displayapp/Colors.cpp +++ b/src/displayapp/Colors.cpp @@ -39,6 +39,8 @@ lv_color_t Pinetime::Applications::Convert(Pinetime::Controllers::Settings::Colo return LV_COLOR_MAKE(0xb0, 0x0, 0xb0); case Pinetime::Controllers::Settings::Colors::Orange: return LV_COLOR_ORANGE; + case Pinetime::Controllers::Settings::Colors::Pink: + return LV_COLOR_MAKE(0xFF, 0xAE, 0xC9); default: return LV_COLOR_WHITE; } diff --git a/src/displayapp/screens/Error.cpp b/src/displayapp/screens/Error.cpp index 1f2c61d6..74f222a9 100644 --- a/src/displayapp/screens/Error.cpp +++ b/src/displayapp/screens/Error.cpp @@ -36,7 +36,8 @@ Error::Error(Pinetime::Applications::DisplayApp* app, System::BootErrors error) lv_obj_set_event_cb(btnOk, ButtonEventCallback); lv_obj_set_size(btnOk, LV_HOR_RES, 50); lv_obj_align(btnOk, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, 0); - lv_obj_set_style_local_value_str(btnOk, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "Proceed"); + lv_obj_t* lblOk = lv_label_create(btnOk, nullptr); + lv_label_set_text_static(lblOk, "Proceed"); lv_obj_set_style_local_bg_color(btnOk, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE); } diff --git a/src/displayapp/screens/Metronome.cpp b/src/displayapp/screens/Metronome.cpp index 174ac1b6..df87092b 100644 --- a/src/displayapp/screens/Metronome.cpp +++ b/src/displayapp/screens/Metronome.cpp @@ -64,7 +64,8 @@ Metronome::Metronome(DisplayApp* app, Controllers::MotorController& motorControl lv_obj_set_event_cb(playPause, eventHandler); lv_obj_set_size(playPause, 115, 50); lv_obj_align(playPause, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); - lv_obj_set_style_local_value_str(playPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Symbols::play); + lblPlayPause = lv_label_create(playPause, nullptr); + lv_label_set_text_static(lblPlayPause, Symbols::play); taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this); } @@ -126,12 +127,12 @@ void Metronome::OnEvent(lv_obj_t* obj, lv_event_t event) { if (obj == playPause) { metronomeStarted = !metronomeStarted; if (metronomeStarted) { - lv_obj_set_style_local_value_str(playPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Symbols::pause); + lv_label_set_text_static(lblPlayPause, Symbols::pause); systemTask.PushMessage(System::Messages::DisableSleeping); startTime = xTaskGetTickCount(); counter = 1; } else { - lv_obj_set_style_local_value_str(playPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Symbols::play); + lv_label_set_text_static(lblPlayPause, Symbols::play); systemTask.PushMessage(System::Messages::EnableSleeping); } } diff --git a/src/displayapp/screens/Metronome.h b/src/displayapp/screens/Metronome.h index 8933b17e..c062959c 100644 --- a/src/displayapp/screens/Metronome.h +++ b/src/displayapp/screens/Metronome.h @@ -31,6 +31,7 @@ namespace Pinetime { lv_obj_t *bpmArc, *bpmTap, *bpmValue; lv_obj_t *bpbDropdown, *currentBpbText; lv_obj_t* playPause; + lv_obj_t* lblPlayPause; lv_task_t* taskRefresh; }; diff --git a/src/displayapp/screens/Twos.cpp b/src/displayapp/screens/Twos.cpp index 5d1f4980..9e7418c8 100644 --- a/src/displayapp/screens/Twos.cpp +++ b/src/displayapp/screens/Twos.cpp @@ -7,53 +7,34 @@ using namespace Pinetime::Applications::Screens; Twos::Twos(Pinetime::Applications::DisplayApp* app) : Screen(app) { - // create styles to apply to different valued tiles - lv_style_init(&style_cell1); - lv_style_init(&style_cell2); - lv_style_init(&style_cell3); - lv_style_init(&style_cell4); - lv_style_init(&style_cell5); + struct colorPair { + lv_color_t bg; + lv_color_t fg; + }; - lv_style_set_border_color(&style_cell1, LV_STATE_DEFAULT, lv_color_hex(0xbbada0)); - lv_style_set_border_width(&style_cell1, LV_STATE_DEFAULT, 3); - lv_style_set_bg_opa(&style_cell1, LV_STATE_DEFAULT, LV_OPA_COVER); - lv_style_set_bg_color(&style_cell1, LV_STATE_DEFAULT, lv_color_hex(0xcdc0b4)); - lv_style_set_pad_top(&style_cell1, LV_STATE_DEFAULT, 29); - lv_style_set_text_color(&style_cell1, LV_STATE_DEFAULT, LV_COLOR_BLACK); + static constexpr colorPair colors[nColors] = { + {LV_COLOR_MAKE(0xcd, 0xc0, 0xb4), LV_COLOR_BLACK}, + {LV_COLOR_MAKE(0xef, 0xdf, 0xc6), LV_COLOR_BLACK}, + {LV_COLOR_MAKE(0xef, 0x92, 0x63), LV_COLOR_WHITE}, + {LV_COLOR_MAKE(0xf7, 0x61, 0x42), LV_COLOR_WHITE}, + {LV_COLOR_MAKE(0x00, 0x7d, 0xc5), LV_COLOR_WHITE}, + }; - lv_style_set_border_color(&style_cell2, LV_STATE_DEFAULT, lv_color_hex(0xbbada0)); - lv_style_set_border_width(&style_cell2, LV_STATE_DEFAULT, 3); - lv_style_set_bg_opa(&style_cell2, LV_STATE_DEFAULT, LV_OPA_COVER); - lv_style_set_bg_color(&style_cell2, LV_STATE_DEFAULT, lv_color_hex(0xefdfc6)); - lv_style_set_pad_top(&style_cell2, LV_STATE_DEFAULT, 29); - lv_style_set_text_color(&style_cell2, LV_STATE_DEFAULT, LV_COLOR_BLACK); - - lv_style_set_border_color(&style_cell3, LV_STATE_DEFAULT, lv_color_hex(0xbbada0)); - lv_style_set_border_width(&style_cell3, LV_STATE_DEFAULT, 3); - lv_style_set_bg_opa(&style_cell3, LV_STATE_DEFAULT, LV_OPA_COVER); - lv_style_set_bg_color(&style_cell3, LV_STATE_DEFAULT, lv_color_hex(0xef9263)); - lv_style_set_pad_top(&style_cell3, LV_STATE_DEFAULT, 29); + gridDisplay = lv_table_create(lv_scr_act(), nullptr); - lv_style_set_border_color(&style_cell4, LV_STATE_DEFAULT, lv_color_hex(0xbbada0)); - lv_style_set_border_width(&style_cell4, LV_STATE_DEFAULT, 3); - lv_style_set_bg_opa(&style_cell4, LV_STATE_DEFAULT, LV_OPA_COVER); - lv_style_set_bg_color(&style_cell4, LV_STATE_DEFAULT, lv_color_hex(0xf76142)); - lv_style_set_pad_top(&style_cell4, LV_STATE_DEFAULT, 29); + for (size_t i = 0; i < nColors; i++) { + lv_style_init(&cellStyles[i]); - lv_style_set_border_color(&style_cell5, LV_STATE_DEFAULT, lv_color_hex(0xbbada0)); - lv_style_set_border_width(&style_cell5, LV_STATE_DEFAULT, 3); - lv_style_set_bg_opa(&style_cell5, LV_STATE_DEFAULT, LV_OPA_COVER); - lv_style_set_bg_color(&style_cell5, LV_STATE_DEFAULT, lv_color_hex(0x007dc5)); - lv_style_set_pad_top(&style_cell5, LV_STATE_DEFAULT, 29); + lv_style_set_border_color(&cellStyles[i], LV_STATE_DEFAULT, lv_color_hex(0xbbada0)); + lv_style_set_border_width(&cellStyles[i], LV_STATE_DEFAULT, 3); + lv_style_set_bg_opa(&cellStyles[i], LV_STATE_DEFAULT, LV_OPA_COVER); + lv_style_set_bg_color(&cellStyles[i], LV_STATE_DEFAULT, colors[i].bg); + lv_style_set_pad_top(&cellStyles[i], LV_STATE_DEFAULT, 29); + lv_style_set_text_color(&cellStyles[i], LV_STATE_DEFAULT, colors[i].fg); - // format grid display + lv_obj_add_style(gridDisplay, LV_TABLE_PART_CELL1 + i, &cellStyles[i]); + } - gridDisplay = lv_table_create(lv_scr_act(), nullptr); - lv_obj_add_style(gridDisplay, LV_TABLE_PART_CELL1, &style_cell1); - lv_obj_add_style(gridDisplay, LV_TABLE_PART_CELL2, &style_cell2); - lv_obj_add_style(gridDisplay, LV_TABLE_PART_CELL3, &style_cell3); - lv_obj_add_style(gridDisplay, LV_TABLE_PART_CELL4, &style_cell4); - lv_obj_add_style(gridDisplay, LV_TABLE_PART_CELL4 + 1, &style_cell5); lv_table_set_col_cnt(gridDisplay, nCols); lv_table_set_row_cnt(gridDisplay, nRows); for (int col = 0; col < nCols; col++) { @@ -83,11 +64,9 @@ Twos::Twos(Pinetime::Applications::DisplayApp* app) : Screen(app) { } Twos::~Twos() { - lv_style_reset(&style_cell1); - lv_style_reset(&style_cell2); - lv_style_reset(&style_cell3); - lv_style_reset(&style_cell4); - lv_style_reset(&style_cell5); + for (lv_style_t cellStyle : cellStyles) { + lv_style_reset(&cellStyle); + } lv_obj_clean(lv_scr_act()); } diff --git a/src/displayapp/screens/Twos.h b/src/displayapp/screens/Twos.h index 4a6ada0b..da935724 100644 --- a/src/displayapp/screens/Twos.h +++ b/src/displayapp/screens/Twos.h @@ -18,11 +18,8 @@ namespace Pinetime { bool OnTouchEvent(TouchEvents event) override; private: - lv_style_t style_cell1; - lv_style_t style_cell2; - lv_style_t style_cell3; - lv_style_t style_cell4; - lv_style_t style_cell5; + static constexpr int nColors = 5; + lv_style_t cellStyles[nColors]; lv_obj_t* scoreText; lv_obj_t* gridDisplay; diff --git a/src/displayapp/screens/WatchFaceAnalog.cpp b/src/displayapp/screens/WatchFaceAnalog.cpp index 5ebb3304..5e5317ee 100644 --- a/src/displayapp/screens/WatchFaceAnalog.cpp +++ b/src/displayapp/screens/WatchFaceAnalog.cpp @@ -70,7 +70,6 @@ WatchFaceAnalog::WatchFaceAnalog(Pinetime::Applications::DisplayApp* app, plugIcon = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(plugIcon, Symbols::plug); - lv_obj_set_style_local_text_color(plugIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED); lv_obj_align(plugIcon, nullptr, LV_ALIGN_IN_TOP_RIGHT, 0, 0); notificationIcon = lv_label_create(lv_scr_act(), NULL); diff --git a/src/displayapp/screens/WatchFacePineTimeStyle.cpp b/src/displayapp/screens/WatchFacePineTimeStyle.cpp index ed09f5dd..002ac887 100644 --- a/src/displayapp/screens/WatchFacePineTimeStyle.cpp +++ b/src/displayapp/screens/WatchFacePineTimeStyle.cpp @@ -196,7 +196,8 @@ WatchFacePineTimeStyle::WatchFacePineTimeStyle(DisplayApp* app, lv_obj_set_size(btnNextTime, 60, 60); lv_obj_align(btnNextTime, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, -15, -80); lv_obj_set_style_local_bg_opa(btnNextTime, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50); - lv_obj_set_style_local_value_str(btnNextTime, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, ">"); + lv_obj_t* lblNextTime = lv_label_create(btnNextTime, nullptr); + lv_label_set_text_static(lblNextTime, ">"); lv_obj_set_event_cb(btnNextTime, event_handler); lv_obj_set_hidden(btnNextTime, true); @@ -205,7 +206,8 @@ WatchFacePineTimeStyle::WatchFacePineTimeStyle(DisplayApp* app, lv_obj_set_size(btnPrevTime, 60, 60); lv_obj_align(btnPrevTime, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 15, -80); lv_obj_set_style_local_bg_opa(btnPrevTime, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50); - lv_obj_set_style_local_value_str(btnPrevTime, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "<"); + lv_obj_t* lblPrevTime = lv_label_create(btnPrevTime, nullptr); + lv_label_set_text_static(lblPrevTime, "<"); lv_obj_set_event_cb(btnPrevTime, event_handler); lv_obj_set_hidden(btnPrevTime, true); @@ -214,7 +216,8 @@ WatchFacePineTimeStyle::WatchFacePineTimeStyle(DisplayApp* app, lv_obj_set_size(btnNextBar, 60, 60); lv_obj_align(btnNextBar, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, -15, 0); lv_obj_set_style_local_bg_opa(btnNextBar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50); - lv_obj_set_style_local_value_str(btnNextBar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, ">"); + lv_obj_t* lblNextBar = lv_label_create(btnNextBar, nullptr); + lv_label_set_text_static(lblNextBar, ">"); lv_obj_set_event_cb(btnNextBar, event_handler); lv_obj_set_hidden(btnNextBar, true); @@ -223,7 +226,8 @@ WatchFacePineTimeStyle::WatchFacePineTimeStyle(DisplayApp* app, lv_obj_set_size(btnPrevBar, 60, 60); lv_obj_align(btnPrevBar, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 15, 0); lv_obj_set_style_local_bg_opa(btnPrevBar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50); - lv_obj_set_style_local_value_str(btnPrevBar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "<"); + lv_obj_t* lblPrevBar = lv_label_create(btnPrevBar, nullptr); + lv_label_set_text_static(lblPrevBar, "<"); lv_obj_set_event_cb(btnPrevBar, event_handler); lv_obj_set_hidden(btnPrevBar, true); @@ -232,7 +236,8 @@ WatchFacePineTimeStyle::WatchFacePineTimeStyle(DisplayApp* app, lv_obj_set_size(btnNextBG, 60, 60); lv_obj_align(btnNextBG, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, -15, 80); lv_obj_set_style_local_bg_opa(btnNextBG, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50); - lv_obj_set_style_local_value_str(btnNextBG, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, ">"); + lv_obj_t* lblNextBG = lv_label_create(btnNextBG, nullptr); + lv_label_set_text_static(lblNextBG, ">"); lv_obj_set_event_cb(btnNextBG, event_handler); lv_obj_set_hidden(btnNextBG, true); @@ -241,7 +246,8 @@ WatchFacePineTimeStyle::WatchFacePineTimeStyle(DisplayApp* app, lv_obj_set_size(btnPrevBG, 60, 60); lv_obj_align(btnPrevBG, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 15, 80); lv_obj_set_style_local_bg_opa(btnPrevBG, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50); - lv_obj_set_style_local_value_str(btnPrevBG, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "<"); + lv_obj_t* lblPrevBG = lv_label_create(btnPrevBG, nullptr); + lv_label_set_text_static(lblPrevBG, "<"); lv_obj_set_event_cb(btnPrevBG, event_handler); lv_obj_set_hidden(btnPrevBG, true); @@ -250,7 +256,8 @@ WatchFacePineTimeStyle::WatchFacePineTimeStyle(DisplayApp* app, lv_obj_set_size(btnReset, 60, 60); lv_obj_align(btnReset, lv_scr_act(), LV_ALIGN_CENTER, 0, 80); lv_obj_set_style_local_bg_opa(btnReset, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50); - lv_obj_set_style_local_value_str(btnReset, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "Rst"); + lv_obj_t* lblReset = lv_label_create(btnReset, nullptr); + lv_label_set_text_static(lblReset, "Rst"); lv_obj_set_event_cb(btnReset, event_handler); lv_obj_set_hidden(btnReset, true); @@ -259,7 +266,8 @@ WatchFacePineTimeStyle::WatchFacePineTimeStyle(DisplayApp* app, lv_obj_set_size(btnRandom, 60, 60); lv_obj_align(btnRandom, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); lv_obj_set_style_local_bg_opa(btnRandom, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50); - lv_obj_set_style_local_value_str(btnRandom, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "Rnd"); + lv_obj_t* lblRandom = lv_label_create(btnRandom, nullptr); + lv_label_set_text_static(lblRandom, "Rnd"); lv_obj_set_event_cb(btnRandom, event_handler); lv_obj_set_hidden(btnRandom, true); @@ -268,7 +276,8 @@ WatchFacePineTimeStyle::WatchFacePineTimeStyle(DisplayApp* app, lv_obj_set_size(btnClose, 60, 60); lv_obj_align(btnClose, lv_scr_act(), LV_ALIGN_CENTER, 0, -80); lv_obj_set_style_local_bg_opa(btnClose, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50); - lv_obj_set_style_local_value_str(btnClose, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "X"); + lv_obj_t* lblClose = lv_label_create(btnClose, nullptr); + lv_label_set_text_static(lblClose, "X"); lv_obj_set_event_cb(btnClose, event_handler); lv_obj_set_hidden(btnClose, true); @@ -570,7 +579,7 @@ void WatchFacePineTimeStyle::UpdateSelected(lv_obj_t* object, lv_event_t event) Pinetime::Controllers::Settings::Colors WatchFacePineTimeStyle::GetNext(Pinetime::Controllers::Settings::Colors color) { auto colorAsInt = static_cast<uint8_t>(color); Pinetime::Controllers::Settings::Colors nextColor; - if (colorAsInt < 16) { + if (colorAsInt < 17) { nextColor = static_cast<Controllers::Settings::Colors>(colorAsInt + 1); } else { nextColor = static_cast<Controllers::Settings::Colors>(0); @@ -585,7 +594,7 @@ Pinetime::Controllers::Settings::Colors WatchFacePineTimeStyle::GetPrevious(Pine if (colorAsInt > 0) { prevColor = static_cast<Controllers::Settings::Colors>(colorAsInt - 1); } else { - prevColor = static_cast<Controllers::Settings::Colors>(16); + prevColor = static_cast<Controllers::Settings::Colors>(17); } return prevColor; } diff --git a/src/displayapp/screens/settings/SettingSetDate.cpp b/src/displayapp/screens/settings/SettingSetDate.cpp index 1407a98f..421aef02 100644 --- a/src/displayapp/screens/settings/SettingSetDate.cpp +++ b/src/displayapp/screens/settings/SettingSetDate.cpp @@ -79,9 +79,11 @@ SettingSetDate::SettingSetDate(Pinetime::Applications::DisplayApp* app, Pinetime lv_obj_set_size(btnSetTime, 120, 48); lv_obj_align(btnSetTime, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, 0); lv_obj_set_style_local_bg_color(btnSetTime, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0x38, 0x38, 0x38)); - lv_obj_set_style_local_value_str(btnSetTime, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "Set"); + lblSetTime = lv_label_create(btnSetTime, nullptr); + lv_label_set_text_static(lblSetTime, "Set"); lv_obj_set_event_cb(btnSetTime, event_handler); lv_btn_set_state(btnSetTime, LV_BTN_STATE_DISABLED); + lv_obj_set_state(lblSetTime, LV_STATE_DISABLED); } SettingSetDate::~SettingSetDate() { @@ -102,10 +104,12 @@ void SettingSetDate::HandleButtonPress() { dateTimeController.Seconds(), nrf_rtc_counter_get(portNRF_RTC_REG)); lv_btn_set_state(btnSetTime, LV_BTN_STATE_DISABLED); + lv_obj_set_state(lblSetTime, LV_STATE_DISABLED); } void SettingSetDate::CheckDay() { const int maxDay = MaximumDayOfMonth(monthCounter.GetValue(), yearCounter.GetValue()); dayCounter.SetMax(maxDay); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); + lv_obj_set_state(lblSetTime, LV_STATE_DEFAULT); } diff --git a/src/displayapp/screens/settings/SettingSetDate.h b/src/displayapp/screens/settings/SettingSetDate.h index af0d654e..a0ffc683 100644 --- a/src/displayapp/screens/settings/SettingSetDate.h +++ b/src/displayapp/screens/settings/SettingSetDate.h @@ -21,6 +21,7 @@ namespace Pinetime { Controllers::DateTime& dateTimeController; lv_obj_t* btnSetTime; + lv_obj_t* lblSetTime; Widgets::Counter dayCounter = Widgets::Counter(1, 31, jetbrains_mono_bold_20); Widgets::Counter monthCounter = Widgets::Counter(1, 12, jetbrains_mono_bold_20); diff --git a/src/displayapp/screens/settings/SettingSetTime.cpp b/src/displayapp/screens/settings/SettingSetTime.cpp index 47b786e4..e7d824fd 100644 --- a/src/displayapp/screens/settings/SettingSetTime.cpp +++ b/src/displayapp/screens/settings/SettingSetTime.cpp @@ -67,13 +67,15 @@ SettingSetTime::SettingSetTime(Pinetime::Applications::DisplayApp* app, btnSetTime->user_data = this; lv_obj_set_size(btnSetTime, 120, 50); lv_obj_align(btnSetTime, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, 0); - lv_obj_set_style_local_value_str(btnSetTime, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "Set"); + lblSetTime = lv_label_create(btnSetTime, nullptr); + lv_label_set_text_static(lblSetTime, "Set"); lv_obj_set_style_local_bg_color(btnSetTime, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); - lv_obj_set_style_local_value_color(btnSetTime, LV_BTN_PART_MAIN, LV_STATE_DISABLED, LV_COLOR_GRAY); + lv_obj_set_style_local_text_color(lblSetTime, LV_LABEL_PART_MAIN, LV_STATE_DISABLED, LV_COLOR_GRAY); lv_obj_set_event_cb(btnSetTime, SetTimeEventHandler); UpdateScreen(); lv_obj_set_state(btnSetTime, LV_STATE_DISABLED); + lv_obj_set_state(lblSetTime, LV_STATE_DISABLED); } SettingSetTime::~SettingSetTime() { @@ -89,6 +91,7 @@ void SettingSetTime::UpdateScreen() { } } lv_obj_set_state(btnSetTime, LV_STATE_DEFAULT); + lv_obj_set_state(lblSetTime, LV_STATE_DEFAULT); } void SettingSetTime::SetTime() { @@ -104,4 +107,5 @@ void SettingSetTime::SetTime() { 0, nrf_rtc_counter_get(portNRF_RTC_REG)); lv_obj_set_state(btnSetTime, LV_STATE_DISABLED); + lv_obj_set_state(lblSetTime, LV_STATE_DISABLED); } diff --git a/src/displayapp/screens/settings/SettingSetTime.h b/src/displayapp/screens/settings/SettingSetTime.h index e0b42bdd..b61962c1 100644 --- a/src/displayapp/screens/settings/SettingSetTime.h +++ b/src/displayapp/screens/settings/SettingSetTime.h @@ -26,6 +26,7 @@ namespace Pinetime { lv_obj_t* lblampm; lv_obj_t* btnSetTime; + lv_obj_t* lblSetTime; Widgets::Counter hourCounter = Widgets::Counter(0, 23, jetbrains_mono_42); Widgets::Counter minuteCounter = Widgets::Counter(0, 59, jetbrains_mono_42); }; diff --git a/src/displayapp/screens/settings/SettingSteps.cpp b/src/displayapp/screens/settings/SettingSteps.cpp index af5bd6e9..a6b6f4a8 100644 --- a/src/displayapp/screens/settings/SettingSteps.cpp +++ b/src/displayapp/screens/settings/SettingSteps.cpp @@ -48,7 +48,8 @@ SettingSteps::SettingSteps(Pinetime::Applications::DisplayApp* app, Pinetime::Co btnPlus->user_data = this; lv_obj_set_size(btnPlus, 80, 50); lv_obj_align(btnPlus, lv_scr_act(), LV_ALIGN_CENTER, 55, 80); - lv_obj_set_style_local_value_str(btnPlus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "+"); + lv_obj_t* lblPlus = lv_label_create(btnPlus, nullptr); + lv_label_set_text_static(lblPlus, "+"); lv_obj_set_event_cb(btnPlus, event_handler); btnMinus = lv_btn_create(lv_scr_act(), nullptr); @@ -56,7 +57,8 @@ SettingSteps::SettingSteps(Pinetime::Applications::DisplayApp* app, Pinetime::Co lv_obj_set_size(btnMinus, 80, 50); lv_obj_set_event_cb(btnMinus, event_handler); lv_obj_align(btnMinus, lv_scr_act(), LV_ALIGN_CENTER, -55, 80); - lv_obj_set_style_local_value_str(btnMinus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "-"); + lv_obj_t* lblMinus = lv_label_create(btnMinus, nullptr); + lv_label_set_text_static(lblMinus, "-"); } SettingSteps::~SettingSteps() { diff --git a/src/displayapp/widgets/StatusIcons.cpp b/src/displayapp/widgets/StatusIcons.cpp index 607f3745..aacf13ae 100644 --- a/src/displayapp/widgets/StatusIcons.cpp +++ b/src/displayapp/widgets/StatusIcons.cpp @@ -15,11 +15,9 @@ void StatusIcons::Create() { lv_obj_set_style_local_bg_opa(container, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP); bleIcon = lv_label_create(container, nullptr); - lv_obj_set_style_local_text_color(bleIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x0082FC)); lv_label_set_text_static(bleIcon, Screens::Symbols::bluetooth); batteryPlug = lv_label_create(container, nullptr); - lv_obj_set_style_local_text_color(batteryPlug, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED); lv_label_set_text_static(batteryPlug, Screens::Symbols::plug); batteryIcon.Create(container); diff --git a/src/libs/lv_conf.h b/src/libs/lv_conf.h index 00f6a1df..063f1d34 100644 --- a/src/libs/lv_conf.h +++ b/src/libs/lv_conf.h @@ -164,7 +164,7 @@ typedef void* lv_anim_user_data_t; #define LV_USE_PATTERN 1 /*1: enable value string drawing on rectangles*/ -#define LV_USE_VALUE_STR 1 +#define LV_USE_VALUE_STR 0 /* 1: Use other blend modes than normal (`LV_BLEND_MODE_...`)*/ #define LV_USE_BLEND_MODES 0 diff --git a/src/resources/CMakeLists.txt b/src/resources/CMakeLists.txt new file mode 100644 index 00000000..0983aaff --- /dev/null +++ b/src/resources/CMakeLists.txt @@ -0,0 +1,29 @@ + +find_program(LV_FONT_CONV "lv_font_conv" NO_CACHE REQUIRED + HINTS "${CMAKE_SOURCE_DIR}/node_modules/.bin") +message(STATUS "Using ${LV_FONT_CONV} to generate font files") + +find_program(LV_IMG_CONV "lv_img_conv" NO_CACHE REQUIRED + HINTS "${CMAKE_SOURCE_DIR}/node_modules/.bin") +message(STATUS "Using ${LV_IMG_CONV} to generate font files") + +if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12) + # FindPython3 module introduces with CMake 3.12 + # https://cmake.org/cmake/help/latest/module/FindPython3.html + find_package(Python3 REQUIRED) +else() + set(Python3_EXECUTABLE "python") +endif() + +# generate fonts +add_custom_target(GenerateResources + COMMAND "${Python3_EXECUTABLE}" ${CMAKE_CURRENT_SOURCE_DIR}/generate-fonts.py --lv-font-conv "${LV_FONT_CONV}" ${CMAKE_CURRENT_SOURCE_DIR}/fonts.json + COMMAND "${Python3_EXECUTABLE}" ${CMAKE_CURRENT_SOURCE_DIR}/generate-img.py --lv-img-conv "${LV_IMG_CONV}" ${CMAKE_CURRENT_SOURCE_DIR}/images.json + COMMAND "${Python3_EXECUTABLE}" ${CMAKE_CURRENT_SOURCE_DIR}/generate-package.py --config ${CMAKE_CURRENT_SOURCE_DIR}/fonts.json --config ${CMAKE_CURRENT_SOURCE_DIR}/images.json --obsolete obsolete_files.json --output infinitime-resources-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.zip + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/fonts.json + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/images.json + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + + COMMENT "Generate fonts and images for resource package" +) + diff --git a/src/resources/fonts.json b/src/resources/fonts.json new file mode 100644 index 00000000..55882c3d --- /dev/null +++ b/src/resources/fonts.json @@ -0,0 +1,62 @@ +{ + "teko" : { + "sources": [ + { + "file": "fonts/Teko-Light.ttf", + "symbols": "0123456789:/amp" + } + ], + "bpp": 1, + "size": 28, + "format": "bin", + "target_path": "/fonts/" + }, + "bebas" : { + "sources": [ + { + "file": "fonts/BebasNeue-Regular.ttf", + "symbols": "0123456789:" + } + ], + "bpp": 1, + "size": 120, + "format": "bin", + "target_path": "/fonts/" + }, + "lv_font_dots_40": { + "sources": [ + { + "file": "fonts/repetitionscrolling.ttf", + "symbols": "0123456789-MONTUEWEDTHUFRISATSUN WK" + } + ], + "bpp": 1, + "size": 40, + "format": "bin", + "target_path": "/fonts/" + }, + "7segments_40" : { + "sources": [ + { + "file": "fonts/7segment.woff", + "symbols": "0123456789: -" + } + ], + "bpp": 1, + "size": 40, + "format": "bin", + "target_path": "/fonts/" + }, + "7segments_115" : { + "sources": [ + { + "file": "fonts/7segment.woff", + "symbols": "0123456789: -" + } + ], + "bpp": 1, + "size": 115, + "format": "bin", + "target_path": "/fonts/" + } +} diff --git a/src/resources/fonts/7segment.woff b/src/resources/fonts/7segment.woff Binary files differnew file mode 100644 index 00000000..79ed9249 --- /dev/null +++ b/src/resources/fonts/7segment.woff diff --git a/src/resources/fonts/BebasNeue-Regular.ttf b/src/resources/fonts/BebasNeue-Regular.ttf Binary files differnew file mode 100644 index 00000000..76e22b8b --- /dev/null +++ b/src/resources/fonts/BebasNeue-Regular.ttf diff --git a/src/resources/fonts/Teko-Light.ttf b/src/resources/fonts/Teko-Light.ttf Binary files differnew file mode 100644 index 00000000..679f0137 --- /dev/null +++ b/src/resources/fonts/Teko-Light.ttf diff --git a/src/resources/fonts/repetitionscrolling.ttf b/src/resources/fonts/repetitionscrolling.ttf Binary files differnew file mode 100644 index 00000000..dc124164 --- /dev/null +++ b/src/resources/fonts/repetitionscrolling.ttf diff --git a/src/resources/generate-fonts.py b/src/resources/generate-fonts.py new file mode 100755 index 00000000..20408166 --- /dev/null +++ b/src/resources/generate-fonts.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python + +import io +import sys +import json +import shutil +import typing +import os.path +import argparse +import subprocess + +class Source(object): + def __init__(self, d): + self.file = d['file'] + if not os.path.exists(self.file): + self.file = os.path.join(os.path.dirname(sys.argv[0]), self.file) + self.range = d.get('range') + self.symbols = d.get('symbols') + + +def gen_lvconv_line(lv_font_conv: str, dest: str, size: int, bpp: int, format: str, sources: typing.List[Source], compress:bool=False): + if format != "lvgl" and format != "bin": + format = "bin" if dest.lower().endswith(".bin") else "lvgl" + + args = [lv_font_conv, '--size', str(size), '--output', dest, '--bpp', str(bpp), '--format', format] + if not compress: + args.append('--no-compress') + for source in sources: + args.extend(['--font', source.file]) + if source.range: + args.extend(['--range', source.range]) + if source.symbols: + args.extend(['--symbols', source.symbols]) + + return args + +def main(): + ap = argparse.ArgumentParser(description='auto generate LVGL font files from fonts') + ap.add_argument('config', type=str, help='config file to use') + ap.add_argument('-f', '--font', type=str, action='append', help='Choose specific fonts to generate (default: all)', default=[]) + ap.add_argument('--lv-font-conv', type=str, help='Path to "lv_font_conf" executable', default="lv_font_conv") + args = ap.parse_args() + + if not shutil.which(args.lv_font_conv): + sys.exit(f"Missing lv_font_conv. Make sure it's findable (in PATH) or specify it manually") + if not os.path.exists(args.config): + sys.exit(f'Error: the config file {args.config} does not exist.') + if not os.access(args.config, os.R_OK): + sys.exit(f'Error: the config file {args.config} is not accessible (permissions?).') + with open(args.config, 'r') as fd: + data = json.load(fd) + + fonts_to_run = set(data.keys()) + + if args.font: + enabled_fonts = set() + for font in args.font: + enabled_fonts.add(font[:-2] if font.endswith('.c') else font) + d = enabled_fonts.difference(fonts_to_run) + if d: + print(f'Warning: requested font{"s" if len(d)>1 else ""} missing: {" ".join(d)}') + fonts_to_run = fonts_to_run.intersection(enabled_fonts) + + for name in fonts_to_run: + font = data[name] + sources = font.pop('sources') + patches = font.pop('patches') if 'patches' in font else [] + font['sources'] = [Source(thing) for thing in sources] + extension = 'c' if font['format'] != 'bin' else 'bin' + font.pop('target_path') + line = gen_lvconv_line(args.lv_font_conv, f'{name}.{extension}', **font) + subprocess.check_call(line) + if patches: + for patch in patches: + subprocess.check_call(['/usr/bin/env', 'patch', name+'.'+extension, patch]) + + + +if __name__ == '__main__': + main() diff --git a/src/resources/generate-img.py b/src/resources/generate-img.py new file mode 100755 index 00000000..cdbfc030 --- /dev/null +++ b/src/resources/generate-img.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python + +import io +import sys +import json +import shutil +import typing +import os.path +import argparse +import subprocess + +def gen_lvconv_line(lv_img_conv: str, dest: str, color_format: str, output_format: str, binary_format: str, sources: str): + args = [lv_img_conv, sources, '--force', '--output-file', dest, '--color-format', color_format, '--output-format', output_format, '--binary-format', binary_format] + + return args + +def main(): + ap = argparse.ArgumentParser(description='auto generate LVGL font files from fonts') + ap.add_argument('config', type=str, help='config file to use') + ap.add_argument('-i', '--image', type=str, action='append', help='Choose specific images to generate (default: all)', default=[]) + ap.add_argument('--lv-img-conv', type=str, help='Path to "lv_img_conf" executable', default="lv_img_conv") + args = ap.parse_args() + + if not shutil.which(args.lv_img_conv): + sys.exit(f"Missing lv_img_conv. Make sure it's findable (in PATH) or specify it manually") + if not os.path.exists(args.config): + sys.exit(f'Error: the config file {args.config} does not exist.') + if not os.access(args.config, os.R_OK): + sys.exit(f'Error: the config file {args.config} is not accessible (permissions?).') + with open(args.config, 'r') as fd: + data = json.load(fd) + + images_to_run = set(data.keys()) + + if args.image: + enabled_images = set() + for image in args.image: + enabled_images.add(image[:-2] if image.endswith('.c') else image) + d = enabled_images.difference(images_to_run) + if d: + print(f'Warning: requested image{"s" if len(d)>1 else ""} missing: {" ".join(d)}') + images_to_run = images_to_run.intersection(enabled_images) + + for name in images_to_run: + image = data[name] + if not os.path.exists(image['sources']): + image['sources'] = os.path.join(os.path.dirname(sys.argv[0]), image['sources']) + extension = 'bin' + image.pop('target_path') + line = gen_lvconv_line(args.lv_img_conv, f'{name}.{extension}', **image) + subprocess.check_call(line) + + + +if __name__ == '__main__': + main() diff --git a/src/resources/generate-package.py b/src/resources/generate-package.py new file mode 100755 index 00000000..ff02d4fe --- /dev/null +++ b/src/resources/generate-package.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python + +import io +import sys +import json +import shutil +import typing +import os.path +import argparse +import subprocess +from zipfile import ZipFile + +def main(): + ap = argparse.ArgumentParser(description='auto generate LVGL font files from fonts') + ap.add_argument('--config', '-c', type=str, action='append', help='config file to use') + ap.add_argument('--obsolete', type=str, help='List of obsolete files') + ap.add_argument('--output', type=str, help='output file name') + args = ap.parse_args() + + for config_file in args.config: + if not os.path.exists(config_file): + sys.exit(f'Error: the config file {config_file} does not exist.') + if not os.access(config_file, os.R_OK): + sys.exit(f'Error: the config file {config_file} is not accessible (permissions?).') + + if args.obsolete: + obsolete_file_path = os.path.join(os.path.dirname(sys.argv[0]), args.obsolete) + if not os.path.exists(obsolete_file_path): + sys.exit(f'Error: the "obsolete" file {args.obsolete} does not exist.') + if not os.access(obsolete_file_path, os.R_OK): + sys.exit(f'Error: the "obsolete" file {args.obsolete} is not accessible (permissions?).') + + zf = ZipFile(args.output, mode='w') + resource_files = [] + + for config_file in args.config: + with open(config_file, 'r') as fd: + data = json.load(fd) + + resource_names = set(data.keys()) + for name in resource_names: + resource = data[name] + resource_files.append({ + "filename": name+'.bin', + "path": resource['target_path'] + name+'.bin' + }) + + path = name + '.bin' + if not os.path.exists(path): + path = os.path.join(os.path.dirname(sys.argv[0]), path) + zf.write(path) + + if args.obsolete: + obsolete_file_path = os.path.join(os.path.dirname(sys.argv[0]), args.obsolete) + with open(obsolete_file_path, 'r') as fd: + obsolete_data = json.load(fd) + else: + obsolete_data = {} + output = { + 'resources': resource_files, + 'obsolete_files': obsolete_data + } + + + with open("resources.json", 'w') as fd: + json.dump(output, fd, indent=4) + + zf.write('resources.json') + zf.close() + +if __name__ == '__main__': + main() diff --git a/src/resources/images.json b/src/resources/images.json new file mode 100644 index 00000000..764747ca --- /dev/null +++ b/src/resources/images.json @@ -0,0 +1,9 @@ +{ + "pine_small" : { + "sources": "images/pine_logo.png", + "color_format": "CF_TRUE_COLOR", + "output_format": "bin", + "binary_format": "ARGB8565_RBSWAP", + "target_path": "/images/" + } +} diff --git a/src/resources/images/pine_logo.png b/src/resources/images/pine_logo.png Binary files differnew file mode 100644 index 00000000..aa96be4b --- /dev/null +++ b/src/resources/images/pine_logo.png diff --git a/src/resources/images/pine_logo.svg b/src/resources/images/pine_logo.svg new file mode 100644 index 00000000..55f21169 --- /dev/null +++ b/src/resources/images/pine_logo.svg @@ -0,0 +1,253 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + width="110.49872" + height="150.24246" + viewBox="0 0 29.236118 39.751652" + version="1.1" + id="svg2418" + inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)" + sodipodi:docname="pine_logo.svg" + inkscape:export-filename="/home/diegomiguel/Syncthing/Watchface/pine_logo_new_2_transparent.png" + inkscape:export-xdpi="19.807983" + inkscape:export-ydpi="19.807983" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview2420" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:document-units="mm" + showgrid="false" + fit-margin-top="0" + fit-margin-left="0" + fit-margin-right="0" + fit-margin-bottom="0" + units="px" + inkscape:zoom="4.1424077" + inkscape:cx="69.886892" + inkscape:cy="73.387272" + inkscape:window-width="1920" + inkscape:window-height="1026" + inkscape:window-x="0" + inkscape:window-y="24" + inkscape:window-maximized="1" + inkscape:current-layer="g972" + inkscape:snap-page="true" /> + <defs + id="defs2415" /> + <g + inkscape:label="Layer 1" + id="layer1" + transform="translate(-91.35232,-110.1768)" + inkscape:groupmode="layer"> + <rect + style="display:none;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#4d4d4d;stroke-width:0" + id="rect2129" + width="29.236118" + height="39.751652" + x="91.352318" + y="110.1768" + inkscape:label="bg" /> + <g + id="g32004" + style="display:none;stroke:none" + inkscape:export-filename="/Users/diegomiguel/Syncthing/Watchface/logo_pine.png" + inkscape:export-xdpi="19.965168" + inkscape:export-ydpi="19.965168" + inkscape:label="pine_logo" + transform="translate(75.060638,-5.5438717)"> + <g + id="g13016" + inkscape:label="pine" + style="display:inline;fill:#6f2d00;fill-opacity:1;stroke:none" + transform="matrix(1.1631294,0,0,1.1631294,-5.0422885,-22.11978)" + inkscape:export-filename="/Users/diegomiguel/Syncthing/Watchface/logo_pine.png" + inkscape:export-xdpi="31.276381" + inkscape:export-ydpi="31.276381" + sodipodi:insensitive="true"> + <path + id="path5716" + style="fill:#6f2d00;fill-opacity:1;stroke:none;stroke-width:2.34917;stroke-linecap:round" + inkscape:transform-center-x="1.2687941" + d="M 116.82422,535.70898 102.4375,542.5 l -14.386719,6.78906 14.386719,6.78906 11,5.19141 v 15.80664 h 3.38672 v -14.20703 -3.93555 -9.64453 z" + transform="scale(0.26458333)" /> + <path + style="fill:#6f2d00;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 18.341872,136.77692 3.331558,7.57837 7.029221,-3.22172 z" + id="path5936" + sodipodi:nodetypes="cccc" /> + <path + sodipodi:type="star" + style="fill:#6f2d00;fill-opacity:1;stroke:none;stroke-width:1.51181;stroke-linecap:round" + id="path7773" + inkscape:flatsided="false" + sodipodi:sides="3" + sodipodi:cx="116.64632" + sodipodi:cy="501.86975" + sodipodi:r1="14.699218" + sodipodi:r2="7.3496094" + sodipodi:arg1="1.0471976" + sodipodi:arg2="2.0943951" + inkscape:rounded="0" + inkscape:randomized="0" + transform="matrix(0.39243637,0,0,0.31059853,-17.750778,-19.228227)" + inkscape:transform-center-x="1.4421265" + d="m 123.99592,514.59965 -11.02441,-6.36495 -11.02441,-6.36495 11.02441,-6.36495 11.02442,-6.36494 0,12.72989 z" /> + <path + sodipodi:type="star" + style="fill:#6f2d00;fill-opacity:1;stroke:none;stroke-width:1.51181;stroke-linecap:round" + id="path7877" + inkscape:flatsided="false" + sodipodi:sides="3" + sodipodi:cx="116.64632" + sodipodi:cy="501.86975" + sodipodi:r1="14.699218" + sodipodi:r2="7.3496094" + sodipodi:arg1="1.0471976" + sodipodi:arg2="2.0943951" + inkscape:rounded="0" + inkscape:randomized="0" + transform="matrix(-0.3940968,0,0,-0.29190487,69.062729,278.57074)" + inkscape:transform-center-x="-1.4482278" + inkscape:transform-center-y="3.6892669e-06" + d="m 123.99592,514.59965 -11.02441,-6.36495 -11.02441,-6.36495 11.02441,-6.36495 11.02442,-6.36494 0,12.72989 z" /> + <path + sodipodi:type="star" + style="fill:#6f2d00;fill-opacity:1;stroke:none;stroke-width:1.51181;stroke-linecap:round" + id="path7929" + inkscape:flatsided="false" + sodipodi:sides="3" + sodipodi:cx="116.64632" + sodipodi:cy="501.86975" + sodipodi:r1="14.699218" + sodipodi:r2="7.3496094" + sodipodi:arg1="1.0471976" + sodipodi:arg2="2.0943951" + inkscape:rounded="0" + inkscape:randomized="0" + transform="matrix(0.34926521,0,0,0.27033526,-12.397729,-7.5515591)" + inkscape:transform-center-x="1.28348" + inkscape:transform-center-y="1.7340579e-06" + d="m 123.99592,514.59965 -11.02441,-6.36495 -11.02441,-6.36495 11.02441,-6.36495 11.02442,-6.36494 0,12.72989 z" /> + <path + style="fill:#6f2d00;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 24.903849,122.34368 -1.378447,3.99721 5.0395,-2.31516 z" + id="path7964" + sodipodi:nodetypes="cccc" /> + <path + style="fill:#6f2d00;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 30.909733,118.50827 v 4.63122 l -3.122345,-1.29967 z" + id="path11445" /> + </g> + <g + id="g13032" + transform="matrix(-1.1631294,0,0,1.1631294,66.861771,-22.11978)" + style="fill:#de5a00;fill-opacity:1;stroke:none" + inkscape:label="pine" + inkscape:export-filename="/Users/diegomiguel/Syncthing/Watchface/logo_pine.png" + inkscape:export-xdpi="31.276381" + inkscape:export-ydpi="31.276381"> + <path + id="path13018" + style="fill:#de5a00;fill-opacity:1;stroke:none;stroke-width:2.34917;stroke-linecap:round" + inkscape:transform-center-x="1.2687941" + d="M 116.82422,535.70898 102.4375,542.5 l -14.386719,6.78906 14.386719,6.78906 11,5.19141 v 15.80664 h 3.38672 v -14.20703 -3.93555 -9.64453 z" + transform="scale(0.26458333)" /> + <path + style="fill:#de5a00;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 18.341872,136.77692 3.331558,7.57837 7.029221,-3.22172 z" + id="path13020" + sodipodi:nodetypes="cccc" /> + <path + sodipodi:type="star" + style="fill:#de5a00;fill-opacity:1;stroke:none;stroke-width:1.51181;stroke-linecap:round" + id="path13022" + inkscape:flatsided="false" + sodipodi:sides="3" + sodipodi:cx="116.64632" + sodipodi:cy="501.86975" + sodipodi:r1="14.699218" + sodipodi:r2="7.3496094" + sodipodi:arg1="1.0471976" + sodipodi:arg2="2.0943951" + inkscape:rounded="0" + inkscape:randomized="0" + transform="matrix(0.39243637,0,0,0.31059853,-17.750778,-19.228227)" + inkscape:transform-center-x="1.4421265" + d="m 123.99592,514.59965 -11.02441,-6.36495 -11.02441,-6.36495 11.02441,-6.36495 11.02442,-6.36494 0,12.72989 z" /> + <path + sodipodi:type="star" + style="fill:#de5a00;fill-opacity:1;stroke:none;stroke-width:1.51181;stroke-linecap:round" + id="path13024" + inkscape:flatsided="false" + sodipodi:sides="3" + sodipodi:cx="116.64632" + sodipodi:cy="501.86975" + sodipodi:r1="14.699218" + sodipodi:r2="7.3496094" + sodipodi:arg1="1.0471976" + sodipodi:arg2="2.0943951" + inkscape:rounded="0" + inkscape:randomized="0" + transform="matrix(-0.3940968,0,0,-0.29190487,69.062729,278.57074)" + inkscape:transform-center-x="-1.4482278" + inkscape:transform-center-y="3.6892669e-06" + d="m 123.99592,514.59965 -11.02441,-6.36495 -11.02441,-6.36495 11.02441,-6.36495 11.02442,-6.36494 0,12.72989 z" /> + <path + sodipodi:type="star" + style="fill:#de5a00;fill-opacity:1;stroke:none;stroke-width:1.51181;stroke-linecap:round" + id="path13026" + inkscape:flatsided="false" + sodipodi:sides="3" + sodipodi:cx="116.64632" + sodipodi:cy="501.86975" + sodipodi:r1="14.699218" + sodipodi:r2="7.3496094" + sodipodi:arg1="1.0471976" + sodipodi:arg2="2.0943951" + inkscape:rounded="0" + inkscape:randomized="0" + transform="matrix(0.34926521,0,0,0.27033526,-12.397729,-7.5515591)" + inkscape:transform-center-x="1.28348" + inkscape:transform-center-y="1.7340579e-06" + d="m 123.99592,514.59965 -11.02441,-6.36495 -11.02441,-6.36495 11.02441,-6.36495 11.02442,-6.36494 0,12.72989 z" /> + <path + style="fill:#de5a00;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 24.903849,122.34368 -1.378447,3.99721 5.0395,-2.31516 z" + id="path13028" + sodipodi:nodetypes="cccc" /> + <path + style="fill:#de5a00;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 30.909733,118.50827 v 4.63122 l -3.122345,-1.29967 z" + id="path13030" /> + </g> + </g> + <g + id="g972" + style="display:inline;stroke:none" + inkscape:export-filename="/Users/diegomiguel/Syncthing/Watchface/logo_pine.png" + inkscape:export-xdpi="19.965168" + inkscape:export-ydpi="19.965168" + inkscape:label="pine_logo" + transform="translate(75.060638,-5.5438717)"> + <path + id="path952" + style="fill:#0f0f0f;fill-opacity:1;stroke:none;stroke-width:0.307744px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 30.909731,115.72067 v 5.38671 l -3.631692,-1.51168 z m -6.985621,4.46108 -1.603312,4.64927 5.861591,-2.69283 z m 6.98562,10.72311 -4.478564,-2.00136 -4.478563,-2.00136 4.478563,-2.00136 4.478568,-2.00137 v 4.00273 z m -12.461069,-3.7293 5.05343,2.16104 5.053431,2.16105 -5.053431,2.16105 -5.053434,2.16104 v -4.32209 z m 12.461067,14.24725 -5.032139,-2.29945 -5.032139,-2.29944 5.032139,-2.29943 5.032144,-2.29945 v 4.59888 z m -14.618046,-4.45333 3.875033,8.81462 8.175894,-3.74728 z m 14.618058,5.77232 -4.427436,2.0899 -4.427436,2.08929 4.427436,2.0893 3.385191,1.59762 v 4.86441 h 1.042245 v -4.37214 -1.21114 -2.96805 z" + inkscape:label="left" /> + <path + id="path968" + style="fill:#575757;fill-opacity:1;stroke:none;stroke-width:0.307744px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 30.909752,115.72067 v 5.38671 l 3.631691,-1.51168 z m 6.98562,4.46108 1.603312,4.64927 -5.86159,-2.69283 z m -6.985619,10.72311 4.478564,-2.00136 4.478563,-2.00136 -4.478563,-2.00136 -4.478568,-2.00136 v 4.00272 z m 12.461067,-3.72931 -5.05343,2.16105 -5.05343,2.16105 5.05343,2.16104 5.053435,2.16105 v -4.32209 z m -12.461065,14.24726 5.032139,-2.29945 5.032139,-2.29944 -5.032139,-2.29944 -5.032144,-2.29944 v 4.59888 z m 14.618045,-4.45333 -3.875033,8.81462 -8.175893,-3.74728 z m -14.618058,5.77231 4.427436,2.0899 4.427436,2.0893 -4.427436,2.0893 -3.385191,1.59763 v 4.8644 h -1.042245 v -4.37213 -1.21115 -2.96805 z" + inkscape:label="right" /> + </g> + </g> +</svg> diff --git a/src/resources/obsolete_files.json b/src/resources/obsolete_files.json new file mode 100644 index 00000000..6109ace7 --- /dev/null +++ b/src/resources/obsolete_files.json @@ -0,0 +1,6 @@ +[ + { + "path": "/example-of-obsolete-file.bin", + "since": "1.11.0" + } +]
\ No newline at end of file |
