2024-01-10 18:54:00 +01:00
|
|
|
/* Copyright (C) 2023-2024 José Rebelo
|
2023-12-11 23:00:16 +01:00
|
|
|
|
|
|
|
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
|
2024-01-10 18:54:00 +01:00
|
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
2023-12-11 23:00:16 +01:00
|
|
|
package nodomain.freeyourgadget.gadgetbridge.activities.widgets;
|
|
|
|
|
|
|
|
import android.app.Activity;
|
|
|
|
import android.os.Bundle;
|
|
|
|
import android.view.MenuItem;
|
|
|
|
import android.view.View;
|
|
|
|
import android.widget.ArrayAdapter;
|
|
|
|
import android.widget.TextView;
|
|
|
|
import android.widget.Toast;
|
|
|
|
|
|
|
|
import androidx.annotation.NonNull;
|
|
|
|
|
|
|
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
|
|
|
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
|
|
|
|
|
|
|
import org.slf4j.Logger;
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBActivity;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.capabilities.widgets.WidgetLayout;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.capabilities.widgets.WidgetManager;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.capabilities.widgets.WidgetPart;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.capabilities.widgets.WidgetPartSubtype;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.capabilities.widgets.WidgetScreen;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.capabilities.widgets.WidgetType;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
|
|
|
|
|
|
|
public class WidgetScreenDetailsActivity extends AbstractGBActivity {
|
|
|
|
private static final Logger LOG = LoggerFactory.getLogger(WidgetScreenDetailsActivity.class);
|
|
|
|
|
|
|
|
private WidgetScreen widgetScreen;
|
|
|
|
private WidgetManager widgetManager;
|
|
|
|
|
|
|
|
private View cardWidgetTopLeft;
|
|
|
|
private View cardWidgetTopRight;
|
|
|
|
private View cardWidgetCenter;
|
|
|
|
private View cardWidgetBotLeft;
|
|
|
|
private View cardWidgetBotRight;
|
|
|
|
|
|
|
|
private TextView labelWidgetScreenLayout;
|
|
|
|
private TextView labelWidgetTopLeft;
|
|
|
|
private TextView labelWidgetTopRight;
|
|
|
|
private TextView labelWidgetCenter;
|
|
|
|
private TextView labelWidgetBotLeft;
|
|
|
|
private TextView labelWidgetBotRight;
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
setContentView(R.layout.activity_widget_screen_details);
|
|
|
|
|
|
|
|
final GBDevice device = getIntent().getParcelableExtra(GBDevice.EXTRA_DEVICE);
|
|
|
|
if (device == null) {
|
|
|
|
LOG.error("device must not be null");
|
|
|
|
finish();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
widgetScreen = (WidgetScreen) getIntent().getSerializableExtra(WidgetScreen.EXTRA_WIDGET_SCREEN);
|
|
|
|
if (widgetScreen == null) {
|
|
|
|
GB.toast("No widget screen provided to WidgetScreenDetailsActivity", Toast.LENGTH_LONG, GB.ERROR);
|
|
|
|
finish();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
widgetManager = device.getDeviceCoordinator().getWidgetManager(device);
|
|
|
|
|
|
|
|
// Save button
|
|
|
|
final FloatingActionButton fab = findViewById(R.id.fab_save);
|
|
|
|
fab.setOnClickListener(view -> {
|
|
|
|
for (final WidgetPart part : widgetScreen.getParts()) {
|
|
|
|
if (part.getId() == null) {
|
|
|
|
GB.toast(getBaseContext().getString(R.string.widget_missing_parts), Toast.LENGTH_LONG, GB.WARN);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
updateWidgetScreen();
|
|
|
|
WidgetScreenDetailsActivity.this.setResult(Activity.RESULT_OK);
|
|
|
|
finish();
|
|
|
|
});
|
|
|
|
|
|
|
|
// Layouts
|
|
|
|
final List<WidgetLayout> supportedLayouts = widgetManager.getSupportedWidgetLayouts();
|
|
|
|
final String[] layoutStrings = new String[supportedLayouts.size()];
|
|
|
|
for (int i = 0; i < supportedLayouts.size(); i++) {
|
|
|
|
layoutStrings[i] = getBaseContext().getString(supportedLayouts.get(i).getName());
|
|
|
|
}
|
|
|
|
final ArrayAdapter<String> layoutAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, layoutStrings);
|
|
|
|
|
|
|
|
final View cardLayout = findViewById(R.id.card_layout);
|
|
|
|
cardLayout.setOnClickListener(view -> {
|
|
|
|
new MaterialAlertDialogBuilder(WidgetScreenDetailsActivity.this).setAdapter(layoutAdapter, (dialogInterface, i) -> {
|
|
|
|
if (widgetScreen.getLayout() != supportedLayouts.get(i)) {
|
|
|
|
final ArrayList<WidgetPart> defaultParts = new ArrayList<>();
|
|
|
|
for (final WidgetType widgetType : supportedLayouts.get(i).getWidgetTypes()) {
|
|
|
|
defaultParts.add(new WidgetPart(null, "", widgetType));
|
|
|
|
}
|
|
|
|
widgetScreen.setParts(defaultParts);
|
|
|
|
}
|
|
|
|
widgetScreen.setLayout(supportedLayouts.get(i));
|
|
|
|
updateUiFromWidget();
|
|
|
|
}).setTitle(R.string.widget_layout).create().show();
|
|
|
|
});
|
|
|
|
|
|
|
|
cardWidgetTopLeft = findViewById(R.id.card_widget_top_left);
|
|
|
|
cardWidgetTopRight = findViewById(R.id.card_widget_top_right);
|
|
|
|
cardWidgetCenter = findViewById(R.id.card_widget_center);
|
|
|
|
cardWidgetBotLeft = findViewById(R.id.card_widget_bottom_left);
|
|
|
|
cardWidgetBotRight = findViewById(R.id.card_widget_bottom_right);
|
|
|
|
|
|
|
|
labelWidgetScreenLayout = findViewById(R.id.widget_screen_layout);
|
|
|
|
labelWidgetTopLeft = findViewById(R.id.widget_top_left);
|
|
|
|
labelWidgetTopRight = findViewById(R.id.widget_top_right);
|
|
|
|
labelWidgetCenter = findViewById(R.id.widget_center);
|
|
|
|
labelWidgetBotLeft = findViewById(R.id.widget_bottom_left);
|
|
|
|
labelWidgetBotRight = findViewById(R.id.widget_bottom_right);
|
|
|
|
|
|
|
|
updateUiFromWidget();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onOptionsItemSelected(final MenuItem item) {
|
|
|
|
switch (item.getItemId()) {
|
|
|
|
case android.R.id.home:
|
|
|
|
// back button
|
|
|
|
// TODO confirm when exiting without saving
|
|
|
|
finish();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return super.onOptionsItemSelected(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void updateWidgetScreen() {
|
|
|
|
widgetManager.saveScreen(widgetScreen);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onSaveInstanceState(@NonNull final Bundle state) {
|
|
|
|
super.onSaveInstanceState(state);
|
|
|
|
state.putSerializable("widgetScreen", widgetScreen);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onRestoreInstanceState(@NonNull final Bundle savedInstanceState) {
|
|
|
|
super.onRestoreInstanceState(savedInstanceState);
|
|
|
|
widgetScreen = (WidgetScreen) savedInstanceState.getSerializable("widgetScreen");
|
|
|
|
updateUiFromWidget();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void updateUiFromWidget() {
|
|
|
|
labelWidgetScreenLayout.setText(widgetScreen.getLayout().getName());
|
|
|
|
|
|
|
|
switch (widgetScreen.getLayout()) {
|
|
|
|
case TOP_1_BOT_2:
|
|
|
|
updateWidget(cardWidgetTopLeft, labelWidgetTopLeft, -1);
|
|
|
|
updateWidget(cardWidgetTopRight, labelWidgetTopRight, -1);
|
|
|
|
updateWidget(cardWidgetCenter, labelWidgetCenter, 0);
|
|
|
|
updateWidget(cardWidgetBotLeft, labelWidgetBotLeft, 1);
|
|
|
|
updateWidget(cardWidgetBotRight, labelWidgetBotRight, 2);
|
|
|
|
break;
|
|
|
|
case TOP_2_BOT_1:
|
|
|
|
updateWidget(cardWidgetTopLeft, labelWidgetTopLeft, 0);
|
|
|
|
updateWidget(cardWidgetTopRight, labelWidgetTopRight, 1);
|
|
|
|
updateWidget(cardWidgetCenter, labelWidgetCenter, 2);
|
|
|
|
updateWidget(cardWidgetBotLeft, labelWidgetBotLeft, -1);
|
|
|
|
updateWidget(cardWidgetBotRight, labelWidgetBotRight, -1);
|
|
|
|
break;
|
|
|
|
case TOP_2_BOT_2:
|
|
|
|
updateWidget(cardWidgetTopLeft, labelWidgetTopLeft, 0);
|
|
|
|
updateWidget(cardWidgetTopRight, labelWidgetTopRight, 1);
|
|
|
|
updateWidget(cardWidgetCenter, labelWidgetCenter, -1);
|
|
|
|
updateWidget(cardWidgetBotLeft, labelWidgetBotLeft, 2);
|
|
|
|
updateWidget(cardWidgetBotRight, labelWidgetBotRight, 3);
|
|
|
|
break;
|
|
|
|
case SINGLE:
|
|
|
|
updateWidget(cardWidgetTopLeft, labelWidgetTopLeft, -1);
|
|
|
|
updateWidget(cardWidgetTopRight, labelWidgetTopRight, -1);
|
|
|
|
updateWidget(cardWidgetCenter, labelWidgetCenter, 0);
|
|
|
|
updateWidget(cardWidgetBotLeft, labelWidgetBotLeft, -1);
|
|
|
|
updateWidget(cardWidgetBotRight, labelWidgetBotRight, -1);
|
|
|
|
break;
|
|
|
|
case TWO:
|
|
|
|
updateWidget(cardWidgetTopLeft, labelWidgetTopLeft, 0);
|
|
|
|
updateWidget(cardWidgetTopRight, labelWidgetTopRight, 1);
|
|
|
|
updateWidget(cardWidgetCenter, labelWidgetCenter, -1);
|
|
|
|
updateWidget(cardWidgetBotLeft, labelWidgetBotLeft, -1);
|
|
|
|
updateWidget(cardWidgetBotRight, labelWidgetBotRight, -1);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw new IllegalStateException("Unknown layout " + widgetScreen.getLayout());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void updateWidget(final View card, final TextView label, final int partIdx) {
|
|
|
|
final boolean validPart = partIdx >= 0 && partIdx < widgetScreen.getParts().size();
|
|
|
|
|
|
|
|
card.setVisibility(validPart ? View.VISIBLE : View.GONE);
|
|
|
|
|
|
|
|
if (!validPart) {
|
|
|
|
card.setOnClickListener(null);
|
|
|
|
label.setText(R.string.not_set);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
final WidgetPart widgetPart = widgetScreen.getParts().get(partIdx);
|
|
|
|
|
|
|
|
if (widgetPart.getId() == null) {
|
|
|
|
label.setText(R.string.not_set);
|
|
|
|
} else {
|
|
|
|
label.setText(widgetPart.getFullName());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Select widget part
|
|
|
|
|
|
|
|
final List<WidgetPart> supportedParts = widgetManager.getSupportedWidgetParts(widgetPart.getType());
|
|
|
|
final String[] layoutStrings = new String[supportedParts.size()];
|
|
|
|
for (int i = 0; i < supportedParts.size(); i++) {
|
|
|
|
layoutStrings[i] = supportedParts.get(i).getName();
|
|
|
|
}
|
|
|
|
final ArrayAdapter<String> partAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, layoutStrings);
|
|
|
|
|
|
|
|
card.setOnClickListener(view -> {
|
|
|
|
new MaterialAlertDialogBuilder(WidgetScreenDetailsActivity.this).setAdapter(partAdapter, (dialogInterface, i) -> {
|
|
|
|
final WidgetPart selectedPart = supportedParts.get(i);
|
|
|
|
|
|
|
|
final List<WidgetPartSubtype> supportedSubtypes = selectedPart.getSupportedSubtypes();
|
|
|
|
if (supportedSubtypes.isEmpty()) {
|
|
|
|
// No subtypes selected
|
|
|
|
|
|
|
|
widgetScreen.getParts().set(partIdx, selectedPart);
|
|
|
|
updateUiFromWidget();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the selected part supports subtypes, the user must select a subtype
|
|
|
|
|
|
|
|
final String[] subtypeStrings = new String[supportedSubtypes.size()];
|
|
|
|
for (int j = 0; j < supportedSubtypes.size(); j++) {
|
|
|
|
subtypeStrings[j] = supportedSubtypes.get(j).getName();
|
|
|
|
}
|
|
|
|
final ArrayAdapter<String> subtypesAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, subtypeStrings);
|
|
|
|
|
|
|
|
new MaterialAlertDialogBuilder(WidgetScreenDetailsActivity.this).setAdapter(subtypesAdapter, (dialogInterface1, j) -> {
|
|
|
|
final WidgetPartSubtype selectedSubtype = supportedSubtypes.get(j);
|
|
|
|
selectedPart.setSubtype(selectedSubtype);
|
|
|
|
widgetScreen.getParts().set(partIdx, selectedPart);
|
|
|
|
updateUiFromWidget();
|
|
|
|
}).setTitle(R.string.widget_subtype).create().show();
|
|
|
|
}).setTitle(R.string.widget).create().show();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|