Add dialog to choose multiple maps to download
This commit is contained in:
parent
454831591b
commit
86ee2c1c92
11 changed files with 487 additions and 54 deletions
|
@ -73,6 +73,7 @@
|
||||||
android:paddingBottom="@dimen/content_padding_small">
|
android:paddingBottom="@dimen/content_padding_small">
|
||||||
|
|
||||||
<net.osmand.plus.widgets.TextViewEx
|
<net.osmand.plus.widgets.TextViewEx
|
||||||
|
android:id="@+id/check_box_title"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="@dimen/content_padding"
|
android:layout_marginEnd="@dimen/content_padding"
|
||||||
|
|
|
@ -380,7 +380,7 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra
|
||||||
AndroidUiHelper.updateVisibility(dismissButton, buttonTextId != DEFAULT_VALUE);
|
AndroidUiHelper.updateVisibility(dismissButton, buttonTextId != DEFAULT_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupRightButton() {
|
protected void setupRightButton() {
|
||||||
rightButton = buttonsContainer.findViewById(R.id.right_bottom_button);
|
rightButton = buttonsContainer.findViewById(R.id.right_bottom_button);
|
||||||
rightButton.getLayoutParams().height = getRightButtonHeight();
|
rightButton.getLayoutParams().height = getRightButtonHeight();
|
||||||
int buttonTextId = getRightBottomButtonTextId();
|
int buttonTextId = getRightBottomButtonTextId();
|
||||||
|
|
|
@ -0,0 +1,301 @@
|
||||||
|
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.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.SimpleBottomSheetItem;
|
||||||
|
import net.osmand.plus.base.bottomsheetmenu.simpleitems.SimpleDividerItem;
|
||||||
|
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 {
|
||||||
|
|
||||||
|
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 activeColorRes;
|
||||||
|
private int secondaryColorRes;
|
||||||
|
|
||||||
|
private final List<SelectableItem> allItems = new ArrayList<>();
|
||||||
|
private final List<SelectableItem> selectedItems = new ArrayList<>();
|
||||||
|
private SelectionUpdateListener selectionUpdateListener;
|
||||||
|
private OnApplySelectionListener onApplySelectionListener;
|
||||||
|
|
||||||
|
public static final String TAG = SelectMultipleItemsBottomSheet.class.getSimpleName();
|
||||||
|
|
||||||
|
@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));
|
||||||
|
createListItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return new SimpleBottomSheetItem.Builder().setCustomView(view).create();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createListItems() {
|
||||||
|
for (final SelectableItem item : allItems) {
|
||||||
|
boolean checked = selectedItems.contains(item);
|
||||||
|
final BottomSheetItemWithCompoundButton[] uiItem = new BottomSheetItemWithCompoundButton[1];
|
||||||
|
final Builder builder = (BottomSheetItemWithCompoundButton.Builder) new Builder();
|
||||||
|
builder.setChecked(checked)
|
||||||
|
.setButtonTintList(AndroidUtils.createCheckedColorStateList(app, secondaryColorRes, activeColorRes))
|
||||||
|
.setLayoutId(R.layout.bottom_sheet_item_with_descr_and_checkbox_56dp)
|
||||||
|
.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
boolean checked = !uiItem[0].isChecked();
|
||||||
|
uiItem[0].setChecked(checked);
|
||||||
|
SelectableItem tag = (SelectableItem) uiItem[0].getTag();
|
||||||
|
if (checked) {
|
||||||
|
selectedItems.add(tag);
|
||||||
|
} else {
|
||||||
|
selectedItems.remove(tag);
|
||||||
|
}
|
||||||
|
onSelectedItemsChanged();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setTag(item);
|
||||||
|
setupListItem(builder, item);
|
||||||
|
uiItem[0] = builder.create();
|
||||||
|
items.add(uiItem[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setupRightButton() {
|
||||||
|
super.setupRightButton();
|
||||||
|
applyButtonTitle = rightButton.findViewById(R.id.button_text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onRightBottomButtonClick() {
|
||||||
|
if (onApplySelectionListener != null) {
|
||||||
|
onApplySelectionListener.onSelectionApplied(selectedItems);
|
||||||
|
}
|
||||||
|
dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onSelectedItemsChanged() {
|
||||||
|
updateSelectAllButton();
|
||||||
|
updateSelectedSizeView();
|
||||||
|
updateApplyButtonEnable();
|
||||||
|
if (selectionUpdateListener != null) {
|
||||||
|
selectionUpdateListener.onSelectionUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getRightBottomButtonTextId() {
|
||||||
|
return R.string.shared_string_apply;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean useVerticalButtons() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupListItem(Builder builder, SelectableItem item) {
|
||||||
|
builder.setTitle(item.title);
|
||||||
|
builder.setDescription(item.description);
|
||||||
|
builder.setIcon(uiUtilities.getIcon(item.iconId, activeColorRes));
|
||||||
|
}
|
||||||
|
|
||||||
|
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() {
|
||||||
|
if (Algorithms.isEmpty(selectedItems)) {
|
||||||
|
rightButton.setEnabled(false);
|
||||||
|
} else {
|
||||||
|
rightButton.setEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateItems(boolean checked) {
|
||||||
|
for (BaseBottomSheetItem item : items) {
|
||||||
|
if (item instanceof BottomSheetItemWithCompoundButton) {
|
||||||
|
((BottomSheetItemWithCompoundButton) item).setChecked(checked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(@NonNull String title) {
|
||||||
|
this.title.setText(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(@NonNull String description) {
|
||||||
|
this.description.setText(description);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfirmButtonTitle(@NonNull String confirmButtonTitle) {
|
||||||
|
applyButtonTitle.setText(confirmButtonTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setItems(List<SelectableItem> allItems) {
|
||||||
|
if (!Algorithms.isEmpty(allItems)) {
|
||||||
|
this.allItems.addAll(allItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setSelectedItems(List<SelectableItem> selected) {
|
||||||
|
if (!Algorithms.isEmpty(selected)) {
|
||||||
|
this.selectedItems.addAll(selected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SelectableItem> getSelectedItems() {
|
||||||
|
return selectedItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
if (requireActivity().isChangingConfigurations()) {
|
||||||
|
dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 void setSelectionUpdateListener(SelectionUpdateListener selectionUpdateListener) {
|
||||||
|
this.selectionUpdateListener = selectionUpdateListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnApplySelectionListener(OnApplySelectionListener onApplySelectionListener) {
|
||||||
|
this.onApplySelectionListener = onApplySelectionListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface SelectionUpdateListener {
|
||||||
|
void onSelectionUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getObject() {
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -2,6 +2,8 @@ package net.osmand.plus.download;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import net.osmand.AndroidUtils;
|
import net.osmand.AndroidUtils;
|
||||||
import net.osmand.IndexConstants;
|
import net.osmand.IndexConstants;
|
||||||
import net.osmand.map.OsmandRegions;
|
import net.osmand.map.OsmandRegions;
|
||||||
|
@ -446,9 +448,11 @@ public class DownloadActivityType {
|
||||||
return fileName;
|
return fileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
public String getBasename(DownloadItem downloadItem) {
|
public String getBasename(@NonNull DownloadItem downloadItem) {
|
||||||
String fileName = downloadItem.getFileName();
|
String fileName = downloadItem.getFileName();
|
||||||
|
if (Algorithms.isEmpty(fileName)) return fileName;
|
||||||
|
|
||||||
if (fileName.endsWith(IndexConstants.EXTRA_ZIP_EXT)) {
|
if (fileName.endsWith(IndexConstants.EXTRA_ZIP_EXT)) {
|
||||||
return fileName.substring(0, fileName.length() - IndexConstants.EXTRA_ZIP_EXT.length());
|
return fileName.substring(0, fileName.length() - IndexConstants.EXTRA_ZIP_EXT.length());
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,8 +35,7 @@ public abstract class DownloadItem {
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public String getSizeDescription(Context ctx) {
|
public String getSizeDescription(Context ctx) {
|
||||||
String size = String.format(Locale.US, "%.2f", getSizeToDownloadInMb());
|
return getFormattedMb(ctx, getSizeToDownloadInMb());
|
||||||
return ctx.getString(R.string.ltr_or_rtl_combine_via_space, size, "MB");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getVisibleName(Context ctx, OsmandRegions osmandRegions) {
|
public String getVisibleName(Context ctx, OsmandRegions osmandRegions) {
|
||||||
|
@ -51,6 +50,7 @@ public abstract class DownloadItem {
|
||||||
return type.getVisibleDescription(this, ctx);
|
return type.getVisibleDescription(this, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
public String getBasename() {
|
public String getBasename() {
|
||||||
return type.getBasename(this);
|
return type.getBasename(this);
|
||||||
}
|
}
|
||||||
|
@ -65,11 +65,17 @@ public abstract class DownloadItem {
|
||||||
|
|
||||||
public abstract boolean hasActualDataToDownload();
|
public abstract boolean hasActualDataToDownload();
|
||||||
|
|
||||||
public abstract boolean isDownloading(DownloadIndexesThread thread);
|
public abstract boolean isDownloading(@NonNull DownloadIndexesThread thread);
|
||||||
|
|
||||||
public abstract String getFileName();
|
public abstract String getFileName();
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public abstract List<File> getDownloadedFiles(OsmandApplication app);
|
public abstract List<File> getDownloadedFiles(@NonNull OsmandApplication app);
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public static String getFormattedMb(@NonNull Context ctx, double sizeInMb) {
|
||||||
|
String size = String.format(Locale.US, "%.2f", sizeInMb);
|
||||||
|
return ctx.getString(R.string.ltr_or_rtl_combine_via_space, size, "MB");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -481,9 +481,10 @@ public class DownloadResources extends DownloadResourceGroup {
|
||||||
if (group != null) {
|
if (group != null) {
|
||||||
boolean listModified = false;
|
boolean listModified = false;
|
||||||
List<IndexItem> indexesList = group.getIndividualResources();
|
List<IndexItem> indexesList = group.getIndividualResources();
|
||||||
|
List<WorldRegion> regionsToCollect = removeDuplicateRegions(subRegions);
|
||||||
for (DownloadActivityType type : DownloadActivityType.values()) {
|
for (DownloadActivityType type : DownloadActivityType.values()) {
|
||||||
if (!doesListContainIndexWithType(indexesList, type)) {
|
if (!doesListContainIndexWithType(indexesList, type)) {
|
||||||
List<IndexItem> indexesFromSubRegions = collectIndexesOfType(subRegions, type);
|
List<IndexItem> indexesFromSubRegions = collectIndexesOfType(regionsToCollect, type);
|
||||||
if (indexesFromSubRegions != null) {
|
if (indexesFromSubRegions != null) {
|
||||||
group.addItem(new MultipleIndexItem(region, indexesFromSubRegions, type));
|
group.addItem(new MultipleIndexItem(region, indexesFromSubRegions, type));
|
||||||
listModified = true;
|
listModified = true;
|
||||||
|
@ -510,7 +511,7 @@ public class DownloadResources extends DownloadResourceGroup {
|
||||||
@Nullable
|
@Nullable
|
||||||
private List<IndexItem> collectIndexesOfType(@NonNull List<WorldRegion> regions,
|
private List<IndexItem> collectIndexesOfType(@NonNull List<WorldRegion> regions,
|
||||||
@NonNull DownloadActivityType type) {
|
@NonNull DownloadActivityType type) {
|
||||||
Map<WorldRegion, IndexItem> collectedIndexes = new LinkedHashMap<>();
|
List<IndexItem> collectedIndexes = new ArrayList<>();
|
||||||
for (WorldRegion region : regions) {
|
for (WorldRegion region : regions) {
|
||||||
List<IndexItem> regionIndexes = getIndexItems(region);
|
List<IndexItem> regionIndexes = getIndexItems(region);
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
|
@ -518,36 +519,33 @@ public class DownloadResources extends DownloadResourceGroup {
|
||||||
for (IndexItem index : regionIndexes) {
|
for (IndexItem index : regionIndexes) {
|
||||||
if (index.getType() == type) {
|
if (index.getType() == type) {
|
||||||
found = true;
|
found = true;
|
||||||
collectedIndexes.put(region, index);
|
collectedIndexes.add(index);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) return null;
|
if (!found) return null;
|
||||||
}
|
}
|
||||||
return removeDuplicates(collectedIndexes);
|
return collectedIndexes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<IndexItem> removeDuplicates(Map<WorldRegion, IndexItem> collectedIndexes) {
|
private List<WorldRegion> removeDuplicateRegions(List<WorldRegion> regions) {
|
||||||
List<WorldRegion> regions = new ArrayList<>(collectedIndexes.keySet());
|
|
||||||
// collect duplicates
|
|
||||||
Set<WorldRegion> duplicates = new HashSet<>();
|
Set<WorldRegion> duplicates = new HashSet<>();
|
||||||
for (int i = 0; i < regions.size() - 1; i++) {
|
for (int i = 0; i < regions.size() - 1; i++) {
|
||||||
WorldRegion r1 = regions.get(i);
|
WorldRegion r1 = regions.get(i);
|
||||||
for (int j = i + 1; j < regions.size(); j++) {
|
for (int j = i + 1; j < regions.size(); j++) {
|
||||||
WorldRegion r2 = regions.get(j);
|
WorldRegion r2 = regions.get(j);
|
||||||
if (r1.containsRegion(r2)) {
|
if (r1.containsRegion(r2)) {
|
||||||
duplicates.add(r1);
|
|
||||||
} else if (r2.containsRegion(r1)) {
|
|
||||||
duplicates.add(r2);
|
duplicates.add(r2);
|
||||||
|
} else if (r2.containsRegion(r1)) {
|
||||||
|
duplicates.add(r1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// remove duplicates
|
for (WorldRegion region : duplicates) {
|
||||||
for (WorldRegion key : duplicates) {
|
regions.remove(region);
|
||||||
collectedIndexes.remove(key);
|
|
||||||
}
|
}
|
||||||
return new ArrayList<>(collectedIndexes.values());
|
return regions;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buildRegionsGroups(WorldRegion region, DownloadResourceGroup group) {
|
private void buildRegionsGroups(WorldRegion region, DownloadResourceGroup group) {
|
||||||
|
|
|
@ -57,7 +57,7 @@ public class IndexItem extends DownloadItem implements Comparable<IndexItem> {
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public List<File> getDownloadedFiles(OsmandApplication app) {
|
public List<File> getDownloadedFiles(@NonNull OsmandApplication app) {
|
||||||
File targetFile = getTargetFile(app);
|
File targetFile = getTargetFile(app);
|
||||||
if (targetFile.exists()) {
|
if (targetFile.exists()) {
|
||||||
return Collections.singletonList(targetFile);
|
return Collections.singletonList(targetFile);
|
||||||
|
@ -167,6 +167,10 @@ public class IndexItem extends DownloadItem implements Comparable<IndexItem> {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getDate(@NonNull DateFormat dateFormat, boolean remote) {
|
||||||
|
return remote ? getRemoteDate(dateFormat) : getLocalDate(dateFormat);
|
||||||
|
}
|
||||||
|
|
||||||
public String getRemoteDate(DateFormat dateFormat) {
|
public String getRemoteDate(DateFormat dateFormat) {
|
||||||
if(timestamp <= 0) {
|
if(timestamp <= 0) {
|
||||||
return "";
|
return "";
|
||||||
|
@ -175,7 +179,7 @@ public class IndexItem extends DownloadItem implements Comparable<IndexItem> {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String getLocalDate(DateFormat dateFormat) {
|
private String getLocalDate(@NonNull DateFormat dateFormat) {
|
||||||
if(localTimestamp <= 0) {
|
if(localTimestamp <= 0) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -214,7 +218,7 @@ public class IndexItem extends DownloadItem implements Comparable<IndexItem> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDownloading(DownloadIndexesThread thread) {
|
public boolean isDownloading(@NonNull DownloadIndexesThread thread) {
|
||||||
return thread.isDownloading(this);
|
return thread.isDownloading(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ public class MultipleIndexItem extends DownloadItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDownloading(DownloadIndexesThread thread) {
|
public boolean isDownloading(@NonNull DownloadIndexesThread thread) {
|
||||||
for (IndexItem item : items) {
|
for (IndexItem item : items) {
|
||||||
if (thread.isDownloading(item)) {
|
if (thread.isDownloading(item)) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -76,7 +76,7 @@ public class MultipleIndexItem extends DownloadItem {
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public List<File> getDownloadedFiles(OsmandApplication app) {
|
public List<File> getDownloadedFiles(@NonNull OsmandApplication app) {
|
||||||
List<File> result = new ArrayList<>();
|
List<File> result = new ArrayList<>();
|
||||||
for (IndexItem item : items) {
|
for (IndexItem item : items) {
|
||||||
result.addAll(item.getDownloadedFiles(app));
|
result.addAll(item.getDownloadedFiles(app));
|
||||||
|
|
113
OsmAnd/src/net/osmand/plus/download/MultipleIndexesUiHelper.java
Normal file
113
OsmAnd/src/net/osmand/plus/download/MultipleIndexesUiHelper.java
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
package net.osmand.plus.download;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
|
import net.osmand.map.OsmandRegions;
|
||||||
|
import net.osmand.plus.OsmandApplication;
|
||||||
|
import net.osmand.plus.R;
|
||||||
|
import net.osmand.plus.base.SelectMultipleItemsBottomSheet;
|
||||||
|
import net.osmand.plus.base.SelectMultipleItemsBottomSheet.OnApplySelectionListener;
|
||||||
|
import net.osmand.plus.base.SelectMultipleItemsBottomSheet.SelectableItem;
|
||||||
|
import net.osmand.plus.base.SelectMultipleItemsBottomSheet.SelectionUpdateListener;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class MultipleIndexesUiHelper {
|
||||||
|
|
||||||
|
public static void showDialog(@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));
|
||||||
|
|
||||||
|
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() {
|
||||||
|
dialog.setTitle(app.getString(R.string.welmode_download_maps));
|
||||||
|
String total = app.getString(R.string.shared_string_total);
|
||||||
|
double sizeToDownload = getDownloadSizeInMb(dialog.getSelectedItems());
|
||||||
|
String size = DownloadItem.getFormattedMb(app, sizeToDownload);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
dialog.setOnApplySelectionListener(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 List<IndexItem> getIndexesToDownload(MultipleIndexItem multipleIndexItem) {
|
||||||
|
if (multipleIndexItem.hasActualDataToDownload()) {
|
||||||
|
// download left regions
|
||||||
|
return multipleIndexItem.getIndexesToDownload();
|
||||||
|
} else {
|
||||||
|
// download all regions again
|
||||||
|
return multipleIndexItem.getAllIndexes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -35,6 +35,7 @@ import net.osmand.plus.download.DownloadActivity;
|
||||||
import net.osmand.plus.download.DownloadActivity.BannerAndDownloadFreeVersion;
|
import net.osmand.plus.download.DownloadActivity.BannerAndDownloadFreeVersion;
|
||||||
import net.osmand.plus.download.DownloadActivityType;
|
import net.osmand.plus.download.DownloadActivityType;
|
||||||
import net.osmand.plus.download.DownloadIndexesThread.DownloadEvents;
|
import net.osmand.plus.download.DownloadIndexesThread.DownloadEvents;
|
||||||
|
import net.osmand.plus.download.DownloadItem;
|
||||||
import net.osmand.plus.download.DownloadResourceGroup;
|
import net.osmand.plus.download.DownloadResourceGroup;
|
||||||
import net.osmand.plus.download.DownloadResources;
|
import net.osmand.plus.download.DownloadResources;
|
||||||
import net.osmand.plus.download.DownloadValidationManager;
|
import net.osmand.plus.download.DownloadValidationManager;
|
||||||
|
@ -504,10 +505,10 @@ public class DownloadResourceGroupFragment extends DialogFragment implements Dow
|
||||||
|
|
||||||
DownloadItemFragment downloadItemFragment = DownloadItemFragment.createInstance(regionId, childPosition);
|
DownloadItemFragment downloadItemFragment = DownloadItemFragment.createInstance(regionId, childPosition);
|
||||||
((DownloadActivity) getActivity()).showDialog(getActivity(), downloadItemFragment);
|
((DownloadActivity) getActivity()).showDialog(getActivity(), downloadItemFragment);
|
||||||
} else if (child instanceof IndexItem) {
|
} else if (child instanceof DownloadItem) {
|
||||||
IndexItem indexItem = (IndexItem) child;
|
DownloadItem downloadItem = (DownloadItem) child;
|
||||||
ItemViewHolder vh = (ItemViewHolder) v.getTag();
|
ItemViewHolder vh = (ItemViewHolder) v.getTag();
|
||||||
OnClickListener ls = vh.getRightButtonAction(indexItem, vh.getClickAction(indexItem));
|
OnClickListener ls = vh.getRightButtonAction(downloadItem, vh.getClickAction(downloadItem));
|
||||||
ls.onClick(v);
|
ls.onClick(v);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,8 @@ import net.osmand.plus.download.DownloadActivityType;
|
||||||
import net.osmand.plus.download.DownloadResourceGroup;
|
import net.osmand.plus.download.DownloadResourceGroup;
|
||||||
import net.osmand.plus.download.DownloadResources;
|
import net.osmand.plus.download.DownloadResources;
|
||||||
import net.osmand.plus.download.IndexItem;
|
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.MultipleIndexItem;
|
||||||
import net.osmand.plus.download.ui.LocalIndexesFragment.LocalIndexOperationTask;
|
import net.osmand.plus.download.ui.LocalIndexesFragment.LocalIndexOperationTask;
|
||||||
import net.osmand.plus.helpers.FileNameTranslationHelper;
|
import net.osmand.plus.helpers.FileNameTranslationHelper;
|
||||||
|
@ -236,7 +238,7 @@ public class ItemViewHolder {
|
||||||
String pattern = context.getString(R.string.ltr_or_rtl_combine_via_bold_point);
|
String pattern = context.getString(R.string.ltr_or_rtl_combine_via_bold_point);
|
||||||
String type = item.getType().getString(context);
|
String type = item.getType().getString(context);
|
||||||
String size = item.getSizeDescription(context);
|
String size = item.getSizeDescription(context);
|
||||||
String date = showRemoteDate ? item.getRemoteDate(dateFormat) : item.getLocalDate(dateFormat);
|
String date = item.getDate(dateFormat, showRemoteDate);
|
||||||
String fullDescription = String.format(pattern, size, date);
|
String fullDescription = String.format(pattern, size, date);
|
||||||
if (showTypeInDesc) {
|
if (showTypeInDesc) {
|
||||||
fullDescription = String.format(pattern, type, fullDescription);
|
fullDescription = String.format(pattern, type, fullDescription);
|
||||||
|
@ -473,23 +475,26 @@ public class ItemViewHolder {
|
||||||
|
|
||||||
private void startDownload(DownloadItem item) {
|
private void startDownload(DownloadItem item) {
|
||||||
if (item instanceof MultipleIndexItem) {
|
if (item instanceof MultipleIndexItem) {
|
||||||
MultipleIndexItem multipleIndexItem = (MultipleIndexItem) item;
|
selectIndexesToDownload((MultipleIndexItem) item);
|
||||||
List<IndexItem> indexes;
|
|
||||||
if (multipleIndexItem.hasActualDataToDownload()) {
|
|
||||||
// download left regions
|
|
||||||
indexes = multipleIndexItem.getIndexesToDownload();
|
|
||||||
} else {
|
|
||||||
// download all regions again
|
|
||||||
indexes = multipleIndexItem.getAllIndexes();
|
|
||||||
}
|
|
||||||
IndexItem[] indexesArray = new IndexItem[indexes.size()];
|
|
||||||
context.startDownload(indexes.toArray(indexesArray));
|
|
||||||
} else if (item instanceof IndexItem) {
|
} else if (item instanceof IndexItem) {
|
||||||
IndexItem indexItem = (IndexItem) item;
|
IndexItem indexItem = (IndexItem) item;
|
||||||
context.startDownload(indexItem);
|
context.startDownload(indexItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void selectIndexesToDownload(MultipleIndexItem item) {
|
||||||
|
OsmandApplication app = context.getMyApplication();
|
||||||
|
MultipleIndexesUiHelper.showDialog(item, context, app, dateFormat, showRemoteDate,
|
||||||
|
new SelectItemsToDownloadListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemsToDownloadSelected(List<IndexItem> indexes) {
|
||||||
|
IndexItem[] indexesArray = new IndexItem[indexes.size()];
|
||||||
|
context.startDownload(indexes.toArray(indexesArray));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private void confirmRemove(@NonNull final DownloadItem downloadItem,
|
private void confirmRemove(@NonNull final DownloadItem downloadItem,
|
||||||
@NonNull final List<File> downloadedFiles) {
|
@NonNull final List<File> downloadedFiles) {
|
||||||
OsmandApplication app = context.getMyApplication();
|
OsmandApplication app = context.getMyApplication();
|
||||||
|
|
Loading…
Reference in a new issue