diff --git a/OsmAnd/res/layout/fragment_import.xml b/OsmAnd/res/layout/fragment_import.xml index 792f7db928..29d43b823e 100644 --- a/OsmAnd/res/layout/fragment_import.xml +++ b/OsmAnd/res/layout/fragment_import.xml @@ -1,136 +1,139 @@ - - - - - - - - - - - - - + android:background="?attr/activity_background_basic"> - - + android:listSelector="@android:color/transparent" + android:paddingBottom="@dimen/dialog_button_ex_height" + osmand:layout_behavior="@string/appbar_scrolling_view_behavior" /> + android:orientation="vertical"> - + + + android:orientation="horizontal" + android:paddingLeft="@dimen/content_padding" + android:paddingTop="@dimen/content_padding_small" + android:paddingRight="@dimen/content_padding" + android:paddingBottom="@dimen/content_padding_small"> - + android:layout_weight="1"> - + - + - + - + android:layout_weight="1" + android:background="?attr/dlg_btn_primary"> - + + + + + - \ No newline at end of file + + + + + + + + + + + + + + + diff --git a/OsmAnd/res/layout/fragment_import_duplicates.xml b/OsmAnd/res/layout/fragment_import_duplicates.xml index 6682b69838..a12f52d4b6 100644 --- a/OsmAnd/res/layout/fragment_import_duplicates.xml +++ b/OsmAnd/res/layout/fragment_import_duplicates.xml @@ -1,107 +1,142 @@ - + xmlns:tools="http://schemas.android.com/tools" + android:background="?attr/activity_background_basic"> + + + + + + + + + + + + + + - + - + android:layout_height="match_parent" + android:orientation="vertical" + android:padding="@dimen/content_padding"> + + + + + + + + + + + + + + + + - + android:background="@android:color/transparent"> - - - - - - - - - + android:layout_height="@dimen/toolbar_height_expanded" + android:background="?attr/colorPrimary" + osmand:collapsedTitleTextAppearance="@style/AppBarTitle" + osmand:expandedTitleGravity="start|bottom" + osmand:expandedTitleTextAppearance="@style/AppBarTitle" + osmand:layout_scrollFlags="scroll|exitUntilCollapsed"> - + android:layout_height="@dimen/toolbar_height" + android:minHeight="@dimen/toolbar_height" + osmand:layout_collapseMode="pin" + osmand:layout_scrollFlags="scroll|enterAlways|exitUntilCollapsed" + osmand:title="@string/import_duplicates_title"> - + - + + + android:layout_height="@dimen/abp__shadow_height" + android:src="@drawable/preference_activity_action_bar_shadow" + tools:ignore="ContentDescription" /> - + - - - - - \ No newline at end of file + diff --git a/OsmAnd/res/layout/list_item_description_header.xml b/OsmAnd/res/layout/list_item_description_header.xml new file mode 100644 index 0000000000..7d0a15d436 --- /dev/null +++ b/OsmAnd/res/layout/list_item_description_header.xml @@ -0,0 +1,23 @@ + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/list_item_import.xml b/OsmAnd/res/layout/list_item_import.xml index 86e6498ba1..25042fd505 100644 --- a/OsmAnd/res/layout/list_item_import.xml +++ b/OsmAnd/res/layout/list_item_import.xml @@ -4,14 +4,14 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" + android:minHeight="@dimen/setting_list_item_small_height" android:orientation="vertical"> + android:gravity="center_vertical"> + android:orientation="vertical" + android:paddingTop="@dimen/content_padding_small" + android:paddingBottom="@dimen/content_padding_small"> @@ -37,6 +41,8 @@ android:id="@+id/sub_title" android:layout_width="match_parent" android:layout_height="wrap_content" + android:ellipsize="end" + android:maxLines="1" android:textColor="?android:textColorSecondary" android:textSize="@dimen/default_desc_text_size" tools:text="Navigation type: Car" /> diff --git a/OsmAnd/res/layout/profile_data_list_item_child.xml b/OsmAnd/res/layout/profile_data_list_item_child.xml index e0a04a1892..265cdd4275 100644 --- a/OsmAnd/res/layout/profile_data_list_item_child.xml +++ b/OsmAnd/res/layout/profile_data_list_item_child.xml @@ -4,6 +4,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" + android:minHeight="@dimen/setting_list_item_small_height" android:orientation="vertical"> + android:gravity="center_vertical"> + android:orientation="vertical" + android:paddingTop="@dimen/content_padding_small" + android:paddingBottom="@dimen/content_padding_small"> @@ -44,6 +48,8 @@ android:id="@+id/sub_title_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:ellipsize="end" + android:maxLines="1" android:textColor="?android:textColorSecondary" android:textSize="@dimen/default_desc_text_size" android:visibility="gone" diff --git a/OsmAnd/res/layout/profile_data_list_item_group.xml b/OsmAnd/res/layout/profile_data_list_item_group.xml index 7f76a45a4e..87dc4eab9f 100644 --- a/OsmAnd/res/layout/profile_data_list_item_group.xml +++ b/OsmAnd/res/layout/profile_data_list_item_group.xml @@ -64,12 +64,24 @@ android:layout_marginBottom="@dimen/content_padding" android:background="?attr/list_divider" /> - + + + + + diff --git a/OsmAnd/res/values-ar/strings.xml b/OsmAnd/res/values-ar/strings.xml index 06f4d91592..10abca6c6b 100644 --- a/OsmAnd/res/values-ar/strings.xml +++ b/OsmAnd/res/values-ar/strings.xml @@ -3438,7 +3438,6 @@ \n \nسيبقى المكوّن الإضافي على الجهاز بعد إزالة OsmAnd. %1$s — %2$s — %3$s - أسلوب تقديم مخصص يحتوي ملف التعريف المستوردة على بيانات إضافية. انقر فوق \"استيراد\" لاستيراد بيانات ملف التعريف فقط أو حدد بيانات إضافية لاستيرادها. التطبيق الافتراضي (%s) تعطيل إعادة الحساب diff --git a/OsmAnd/res/values-da/strings.xml b/OsmAnd/res/values-da/strings.xml index ca3511ff23..36c7120fff 100644 --- a/OsmAnd/res/values-da/strings.xml +++ b/OsmAnd/res/values-da/strings.xml @@ -3500,5 +3500,4 @@ Repræsenterer område: %1$s x %2$s Medtag yderligere data Vælg yderligere data, der skal eksporteres sammen med profilen. Antarktis - Brugerdefineret renderingssstil \ No newline at end of file diff --git a/OsmAnd/res/values-de/strings.xml b/OsmAnd/res/values-de/strings.xml index ef397bc002..e1b869f11f 100644 --- a/OsmAnd/res/values-de/strings.xml +++ b/OsmAnd/res/values-de/strings.xml @@ -3533,7 +3533,6 @@ Lon %2$s Menü %1$s — %2$s — %3$s Routing - Benutzerdefinierter Rendering-Stil Zusätzliche Daten einschließen Das importierte Profil enthält zusätzliche Daten. Klicken Sie auf \'Importieren\', um nur Profildaten zu importieren, oder wählen Sie zusätzliche Daten zum Importieren aus. Sie können zusätzliche Daten zum Exportieren zusammen mit dem Profil auswählen. diff --git a/OsmAnd/res/values-eo/strings.xml b/OsmAnd/res/values-eo/strings.xml index f5ea1a20e8..66b9fa7e46 100644 --- a/OsmAnd/res/values-eo/strings.xml +++ b/OsmAnd/res/values-eo/strings.xml @@ -3516,7 +3516,6 @@ Indikas lokon: %1$s x %2$s" Menuo %1$s — %2$s — %3$s Kurs‑difinado - Propra stilo de bildigado Ampleksi kromajn datumojn La enportata profilo enhavas kromajn datumojn. Frapetu “enporti” por enporti nur profilajn datumojn aŭ elektu kromajn datumojn por enporti. Vi povas elekti kromajn datumojn por elporti kune kun la profilo. diff --git a/OsmAnd/res/values-es-rAR/strings.xml b/OsmAnd/res/values-es-rAR/strings.xml index d7a8d9ed0b..7802c9ba0e 100644 --- a/OsmAnd/res/values-es-rAR/strings.xml +++ b/OsmAnd/res/values-es-rAR/strings.xml @@ -3535,7 +3535,6 @@ Lon %2$s Menú %1$s → %2$s → %3$s Enrutamiento - Vista de estilo propia Incluir datos adicionales El perfil importado contiene datos adicionales. Pulsa en «Importar» para importar sólo datos de perfil o marca datos adicionales para importar. Puedes marcar datos adicionales para exportar junto con el perfil. diff --git a/OsmAnd/res/values-es-rUS/strings.xml b/OsmAnd/res/values-es-rUS/strings.xml index 5ad87acde6..12634c375e 100644 --- a/OsmAnd/res/values-es-rUS/strings.xml +++ b/OsmAnd/res/values-es-rUS/strings.xml @@ -3535,7 +3535,6 @@ Lon %2$s Menú %1$s → %2$s → %3$s Enrutamiento - Vista de estilo propia Incluir datos adicionales El perfil importado contiene datos adicionales. Pulsa en «Importar» para importar sólo datos de perfil o marca datos adicionales para importar. Puedes marcar datos adicionales para exportar junto con el perfil. diff --git a/OsmAnd/res/values-es/strings.xml b/OsmAnd/res/values-es/strings.xml index 9a7c209446..0279dc7552 100644 --- a/OsmAnd/res/values-es/strings.xml +++ b/OsmAnd/res/values-es/strings.xml @@ -3515,7 +3515,6 @@ Menú %1$s — %2$s — %3$s Enrutado - Estilo de representación personalizado Incluir datos adicionales El perfil importado contiene datos adicionales. Pulsa en Importar para importar solo datos de perfil o seleccione datos adicionales para importar. Puedes seleccionar datos adicionales para exportar junto con el perfil. diff --git a/OsmAnd/res/values-fa/strings.xml b/OsmAnd/res/values-fa/strings.xml index aea3553957..0a8c8fd502 100644 --- a/OsmAnd/res/values-fa/strings.xml +++ b/OsmAnd/res/values-fa/strings.xml @@ -3561,7 +3561,6 @@ منو %1$s — %2$s — %3$s مسیریابی - سبک رندر سفارشی شامل دادهٔ بیشتر پروفایلِ درون‌بردی حاوی دادهٔ بیشتری است. «درون‌برد» را بزنید تا فقط دادهٔ پروفایل درون‌برد شود. «دادهٔ بیشتر» را انتخاب کنید تا آن را نیز درون‌برد کنید. می‌توانید دادهٔ بیشتری را انتخاب کنید تا همراه با پروفایل برون‌برد کنید. diff --git a/OsmAnd/res/values-fr/strings.xml b/OsmAnd/res/values-fr/strings.xml index b8c06cf7f9..61a1cf4988 100644 --- a/OsmAnd/res/values-fr/strings.xml +++ b/OsmAnd/res/values-fr/strings.xml @@ -3505,7 +3505,6 @@ représentant la zone : %1$s x %2$s Menu %1$s — %2$s — %3$s Calcul d\'itinéraire - Style de rendu personnalisé Inclure des données supplémentaires Le profil importé contient des données supplémentaires. Cliquez sur Importer pour n\'importer que les données de profil ou sélectionnez des données supplémentaires à importer. Vous pouvez sélectionner des données supplémentaires à exporter en même temps que le profil. diff --git a/OsmAnd/res/values-gl/strings.xml b/OsmAnd/res/values-gl/strings.xml index f0f5bdf4ef..43ab705271 100644 --- a/OsmAnd/res/values-gl/strings.xml +++ b/OsmAnd/res/values-gl/strings.xml @@ -3585,7 +3585,6 @@ Lon %2$s Menú %1$s — %2$s — %3$s Enrutamento - Estilo de renderización personalizado Incluír datos adicionais O perfil importado contén datos adicionais. Preme en \"Importar\" para importar só datos de perfil ou marca datos adicionais para importar. Podes marcar datos adicionais para exportar ó carón do perfil. diff --git a/OsmAnd/res/values-is/strings.xml b/OsmAnd/res/values-is/strings.xml index 3392118440..6dc1d6ecc6 100644 --- a/OsmAnd/res/values-is/strings.xml +++ b/OsmAnd/res/values-is/strings.xml @@ -3513,7 +3513,6 @@ Stendur fyrir svæði: %1$s x %2$s Valmynd %1$s — %2$s — %3$s Leiðagerð - Sérsniðinn myndgerðaðrstíll Taka með viðbótargögn Suðurskautslandið Þetta er sjálfgefið óvirkt, ef OsmAnd keyrir í forgrunni rennur skjárinn ekki út á tíma. diff --git a/OsmAnd/res/values-ja/strings.xml b/OsmAnd/res/values-ja/strings.xml index d174512f76..fa86b1cdb2 100644 --- a/OsmAnd/res/values-ja/strings.xml +++ b/OsmAnd/res/values-ja/strings.xml @@ -3536,7 +3536,6 @@ POIの更新は利用できません メニュー %1$s — %2$s — %3$s ルート検索 - 描写スタイル 追加データを内包 インポートされたプロファイルには追加データが含まれています。 [インポート]をタップしてプロファイルデータのみをインポートするか、インポートする追加データを選択してください。 プロファイルとともにエクスポートする追加データを選択できます。 diff --git a/OsmAnd/res/values-lv/strings.xml b/OsmAnd/res/values-lv/strings.xml index 190a01101f..7d4e18a073 100644 --- a/OsmAnd/res/values-lv/strings.xml +++ b/OsmAnd/res/values-lv/strings.xml @@ -3278,7 +3278,6 @@ No Afganistānas līdz Zimbabvei, no Austrālijas līdz ASV, Argentīna, Brazīl Izvēlne %1$s — %2$s — %3$s Maršrutēšana - Pielāgots renderēšanas stils Iekļaut papildus datus Importētais profils satur papildus datus. Spiediet uz Importēt, lai importētu tikai profilu datus vai izvēlieties arī papildus datus, ko importēt. Jūs varat izvēlēties arī papildus datus, ko eksportēt kopā ar profilu. diff --git a/OsmAnd/res/values-pl/strings.xml b/OsmAnd/res/values-pl/strings.xml index b131841975..b1a52241dc 100644 --- a/OsmAnd/res/values-pl/strings.xml +++ b/OsmAnd/res/values-pl/strings.xml @@ -3513,7 +3513,6 @@ Reprezentuje obszar: %1$s x %2$s \n \nWtyczka pozostanie na urządzeniu po usunięciu OsmAnd. %1$s — %2$s — %3$s - Własny styl wyświetlania Uwzględnij dodatkowe dane Zaimportowany profil zawiera dodatkowe dane. Kliknij przycisk Importuj, aby zaimportować tylko dane profilu lub wybierz dodatkowe dane do zaimportowania. Można wybrać dodatkowe dane do wyeksportowania wraz z profilem. diff --git a/OsmAnd/res/values-pt-rBR/strings.xml b/OsmAnd/res/values-pt-rBR/strings.xml index c72a1b91f6..efb7900875 100644 --- a/OsmAnd/res/values-pt-rBR/strings.xml +++ b/OsmAnd/res/values-pt-rBR/strings.xml @@ -3522,7 +3522,6 @@ Pôr do Sol: %2$s Menu %1$s — %2$s — %3$s Roteamento - Estilo de renderização personalizado Incluir dados adicionais O perfil importado contém dados adicionais. Clique em Importar para importar apenas dados do perfil ou selecione dados adicionais a serem importados. Você pode selecionar dados adicionais para exportar junto com o perfil. diff --git a/OsmAnd/res/values-sc/strings.xml b/OsmAnd/res/values-sc/strings.xml index 853a0e9224..97a671b458 100644 --- a/OsmAnd/res/values-sc/strings.xml +++ b/OsmAnd/res/values-sc/strings.xml @@ -3501,7 +3501,6 @@ Pro praghere iscrie su còdighe intreu Menù %1$s — %2$s — %3$s Càrculu de s\'àndala - Istile de renderizatzione personalizadu Inclue datos additzionales Su profilu importadu tenet datos additzionales. Incarca in \"Importa\" pro importare sos datos de su profilu ebbia o ischerta sos datos additzionales de importare. Podes ischertare datos additzionales de esportare in paris cun su profilu. diff --git a/OsmAnd/res/values-sr/strings.xml b/OsmAnd/res/values-sr/strings.xml index c106036a67..c301fe8475 100644 --- a/OsmAnd/res/values-sr/strings.xml +++ b/OsmAnd/res/values-sr/strings.xml @@ -3501,7 +3501,6 @@ Додатак искључен Мени %1$s — %2$s — %3$s - Произвољни стил исцртавања Укључи додатне податке Увезени профил садржи додатне податке. Кликните на Увоз да увезете да увезете само профилне податке или одаберите које додатне податке увести. Поред профила, можете одабрати додатне податке за извоз. diff --git a/OsmAnd/res/values-tr/strings.xml b/OsmAnd/res/values-tr/strings.xml index 41c3332e91..eaf9545fab 100644 --- a/OsmAnd/res/values-tr/strings.xml +++ b/OsmAnd/res/values-tr/strings.xml @@ -3490,7 +3490,6 @@ Menü %1$s — %2$s — %3$s Yönlendirme - Özel görselleştirme stili İlave veriler ekle İçe aktarılan profil ilave veriler içermektedir. Yalnızca profil verilerini içe aktarmak için İçe Aktar\'ı tıklayın veya içe aktarılacak ilave verileri seçin. Profil ile birlikte dışa aktarılacak ilave veriler seçebilirsiniz. diff --git a/OsmAnd/res/values-uk/strings.xml b/OsmAnd/res/values-uk/strings.xml index 00d5fc2a34..51fc617548 100644 --- a/OsmAnd/res/values-uk/strings.xml +++ b/OsmAnd/res/values-uk/strings.xml @@ -3523,7 +3523,6 @@ Меню %1$s — %2$s — %3$s Маршрутизація - Власний стиль відмальовування Включати додаткові дані Імпортований профіль містить додаткові дані. Натисніть кнопку імпортувати, щоб імпортувати лише дані профілю або вибрати додаткові дані для імпорту. Ви можете вибрати додаткові дані для експорту разом із профілем. diff --git a/OsmAnd/res/values-zh-rTW/strings.xml b/OsmAnd/res/values-zh-rTW/strings.xml index 6fe4139dfa..ff30a34d1a 100644 --- a/OsmAnd/res/values-zh-rTW/strings.xml +++ b/OsmAnd/res/values-zh-rTW/strings.xml @@ -3525,7 +3525,6 @@ 選單 %1$s — %2$s — %3$s 路徑 - 自訂彩現樣式 包含額外資料 已匯入的設定檔包含了額外資料。點擊匯入僅匯入設定檔資料或選取額外的資料以匯入。 您可以選取額外的資料以與設定檔一起匯出。 diff --git a/OsmAnd/res/values/sizes.xml b/OsmAnd/res/values/sizes.xml index 020d67735b..fcd589b5d8 100644 --- a/OsmAnd/res/values/sizes.xml +++ b/OsmAnd/res/values/sizes.xml @@ -319,6 +319,7 @@ 56dp 56dp + 112dp 36dp 80dp @@ -353,5 +354,6 @@ 18dp 72dp 72dp + 42dp \ No newline at end of file diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 577fbd1a68..6984349329 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -72,7 +72,7 @@ Sunset at %1$s Sunrise at %1$s Routing - Custom rendering style + Rendering style Include additional data The imported profile contains additional data. Click Import to import only profile data or select additional data to import. You can select additional data to export along with the profile. diff --git a/OsmAnd/res/values/styles.xml b/OsmAnd/res/values/styles.xml index 2450784402..4e221e33f8 100644 --- a/OsmAnd/res/values/styles.xml +++ b/OsmAnd/res/values/styles.xml @@ -749,4 +749,9 @@ ?attr/app_bar_primary_item_color + + diff --git a/OsmAnd/src/net/osmand/plus/SettingsHelper.java b/OsmAnd/src/net/osmand/plus/SettingsHelper.java index ab8c98c0c7..af26bfaa5b 100644 --- a/OsmAnd/src/net/osmand/plus/SettingsHelper.java +++ b/OsmAnd/src/net/osmand/plus/SettingsHelper.java @@ -14,6 +14,7 @@ import com.google.gson.reflect.TypeToken; import net.osmand.IndexConstants; import net.osmand.PlatformUtil; +import net.osmand.data.LatLon; import net.osmand.map.ITileSource; import net.osmand.map.TileSourceManager; import net.osmand.osm.MapPoiTypes; @@ -21,6 +22,8 @@ import net.osmand.osm.PoiCategory; import net.osmand.plus.ApplicationMode.ApplicationModeBean; import net.osmand.plus.ApplicationMode.ApplicationModeBuilder; import net.osmand.plus.OsmandSettings.OsmandPreference; +import net.osmand.plus.helpers.AvoidSpecificRoads; +import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo; import net.osmand.plus.poi.PoiUIFilter; import net.osmand.plus.quickaction.QuickAction; import net.osmand.plus.quickaction.QuickActionRegistry; @@ -147,6 +150,7 @@ public class SettingsHelper { QUICK_ACTION, POI_UI_FILTERS, MAP_SOURCES, + AVOID_ROADS } public abstract static class SettingsItem { @@ -233,14 +237,16 @@ public class SettingsHelper { } SettingsItem item = (SettingsItem) other; - return item.getType() == getType() && item.getName().equals(getName()); + return item.getType() == getType() + && item.getName().equals(getName()) + && item.getFileName().equals(getFileName()); } } public abstract static class CollectionSettingsItem extends SettingsItem { protected List items; - protected List duplicateItems; + protected List duplicateItems = new ArrayList<>(); protected List existingItems; CollectionSettingsItem(@NonNull SettingsItemType type, @NonNull List items) { @@ -258,7 +264,17 @@ public class SettingsHelper { } @NonNull - public abstract List excludeDuplicateItems(); + public List excludeDuplicateItems() { + if (!items.isEmpty()) { + for (T item : items) { + if (isDuplicate(item)) { + duplicateItems.add(item); + } + } + } + items.removeAll(duplicateItems); + return duplicateItems; + } public abstract boolean isDuplicate(@NonNull T item); @@ -801,7 +817,7 @@ public class SettingsHelper { @Override public void readFromStream(@NonNull InputStream inputStream) throws IOException, IllegalArgumentException { OutputStream output; - if (shouldReplace || !file.exists()) { + if (!file.exists() || shouldReplace) { output = new FileOutputStream(file); } else { output = new FileOutputStream(renameFile(file)); @@ -864,19 +880,6 @@ public class SettingsHelper { return actionRegistry.generateUniqueName(item, app); } - @NonNull - @Override - public List excludeDuplicateItems() { - duplicateItems = new ArrayList<>(); - for (QuickAction item : items) { - if (isDuplicate(item)) { - duplicateItems.add(item); - } - } - items.removeAll(duplicateItems); - return duplicateItems; - } - @Override public void apply() { if (!items.isEmpty() || !duplicateItems.isEmpty()) { @@ -1054,22 +1057,6 @@ public class SettingsHelper { return false; } - @NonNull - @Override - public List excludeDuplicateItems() { - duplicateItems = new ArrayList<>(); - if (!items.isEmpty()) { - for (PoiUIFilter item : items) { - if (isDuplicate(item)) { - duplicateItems.add(item); - } - } - } - items.removeAll(duplicateItems); - return duplicateItems; - } - - @NonNull @Override public PoiUIFilter renameItem(@NonNull PoiUIFilter item) { @@ -1253,22 +1240,6 @@ public class SettingsHelper { } } - - @NonNull - @Override - public List excludeDuplicateItems() { - duplicateItems = new ArrayList<>(); - for (String name : existingItemsNames) { - for (ITileSource tileSource : items) { - if (name.equals(tileSource.getName())) { - duplicateItems.add(tileSource); - } - } - } - items.removeAll(duplicateItems); - return duplicateItems; - } - @NonNull @Override public ITileSource renameItem(@NonNull ITileSource item) { @@ -1440,6 +1411,183 @@ public class SettingsHelper { } } + public static class AvoidRoadsSettingsItem extends CollectionSettingsItem { + + private OsmandApplication app; + private OsmandSettings settings; + private AvoidSpecificRoads specificRoads; + + public AvoidRoadsSettingsItem(@NonNull OsmandApplication app, @NonNull List items) { + super(SettingsItemType.AVOID_ROADS, items); + this.app = app; + settings = app.getSettings(); + specificRoads = app.getAvoidSpecificRoads(); + existingItems = new ArrayList<>(specificRoads.getImpassableRoads().values()); + } + + AvoidRoadsSettingsItem(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException { + super(SettingsItemType.AVOID_ROADS, json); + this.app = app; + settings = app.getSettings(); + specificRoads = app.getAvoidSpecificRoads(); + existingItems = new ArrayList<>(specificRoads.getImpassableRoads().values()); + } + + @NonNull + @Override + public String getName() { + return "avoid_roads"; + } + + @NonNull + @Override + public String getPublicName(@NonNull Context ctx) { + return "avoid_roads"; + } + + @NonNull + @Override + public String getFileName() { + return getName() + ".json"; + } + + @Override + public void apply() { + if (!items.isEmpty() || !duplicateItems.isEmpty()) { + for (AvoidRoadInfo duplicate : duplicateItems) { + if (shouldReplace) { + LatLon latLon = new LatLon(duplicate.latitude, duplicate.longitude); + if (settings.removeImpassableRoad(latLon)) { + settings.addImpassableRoad(duplicate); + } + } else { + settings.addImpassableRoad(renameItem(duplicate)); + } + } + for (AvoidRoadInfo avoidRoad : items) { + settings.addImpassableRoad(avoidRoad); + } + specificRoads.loadImpassableRoads(); + specificRoads.initRouteObjects(true); + } + } + + @Override + public boolean isDuplicate(@NonNull AvoidRoadInfo item) { + return existingItems.contains(item); + } + + @Override + public boolean shouldReadOnCollecting() { + return true; + } + + @NonNull + @Override + public AvoidRoadInfo renameItem(@NonNull AvoidRoadInfo item) { + int number = 0; + while (true) { + number++; + AvoidRoadInfo renamedItem = new AvoidRoadInfo(); + renamedItem.name = item.name + "_" + number; + if (!isDuplicate(renamedItem)) { + renamedItem.id = item.id; + renamedItem.latitude = item.latitude; + renamedItem.longitude = item.longitude; + renamedItem.appModeKey = item.appModeKey; + return renamedItem; + } + } + } + + @NonNull + @Override + SettingsItemReader getReader() { + return new SettingsItemReader(this) { + @Override + public void readFromStream(@NonNull InputStream inputStream) throws IOException, IllegalArgumentException { + StringBuilder buf = new StringBuilder(); + try { + BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); + String str; + while ((str = in.readLine()) != null) { + buf.append(str); + } + } catch (IOException e) { + throw new IOException("Cannot read json body", e); + } + String jsonStr = buf.toString(); + if (Algorithms.isEmpty(jsonStr)) { + throw new IllegalArgumentException("Cannot find json body"); + } + final JSONObject json; + try { + items = new ArrayList<>(); + json = new JSONObject(jsonStr); + JSONArray jsonArray = json.getJSONArray("items"); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject object = jsonArray.getJSONObject(i); + double latitude = object.optDouble("latitude"); + double longitude = object.optDouble("longitude"); + String name = object.optString("name"); + String appModeKey = object.optString("appModeKey"); + AvoidRoadInfo roadInfo = new AvoidRoadInfo(); + roadInfo.id = 0; + roadInfo.latitude = latitude; + roadInfo.longitude = longitude; + roadInfo.name = name; + if (ApplicationMode.valueOfStringKey(appModeKey, null) != null) { + roadInfo.appModeKey = appModeKey; + } else { + roadInfo.appModeKey = app.getRoutingHelper().getAppMode().getStringKey(); + } + items.add(roadInfo); + } + } catch (JSONException e) { + throw new IllegalArgumentException("Json parse error", e); + } + } + }; + } + + @NonNull + @Override + SettingsItemWriter getWriter() { + return new SettingsItemWriter(this) { + @Override + public boolean writeToStream(@NonNull OutputStream outputStream) throws IOException { + JSONObject json = new JSONObject(); + JSONArray jsonArray = new JSONArray(); + if (!items.isEmpty()) { + try { + for (AvoidRoadInfo avoidRoad : items) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("latitude", avoidRoad.latitude); + jsonObject.put("longitude", avoidRoad.longitude); + jsonObject.put("name", avoidRoad.name); + jsonObject.put("appModeKey", avoidRoad.appModeKey); + jsonArray.put(jsonObject); + } + json.put("items", jsonArray); + } catch (JSONException e) { + LOG.error("Failed write to json", e); + } + } + if (json.length() > 0) { + try { + String s = json.toString(2); + outputStream.write(s.getBytes("UTF-8")); + } catch (JSONException e) { + LOG.error("Failed to write json to stream", e); + } + return true; + } + return false; + } + }; + } + } + private static class SettingsItemsFactory { private OsmandApplication app; @@ -1505,6 +1653,9 @@ public class SettingsHelper { case MAP_SOURCES: item = new MapSourcesSettingsItem(app, json); break; + case AVOID_ROADS: + item = new AvoidRoadsSettingsItem(app, json); + break; } return item; } @@ -1603,22 +1754,27 @@ public class SettingsHelper { } finally { zis.closeEntry(); } - SettingsItemsFactory itemsFactory; - try { - itemsFactory = new SettingsItemsFactory(app, itemsJson); - if (collecting) { + if (collecting) { + try { + SettingsItemsFactory itemsFactory = new SettingsItemsFactory(app, itemsJson); items.addAll(itemsFactory.getItems()); + } catch (IllegalArgumentException e) { + LOG.error("Error parsing items: " + itemsJson, e); + throw new IllegalArgumentException("No items"); + } catch (JSONException e) { + LOG.error("Error parsing items: " + itemsJson, e); + throw new IllegalArgumentException("No items"); } - } catch (IllegalArgumentException e) { - LOG.error("Error parsing items: " + itemsJson, e); - throw new IllegalArgumentException("No items"); - } catch (JSONException e) { - LOG.error("Error parsing items: " + itemsJson, e); - throw new IllegalArgumentException("No items"); } while ((entry = zis.getNextEntry()) != null) { String fileName = entry.getName(); - SettingsItem item = itemsFactory.getItemByFileName(fileName); + SettingsItem item = null; + for (SettingsItem settingsItem : items) { + if (settingsItem != null && settingsItem.getFileName().equals(fileName)) { + item = settingsItem; + break; + } + } if (item != null && collecting && item.shouldReadOnCollecting() || item != null && !collecting && !item.shouldReadOnCollecting()) { try { diff --git a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java index 5576793e2c..4025e127d5 100644 --- a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java +++ b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java @@ -140,6 +140,7 @@ import net.osmand.plus.settings.BaseSettingsFragment; import net.osmand.plus.settings.BaseSettingsFragment.SettingsScreenType; import net.osmand.plus.settings.ConfigureProfileFragment; import net.osmand.plus.settings.DataStorageFragment; +import net.osmand.plus.settings.ImportSettingsFragment; import net.osmand.plus.settings.ProfileAppearanceFragment; import net.osmand.plus.views.AddGpxPointBottomSheetHelper.NewGpxPoint; import net.osmand.plus.views.AnimateDraggingMapThread; @@ -732,6 +733,11 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven if ( quickActionListFragment != null && quickActionListFragment.isVisible()) { this.getDashboard().setDashboardVisibility(true, DashboardType.CONFIGURE_SCREEN, null); } + ImportSettingsFragment importSettingsFragment = getImportSettingsFragment(); + if (importSettingsFragment != null) { + importSettingsFragment.showExitDialog(); + return; + } super.onBackPressed(); } @@ -2447,6 +2453,10 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven return getFragment(QuickActionListFragment.TAG); } + public ImportSettingsFragment getImportSettingsFragment() { + return getFragment(ImportSettingsFragment.TAG); + } + public void backToConfigureProfileFragment() { FragmentManager fragmentManager = getSupportFragmentManager(); int backStackEntryCount = fragmentManager.getBackStackEntryCount(); diff --git a/OsmAnd/src/net/osmand/plus/helpers/AvoidSpecificRoads.java b/OsmAnd/src/net/osmand/plus/helpers/AvoidSpecificRoads.java index d724e0f9ce..86ba6ebe0e 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/AvoidSpecificRoads.java +++ b/OsmAnd/src/net/osmand/plus/helpers/AvoidSpecificRoads.java @@ -37,6 +37,7 @@ import net.osmand.plus.routing.RoutingHelper.RouteSegmentSearchResult; import net.osmand.plus.views.ContextMenuLayer; import net.osmand.router.RouteSegmentResult; import net.osmand.router.RoutingConfiguration; +import net.osmand.util.Algorithms; import net.osmand.util.MapUtils; import java.util.ArrayList; @@ -54,6 +55,10 @@ public class AvoidSpecificRoads { public AvoidSpecificRoads(final OsmandApplication app) { this.app = app; + loadImpassableRoads(); + } + + public void loadImpassableRoads(){ for (AvoidRoadInfo avoidRoadInfo : app.getSettings().getImpassableRoadPoints()) { impassableRoads.put(new LatLon(avoidRoadInfo.latitude, avoidRoadInfo.longitude), avoidRoadInfo); } @@ -398,5 +403,20 @@ public class AvoidSpecificRoads { public double longitude; public String name; public String appModeKey; + + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + + AvoidRoadInfo other = (AvoidRoadInfo) obj; + return Math.abs(latitude - other.latitude) < 0.00001 + && Math.abs(longitude - other.longitude) < 0.00001 + && Algorithms.objectEquals(name, other.name); + } } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java b/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java index b93a803b8a..d599458d78 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java @@ -782,7 +782,7 @@ public class ImportHelper { if (fragmentManager != null) { ImportSettingsFragment.showInstance(fragmentManager, items, file); } - } else { + } else if (empty) { app.showShortToastMessage(app.getString(R.string.file_import_error, name, app.getString(R.string.shared_string_unexpected_error))); } } diff --git a/OsmAnd/src/net/osmand/plus/profiles/AdditionalDataWrapper.java b/OsmAnd/src/net/osmand/plus/profiles/AdditionalDataWrapper.java index 9eb2ceed13..c0300b6e9b 100644 --- a/OsmAnd/src/net/osmand/plus/profiles/AdditionalDataWrapper.java +++ b/OsmAnd/src/net/osmand/plus/profiles/AdditionalDataWrapper.java @@ -31,6 +31,7 @@ public class AdditionalDataWrapper { POI_TYPES, MAP_SOURCES, CUSTOM_RENDER_STYLE, - CUSTOM_ROUTING + CUSTOM_ROUTING, + AVOID_ROADS } } diff --git a/OsmAnd/src/net/osmand/plus/render/RendererRegistry.java b/OsmAnd/src/net/osmand/plus/render/RendererRegistry.java index 64d091269c..a5bfc2d7bc 100644 --- a/OsmAnd/src/net/osmand/plus/render/RendererRegistry.java +++ b/OsmAnd/src/net/osmand/plus/render/RendererRegistry.java @@ -239,9 +239,20 @@ public class RendererRegistry { } public void initRenderers(IProgress progress) { + updateExternalRenderers(); + String r = app.getSettings().RENDERER.get(); + if(r != null){ + RenderingRulesStorage obj = getRenderer(r); + if(obj != null){ + setCurrentSelectedRender(obj); + } + } + } + + public void updateExternalRenderers() { File file = app.getAppPath(IndexConstants.RENDERERS_DIR); file.mkdirs(); - Map externalRenderers = new LinkedHashMap(); + Map externalRenderers = new LinkedHashMap(); if (file.exists() && file.canRead()) { File[] lf = file.listFiles(); if (lf != null) { @@ -256,13 +267,6 @@ public class RendererRegistry { } } this.externalRenderers = externalRenderers; - String r = app.getSettings().RENDERER.get(); - if(r != null){ - RenderingRulesStorage obj = getRenderer(r); - if(obj != null){ - setCurrentSelectedRender(obj); - } - } } public Collection getRendererNames(){ diff --git a/OsmAnd/src/net/osmand/plus/settings/DuplicatesSettingsAdapter.java b/OsmAnd/src/net/osmand/plus/settings/DuplicatesSettingsAdapter.java index 8619202977..ff49348940 100644 --- a/OsmAnd/src/net/osmand/plus/settings/DuplicatesSettingsAdapter.java +++ b/OsmAnd/src/net/osmand/plus/settings/DuplicatesSettingsAdapter.java @@ -15,6 +15,7 @@ import net.osmand.plus.ApplicationMode.ApplicationModeBean; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; +import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo; import net.osmand.plus.poi.PoiUIFilter; import net.osmand.plus.profiles.ProfileIconColors; import net.osmand.plus.quickaction.QuickAction; @@ -118,6 +119,11 @@ public class DuplicatesSettingsAdapter extends RecyclerView.Adapter impassableRoads = app.getAvoidSpecificRoads().getImpassableRoads(); + if (!impassableRoads.isEmpty()) { + dataList.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.AVOID_ROADS, + new ArrayList<>(impassableRoads.values()) + )); + } return dataList; } @@ -262,6 +270,7 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { List quickActions = new ArrayList<>(); List poiUIFilters = new ArrayList<>(); List tileSourceTemplates = new ArrayList<>(); + List avoidRoads = new ArrayList<>(); for (Object object : adapter.getDataToOperate()) { if (object instanceof QuickAction) { quickActions.add((QuickAction) object); @@ -272,6 +281,8 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { tileSourceTemplates.add((ITileSource) object); } else if (object instanceof File) { settingsItems.add(new SettingsHelper.FileSettingsItem(app, (File) object)); + } else if (object instanceof AvoidRoadInfo) { + avoidRoads.add((AvoidRoadInfo) object); } } if (!quickActions.isEmpty()) { @@ -283,6 +294,9 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { if (!tileSourceTemplates.isEmpty()) { settingsItems.add(new SettingsHelper.MapSourcesSettingsItem(app, tileSourceTemplates)); } + if (!avoidRoads.isEmpty()) { + settingsItems.add(new SettingsHelper.AvoidRoadsSettingsItem(app, avoidRoads)); + } return settingsItems; } diff --git a/OsmAnd/src/net/osmand/plus/settings/ImportDuplicatesFragment.java b/OsmAnd/src/net/osmand/plus/settings/ImportDuplicatesFragment.java index 52dd061de0..2b4fe6990d 100644 --- a/OsmAnd/src/net/osmand/plus/settings/ImportDuplicatesFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/ImportDuplicatesFragment.java @@ -1,24 +1,34 @@ package net.osmand.plus.settings; +import android.os.Build; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.design.widget.AppBarLayout; +import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; +import android.support.v4.view.ViewCompat; +import android.support.v4.widget.NestedScrollView; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.ViewTreeObserver; +import android.widget.LinearLayout; +import net.osmand.AndroidUtils; import net.osmand.map.ITileSource; +import net.osmand.plus.AppInitializer; import net.osmand.plus.ApplicationMode; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.SettingsHelper; import net.osmand.plus.SettingsHelper.SettingsItem; import net.osmand.plus.UiUtilities; -import net.osmand.plus.base.BaseOsmAndDialogFragment; +import net.osmand.plus.base.BaseOsmAndFragment; +import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo; import net.osmand.plus.poi.PoiUIFilter; import net.osmand.plus.quickaction.QuickAction; import net.osmand.view.ComplexButton; @@ -27,15 +37,18 @@ import java.io.File; import java.util.ArrayList; import java.util.List; +import static net.osmand.plus.settings.ImportSettingsFragment.getDuplicatesData; -public class ImportDuplicatesFragment extends BaseOsmAndDialogFragment implements View.OnClickListener { - public static final String TAG = ImportSettingsFragment.class.getSimpleName(); +public class ImportDuplicatesFragment extends BaseOsmAndFragment implements View.OnClickListener { + + public static final String TAG = ImportDuplicatesFragment.class.getSimpleName(); private OsmandApplication app; private RecyclerView list; + private LinearLayout buttonsContainer; + private NestedScrollView nestedScroll; private List duplicatesList; private List settingsItems; - private DuplicatesSettingsAdapter adapter; private File file; private boolean nightMode; @@ -45,15 +58,21 @@ public class ImportDuplicatesFragment extends BaseOsmAndDialogFragment implement fragment.setDuplicatesList(duplicatesList); fragment.setSettingsItems(settingsItems); fragment.setFile(file); - fragment.setRetainInstance(true); - fragment.show(fm, TAG); + fm.beginTransaction().replace(R.id.fragmentContainer, fragment, TAG).addToBackStack(null).commit(); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - app = getMyApplication(); - nightMode = !getSettings().isLightContent(); + app = requireMyApplication(); + nightMode = !app.getSettings().isLightContent(); + if (settingsItems == null) { + settingsItems = app.getSettingsHelper().getSettingsItems(); + duplicatesList = getDuplicatesData(settingsItems); + } + if (file == null) { + file = app.getSettingsHelper().getSettingsFile(); + } } @Nullable @@ -64,6 +83,8 @@ public class ImportDuplicatesFragment extends BaseOsmAndDialogFragment implement setupToolbar((Toolbar) root.findViewById(R.id.toolbar)); ComplexButton replaceAllBtn = root.findViewById(R.id.replace_all_btn); ComplexButton keepBothBtn = root.findViewById(R.id.keep_both_btn); + buttonsContainer = root.findViewById(R.id.buttons_container); + nestedScroll = root.findViewById(R.id.nested_scroll); keepBothBtn.setIcon(getPaintedContentIcon(R.drawable.ic_action_keep_both, nightMode ? getResources().getColor(R.color.icon_color_active_dark) @@ -77,14 +98,34 @@ public class ImportDuplicatesFragment extends BaseOsmAndDialogFragment implement keepBothBtn.setOnClickListener(this); replaceAllBtn.setOnClickListener(this); list = root.findViewById(R.id.list); + ViewTreeObserver treeObserver = buttonsContainer.getViewTreeObserver(); + treeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + if (buttonsContainer != null) { + ViewTreeObserver vts = buttonsContainer.getViewTreeObserver(); + int height = buttonsContainer.getMeasuredHeight(); + nestedScroll.setPadding(0, 0, 0, height); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + vts.removeOnGlobalLayoutListener(this); + } else { + vts.removeGlobalOnLayoutListener(this); + } + } + } + }); + if (Build.VERSION.SDK_INT >= 21) { + AndroidUtils.addStatusBarPadding21v(app, root); + } return root; } + @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - adapter = new DuplicatesSettingsAdapter(getMyApplication(), prepareDuplicates(), nightMode); + DuplicatesSettingsAdapter adapter = new DuplicatesSettingsAdapter(app, prepareDuplicates(), nightMode); list.setLayoutManager(new LinearLayoutManager(getMyApplication())); list.setAdapter(adapter); } @@ -97,6 +138,7 @@ public class ImportDuplicatesFragment extends BaseOsmAndDialogFragment implement List tileSources = new ArrayList<>(); List renderFilesList = new ArrayList<>(); List routingFilesList = new ArrayList<>(); + List avoidRoads = new ArrayList<>(); for (Object object : duplicatesList) { if (object instanceof ApplicationMode.ApplicationModeBean) { @@ -114,6 +156,8 @@ public class ImportDuplicatesFragment extends BaseOsmAndDialogFragment implement } else if (file.getAbsolutePath().contains("files/routing")) { routingFilesList.add(file); } + } else if (object instanceof AvoidRoadInfo) { + avoidRoads.add((AvoidRoadInfo) object); } } if (!profiles.isEmpty()) { @@ -137,9 +181,13 @@ public class ImportDuplicatesFragment extends BaseOsmAndDialogFragment implement duplicates.addAll(routingFilesList); } if (!renderFilesList.isEmpty()) { - duplicates.add(getString(R.string.shared_string_custom_rendering_style)); + duplicates.add(getString(R.string.shared_string_rendering_style)); duplicates.addAll(renderFilesList); } + if (!avoidRoads.isEmpty()) { + duplicates.add(getString(R.string.avoid_road)); + duplicates.addAll(avoidRoads); + } return duplicates; } @@ -157,6 +205,11 @@ public class ImportDuplicatesFragment extends BaseOsmAndDialogFragment implement } } + @Override + public int getStatusBarColorId() { + return nightMode ? R.color.status_bar_color_dark : R.color.status_bar_color_light; + } + private void importItems(boolean shouldReplace) { for (SettingsItem item : settingsItems) { item.setShouldReplace(shouldReplace); @@ -166,12 +219,26 @@ public class ImportDuplicatesFragment extends BaseOsmAndDialogFragment implement public void onSettingsImportFinished(boolean succeed, boolean empty, @NonNull List items) { if (succeed) { app.showShortToastMessage(app.getString(R.string.file_imported_successfully, file.getName())); + app.getRendererRegistry().updateExternalRenderers(); + AppInitializer.loadRoutingFiles(app, new AppInitializer.LoadRoutingFilesCallback() { + @Override + public void onRoutingFilesLoaded() { + } + }); } else if (empty) { app.showShortToastMessage(app.getString(R.string.file_import_error, file.getName(), app.getString(R.string.shared_string_unexpected_error))); } } }); - dismiss(); + FragmentManager fm = getFragmentManager(); + if (fm != null) { + fm.popBackStackImmediate(); + Fragment fragment = fm.findFragmentByTag(ImportSettingsFragment.TAG); + if (fragment != null) { + fm.beginTransaction().remove(fragment).commit(); + fm.popBackStackImmediate(); + } + } } private void setupToolbar(Toolbar toolbar) { @@ -183,7 +250,11 @@ public class ImportDuplicatesFragment extends BaseOsmAndDialogFragment implement toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - dismiss(); + FragmentManager fm = getFragmentManager(); + if (fm != null) { + fm.popBackStackImmediate(); + ImportSettingsFragment.showInstance(fm, null, file); + } } }); } diff --git a/OsmAnd/src/net/osmand/plus/settings/ImportSettingsFragment.java b/OsmAnd/src/net/osmand/plus/settings/ImportSettingsFragment.java index 0f092e6044..664cbcdbc1 100644 --- a/OsmAnd/src/net/osmand/plus/settings/ImportSettingsFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/ImportSettingsFragment.java @@ -1,17 +1,26 @@ package net.osmand.plus.settings; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Build; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.design.widget.AppBarLayout; import android.support.v4.app.FragmentManager; +import android.support.v4.view.ViewCompat; +import android.support.v7.app.AlertDialog; import android.support.v7.widget.Toolbar; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ExpandableListView; +import android.widget.TextView; +import net.osmand.AndroidUtils; import net.osmand.map.ITileSource; import net.osmand.map.TileSourceManager; +import net.osmand.plus.AppInitializer; import net.osmand.plus.ApplicationMode; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; @@ -19,7 +28,8 @@ import net.osmand.plus.SQLiteTileSource; import net.osmand.plus.SettingsHelper; import net.osmand.plus.SettingsHelper.SettingsItem; import net.osmand.plus.UiUtilities; -import net.osmand.plus.base.BaseOsmAndDialogFragment; +import net.osmand.plus.base.BaseOsmAndFragment; +import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo; import net.osmand.plus.poi.PoiUIFilter; import net.osmand.plus.profiles.AdditionalDataWrapper; import net.osmand.plus.quickaction.QuickAction; @@ -29,7 +39,7 @@ import java.io.File; import java.util.ArrayList; import java.util.List; -public class ImportSettingsFragment extends BaseOsmAndDialogFragment +public class ImportSettingsFragment extends BaseOsmAndFragment implements View.OnClickListener { public static final String TAG = ImportSettingsFragment.class.getSimpleName(); @@ -42,18 +52,18 @@ public class ImportSettingsFragment extends BaseOsmAndDialogFragment private boolean allSelected; private boolean nightMode; - public static void showInstance(@NonNull FragmentManager fm, @NonNull List settingsItems, @NonNull File file) { + public static void showInstance(@NonNull FragmentManager fm, List settingsItems, @NonNull File file) { ImportSettingsFragment fragment = new ImportSettingsFragment(); fragment.setSettingsItems(settingsItems); fragment.setFile(file); - fragment.show(fm, TAG); + fm.beginTransaction().replace(R.id.fragmentContainer, fragment, TAG).addToBackStack(null).commit(); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - app = getMyApplication(); - nightMode = !getSettings().isLightContent(); + app = requireMyApplication(); + nightMode = !app.getSettings().isLightContent(); if (settingsItems == null) { settingsItems = app.getSettingsHelper().getSettingsItems(); } @@ -71,15 +81,23 @@ public class ImportSettingsFragment extends BaseOsmAndDialogFragment TextViewEx continueBtn = root.findViewById(R.id.continue_button); selectBtn = root.findViewById(R.id.select_button); expandableList = root.findViewById(R.id.list); + ViewCompat.setNestedScrollingEnabled(expandableList, true); + View header = inflater.inflate(R.layout.list_item_description_header, container, false); + TextView description = header.findViewById(R.id.description); + description.setText(R.string.select_data_to_import); + expandableList.addHeaderView(header); continueBtn.setOnClickListener(this); selectBtn.setOnClickListener(this); + if (Build.VERSION.SDK_INT >= 21) { + AndroidUtils.addStatusBarPadding21v(app, root); + } return root; } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - adapter = new ExportImportSettingsAdapter(getMyApplication(), getSettingsToOperate(), nightMode, true); + adapter = new ExportImportSettingsAdapter(app, getSettingsToOperate(), nightMode, true); expandableList.setAdapter(adapter); } @@ -112,20 +130,27 @@ public class ImportSettingsFragment extends BaseOsmAndDialogFragment public void onSettingsImportFinished(boolean succeed, boolean empty, @NonNull List items) { if (succeed) { app.showShortToastMessage(app.getString(R.string.file_imported_successfully, file.getName())); + app.getRendererRegistry().updateExternalRenderers(); + AppInitializer.loadRoutingFiles(app, new AppInitializer.LoadRoutingFilesCallback() { + @Override + public void onRoutingFilesLoaded() { + } + }); } else if (empty) { app.showShortToastMessage(app.getString(R.string.file_import_error, file.getName(), app.getString(R.string.shared_string_unexpected_error))); } } }); - dismiss(); + FragmentManager fm = getFragmentManager(); + if (fm != null) { + fm.popBackStackImmediate(); + } } else { - ImportDuplicatesFragment.showInstance(getFragmentManager(), duplicateItems, settingsItems, file); - dismiss(); + ImportDuplicatesFragment.showInstance(requireActivity().getSupportFragmentManager(), duplicateItems, settingsItems, file); } } - @SuppressWarnings("unchecked") - private List getDuplicatesData(List items) { + public static List getDuplicatesData(List items) { List duplicateItems = new ArrayList<>(); for (SettingsItem item : items) { if (item instanceof SettingsHelper.ProfileSettingsItem) { @@ -151,6 +176,11 @@ public class ImportSettingsFragment extends BaseOsmAndDialogFragment if (item.exists()) { duplicateItems.add(((SettingsHelper.FileSettingsItem) item).getFile()); } + } else if (item instanceof SettingsHelper.AvoidRoadsSettingsItem) { + List avoidRoads = ((SettingsHelper.AvoidRoadsSettingsItem) item).excludeDuplicateItems(); + if (!avoidRoads.isEmpty()) { + duplicateItems.addAll(avoidRoads); + } } } return duplicateItems; @@ -165,6 +195,7 @@ public class ImportSettingsFragment extends BaseOsmAndDialogFragment List quickActions = new ArrayList<>(); List poiUIFilters = new ArrayList<>(); List tileSourceTemplates = new ArrayList<>(); + List avoidRoads = new ArrayList<>(); for (Object object : dataToOperate) { if (object instanceof ApplicationMode.ApplicationModeBean) { settingsItems.add(new SettingsHelper.ProfileSettingsItem(app, (ApplicationMode.ApplicationModeBean) object)); @@ -177,22 +208,26 @@ public class ImportSettingsFragment extends BaseOsmAndDialogFragment || object instanceof SQLiteTileSource) { tileSourceTemplates.add((ITileSource) object); } else if (object instanceof File) { - settingsItems.add(new SettingsHelper.FileSettingsItem(getMyApplication(), (File) object)); + settingsItems.add(new SettingsHelper.FileSettingsItem(app, (File) object)); + } else if (object instanceof AvoidRoadInfo) { + avoidRoads.add((AvoidRoadInfo) object); } } if (!quickActions.isEmpty()) { - settingsItems.add(new SettingsHelper.QuickActionSettingsItem(getMyApplication(), quickActions)); + settingsItems.add(new SettingsHelper.QuickActionSettingsItem(app, quickActions)); } if (!poiUIFilters.isEmpty()) { - settingsItems.add(new SettingsHelper.PoiUiFilterSettingsItem(getMyApplication(), poiUIFilters)); + settingsItems.add(new SettingsHelper.PoiUiFilterSettingsItem(app, poiUIFilters)); } if (!tileSourceTemplates.isEmpty()) { - settingsItems.add(new SettingsHelper.MapSourcesSettingsItem(getMyApplication(), tileSourceTemplates)); + settingsItems.add(new SettingsHelper.MapSourcesSettingsItem(app, tileSourceTemplates)); + } + if (!avoidRoads.isEmpty()) { + settingsItems.add(new SettingsHelper.AvoidRoadsSettingsItem(app, avoidRoads)); } return settingsItems; } - @SuppressWarnings("unchecked") private List getSettingsToOperate() { List settingsToOperate = new ArrayList<>(); List profiles = new ArrayList<>(); @@ -201,6 +236,7 @@ public class ImportSettingsFragment extends BaseOsmAndDialogFragment List tileSourceTemplates = new ArrayList<>(); List routingFilesList = new ArrayList<>(); List renderFilesList = new ArrayList<>(); + List avoidRoads = new ArrayList<>(); for (SettingsHelper.SettingsItem item : settingsItems) { if (item.getType().equals(SettingsHelper.SettingsItemType.PROFILE)) { @@ -217,6 +253,8 @@ public class ImportSettingsFragment extends BaseOsmAndDialogFragment } else if (item.getName().startsWith("/routing/")) { routingFilesList.add(((SettingsHelper.FileSettingsItem) item).getFile()); } + } else if (item.getType().equals(SettingsHelper.SettingsItemType.AVOID_ROADS)) { + avoidRoads.addAll(((SettingsHelper.AvoidRoadsSettingsItem) item).getItems()); } } @@ -253,18 +291,47 @@ public class ImportSettingsFragment extends BaseOsmAndDialogFragment routingFilesList )); } + if (!avoidRoads.isEmpty()) { + settingsToOperate.add(new AdditionalDataWrapper( + AdditionalDataWrapper.Type.AVOID_ROADS, + avoidRoads + )); + } return settingsToOperate; } + @Override + public int getStatusBarColorId() { + return nightMode ? R.color.status_bar_color_dark : R.color.status_bar_color_light; + } + + public void showExitDialog() { + Context themedContext = UiUtilities.getThemedContext(getActivity(), nightMode); + AlertDialog.Builder dismissDialog = new AlertDialog.Builder(themedContext); + dismissDialog.setTitle(getString(R.string.shared_string_dismiss)); + dismissDialog.setMessage(getString(R.string.exit_without_saving)); + dismissDialog.setNegativeButton(R.string.shared_string_cancel, null); + dismissDialog.setPositiveButton(R.string.shared_string_exit, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + FragmentManager fm = getFragmentManager(); + if (fm != null) { + fm.popBackStackImmediate(); + } + } + }); + dismissDialog.show(); + } + private void setupToolbar(Toolbar toolbar) { - toolbar.setNavigationIcon(getPaintedContentIcon(R.drawable.headline_close_button, nightMode + toolbar.setNavigationIcon(getPaintedContentIcon(R.drawable.ic_action_close, nightMode ? getResources().getColor(R.color.active_buttons_and_links_text_dark) : getResources().getColor(R.color.active_buttons_and_links_text_light))); toolbar.setNavigationContentDescription(R.string.shared_string_close); toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - dismiss(); + showExitDialog(); } }); }