diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 36c6e36d0..96a65c05b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -678,6 +678,10 @@
android:name=".devices.qhybrid.HybridHRWatchfaceSettingsActivity"
android:label="@string/watchface_dialog_title_settings"
android:parentActivityName=".devices.qhybrid.HybridHRWatchfaceDesignerActivity" />
+
= 0) {
+ widgets.set(widgetIndex, editedWidget);
+ } else {
+ widgets.add(editedWidget);
+ }
+ renderWatchfacePreview();
}
}
@@ -478,227 +488,30 @@ public class HybridHRWatchfaceDesignerActivity extends AbstractGBActivity implem
backgroundImageView.setImageBitmap(processedBackgroundImage);
}
- private void showWidgetEditPopup(final int index) {
- View layout = getLayoutInflater().inflate(R.layout.dialog_hybridhr_watchface_widget, null);
- HybridHRWatchfaceWidget widget = null;
+ private void showWidgetEditPopup(int index) {
+ HybridHRWatchfaceWidget widget;
if (index >= 0) {
widget = widgets.get(index);
- }
- // Configure widget type dropdown
- final Spinner typeSpinner = layout.findViewById(R.id.watchface_widget_type_spinner);
- LinkedHashMap widgetTypes = HybridHRWatchfaceWidget.getAvailableWidgetTypes(this);
- ArrayAdapter widgetTypeAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_dropdown_item, widgetTypes.values().toArray(new String[0]));
- typeSpinner.setAdapter(widgetTypeAdapter);
- final ArrayList widgetTypesArray = new ArrayList<>(widgetTypes.keySet());
- if ((widget != null) && (widgetTypesArray.contains(widget.getWidgetType()))) {
- typeSpinner.setSelection(widgetTypesArray.indexOf(widget.getWidgetType()));
- }
- // Configure widget color dropdown
- final Spinner colorSpinner = layout.findViewById(R.id.watchface_widget_color_spinner);
- ArrayAdapter widgetColorAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_dropdown_item, new String[]{getString(R.string.watchface_dialog_widget_color_white), getString(R.string.watchface_dialog_widget_color_black)});
- colorSpinner.setAdapter(widgetColorAdapter);
- if (widget != null) {
- colorSpinner.setSelection(widget.getColor());
} else {
- colorSpinner.setSelection(defaultWidgetColor);
- }
- // Set X coordinate
- final EditText posX = layout.findViewById(R.id.watchface_widget_pos_x);
- if (widget != null) {
- posX.setText(Integer.toString(widget.getPosX()));
- }
- // Set Y coordinate
- final EditText posY = layout.findViewById(R.id.watchface_widget_pos_y);
- if (widget != null) {
- posY.setText(Integer.toString(widget.getPosY()));
- }
-
- class WidgetPosition{
- final int posX, posY, buttonResource, hintStringResource;
-
- public WidgetPosition(int posX, int posY, int buttonResource, int hintStringResource) {
- this.posX = posX;
- this.posY = posY;
- this.buttonResource = buttonResource;
- this.hintStringResource = hintStringResource;
- }
- }
-
- WidgetPosition[] positions = new WidgetPosition[]{
- new WidgetPosition(120, 58, R.id.watchface_widget_preset_top, R.string.watchface_dialog_widget_preset_top),
- new WidgetPosition(182, 120, R.id.watchface_widget_preset_right, R.string.watchface_dialog_widget_preset_right),
- new WidgetPosition(120, 182, R.id.watchface_widget_preset_bottom, R.string.watchface_dialog_widget_preset_bottom),
- new WidgetPosition(58, 120, R.id.watchface_widget_preset_left, R.string.watchface_dialog_widget_preset_left),
- };
-
- for(final WidgetPosition position : positions){
- Button btn = layout.findViewById(position.buttonResource);
- btn.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- posX.setText(String.valueOf(position.posX));
- posY.setText(String.valueOf(position.posY));
- }
- });
- }
-
- if(widget == null){
+ int posX = 120;
+ int posY = 120;
int currentIndex = widgets.size();
- if(currentIndex < 4){
- WidgetPosition newPosition = positions[currentIndex];
- posX.setText(String.valueOf(newPosition.posX));
- posY.setText(String.valueOf(newPosition.posY));
+ if (currentIndex < 4) {
+ HybridHRWidgetPosition newPosition = HybridHRWatchfaceWidget.defaultPositions[currentIndex];
+ posX = newPosition.posX;
+ posY = newPosition.posY;
GB.toast(getString(R.string.watchface_dialog_pre_setting_position, getString(newPosition.hintStringResource)), Toast.LENGTH_SHORT, GB.INFO);
}
- }
-
- // Set widget size
- final LinearLayout sizeLayout = layout.findViewById(R.id.watchface_widget_size_layout);
- sizeLayout.setVisibility(View.GONE);
- final EditText widgetWidth = layout.findViewById(R.id.watchface_widget_width);
- if ((widget != null) && (widget.getWidth() >= 0)) {
- widgetWidth.setText(Integer.toString(widget.getWidth()));
- }
- // Populate timezone spinner
- String[] timezonesList = TimeZone.getAvailableIDs();
- final Spinner tzSpinner = layout.findViewById(R.id.watchface_widget_timezone_spinner);
- final LinearLayout timezoneLayout = layout.findViewById(R.id.watchface_widget_timezone_layout);
- timezoneLayout.setVisibility(View.GONE);
- ArrayAdapter widgetTZAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_dropdown_item, timezonesList);
- tzSpinner.setAdapter(widgetTZAdapter);
- if (widget != null) {
- tzSpinner.setSelection(Arrays.asList(timezonesList).indexOf(widget.getExtraConfigString("tzName", "Etc/UTC")));
- } else {
- tzSpinner.setSelection(Arrays.asList(timezonesList).indexOf("Etc/UTC"));
- }
- // Set timezone clock timeout
- final LinearLayout timezoneTimeoutLayout = layout.findViewById(R.id.watchface_widget_timezone_timeout_layout);
- timezoneTimeoutLayout.setVisibility(View.GONE);
- final EditText timezoneTimeout = layout.findViewById(R.id.watchface_widget_timezone_timeout);
- if ((widget != null) && (widget.getExtraConfigInt("timeout_secs", -1) >= 0)) {
- timezoneTimeout.setText(Integer.toString(widget.getExtraConfigInt("timeout_secs", -1)));
- }
- // Set update timeout value
- final LinearLayout updateTimeoutLayout = layout.findViewById(R.id.watchface_widget_update_timeout_layout);
- updateTimeoutLayout.setVisibility(View.GONE);
- final EditText updateTimeout = layout.findViewById(R.id.watchface_widget_update_timeout);
- if ((widget != null) && (widget.getExtraConfigInt("update_timeout", -1) > 0)) {
- updateTimeout.setText(Integer.toString(widget.getExtraConfigInt("update_timeout", -1)));
- }
- final CheckBox timeoutHideText = layout.findViewById(R.id.watchface_widget_timeout_hide_text);
- if (widget != null) {
- timeoutHideText.setChecked(widget.getExtraConfigBoolean("timeout_hide_text", true));
- }
- final CheckBox timeoutShowCircle = layout.findViewById(R.id.watchface_widget_timeout_show_circle);
- if (widget != null) {
- timeoutShowCircle.setChecked(widget.getExtraConfigBoolean("timeout_show_circle", true));
- }
- // Show certain input fields only when the relevant TZ widget is selected
- typeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
- @Override
- public void onItemSelected(AdapterView> parent, View view, int position, long id) {
- String selectedType = widgetTypesArray.get(typeSpinner.getSelectedItemPosition());
- if (selectedType.equals("widget2ndTZ")) {
- timezoneLayout.setVisibility(View.VISIBLE);
- timezoneTimeoutLayout.setVisibility(View.VISIBLE);
- } else {
- timezoneLayout.setVisibility(View.GONE);
- timezoneTimeoutLayout.setVisibility(View.GONE);
- }
- if (selectedType.equals("widgetCustom")) {
- sizeLayout.setVisibility(View.VISIBLE);
- updateTimeoutLayout.setVisibility(View.VISIBLE);
- } else {
- sizeLayout.setVisibility(View.GONE);
- updateTimeoutLayout.setVisibility(View.GONE);
- }
+ int color = 0;
+ if (widgets.size() > 0) {
+ color = widgets.get(0).getColor();
}
- @Override
- public void onNothingSelected(AdapterView> parent) { }
- });
- // Show dialog
- new AlertDialog.Builder(this)
- .setView(layout)
- .setNegativeButton(R.string.fossil_hr_edit_action_delete, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- if (index >= 0) {
- widgets.remove(index);
- renderWatchfacePreview();
- }
- }
- })
- .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- int selectedPosX;
- int selectedPosY;
- try {
- selectedPosX = Integer.parseInt(posX.getText().toString());
- selectedPosY = Integer.parseInt(posY.getText().toString());
- } catch (NumberFormatException e) {
- GB.toast(getString(R.string.watchface_toast_settings_incomplete), Toast.LENGTH_SHORT, GB.WARN);
- LOG.warn("Error parsing input", e);
- return;
- }
- if (selectedPosX < 1) selectedPosX = 1;
- if (selectedPosX > 240) selectedPosX = 240;
- if (selectedPosY < 1) selectedPosY = 1;
- if (selectedPosY > 240) selectedPosY = 240;
- int selectedWidth = 76;
- try {
- selectedWidth = Integer.parseInt(widgetWidth.getText().toString());
- } catch (NumberFormatException e) {
- LOG.warn("Error parsing input", e);
- }
- String selectedType = widgetTypesArray.get(typeSpinner.getSelectedItemPosition());
- String selectedTZ = tzSpinner.getSelectedItem().toString();
- int selectedTZtimeout = Integer.parseInt(timezoneTimeout.getText().toString());
- int selectedUpdateTimeout = 0;
- if (selectedType.equals("widgetCustom")) {
- try {
- selectedUpdateTimeout = Integer.parseInt(updateTimeout.getText().toString());
- } catch (NumberFormatException e) {
- GB.toast(getString(R.string.watchface_toast_settings_incomplete), Toast.LENGTH_SHORT, GB.WARN);
- LOG.warn("Error parsing input", e);
- return;
- }
- }
- boolean selectedTimeoutHideText = timeoutHideText.isChecked();
- boolean selectedTimeoutShowCircle = timeoutShowCircle.isChecked();
- HybridHRWatchfaceWidget widgetConfig;
- if (selectedType.equals("widget2ndTZ")) {
- JSONObject extraConfig = new JSONObject();
- try {
- extraConfig.put("tzName", selectedTZ);
- extraConfig.put("timeout_secs", selectedTZtimeout);
- } catch (JSONException e) {
- LOG.warn("JSON error", e);
- }
- widgetConfig = new HybridHRWatchfaceWidget(selectedType, selectedPosX, selectedPosY, 76, 76, colorSpinner.getSelectedItemPosition(), extraConfig);
- } else if (selectedType.equals("widgetCustom")) {
- JSONObject extraConfig = new JSONObject();
- try {
- extraConfig.put("update_timeout", selectedUpdateTimeout);
- extraConfig.put("timeout_hide_text", selectedTimeoutHideText);
- extraConfig.put("timeout_show_circle", selectedTimeoutShowCircle);
- } catch (JSONException e) {
- LOG.warn("JSON error", e);
- }
- widgetConfig = new HybridHRWatchfaceWidget(selectedType, selectedPosX, selectedPosY, selectedWidth, 76, colorSpinner.getSelectedItemPosition(), extraConfig);
- } else {
- widgetConfig = new HybridHRWatchfaceWidget(selectedType, selectedPosX, selectedPosY, 76, 76, colorSpinner.getSelectedItemPosition(), null);
- }
- if (index >= 0) {
- widgets.set(index, widgetConfig);
- } else {
- widgets.add(widgetConfig);
- }
- renderWatchfacePreview();
- }
- })
- .setTitle(R.string.watchface_dialog_title_add_widget)
- .show();
+ widget = new HybridHRWatchfaceWidget("widgetDate", posX, posY, 76, 76, color, null);
+ }
+ Intent intent = new Intent(this, HybridHRWatchfaceWidgetActivity.class);
+ intent.putExtra("widgetIndex", index);
+ intent.putExtra("widgetSettings", widget);
+ startActivityForResult(intent, CHILD_ACTIVITY_WIDGET);
}
private void showWatchfaceSettingsPopup() {
@@ -771,7 +584,7 @@ public class HybridHRWatchfaceDesignerActivity extends AbstractGBActivity implem
public void run() {
GBApplication.deviceService().onAppDelete(UUID.nameUUIDFromBytes("previewWatchface".getBytes(StandardCharsets.UTF_8)));
}
- }, 10000);
+ }, 15000);
} else {
readyToCloseActivity = true;
final FossilFileReader fossilFile = new FossilFileReader(tempAppFileUri, this);
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceWidget.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceWidget.java
index cd2f879e3..4db6c05e6 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceWidget.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceWidget.java
@@ -20,28 +20,35 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import org.json.JSONObject;
+
import java.io.IOException;
+import java.io.Serializable;
import java.util.LinkedHashMap;
import nodomain.freeyourgadget.gadgetbridge.R;
import static nodomain.freeyourgadget.gadgetbridge.util.BitmapUtil.invertBitmapColors;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-public class HybridHRWatchfaceWidget {
+public class HybridHRWatchfaceWidget implements Serializable {
private String widgetType;
private int posX;
private int posY;
private int width;
private int height;
private int color;
- private JSONObject extraConfig;
+ private String extraConfigJSON;
public static int COLOR_WHITE = 0;
public static int COLOR_BLACK = 1;
+ static HybridHRWidgetPosition[] defaultPositions = new HybridHRWidgetPosition[]{
+ new HybridHRWidgetPosition(120, 58, R.string.watchface_dialog_widget_preset_top),
+ new HybridHRWidgetPosition(182, 120, R.string.watchface_dialog_widget_preset_right),
+ new HybridHRWidgetPosition(120, 182, R.string.watchface_dialog_widget_preset_bottom),
+ new HybridHRWidgetPosition(58, 120, R.string.watchface_dialog_widget_preset_left),
+ };
+
public HybridHRWatchfaceWidget(String widgetType, int posX, int posY, int width, int height, int color, JSONObject extraConfig) {
this.widgetType = widgetType;
this.posX = posX;
@@ -49,7 +56,11 @@ public class HybridHRWatchfaceWidget {
this.width = width;
this.height = height;
this.color = color;
- this.extraConfig = extraConfig;
+ try {
+ this.extraConfigJSON = extraConfig.toString();
+ } catch (Exception e) {
+ this.extraConfigJSON = "{}";
+ }
}
public static LinkedHashMap getAvailableWidgetTypes(Context context) {
@@ -67,10 +78,14 @@ public class HybridHRWatchfaceWidget {
return widgetTypes;
}
+ public void setWidgetType(String widgetType) {
+ this.widgetType = widgetType;
+ }
public String getWidgetType() {
return widgetType;
}
+
public Bitmap getPreviewImage(Context context) throws IOException {
Bitmap preview = BitmapFactory.decodeStream(context.getAssets().open("fossil_hr/" + widgetType + "_preview.png"));
if (color == COLOR_WHITE) {
@@ -116,24 +131,67 @@ public class HybridHRWatchfaceWidget {
}
public int getExtraConfigInt(String name, int fallback) {
- if (extraConfig == null) {
+ try {
+ return new JSONObject(extraConfigJSON).optInt(name, fallback);
+ } catch (Exception e) {
return fallback;
- } else {
- return extraConfig.optInt(name, fallback);
}
}
public String getExtraConfigString(String name, String fallback) {
- if (extraConfig == null) {
+ try {
+ return new JSONObject(extraConfigJSON).optString(name, fallback);
+ } catch (Exception e) {
return fallback;
- } else {
- return extraConfig.optString(name, fallback);
}
}
public Boolean getExtraConfigBoolean(String name, Boolean fallback) {
- if (extraConfig == null) {
+ try {
+ return new JSONObject(extraConfigJSON).optBoolean(name, fallback);
+ } catch (Exception e) {
return fallback;
- } else {
- return extraConfig.optBoolean(name, fallback);
+ }
+ }
+
+ public void setExtraConfigInt(String name, int value) {
+ JSONObject extraConfig;
+ try {
+ extraConfig = new JSONObject(extraConfigJSON);
+ } catch (Exception e) {
+ extraConfig = new JSONObject();
+ }
+ try {
+ extraConfig.put(name, value);
+ extraConfigJSON = extraConfig.toString();
+ } catch (Exception e) {
+ return;
+ }
+ }
+ public void setExtraConfigString(String name, String value) {
+ JSONObject extraConfig;
+ try {
+ extraConfig = new JSONObject(extraConfigJSON);
+ } catch (Exception e) {
+ extraConfig = new JSONObject();
+ }
+ try {
+ extraConfig.put(name, value);
+ extraConfigJSON = extraConfig.toString();
+ } catch (Exception e) {
+ return;
+ }
+ }
+ public void setExtraConfigBoolean(String name, Boolean value) {
+ JSONObject extraConfig;
+ try {
+ extraConfig = new JSONObject(extraConfigJSON);
+ } catch (Exception e) {
+ extraConfig = new JSONObject();
+ }
+ try {
+ extraConfig.put(name, value);
+ extraConfigJSON = extraConfig.toString();
+ } catch (Exception e) {
+ return;
}
}
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceWidgetActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceWidgetActivity.java
new file mode 100644
index 000000000..af811a6a5
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWatchfaceWidgetActivity.java
@@ -0,0 +1,246 @@
+/* Copyright (C) 2022 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;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.preference.EditTextPreference;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.PreferenceCategory;
+import android.preference.PreferenceFragment;
+import android.preference.SwitchPreference;
+import android.view.MenuItem;
+
+import java.util.LinkedHashMap;
+import java.util.TimeZone;
+
+import nodomain.freeyourgadget.gadgetbridge.R;
+import nodomain.freeyourgadget.gadgetbridge.activities.AbstractSettingsActivity;
+
+public class HybridHRWatchfaceWidgetActivity extends AbstractSettingsActivity {
+ private static int widgetIndex;
+ private static HybridHRWatchfaceWidget widget;
+
+ private static LinkedHashMap widgetTypes;
+ private static String[] widgetColors;
+
+ private static final String WIDGET_2NDTZ_DEFAULT_TZ = "Etc/UTC";
+ private static final int WIDGET_2NDTZ_DEFAULT_TIMEOUT = 15;
+ private static final int WIDGET_CUSTOM_DEFAULT_TIMEOUT = 60;
+ private static final Boolean WIDGET_CUSTOM_DEFAULT_HIDE_TEXT = true;
+ private static final Boolean WIDGET_CUSTOM_DEFAULT_SHOW_CIRCLE = true;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Intent intent = getIntent();
+ Bundle bundle = intent.getExtras();
+ if (bundle != null) {
+ widgetIndex = (int) bundle.getSerializable("widgetIndex");
+ widget = (HybridHRWatchfaceWidget) bundle.getSerializable("widgetSettings");
+ } else {
+ throw new IllegalArgumentException("Must provide a widget object when invoking this activity");
+ }
+
+ getFragmentManager().beginTransaction().replace(android.R.id.content, new HybridHRWatchfaceWidgetFragment()).commit();
+ }
+
+ @Override
+ public void onBackPressed() {
+ // Hardware back button
+ Intent output = new Intent();
+ output.putExtra("widgetIndex", widgetIndex);
+ output.putExtra("widgetSettings", widget);
+ setResult(RESULT_OK, output);
+ finish();
+ super.onBackPressed();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ // Action bar back button
+ Intent output = new Intent();
+ output.putExtra("widgetIndex", widgetIndex);
+ output.putExtra("widgetSettings", widget);
+ setResult(RESULT_OK, output);
+ finish();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ public static class HybridHRWatchfaceWidgetFragment extends PreferenceFragment implements Preference.OnPreferenceChangeListener
+ {
+ @Override
+ public void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ addPreferencesFromResource(R.xml.fossil_hr_widget_settings);
+
+ widgetTypes = HybridHRWatchfaceWidget.getAvailableWidgetTypes(getContext());
+ ListPreference widgetType = (ListPreference) findPreference("pref_hybridhr_widget_type");
+ widgetType.setOnPreferenceChangeListener(this);
+ widgetType.setEntries(widgetTypes.values().toArray(new String[0]));
+ widgetType.setEntryValues(widgetTypes.keySet().toArray(new String[0]));
+ widgetType.setValue(widget.getWidgetType());
+ widgetType.setSummary(widgetTypes.get(widget.getWidgetType()));
+ updateEnabledCategories();
+
+ widgetColors = new String[]{getString(R.string.watchface_dialog_widget_color_white), getString(R.string.watchface_dialog_widget_color_black)};
+ ListPreference widgetColor = (ListPreference) findPreference("pref_hybridhr_widget_color");
+ widgetColor.setOnPreferenceChangeListener(this);
+ widgetColor.setEntries(widgetColors);
+ widgetColor.setEntryValues(new String[]{"0", "1"});
+ widgetColor.setValueIndex(widget.getColor());
+ widgetColor.setSummary(widgetColors[widget.getColor()]);
+
+ EditTextPreference posX = (EditTextPreference) findPreference("pref_hybridhr_widget_pos_x");
+ posX.setOnPreferenceChangeListener(this);
+ posX.setText(Integer.toString(widget.getPosX()));
+ posX.setSummary(Integer.toString(widget.getPosX()));
+
+ EditTextPreference posY = (EditTextPreference) findPreference("pref_hybridhr_widget_pos_y");
+ posY.setOnPreferenceChangeListener(this);
+ posY.setText(Integer.toString(widget.getPosY()));
+ posY.setSummary(Integer.toString(widget.getPosY()));
+
+ LinkedHashMap positionPresets = new LinkedHashMap();
+ for (final HybridHRWidgetPosition position : widget.defaultPositions) {
+ positionPresets.put(String.valueOf(position.hintStringResource), getString(position.hintStringResource));
+ }
+ ListPreference widgetPositionPreset = (ListPreference) findPreference("pref_hybridhr_widget_pos_preset");
+ widgetPositionPreset.setOnPreferenceChangeListener(this);
+ widgetPositionPreset.setEntries(positionPresets.values().toArray(new String[0]));
+ widgetPositionPreset.setEntryValues(positionPresets.keySet().toArray(new String[0]));
+
+ String[] timezonesList = TimeZone.getAvailableIDs();
+ ListPreference widgetTimezone = (ListPreference) findPreference("pref_hybridhr_widget_timezone");
+ widgetTimezone.setOnPreferenceChangeListener(this);
+ widgetTimezone.setEntries(timezonesList);
+ widgetTimezone.setEntryValues(timezonesList);
+ widgetTimezone.setValue(widget.getExtraConfigString("tzName", WIDGET_2NDTZ_DEFAULT_TZ));
+ widgetTimezone.setSummary(widget.getExtraConfigString("tzName", WIDGET_2NDTZ_DEFAULT_TZ));
+
+ EditTextPreference timezoneDuration = (EditTextPreference) findPreference("pref_hybridhr_widget_timezone_timeout");
+ timezoneDuration.setOnPreferenceChangeListener(this);
+ timezoneDuration.setText(Integer.toString(widget.getExtraConfigInt("timeout_secs", WIDGET_2NDTZ_DEFAULT_TIMEOUT)));
+ timezoneDuration.setSummary(Integer.toString(widget.getExtraConfigInt("timeout_secs", WIDGET_2NDTZ_DEFAULT_TIMEOUT)));
+
+ EditTextPreference width = (EditTextPreference) findPreference("pref_hybridhr_widget_width");
+ width.setOnPreferenceChangeListener(this);
+ width.setText(Integer.toString(widget.getWidth()));
+ width.setSummary(Integer.toString(widget.getWidth()));
+
+ EditTextPreference customWidgetTimeout = (EditTextPreference) findPreference("pref_hybridhr_widget_custom_timeout");
+ customWidgetTimeout.setOnPreferenceChangeListener(this);
+ customWidgetTimeout.setText(Integer.toString(widget.getExtraConfigInt("update_timeout", WIDGET_CUSTOM_DEFAULT_TIMEOUT)));
+ customWidgetTimeout.setSummary(Integer.toString(widget.getExtraConfigInt("update_timeout", WIDGET_CUSTOM_DEFAULT_TIMEOUT)));
+
+ SwitchPreference customWidgetHideText = (SwitchPreference) findPreference("pref_hybridhr_widget_custom_hide_text");
+ customWidgetHideText.setOnPreferenceChangeListener(this);
+ customWidgetHideText.setChecked(widget.getExtraConfigBoolean("timeout_hide_text", WIDGET_CUSTOM_DEFAULT_HIDE_TEXT));
+
+ SwitchPreference customWidgetShowCircle = (SwitchPreference) findPreference("pref_hybridhr_widget_custom_show_circle");
+ customWidgetShowCircle.setOnPreferenceChangeListener(this);
+ customWidgetShowCircle.setChecked(widget.getExtraConfigBoolean("timeout_show_circle", WIDGET_CUSTOM_DEFAULT_SHOW_CIRCLE));
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ switch (preference.getKey()) {
+ case "pref_hybridhr_widget_type":
+ widget.setWidgetType(newValue.toString());
+ preference.setSummary(widgetTypes.get(widget.getWidgetType()));
+ updateEnabledCategories();
+ if (newValue.toString().equals("widget2ndTZ")) {
+ widget.setExtraConfigString("tzName", widget.getExtraConfigString("tzName", WIDGET_2NDTZ_DEFAULT_TZ));
+ widget.setExtraConfigInt("timeout_secs", widget.getExtraConfigInt("timeout_secs", WIDGET_2NDTZ_DEFAULT_TIMEOUT));
+ } else if (newValue.toString().equals("widgetCustom")) {
+ widget.setExtraConfigInt("update_timeout", widget.getExtraConfigInt("update_timeout", WIDGET_CUSTOM_DEFAULT_TIMEOUT));
+ widget.setExtraConfigBoolean("timeout_hide_text", widget.getExtraConfigBoolean("timeout_hide_text", WIDGET_CUSTOM_DEFAULT_HIDE_TEXT));
+ widget.setExtraConfigBoolean("timeout_show_circle", widget.getExtraConfigBoolean("timeout_show_circle", WIDGET_CUSTOM_DEFAULT_SHOW_CIRCLE));
+ }
+ break;
+ case "pref_hybridhr_widget_color":
+ widget.setColor(Integer.parseInt(newValue.toString()));
+ preference.setSummary(widgetColors[widget.getColor()]);
+ break;
+ case "pref_hybridhr_widget_pos_x":
+ widget.setPosX(Integer.parseInt(newValue.toString()));
+ preference.setSummary(newValue.toString());
+ break;
+ case "pref_hybridhr_widget_pos_y":
+ widget.setPosY(Integer.parseInt(newValue.toString()));
+ preference.setSummary(newValue.toString());
+ break;
+ case "pref_hybridhr_widget_pos_preset":
+ LinkedHashMap positionPresets = new LinkedHashMap();
+ for (final HybridHRWidgetPosition position : widget.defaultPositions){
+ if (newValue.toString().equals(String.valueOf(position.hintStringResource))) {
+ widget.setPosX(position.posX);
+ widget.setPosY(position.posY);
+ EditTextPreference prefPosX = (EditTextPreference) findPreference("pref_hybridhr_widget_pos_x");
+ EditTextPreference prefPosY = (EditTextPreference) findPreference("pref_hybridhr_widget_pos_y");
+ prefPosX.setSummary(String.valueOf(position.posX));
+ prefPosY.setSummary(String.valueOf(position.posY));
+ }
+ }
+ break;
+ case "pref_hybridhr_widget_timezone":
+ widget.setExtraConfigString("tzName", newValue.toString());
+ preference.setSummary(newValue.toString());
+ break;
+ case "pref_hybridhr_widget_timezone_timeout":
+ widget.setExtraConfigInt("timeout_secs", Integer.parseInt(newValue.toString()));
+ preference.setSummary(newValue.toString());
+ break;
+ case "pref_hybridhr_widget_width":
+ widget.setWidth(Integer.parseInt(newValue.toString()));
+ preference.setSummary(newValue.toString());
+ break;
+ case "pref_hybridhr_widget_custom_timeout":
+ widget.setExtraConfigInt("update_timeout", Integer.parseInt(newValue.toString()));
+ preference.setSummary(newValue.toString());
+ break;
+ case "pref_hybridhr_widget_custom_hide_text":
+ widget.setExtraConfigBoolean("timeout_hide_text", (boolean) newValue);
+ break;
+ case "pref_hybridhr_widget_custom_show_circle":
+ widget.setExtraConfigBoolean("timeout_show_circle", (boolean) newValue);
+ break;
+ }
+ return true;
+ }
+
+ private void updateEnabledCategories() {
+ PreferenceCategory cat2ndTZ = (PreferenceCategory) findPreference("widget_pref_category_2nd_tz_widget");
+ if (widget.getWidgetType().equals("widget2ndTZ")) {
+ cat2ndTZ.setEnabled(true);
+ } else {
+ cat2ndTZ.setEnabled(false);
+ }
+ PreferenceCategory catCustom = (PreferenceCategory) findPreference("widget_pref_category_custom_widget");
+ if (widget.getWidgetType().equals("widgetCustom")) {
+ catCustom.setEnabled(true);
+ } else {
+ catCustom.setEnabled(false);
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWidgetPosition.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWidgetPosition.java
new file mode 100644
index 000000000..fc4880a0f
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/HybridHRWidgetPosition.java
@@ -0,0 +1,27 @@
+/* Copyright (C) 2021 Daniel Dakhno
+
+ 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;
+
+class HybridHRWidgetPosition{
+ int posX, posY, hintStringResource;
+
+ public HybridHRWidgetPosition(int posX, int posY, int hintStringResource) {
+ this.posX = posX;
+ this.posY = posY;
+ this.hintStringResource = hintStringResource;
+ }
+}
diff --git a/app/src/main/res/layout/dialog_hybridhr_watchface_widget.xml b/app/src/main/res/layout/dialog_hybridhr_watchface_widget.xml
deleted file mode 100644
index dd7ee7cb4..000000000
--- a/app/src/main/res/layout/dialog_hybridhr_watchface_widget.xml
+++ /dev/null
@@ -1,161 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 96f31ed26..0eed3d09f 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1433,8 +1433,6 @@
Add widget
Watchface settings
Set watchface name
- Settings incomplete, widget not added
- Add widget
Date
Weather
Steps
@@ -1442,28 +1440,34 @@
Preview on watch
Save and apply
Edit
- Type:
- X coordinate (max 240):
- Y coordinate (max 240):
- Position presets:
+ Generic
+ Position
+ 2nd timezone widget
+ Custom widget
+ Type
+ X coordinate (max 240)
+ Y coordinate (max 240)
+ Position presets
Top
Bottom
Left
Right
Watchface designer
- Color:
+ Color
White
Black
Watchface settings
+ Widget settings
+ Widget width (in pixels)
Display refresh timeout
- Full refresh (in minutes):
- Partial refresh (in minutes):
+ Full refresh (in minutes)
+ Partial refresh (in minutes)
Wrist flick
(to disable completely, enable relative movement and set all values to 0)
- Move hands relative to time:
- Hour hand (-360 to 360):
- Minute hand (-360 to 360):
- Duration (in ms):
+ Move hands relative to time
+ Hour hand (-360 to 360)
+ Minute hand (-360 to 360)
+ Duration (in ms)
A watchface with this name already exists in the cache. Do you want to overwrite it?
Upload of the watchface failed. Please try again.
Battery
@@ -1651,11 +1655,11 @@
Playback Control
Volume Control
Custom widget
- Time zone:
- Clock visibility duration (in seconds):
- Update timeout in minutes:
- Hide text on timeout:
- Show circle on timeout:
+ Time zone
+ Clock visibility duration (in seconds)
+ Update timeout in minutes
+ Hide text on timeout
+ Show circle on timeout
Enable on-device pairing confirmation
On-device pairing confirmations can get annoying. Disabling them might lose you functionality.
VESC
@@ -1695,7 +1699,6 @@
Menu
Some buttons cannot be configured because their functions are hard-coded in the watch firmware.\n\nWarning: long-pressing the upper button when a watchface from the official Fossil app is installed will also toggle between showing/hiding widgets.
- Width:
OpenTracks package name
Used for starting/stopping GPS track recording in external fitness app.
pre-setting position to %s
diff --git a/app/src/main/res/xml/fossil_hr_widget_settings.xml b/app/src/main/res/xml/fossil_hr_widget_settings.xml
new file mode 100644
index 000000000..28237547d
--- /dev/null
+++ b/app/src/main/res/xml/fossil_hr_widget_settings.xml
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file