Merge pull request #11410 from osmandapp/srtmf_dialogs_fixes

Refactoring SRTMf download ui
This commit is contained in:
Vitaliy 2021-04-18 23:34:17 +03:00 committed by GitHub
commit 6bf7da4290
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 1320 additions and 923 deletions

View file

@ -5,8 +5,11 @@ import net.osmand.data.QuadRect;
import net.osmand.util.Algorithms;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
public class WorldRegion implements Serializable {
@ -212,4 +215,22 @@ public class WorldRegion implements Serializable {
}
return false;
}
public static List<WorldRegion> removeDuplicates(List<WorldRegion> regions) {
List<WorldRegion> copy = new ArrayList<>(regions);
Set<WorldRegion> duplicates = new HashSet<>();
for (int i = 0; i < copy.size() - 1; i++) {
WorldRegion r1 = copy.get(i);
for (int j = i + 1; j < copy.size(); j++) {
WorldRegion r2 = copy.get(j);
if (r1.containsRegion(r2)) {
duplicates.add(r2);
} else if (r2.containsRegion(r1)) {
duplicates.add(r1);
}
}
}
copy.removeAll(duplicates);
return copy;
}
}

View file

@ -31,7 +31,7 @@
tools:text="Some title" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/description"
android:id="@+id/title_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/title"
@ -61,7 +61,25 @@
</RelativeLayout>
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/additional_description"
android:id="@+id/primary_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dialog_content_margin"
android:letterSpacing="@dimen/description_letter_spacing"
android:orientation="vertical"
android:paddingStart="@dimen/content_padding"
android:paddingLeft="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
android:visibility="gone"
app:typeface="@string/font_roboto_regular"
tools:text="@string/srtm_download_single_help_message"
tools:visibility="visible" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/secondary_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/content_padding_small"

View file

@ -13,6 +13,7 @@ import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.SQLiteTileSource;
import net.osmand.plus.Version;
import net.osmand.plus.download.SrtmDownloadItem;
import net.osmand.plus.download.ui.AbstractLoadLocalIndexTask;
import net.osmand.plus.voice.JSMediaCommandPlayerImpl;
import net.osmand.plus.voice.JSTTSCommandPlayerImpl;
@ -333,8 +334,7 @@ public class LocalIndexHelper {
if (mapFile.isFile() && mapFile.getName().endsWith(IndexConstants.BINARY_MAP_INDEX_EXT)) {
String fileName = mapFile.getName();
LocalIndexType lt = LocalIndexType.MAP_DATA;
if (fileName.endsWith(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)
|| fileName.endsWith(IndexConstants.BINARY_SRTM_FEET_MAP_INDEX_EXT)) {
if (SrtmDownloadItem.isSrtmFile(fileName)) {
lt = LocalIndexType.SRTM_DATA;
} else if (fileName.endsWith(IndexConstants.BINARY_WIKI_MAP_INDEX_EXT)) {
lt = LocalIndexType.WIKI_DATA;

View file

@ -0,0 +1,80 @@
package net.osmand.plus.base;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentManager;
import net.osmand.AndroidUtils;
import net.osmand.plus.R;
import net.osmand.plus.widgets.MultiStateToggleButton.RadioItem;
import java.util.Collections;
import java.util.List;
public class ModeSelectionBottomSheet extends SelectionBottomSheet {
public static final String TAG = ModeSelectionBottomSheet.class.getSimpleName();
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
showElements(primaryDescription, toggleContainer);
hideElements(checkBox, checkBoxTitle, titleDescription,
secondaryDescription, selectedSize, selectAllButton);
}
@Override
protected void updateItemView(SelectableItem item, View view) {
ImageView ivIcon = view.findViewById(R.id.icon);
TextView tvTitle = view.findViewById(R.id.title);
TextView tvDescr = view.findViewById(R.id.description);
Drawable icon = uiUtilities.getIcon(item.getIconId(), activeColorRes);
ivIcon.setImageDrawable(icon);
tvTitle.setText(item.getTitle());
tvDescr.setText(item.getDescription());
tvDescr.setTextColor(ContextCompat.getColor(app, AndroidUtils.getSecondaryTextColorId(nightMode)));
}
@Override
protected int getItemLayoutId() {
return R.layout.bottom_sheet_item_with_descr_56dp;
}
public void setItem(SelectableItem item) {
setItems(Collections.singletonList(item));
}
@NonNull
@Override
public List<SelectableItem> getSelectedItems() {
return allItems;
}
@Override
protected boolean shouldShowDivider() {
return false;
}
public static ModeSelectionBottomSheet showInstance(@NonNull AppCompatActivity activity,
@NonNull SelectableItem previewItem,
@NonNull List<RadioItem> radioItems,
boolean usedOnMap) {
ModeSelectionBottomSheet fragment = new ModeSelectionBottomSheet();
fragment.setUsedOnMap(usedOnMap);
fragment.setModes(radioItems);
fragment.setItems(Collections.singletonList(previewItem));
FragmentManager fm = activity.getSupportFragmentManager();
fragment.show(fm, TAG);
return fragment;
}
}

View file

@ -0,0 +1,180 @@
package net.osmand.plus.base;
import android.content.res.ColorStateList;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.core.widget.CompoundButtonCompat;
import androidx.fragment.app.FragmentManager;
import net.osmand.AndroidUtils;
import net.osmand.plus.R;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.util.Algorithms;
import java.util.ArrayList;
import java.util.List;
import static net.osmand.view.ThreeStateCheckbox.State.CHECKED;
import static net.osmand.view.ThreeStateCheckbox.State.MISC;
import static net.osmand.view.ThreeStateCheckbox.State.UNCHECKED;
public class MultipleSelectionBottomSheet extends SelectionBottomSheet {
public static final String TAG = MultipleSelectionBottomSheet.class.getSimpleName();
private final List<SelectableItem> selectedItems = new ArrayList<>();
private SelectionUpdateListener selectionUpdateListener;
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
selectAllButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
checkBox.performClick();
boolean checked = checkBox.getState() == CHECKED;
if (checked) {
selectedItems.addAll(allItems);
} else {
selectedItems.clear();
}
onSelectedItemsChanged();
updateItemsSelection(checked);
}
});
}
@Override
protected boolean shouldShowDivider() {
return true;
}
@Override
protected void updateItemView(final SelectableItem item, View view) {
boolean checked = selectedItems.contains(item);
ImageView imageView = view.findViewById(R.id.icon);
TextView title = view.findViewById(R.id.title);
TextView description = view.findViewById(R.id.description);
final CheckBox checkBox = view.findViewById(R.id.compound_button);
AndroidUiHelper.setVisibility(View.VISIBLE, imageView, title, description, checkBox);
checkBox.setChecked(checked);
CompoundButtonCompat.setButtonTintList(checkBox, AndroidUtils.createCheckedColorStateList(app, secondaryColorRes, activeColorRes));
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
boolean checked = !checkBox.isChecked();
checkBox.setChecked(checked);
if (checked) {
selectedItems.add(item);
} else {
selectedItems.remove(item);
}
onSelectedItemsChanged();
}
});
title.setText(item.getTitle());
description.setText(item.getDescription());
imageView.setImageDrawable(uiUtilities.getIcon(item.getIconId(), activeColorRes));
}
@Override
protected int getItemLayoutId() {
return R.layout.bottom_sheet_item_with_descr_and_checkbox_56dp;
}
@Override
protected void notifyUiInitialized() {
onSelectedItemsChanged();
super.notifyUiInitialized();
}
private void onSelectedItemsChanged() {
updateSelectAllButton();
updateSelectedSizeView();
updateApplyButtonEnable();
if (selectionUpdateListener != null) {
selectionUpdateListener.onSelectionUpdate();
}
}
private void updateSelectAllButton() {
String checkBoxTitle;
if (Algorithms.isEmpty(selectedItems)) {
checkBox.setState(UNCHECKED);
checkBoxTitle = getString(R.string.shared_string_select_all);
} else {
checkBox.setState(selectedItems.containsAll(allItems) ? CHECKED : MISC);
checkBoxTitle = getString(R.string.shared_string_deselect_all);
}
int checkBoxColor = checkBox.getState() == UNCHECKED ? secondaryColorRes : activeColorRes;
CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, checkBoxColor)));
this.checkBoxTitle.setText(checkBoxTitle);
}
private void updateSelectedSizeView() {
String selected = String.valueOf(selectedItems.size());
String all = String.valueOf(allItems.size());
selectedSize.setText(getString(R.string.ltr_or_rtl_combine_via_slash, selected, all));
}
private void updateApplyButtonEnable() {
boolean noEmptySelection = !Algorithms.isEmpty(selectedItems);
rightButton.setEnabled(noEmptySelection);
}
private void updateItemsSelection(boolean checked) {
for (SelectableItem item : allItems) {
View v = listViews.get(item);
CheckBox checkBox = v != null ? (CheckBox) v.findViewById(R.id.compound_button) : null;
if (checkBox != null) {
checkBox.setChecked(checked);
}
}
}
protected void setSelectedItems(List<SelectableItem> selected) {
if (!Algorithms.isEmpty(selected)) {
selectedItems.clear();
selectedItems.addAll(selected);
}
}
@NonNull
@Override
public List<SelectableItem> getSelectedItems() {
return selectedItems;
}
public void setSelectionUpdateListener(SelectionUpdateListener selectionUpdateListener) {
this.selectionUpdateListener = selectionUpdateListener;
}
public static MultipleSelectionBottomSheet showInstance(@NonNull AppCompatActivity activity,
@NonNull List<SelectableItem> items,
@Nullable List<SelectableItem> selected,
boolean usedOnMap) {
MultipleSelectionBottomSheet fragment = new MultipleSelectionBottomSheet();
fragment.setUsedOnMap(usedOnMap);
fragment.setItems(items);
fragment.setSelectedItems(selected);
FragmentManager fm = activity.getSupportFragmentManager();
fragment.show(fm, TAG);
return fragment;
}
public interface SelectionUpdateListener {
void onSelectionUpdate();
}
}

View file

@ -0,0 +1,41 @@
package net.osmand.plus.base;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentManager;
import net.osmand.plus.widgets.MultiStateToggleButton.RadioItem;
import java.util.List;
public class MultipleSelectionWithModeBottomSheet extends MultipleSelectionBottomSheet {
public static final String TAG = MultipleSelectionWithModeBottomSheet.class.getSimpleName();
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
showElements(secondaryDescription, toggleContainer, checkBox,
checkBoxTitle, titleDescription, selectedSize, selectAllButton);
}
public static MultipleSelectionWithModeBottomSheet showInstance(@NonNull AppCompatActivity activity,
@NonNull List<SelectableItem> items,
@Nullable List<SelectableItem> selected,
@NonNull List<RadioItem> modes,
boolean usedOnMap) {
MultipleSelectionWithModeBottomSheet fragment = new MultipleSelectionWithModeBottomSheet();
fragment.setUsedOnMap(usedOnMap);
fragment.setItems(items);
fragment.setSelectedItems(selected);
fragment.setModes(modes);
FragmentManager fm = activity.getSupportFragmentManager();
fragment.show(fm, TAG);
return fragment;
}
}

View file

@ -1,462 +0,0 @@
package net.osmand.plus.base;
import android.content.res.ColorStateList;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.core.widget.CompoundButtonCompat;
import androidx.fragment.app.FragmentManager;
import net.osmand.AndroidUtils;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton;
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton.Builder;
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription;
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.SimpleDividerItem;
import net.osmand.plus.download.MultipleIndexesUiHelper.SelectedItemsListener;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.widgets.MultiStateToggleButton;
import net.osmand.plus.widgets.MultiStateToggleButton.OnRadioItemClickListener;
import net.osmand.plus.widgets.MultiStateToggleButton.RadioItem;
import net.osmand.util.Algorithms;
import net.osmand.view.ThreeStateCheckbox;
import java.util.ArrayList;
import java.util.List;
import static net.osmand.view.ThreeStateCheckbox.State.CHECKED;
import static net.osmand.view.ThreeStateCheckbox.State.MISC;
import static net.osmand.view.ThreeStateCheckbox.State.UNCHECKED;
public class SelectMultipleItemsBottomSheet extends MenuBottomSheetDialogFragment {
public static final String TAG = SelectMultipleItemsBottomSheet.class.getSimpleName();
private OsmandApplication app;
private UiUtilities uiUtilities;
private TextView title;
private TextView description;
private TextView applyButtonTitle;
private TextView checkBoxTitle;
private TextView selectedSize;
private ThreeStateCheckbox checkBox;
private int sizeAboveList = 0;
private int activeColorRes;
private int secondaryColorRes;
private String addDescriptionText;
private String leftRadioButtonText;
private String rightRadioButtonText;
private boolean customOptionsVisible;
private boolean leftButtonSelected;
private final List<SelectableItem> allItems = new ArrayList<>();
private final List<SelectableItem> selectedItems = new ArrayList<>();
private SelectionUpdateListener selectionUpdateListener;
private OnApplySelectionListener onApplySelectionListener;
private OnRadioButtonSelectListener onRadioButtonSelectListener;
private SelectedItemsListener selectedItemsListener;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View mainView = super.onCreateView(inflater, parent, savedInstanceState);
onSelectedItemsChanged();
return mainView;
}
@Override
public void createMenuItems(Bundle savedInstanceState) {
app = requiredMyApplication();
uiUtilities = app.getUIUtilities();
activeColorRes = nightMode ? R.color.icon_color_active_dark : R.color.icon_color_active_light;
secondaryColorRes = nightMode ? R.color.icon_color_secondary_dark : R.color.icon_color_secondary_light;
items.add(createTitleItem());
items.add(new SimpleDividerItem(app));
sizeAboveList = items.size();
createListItems();
}
@Override
public void onPause() {
super.onPause();
if (requireActivity().isChangingConfigurations()) {
dismiss();
}
}
private BaseBottomSheetItem createTitleItem() {
LayoutInflater themedInflater = UiUtilities.getInflater(requireContext(), nightMode);
View view = themedInflater.inflate(R.layout.settings_group_title, null);
checkBox = view.findViewById(R.id.check_box);
checkBoxTitle = view.findViewById(R.id.check_box_title);
description = view.findViewById(R.id.description);
selectedSize = view.findViewById(R.id.selected_size);
title = view.findViewById(R.id.title);
View selectAllButton = view.findViewById(R.id.select_all_button);
TextView addDescription = view.findViewById(R.id.additional_description);
LinearLayout customRadioButtons = view.findViewById(R.id.custom_radio_buttons);
if (!isMultipleItem()) {
AndroidUiHelper.setVisibility(View.GONE, description, selectedSize, selectAllButton);
} else {
selectAllButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
checkBox.performClick();
boolean checked = checkBox.getState() == CHECKED;
if (checked) {
selectedItems.addAll(allItems);
} else {
selectedItems.clear();
}
onSelectedItemsChanged();
updateItems(checked);
}
});
}
if (!Algorithms.isEmpty(addDescriptionText)) {
addDescription.setText(addDescriptionText);
AndroidUiHelper.setVisibility(View.VISIBLE, addDescription);
}
if (customOptionsVisible) {
AndroidUiHelper.setVisibility(View.VISIBLE, customRadioButtons);
RadioItem leftRadioButton = new RadioItem(leftRadioButtonText);
RadioItem rightRadioButton = new RadioItem(rightRadioButtonText);
MultiStateToggleButton toggleButtons =
new MultiStateToggleButton(app, customRadioButtons, nightMode);
toggleButtons.setItems(leftRadioButton, rightRadioButton);
toggleButtons.updateView(true);
leftRadioButton.setOnClickListener(new OnRadioItemClickListener() {
@Override
public boolean onRadioItemClick(RadioItem radioItem, View view) {
onRadioButtonSelectListener.onSelect(leftButtonSelected = true);
updateSelectedSizeView();
updateSelectAllButton();
updateApplyButtonEnable();
return true;
}
});
rightRadioButton.setOnClickListener(new OnRadioItemClickListener() {
@Override
public boolean onRadioItemClick(RadioItem radioItem, View view) {
onRadioButtonSelectListener.onSelect(leftButtonSelected = false);
updateSelectedSizeView();
updateSelectAllButton();
updateApplyButtonEnable();
return true;
}
});
toggleButtons.setSelectedItem(leftButtonSelected ? leftRadioButton : rightRadioButton);
}
return new SimpleBottomSheetItem.Builder().setCustomView(view).create();
}
private void createListItems() {
if (isMultipleItem()) {
for (int i = 0; i < allItems.size(); i++) {
final SelectableItem item = allItems.get(i);
boolean checked = selectedItems.contains(item);
final int finalI = i;
items.add(new Builder()
.setChecked(checked)
.setButtonTintList(AndroidUtils.createCheckedColorStateList(app, secondaryColorRes, activeColorRes))
.setDescription(item.description)
.setIcon(uiUtilities.getIcon(item.iconId, activeColorRes))
.setTitle(item.title)
.setLayoutId(R.layout.bottom_sheet_item_with_descr_and_checkbox_56dp)
.setTag(item)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
BottomSheetItemWithCompoundButton item = (BottomSheetItemWithCompoundButton) items.get(finalI + sizeAboveList);
boolean checked = item.isChecked();
item.setChecked(!checked);
SelectableItem tag = (SelectableItem) item.getTag();
if (!checked) {
selectedItems.add(tag);
} else {
selectedItems.remove(tag);
}
onSelectedItemsChanged();
}
})
.create());
}
} else if (allItems.size() == 1) {
final SelectableItem item = allItems.get(0);
items.add(new Builder()
.setDescription(item.description)
.setDescriptionColorId(AndroidUtils.getSecondaryTextColorId(nightMode))
.setIcon(uiUtilities.getIcon(item.iconId, activeColorRes))
.setTitle(item.title)
.setLayoutId(R.layout.bottom_sheet_item_with_descr_56dp)
.setTag(item)
.create());
}
}
private void onSelectedItemsChanged() {
updateSelectAllButton();
updateSelectedSizeView();
updateApplyButtonEnable();
if (selectionUpdateListener != null) {
selectionUpdateListener.onSelectionUpdate();
}
}
private void updateSelectAllButton() {
if (isMultipleItem()) {
String checkBoxTitle;
if (Algorithms.isEmpty(selectedItems)) {
checkBox.setState(UNCHECKED);
checkBoxTitle = getString(R.string.shared_string_select_all);
} else {
checkBox.setState(selectedItems.containsAll(allItems) ? CHECKED : MISC);
checkBoxTitle = getString(R.string.shared_string_deselect_all);
}
int checkBoxColor = checkBox.getState() == UNCHECKED ? secondaryColorRes : activeColorRes;
CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, checkBoxColor)));
this.checkBoxTitle.setText(checkBoxTitle);
}
}
private void updateSelectedSizeView() {
if (isMultipleItem()) {
String selected = String.valueOf(selectedItems.size());
String all = String.valueOf(allItems.size());
selectedSize.setText(getString(R.string.ltr_or_rtl_combine_via_slash, selected, all));
}
}
private void updateApplyButtonEnable() {
rightButton.setEnabled(!Algorithms.isEmpty(selectedItems));
}
private void updateItems(boolean checked) {
for (BaseBottomSheetItem item : items) {
if (item instanceof BottomSheetItemWithCompoundButton) {
((BottomSheetItemWithCompoundButton) item).setChecked(checked);
}
}
}
public void setItems(List<SelectableItem> allItems) {
this.allItems.clear();
if (!Algorithms.isEmpty(allItems)) {
this.allItems.addAll(allItems);
}
}
private void setSelectedItems(List<SelectableItem> selected) {
this.selectedItems.clear();
if (!Algorithms.isEmpty(selected)) {
/*List<SelectableItem> prevDownloadItems = new ArrayList<>(this.selectedItems);
for (SelectableItem prevDownloadItem : selected) {
Object object = prevDownloadItem.getObject();
if (object instanceof IndexItem && ((IndexItem) object).isDownloaded()) {
prevDownloadItems.add(prevDownloadItem);
}
}
selected.removeAll(prevDownloadItems);*/
this.selectedItems.addAll(selected);
}
}
public void recreateList(List<SelectableItem> allItems) {
setItems(allItems);
if (selectedItemsListener != null) {
setSelectedItems(selectedItemsListener.createSelectedItems(this.allItems, leftButtonSelected));
}
if (items.size() > sizeAboveList) {
for (int i = 0; i < this.allItems.size(); i++) {
SelectableItem item = this.allItems.get(i);
BottomSheetItemWithDescription button = (BottomSheetItemWithDescription) items.get(i + sizeAboveList);
button.setDescription(item.description);
button.setTitle(item.title);
button.setTag(item);
if (isMultipleItem()) {
((BottomSheetItemWithCompoundButton) button).setChecked(selectedItems.contains(item));
}
}
}
}
public boolean isMultipleItem() {
return allItems.size() > 1;
}
public List<SelectableItem> getSelectedItems() {
return selectedItems;
}
public void setConfirmButtonTitle(@NonNull String confirmButtonTitle) {
applyButtonTitle.setText(confirmButtonTitle);
}
public void setTitle(@NonNull String title) {
this.title.setText(title);
}
public void setDescription(@NonNull String description) {
this.description.setText(description);
}
public void setAddDescriptionText(String addDescriptionText) {
this.addDescriptionText = addDescriptionText;
}
public void setLeftRadioButtonText(String leftRadioButtonText) {
this.leftRadioButtonText = leftRadioButtonText;
}
public void setRightRadioButtonText(String rightRadioButtonText) {
this.rightRadioButtonText = rightRadioButtonText;
}
public void setCustomOptionsVisible(boolean customOptionsVisible) {
this.customOptionsVisible = customOptionsVisible;
}
public void setLeftButtonSelected(boolean leftButtonSelected) {
this.leftButtonSelected = leftButtonSelected;
}
public void setSelectionUpdateListener(SelectionUpdateListener selectionUpdateListener) {
this.selectionUpdateListener = selectionUpdateListener;
}
public void setOnApplySelectionListener(OnApplySelectionListener onApplySelectionListener) {
this.onApplySelectionListener = onApplySelectionListener;
}
public void setOnRadioButtonSelectListener(OnRadioButtonSelectListener onRadioButtonSelectListener) {
this.onRadioButtonSelectListener = onRadioButtonSelectListener;
}
public void setSelectedItemsListener(SelectedItemsListener selectedItemsListener) {
this.selectedItemsListener = selectedItemsListener;
}
@Override
protected void setupRightButton() {
super.setupRightButton();
applyButtonTitle = rightButton.findViewById(R.id.button_text);
}
@Override
protected void onRightBottomButtonClick() {
if (onApplySelectionListener != null) {
onApplySelectionListener.onSelectionApplied(selectedItems);
}
dismiss();
}
@Override
protected int getRightBottomButtonTextId() {
return R.string.shared_string_apply;
}
@Override
protected boolean useVerticalButtons() {
return true;
}
public static SelectMultipleItemsBottomSheet showInstance(@NonNull AppCompatActivity activity,
@NonNull List<SelectableItem> items,
@Nullable List<SelectableItem> selected,
boolean usedOnMap) {
SelectMultipleItemsBottomSheet fragment = new SelectMultipleItemsBottomSheet();
fragment.setUsedOnMap(usedOnMap);
fragment.setItems(items);
fragment.setSelectedItems(selected);
FragmentManager fm = activity.getSupportFragmentManager();
fragment.show(fm, TAG);
return fragment;
}
public static SelectMultipleItemsBottomSheet showInstance(@NonNull AppCompatActivity activity,
@NonNull List<SelectableItem> items,
@Nullable List<SelectableItem> selected,
boolean usedOnMap,
String addDescription,
boolean customOptionsVisible,
boolean leftButtonSelected,
String leftRadioButtonText,
String rightRadioButtonText) {
SelectMultipleItemsBottomSheet fragment = new SelectMultipleItemsBottomSheet();
fragment.setUsedOnMap(usedOnMap);
fragment.setItems(items);
fragment.setSelectedItems(selected);
fragment.setAddDescriptionText(addDescription);
fragment.setCustomOptionsVisible(customOptionsVisible);
fragment.setLeftButtonSelected(leftButtonSelected);
fragment.setLeftRadioButtonText(leftRadioButtonText);
fragment.setRightRadioButtonText(rightRadioButtonText);
FragmentManager fm = activity.getSupportFragmentManager();
fragment.show(fm, TAG);
return fragment;
}
public interface SelectionUpdateListener {
void onSelectionUpdate();
}
public interface OnApplySelectionListener {
void onSelectionApplied(List<SelectableItem> selectedItems);
}
public interface OnRadioButtonSelectListener {
void onSelect(boolean leftButton);
}
public static class SelectableItem {
private String title;
private String description;
private int iconId;
private Object object;
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public void setIconId(int iconId) {
this.iconId = iconId;
}
public void setObject(Object object) {
this.object = object;
}
public Object getObject() {
return object;
}
}
}

View file

@ -0,0 +1,289 @@
package net.osmand.plus.base;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.SimpleDividerItem;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.widgets.MultiStateToggleButton;
import net.osmand.plus.widgets.MultiStateToggleButton.RadioItem;
import net.osmand.util.Algorithms;
import net.osmand.view.ThreeStateCheckbox;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class SelectionBottomSheet extends MenuBottomSheetDialogFragment {
protected OsmandApplication app;
protected LayoutInflater inflater;
protected UiUtilities uiUtilities;
protected TextView title;
protected TextView titleDescription;
protected TextView primaryDescription;
protected TextView secondaryDescription;
protected TextView selectedSize;
protected LinearLayout toggleContainer;
protected MultiStateToggleButton radioGroup;
protected View selectAllButton;
protected TextView checkBoxTitle;
protected ThreeStateCheckbox checkBox;
protected LinearLayout listContainer;
protected TextView applyButtonTitle;
protected int activeColorRes;
protected int secondaryColorRes;
private OnUiInitializedListener uiInitializedListener;
private OnApplySelectionListener applySelectionListener;
protected List<SelectableItem> allItems = new ArrayList<>();
protected Map<SelectableItem, View> listViews = new HashMap<>();
private List<RadioItem> modes;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View mainView = super.onCreateView(inflater, parent, savedInstanceState);
createSelectionListIfPossible();
notifyUiInitialized();
return mainView;
}
@Override
public void createMenuItems(Bundle savedInstanceState) {
app = requiredMyApplication();
uiUtilities = app.getUIUtilities();
inflater = UiUtilities.getInflater(requireContext(), nightMode);
activeColorRes = nightMode ? R.color.icon_color_active_dark : R.color.icon_color_active_light;
secondaryColorRes = nightMode ? R.color.icon_color_secondary_dark : R.color.icon_color_secondary_light;
items.add(createHeaderView());
if (shouldShowDivider()) {
items.add(new SimpleDividerItem(app));
}
items.add(createSelectionView());
}
private BaseBottomSheetItem createHeaderView() {
View view = inflater.inflate(R.layout.settings_group_title, null);
title = view.findViewById(R.id.title);
titleDescription = view.findViewById(R.id.title_description);
primaryDescription = view.findViewById(R.id.primary_description);
secondaryDescription = view.findViewById(R.id.secondary_description);
selectedSize = view.findViewById(R.id.selected_size);
toggleContainer = view.findViewById(R.id.custom_radio_buttons);
radioGroup = new MultiStateToggleButton(app, toggleContainer, nightMode);
selectAllButton = view.findViewById(R.id.select_all_button);
checkBoxTitle = view.findViewById(R.id.check_box_title);
checkBox = view.findViewById(R.id.check_box);
if (modes != null) {
radioGroup.setItems(modes);
}
return new SimpleBottomSheetItem.Builder().setCustomView(view).create();
}
private BaseBottomSheetItem createSelectionView() {
Context themedCtx = UiUtilities.getThemedContext(requireContext(), nightMode);
listContainer = new LinearLayout(themedCtx);
listContainer.setLayoutParams(new LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
listContainer.setOrientation(LinearLayout.VERTICAL);
return new SimpleBottomSheetItem.Builder().setCustomView(listContainer).create();
}
public void setTitle(@NonNull String title) {
this.title.setText(title);
}
public void setTitleDescription(@NonNull String description) {
titleDescription.setText(description);
}
public void setPrimaryDescription(@NonNull String description) {
primaryDescription.setText(description);
}
public void setSecondaryDescription(@NonNull String description) {
secondaryDescription.setText(description);
}
public void setApplyButtonTitle(@NonNull String title) {
applyButtonTitle.setText(title);
}
public void setModes(@NonNull List<RadioItem> modes) {
this.modes = modes;
if (radioGroup != null) {
radioGroup.setItems(modes);
}
}
public void setSelectedMode(@NonNull RadioItem mode) {
radioGroup.setSelectedItem(mode);
}
public void setItems(List<SelectableItem> allItems) {
if (!Algorithms.isEmpty(allItems)) {
this.allItems.clear();
this.allItems.addAll(allItems);
createSelectionListIfPossible();
}
}
public void setUiInitializedListener(OnUiInitializedListener uiInitializedListener) {
this.uiInitializedListener = uiInitializedListener;
}
public void setOnApplySelectionListener(OnApplySelectionListener onApplySelectionListener) {
this.applySelectionListener = onApplySelectionListener;
}
private void createSelectionListIfPossible() {
if (listContainer != null && allItems != null) {
recreateList();
}
}
private void recreateList() {
listViews.clear();
listContainer.removeAllViews();
for (SelectableItem item : allItems) {
setupItemView(item, inflater.inflate(getItemLayoutId(), null));
}
}
private void setupItemView(SelectableItem item, View view) {
updateItemView(item, view);
listViews.put(item, view);
listContainer.addView(view);
}
public List<SelectableItem> getAllItems() {
return allItems;
}
@NonNull
public abstract List<SelectableItem> getSelectedItems();
protected abstract void updateItemView(SelectableItem item, View view);
protected abstract int getItemLayoutId();
protected abstract boolean shouldShowDivider();
protected void notifyUiInitialized() {
if (uiInitializedListener != null) {
uiInitializedListener.onUiInitialized();
}
}
protected void showElements(View... views) {
AndroidUiHelper.setVisibility(View.VISIBLE, views);
}
protected void hideElements(View... views) {
AndroidUiHelper.setVisibility(View.GONE, views);
}
@Override
protected void setupRightButton() {
super.setupRightButton();
applyButtonTitle = rightButton.findViewById(R.id.button_text);
}
@Override
protected void onRightBottomButtonClick() {
if (applySelectionListener != null) {
applySelectionListener.onSelectionApplied(getSelectedItems());
}
dismiss();
}
@Override
protected int getRightBottomButtonTextId() {
return R.string.shared_string_apply;
}
@Override
protected boolean useVerticalButtons() {
return true;
}
@Override
public void onPause() {
super.onPause();
if (requireActivity().isChangingConfigurations()) {
dismiss();
}
}
public interface OnUiInitializedListener {
void onUiInitialized();
}
public interface OnApplySelectionListener {
void onSelectionApplied(List<SelectableItem> selectedItems);
}
public static class SelectableItem {
private String title;
private String description;
private int iconId;
private Object object;
public String getTitle() {
return title;
}
public String getDescription() {
return description;
}
public int getIconId() {
return iconId;
}
public Object getObject() {
return object;
}
public void setTitle(String title) {
this.title = title;
}
public void setDescription(String description) {
this.description = description;
}
public void setIconId(int iconId) {
this.iconId = iconId;
}
public void setObject(Object object) {
this.object = object;
}
}
}

View file

@ -29,7 +29,6 @@ import java.util.Map;
import static net.osmand.IndexConstants.BINARY_MAP_INDEX_EXT;
import static net.osmand.plus.activities.LocalIndexHelper.LocalIndexType.SRTM_DATA;
import static net.osmand.plus.download.MultipleIndexesUiHelper.getSRTMExt;
public class DownloadActivityType {
private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd.MM.yyyy", Locale.US);
@ -231,7 +230,7 @@ public class DownloadActivityType {
} else if (FONT_FILE == this) {
return IndexConstants.FONT_INDEX_EXT;
} else if (SRTM_COUNTRY_FILE == this) {
return getSRTMExt(indexItem);
return SrtmDownloadItem.getExtension(indexItem);
} else if (WIKIPEDIA_FILE == this) {
return IndexConstants.BINARY_WIKI_MAP_INDEX_EXT;
} else if (WIKIVOYAGE_FILE == this) {
@ -427,7 +426,7 @@ public class DownloadActivityType {
}
String baseNameWithoutVersion = fileName.substring(0, l);
if (this == SRTM_COUNTRY_FILE) {
return baseNameWithoutVersion + getSRTMExt(item);
return baseNameWithoutVersion + SrtmDownloadItem.getExtension(item);
}
if (this == WIKIPEDIA_FILE) {
return baseNameWithoutVersion + IndexConstants.BINARY_WIKI_MAP_INDEX_EXT;
@ -505,14 +504,4 @@ public class DownloadActivityType {
return fileName;
}
public static boolean isSRTMItem(Object item) {
if (item instanceof IndexItem) {
return ((IndexItem) item).getType() == SRTM_COUNTRY_FILE;
} else if (item instanceof DownloadItem) {
return ((DownloadItem) item).getType() == SRTM_COUNTRY_FILE;
} else if (item instanceof LocalIndexInfo) {
return ((LocalIndexInfo) item).getType() == SRTM_DATA;
}
return false;
}
}

View file

@ -240,9 +240,12 @@ public class DownloadIndexesThread {
}
public void cancelDownload(DownloadItem item) {
if (item instanceof MultipleIndexItem) {
MultipleIndexItem multipleIndexItem = (MultipleIndexItem) item;
cancelDownload(multipleIndexItem.getAllIndexes());
if (item instanceof MultipleDownloadItem) {
MultipleDownloadItem multipleDownloadItem = (MultipleDownloadItem) item;
cancelDownload(multipleDownloadItem.getAllIndexes());
} else if (item instanceof SrtmDownloadItem) {
IndexItem indexItem = ((SrtmDownloadItem) item).getIndexItem();
cancelDownload(indexItem);
} else if (item instanceof IndexItem) {
IndexItem indexItem = (IndexItem) item;
cancelDownload(indexItem);

View file

@ -9,6 +9,7 @@ import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import java.io.File;
import java.text.DateFormat;
import java.util.List;
import java.util.Locale;
@ -55,6 +56,13 @@ public abstract class DownloadItem {
return type.getBasename(this);
}
@NonNull
public abstract List<File> getDownloadedFiles(@NonNull OsmandApplication app);
public abstract boolean isUseAbbreviation();
public abstract String getAbbreviationInScopes(Context ctx);
protected abstract double getSizeToDownloadInMb();
public abstract double getArchiveSizeMB();
@ -69,8 +77,7 @@ public abstract class DownloadItem {
public abstract String getFileName();
@NonNull
public abstract List<File> getDownloadedFiles(@NonNull OsmandApplication app);
public abstract String getDate(@NonNull DateFormat dateFormat, boolean remote);
@NonNull
public static String getFormattedMb(@NonNull Context ctx, double sizeInMb) {

View file

@ -25,12 +25,10 @@ import java.io.InputStream;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static net.osmand.plus.download.DownloadResourceGroup.DownloadResourceGroupType.REGION_MAPS;
@ -117,6 +115,16 @@ public class DownloadResources extends DownloadResourceGroup {
return res;
}
@NonNull
public List<DownloadItem> getDownloadItems(WorldRegion region) {
DownloadResourceGroup group = getRegionMapsGroup(region);
if (group != null) {
return group.getIndividualDownloadItems();
}
return new LinkedList<>();
}
@NonNull
public List<IndexItem> getIndexItems(WorldRegion region) {
if (groupByRegion != null) {
List<IndexItem> res = groupByRegion.get(region);
@ -471,30 +479,60 @@ public class DownloadResources extends DownloadResourceGroup {
addGroup(otherGroup);
createHillshadeSRTMGroups();
collectMultipleIndexesItems();
replaceIndividualSrtmWithGroups(region);
createMultipleDownloadItems(region);
trimEmptyGroups();
updateLoadedFiles();
return true;
}
private void collectMultipleIndexesItems() {
collectMultipleIndexesItems(region);
private void replaceIndividualSrtmWithGroups(@NonNull WorldRegion region) {
DownloadResourceGroup group = getRegionMapsGroup(region);
if (group != null) {
boolean useMetersByDefault = SrtmDownloadItem.shouldUseMetersByDefault(app);
boolean listModified = false;
DownloadActivityType srtmType = DownloadActivityType.SRTM_COUNTRY_FILE;
List<DownloadItem> individualItems = group.getIndividualDownloadItems();
if (isListContainsType(individualItems, srtmType)) {
List<IndexItem> srtmIndexes = new ArrayList<>();
for (DownloadItem item : individualItems) {
if (item.getType() == srtmType && item instanceof IndexItem) {
srtmIndexes.add((IndexItem) item);
}
}
if (srtmIndexes.size() == 2) {
individualItems.removeAll(srtmIndexes);
group.addItem(new SrtmDownloadItem(srtmIndexes, useMetersByDefault));
}
listModified = true;
}
if (listModified) {
sortDownloadItems(individualItems);
}
}
private void collectMultipleIndexesItems(@NonNull WorldRegion region) {
List<WorldRegion> subRegions = region.getSubregions();
if (!Algorithms.isEmpty(subRegions)) {
for (WorldRegion subRegion : subRegions) {
replaceIndividualSrtmWithGroups(subRegion);
}
}
}
private void createMultipleDownloadItems(@NonNull WorldRegion region) {
List<WorldRegion> subRegions = region.getSubregions();
if (Algorithms.isEmpty(subRegions)) return;
DownloadResourceGroup group = getRegionMapsGroup(region);
if (group != null) {
boolean listModified = false;
List<IndexItem> indexesList = group.getIndividualResources();
List<WorldRegion> regionsToCollect = removeDuplicateRegions(subRegions);
List<DownloadItem> downloadItems = group.getIndividualDownloadItems();
List<WorldRegion> uniqueSubRegions = WorldRegion.removeDuplicates(subRegions);
for (DownloadActivityType type : DownloadActivityType.values()) {
if (!doesListContainIndexWithType(indexesList, type)) {
List<IndexItem> indexesFromSubRegions = collectIndexesOfType(regionsToCollect, type);
if (indexesFromSubRegions != null) {
group.addItem(new MultipleIndexItem(region, indexesFromSubRegions, type));
if (!isListContainsType(downloadItems, type)) {
List<DownloadItem> itemsFromSubRegions = collectItemsOfType(uniqueSubRegions, type);
if (itemsFromSubRegions != null) {
group.addItem(new MultipleDownloadItem(region, itemsFromSubRegions, type));
listModified = true;
}
}
@ -504,7 +542,7 @@ public class DownloadResources extends DownloadResourceGroup {
}
}
for (WorldRegion subRegion : subRegions) {
collectMultipleIndexesItems(subRegion);
createMultipleDownloadItems(subRegion);
}
}
@ -517,42 +555,21 @@ public class DownloadResources extends DownloadResourceGroup {
}
@Nullable
private List<IndexItem> collectIndexesOfType(@NonNull List<WorldRegion> regions,
private List<DownloadItem> collectItemsOfType(@NonNull List<WorldRegion> regions,
@NonNull DownloadActivityType type) {
List<IndexItem> collectedIndexes = new ArrayList<>();
List<DownloadItem> collectedItems = new ArrayList<>();
for (WorldRegion region : regions) {
List<IndexItem> regionIndexes = getIndexItems(region);
boolean found = false;
if (regionIndexes != null) {
for (IndexItem index : regionIndexes) {
if (index.getType() == type) {
for (DownloadItem item : getDownloadItems(region)) {
if (item.getType() == type) {
found = true;
collectedIndexes.add(index);
}
collectedItems.add(item);
break;
}
}
if (!found) return null;
}
return collectedIndexes;
}
private List<WorldRegion> removeDuplicateRegions(List<WorldRegion> regions) {
Set<WorldRegion> duplicates = new HashSet<>();
for (int i = 0; i < regions.size() - 1; i++) {
WorldRegion r1 = regions.get(i);
for (int j = i + 1; j < regions.size(); j++) {
WorldRegion r2 = regions.get(j);
if (r1.containsRegion(r2)) {
duplicates.add(r2);
} else if (r2.containsRegion(r1)) {
duplicates.add(r1);
}
}
}
for (WorldRegion region : duplicates) {
regions.remove(region);
}
return regions;
return collectedItems;
}
private void buildRegionsGroups(WorldRegion region, DownloadResourceGroup group) {
@ -679,11 +696,11 @@ public class DownloadResources extends DownloadResourceGroup {
&& isIndexItemDownloaded(downloadThread, type, downloadRegion.getSuperregion(), res);
}
private boolean doesListContainIndexWithType(List<IndexItem> indexItems,
private boolean isListContainsType(List<DownloadItem> items,
DownloadActivityType type) {
if (indexItems != null) {
for (IndexItem indexItem : indexItems) {
if (indexItem.getType() == type) {
if (items != null) {
for (DownloadItem item : items) {
if (item.getType() == type) {
return true;
}
}

View file

@ -1,5 +1,7 @@
package net.osmand.plus.download;
import android.content.Context;
import androidx.annotation.NonNull;
import net.osmand.IndexConstants;
@ -19,6 +21,7 @@ import java.util.Date;
import java.util.List;
public class IndexItem extends DownloadItem implements Comparable<IndexItem> {
private static final Log log = PlatformUtil.getLog(IndexItem.class);
String description;
@ -226,6 +229,16 @@ public class IndexItem extends DownloadItem implements Comparable<IndexItem> {
return format.format(new Date(timestamp));
}
@Override
public boolean isUseAbbreviation() {
return false;
}
@Override
public String getAbbreviationInScopes(Context ctx) {
return "";
}
public static class DownloadEntry {
public long dateModified;
public double sizeMB;
@ -254,5 +267,4 @@ public class IndexItem extends DownloadItem implements Comparable<IndexItem> {
}
}
}

View file

@ -3,35 +3,45 @@ package net.osmand.plus.download;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.map.WorldRegion;
import net.osmand.plus.OsmandApplication;
import java.io.File;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.List;
import static net.osmand.plus.download.DownloadActivityType.SRTM_COUNTRY_FILE;
import static net.osmand.plus.download.MultipleIndexesUiHelper.isBaseSRTMItem;
public class MultipleDownloadItem extends DownloadItem {
public class MultipleIndexItem extends DownloadItem {
private final List<DownloadItem> items;
private final List<IndexItem> items;
public MultipleIndexItem(@NonNull WorldRegion region,
@NonNull List<IndexItem> items,
public MultipleDownloadItem(@NonNull WorldRegion region,
@NonNull List<DownloadItem> items,
@NonNull DownloadActivityType type) {
super(type);
this.items = items;
}
public List<IndexItem> getAllIndexes() {
List<IndexItem> indexes = new ArrayList<>();
for (DownloadItem item : items) {
IndexItem index = getIndexItem(item);
if (index != null) {
indexes.add(index);
}
}
return indexes;
}
public List<DownloadItem> getAllItems() {
return items;
}
@Override
public boolean isOutdated() {
for (IndexItem item : items) {
for (DownloadItem item : items) {
if (item.isOutdated()) {
return true;
}
@ -41,7 +51,7 @@ public class MultipleIndexItem extends DownloadItem {
@Override
public boolean isDownloaded() {
for (IndexItem item : items) {
for (DownloadItem item : items) {
if (item.isDownloaded()) {
return true;
}
@ -51,8 +61,8 @@ public class MultipleIndexItem extends DownloadItem {
@Override
public boolean isDownloading(@NonNull DownloadIndexesThread thread) {
for (IndexItem item : items) {
if (thread.isDownloading(item)) {
for (DownloadItem item : items) {
if (item.isDownloading(thread)) {
return true;
}
}
@ -83,31 +93,31 @@ public class MultipleIndexItem extends DownloadItem {
@Override
public List<File> getDownloadedFiles(@NonNull OsmandApplication app) {
List<File> result = new ArrayList<>();
for (IndexItem item : items) {
for (DownloadItem item : items) {
result.addAll(item.getDownloadedFiles(app));
}
return result;
}
public List<IndexItem> getIndexesToDownload() {
List<IndexItem> indexesToDownload = new ArrayList<>();
for (IndexItem item : items) {
public List<DownloadItem> getItemsToDownload() {
List<DownloadItem> itemsToDownload = new ArrayList<>();
for (DownloadItem item : getAllItems()) {
if (item.hasActualDataToDownload()) {
indexesToDownload.add(item);
itemsToDownload.add(item);
}
}
return indexesToDownload;
return itemsToDownload;
}
@Override
public boolean hasActualDataToDownload() {
return getIndexesToDownload().size() > 0;
return getItemsToDownload().size() > 0;
}
@Override
public double getSizeToDownloadInMb() {
double totalSizeMb = 0.0d;
for (IndexItem item : items) {
for (DownloadItem item : items) {
if (item.hasActualDataToDownload()) {
totalSizeMb += item.getSizeToDownloadInMb();
}
@ -115,29 +125,47 @@ public class MultipleIndexItem extends DownloadItem {
return totalSizeMb;
}
@NonNull
public String getSizeDescription(Context ctx, boolean baseSRTM) {
double totalSizeMb = 0.0d;
if (this.type == SRTM_COUNTRY_FILE) {
for (IndexItem item : items) {
if (item.hasActualDataToDownload()) {
if (baseSRTM && isBaseSRTMItem(item) || !baseSRTM && !isBaseSRTMItem(item)) {
totalSizeMb += item.getSizeToDownloadInMb();
}
}
}
return getFormattedMb(ctx, totalSizeMb);
}
return getFormattedMb(ctx, getSizeToDownloadInMb());
}
@Override
public double getArchiveSizeMB() {
double result = 0.0d;
for (IndexItem item : items) {
for (DownloadItem item : items) {
result += item.getArchiveSizeMB();
}
return result;
}
@Nullable
public static IndexItem getIndexItem(@NonNull DownloadItem obj) {
if (obj instanceof IndexItem) {
return (IndexItem) obj;
} else if (obj instanceof SrtmDownloadItem) {
return ((SrtmDownloadItem) obj).getIndexItem();
}
return null;
}
@Override
public boolean isUseAbbreviation() {
for (DownloadItem item : items) {
if (item.isUseAbbreviation()) {
return true;
}
}
return false;
}
@Override
public String getAbbreviationInScopes(Context ctx) {
for (DownloadItem item : items) {
return item.getAbbreviationInScopes(ctx);
}
return "";
}
@Override
public String getDate(@NonNull DateFormat dateFormat, boolean remote) {
return "";
}
}

View file

@ -1,272 +0,0 @@
package net.osmand.plus.download;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import net.osmand.IndexConstants;
import net.osmand.map.OsmandRegions;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.activities.LocalIndexInfo;
import net.osmand.plus.base.SelectMultipleItemsBottomSheet;
import net.osmand.plus.base.SelectMultipleItemsBottomSheet.OnApplySelectionListener;
import net.osmand.plus.base.SelectMultipleItemsBottomSheet.OnRadioButtonSelectListener;
import net.osmand.plus.base.SelectMultipleItemsBottomSheet.SelectableItem;
import net.osmand.plus.base.SelectMultipleItemsBottomSheet.SelectionUpdateListener;
import net.osmand.plus.helpers.enums.MetricsConstants;
import net.osmand.util.Algorithms;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.List;
import static net.osmand.IndexConstants.BINARY_SRTM_MAP_INDEX_EXT;
import static net.osmand.IndexConstants.BINARY_SRTM_MAP_INDEX_EXT_ZIP;
import static net.osmand.plus.download.DownloadActivityType.SRTM_COUNTRY_FILE;
public class MultipleIndexesUiHelper {
public static void showDialog(@NonNull DownloadItem item,
@NonNull AppCompatActivity activity,
@NonNull final OsmandApplication app,
@NonNull DateFormat dateFormat,
boolean showRemoteDate,
@NonNull final SelectItemsToDownloadListener listener) {
if (item.getType() == SRTM_COUNTRY_FILE) {
showSRTMDialog(item, activity, app, dateFormat, showRemoteDate, listener);
} else if (item instanceof MultipleIndexItem) {
showBaseDialog((MultipleIndexItem) item, activity, app, dateFormat, showRemoteDate, listener);
}
}
public static void showBaseDialog(@NonNull MultipleIndexItem multipleIndexItem,
@NonNull AppCompatActivity activity,
@NonNull final OsmandApplication app,
@NonNull DateFormat dateFormat,
boolean showRemoteDate,
@NonNull final SelectItemsToDownloadListener listener) {
List<IndexItem> indexesToDownload = getIndexesToDownload(multipleIndexItem);
List<SelectableItem> allItems = new ArrayList<>();
List<SelectableItem> selectedItems = new ArrayList<>();
OsmandRegions osmandRegions = app.getRegions();
for (IndexItem indexItem : multipleIndexItem.getAllIndexes()) {
SelectableItem selectableItem = new SelectableItem();
selectableItem.setTitle(indexItem.getVisibleName(app, osmandRegions, false));
String size = indexItem.getSizeDescription(app);
String date = indexItem.getDate(dateFormat, showRemoteDate);
String description = app.getString(R.string.ltr_or_rtl_combine_via_bold_point, size, date);
selectableItem.setDescription(description);
selectableItem.setIconId(indexItem.getType().getIconResource());
selectableItem.setObject(indexItem);
allItems.add(selectableItem);
if (indexesToDownload.contains(indexItem)) {
selectedItems.add(selectableItem);
}
}
final SelectMultipleItemsBottomSheet dialog =
SelectMultipleItemsBottomSheet.showInstance(activity, allItems, selectedItems, true);
dialog.setSelectionUpdateListener(new SelectionUpdateListener() {
@Override
public void onSelectionUpdate() {
updateSize(app, dialog);
}
});
dialog.setOnApplySelectionListener(getOnApplySelectionListener(listener));
}
public static void showSRTMDialog(@NonNull final DownloadItem downloadItem,
@NonNull AppCompatActivity activity,
@NonNull final OsmandApplication app,
@NonNull final DateFormat dateFormat,
final boolean showRemoteDate,
@NonNull final SelectItemsToDownloadListener listener) {
List<SelectableItem> selectedItems = new ArrayList<>();
final List<SelectableItem> leftItems = new ArrayList<>();
final List<SelectableItem> rightItems = new ArrayList<>();
List<IndexItem> indexesToDownload = getIndexesToDownload(downloadItem);
boolean baseSRTM = isBaseSRTMMetricSystem(app);
List<IndexItem> allIndexes = new ArrayList<>();
if (downloadItem instanceof MultipleIndexItem) {
allIndexes.addAll(((MultipleIndexItem) downloadItem).getAllIndexes());
} else {
for (IndexItem indexItem : downloadItem.getRelatedGroup().getIndividualResources()) {
if (indexItem.getType() == SRTM_COUNTRY_FILE) {
allIndexes.add(indexItem);
}
}
}
for (IndexItem indexItem : allIndexes) {
boolean baseItem = isBaseSRTMItem(indexItem);
SelectableItem selectableItem = new SelectableItem();
selectableItem.setTitle(indexItem.getVisibleName(app, app.getRegions(), false));
String size = indexItem.getSizeDescription(app);
size += " (" + getSRTMAbbrev(app, baseItem) + ")";
String date = indexItem.getDate(dateFormat, showRemoteDate);
String description = app.getString(R.string.ltr_or_rtl_combine_via_bold_point, size, date);
selectableItem.setDescription(description);
selectableItem.setIconId(indexItem.getType().getIconResource());
selectableItem.setObject(indexItem);
if (baseItem) {
leftItems.add(selectableItem);
} else {
rightItems.add(selectableItem);
}
if (indexesToDownload.contains(indexItem)
&& (baseSRTM && baseItem || !baseSRTM && !baseItem)) {
selectedItems.add(selectableItem);
}
}
String addDescription = app.getString(isListDialog(app, leftItems, rightItems)
? R.string.srtm_download_list_help_message : R.string.srtm_download_single_help_message);
final SelectMultipleItemsBottomSheet dialog = SelectMultipleItemsBottomSheet.showInstance(
activity, baseSRTM ? leftItems : rightItems, selectedItems, true,
addDescription, true, baseSRTM,
Algorithms.capitalizeFirstLetter(app.getString(R.string.shared_string_meters)),
Algorithms.capitalizeFirstLetter(app.getString(R.string.shared_string_feets)));
dialog.setSelectionUpdateListener(new SelectionUpdateListener() {
@Override
public void onSelectionUpdate() {
updateSize(app, dialog);
}
});
dialog.setOnApplySelectionListener(getOnApplySelectionListener(listener));
dialog.setOnRadioButtonSelectListener(new OnRadioButtonSelectListener() {
@Override
public void onSelect(boolean leftButton) {
dialog.recreateList(leftButton ? leftItems : rightItems);
updateSize(app, dialog);
}
});
dialog.setSelectedItemsListener(new SelectedItemsListener() {
@Override
public List<SelectableItem> createSelectedItems(List<SelectableItem> currentAllItems, boolean baseSRTM) {
List<IndexItem> indexesToDownload = getIndexesToDownload(downloadItem);
List<SelectableItem> selectedItems = new ArrayList<>();
for (SelectableItem currentItem : currentAllItems) {
IndexItem indexItem = (IndexItem) currentItem.getObject();
boolean baseItem = isBaseSRTMItem(indexItem);
if (indexesToDownload.contains(indexItem)
&& (baseSRTM && baseItem || !baseSRTM && !baseItem)) {
selectedItems.add(currentItem);
}
}
return selectedItems;
}
});
}
private static OnApplySelectionListener getOnApplySelectionListener(final SelectItemsToDownloadListener listener) {
return new OnApplySelectionListener() {
@Override
public void onSelectionApplied(List<SelectableItem> selectedItems) {
List<IndexItem> indexItems = new ArrayList<>();
for (SelectableItem item : selectedItems) {
Object obj = item.getObject();
if (obj instanceof IndexItem) {
indexItems.add((IndexItem) obj);
}
}
listener.onItemsToDownloadSelected(indexItems);
}
};
}
private static void updateSize(OsmandApplication app, SelectMultipleItemsBottomSheet dialog) {
boolean isListDialog = dialog.isMultipleItem();
dialog.setTitle(app.getString(isListDialog ? R.string.welmode_download_maps : R.string.srtm_unit_format));
double sizeToDownload = getDownloadSizeInMb(dialog.getSelectedItems());
String size = DownloadItem.getFormattedMb(app, sizeToDownload);
if (isListDialog) {
String total = app.getString(R.string.shared_string_total);
String description = app.getString(R.string.ltr_or_rtl_combine_via_colon, total, size);
dialog.setDescription(description);
}
String btnTitle = app.getString(R.string.shared_string_download);
if (sizeToDownload > 0) {
btnTitle = app.getString(R.string.ltr_or_rtl_combine_via_dash, btnTitle, size);
}
dialog.setConfirmButtonTitle(btnTitle);
}
private static boolean isListDialog(OsmandApplication app,
List<SelectableItem> leftItems, List<SelectableItem> rightItems) {
return (isBaseSRTMMetricSystem(app) ? leftItems : rightItems).size() > 1;
}
public static String getSRTMAbbrev(Context context, boolean base) {
return context.getString(base ? R.string.m : R.string.foot);
}
public static String getSRTMExt(IndexItem indexItem) {
return isBaseSRTMItem(indexItem)
? IndexConstants.BINARY_SRTM_MAP_INDEX_EXT : IndexConstants.BINARY_SRTM_FEET_MAP_INDEX_EXT;
}
public static boolean isBaseSRTMItem(Object item) {
if (item instanceof IndexItem) {
return ((IndexItem) item).getFileName().endsWith(BINARY_SRTM_MAP_INDEX_EXT_ZIP);
} else if (item instanceof LocalIndexInfo) {
return ((LocalIndexInfo) item).getFileName().endsWith(BINARY_SRTM_MAP_INDEX_EXT);
}
return false;
}
public static boolean isBaseSRTMMetricSystem(OsmandApplication app) {
return app.getSettings().METRIC_SYSTEM.get() != MetricsConstants.MILES_AND_FEET;
}
private static List<IndexItem> getIndexesToDownload(DownloadItem downloadItem) {
if (downloadItem instanceof MultipleIndexItem) {
if (downloadItem.hasActualDataToDownload()) {
// download left regions
return ((MultipleIndexItem) downloadItem).getIndexesToDownload();
} else {
// download all regions again
return ((MultipleIndexItem) downloadItem).getAllIndexes();
}
} else {
List<IndexItem> indexesToDownload = new ArrayList<>();
for (IndexItem indexItem : downloadItem.getRelatedGroup().getIndividualResources()) {
if (indexItem.getType() == SRTM_COUNTRY_FILE && indexItem.hasActualDataToDownload()) {
indexesToDownload.add(indexItem);
}
}
return indexesToDownload;
}
}
private static double getDownloadSizeInMb(@NonNull List<SelectableItem> selectableItems) {
List<IndexItem> indexItems = new ArrayList<>();
for (SelectableItem i : selectableItems) {
Object obj = i.getObject();
if (obj instanceof IndexItem) {
indexItems.add((IndexItem) obj);
}
}
double totalSizeMb = 0.0d;
for (IndexItem item : indexItems) {
totalSizeMb += item.getSizeToDownloadInMb();
}
return totalSizeMb;
}
public interface SelectItemsToDownloadListener {
void onItemsToDownloadSelected(List<IndexItem> items);
}
public interface SelectedItemsListener {
List<SelectableItem> createSelectedItems(List<SelectableItem> currentAllItems, boolean base);
}
}

View file

@ -0,0 +1,280 @@
package net.osmand.plus.download;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.base.MultipleSelectionBottomSheet;
import net.osmand.plus.base.MultipleSelectionBottomSheet.SelectionUpdateListener;
import net.osmand.plus.base.ModeSelectionBottomSheet;
import net.osmand.plus.base.MultipleSelectionWithModeBottomSheet;
import net.osmand.plus.base.SelectionBottomSheet;
import net.osmand.plus.base.SelectionBottomSheet.OnApplySelectionListener;
import net.osmand.plus.base.SelectionBottomSheet.OnUiInitializedListener;
import net.osmand.plus.base.SelectionBottomSheet.SelectableItem;
import net.osmand.plus.widgets.MultiStateToggleButton.OnRadioItemClickListener;
import net.osmand.plus.widgets.MultiStateToggleButton.RadioItem;
import net.osmand.util.Algorithms;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.List;
import static net.osmand.plus.download.MultipleDownloadItem.getIndexItem;
public class SelectIndexesUiHelper {
private final OsmandApplication app;
private final AppCompatActivity activity;
private final ItemsToDownloadSelectedListener listener;
private final DateFormat dateFormat;
private final boolean showRemoteDate;
private final DownloadItem downloadItem;
private SelectionBottomSheet dialog;
private SelectIndexesUiHelper(@NonNull DownloadItem downloadItem,
@NonNull AppCompatActivity activity,
@NonNull DateFormat dateFormat,
boolean showRemoteDate,
@NonNull ItemsToDownloadSelectedListener listener) {
this.app = (OsmandApplication) activity.getApplicationContext();
this.activity = activity;
this.downloadItem = downloadItem;
this.dateFormat = dateFormat;
this.showRemoteDate = showRemoteDate;
this.listener = listener;
}
public static void showDialog(@NonNull DownloadItem i,
@NonNull AppCompatActivity a,
@NonNull DateFormat df,
boolean showRemoteDate,
@NonNull ItemsToDownloadSelectedListener l) {
new SelectIndexesUiHelper(i, a, df, showRemoteDate, l).showDialogInternal();
}
private void showDialogInternal() {
if (downloadItem.getType() == DownloadActivityType.SRTM_COUNTRY_FILE) {
if (downloadItem instanceof MultipleDownloadItem) {
showSrtmMultipleSelectionDialog();
} else {
showSrtmModeSelectionDialog();
}
} else if (downloadItem instanceof MultipleDownloadItem) {
showMultipleSelectionDialog();
}
}
private void showMultipleSelectionDialog() {
List<SelectableItem> allItems = new ArrayList<>();
List<SelectableItem> selectedItems = new ArrayList<>();
prepareItems(allItems, selectedItems);
MultipleSelectionBottomSheet msDialog = MultipleSelectionBottomSheet.showInstance(
activity, allItems, selectedItems, true);
this.dialog = msDialog;
msDialog.setUiInitializedListener(new OnUiInitializedListener() {
@Override
public void onUiInitialized() {
dialog.setTitle(app.getString(R.string.welmode_download_maps));
}
});
msDialog.setSelectionUpdateListener(new SelectionUpdateListener() {
@Override
public void onSelectionUpdate() {
updateSize();
}
});
msDialog.setOnApplySelectionListener(getOnApplySelectionListener(listener));
}
private void showSrtmMultipleSelectionDialog() {
List<SelectableItem> allItems = new ArrayList<>();
List<SelectableItem> selectedItems = new ArrayList<>();
prepareItems(allItems, selectedItems);
SrtmDownloadItem srtmItem = (SrtmDownloadItem) ((MultipleDownloadItem)downloadItem).getAllItems().get(0);
final int selectedModeOrder = srtmItem.isUseMeters() ? 0 : 1;
final List<RadioItem> radioItems = createSrtmRadioItems();
MultipleSelectionBottomSheet msDialog = MultipleSelectionWithModeBottomSheet.showInstance(
activity, allItems, selectedItems, radioItems, true);
this.dialog = msDialog;
msDialog.setUiInitializedListener(new OnUiInitializedListener() {
@Override
public void onUiInitialized() {
dialog.setTitle(app.getString(R.string.welmode_download_maps));
dialog.setSelectedMode(radioItems.get(selectedModeOrder));
dialog.setSecondaryDescription(app.getString(R.string.srtm_download_list_help_message));
}
});
msDialog.setSelectionUpdateListener(new SelectionUpdateListener() {
@Override
public void onSelectionUpdate() {
updateSize();
}
});
msDialog.setOnApplySelectionListener(getOnApplySelectionListener(listener));
}
private void showSrtmModeSelectionDialog() {
SrtmDownloadItem srtmItem = (SrtmDownloadItem) downloadItem;
final int selectedModeOrder = srtmItem.isUseMeters() ? 0 : 1;
final List<RadioItem> radioItems = createSrtmRadioItems();
SelectableItem preview = createSelectableItem(srtmItem);
dialog = ModeSelectionBottomSheet.showInstance(activity, preview, radioItems, true);
dialog.setUiInitializedListener(new OnUiInitializedListener() {
@Override
public void onUiInitialized() {
ModeSelectionBottomSheet dialog = (ModeSelectionBottomSheet) SelectIndexesUiHelper.this.dialog;
dialog.setTitle(app.getString(R.string.srtm_unit_format));
dialog.setPrimaryDescription(app.getString(R.string.srtm_download_single_help_message));
updateSize();
dialog.setSelectedMode(radioItems.get(selectedModeOrder));
}
});
dialog.setOnApplySelectionListener(getOnApplySelectionListener(listener));
}
private void prepareItems(List<SelectableItem> allItems,
List<SelectableItem> selectedItems) {
final MultipleDownloadItem multipleDownloadItem = (MultipleDownloadItem) downloadItem;
final List<DownloadItem> itemsToDownload = getItemsToDownload(multipleDownloadItem);
for (DownloadItem downloadItem : multipleDownloadItem.getAllItems()) {
SelectableItem selectableItem = createSelectableItem(downloadItem);
allItems.add(selectableItem);
if (itemsToDownload.contains(downloadItem)) {
selectedItems.add(selectableItem);
}
}
}
private List<RadioItem> createSrtmRadioItems() {
List<RadioItem> radioItems = new ArrayList<>();
radioItems.add(createSrtmRadioBtn(R.string.shared_string_meters, true));
radioItems.add(createSrtmRadioBtn(R.string.shared_string_feets, false));
return radioItems;
}
private RadioItem createSrtmRadioBtn(int titleId,
final boolean useMeters) {
String title = Algorithms.capitalizeFirstLetter(app.getString(titleId));
RadioItem radioItem = new RadioItem(title);
radioItem.setOnClickListener(new OnRadioItemClickListener() {
@Override
public boolean onRadioItemClick(RadioItem radioItem, View view) {
updateDialogListItems(useMeters);
updateSize();
return true;
}
});
return radioItem;
}
private void updateDialogListItems(boolean useMeters) {
List<SelectableItem> items = new ArrayList<>(dialog.getAllItems());
for (SelectableItem item : items) {
DownloadItem downloadItem = (DownloadItem) item.getObject();
if (downloadItem instanceof SrtmDownloadItem) {
((SrtmDownloadItem) downloadItem).setUseMeters(useMeters);
updateSelectableItem(item, downloadItem);
}
}
dialog.setItems(items);
}
private SelectableItem createSelectableItem(DownloadItem item) {
SelectableItem selectableItem = new SelectableItem();
updateSelectableItem(selectableItem, item);
return selectableItem;
}
private void updateSelectableItem(SelectableItem selectableItem,
DownloadItem downloadItem) {
selectableItem.setTitle(
downloadItem.getVisibleName(app, app.getRegions(), false));
String size = downloadItem.getSizeDescription(app);
if (downloadItem.isUseAbbreviation()) {
size += " " + downloadItem.getAbbreviationInScopes(app);
}
String date = downloadItem.getDate(dateFormat, showRemoteDate);
String description = app.getString(R.string.ltr_or_rtl_combine_via_bold_point, size, date);
selectableItem.setDescription(description);
selectableItem.setIconId(downloadItem.getType().getIconResource());
selectableItem.setObject(downloadItem);
}
private OnApplySelectionListener getOnApplySelectionListener(final ItemsToDownloadSelectedListener listener) {
return new OnApplySelectionListener() {
@Override
public void onSelectionApplied(List<SelectableItem> selectedItems) {
List<IndexItem> indexes = new ArrayList<>();
for (SelectableItem item : selectedItems) {
IndexItem index = getIndexItem((DownloadItem) item.getObject());
if (index != null) {
indexes.add(index);
}
}
listener.onItemsToDownloadSelected(indexes);
}
};
}
private void updateSize() {
double sizeToDownload = getDownloadSizeInMb(dialog.getSelectedItems());
String size = DownloadItem.getFormattedMb(app, sizeToDownload);
String total = app.getString(R.string.shared_string_total);
String description = app.getString(R.string.ltr_or_rtl_combine_via_colon, total, size);
dialog.setTitleDescription(description);
String btnTitle = app.getString(R.string.shared_string_download);
if (sizeToDownload > 0) {
btnTitle = app.getString(R.string.ltr_or_rtl_combine_via_dash, btnTitle, size);
}
dialog.setApplyButtonTitle(btnTitle);
}
private double getDownloadSizeInMb(@NonNull List<SelectableItem> selectableItems) {
double totalSizeMb = 0.0d;
for (SelectableItem i : selectableItems) {
Object obj = i.getObject();
if (obj instanceof DownloadItem) {
totalSizeMb += ((DownloadItem) obj).getSizeToDownloadInMb();
}
}
return totalSizeMb;
}
private static List<DownloadItem> getItemsToDownload(MultipleDownloadItem md) {
if (md.hasActualDataToDownload()) {
// download left regions
return md.getItemsToDownload();
} else {
// download all regions again
return md.getAllItems();
}
}
public interface ItemsToDownloadSelectedListener {
void onItemsToDownloadSelected(List<IndexItem> items);
}
}

View file

@ -0,0 +1,194 @@
package net.osmand.plus.download;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.IndexConstants;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.activities.LocalIndexInfo;
import net.osmand.plus.helpers.enums.MetricsConstants;
import java.io.File;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.List;
import static net.osmand.IndexConstants.BINARY_SRTM_MAP_INDEX_EXT;
import static net.osmand.IndexConstants.BINARY_SRTM_MAP_INDEX_EXT_ZIP;
import static net.osmand.plus.activities.LocalIndexHelper.LocalIndexType.SRTM_DATA;
import static net.osmand.plus.download.DownloadActivityType.SRTM_COUNTRY_FILE;
public class SrtmDownloadItem extends DownloadItem {
private final List<IndexItem> indexes;
private boolean useMeters;
public SrtmDownloadItem(List<IndexItem> indexes,
boolean useMeters) {
super(SRTM_COUNTRY_FILE);
this.indexes = indexes;
this.useMeters = useMeters;
}
public void setUseMeters(boolean useMeters) {
this.useMeters = useMeters;
}
public boolean isUseMeters() {
return useMeters;
}
@Nullable
public IndexItem getIndexItem() {
for (IndexItem index : indexes) {
if (useMeters && isMetersItem(index) || !useMeters && !isMetersItem(index)) {
return index;
}
}
return null;
}
@Override
protected double getSizeToDownloadInMb() {
return getIndexItem().getSizeToDownloadInMb();
}
@Override
public double getArchiveSizeMB() {
return getIndexItem().getArchiveSizeMB();
}
@Override
public boolean isOutdated() {
for (DownloadItem item : indexes) {
if (item.isOutdated()) {
return true;
}
}
return false;
}
@Override
public boolean isDownloaded() {
for (DownloadItem item : indexes) {
if (item.isDownloaded()) {
return true;
}
}
return false;
}
@Override
public boolean hasActualDataToDownload() {
// may be check only downloaded items if any downloaded
for (IndexItem item : indexes) {
if (item.hasActualDataToDownload()) {
return true;
}
}
return false;
}
@Override
public boolean isDownloading(@NonNull DownloadIndexesThread thread) {
for (IndexItem item : indexes) {
if (thread.isDownloading(item)) {
return true;
}
}
return false;
}
@Override
public String getFileName() {
return getIndexItem().getFileName();
}
@NonNull
@Override
public List<File> getDownloadedFiles(@NonNull OsmandApplication app) {
// may be check both indexes files
List<File> result = new ArrayList<>();
for (IndexItem index : indexes) {
result.addAll(index.getDownloadedFiles(app));
}
return result;
}
public String getDate(@NonNull DateFormat dateFormat, boolean remote) {
// may be check only downloaded items if any downloaded
return getIndexItem().getDate(dateFormat, remote);
}
@Override
public boolean isUseAbbreviation() {
return true;
}
@Override
public String getAbbreviationInScopes(Context ctx) {
return getAbbreviationInScopes(ctx, this);
}
public static boolean shouldUseMetersByDefault(@NonNull OsmandApplication app) {
MetricsConstants metricSystem = app.getSettings().METRIC_SYSTEM.get();
return metricSystem != MetricsConstants.MILES_AND_FEET;
}
@NonNull
public static String getAbbreviationInScopes(Context ctx, Object obj) {
return "(" + getAbbreviation(ctx, obj) + ")";
}
@NonNull
public static String getAbbreviation(Context context, Object obj) {
return context.getString(isMetersItem(obj) ? R.string.m : R.string.foot);
}
public static boolean isMetersItem(Object item) {
if (item instanceof IndexItem) {
return ((IndexItem) item).getFileName().endsWith(BINARY_SRTM_MAP_INDEX_EXT_ZIP);
} else if (item instanceof LocalIndexInfo) {
return ((LocalIndexInfo) item).getFileName().endsWith(BINARY_SRTM_MAP_INDEX_EXT);
} else if (item instanceof SrtmDownloadItem) {
return ((SrtmDownloadItem) item).useMeters;
} else if (item instanceof MultipleDownloadItem) {
for (DownloadItem downloadItem : ((MultipleDownloadItem) item).getAllItems()) {
return isMetersItem(downloadItem);
}
}
return false;
}
public static boolean containsSrtmExtension(@NonNull String fileName) {
return fileName.contains(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)
|| fileName.contains(IndexConstants.BINARY_SRTM_FEET_MAP_INDEX_EXT);
}
public static boolean isSrtmFile(@NonNull String fileName) {
return fileName.endsWith(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)
|| fileName.endsWith(IndexConstants.BINARY_SRTM_FEET_MAP_INDEX_EXT);
}
@NonNull
public static String getExtension(IndexItem indexItem) {
return isMetersItem(indexItem) ?
IndexConstants.BINARY_SRTM_MAP_INDEX_EXT :
IndexConstants.BINARY_SRTM_FEET_MAP_INDEX_EXT;
}
public static boolean isSRTMItem(Object item) {
if (item instanceof IndexItem) {
return ((IndexItem) item).getType() == SRTM_COUNTRY_FILE;
} else if (item instanceof DownloadItem) {
return ((DownloadItem) item).getType() == SRTM_COUNTRY_FILE;
} else if (item instanceof LocalIndexInfo) {
return ((LocalIndexInfo) item).getType() == SRTM_DATA;
}
return false;
}
}

View file

@ -87,7 +87,7 @@ public class ActiveDownloadsDialogFragment extends DialogFragment implements Dow
}
ItemViewHolder viewHolder = (ItemViewHolder) convertView.getTag();
IndexItem item = getItem(position);
viewHolder.bindIndexItem(item);
viewHolder.bindDownloadItem(item);
return convertView;
}

View file

@ -78,7 +78,7 @@ public class DownloadResourceGroupAdapter extends OsmandBaseExpandableListAdapte
} else {
viewHolder.setShowTypeInDesc(true);
}
viewHolder.bindIndexItem(item);
viewHolder.bindDownloadItem(item);
} else {
DownloadResourceGroup group = (DownloadResourceGroup) child;
DownloadGroupViewHolder viewHolder;

View file

@ -41,9 +41,9 @@ import net.osmand.plus.download.DownloadActivityType;
import net.osmand.plus.download.DownloadResourceGroup;
import net.osmand.plus.download.DownloadResources;
import net.osmand.plus.download.IndexItem;
import net.osmand.plus.download.MultipleIndexesUiHelper;
import net.osmand.plus.download.MultipleIndexesUiHelper.SelectItemsToDownloadListener;
import net.osmand.plus.download.MultipleIndexItem;
import net.osmand.plus.download.SelectIndexesUiHelper;
import net.osmand.plus.download.SelectIndexesUiHelper.ItemsToDownloadSelectedListener;
import net.osmand.plus.download.MultipleDownloadItem;
import net.osmand.plus.download.ui.LocalIndexesFragment.LocalIndexOperationTask;
import net.osmand.plus.helpers.FileNameTranslationHelper;
import net.osmand.plus.inapp.InAppPurchaseHelper;
@ -51,15 +51,8 @@ import net.osmand.util.Algorithms;
import java.io.File;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.List;
import static net.osmand.plus.download.DownloadActivityType.SRTM_COUNTRY_FILE;
import static net.osmand.plus.download.DownloadActivityType.isSRTMItem;
import static net.osmand.plus.download.MultipleIndexesUiHelper.getSRTMAbbrev;
import static net.osmand.plus.download.MultipleIndexesUiHelper.isBaseSRTMItem;
import static net.osmand.plus.download.MultipleIndexesUiHelper.isBaseSRTMMetricSystem;
public class ItemViewHolder {
protected final TextView nameTextView;
@ -153,11 +146,11 @@ public class ItemViewHolder {
depthContoursPurchased = InAppPurchaseHelper.isDepthContoursPurchased(context.getMyApplication());
}
public void bindIndexItem(final DownloadItem downloadItem) {
bindIndexItem(downloadItem, null);
public void bindDownloadItem(final DownloadItem downloadItem) {
bindDownloadItem(downloadItem, null);
}
public void bindIndexItem(final DownloadItem downloadItem, final String cityName) {
public void bindDownloadItem(final DownloadItem downloadItem, final String cityName) {
initAppStatusVariables();
boolean isDownloading = downloadItem.isDownloading(context.getDownloadThread());
int progress = -1;
@ -196,8 +189,6 @@ public class ItemViewHolder {
}
descrTextView.setTextColor(textColorSecondary);
if (!isDownloading) {
boolean srtmItem = isSRTMItem(downloadItem);
boolean baseMetricSystem = isBaseSRTMMetricSystem(context.getMyApplication());
progressBar.setVisibility(View.GONE);
descrTextView.setVisibility(View.VISIBLE);
if (downloadItem instanceof CustomIndexItem && (((CustomIndexItem) downloadItem).getSubName(context) != null)) {
@ -212,34 +203,12 @@ public class ItemViewHolder {
} else {
descrTextView.setText(downloadItem.getType().getString(context));
}
} else if (downloadItem instanceof MultipleIndexItem) {
MultipleIndexItem item = (MultipleIndexItem) downloadItem;
} else if (downloadItem instanceof MultipleDownloadItem) {
MultipleDownloadItem item = (MultipleDownloadItem) downloadItem;
String allRegionsHeader = context.getString(R.string.shared_strings_all_regions);
String regionsHeader = context.getString(R.string.regions);
String allRegionsCount;
String leftToDownloadCount;
if (isSRTMItem(item)) {
List<IndexItem> items = new ArrayList<>();
for (IndexItem indexItem : item.getAllIndexes()) {
boolean baseItem = isBaseSRTMItem(indexItem);
if (baseMetricSystem && baseItem || !baseMetricSystem && !baseItem) {
items.add(indexItem);
}
}
allRegionsCount = String.valueOf(items.size());
items.clear();
for (IndexItem indexItem : item.getIndexesToDownload()) {
boolean baseItem = isBaseSRTMItem(indexItem);
if (!indexItem.isDownloaded()
&& (baseMetricSystem && baseItem || !baseMetricSystem && !baseItem)) {
items.add(indexItem);
}
}
leftToDownloadCount = String.valueOf(items.size());
} else {
allRegionsCount = String.valueOf(item.getAllIndexes().size());
leftToDownloadCount = String.valueOf(item.getIndexesToDownload().size());
}
String allRegionsCount = String.valueOf(item.getAllItems().size());
String leftToDownloadCount = String.valueOf(item.getItemsToDownload().size());
String header;
String count;
if (item.hasActualDataToDownload()) {
@ -258,24 +227,23 @@ public class ItemViewHolder {
count = allRegionsCount;
}
String fullDescription = context.getString(R.string.ltr_or_rtl_combine_via_colon, header, count);
if (srtmItem) {
fullDescription += " (" + getSRTMAbbrev(context, baseMetricSystem) + ")";
if (item.isUseAbbreviation()) {
fullDescription += " " + item.getAbbreviationInScopes(context);
}
if (item.hasActualDataToDownload()) {
fullDescription = context.getString(
R.string.ltr_or_rtl_combine_via_bold_point, fullDescription, srtmItem
? item.getSizeDescription(context, baseMetricSystem) : item.getSizeDescription(context));
R.string.ltr_or_rtl_combine_via_bold_point, fullDescription,
item.getSizeDescription(context));
}
descrTextView.setText(fullDescription);
} else {
IndexItem item = (IndexItem) downloadItem;
String pattern = context.getString(R.string.ltr_or_rtl_combine_via_bold_point);
String type = item.getType().getString(context);
String size = item.getSizeDescription(context);
if (srtmItem) {
size += " (" + getSRTMAbbrev(context, isBaseSRTMItem(item)) + ")";
String type = downloadItem.getType().getString(context);
String size = downloadItem.getSizeDescription(context);
if (downloadItem.isUseAbbreviation()) {
size += " " + downloadItem.getAbbreviationInScopes(context);
}
String date = item.getDate(dateFormat, showRemoteDate);
String date = downloadItem.getDate(dateFormat, showRemoteDate);
String fullDescription = String.format(pattern, size, date);
if (showTypeInDesc) {
fullDescription = String.format(pattern, type, fullDescription);
@ -310,9 +278,9 @@ public class ItemViewHolder {
}
}
public void bindIndexItem(final CityItem cityItem) {
public void bindDownloadItem(final CityItem cityItem) {
if (cityItem.getIndexItem() != null) {
bindIndexItem(cityItem.getIndexItem(), cityItem.getName());
bindDownloadItem(cityItem.getIndexItem(), cityItem.getName());
} else {
nameTextView.setText(cityItem.getName());
nameTextView.setTextColor(textColorPrimary);
@ -352,7 +320,7 @@ public class ItemViewHolder {
}
private int getDownloadActionIconId(@NonNull DownloadItem item) {
return item instanceof MultipleIndexItem ?
return item instanceof MultipleDownloadItem ?
R.drawable.ic_action_multi_download :
R.drawable.ic_action_gsave_dark;
}
@ -513,18 +481,17 @@ public class ItemViewHolder {
}
private void startDownload(DownloadItem item) {
if (item instanceof MultipleIndexItem || item.getType() == SRTM_COUNTRY_FILE) {
selectIndexesToDownload(item);
} else if (item instanceof IndexItem) {
if (item instanceof IndexItem) {
IndexItem indexItem = (IndexItem) item;
context.startDownload(indexItem);
} else {
selectIndexesToDownload(item);
}
}
private void selectIndexesToDownload(DownloadItem item) {
OsmandApplication app = context.getMyApplication();
MultipleIndexesUiHelper.showDialog(item, context, app, dateFormat, showRemoteDate,
new SelectItemsToDownloadListener() {
SelectIndexesUiHelper.showDialog(item, context, dateFormat, showRemoteDate,
new ItemsToDownloadSelectedListener() {
@Override
public void onItemsToDownloadSelected(List<IndexItem> indexes) {
IndexItem[] indexesArray = new IndexItem[indexes.size()];

View file

@ -55,6 +55,7 @@ import net.osmand.plus.dialogs.DirectionsDialogs;
import net.osmand.plus.download.DownloadActivity;
import net.osmand.plus.download.DownloadIndexesThread.DownloadEvents;
import net.osmand.plus.download.IndexItem;
import net.osmand.plus.download.SrtmDownloadItem;
import net.osmand.plus.helpers.FileNameTranslationHelper;
import net.osmand.plus.inapp.InAppPurchaseHelper;
import net.osmand.plus.mapsource.EditMapSourceDialogFragment.OnMapSourceUpdateListener;
@ -74,9 +75,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import static net.osmand.plus.download.DownloadActivityType.isSRTMItem;
import static net.osmand.plus.download.MultipleIndexesUiHelper.getSRTMAbbrev;
import static net.osmand.plus.download.MultipleIndexesUiHelper.isBaseSRTMItem;
public class LocalIndexesFragment extends OsmandExpandableListFragment implements DownloadEvents,
OnMapSourceUpdateListener, RenameCallback {
@ -967,8 +965,7 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement
return ctx.getString(R.string.download_roads_only_item);
} else if (child.isBackupedData() && child.getFileName().endsWith(IndexConstants.BINARY_WIKI_MAP_INDEX_EXT)) {
return ctx.getString(R.string.download_wikipedia_maps);
} else if (child.isBackupedData() && (child.getFileName().endsWith(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)
|| child.getFileName().endsWith(IndexConstants.BINARY_SRTM_FEET_MAP_INDEX_EXT))) {
} else if (child.isBackupedData() && (SrtmDownloadItem.isSrtmFile(child.getFileName()))) {
return ctx.getString(R.string.download_srtm_maps);
}
return "";
@ -1034,8 +1031,8 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement
builder.append(AndroidUtils.formatSize(ctx, child.getSize() * 1024l));
}
if (isSRTMItem(child)) {
builder.append(" (").append(getSRTMAbbrev(ctx, isBaseSRTMItem(child))).append(")");
if (SrtmDownloadItem.isSRTMItem(child)) {
builder.append(" ").append(SrtmDownloadItem.getAbbreviationInScopes(ctx, child));
}
if (!Algorithms.isEmpty(child.getDescription())) {

View file

@ -382,10 +382,10 @@ public class SearchDialogFragment extends DialogFragment implements DownloadEven
if (obj instanceof IndexItem) {
IndexItem item = (IndexItem) obj;
viewHolder.setShowTypeInDesc(true);
viewHolder.bindIndexItem(item);
viewHolder.bindDownloadItem(item);
} else {
CityItem item = (CityItem) obj;
viewHolder.bindIndexItem(item);
viewHolder.bindDownloadItem(item);
if (item.getIndexItem() == null) {
new IndexItemResolverTask(viewHolder, item).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
@ -461,7 +461,7 @@ public class SearchDialogFragment extends DialogFragment implements DownloadEven
if (viewHolder != null) {
if (indexItem != null) {
cityItem.setIndexItem(indexItem);
viewHolder.bindIndexItem(indexItem, cityItem.getName());
viewHolder.bindDownloadItem(indexItem, cityItem.getName());
}
}
}

View file

@ -410,7 +410,7 @@ public class UpdatesIndexFragment extends OsmAndListFragment implements Download
holder.setShowRemoteDate(true);
holder.setShowTypeInDesc(true);
holder.setShowParentRegionName(true);
holder.bindIndexItem(getItem(position));
holder.bindDownloadItem(getItem(position));
}
return view;
}

View file

@ -5,6 +5,7 @@ import net.osmand.PlatformUtil;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.osm.io.NetworkUtils;
import net.osmand.plus.R;
import net.osmand.plus.download.SrtmDownloadItem;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
@ -45,8 +46,7 @@ public class IncrementalChangesManager {
Set<String> existingFiles = new HashSet<String>();
for (File f : files) {
if (!f.getName().endsWith(IndexConstants.BINARY_WIKI_MAP_INDEX_EXT) &&
!f.getName().endsWith(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT) &&
!f.getName().endsWith(IndexConstants.BINARY_SRTM_FEET_MAP_INDEX_EXT)) {
!SrtmDownloadItem.isSrtmFile(f.getName())) {
existingFiles.add(Algorithms.getFileNameWithoutExtension(f));
}
}

View file

@ -41,6 +41,7 @@ import net.osmand.plus.R;
import net.osmand.plus.Version;
import net.osmand.plus.download.DownloadOsmandIndexesHelper;
import net.osmand.plus.download.DownloadOsmandIndexesHelper.AssetEntry;
import net.osmand.plus.download.SrtmDownloadItem;
import net.osmand.plus.inapp.InAppPurchaseHelper;
import net.osmand.plus.render.MapRenderRepositories;
import net.osmand.plus.render.NativeOsmandLibrary;
@ -701,8 +702,7 @@ public class ResourceManager {
log.error(String.format("File %s could not be read", f.getName()), e);
}
boolean wikiMap = (f.getName().contains("_wiki") || f.getName().contains(IndexConstants.BINARY_WIKI_MAP_INDEX_EXT));
boolean srtmMap = f.getName().contains(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)
|| f.getName().contains(IndexConstants.BINARY_SRTM_FEET_MAP_INDEX_EXT);
boolean srtmMap = SrtmDownloadItem.containsSrtmExtension(f.getName());
if (mapReader == null || (!Version.isPaidVersion(context) && wikiMap && !f.getName().equals(DEFAULT_WIKIVOYAGE_TRAVEL_OBF))) {
warnings.add(MessageFormat.format(context.getString(R.string.version_index_is_not_supported), f.getName())); //$NON-NLS-1$
} else {

View file

@ -7,6 +7,7 @@ import androidx.annotation.Nullable;
import net.osmand.IndexConstants;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.download.SrtmDownloadItem;
import net.osmand.util.Algorithms;
import org.json.JSONException;
@ -92,8 +93,7 @@ public class FileSettingsItem extends StreamSettingsItem {
case OTHER:
break;
case SRTM_MAP:
if (name.endsWith(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)
|| name.endsWith(IndexConstants.BINARY_SRTM_FEET_MAP_INDEX_EXT)) {
if (SrtmDownloadItem.isSrtmFile(name)) {
return subtype;
}
break;

View file

@ -36,6 +36,7 @@ import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton.Bu
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription;
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.SimpleDividerItem;
import net.osmand.plus.download.SrtmDownloadItem;
import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo;
import net.osmand.plus.helpers.FileNameTranslationHelper;
import net.osmand.plus.helpers.GpxUiHelper;
@ -530,8 +531,7 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment {
return getString(R.string.download_roads_only_item);
} else if (file.getName().endsWith(IndexConstants.BINARY_WIKI_MAP_INDEX_EXT)) {
return getString(R.string.download_wikipedia_maps);
} else if (file.getName().endsWith(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)
|| file.getName().endsWith(IndexConstants.BINARY_SRTM_FEET_MAP_INDEX_EXT)) {
} else if (SrtmDownloadItem.isSrtmFile(file.getName())) {
return getString(R.string.download_srtm_maps);
} else if (file.getName().endsWith(IndexConstants.BINARY_MAP_INDEX_EXT)) {
return getString(R.string.download_regular_maps);

View file

@ -18,6 +18,7 @@ import net.osmand.plus.UiUtilities;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
public class MultiStateToggleButton {
@ -37,6 +38,13 @@ public class MultiStateToggleButton {
this.nightMode = nightMode;
}
public void setItems(Collection<RadioItem> radioItems) {
if (radioItems == null || radioItems.size() < 2) return;
items.clear();
items.addAll(radioItems);
initView();
}
public void setItems(RadioItem firstBtn, RadioItem secondBtn, RadioItem... other) {
items.clear();
items.add(firstBtn);