Introduce plugin concept and plugin settings

This commit is contained in:
Victor Shcherb 2012-05-22 19:19:54 +02:00
parent 51f386a8f7
commit 4846c6f647
15 changed files with 417 additions and 264 deletions

View file

@ -1,5 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<resources>
<string name="tip_recent_changes_0_8_0_t">Changes in 0.8.0 :
\n\t- Plugin functionality
\n\t- New offline map data support
\n\t- Lots of bug fixes
</string>
<string name="osm_editing_plugin_description">This plugin is intented to improve OSM quality. It allows to collect/modify OSM POI objects, open/comment OSM bugs and send recorded GPX (requires OSM credentials).</string>
<string name="osm_editing_plugin_name">Osm Editing</string>
<string name="vector_maps_may_display_faster_on_some_devices">Vector maps may display faster. May not work well on some devices.</string>
<string name="simulate_route_progression_manually">Simulate route progression manually</string>
<string name="play_commands_of_currently_selected_voice">Play commands of currently selected voice</string>

View file

@ -162,9 +162,4 @@ public class MapExplorer implements OnGestureListener, IContextMenuProvider {
return mapView.getContext().getString(R.string.i_am_here);
}
@Override
public DialogInterface.OnClickListener getActionListener(List<String> actionsList, Object o) {
return null;
}
}

View file

@ -0,0 +1,77 @@
package net.osmand.plus;
import java.util.ArrayList;
import gnu.trove.list.array.TIntArrayList;
import android.content.Context;
public class ContextMenuAdapter {
public interface OnContextMenuClick {
public void onContextMenuClick(int itemId, int pos, boolean isChecked);
}
private final Context ctx;
final TIntArrayList items = new TIntArrayList();
final ArrayList<String> itemNames = new ArrayList<String>();
final ArrayList<OnContextMenuClick> listeners = new ArrayList<ContextMenuAdapter.OnContextMenuClick>();
final TIntArrayList selectedList = new TIntArrayList();
final TIntArrayList iconList = new TIntArrayList();
public ContextMenuAdapter(Context ctx) {
this.ctx = ctx;
}
public int length(){
return items.size();
}
public int getItemId(int pos){
return items.get(pos);
}
public OnContextMenuClick getClickAdapter(int i) {
return listeners.get(i);
}
public String getItemName(int pos){
return itemNames.get(pos);
}
public int getSelection(int pos) {
return selectedList.get(pos);
}
public int getImageId(int pos) {
return iconList.get(pos);
}
public void registerItem(int stringResId, int icon, OnContextMenuClick listener, int pos) {
registerSelectedItem(stringResId, -1, icon, listener, pos);
}
public void registerSelectedItem(int stringResId, int selected, int icon, OnContextMenuClick listener, int pos) {
if(pos >= items.size() || pos < 0) {
pos = items.size();
}
items.insert(pos, stringResId);
itemNames.add(pos, ctx.getString(stringResId));
selectedList.insert(pos, selected);
iconList.insert(pos, icon);
}
public void registerSelectedItem(int stringResId, int selected, int icon) {
registerSelectedItem(stringResId, selected, icon, null, -1);
}
public void registerItem(int stringResId) {
registerSelectedItem(stringResId, -1, 0);
}
public String[] getItemNames() {
return itemNames.toArray(new String[itemNames.size()]);
}
}

View file

@ -1,9 +1,9 @@
package net.osmand.plus;
import gnu.trove.list.array.TIntArrayList;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.osmedit.OsmEditingPlugin;
@ -11,28 +11,23 @@ import net.osmand.plus.views.OsmandMapTileView;
public abstract class OsmandPlugin {
private static List<OsmandPlugin> plugins = new ArrayList<OsmandPlugin>();
private static List<OsmandPlugin> installedPlugins = new ArrayList<OsmandPlugin>();
private static List<OsmandPlugin> activePlugins = new ArrayList<OsmandPlugin>();
static {
plugins.add(new OsmEditingPlugin());
}
public static List<OsmandPlugin> getAvailablePlugins(){
return plugins;
}
@SuppressWarnings("unchecked")
public static <T extends OsmandPlugin> T getEnabledPlugin(Class<T> clz) {
for(OsmandPlugin lr : plugins) {
if(clz.isInstance(lr)){
return (T) lr;
}
}
return null;
installedPlugins.add(new OsmEditingPlugin());
}
public abstract String getId();
public abstract String getDescription();
public abstract String getName();
public String getVersion() {
return "";
}
/**
* Initialize plugin runs just after creation
*/
@ -40,8 +35,14 @@ public abstract class OsmandPlugin {
public static void initPlugins(OsmandApplication app) {
for (OsmandPlugin plugin : plugins) {
plugin.init(app);
OsmandSettings settings = app.getSettings();
Set<String> enabledPlugins = settings.getEnabledPlugins();
for (OsmandPlugin plugin : installedPlugins) {
if (enabledPlugins.contains(plugin.getId())) {
if (plugin.init(app)) {
activePlugins.add(plugin);
}
}
}
}
@ -51,7 +52,7 @@ public abstract class OsmandPlugin {
public abstract void updateLayers(OsmandMapTileView mapView);
public static void refreshLayers(OsmandMapTileView mapView) {
for (OsmandPlugin plugin : plugins) {
for (OsmandPlugin plugin : activePlugins) {
plugin.updateLayers(mapView);
}
}
@ -59,36 +60,77 @@ public abstract class OsmandPlugin {
public abstract void registerLayers(MapActivity activity);
public static void createLayers(OsmandMapTileView mapView, MapActivity activity) {
for (OsmandPlugin plugin : plugins) {
plugin.registerLayers(activity);
}
public void mapActivityCreate(MapActivity activity) { }
public void mapActivityResume(MapActivity activity) { }
public void mapActivityPause(MapActivity activity) { }
public void mapActivityDestroy(MapActivity activity) { }
public abstract void registerLayerContextMenuActions(OsmandMapTileView mapView, ContextMenuAdapter adapter);
public abstract void registerMapContextMenuActions(MapActivity mapActivity, double latitude, double longitude, ContextMenuAdapter adapter, Object selectedObj);
public static List<OsmandPlugin> getAvailablePlugins(){
return installedPlugins;
}
public static List<OsmandPlugin> getEnabledPlugins(){
return activePlugins;
}
@SuppressWarnings("unchecked")
public static <T extends OsmandPlugin> T getEnabledPlugin(Class<T> clz) {
for(OsmandPlugin lr : activePlugins) {
if(clz.isInstance(lr)){
return (T) lr;
}
}
return null;
}
public abstract void mapActivityCreate(MapActivity activity);
public static void onMapActivityCreate(MapActivity activity) {
for (OsmandPlugin plugin : plugins) {
for (OsmandPlugin plugin : activePlugins) {
plugin.mapActivityCreate(activity);
}
}
public abstract boolean handleContextMenuAction(int resId, double latitude, double longitude);
public abstract void registerContextMenuActions(double latitude, double longitude, TIntArrayList list);
public static void registerContextMenu(double latitude, double longitude, TIntArrayList list) {
for (OsmandPlugin plugin : plugins) {
plugin.registerContextMenuActions(latitude, longitude, list);
public static void onMapActivityResume(MapActivity activity) {
for (OsmandPlugin plugin : activePlugins) {
plugin.mapActivityResume(activity);
}
}
public static boolean contextMenuAction(int resId, double latitude, double longitude) {
for (OsmandPlugin plugin : plugins) {
if(plugin.handleContextMenuAction(resId, latitude, longitude)){
return true;
}
public static void onMapActivityPause(MapActivity activity) {
for (OsmandPlugin plugin : activePlugins) {
plugin.mapActivityPause(activity);
}
}
public static void onMapActivityDestroy(MapActivity activity) {
for (OsmandPlugin plugin : activePlugins) {
plugin.mapActivityDestroy(activity);
}
}
public static void createLayers(OsmandMapTileView mapView, MapActivity activity) {
for (OsmandPlugin plugin : activePlugins) {
plugin.registerLayers(activity);
}
}
public static void registerMapContextMenu(MapActivity map, double latitude, double longitude, ContextMenuAdapter adapter, Object selectedObj) {
for (OsmandPlugin plugin : activePlugins) {
plugin.registerMapContextMenuActions(map, latitude, longitude, adapter, selectedObj);
}
}
public static void registerLayerContextMenu(OsmandMapTileView mapView, ContextMenuAdapter adapter) {
for (OsmandPlugin plugin : activePlugins) {
plugin.registerLayerContextMenuActions(mapView, adapter);
}
return false;
}
}

View file

@ -4,9 +4,13 @@ import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import net.osmand.Version;
import net.osmand.access.AccessibilityMode;
@ -73,21 +77,18 @@ public class OsmandSettings {
private boolean internetConnectionAvailable = true;
private List<TileSourceTemplate> internetAvailableSourceTemplates = null;
// TODO make all layers profile preferenced????
protected OsmandSettings(OsmandApplication application) {
ctx = application;
//TODO: Is it really intended to keep settings WORLD_READABLE?
// TODO: Is it really intended to keep settings WORLD_READABLE?
globalPreferences = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE);
// start from default settings
currentMode = ApplicationMode.DEFAULT;
defaultProfilePreferences = getProfilePreferences(ApplicationMode.DEFAULT);
profilePreferences = defaultProfilePreferences;
// if(FOLLOW_TO_THE_ROUTE.get()){
currentMode = readApplicationMode();
profilePreferences = getProfilePreferences(currentMode);
// }
currentMode = readApplicationMode();
profilePreferences = getProfilePreferences(currentMode);
}
public static String getSharedPreferencesName(ApplicationMode mode){
@ -425,6 +426,39 @@ public class OsmandSettings {
}
}
// this value string is synchronized with settings_pref.xml preference name
private final OsmandPreference<String> ENABLED_PLUGINS =
new StringPreference("enabled_plugins", "", true);
public Set<String> getEnabledPlugins(){
String plugs = ENABLED_PLUGINS.get();
StringTokenizer toks = new StringTokenizer(plugs, ",");
Set<String> res = new LinkedHashSet<String>();
while(toks.hasMoreTokens()) {
res.add(toks.nextToken());
}
return res;
}
public void enablePlugin(String pluginId, boolean enable){
Set<String> set = getEnabledPlugins();
if(enable){
set.add(pluginId);
} else {
set.remove(pluginId);
}
StringBuilder serialization = new StringBuilder();
Iterator<String> it = set.iterator();
while(it.hasNext()){
serialization.append(it.next());
if(it.hasNext()) {
serialization.append(",");
}
}
ENABLED_PLUGINS.set(serialization.toString());
}
/////////////// PREFERENCES classes ////////////////
// this value string is synchronized with settings_pref.xml preference name

View file

@ -19,6 +19,7 @@ import net.osmand.data.MapTileDownloader.IMapDownloaderCallback;
import net.osmand.map.IMapLocationListener;
import net.osmand.osm.LatLon;
import net.osmand.plus.BusyIndicator;
import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.FavouritesDbHelper;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
@ -316,6 +317,7 @@ public class MapActivity extends AccessibleActivity implements IMapLocationListe
getMyApplication().getResourceManager().setBusyIndicator(new BusyIndicator(this, progress));
}
OsmandPlugin.onMapActivityResume(this);
getMyApplication().getDaynightHelper().onMapResume();
mapView.refreshMap(true);
}
@ -650,6 +652,7 @@ public class MapActivity extends AccessibleActivity implements IMapLocationListe
@Override
protected void onDestroy() {
super.onDestroy();
OsmandPlugin.onMapActivityDestroy(this);
savingTrackHelper.close();
routeAnimation.close();
cancelNotification();
@ -981,6 +984,7 @@ public class MapActivity extends AccessibleActivity implements IMapLocationListe
settings.MAP_ACTIVITY_ENABLED.set(false);
getMyApplication().getResourceManager().interruptRendering();
getMyApplication().getResourceManager().setBusyIndicator(null);
OsmandPlugin.onMapActivityPause(this);
}
public void updateApplicationModeSettings(){
@ -1315,9 +1319,8 @@ public class MapActivity extends AccessibleActivity implements IMapLocationListe
mapActions.contextMenuPoint(latitude, longitude, null, null);
}
public void contextMenuPoint(final double latitude, final double longitude, List<String> additionalItems,
final DialogInterface.OnClickListener additionalActions) {
mapActions.contextMenuPoint(latitude, longitude, additionalItems, additionalActions);
public void contextMenuPoint(final double latitude, final double longitude, ContextMenuAdapter adapter, Object selectedObj) {
mapActions.contextMenuPoint(latitude, longitude, adapter, selectedObj);
}
public MapActivityActions getMapActions() {

View file

@ -1,6 +1,5 @@
package net.osmand.plus.activities;
import gnu.trove.list.array.TIntArrayList;
import java.io.File;
import java.text.MessageFormat;
@ -22,6 +21,8 @@ import net.osmand.map.ITileSource;
import net.osmand.osm.LatLon;
import net.osmand.osm.MapUtils;
import net.osmand.plus.AmenityIndexRepositoryOdb;
import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.ContextMenuAdapter.OnContextMenuClick;
import net.osmand.plus.FavouritesDbHelper;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
@ -715,40 +716,32 @@ public class MapActivityActions implements DialogProvider {
}
public void contextMenuPoint(final double latitude, final double longitude, List<String> additionalItems,
final DialogInterface.OnClickListener additionalActions) {
public void contextMenuPoint(final double latitude, final double longitude, final ContextMenuAdapter iadapter, Object selectedObj) {
final ContextMenuAdapter adapter = iadapter == null ? new ContextMenuAdapter(mapActivity) : iadapter;
Builder builder = new AlertDialog.Builder(mapActivity);
final int sizeAdditional = additionalActions == null || additionalItems == null ? 0 : additionalItems.size();
List<String> actions = new ArrayList<String>();
if (sizeAdditional > 0) {
actions.addAll(additionalItems);
}
final OsmandMapTileView mapView = mapActivity.getMapView();
final TIntArrayList contextMenuStandardActions = new TIntArrayList();
contextMenuStandardActions.add(new int[] { R.string.context_menu_item_navigate_point,
R.string.context_menu_item_show_route, R.string.context_menu_item_search, R.string.context_menu_item_add_favorite,
R.string.context_menu_item_share_location, R.string.context_menu_item_add_waypoint});
OsmandPlugin.registerContextMenu(latitude, longitude, contextMenuStandardActions);
if(mapView.getMainLayer() instanceof MapTileLayer) {
contextMenuStandardActions.add(R.string.context_menu_item_update_map);
contextMenuStandardActions.add(R.string.context_menu_item_download_map);
adapter.registerItem(R.string.context_menu_item_navigate_point);
adapter.registerItem(R.string.context_menu_item_show_route);
adapter.registerItem(R.string.context_menu_item_search);
adapter.registerItem(R.string.context_menu_item_add_favorite);
adapter.registerItem(R.string.context_menu_item_share_location);
adapter.registerItem(R.string.context_menu_item_add_waypoint);
OsmandPlugin.registerMapContextMenu(mapActivity, latitude, longitude, adapter, selectedObj);
if (mapView.getMainLayer() instanceof MapTileLayer) {
adapter.registerItem(R.string.context_menu_item_update_map);
adapter.registerItem(R.string.context_menu_item_download_map);
}
for (int j = 0; j < contextMenuStandardActions.size(); j++) {
actions.add(mapActivity.getString(contextMenuStandardActions.get(j)));
}
builder.setItems(actions.toArray(new String[actions.size()]), new DialogInterface.OnClickListener() {
builder.setItems(adapter.getItemNames(), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (which < sizeAdditional) {
additionalActions.onClick(dialog, which);
return;
}
int standardId = contextMenuStandardActions.get(which - sizeAdditional);
if(OsmandPlugin.contextMenuAction(standardId, latitude, longitude)) {
// Plugin action
int standardId = adapter.getItemId(which );
OnContextMenuClick click = adapter.getClickAdapter(which);
if(click != null) {
click.onContextMenuClick(standardId, which, false);
} else if (standardId == R.string.context_menu_item_navigate_point) {
mapActivity.navigateToPoint(new LatLon(latitude, longitude));
} else if (standardId == R.string.context_menu_item_show_route) {

View file

@ -1,6 +1,5 @@
package net.osmand.plus.activities;
import gnu.trove.list.array.TIntArrayList;
import java.io.File;
import java.util.ArrayList;
@ -22,6 +21,8 @@ import net.osmand.access.AccessibleToast;
import net.osmand.data.AmenityType;
import net.osmand.map.ITileSource;
import net.osmand.map.TileSourceManager.TileSourceTemplate;
import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.ContextMenuAdapter.OnContextMenuClick;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.OsmandSettings;
@ -246,68 +247,57 @@ public class MapActivityLayers {
}
public void openLayerSelectionDialog(final OsmandMapTileView mapView){
final TIntArrayList layers = new TIntArrayList();
final TIntArrayList selectedList = new TIntArrayList();
final TIntArrayList iconList = new TIntArrayList();
final OsmandSettings settings = getApplication().getSettings();
layers.add(R.string.layer_map);
iconList.add(R.drawable.list_activities_map_src);
selectedList.add(-1);
layers.add(R.string.layer_poi);
iconList.add(R.drawable.list_activities_poi);
selectedList.add(settings.SHOW_POI_OVER_MAP.get() ? 1 : 0);
if(settings.SHOW_POI_OVER_MAP.get()){
layers.add(R.string.layer_poi_label);
selectedList.add(settings.SHOW_POI_LABEL.get() ? 1 : 0);
iconList.add(0);
}
layers.add(R.string.layer_favorites);
iconList.add(R.drawable.list_activities_favorites);
selectedList.add(settings.SHOW_FAVORITES.get() ? 1 : 0);
layers.add(R.string.layer_gpx_layer);
selectedList.add(getApplication().getGpxFileToDisplay() != null ? 1 : 0);
iconList.add(R.drawable.list_activities_gpx_tracks);
final ContextMenuAdapter adapter = new ContextMenuAdapter(activity);
adapter.registerSelectedItem(R.string.layer_map, -1, R.drawable.list_activities_map_src);
adapter.registerSelectedItem(R.string.layer_poi, settings.SHOW_POI_OVER_MAP.get() ? 1 : 0,
R.drawable.list_activities_poi);
adapter.registerSelectedItem(R.string.layer_poi_label, settings.SHOW_POI_LABEL.get() ? 1 : 0,
0);
adapter.registerSelectedItem(R.string.layer_favorites, settings.SHOW_FAVORITES.get() ? 1 : 0,
R.drawable.list_activities_favorites);
adapter.registerSelectedItem(R.string.layer_gpx_layer,
getApplication().getGpxFileToDisplay() != null ? 1 : 0, R.drawable.list_activities_gpx_tracks);
if(routeInfoLayer.couldBeVisible()){
layers.add(R.string.layer_route);
selectedList.add(routeInfoLayer.isUserDefinedVisible() ? 1 : 0);
iconList.add(0);
adapter.registerSelectedItem(R.string.layer_route,
routeInfoLayer.isUserDefinedVisible() ? 1 : 0, 0);
}
layers.add(R.string.layer_transport);
selectedList.add(settings.SHOW_TRANSPORT_OVER_MAP.get() ? 1 : 0);
iconList.add(R.drawable.list_activities_transport_stops);
adapter.registerSelectedItem(R.string.layer_transport, settings.SHOW_TRANSPORT_OVER_MAP.get() ? 1 : 0,
R.drawable.list_activities_transport_stops);
if(TransportRouteHelper.getInstance().routeIsCalculated()){
layers.add(R.string.layer_transport_route);
selectedList.add(routeInfoLayer.isUserDefinedVisible() ? 1 : 0);
iconList.add(0);
adapter.registerSelectedItem(R.string.layer_transport_route,
routeInfoLayer.isUserDefinedVisible() ? 1 : 0, 0);
}
layers.add(R.string.layer_osm_bugs);
selectedList.add(settings.SHOW_OSM_BUGS.get() ? 1 : 0);
iconList.add(R.drawable.list_activities_osm_bugs);
layers.add(R.string.layer_overlay);
selectedList.add(overlayLayer.getMap() != null ? 1 : 0);
iconList.add(R.drawable.list_activities_overlay_map);
layers.add(R.string.layer_underlay);
selectedList.add(underlayLayer.getMap() != null ? 1 : 0);
iconList.add(R.drawable.list_activities_underlay_map);
adapter.registerSelectedItem(R.string.layer_overlay, overlayLayer.getMap() != null ? 1 : 0,
R.drawable.list_activities_overlay_map);
adapter.registerSelectedItem(R.string.layer_underlay, underlayLayer.getMap() != null ? 1 : 0,
R.drawable.list_activities_underlay_map);
OsmandPlugin.registerLayerContextMenu(mapView, adapter);
final OnMultiChoiceClickListener listener = new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int item, boolean isChecked) {
if (layers.get(item) == R.string.layer_map) {
int itemId = adapter.getItemId(item);
OnContextMenuClick clck = adapter.getClickAdapter(item);
if(clck != null) {
clck.onContextMenuClick(itemId, item, isChecked);
} else if (itemId == R.string.layer_map) {
dialog.dismiss();
selectMapLayer(mapView);
} else if(layers.get(item) == R.string.layer_poi){
} else if(itemId == R.string.layer_poi){
if(isChecked){
selectPOIFilterLayer(mapView);
}
settings.SHOW_POI_OVER_MAP.set(isChecked);
} else if(layers.get(item) == R.string.layer_poi_label){
} else if(itemId == R.string.layer_poi_label){
settings.SHOW_POI_LABEL.set(isChecked);
} else if(layers.get(item) == R.string.layer_favorites){
} else if(itemId == R.string.layer_favorites){
settings.SHOW_FAVORITES.set(isChecked);
} else if(layers.get(item) == R.string.layer_gpx_layer){
} else if(itemId == R.string.layer_gpx_layer){
if(getApplication().getGpxFileToDisplay() != null){
getApplication().setGpxFileToDisplay(null, false);
gpxLayer.clearCurrentGPX();
@ -315,15 +305,13 @@ public class MapActivityLayers {
dialog.dismiss();
showGPXFileLayer(mapView);
}
} else if(layers.get(item) == R.string.layer_route){
} else if(itemId == R.string.layer_route){
routeInfoLayer.setVisible(isChecked);
} else if(layers.get(item) == R.string.layer_transport_route){
} else if(itemId == R.string.layer_transport_route){
transportInfoLayer.setVisible(isChecked);
} else if(layers.get(item) == R.string.layer_transport){
} else if(itemId == R.string.layer_transport){
settings.SHOW_TRANSPORT_OVER_MAP.set(isChecked);
} else if(layers.get(item) == R.string.layer_osm_bugs){
settings.SHOW_OSM_BUGS.set(isChecked);
} else if(layers.get(item) == R.string.layer_overlay){
} else if(itemId == R.string.layer_overlay){
if(overlayLayer.getMap() != null){
settings.MAP_OVERLAY.set(null);
updateMapSource(mapView, null);
@ -332,7 +320,7 @@ public class MapActivityLayers {
selectMapOverlayLayer(mapView, settings.MAP_OVERLAY, settings.MAP_OVERLAY_TRANSPARENCY,
overlayLayer);
}
} else if(layers.get(item) == R.string.layer_underlay){
} else if(itemId == R.string.layer_underlay){
if(underlayLayer.getMap() != null){
settings.MAP_UNDERLAY.set(null);
updateMapSource(mapView, null);
@ -351,31 +339,26 @@ public class MapActivityLayers {
// list.setBackgroundColor(white);
list.setCacheColorHint(activity.getResources().getColor(R.color.color_transparent));
b.setView(list);
final List<String> layerNames = new ArrayList<String>();
for (int i = 0; i < layers.size(); i++) {
layerNames.add(getString(layers.get(i)));
}
final AlertDialog dlg = b.create();
final int minWidth = activity.getResources().getDrawable(R.drawable.list_activities_favorites).getMinimumWidth();
ArrayAdapter<String> adapter = new ArrayAdapter<String>(activity, R.layout.layers_list_activity_item,
layerNames) {
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(activity, R.layout.layers_list_activity_item,
adapter.getItemNames()) {
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
View row = activity.getLayoutInflater().inflate(R.layout.layers_list_activity_item, null);
((TextView) row.findViewById(R.id.title)).setText(layerNames.get(position));
if(iconList.get(position) != 0) {
Drawable d = activity.getResources().getDrawable(iconList.get(position));
((TextView) row.findViewById(R.id.title)).setText(adapter.getItemName(position));
if(adapter.getImageId(position) != 0) {
Drawable d = activity.getResources().getDrawable(adapter.getImageId(position));
((ImageView) row.findViewById(R.id.icon)).setImageDrawable(d);
} else {
LinearLayout.LayoutParams layoutParams = (android.widget.LinearLayout.LayoutParams) ((ImageView) row.findViewById(R.id.icon)).getLayoutParams();
layoutParams.leftMargin = minWidth;
}
final CheckBox ch = ((CheckBox) row.findViewById(R.id.check_item));
if(selectedList.get(position) == -1){
if(adapter.getSelection(position) == -1){
ch.setVisibility(View.INVISIBLE);
} else {
ch.setChecked(selectedList.get(position) > 0);
ch.setChecked(adapter.getSelection(position) > 0);
ch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
@ -396,15 +379,15 @@ public class MapActivityLayers {
return row;
}
};
list.setAdapter(adapter);
list.setAdapter(arrayAdapter);
list.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(selectedList.get(position) >= 0) {
if(adapter.getSelection(position) >= 0) {
CheckBox ch = ((CheckBox) view.findViewById(R.id.check_item));
ch.setChecked(!ch.isChecked());
} else {
listener.onClick(dlg, position, selectedList.get(position) > 0);
listener.onClick(dlg, position, adapter.getSelection(position) > 0);
}
}
});

View file

@ -16,14 +16,14 @@ import java.util.regex.Pattern;
import net.osmand.LogUtil;
import net.osmand.access.AccessibleToast;
import net.osmand.osm.LatLon;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.ContextMenuAdapter.OnContextMenuClick;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.activities.DialogProvider;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.views.ContextMenuLayer.IContextMenuProvider;
import net.osmand.plus.views.OsmandMapLayer;
import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
import net.osmand.plus.views.OsmandMapTileView;
import org.apache.commons.logging.Log;
@ -33,7 +33,6 @@ import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
@ -451,25 +450,26 @@ public class OsmBugsLayer extends OsmandMapLayer implements IContextMenuProvider
return builder.create();
}
@Override
public OnClickListener getActionListener(List<String> actionsList, Object o) {
final OpenStreetBug bug = (OpenStreetBug) o;
actionsList.add(activity.getString(R.string.osb_comment_menu_item));
actionsList.add(activity.getString(R.string.osb_close_menu_item));
return new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (which == 0) {
commentBug(bug);
} else if (which == 1) {
closeBug(bug);
public void populateObjectContextMenu(Object o, ContextMenuAdapter adapter) {
if(o instanceof OpenStreetBug) {
final OpenStreetBug bug = (OpenStreetBug) o;
OnContextMenuClick listener = new OnContextMenuClick() {
@Override
public void onContextMenuClick(int itemId, int pos, boolean isChecked) {
if (itemId == R.string.osb_comment_menu_item) {
commentBug(bug);
} else if (itemId == R.string.osb_close_menu_item) {
closeBug(bug);
}
}
}
};
};
adapter.registerItem(R.string.osb_comment_menu_item, 0, listener, -1);
adapter.registerItem(R.string.osb_close_menu_item, 0, listener, -1);
}
}
@Override
public String getObjectDescription(Object o) {
if(o instanceof OpenStreetBug){

View file

@ -1,6 +1,8 @@
package net.osmand.plus.osmedit;
import gnu.trove.list.array.TIntArrayList;
import net.osmand.data.Amenity;
import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.ContextMenuAdapter.OnContextMenuClick;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.OsmandSettings;
@ -9,8 +11,9 @@ import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.views.OsmandMapTileView;
public class OsmEditingPlugin extends OsmandPlugin {
private static final String ID = "osm.editing.plugin";
private static final String ID = "osm.editing";
private OsmandSettings settings;
private OsmandApplication app;
@Override
public String getId() {
@ -19,6 +22,7 @@ public class OsmEditingPlugin extends OsmandPlugin {
@Override
public boolean init(OsmandApplication app) {
this.app = app;
settings = app.getSettings();
return true;
}
@ -53,23 +57,65 @@ public class OsmEditingPlugin extends OsmandPlugin {
public EditingPOIActivity getPoiActions() {
return poiActions;
}
@Override
public boolean handleContextMenuAction(int resId, final double latitude, final double longitude) {
if (resId == R.string.context_menu_item_create_poi) {
poiActions.showCreateDialog(latitude, longitude);
return true;
} else if (resId == R.string.context_menu_item_open_bug) {
osmBugsLayer.openBug(latitude, longitude);
return true;
public void registerMapContextMenuActions(MapActivity mapActivity, final double latitude, final double longitude, ContextMenuAdapter adapter,
Object selectedObj) {
if(selectedObj instanceof Amenity) {
final Amenity a = (Amenity) selectedObj;
OnContextMenuClick alist = new OnContextMenuClick() {
@Override
public void onContextMenuClick(int resId, int pos, boolean isChecked) {
if (resId == R.string.poi_context_menu_delete) {
getPoiActions().showDeleteDialog(a);
} else if (resId == R.string.poi_context_menu_modify) {
getPoiActions().showEditDialog(a);
}
}
};
adapter.registerItem(R.string.poi_context_menu_modify, 0, alist, 1);
adapter.registerItem(R.string.poi_context_menu_delete, 0, alist, 2);
}
return false;
OnContextMenuClick listener = new OnContextMenuClick() {
@Override
public void onContextMenuClick(int resId, int pos, boolean isChecked) {
if (resId == R.string.context_menu_item_create_poi) {
poiActions.showCreateDialog(latitude, longitude);
} else if (resId == R.string.context_menu_item_open_bug) {
osmBugsLayer.openBug(latitude, longitude);
}
}
};
adapter.registerItem(R.string.context_menu_item_create_poi, 0, listener, -1);
adapter.registerItem(R.string.context_menu_item_open_bug, 0, listener, -1);
}
@Override
public void registerContextMenuActions(double latitude, double longitude, TIntArrayList list) {
list.add(R.string.context_menu_item_create_poi);
list.add(R.string.context_menu_item_open_bug);
public void registerLayerContextMenuActions(OsmandMapTileView mapView, ContextMenuAdapter adapter) {
adapter.registerSelectedItem(R.string.layer_osm_bugs, settings.SHOW_OSM_BUGS.get() ? 1 : 0, R.drawable.list_activities_osm_bugs,
new OnContextMenuClick() {
@Override
public void onContextMenuClick(int itemId, int pos, boolean isChecked) {
if (itemId == R.string.layer_osm_bugs) {
settings.SHOW_OSM_BUGS.set(isChecked);
}
}
}, 5);
}
@Override
public String getDescription() {
return app.getString(R.string.osm_editing_plugin_description);
}
@Override
public String getName() {
return app.getString(R.string.osm_editing_plugin_name);
}
}

View file

@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.List;
import net.osmand.osm.LatLon;
import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import android.app.AlertDialog;
@ -37,7 +38,6 @@ public class ContextMenuLayer extends OsmandMapLayer {
public String getObjectName(Object o);
public DialogInterface.OnClickListener getActionListener(List<String> actionsList, Object o);
}
private LatLon latLon;
@ -284,6 +284,7 @@ public class ContextMenuLayer extends OsmandMapLayer {
}
private void showContextMenuForSelectedObjects() {
final ContextMenuAdapter menuAdapter = new ContextMenuAdapter(activity);
if(selectedObjects.size() > 1){
Builder builder = new AlertDialog.Builder(view.getContext());
String[] d = new String[selectedObjects.size()];
@ -294,21 +295,22 @@ public class ContextMenuLayer extends OsmandMapLayer {
builder.setItems(d, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// single selection at 0
selectedObjects.set(0, selectedObjects.get(which));
ArrayList<String> l = new ArrayList<String>();
OnClickListener listener = selectedContextProvider.getActionListener(l, selectedObjects.get(0));
activity.contextMenuPoint(latLon.getLatitude(), latLon.getLongitude(), l, listener);
Object selectedObj = selectedObjects.get(which);
for(OsmandMapLayer layer : view.getLayers()) {
layer.populateObjectContextMenu(selectedObj, menuAdapter);
}
activity.contextMenuPoint(latLon.getLatitude(), latLon.getLongitude(), menuAdapter, selectedObj);
}
});
builder.show();
} else {
ArrayList<String> l = new ArrayList<String>();
OnClickListener listener = selectedContextProvider.getActionListener(l, selectedObjects.get(0));
activity.contextMenuPoint(latLon.getLatitude(), latLon.getLongitude(), l, listener);
Object selectedObj = selectedObjects.get(0);
for(OsmandMapLayer layer : view.getLayers()) {
layer.populateObjectContextMenu(selectedObj, menuAdapter);
}
activity.contextMenuPoint(latLon.getLatitude(), latLon.getLongitude(), menuAdapter, selectedObj);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {

View file

@ -9,7 +9,6 @@ import net.osmand.osm.LatLon;
import net.osmand.plus.FavouritesDbHelper;
import net.osmand.plus.R;
import android.content.Context;
import android.content.DialogInterface.OnClickListener;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
@ -125,12 +124,6 @@ public class FavoritesLayer extends OsmandMapLayer implements ContextMenuLayer.I
}
@Override
public OnClickListener getActionListener(List<String> actionsList, Object o) {
return null;
}
@Override
public String getObjectDescription(Object o) {
if(o instanceof FavouritePoint){

View file

@ -1,5 +1,6 @@
package net.osmand.plus.views;
import net.osmand.plus.ContextMenuAdapter;
import android.graphics.Canvas;
import android.graphics.PointF;
import android.graphics.RectF;
@ -14,6 +15,8 @@ public abstract class OsmandMapLayer {
public abstract void destroyLayer();
public void populateObjectContextMenu(Object o, ContextMenuAdapter adapter) {}
public boolean onSingleTap(PointF point) {
return false;
}

View file

@ -11,18 +11,16 @@ import net.osmand.access.AccessibleToast;
import net.osmand.data.Amenity;
import net.osmand.data.AmenityType;
import net.osmand.osm.LatLon;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.ContextMenuAdapter.OnContextMenuClick;
import net.osmand.plus.PoiFilter;
import net.osmand.plus.R;
import net.osmand.plus.ResourceManager;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.osmedit.OsmEditingPlugin;
import net.osmand.plus.render.RenderingIcons;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@ -298,62 +296,46 @@ public class POIMapLayer extends OsmandMapLayer implements ContextMenuLayer.ICon
public boolean drawInScreenPixels() {
return true;
}
@Override
public OnClickListener getActionListener(List<String> actionsList, Object o) {
final Amenity a = (Amenity) o;
int ind = 0;
final int phoneIndex = a.getPhone() != null ? ind++ : -1;
final int siteIndex = a.getSite() != null ? ind++ : -1;
final int descriptionIndex = a.getDescription() != null ? ind++ : -1;
if(a.getDescription() != null){
actionsList.add(this.view.getResources().getString(R.string.poi_context_menu_showdescription));
}
if(a.getPhone() != null){
actionsList.add(this.view.getResources().getString(R.string.poi_context_menu_call));
}
if(a.getSite() != null){
actionsList.add(this.view.getResources().getString(R.string.poi_context_menu_website));
}
final OsmEditingPlugin editingPlugin = OsmandPlugin.getEnabledPlugin(OsmEditingPlugin.class);
final int modifyInd = editingPlugin != null ? ind++ : -1;
final int deleteInd = editingPlugin != null ? ind++ : -1;
if (editingPlugin != null) {
actionsList.add(this.view.getResources().getString(R.string.poi_context_menu_modify));
actionsList.add(this.view.getResources().getString(R.string.poi_context_menu_delete));
}
return new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
if (which == phoneIndex) {
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("tel:"+a.getPhone())); //$NON-NLS-1$
view.getContext().startActivity(intent);
} catch (RuntimeException e) {
log.error("Failed to invoke call", e); //$NON-NLS-1$
AccessibleToast.makeText(view.getContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
public void populateObjectContextMenu(Object o, ContextMenuAdapter adapter) {
if(o instanceof Amenity) {
final Amenity a = (Amenity) o;
OnContextMenuClick listener = new ContextMenuAdapter.OnContextMenuClick() {
@Override
public void onContextMenuClick(int itemId, int pos, boolean isChecked) {
if (itemId == R.string.poi_context_menu_call) {
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("tel:"+a.getPhone())); //$NON-NLS-1$
view.getContext().startActivity(intent);
} catch (RuntimeException e) {
log.error("Failed to invoke call", e); //$NON-NLS-1$
AccessibleToast.makeText(view.getContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
}
} else if (itemId == R.string.poi_context_menu_website) {
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(a.getSite()));
view.getContext().startActivity(intent);
} catch (RuntimeException e) {
log.error("Failed to invoke call", e); //$NON-NLS-1$
AccessibleToast.makeText(view.getContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
}
} else if (itemId == R.string.poi_context_menu_showdescription) {
showDescriptionDialog(a);
}
} else if (which == siteIndex) {
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(a.getSite()));
view.getContext().startActivity(intent);
} catch (RuntimeException e) {
log.error("Failed to invoke call", e); //$NON-NLS-1$
AccessibleToast.makeText(view.getContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
}
} else if (which == descriptionIndex) {
showDescriptionDialog(a);
} else if (which == modifyInd) {
editingPlugin.getPoiActions().showEditDialog(a);
} else if(which == deleteInd) {
editingPlugin.getPoiActions().showDeleteDialog(a);
} else {
}
};
if(a.getDescription() != null){
adapter.registerItem(R.string.poi_context_menu_showdescription, 0, listener, -1);
}
};
if(a.getPhone() != null){
adapter.registerItem(R.string.poi_context_menu_call, 0, listener, -1);
}
if(a.getSite() != null){
adapter.registerItem(R.string.poi_context_menu_website, 0, listener, -1);
}
}
}
private void showDescriptionDialog(Amenity a) {

View file

@ -9,7 +9,6 @@ import net.osmand.osm.LatLon;
import net.osmand.plus.R;
import net.osmand.plus.TransportIndexRepository;
import android.content.Context;
import android.content.DialogInterface.OnClickListener;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
@ -156,12 +155,6 @@ public class TransportStopsLayer extends OsmandMapLayer implements ContextMenuLa
return false;
}
@Override
public OnClickListener getActionListener(List<String> actionsList, Object o) {
return null;
}
@Override
public String getObjectDescription(Object o) {
if(o instanceof TransportStop){