package net.osmand.plus.dialogs;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnMultiChoiceClickListener;
import android.content.Intent;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.annotation.StringRes;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.AppCompatCheckedTextView;
import android.support.v7.widget.SwitchCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import net.osmand.AndroidUtils;
import net.osmand.PlatformUtil;
import net.osmand.core.android.MapRendererContext;
import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.ContextMenuAdapter.ItemClickListener;
import net.osmand.plus.ContextMenuAdapter.OnRowItemClick;
import net.osmand.plus.ContextMenuItem;
import net.osmand.plus.GpxSelectionHelper;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.OsmandSettings.CommonPreference;
import net.osmand.plus.OsmandSettings.ListStringPreference;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.MapActivityLayers;
import net.osmand.plus.activities.PluginActivity;
import net.osmand.plus.activities.SettingsActivity;
import net.osmand.plus.dashboard.DashboardOnMap;
import net.osmand.plus.openseamapsplugin.NauticalMapsPlugin;
import net.osmand.plus.poi.PoiFiltersHelper;
import net.osmand.plus.rastermaps.OsmandRasterMapsPlugin;
import net.osmand.plus.render.RendererRegistry;
import net.osmand.plus.srtmplugin.SRTMPlugin;
import net.osmand.plus.views.GPXLayer;
import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.plus.views.RouteLayer;
import net.osmand.plus.views.corenative.NativeCoreContext;
import net.osmand.render.RenderingRule;
import net.osmand.render.RenderingRuleProperty;
import net.osmand.render.RenderingRuleStorageProperties;
import net.osmand.render.RenderingRulesStorage;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import gnu.trove.list.array.TIntArrayList;
import static net.osmand.plus.srtmplugin.SRTMPlugin.CONTOUR_DENSITY_ATTR;
import static net.osmand.plus.srtmplugin.SRTMPlugin.CONTOUR_LINES_ATTR;
import static net.osmand.plus.srtmplugin.SRTMPlugin.CONTOUR_LINES_SCHEME_ATTR;
import static net.osmand.plus.srtmplugin.SRTMPlugin.CONTOUR_WIDTH_ATTR;
public class ConfigureMapMenu {
private static final Log LOG = PlatformUtil.getLog(ConfigureMapMenu.class);
public static final String HIKING_ROUTES_OSMC_ATTR = "hikingRoutesOSMC";
public static final String CURRENT_TRACK_COLOR_ATTR = "currentTrackColor";
public static final String CURRENT_TRACK_WIDTH_ATTR = "currentTrackWidth";
public static final String COLOR_ATTR = "color";
public static final String ROAD_STYLE_ATTR = "roadStyle";
private int hikingRouteOSMCValue;
private int selectedLanguageIndex;
private boolean transliterateNames;
public interface OnClickListener {
void onClick();
}
public ContextMenuAdapter createListAdapter(final MapActivity ma) {
ContextMenuAdapter adapter = new ContextMenuAdapter();
adapter.setDefaultLayoutId(R.layout.list_item_icon_and_menu);
adapter.addItem(new ContextMenuItem.ItemBuilder()
.setTitleId(R.string.app_modes_choose, ma)
.setLayout(R.layout.mode_toggles).createItem());
adapter.setChangeAppModeListener(new OnClickListener() {
@Override
public void onClick() {
ma.getDashboard().updateListAdapter(createListAdapter(ma));
}
});
RenderingRulesStorage renderer = ma.getMyApplication().getRendererRegistry().getCurrentSelectedRenderer();
List<RenderingRuleProperty> customRules = new ArrayList<>();
boolean hasDepthContours = ma.getMyApplication().getResourceManager().hasDepthContours();
if (renderer != null) {
for (RenderingRuleProperty p : renderer.PROPS.getCustomRules()) {
if (!RenderingRuleStorageProperties.UI_CATEGORY_HIDDEN.equals(p.getCategory())
&& (hasDepthContours || !p.getAttrName().equals("depthContours"))) {
customRules.add(p);
}
}
}
createLayersItems(customRules, adapter, ma);
createRenderingAttributeItems(customRules, adapter, ma);
return adapter;
}
private final class LayerMenuListener extends OnRowItemClick {
private MapActivity ma;
private ContextMenuAdapter cm;
private LayerMenuListener(MapActivity ma, ContextMenuAdapter cm) {
this.ma = ma;
this.cm = cm;
}
private List<String> getAlreadySelectedGpx() {
GpxSelectionHelper selectedGpxHelper = ma.getMyApplication().getSelectedGpxHelper();
List<GpxSelectionHelper.SelectedGpxFile> selectedGpxFiles = selectedGpxHelper.getSelectedGPXFiles();
List<String> files = new ArrayList<>();
for (GpxSelectionHelper.SelectedGpxFile file : selectedGpxFiles) {
files.add(file.getGpxFile().path);
}
return files;
}
@Override
public boolean onRowItemClick(ArrayAdapter<ContextMenuItem> adapter, View view, int itemId, int pos) {
if (itemId == R.string.layer_poi) {
showPoiFilterDialog(adapter, adapter.getItem(pos));
return false;
} else if (itemId == R.string.layer_gpx_layer && cm.getItem(pos).getSelected()) {
showGpxSelectionDialog(adapter, adapter.getItem(pos));
return false;
} else {
CompoundButton btn = (CompoundButton) view.findViewById(R.id.toggle_item);
if (btn != null && btn.getVisibility() == View.VISIBLE) {
btn.setChecked(!btn.isChecked());
cm.getItem(pos).setColorRes(btn.isChecked() ? R.color.osmand_orange : ContextMenuItem.INVALID_ID);
adapter.notifyDataSetChanged();
return false;
} else {
return onContextMenuClick(adapter, itemId, pos, false);
}
}
}
@Override
public boolean onContextMenuClick(final ArrayAdapter<ContextMenuItem> adapter, int itemId, final int pos, boolean isChecked) {
final OsmandSettings settings = ma.getMyApplication().getSettings();
final PoiFiltersHelper poiFiltersHelper = ma.getMyApplication().getPoiFilters();
final ContextMenuItem item = cm.getItem(pos);
if (item.getSelected() != null) {
item.setColorRes(isChecked ? R.color.osmand_orange : ContextMenuItem.INVALID_ID);
}
if (itemId == R.string.layer_poi) {
poiFiltersHelper.clearSelectedPoiFilters();
if (isChecked) {
showPoiFilterDialog(adapter, adapter.getItem(pos));
} else {
adapter.getItem(pos).setDescription(poiFiltersHelper.getSelectedPoiFiltersName());
}
} else if (itemId == R.string.layer_amenity_label) {
settings.SHOW_POI_LABEL.set(isChecked);
} else if (itemId == R.string.shared_string_favorites) {
settings.SHOW_FAVORITES.set(isChecked);
} else if (itemId == R.string.layer_gpx_layer) {
final GpxSelectionHelper selectedGpxHelper = ma.getMyApplication().getSelectedGpxHelper();
if (selectedGpxHelper.isShowingAnyGpxFiles()) {
selectedGpxHelper.clearAllGpxFileToShow();
adapter.getItem(pos).setDescription(selectedGpxHelper.getGpxDescription());
} else {
showGpxSelectionDialog(adapter, adapter.getItem(pos));
}
} else if (itemId == R.string.layer_map) {
if (OsmandPlugin.getEnabledPlugin(OsmandRasterMapsPlugin.class) == null) {
Intent intent = new Intent(ma, PluginActivity.class);
intent.putExtra(PluginActivity.EXTRA_PLUGIN_ID, OsmandRasterMapsPlugin.ID);
ma.startActivity(intent);
} else {
ContextMenuItem it = adapter.getItem(pos);
ma.getMapLayers().selectMapLayer(ma.getMapView(), it, adapter);
}
}
adapter.notifyDataSetChanged();
ma.getMapLayers().updateLayers(ma.getMapView());
ma.getMapView().refreshMap();
return false;
}
private void showGpxSelectionDialog(final ArrayAdapter<ContextMenuItem> adapter,
final ContextMenuItem item) {
AlertDialog dialog = ma.getMapLayers().showGPXFileLayer(getAlreadySelectedGpx(),
ma.getMapView());
dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
OsmandApplication app = ma.getMyApplication();
boolean selected = app.getSelectedGpxHelper().isShowingAnyGpxFiles();
item.setSelected(app.getSelectedGpxHelper().isShowingAnyGpxFiles());
item.setDescription(app.getSelectedGpxHelper().getGpxDescription());
item.setColorRes(selected ? R.color.osmand_orange : ContextMenuItem.INVALID_ID);
adapter.notifyDataSetChanged();
}
});
}
protected void showPoiFilterDialog(final ArrayAdapter<ContextMenuItem> adapter,
final ContextMenuItem item) {
final PoiFiltersHelper poiFiltersHelper = ma.getMyApplication().getPoiFilters();
MapActivityLayers.DismissListener dismissListener =
new MapActivityLayers.DismissListener() {
@Override
public void dismiss() {
PoiFiltersHelper pf = ma.getMyApplication().getPoiFilters();
boolean selected = pf.isShowingAnyPoi();
item.setSelected(selected);
item.setDescription(pf.getSelectedPoiFiltersName());
item.setColorRes(selected ? R.color.osmand_orange : ContextMenuItem.INVALID_ID);
adapter.notifyDataSetChanged();
}
};
if (poiFiltersHelper.getSelectedPoiFilters().size() > 1) {
ma.getMapLayers().showMultichoicePoiFilterDialog(ma.getMapView(),
dismissListener);
} else {
ma.getMapLayers().showSingleChoicePoiFilterDialog(ma.getMapView(),
dismissListener);
}
}
}
private void createLayersItems(List<RenderingRuleProperty> customRules, ContextMenuAdapter adapter, final MapActivity activity) {
final OsmandApplication app = activity.getMyApplication();
final OsmandSettings settings = app.getSettings();
LayerMenuListener l = new LayerMenuListener(activity, adapter);
adapter.addItem(new ContextMenuItem.ItemBuilder()
.setTitleId(R.string.shared_string_show, activity)
.setCategory(true).setLayout(R.layout.list_group_title_with_switch).createItem());
// String appMode = " [" + settings.getApplicationMode().toHumanString(view.getApplication()) +"] ";
boolean selected = settings.SHOW_FAVORITES.get();
adapter.addItem(new ContextMenuItem.ItemBuilder()
.setTitleId(R.string.shared_string_favorites, activity)
.setSelected(settings.SHOW_FAVORITES.get())
.setColor(selected ? R.color.osmand_orange : ContextMenuItem.INVALID_ID)
.setIcon(R.drawable.ic_action_fav_dark)
.setListener(l).createItem());
selected = app.getPoiFilters().isShowingAnyPoi();
adapter.addItem(new ContextMenuItem.ItemBuilder()
.setTitleId(R.string.layer_poi, activity)
.setSelected(selected)
.setDescription(app.getPoiFilters().getSelectedPoiFiltersName())
.setColor(selected ? R.color.osmand_orange : ContextMenuItem.INVALID_ID)
.setIcon(R.drawable.ic_action_info_dark)
.setSecondaryIcon(R.drawable.ic_action_additional_option)
.setListener(l).createItem());
/*
ContextMenuItem item = createProperties(customRules, null, R.string.rendering_category_transport, R.drawable.ic_action_bus_dark,
"transport", settings.TRANSPORT_DEFAULT_SETTINGS, adapter, activity, false);
if (item != null) {
adapter.addItem(item);
}
*/
final List<RenderingRuleProperty> transportRules = new ArrayList<>();
final List<OsmandSettings.CommonPreference<Boolean>> transportPrefs = new ArrayList<>();
Iterator<RenderingRuleProperty> it = customRules.iterator();
while (it.hasNext()) {
RenderingRuleProperty p = it.next();
if ("transport".equals(p.getCategory()) && p.isBoolean()) {
transportRules.add(p);
final OsmandSettings.CommonPreference<Boolean> pref = activity.getMyApplication().getSettings()
.getCustomRenderBooleanProperty(p.getAttrName());
transportPrefs.add(pref);
it.remove();
}
}
selected = false;
for (OsmandSettings.CommonPreference<Boolean> p : transportPrefs) {
if (p.get()) {
selected = true;
break;
}
}
final boolean transportSelected = selected;
adapter.addItem(new ContextMenuItem.ItemBuilder()
.setTitleId(R.string.rendering_category_transport, activity)
.setIcon(R.drawable.ic_action_bus_dark)
.setSecondaryIcon(R.drawable.ic_action_additional_option)
.setSelected(transportSelected)
.setColor(transportSelected ? R.color.osmand_orange : ContextMenuItem.INVALID_ID)
.setListener(new ContextMenuAdapter.OnRowItemClick() {
ArrayAdapter<CharSequence> adapter;
boolean transportSelectedInner = transportSelected;
@Override
public boolean onRowItemClick(ArrayAdapter<ContextMenuItem> adapter, View view, int itemId, int position) {
if (transportSelectedInner) {
showTransportDialog(adapter, position);
return false;
} else {
CompoundButton btn = (CompoundButton) view.findViewById(R.id.toggle_item);
if (btn != null && btn.getVisibility() == View.VISIBLE) {
btn.setChecked(!btn.isChecked());
adapter.getItem(position).setColorRes(btn.isChecked() ? R.color.osmand_orange : ContextMenuItem.INVALID_ID);
adapter.notifyDataSetChanged();
return false;
} else {
return onContextMenuClick(adapter, itemId, position, false);
}
}
}
@Override
public boolean onContextMenuClick(final ArrayAdapter<ContextMenuItem> ad, int itemId,
final int pos, boolean isChecked) {
if (transportSelectedInner) {
for (int i = 0; i < transportPrefs.size(); i++) {
transportPrefs.get(i).set(false);
}
transportSelectedInner = false;
ad.getItem(pos).setColorRes(ContextMenuItem.INVALID_ID);
refreshMapComplete(activity);
activity.getMapLayers().updateLayers(activity.getMapView());
} else {
ad.getItem(pos).setColorRes(R.color.osmand_orange);
showTransportDialog(ad, pos);
}
ad.notifyDataSetChanged();
return false;
}
private void showTransportDialog(final ArrayAdapter<ContextMenuItem> ad, final int pos) {
final AlertDialog.Builder b = new AlertDialog.Builder(activity);
b.setTitle(activity.getString(R.string.rendering_category_transport));
final int[] iconIds = new int[transportPrefs.size()];
final boolean[] checkedItems = new boolean[transportPrefs.size()];
for (int i = 0; i < transportPrefs.size(); i++) {
checkedItems[i] = transportPrefs.get(i).get();
}
final String[] vals = new String[transportRules.size()];
for (int i = 0; i < transportRules.size(); i++) {
RenderingRuleProperty p = transportRules.get(i);
String propertyName = SettingsActivity.getStringPropertyName(activity, p.getAttrName(),
p.getName());
vals[i] = propertyName;
if ("transportStops".equals(p.getAttrName())) {
iconIds[i] = R.drawable.ic_action_transport_stop;
} else if ("publicTransportMode".equals(p.getAttrName())) {
iconIds[i] = R.drawable.ic_action_bus_dark;
} else if ("tramTrainRoutes".equals(p.getAttrName())) {
iconIds[i] = R.drawable.ic_action_transport_tram;
} else if ("subwayMode".equals(p.getAttrName())) {
iconIds[i] = R.drawable.ic_action_transport_subway;
} else {
iconIds[i] = R.drawable.ic_action_bus_dark;
}
}
adapter = new ArrayAdapter<CharSequence>(activity, R.layout.popup_list_item_icon24_and_menu, R.id.title, vals) {
@NonNull
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
View v = super.getView(position, convertView, parent);
final ImageView icon = (ImageView) v.findViewById(R.id.icon);
if (checkedItems[position]) {
icon.setImageDrawable(app.getIconsCache().getIcon(iconIds[position], R.color.osmand_orange));
} else {
icon.setImageDrawable(app.getIconsCache().getThemedIcon(iconIds[position]));
}
v.findViewById(R.id.divider).setVisibility(View.GONE);
v.findViewById(R.id.description).setVisibility(View.GONE);
v.findViewById(R.id.secondary_icon).setVisibility(View.GONE);
final SwitchCompat check = (SwitchCompat) v.findViewById(R.id.toggle_item);
check.setOnCheckedChangeListener(null);
check.setChecked(checkedItems[position]);
check.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
checkedItems[position] = isChecked;
if (checkedItems[position]) {
icon.setImageDrawable(app.getIconsCache().getIcon(iconIds[position], R.color.osmand_orange));
} else {
icon.setImageDrawable(app.getIconsCache().getThemedIcon(iconIds[position]));
}
}
});
return v;
}
};
final ListView listView = new ListView(activity);
listView.setDivider(null);
listView.setClickable(true);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new ListView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
checkedItems[position] = !checkedItems[position];
adapter.notifyDataSetChanged();
}
});
b.setView(listView);
b.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
ContextMenuItem item = ad.getItem(pos);
if (item != null) {
item.setSelected(transportSelectedInner);
item.setColorRes(transportSelectedInner ? R.color.osmand_orange : ContextMenuItem.INVALID_ID);
ad.notifyDataSetChanged();
}
}
});
b.setNegativeButton(R.string.shared_string_cancel, null);
b.setPositiveButton(R.string.shared_string_apply, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
transportSelectedInner = false;
for (int i = 0; i < transportPrefs.size(); i++) {
transportPrefs.get(i).set(checkedItems[i]);
if (!transportSelectedInner && checkedItems[i]) {
transportSelectedInner = true;
}
}
refreshMapComplete(activity);
activity.getMapLayers().updateLayers(activity.getMapView());
}
});
b.show();
}
}).createItem());
selected = settings.SHOW_POI_LABEL.get();
adapter.addItem(new ContextMenuItem.ItemBuilder()
.setTitleId(R.string.layer_amenity_label, activity)
.setSelected(settings.SHOW_POI_LABEL.get())
.setColor(selected ? R.color.osmand_orange : ContextMenuItem.INVALID_ID)
.setIcon(R.drawable.ic_action_text_dark)
.setListener(l).createItem());
selected = app.getSelectedGpxHelper().isShowingAnyGpxFiles();
adapter.addItem(new ContextMenuItem.ItemBuilder()
.setTitleId(R.string.layer_gpx_layer, activity)
.setSelected(app.getSelectedGpxHelper().isShowingAnyGpxFiles())
.setDescription(app.getSelectedGpxHelper().getGpxDescription())
.setColor(selected ? R.color.osmand_orange : ContextMenuItem.INVALID_ID)
.setIcon(R.drawable.ic_action_polygom_dark)
.setSecondaryIcon(R.drawable.ic_action_additional_option)
.setListener(l).createItem());
adapter.addItem(new ContextMenuItem.ItemBuilder()
.setTitleId(R.string.layer_map, activity)
.setIcon(R.drawable.ic_world_globe_dark)
.setDescription(settings.MAP_ONLINE_DATA.get() ? settings.MAP_TILE_SOURCES.get() : null)
.setListener(l).createItem());
OsmandPlugin.registerLayerContextMenu(activity.getMapView(), adapter, activity);
app.getAppCustomization().prepareLayerContextMenu(activity, adapter);
boolean srtmDisabled = OsmandPlugin.getEnabledPlugin(SRTMPlugin.class) == null;
if (srtmDisabled) {
SRTMPlugin srtmPlugin = OsmandPlugin.getPlugin(SRTMPlugin.class);
if (srtmPlugin != null) {
srtmPlugin.registerLayerContextMenuActions(activity.getMapView(), adapter, activity);
}
}
}
public static void refreshMapComplete(final MapActivity activity) {
activity.getMyApplication().getResourceManager().getRenderer().clearCache();
activity.updateMapSettings();
GPXLayer gpx = activity.getMapView().getLayerByClass(GPXLayer.class);
if (gpx != null) {
gpx.updateLayerStyle();
}
RouteLayer rte = activity.getMapView().getLayerByClass(RouteLayer.class);
if (rte != null) {
rte.updateLayerStyle();
}
activity.getMapView().refreshMap(true);
}
private void createRenderingAttributeItems(List<RenderingRuleProperty> customRules,
final ContextMenuAdapter adapter, final MapActivity activity) {
adapter.addItem(new ContextMenuItem.ItemBuilder().setTitleId(R.string.map_widget_map_rendering, activity)
.setCategory(true).setLayout(R.layout.list_group_title_with_switch).createItem());
adapter.addItem(new ContextMenuItem.ItemBuilder().setTitleId(R.string.map_widget_renderer, activity)
.setDescription(getRenderDescr(activity)).setLayout(R.layout.list_item_single_line_descrition_narrow)
.setIcon(R.drawable.ic_map).setListener(new ContextMenuAdapter.ItemClickListener() {
@Override
public boolean onContextMenuClick(final ArrayAdapter<ContextMenuItem> ad, int itemId,
final int pos, boolean isChecked) {
AlertDialog.Builder bld = new AlertDialog.Builder(activity);
bld.setTitle(R.string.renderers);
final OsmandApplication app = activity.getMyApplication();
Collection<String> rendererNames = app.getRendererRegistry().getRendererNames();
final String[] items = rendererNames.toArray(new String[rendererNames.size()]);
boolean nauticalPluginDisabled = OsmandPlugin.getEnabledPlugin(NauticalMapsPlugin.class) == null;
final List<String> visibleNamesList = new ArrayList<>();
int selected = -1;
final String selectedName = app.getRendererRegistry().getCurrentSelectedRenderer().getName();
int i = 0;
for (String item : items) {
if (nauticalPluginDisabled && item.equals(RendererRegistry.NAUTICAL_RENDER)) {
continue;
}
if (item.equals(selectedName)) {
selected = i;
}
visibleNamesList.add(item.replace('_', ' ').replace('-', ' '));
i++;
}
bld.setSingleChoiceItems(visibleNamesList.toArray(new String[visibleNamesList.size()]), selected, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String renderer = visibleNamesList.get(which);
RenderingRulesStorage loaded = app.getRendererRegistry().getRenderer(renderer);
if (loaded != null) {
OsmandMapTileView view = activity.getMapView();
view.getSettings().RENDERER.set(renderer);
app.getRendererRegistry().setCurrentSelectedRender(loaded);
refreshMapComplete(activity);
} else {
Toast.makeText(app, R.string.renderer_load_exception, Toast.LENGTH_SHORT).show();
}
adapter.getItem(pos).setDescription(getRenderDescr(activity));
activity.getDashboard().refreshContent(true);
dialog.dismiss();
}
});
bld.setNegativeButton(R.string.shared_string_dismiss, null);
bld.show();
return false;
}
}).createItem());
adapter.addItem(new ContextMenuItem.ItemBuilder().setTitleId(R.string.map_mode, activity)
.setDescription(getDayNightDescr(activity)).setLayout(R.layout.list_item_single_line_descrition_narrow)
.setIcon(getDayNightIcon(activity)).setListener(new ItemClickListener() {
@Override
public boolean onContextMenuClick(final ArrayAdapter<ContextMenuItem> ad, int itemId,
final int pos, boolean isChecked) {
final OsmandMapTileView view = activity.getMapView();
AlertDialog.Builder bld = new AlertDialog.Builder(view.getContext());
bld.setTitle(R.string.daynight);
final String[] items = new String[OsmandSettings.DayNightMode.values().length];
for (int i = 0; i < items.length; i++) {
items[i] = OsmandSettings.DayNightMode.values()[i].toHumanString(activity
.getMyApplication());
}
int i = view.getSettings().DAYNIGHT_MODE.get().ordinal();
bld.setSingleChoiceItems(items, i, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
view.getSettings().DAYNIGHT_MODE.set(OsmandSettings.DayNightMode.values()[which]);
refreshMapComplete(activity);
dialog.dismiss();
activity.getDashboard().refreshContent(true);
// adapter.getItem(pos).setDescription(s, getDayNightDescr(activity));
// ad.notifyDataSetInvalidated();
}
});
bld.setNegativeButton(R.string.shared_string_dismiss, null);
bld.show();
return false;
}
}).createItem());
adapter.addItem(new ContextMenuItem.ItemBuilder()
.setTitleId(R.string.map_magnifier, activity)
.setDescription(
String.format(Locale.UK, "%.0f",
100f * activity.getMyApplication().getSettings().MAP_DENSITY.get())
+ " %").setLayout(R.layout.list_item_single_line_descrition_narrow)
.setIcon(R.drawable.ic_action_map_magnifier).setListener(new ContextMenuAdapter.ItemClickListener() {
@Override
public boolean onContextMenuClick(final ArrayAdapter<ContextMenuItem> ad, int itemId,
final int pos, boolean isChecked) {
final OsmandMapTileView view = activity.getMapView();
final OsmandSettings.OsmandPreference<Float> mapDensity = view.getSettings().MAP_DENSITY;
final AlertDialog.Builder bld = new AlertDialog.Builder(view.getContext());
int p = (int) (mapDensity.get() * 100);
final TIntArrayList tlist = new TIntArrayList(new int[]{33, 50, 75, 100, 150, 200, 300, 400});
final List<String> values = new ArrayList<>();
int i = -1;
for (int k = 0; k <= tlist.size(); k++) {
final boolean end = k == tlist.size();
if (i == -1) {
if ((end || p < tlist.get(k))) {
values.add(p + " %");
i = k;
} else if (p == tlist.get(k)) {
i = k;
}
}
if (k < tlist.size()) {
values.add(tlist.get(k) + " %");
}
}
if (values.size() != tlist.size()) {
tlist.insert(i, p);
}
bld.setTitle(R.string.map_magnifier);
bld.setSingleChoiceItems(values.toArray(new String[values.size()]), i,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int p = tlist.get(which);
mapDensity.set(p / 100.0f);
view.setComplexZoom(view.getZoom(), view.getSettingsMapDensity());
MapRendererContext mapContext = NativeCoreContext.getMapRendererContext();
if (mapContext != null) {
mapContext.updateMapSettings();
}
adapter.getItem(pos).setDescription(
String.format(Locale.UK, "%.0f", 100f * activity.getMyApplication()
.getSettings().MAP_DENSITY.get())
+ " %");
ad.notifyDataSetInvalidated();
dialog.dismiss();
}
});
bld.setNegativeButton(R.string.shared_string_dismiss, null);
bld.show();
return false;
}
}).createItem());
ContextMenuItem props;
props = createRenderingProperty(customRules, adapter, activity, R.drawable.ic_action_intersection, ROAD_STYLE_ATTR);
if (props != null) {
adapter.addItem(props);
}
adapter.addItem(new ContextMenuItem.ItemBuilder().setTitleId(R.string.text_size, activity)
.setDescription(getScale(activity)).setLayout(R.layout.list_item_single_line_descrition_narrow)
.setIcon(R.drawable.ic_action_map_text_size).setListener(new ContextMenuAdapter.ItemClickListener() {
@Override
public boolean onContextMenuClick(final ArrayAdapter<ContextMenuItem> ad, int itemId,
final int pos, boolean isChecked) {
final OsmandMapTileView view = activity.getMapView();
AlertDialog.Builder b = new AlertDialog.Builder(view.getContext());
// test old descr as title
b.setTitle(R.string.text_size);
final Float[] txtValues = new Float[]{0.75f, 1f, 1.25f, 1.5f, 2f, 3f};
int selected = -1;
final String[] txtNames = new String[txtValues.length];
for (int i = 0; i < txtNames.length; i++) {
txtNames[i] = (int) (txtValues[i] * 100) + " %";
if (Math.abs(view.getSettings().TEXT_SCALE.get() - txtValues[i]) < 0.1f) {
selected = i;
}
}
b.setSingleChoiceItems(txtNames, selected, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
view.getSettings().TEXT_SCALE.set(txtValues[which]);
refreshMapComplete(activity);
adapter.getItem(pos).setDescription(getScale(activity));
ad.notifyDataSetInvalidated();
dialog.dismiss();
}
});
b.setNegativeButton(R.string.shared_string_dismiss, null);
b.show();
return false;
}
}).createItem());
String localeDescr = activity.getMyApplication().getSettings().MAP_PREFERRED_LOCALE.get();
localeDescr = localeDescr == null || localeDescr.equals("") ? activity.getString(R.string.local_map_names)
: localeDescr;
adapter.addItem(new ContextMenuItem.ItemBuilder().setTitleId(R.string.map_locale, activity)
.setDescription(localeDescr).setLayout(R.layout.list_item_single_line_descrition_narrow)
.setIcon(R.drawable.ic_action_map_language)
.setListener(new ContextMenuAdapter.ItemClickListener() {
@Override
public boolean onContextMenuClick(final ArrayAdapter<ContextMenuItem> ad, int itemId,
final int pos, boolean isChecked) {
final OsmandMapTileView view = activity.getMapView();
final AlertDialog.Builder b = new AlertDialog.Builder(view.getContext());
b.setTitle(activity.getString(R.string.map_locale));
final String[] txtIds = getSortedMapNamesIds(activity, mapNamesIds,
getMapNamesValues(activity, mapNamesIds));
final String[] txtValues = getMapNamesValues(activity, txtIds);
int selected = -1;
for (int i = 0; i < txtIds.length; i++) {
if (view.getSettings().MAP_PREFERRED_LOCALE.get().equals(txtIds[i])) {
selected = i;
break;
}
}
selectedLanguageIndex = selected;
transliterateNames = view.getSettings().MAP_TRANSLITERATE_NAMES.get();
final OnCheckedChangeListener translitChangdListener = new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
transliterateNames = isChecked;
}
};
final ArrayAdapter<CharSequence> singleChoiceAdapter = new ArrayAdapter<CharSequence>(activity, R.layout.single_choice_switch_item, R.id.text1, txtValues) {
@NonNull
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = super.getView(position, convertView, parent);
AppCompatCheckedTextView checkedTextView = (AppCompatCheckedTextView) v.findViewById(R.id.text1);
if (position == selectedLanguageIndex && position > 0) {
checkedTextView.setChecked(true);
v.findViewById(R.id.topDivider).setVisibility(View.VISIBLE);
v.findViewById(R.id.bottomDivider).setVisibility(View.VISIBLE);
v.findViewById(R.id.switchLayout).setVisibility(View.VISIBLE);
TextView switchText = (TextView) v.findViewById(R.id.switchText);
switchText.setText(activity.getString(R.string.translit_name_if_miss, txtValues[position]));
SwitchCompat check = (SwitchCompat) v.findViewById(R.id.check);
check.setChecked(transliterateNames);
check.setOnCheckedChangeListener(translitChangdListener);
} else {
checkedTextView.setChecked(position == selectedLanguageIndex);
v.findViewById(R.id.topDivider).setVisibility(View.GONE);
v.findViewById(R.id.bottomDivider).setVisibility(View.GONE);
v.findViewById(R.id.switchLayout).setVisibility(View.GONE);
}
return v;
}
};
b.setAdapter(singleChoiceAdapter, null);
b.setSingleChoiceItems(txtValues, selected, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
selectedLanguageIndex = which;
((AlertDialog) dialog).getListView().setSelection(which);
singleChoiceAdapter.notifyDataSetChanged();
}
});
b.setNegativeButton(R.string.shared_string_cancel, null);
b.setPositiveButton(R.string.shared_string_apply, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
view.getSettings().MAP_TRANSLITERATE_NAMES.set(selectedLanguageIndex > 0 && transliterateNames);
AlertDialog dlg = (AlertDialog) dialog;
int index = dlg.getListView().getCheckedItemPosition();
view.getSettings().MAP_PREFERRED_LOCALE.set(
txtIds[index]);
refreshMapComplete(activity);
String localeDescr = txtIds[index];
localeDescr = localeDescr == null || localeDescr.equals("") ? activity
.getString(R.string.local_map_names) : localeDescr;
adapter.getItem(pos).setDescription(localeDescr);
ad.notifyDataSetInvalidated();
}
});
b.show();
return false;
}
}).createItem());
props = createProperties(customRules, null, R.string.rendering_category_transport, R.drawable.ic_action_bus_dark,
"transport", null, adapter, activity, true);
if (props != null) {
adapter.addItem(props);
}
props = createProperties(customRules, null, R.string.rendering_category_details, R.drawable.ic_action_layers_dark,
"details", null, adapter, activity, true);
if (props != null) {
adapter.addItem(props);
}
props = createProperties(customRules, null, R.string.rendering_category_hide, R.drawable.ic_action_hide,
"hide", null, adapter, activity, true);
if (props != null) {
adapter.addItem(props);
}
List<RenderingRuleProperty> customRulesIncluded = new ArrayList<>();
for (RenderingRuleProperty p : customRules) {
if (p.getAttrName().equals(HIKING_ROUTES_OSMC_ATTR)) {
customRulesIncluded.add(p);
break;
}
}
props = createProperties(customRules, customRulesIncluded, R.string.rendering_category_routes, R.drawable.ic_action_map_routes,
"routes", null, adapter, activity, true);
if (props != null) {
adapter.addItem(props);
}
if (getCustomRenderingPropertiesSize(customRules) > 0) {
adapter.addItem(new ContextMenuItem.ItemBuilder().setTitleId(R.string.rendering_category_others, activity)
.setCategory(true).setLayout(R.layout.list_group_title_with_switch).createItem());
createCustomRenderingProperties(adapter, activity, customRules);
}
}
public static String[] mapNamesIds = new String[]{"", "en", "af", "als", "ar", "az", "be", "ber", "bg", "bn", "bpy", "br", "bs", "ca", "ceb", "cs", "cy", "da", "de", "el", "eo", "es", "et", "eu", "fa", "fi", "fr", "fy", "ga", "gl", "he", "hi", "hsb", "hr", "ht", "hu", "hy", "id", "is", "it", "ja", "ka", "kab", "ko", "ku", "la", "lb", "lt", "lv", "mk", "ml", "mr", "ms", "nds", "new", "nl", "nn", "no", "nv", "os", "pl", "pms", "pt", "ro", "ru", "sc", "sh", "sk", "sl", "sq", "sr", "sv", "sw", "ta", "te", "th", "tl", "tr", "uk", "vi", "vo", "zh"};
public static String[] getSortedMapNamesIds(Context ctx, String[] ids, String[] values) {
final Map<String, String> mp = new HashMap<>();
for (int i = 0; i < ids.length; i++) {
mp.put(ids[i], values[i]);
}
ArrayList<String> lst = new ArrayList<>(mp.keySet());
final String systemLocale = ctx.getString(R.string.system_locale) + " (" + ctx.getString(R.string.system_locale_no_translate) + ")";
final String englishLocale = ctx.getString(R.string.lang_en);
Collections.sort(lst, new Comparator<String>() {
@Override
public int compare(String lhs, String rhs) {
int i1 = Algorithms.isEmpty(lhs) ? 0 : (lhs.equals("en") ? 1 : 2);
int i2 = Algorithms.isEmpty(rhs) ? 0 : (rhs.equals("en") ? 1 : 2);
if (i1 != i2) {
return i1 < i2 ? -1 : 1;
}
i1 = systemLocale.equals(lhs) ? 0 : (englishLocale.equals(lhs) ? 1 : 2);
i2 = systemLocale.equals(rhs) ? 0 : (englishLocale.equals(rhs) ? 1 : 2);
if (i1 != i2) {
return i1 < i2 ? -1 : 1;
}
return mp.get(lhs).compareTo(mp.get(rhs));
}
});
return lst.toArray(new String[lst.size()]);
}
public static String[] getMapNamesValues(Context ctx, String[] ids) {
String[] translates = new String[ids.length];
for (int i = 0; i < translates.length; i++) {
if (Algorithms.isEmpty(ids[i])) {
translates[i] = ctx.getString(R.string.local_map_names);
} else {
translates[i] = ((OsmandApplication) ctx.getApplicationContext()).getLangTranslation(ids[i]);
}
}
return translates;
}
private ContextMenuItem createProperties(List<RenderingRuleProperty> customRules,
final List<RenderingRuleProperty> customRulesIncluded,
@StringRes final int strId,
@DrawableRes final int icon,
String category,
final ListStringPreference defaultSettings,
final ContextMenuAdapter adapter,
final MapActivity activity,
final boolean useDescription) {
final List<RenderingRuleProperty> ps = new ArrayList<>();
final List<OsmandSettings.CommonPreference<Boolean>> prefs = new ArrayList<>();
Iterator<RenderingRuleProperty> it = customRules.iterator();
while (it.hasNext()) {
RenderingRuleProperty p = it.next();
if (category.equals(p.getCategory()) && p.isBoolean()) {
ps.add(p);
final OsmandSettings.CommonPreference<Boolean> pref = activity.getMyApplication().getSettings()
.getCustomRenderBooleanProperty(p.getAttrName());
prefs.add(pref);
it.remove();
}
}
if (prefs.size() > 0) {
final List<OsmandSettings.CommonPreference<String>> includedPrefs = new ArrayList<>();
if (customRulesIncluded != null) {
for (RenderingRuleProperty p : customRulesIncluded) {
if (!p.isBoolean()) {
final OsmandSettings.CommonPreference<String> pref = activity.getMyApplication().getSettings()
.getCustomRenderProperty(p.getAttrName());
includedPrefs.add(pref);
}
}
}
final ItemClickListener clickListener = new ContextMenuAdapter.ItemClickListener() {
@Override
public boolean onContextMenuClick(ArrayAdapter<ContextMenuItem> a, int itemId, int pos,
boolean isChecked) {
if (!isChecked && !useDescription) {
if (defaultSettings != null) {
defaultSettings.set("");
for (int i = 0; i < prefs.size(); i++) {
if (prefs.get(i).get()) {
defaultSettings.addValue(prefs.get(i).getId());
}
}
}
for (int i = 0; i < prefs.size(); i++) {
prefs.get(i).set(false);
}
adapter.getItem(pos).setColorRes(ContextMenuItem.INVALID_ID);
a.notifyDataSetInvalidated();
refreshMapComplete(activity);
activity.getMapLayers().updateLayers(activity.getMapView());
} else {
showPreferencesDialog(adapter, a, pos, activity, activity.getString(strId), ps, prefs,
useDescription, defaultSettings, true, customRulesIncluded);
}
return false;
}
};
ContextMenuItem.ItemBuilder builder = new ContextMenuItem.ItemBuilder().setTitleId(strId, activity)
.setIcon(icon).setListener(clickListener);
boolean selected = false;
for (OsmandSettings.CommonPreference<Boolean> p : prefs) {
if (p.get()) {
selected = true;
break;
}
}
if (!selected && includedPrefs.size() > 0) {
for (OsmandSettings.CommonPreference<String> p : includedPrefs) {
if (!Algorithms.isEmpty(p.get())) {
selected = true;
break;
}
}
}
builder.setColor(selected ? R.color.osmand_orange : ContextMenuItem.INVALID_ID);
if (useDescription) {
final String descr = getDescription(prefs, includedPrefs);
builder.setDescription(descr);
builder.setLayout(R.layout.list_item_single_line_descrition_narrow);
} else {
builder.setListener(new OnRowItemClick() {
@Override
public boolean onContextMenuClick(ArrayAdapter<ContextMenuItem> a, int itemId, int pos, boolean isChecked) {
return clickListener.onContextMenuClick(a, itemId, pos, isChecked);
}
@Override
public boolean onRowItemClick(ArrayAdapter<ContextMenuItem> a, View view, int itemId,
int pos) {
showPreferencesDialog(adapter, a, pos, activity, activity.getString(strId), ps, prefs,
useDescription, defaultSettings, false, customRulesIncluded);
return false;
}
});
builder.setSecondaryIcon(R.drawable.ic_action_additional_option);
builder.setSelected(selected);
}
return builder.createItem();
// createCustomRenderingProperties(adapter, activity, ps);
}
return null;
}
protected String getDescription(final List<OsmandSettings.CommonPreference<Boolean>> prefs,
final List<OsmandSettings.CommonPreference<String>> includedPrefs) {
int count = 0;
int enabled = 0;
for (OsmandSettings.CommonPreference<Boolean> p : prefs) {
count++;
if (p.get()) {
enabled++;
}
}
for (OsmandSettings.CommonPreference<String> p : includedPrefs) {
count++;
if (!Algorithms.isEmpty(p.get())) {
enabled++;
}
}
return enabled + "/" + count;
}
protected void showPreferencesDialog(final ContextMenuAdapter adapter,
final ArrayAdapter<?> a,
final int pos,
final MapActivity activity,
String category,
List<RenderingRuleProperty> ps,
final List<CommonPreference<Boolean>> prefs,
final boolean useDescription,
ListStringPreference defaultSettings,
boolean useDefault,
final List<RenderingRuleProperty> customRulesIncluded) {
AlertDialog.Builder bld = new AlertDialog.Builder(activity);
boolean[] checkedItems = new boolean[prefs.size()];
final boolean[] tempPrefs = new boolean[prefs.size()];
for (int i = 0; i < prefs.size(); i++) {
tempPrefs[i] = checkedItems[i] = defaultSettings != null && useDefault ?
defaultSettings.containsValue(prefs.get(i).getId()) : prefs.get(i).get();
}
final String[] vals = new String[ps.size()];
for (int i = 0; i < ps.size(); i++) {
RenderingRuleProperty p = ps.get(i);
String propertyName = SettingsActivity.getStringPropertyName(activity, p.getAttrName(),
p.getName());
vals[i] = propertyName;
}
bld.setMultiChoiceItems(vals, checkedItems, new OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
tempPrefs[which] = isChecked;
}
});
bld.setTitle(category);
bld.setNegativeButton(R.string.shared_string_cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
boolean selected = false;
for (int i = 0; i < prefs.size(); i++) {
selected |= prefs.get(i).get();
}
adapter.getItem(pos).setSelected(selected);
adapter.getItem(pos).setColorRes(selected ? R.color.osmand_orange : ContextMenuItem.INVALID_ID);
a.notifyDataSetInvalidated();
}
});
bld.setPositiveButton(R.string.shared_string_ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
boolean selected = false;
for (int i = 0; i < prefs.size(); i++) {
prefs.get(i).set(tempPrefs[i]);
selected |= tempPrefs[i];
}
final List<OsmandSettings.CommonPreference<String>> includedPrefs = new ArrayList<>();
if (customRulesIncluded != null) {
for (RenderingRuleProperty p : customRulesIncluded) {
if (p.getAttrName().equals(HIKING_ROUTES_OSMC_ATTR)) {
final OsmandSettings.CommonPreference<String> pref = activity.getMyApplication().getSettings()
.getCustomRenderProperty(p.getAttrName());
includedPrefs.add(pref);
if (hikingRouteOSMCValue == 0) {
pref.set("");
} else {
pref.set(p.getPossibleValues()[hikingRouteOSMCValue - 1]);
selected = true;
}
break;
}
}
}
if (adapter != null) {
if (useDescription) {
adapter.getItem(pos).setDescription(getDescription(prefs, includedPrefs));
} else {
adapter.getItem(pos).setSelected(selected);
}
adapter.getItem(pos).setColorRes(selected ? R.color.osmand_orange : ContextMenuItem.INVALID_ID);
}
a.notifyDataSetInvalidated();
refreshMapComplete(activity);
activity.getMapLayers().updateLayers(activity.getMapView());
}
});
final AlertDialog dialog = bld.create();
if (customRulesIncluded != null) {
for (RenderingRuleProperty p : customRulesIncluded) {
if (!p.isBoolean()) {
final OsmandSettings.CommonPreference<String> pref = activity.getMyApplication().getSettings()
.getCustomRenderProperty(p.getAttrName());
LayoutInflater inflater = activity.getLayoutInflater();
View spinnerView = inflater.inflate(R.layout.spinner_rule_layout, null);
TextView title = (TextView) spinnerView.findViewById(R.id.title);
final Spinner spinner = (Spinner) spinnerView.findViewById(R.id.spinner);
TextView description = (TextView) spinnerView.findViewById(R.id.description);
String propertyName = SettingsActivity.getStringPropertyName(activity, p.getAttrName(),
p.getName());
String propertyDescr = SettingsActivity.getStringPropertyDescription(activity,
p.getAttrName(), p.getName());
title.setText(propertyName);
description.setText(propertyDescr);
int i = Arrays.asList(p.getPossibleValues()).indexOf(pref.get());
if (i >= 0) {
i++;
} else if (Algorithms.isEmpty(pref.get())) {
i = 0;
}
String[] possibleValuesString = new String[p.getPossibleValues().length + 1];
possibleValuesString[0] = SettingsActivity.getStringPropertyValue(activity,
p.getDefaultValueDescription());
for (int j = 0; j < p.getPossibleValues().length; j++) {
possibleValuesString[j + 1] = SettingsActivity.getStringPropertyValue(activity,
p.getPossibleValues()[j]);
}
StringSpinnerArrayAdapter arrayAdapter = new StringSpinnerArrayAdapter(activity);
for (String val : possibleValuesString) {
arrayAdapter.add(val);
}
spinner.setAdapter(arrayAdapter);
hikingRouteOSMCValue = i;
spinner.setSelection(i);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
hikingRouteOSMCValue = position;
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
dialog.getListView().addFooterView(spinnerView);
}
}
}
dialog.show();
}
protected String getRenderDescr(final MapActivity activity) {
RendererRegistry rr = activity.getMyApplication().getRendererRegistry();
RenderingRulesStorage storage = rr.getCurrentSelectedRenderer();
if (storage == null) {
return "";
}
return storage.getName();
}
protected String getDayNightDescr(final MapActivity activity) {
return activity.getMyApplication().getSettings().DAYNIGHT_MODE.get().toHumanString(activity);
}
@DrawableRes
protected int getDayNightIcon(final MapActivity activity) {
return activity.getMyApplication().getSettings().DAYNIGHT_MODE.get().getIconRes();
}
protected String getScale(final MapActivity activity) {
int scale = (int) (activity.getMyApplication().getSettings().TEXT_SCALE.get() * 100);
return scale + " %";
}
private boolean isPropertyAccepted(RenderingRuleProperty p) {
return !(p.getAttrName().equals(RenderingRuleStorageProperties.A_APP_MODE) ||
p.getAttrName().equals(RenderingRuleStorageProperties.A_ENGINE_V1) ||
p.getAttrName().equals(HIKING_ROUTES_OSMC_ATTR) ||
p.getAttrName().equals(ROAD_STYLE_ATTR) ||
p.getAttrName().equals(CONTOUR_WIDTH_ATTR) ||
p.getAttrName().equals(CONTOUR_DENSITY_ATTR) ||
p.getAttrName().equals(CONTOUR_LINES_ATTR) ||
p.getAttrName().equals(CONTOUR_LINES_SCHEME_ATTR) ||
p.getAttrName().equals(CURRENT_TRACK_COLOR_ATTR) ||
p.getAttrName().equals(CURRENT_TRACK_WIDTH_ATTR));
}
private void createCustomRenderingProperties(final ContextMenuAdapter adapter, final MapActivity activity,
List<RenderingRuleProperty> customRules) {
for (final RenderingRuleProperty p : customRules) {
if (isPropertyAccepted(p)) {
adapter.addItem(createRenderingProperty(adapter, activity, 0, p));
}
}
}
private int getCustomRenderingPropertiesSize(List<RenderingRuleProperty> customRules) {
int size = 0;
for (final RenderingRuleProperty p : customRules) {
if (isPropertyAccepted(p)) {
size++;
}
}
return size;
}
private ContextMenuItem createRenderingProperty(final List<RenderingRuleProperty> customRules,
final ContextMenuAdapter adapter, final MapActivity activity,
@DrawableRes final int icon, final String attrName) {
for (final RenderingRuleProperty p : customRules) {
if (p.getAttrName().equals(attrName)) {
return createRenderingProperty(adapter, activity, icon, p);
}
}
return null;
}
private ContextMenuItem createRenderingProperty(final ContextMenuAdapter adapter, final MapActivity activity,
@DrawableRes final int icon, final RenderingRuleProperty p) {
final OsmandMapTileView view = activity.getMapView();
String propertyName = SettingsActivity.getStringPropertyName(view.getContext(), p.getAttrName(),
p.getName());
final String propertyDescr = SettingsActivity.getStringPropertyDescription(view.getContext(),
p.getAttrName(), p.getName());
if (p.isBoolean()) {
final OsmandSettings.CommonPreference<Boolean> pref = view.getApplication().getSettings()
.getCustomRenderBooleanProperty(p.getAttrName());
return ContextMenuItem.createBuilder(propertyName)
.setListener(new ContextMenuAdapter.ItemClickListener() {
@Override
public boolean onContextMenuClick(ArrayAdapter<ContextMenuItem> adapter, int itemId, int pos, boolean isChecked) {
pref.set(!pref.get());
refreshMapComplete(activity);
return false;
}
})
.setSelected(pref.get())
.createItem();
} else {
final OsmandSettings.CommonPreference<String> pref = view.getApplication().getSettings()
.getCustomRenderProperty(p.getAttrName());
final String descr;
if (!Algorithms.isEmpty(pref.get())) {
descr = SettingsActivity.getStringPropertyValue(activity, pref.get());
} else {
descr = SettingsActivity.getStringPropertyValue(view.getContext(),
p.getDefaultValueDescription());
}
ContextMenuItem.ItemBuilder builder = ContextMenuItem.createBuilder(propertyName)
.setListener(new ContextMenuAdapter.ItemClickListener() {
@Override
public boolean onContextMenuClick(final ArrayAdapter<ContextMenuItem> ad,
final int itemId, final int pos, boolean isChecked) {
AlertDialog.Builder b = new AlertDialog.Builder(view.getContext());
// test old descr as title
b.setTitle(propertyDescr);
int i = Arrays.asList(p.getPossibleValues()).indexOf(pref.get());
if (i >= 0) {
i++;
} else if (Algorithms.isEmpty(pref.get())) {
i = 0;
}
String[] possibleValuesString = new String[p.getPossibleValues().length + 1];
possibleValuesString[0] = SettingsActivity.getStringPropertyValue(view.getContext(),
p.getDefaultValueDescription());
for (int j = 0; j < p.getPossibleValues().length; j++) {
possibleValuesString[j + 1] = SettingsActivity.getStringPropertyValue(view.getContext(),
p.getPossibleValues()[j]);
}
b.setSingleChoiceItems(possibleValuesString, i, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (which == 0) {
pref.set("");
} else {
pref.set(p.getPossibleValues()[which - 1]);
}
refreshMapComplete(activity);
String description = SettingsActivity.getStringPropertyValue(activity, pref.get());
adapter.getItem(pos).setDescription(description);
dialog.dismiss();
}
});
b.setNegativeButton(R.string.shared_string_dismiss, null);
b.show();
return false;
}
})
.setDescription(descr)
.setLayout(R.layout.list_item_single_line_descrition_narrow);
if (icon != 0) {
builder.setIcon(icon);
}
return builder.createItem();
}
}
private class StringSpinnerArrayAdapter extends ArrayAdapter<String> {
private boolean lightTheme;
public StringSpinnerArrayAdapter(Context context) {
super(context, android.R.layout.simple_spinner_item);
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
OsmandApplication app = (OsmandApplication )getContext().getApplicationContext();
lightTheme = app.getSettings().isLightContent();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView label = (TextView) super.getView(position, convertView, parent);
String text = getItem(position);
label.setText(text);
label.setTextColor(!lightTheme ?
ContextCompat.getColorStateList(getContext(), android.R.color.primary_text_dark) : ContextCompat.getColorStateList(getContext(), android.R.color.primary_text_light));
return label;
}
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
TextView label = (TextView) super.getDropDownView(position, convertView, parent);
String text = getItem(position);
label.setText(text);
label.setTextColor(!lightTheme ?
ContextCompat.getColorStateList(getContext(), android.R.color.primary_text_dark) : ContextCompat.getColorStateList(getContext(), android.R.color.primary_text_light));
return label;
}
}
public static class GpxAppearanceAdapter extends ArrayAdapter<AppearanceListItem> {
private OsmandApplication app;
private int currentColor;
private GpxAppearanceAdapterType adapterType = GpxAppearanceAdapterType.TRACK_WIDTH_COLOR;
public enum GpxAppearanceAdapterType {
TRACK_WIDTH,
TRACK_COLOR,
TRACK_WIDTH_COLOR
}
public GpxAppearanceAdapter(Context context, String currentColorValue, GpxAppearanceAdapterType adapterType) {
super(context, R.layout.rendering_prop_menu_item);
this.app = (OsmandApplication) getContext().getApplicationContext();
this.adapterType = adapterType;
RenderingRulesStorage renderer = app.getRendererRegistry().getCurrentSelectedRenderer();
this.currentColor = parseTrackColor(renderer, currentColorValue);
init();
}
public GpxAppearanceAdapter(Context context, int currentColor, GpxAppearanceAdapterType adapterType) {
super(context, R.layout.rendering_prop_menu_item);
this.app = (OsmandApplication) getContext().getApplicationContext();
this.adapterType = adapterType;
this.currentColor = currentColor;
init();
}
public void init() {
RenderingRuleProperty trackWidthProp = null;
RenderingRuleProperty trackColorProp = null;
RenderingRulesStorage renderer = app.getRendererRegistry().getCurrentSelectedRenderer();
if (renderer != null) {
if (adapterType == GpxAppearanceAdapterType.TRACK_WIDTH || adapterType == GpxAppearanceAdapterType.TRACK_WIDTH_COLOR) {
trackWidthProp = renderer.PROPS.getCustomRule(CURRENT_TRACK_WIDTH_ATTR);
}
if (adapterType == GpxAppearanceAdapterType.TRACK_COLOR || adapterType == GpxAppearanceAdapterType.TRACK_WIDTH_COLOR) {
trackColorProp = renderer.PROPS.getCustomRule(CURRENT_TRACK_COLOR_ATTR);
}
}
if (trackWidthProp != null) {
AppearanceListItem item = new AppearanceListItem(CURRENT_TRACK_WIDTH_ATTR, "",
SettingsActivity.getStringPropertyValue(getContext(), trackWidthProp.getDefaultValueDescription()));
add(item);
for (int j = 0; j < trackWidthProp.getPossibleValues().length; j++) {
item = new AppearanceListItem(CURRENT_TRACK_WIDTH_ATTR,
trackWidthProp.getPossibleValues()[j],
SettingsActivity.getStringPropertyValue(getContext(), trackWidthProp.getPossibleValues()[j]));
add(item);
}
item.setLastItem(true);
}
if (trackColorProp != null) {
AppearanceListItem item = new AppearanceListItem(CURRENT_TRACK_COLOR_ATTR, "",
SettingsActivity.getStringPropertyValue(getContext(), trackColorProp.getDefaultValueDescription()),
parseTrackColor(renderer, ""));
add(item);
for (int j = 0; j < trackColorProp.getPossibleValues().length; j++) {
item = new AppearanceListItem(CURRENT_TRACK_COLOR_ATTR,
trackColorProp.getPossibleValues()[j],
SettingsActivity.getStringPropertyValue(getContext(), trackColorProp.getPossibleValues()[j]),
parseTrackColor(renderer, trackColorProp.getPossibleValues()[j]));
add(item);
}
item.setLastItem(true);
}
}
public static int parseTrackColor(RenderingRulesStorage renderer, String colorName) {
int defaultColor = -1;
RenderingRule gpxRule = renderer.getRenderingAttributeRule("gpx");
if (gpxRule != null && gpxRule.getIfElseChildren().size() > 0) {
List<RenderingRule> rules = renderer.getRenderingAttributeRule("gpx").getIfElseChildren().get(0).getIfElseChildren();
for (RenderingRule r : rules) {
String cName = r.getStringPropertyValue(CURRENT_TRACK_COLOR_ATTR);
if (!Algorithms.isEmpty(cName) && cName.equals(colorName)) {
return r.getIntPropertyValue(COLOR_ATTR);
}
if (cName == null && defaultColor == -1) {
defaultColor = r.getIntPropertyValue(COLOR_ATTR);
}
}
}
return defaultColor;
}
@NonNull
@Override
public View getView(int position, View convertView, @NonNull ViewGroup parent) {
AppearanceListItem item = getItem(position);
View v = convertView;
if (v == null) {
v = LayoutInflater.from(getContext()).inflate(R.layout.rendering_prop_menu_item, null);
}
if (item != null) {
TextView textView = (TextView) v.findViewById(R.id.text1);
textView.setText(item.localizedValue);
if (item.attrName == CURRENT_TRACK_WIDTH_ATTR) {
int iconId;
if (item.value.equals("bold")) {
iconId = R.drawable.ic_action_gpx_width_bold;
} else if (item.value.equals("medium")) {
iconId = R.drawable.ic_action_gpx_width_medium;
} else {
iconId = R.drawable.ic_action_gpx_width_thin;
}
textView.setCompoundDrawablesWithIntrinsicBounds(null, null,
app.getIconsCache().getPaintedIcon(iconId, currentColor), null);
} else {
if (item.color == -1) {
textView.setCompoundDrawablesWithIntrinsicBounds(null, null,
app.getIconsCache().getThemedIcon(R.drawable.ic_action_circle), null);
} else {
textView.setCompoundDrawablesWithIntrinsicBounds(null, null,
app.getIconsCache().getPaintedIcon(R.drawable.ic_action_circle, item.color), null);
}
}
textView.setCompoundDrawablePadding(AndroidUtils.dpToPx(getContext(), 10f));
v.findViewById(R.id.divider).setVisibility(item.lastItem
&& position < getCount() - 1 ? View.VISIBLE : View.GONE);
}
return v;
}
}
public static class AppearanceListItem {
private String attrName;
private String value;
private String localizedValue;
private int color;
private boolean lastItem;
public AppearanceListItem(String attrName, String value, String localizedValue) {
this.attrName = attrName;
this.value = value;
this.localizedValue = localizedValue;
}
public AppearanceListItem(String attrName, String value, String localizedValue, int color) {
this.attrName = attrName;
this.value = value;
this.localizedValue = localizedValue;
this.color = color;
}
public String getAttrName() {
return attrName;
}
public String getValue() {
return value;
}
public String getLocalizedValue() {
return localizedValue;
}
public int getColor() {
return color;
}
public boolean isLastItem() {
return lastItem;
}
public void setLastItem(boolean lastItem) {
this.lastItem = lastItem;
}
}
}