From 8fabf0d03857c68609895f886532142493ea601a Mon Sep 17 00:00:00 2001 From: Arjan Schrijver Date: Sat, 17 Jul 2021 22:24:52 +0200 Subject: [PATCH] Fossil Hybrid HR: Support configuring watchface internal values --- .../assets/fossil_hr/openSourceWatchface.bin | Bin 2778 -> 3160 bytes .../HybridHRWatchfaceDesignerActivity.java | 61 +++++++++ .../qhybrid/HybridHRWatchfaceFactory.java | 19 ++- .../qhybrid/HybridHRWatchfaceSettings.java | 89 +++++++++++++ .../activity_hybridhr_watchface_designer.xml | 1 - .../dialog_hybridhr_watchface_settings.xml | 122 ++++++++++++++++++ app/src/main/res/values/strings.xml | 10 ++ 7 files changed, 298 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceSettings.java create mode 100644 app/src/main/res/layout/dialog_hybridhr_watchface_settings.xml diff --git a/app/src/main/assets/fossil_hr/openSourceWatchface.bin b/app/src/main/assets/fossil_hr/openSourceWatchface.bin index a032285597b49702868e400db847fd3c588ec332..eeaa332bc96c51bd8642c2014068d598910d1f77 100644 GIT binary patch delta 1185 zcmZWoOHUI~6h60|_D-!lsx57y6k1w3!^1Z%0xBZV0bfXrQ4>>(Ev2!vq_m)J>aKAI znP1?_oiQPCg)wd%+;C$zj*l?U3O*gpCsdh8a7iWzb$Wn_o@tklN`5E-GQ&438tE@@=L}68LLXiqkhF54Jn?esj9|QyZJmSEv;332yXkh-L z(}op{Zr6vA7i)qu0$hNDS=O78fF%)Q5Q`<|B$iB{v2?TR`l@A|$@-?Hi+$I>Sz>Hc zm#sbWTAYsLqONIu$QlWBDg3QsO9YfyLV06VS&KWN`n-uApFh#7uUc=^`V{tlzXe39 z*#wzMJQDf6Udc<4g(L3FM{x~+kD)JDz~i_gV7_$%48&0E-!4DQXjLegblc2Ec^zlU@QjMfQtDK zz-V$e^&Q(-I5vY!zyOlBU_-PMpVeU-0)rbD?HP8xl~&976}MN5rrDr zd9*1papb2@N)PAXiP(c8N5CFJW<}b=BEJbeCg+WYVxWV+#>uCRhMyntCvyH|+Aoay zQ)7N{ygn4yOp9g>3{Y9@oQO9{u`!X;aSD2p-iYA?F0`o3H^$>^??sP!*r zT-9~%nAqRK>fp?8NCech#JcVS8?KB0hgFa#w!3}gKbJS0+PK^PPL&ksj=khXO zA`7jAD^|u@O*x`IyV4b;GyP7uu63*3@UFJ4jPO{SR=>hmnyuc3KeSovc@#C1@xorc zlq;0Y*JYzNUbbuH7n-B8gT6ED&*tXCJ${P)eP-0`jU8bxS29#S-2)-fC4jCTNOuj2&m^>ESn zIuUGOZc>x??c3 widgets = new ArrayList<>(); + private HybridHRWatchfaceSettings watchfaceSettings = new HybridHRWatchfaceSettings(); @Override protected void onCreate(Bundle savedInstanceState) { @@ -183,6 +185,8 @@ public class HybridHRWatchfaceDesignerActivity extends AbstractGBActivity implem startActivityForResult(intent, 42); } else if (v.getId() == R.id.button_add_widget) { showWidgetEditPopup(-1); + } else if (v.getId() == R.id.button_watchface_settings) { + showWatchfaceSettingsPopup(); } } @@ -284,6 +288,30 @@ public class HybridHRWatchfaceDesignerActivity extends AbstractGBActivity implem } catch (JSONException e) { LOG.warn("JSON parsing error", e); } + } else if (key.equals("config")) { + try { + JSONObject watchfaceConfig = configJSON.getJSONObject(key); + if (watchfaceConfig.has("timeout_display_full")) { + watchfaceSettings.setDisplayTimeoutFull(watchfaceConfig.getInt("timeout_display_full") / 60 / 1000); + } + if (watchfaceConfig.has("timeout_display_partial")) { + watchfaceSettings.setDisplayTimeoutPartial(watchfaceConfig.getInt("timeout_display_partial") / 60 / 1000); + } + if (watchfaceConfig.has("wrist_flick_hands_relative")) { + watchfaceSettings.setWristFlickHandsMoveRelative(watchfaceConfig.getBoolean("wrist_flick_hands_relative")); + } + if (watchfaceConfig.has("wrist_flick_duration")) { + watchfaceSettings.setWristFlickDuration(watchfaceConfig.getInt("wrist_flick_duration")); + } + if (watchfaceConfig.has("wrist_flick_move_hour")) { + watchfaceSettings.setWristFlickMoveHour(watchfaceConfig.getInt("wrist_flick_move_hour")); + } + if (watchfaceConfig.has("wrist_flick_move_minute")) { + watchfaceSettings.setWristFlickMoveMinute(watchfaceConfig.getInt("wrist_flick_move_minute")); + } + } catch (JSONException e) { + LOG.warn("JSON parsing error", e); + } } } } @@ -466,6 +494,38 @@ public class HybridHRWatchfaceDesignerActivity extends AbstractGBActivity implem .show(); } + private void showWatchfaceSettingsPopup() { + View layout = getLayoutInflater().inflate(R.layout.dialog_hybridhr_watchface_settings, null); + final EditText displayTimeoutFullInput = layout.findViewById(R.id.watchface_setting_display_full); + displayTimeoutFullInput.setText(String.valueOf(watchfaceSettings.getDisplayTimeoutFull())); + final EditText displayTimeoutPartialInput = layout.findViewById(R.id.watchface_setting_display_partial); + displayTimeoutPartialInput.setText(String.valueOf(watchfaceSettings.getDisplayTimeoutPartial())); + final CheckBox wristFlickHandsMoveRelativeInput = layout.findViewById(R.id.watchface_setting_flick_relative); + wristFlickHandsMoveRelativeInput.setChecked(watchfaceSettings.isWristFlickHandsMoveRelative()); + final EditText wristFlickDurationInput = layout.findViewById(R.id.watchface_setting_flick_timeout); + wristFlickDurationInput.setText(String.valueOf(watchfaceSettings.getWristFlickDuration())); + final EditText wristFlickMoveHourInput = layout.findViewById(R.id.watchface_setting_flick_hour); + wristFlickMoveHourInput.setText(String.valueOf(watchfaceSettings.getWristFlickMoveHour())); + final EditText wristFlickMoveMinuteInput = layout.findViewById(R.id.watchface_setting_flick_minute); + wristFlickMoveMinuteInput.setText(String.valueOf(watchfaceSettings.getWristFlickMoveMinute())); + new AlertDialog.Builder(this) + .setView(layout) + .setNegativeButton(R.string.fossil_hr_new_action_cancel, null) + .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + watchfaceSettings.setDisplayTimeoutFull(Integer.parseInt(displayTimeoutFullInput.getText().toString())); + watchfaceSettings.setDisplayTimeoutPartial(Integer.parseInt(displayTimeoutPartialInput.getText().toString())); + watchfaceSettings.setWristFlickHandsMoveRelative(wristFlickHandsMoveRelativeInput.isChecked()); + watchfaceSettings.setWristFlickDuration(Integer.parseInt(wristFlickDurationInput.getText().toString())); + watchfaceSettings.setWristFlickMoveHour(Integer.parseInt(wristFlickMoveHourInput.getText().toString())); + watchfaceSettings.setWristFlickMoveMinute(Integer.parseInt(wristFlickMoveMinuteInput.getText().toString())); + } + }) + .setTitle(R.string.watchface_dialog_title_settings) + .show(); + } + private void calculateDisplayImageSize() { DisplayMetrics displayMetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); @@ -504,6 +564,7 @@ public class HybridHRWatchfaceDesignerActivity extends AbstractGBActivity implem } else { wfFactory = new HybridHRWatchfaceFactory(watchfaceName); } + wfFactory.setSettings(watchfaceSettings); wfFactory.setBackground(processedBackgroundImage); wfFactory.addWidgets(widgets); try { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceFactory.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceFactory.java index 3960b630a..984bd19ec 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceFactory.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceFactory.java @@ -36,6 +36,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fos public class HybridHRWatchfaceFactory { private final Logger LOG = LoggerFactory.getLogger(HybridHRWatchfaceFactory.class); private String watchfaceName; + private HybridHRWatchfaceSettings settings; private Bitmap background; private ArrayList widgets = new ArrayList<>(); @@ -45,6 +46,10 @@ public class HybridHRWatchfaceFactory { if (watchfaceName.endsWith("App")) watchfaceName += "Watchface"; } + public void setSettings(HybridHRWatchfaceSettings settings) { + this.settings = settings; + } + public void setBackground(Bitmap background) { if ((background.getWidth() == 240) && (background.getHeight() == 240)) { this.background = background; @@ -259,8 +264,8 @@ public class HybridHRWatchfaceFactory { private String getConfiguration() throws JSONException { JSONObject configuration = new JSONObject(); - JSONArray layout = new JSONArray(); + JSONArray layout = new JSONArray(); JSONObject background = new JSONObject(); background.put("type", "image"); background.put("name", "background.raw"); @@ -273,12 +278,20 @@ public class HybridHRWatchfaceFactory { pos.put("y", 120); background.put("pos", pos); layout.put(background); - for (JSONObject widget : widgets) { layout.put(widget); } - configuration.put("layout", layout); + + JSONObject config = new JSONObject(); + config.put("timeout_display_full", settings.getDisplayTimeoutFull() * 60 * 1000); + config.put("timeout_display_partial", settings.getDisplayTimeoutPartial() * 60 * 1000); + config.put("wrist_flick_hands_relative", settings.isWristFlickHandsMoveRelative()); + config.put("wrist_flick_duration", settings.getWristFlickDuration()); + config.put("wrist_flick_move_hour", settings.getWristFlickMoveHour()); + config.put("wrist_flick_move_minute", settings.getWristFlickMoveMinute()); + configuration.put("config", config); + return configuration.toString(); } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceSettings.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceSettings.java new file mode 100644 index 000000000..127b7b151 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceSettings.java @@ -0,0 +1,89 @@ +/* Copyright (C) 2021 Arjan Schrijver + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ +package nodomain.freeyourgadget.gadgetbridge.devices.qhybrid; + +public class HybridHRWatchfaceSettings { + private int displayTimeoutFull = 60; + private int displayTimeoutPartial = 15; + private boolean wristFlickHandsMoveRelative = true; + private int wristFlickDuration = 2200; + private int wristFlickMoveHour = 360; + private int wristFlickMoveMinute = -360; + + public HybridHRWatchfaceSettings() { + } + + public int getDisplayTimeoutFull() { + return displayTimeoutFull; + } + + public void setDisplayTimeoutFull(int displayTimeoutFull) { + this.displayTimeoutFull = displayTimeoutFull; + } + + public int getDisplayTimeoutPartial() { + return displayTimeoutPartial; + } + + public void setDisplayTimeoutPartial(int displayTimeoutPartial) { + this.displayTimeoutPartial = displayTimeoutPartial; + } + + public boolean isWristFlickHandsMoveRelative() { + return wristFlickHandsMoveRelative; + } + + public void setWristFlickHandsMoveRelative(boolean wristFlickHandsMoveRelative) { + this.wristFlickHandsMoveRelative = wristFlickHandsMoveRelative; + } + + public int getWristFlickDuration() { + return wristFlickDuration; + } + + public void setWristFlickDuration(int wristFlickDuration) { + this.wristFlickDuration = wristFlickDuration; + } + + public int getWristFlickMoveHour() { + return wristFlickMoveHour; + } + + public void setWristFlickMoveHour(int wristFlickMoveHour) { + if (wristFlickMoveHour < -360) { + this.wristFlickMoveHour = -360; + } else if (wristFlickMoveHour > 360) { + this.wristFlickMoveHour = 360; + } else { + this.wristFlickMoveHour = wristFlickMoveHour; + } + } + + public int getWristFlickMoveMinute() { + return wristFlickMoveMinute; + } + + public void setWristFlickMoveMinute(int wristFlickMoveMinute) { + if (wristFlickMoveMinute < -360) { + this.wristFlickMoveMinute = -360; + } else if (wristFlickMoveMinute > 360) { + this.wristFlickMoveMinute = 360; + } else { + this.wristFlickMoveMinute = wristFlickMoveMinute; + } + } +} diff --git a/app/src/main/res/layout/activity_hybridhr_watchface_designer.xml b/app/src/main/res/layout/activity_hybridhr_watchface_designer.xml index 909eeba4f..e55d2dd23 100644 --- a/app/src/main/res/layout/activity_hybridhr_watchface_designer.xml +++ b/app/src/main/res/layout/activity_hybridhr_watchface_designer.xml @@ -61,7 +61,6 @@ android:id="@+id/button_watchface_settings" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:enabled="false" android:text="@string/button_watchface_settings" /> diff --git a/app/src/main/res/layout/dialog_hybridhr_watchface_settings.xml b/app/src/main/res/layout/dialog_hybridhr_watchface_settings.xml new file mode 100644 index 000000000..e0bfb59b7 --- /dev/null +++ b/app/src/main/res/layout/dialog_hybridhr_watchface_settings.xml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c6e291902..1086aabc0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1230,4 +1230,14 @@ Color: White on black Black on white + Watchface settings + Display refresh timeout + Full refresh (in minutes): + Partial refresh (in minutes): + Wrist flick + (to disable completely, enable relative movement and set all values to 0) + Hands move relative to time: + Hour hand (-360 to 360): + Minute hand (-360 to 360): + Duration (in ms): \ No newline at end of file