Add gpx tracks selection

This commit is contained in:
Victor Shcherb 2014-06-05 01:31:50 +02:00
parent d91fc3c508
commit 83619fde7d
14 changed files with 1445 additions and 224 deletions

View file

@ -1,14 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<ExpandableListView
android:id="@android:id/list"
xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/OsmandListView"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginLeft="0dp"
android:layout_marginRight="0dp"
android:layout_marginTop="0dp"
android:layout_weight="1"
android:groupIndicator="@android:color/transparent" >
android:orientation="vertical" >
</ExpandableListView>
<TextView
android:id="@+id/DescriptionText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="3dp"
android:text=""
android:visibility="gone" />
<ExpandableListView
android:id="@android:id/list"
style="@style/OsmandListView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginLeft="0dp"
android:layout_marginRight="0dp"
android:layout_marginTop="0dp"
android:layout_weight="1"
android:groupIndicator="@android:color/transparent" >
</ExpandableListView>
</LinearLayout>

View file

@ -9,6 +9,7 @@
3. All your modified/created strings are in the top of the file (to make easier find what\'s translated).
PLEASE: Have a look at http://code.google.com/p/osmand/wiki/UIConsistency, it may really improve your and our work :-) Thx - Hardy
-->
<string name="gpx_file_is_empty">Gpx track is empty</string>
<string name="selected_track">Track</string>
<string name="my_tracks">All tracks</string>
<string name="my_favorites">My Favorites</string>

View file

@ -261,6 +261,21 @@ public class GPXUtilities {
int endPointInd;
int metricEnd;
public SplitSegment(TrkSegment s) {
startPointInd = 0;
startCoeff = 0;
endPointInd = s.points.size() - 2;
startCoeff = 1;
this.segment = s;
}
public SplitSegment(TrkSegment s, int pointInd, float cf) {
this.segment = s;
this.startPointInd = pointInd;
this.startCoeff = cf;
}
public int getNumberOfPoints() {
return endPointInd - startPointInd + 2;
}
@ -273,7 +288,7 @@ public class GPXUtilities {
}
return approx(segment.points.get(ind), segment.points.get(ind + 1), startCoeff);
}
if(j == getNumberOfPoints()) {
if(j == getNumberOfPoints() - 1) {
if(startCoeff == 1) {
return segment.points.get(ind);
}
@ -311,19 +326,7 @@ public class GPXUtilities {
return vl + ((long) cf * (vl2 - vl));
}
public SplitSegment(TrkSegment s) {
startPointInd = 0;
startCoeff = 0;
endPointInd = s.points.size() - 1;
startCoeff = 1;
}
public SplitSegment(TrkSegment s, int pointInd, float cf) {
this.segment = s;
this.startPointInd = pointInd;
this.startCoeff = cf;
}
public float setLastPoint(int pointInd, float endCf) {
endCoeff = endCf;
endPointInd = pointInd;
@ -406,7 +409,7 @@ public class GPXUtilities {
List<SplitSegment> splitSegments = new ArrayList<GPXUtilities.SplitSegment>();
for(int i = 0; i< tracks.size() ; i++){
Track subtrack = tracks.get(i);
for(int j = 0; j<subtrack.segments.size(); j++){
for (int j = 0; j < subtrack.segments.size(); j++) {
TrkSegment segment = subtrack.segments.get(j);
SplitSegment sp = new SplitSegment(segment, 0, 0);
int total = 0;
@ -415,17 +418,18 @@ public class GPXUtilities {
if (k > 0) {
WptPt prev = segment.points.get(k - 1);
int currentSegment = m.metric(prev, point);
while(total + currentSegment > ml) {
int p = ml - total;
float cf = sp.setLastPoint(k - 1, p / ((float)currentSegment));
while (total + currentSegment > ml) {
int p = ml - total;
float cf = sp.setLastPoint(k - 1, p / ((float) currentSegment));
sp = new SplitSegment(segment, k - 1, cf);
sp.metricEnd = ml;
sp.metricEnd = ml;
ml += metricLimit;
}
total += currentSegment;
}
}
if(segment.points.size() > 0 && !(sp.endPointInd == segment.points.size() -1 && sp.startCoeff == 1)) {
if (segment.points.size() > 0
&& !(sp.endPointInd == segment.points.size() - 1 && sp.startCoeff == 1)) {
sp.metricEnd = total;
sp.setLastPoint(0, 1);
splitSegments.add(sp);

View file

@ -1,6 +1,7 @@
package net.osmand.plus;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.preference.PreferenceScreen;
@ -9,7 +10,6 @@ import net.osmand.Location;
import net.osmand.PlatformUtil;
import net.osmand.access.AccessibilityPlugin;
import net.osmand.plus.activities.LocalIndexInfo;
import net.osmand.plus.activities.LocalIndexesActivity;
import net.osmand.plus.activities.LocalIndexesActivity.LoadLocalIndexTask;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.SettingsActivity;
@ -26,6 +26,8 @@ import net.osmand.plus.srtmplugin.SRTMPlugin;
import net.osmand.plus.views.OsmandMapTileView;
import org.apache.commons.logging.Log;
import com.actionbarsherlock.app.SherlockFragment;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@ -141,11 +143,11 @@ public abstract class OsmandPlugin {
public void updateLocation(Location location) {}
public void contextMenuLocalIndexes(LocalIndexesActivity la, LocalIndexInfo info, ContextMenuAdapter adapter) {};
public void contextMenuLocalIndexes(Activity activity, SherlockFragment fragment, Object info, ContextMenuAdapter adapter) {};
public void updateLocalIndexDescription(LocalIndexInfo info) {}
public void optionsMenuLocalIndexes(LocalIndexesActivity localIndexesActivity, ContextMenuAdapter optionsMenuAdapter) {};
public void optionsMenuLocalIndexes(Activity activity, SherlockFragment fragment, ContextMenuAdapter optionsMenuAdapter) {};
public List<String> indexingFiles(IProgress progress) { return null;}
@ -265,14 +267,16 @@ public abstract class OsmandPlugin {
}
}
public static void onContextMenuLocalIndexes(LocalIndexesActivity la, LocalIndexInfo info, ContextMenuAdapter adapter) {
public static void onContextMenuActivity(Activity activity, SherlockFragment fragment, Object info, ContextMenuAdapter adapter) {
for (OsmandPlugin plugin : activePlugins) {
plugin.contextMenuLocalIndexes(la, info, adapter);
plugin.contextMenuLocalIndexes(activity, fragment, info, adapter);
}
}
public static void onOptionsMenuLocalIndexes(LocalIndexesActivity localIndexesActivity, ContextMenuAdapter optionsMenuAdapter) {
public static void onOptionsMenuActivity(Activity activity, SherlockFragment fragment, ContextMenuAdapter optionsMenuAdapter) {
for (OsmandPlugin plugin : activePlugins) {
plugin.optionsMenuLocalIndexes(localIndexesActivity, optionsMenuAdapter);
plugin.optionsMenuLocalIndexes(activity, fragment, optionsMenuAdapter);
}
}

View file

@ -0,0 +1,900 @@
package net.osmand.plus.activities;
import java.io.File;
import java.text.Collator;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import net.osmand.IndexConstants;
import net.osmand.access.AccessibleToast;
import net.osmand.plus.GPXUtilities;
import net.osmand.plus.ContextMenuAdapter.OnContextMenuClick;
import net.osmand.plus.GPXUtilities.GPXFile;
import net.osmand.plus.GPXUtilities.WptPt;
import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.activities.LocalIndexHelper.LocalIndexType;
import net.osmand.plus.activities.LocalIndexesActivity.LoadLocalIndexDescriptionTask;
import net.osmand.plus.activities.LocalIndexesActivity.LocalIndexOperationTask;
import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.util.Algorithms;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.TypedArray;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.AsyncTask.Status;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ExpandableListView;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;
import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
import android.widget.Toast;
import com.actionbarsherlock.view.ActionMode;
import com.actionbarsherlock.view.ActionMode.Callback;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.view.SubMenu;
import com.actionbarsherlock.widget.SearchView;
import com.actionbarsherlock.widget.SearchView.OnQueryTextListener;
public class AvailableGPXFragment extends OsmandExpandableListFragment {
public static final int SEARCH_ID = -1;
public static final int ACTION_ID = 0;
protected static final int DELETE_ACTION_ID = 1;
private boolean selectionMode = false;
private List<GpxInfo> selectedItems = new ArrayList<GpxInfo>();
private ActionMode actionMode;
private SearchView searchView;
private LoadGpxTask asyncLoader;
private GpxIndexesAdapter listAdapter;
MessageFormat formatMb = new MessageFormat("{0, number,##.#} MB", Locale.US);
private LoadLocalIndexDescriptionTask descriptionLoader;
private ContextMenuAdapter optionsMenuAdapter;
private AsyncTask<GpxInfo, ?, ?> operationTask;
public static class GpxInfo {
public GPXFile gpx;
public File file;
public String subfolder;
private String name = null;
private int sz = -1;
private String description;
private boolean corrupted;
private boolean expanded;
public String getName() {
if(name == null) {
name = formatName(file.getName());
}
return name;
}
private String formatName(String name) {
int ext = name.indexOf('.');
if (ext != -1) {
name = name.substring(0, ext);
}
return name.replace('_', ' ');
}
public boolean isCorrupted() {
return corrupted;
}
public int getSize() {
if(sz == -1) {
sz = (int) (file.length() >> 10);
}
return sz;
}
public boolean isExpanded() {
return expanded;
}
public void setExpanded(boolean expanded) {
this.expanded = expanded;
}
public CharSequence getDescription() {
if(description == null) {
return "";
}
return description;
}
public void updateGpxInfo(OsmandApplication app ) {
if(gpx == null){
gpx = GPXUtilities.loadGPXFile(app, file);
}
if(gpx.warning != null){
corrupted = true;
description = gpx.warning;
} else {
// 'Long-press for options' message
description = GpxUiHelper.getDescription(app, gpx, file) +
app.getString(R.string.local_index_gpx_info_show);
}
}
public String getFileName() {
return file.getName();
}
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
final Collator collator = Collator.getInstance();
collator.setStrength(Collator.SECONDARY);
asyncLoader = new LoadGpxTask();
listAdapter = new GpxIndexesAdapter(getActivity());
setAdapter(listAdapter);
}
public OsmandApplication getMyApplication() {
return (OsmandApplication) getActivity().getApplication();
}
public List<GpxInfo> getSelectedItems() {
return selectedItems;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View vs = super.onCreateView(inflater, container, savedInstanceState);
getExpandableListView().setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
long packedPos = ((ExpandableListContextMenuInfo) menuInfo).packedPosition;
int group = ExpandableListView.getPackedPositionGroup(packedPos);
int child = ExpandableListView.getPackedPositionChild(packedPos);
if (child >= 0 && group >= 0) {
showContextMenu(listAdapter.getChild(group, child));
}
}
});
return vs;
}
@Override
public void onResume() {
super.onResume();
if (asyncLoader == null || asyncLoader.getResult() == null) {
asyncLoader = new LoadGpxTask();
asyncLoader.execute(getActivity());
}
}
@Override
public void onPause() {
super.onPause();
if(operationTask != null){
operationTask.cancel(true);
}
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
MenuItem mi = createMenuItem(menu, SEARCH_ID, R.string.export_fav, R.drawable.ic_action_search_light,
R.drawable.ic_action_search_dark, MenuItem.SHOW_AS_ACTION_ALWAYS
| MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
searchView = new com.actionbarsherlock.widget.SearchView(getActivity());
mi.setActionView(searchView);
searchView.setOnQueryTextListener(new OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
listAdapter.getFilter().filter(query);
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
listAdapter.getFilter().filter(newText);
return true;
}
});
optionsMenuAdapter = new ContextMenuAdapter(getActivity());
OnContextMenuClick listener = new OnContextMenuClick() {
@Override
public void onContextMenuClick(final int itemId, int pos, boolean isChecked, DialogInterface dialog) {
if (itemId == R.string.local_index_mi_reload) {
asyncLoader.execute(getActivity());
} else if (itemId == R.string.local_index_mi_delete) {
openSelectionMode(itemId, R.drawable.ic_action_delete_dark, R.drawable.ic_action_delete_light,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
doAction(itemId);
}
});
}
}
};
optionsMenuAdapter.item(R.string.local_index_mi_delete)
.icons(R.drawable.ic_action_delete_dark, R.drawable.ic_action_delete_light).listen(listener).reg();
optionsMenuAdapter.item(R.string.local_index_mi_reload)
.icons(R.drawable.ic_action_refresh_dark, R.drawable.ic_action_refresh_light).listen(listener).reg();
OsmandPlugin.onOptionsMenuActivity(getSherlockActivity(), this, optionsMenuAdapter);
for (int j = 0; j < optionsMenuAdapter.length(); j++) {
MenuItem item;
item = menu.add(0, optionsMenuAdapter.getItemId(j), j + 1, optionsMenuAdapter.getItemName(j));
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM
);
if (optionsMenuAdapter.getImageId(j, isLightActionBar()) != 0) {
item.setIcon(optionsMenuAdapter.getImageId(j, isLightActionBar()));
}
}
}
public void doAction(int actionResId){
if(actionResId == R.string.local_index_mi_delete){
operationTask = new DeleteGpxTask();
} else {
operationTask = null;
}
if(operationTask != null){
operationTask.execute(selectedItems.toArray(new GpxInfo[selectedItems.size()]));
}
if(actionMode != null) {
actionMode.finish();
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int itemId = item.getItemId();
for (int i = 0; i < optionsMenuAdapter.length(); i++) {
if (itemId == optionsMenuAdapter.getItemId(i)) {
optionsMenuAdapter.getClickAdapter(i).onContextMenuClick(itemId, i, false, null);
return true;
}
}
return super.onOptionsItemSelected(item);
}
public void showProgressBar() {
getSherlockActivity().setSupportProgressBarIndeterminateVisibility(true);
}
public void hideProgressBar() {
getSherlockActivity().setSupportProgressBarIndeterminateVisibility(false);
}
public void openSelectionMode(int stringRes, int darkIcon, int lightIcon, DialogInterface.OnClickListener listener) {
openSelectionMode(stringRes, !isLightActionBar() ? darkIcon : lightIcon, listener);
}
private void openSelectionMode(final int actionResId, final int actionIconId,
final DialogInterface.OnClickListener listener){
String value = getString(actionResId);
if (value.endsWith("...")) {
value = value.substring(0, value.length() - 3);
}
final String actionButton = value;
if(listAdapter.getGroupCount() == 0){
AccessibleToast.makeText(getActivity(), getString(R.string.local_index_no_items_to_do, actionButton.toLowerCase()), Toast.LENGTH_SHORT).show();
return;
}
selectionMode = true;
selectedItems.clear();
actionMode = getSherlockActivity().startActionMode(new Callback() {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
selectionMode = true;
MenuItem it = menu.add(actionResId);
if(actionIconId != 0) {
it.setIcon(actionIconId);
}
it.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM |
MenuItem.SHOW_AS_ACTION_WITH_TEXT);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
if (selectedItems.isEmpty()) {
AccessibleToast.makeText(getActivity(),
getString(R.string.local_index_no_items_to_do, actionButton.toLowerCase()), Toast.LENGTH_SHORT).show();
return true;
}
Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(getString(R.string.local_index_action_do, actionButton.toLowerCase(), selectedItems.size()));
builder.setPositiveButton(actionButton, listener);
builder.setNegativeButton(R.string.default_buttons_cancel, null);
builder.show();
return true;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
selectionMode = false;
getView().findViewById(R.id.DescriptionText).setVisibility(View.GONE);
listAdapter.notifyDataSetChanged();
}
});
if(R.string.local_index_mi_upload_gpx == actionResId){
((TextView) getView().findViewById(R.id.DescriptionText)).setText(R.string.local_index_upload_gpx_description);
((TextView) getView().findViewById(R.id.DescriptionText)).setVisibility(View.VISIBLE);
}
listAdapter.notifyDataSetChanged();
}
private void renameFile(GpxInfo info) {
final File f = info.file;
Builder b = new AlertDialog.Builder(getActivity());
if(f.exists()){
final EditText editText = new EditText(getActivity());
editText.setText(f.getName());
b.setView(editText);
b.setPositiveButton(R.string.default_buttons_save, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String newName = editText.getText().toString();
File dest = new File(f.getParentFile(), newName);
if (dest.exists()) {
AccessibleToast.makeText(getActivity(), R.string.file_with_name_already_exists, Toast.LENGTH_LONG).show();
} else {
if(!f.getParentFile().exists()) {
f.getParentFile().mkdirs();
}
if(f.renameTo(dest)){
if(asyncLoader.getStatus() == Status.PENDING) {
asyncLoader.execute(getActivity());
}
} else {
AccessibleToast.makeText(getActivity(), R.string.file_can_not_be_renamed, Toast.LENGTH_LONG).show();
}
}
}
});
b.setNegativeButton(R.string.default_buttons_cancel, null);
b.show();
}
}
private void basicFileOperation(final GpxInfo info, ContextMenuAdapter adapter) {
OnContextMenuClick listener = new OnContextMenuClick() {
@Override
public void onContextMenuClick(int resId, int pos, boolean isChecked, DialogInterface dialog) {
if (resId == R.string.local_index_mi_rename) {
renameFile(info);
} else if (resId == R.string.local_index_mi_delete) {
Builder confirm = new AlertDialog.Builder(getActivity());
confirm.setPositiveButton(R.string.default_buttons_yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
new DeleteGpxTask().execute(info);
}
});
confirm.setNegativeButton(R.string.default_buttons_no, null);
confirm.setMessage(getString(R.string.delete_confirmation_msg, info.file.getName()));
confirm.show();
} else if (resId == R.string.local_index_mi_export) {
final Uri fileUri = Uri.fromFile(info.file);
final Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri);
sendIntent.setType("application/gpx+xml");
startActivity(sendIntent);
} else if (resId == R.string.show_gpx_route) {
info.updateGpxInfo(getMyApplication());
boolean e = true;
if (info != null && info.gpx != null) {
WptPt loc = info.gpx.findPointToShow();
OsmandSettings settings = getMyApplication().getSettings();
if (loc != null) {
settings.setMapLocationToShow(loc.lat, loc.lon, settings.getLastKnownMapZoom());
e = false;
getMyApplication().setGpxFileToDisplay(info.gpx, false);
MapActivity.launchMapActivityMoveToTop(getActivity());
}
}
if (e) {
AccessibleToast.makeText(getActivity(), R.string.gpx_file_is_empty, Toast.LENGTH_LONG).show();
}
}
}
};
adapter.item(R.string.show_gpx_route).listen(listener).reg();
adapter.item(R.string.local_index_mi_rename).listen(listener).reg();
adapter.item(R.string.local_index_mi_delete).listen(listener).reg();
adapter.item(R.string.local_index_mi_export).listen(listener).reg();
OsmandPlugin.onContextMenuActivity(getSherlockActivity(), this, info, adapter);
}
private void showContextMenu(final GpxInfo info) {
Builder builder = new AlertDialog.Builder(getActivity());
final ContextMenuAdapter adapter = new ContextMenuAdapter(getActivity());
basicFileOperation(info, adapter);
String[] values = adapter.getItemNames();
builder.setItems(values, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
OnContextMenuClick clk = adapter.getClickAdapter(which);
if (clk != null) {
clk.onContextMenuClick(adapter.getItemId(which), which, false, dialog);
}
}
});
builder.show();
}
public class LoadGpxTask extends AsyncTask<Activity, GpxInfo, List<GpxInfo>> {
private List<GpxInfo> result;
@Override
protected List<GpxInfo> doInBackground(Activity... params) {
List<GpxInfo> result = new ArrayList<GpxInfo>();
loadGPXData(getMyApplication().getAppPath(IndexConstants.GPX_INDEX_DIR), result, this);
return result;
}
public void loadFile(GpxInfo... loaded) {
publishProgress(loaded);
}
@Override
protected void onPreExecute() {
getSherlockActivity().setSupportProgressBarIndeterminateVisibility(true);
}
@Override
protected void onProgressUpdate(GpxInfo... values) {
for (GpxInfo v : values) {
listAdapter.addLocalIndexInfo(v);
}
listAdapter.notifyDataSetChanged();
}
public void setResult(List<GpxInfo> result) {
this.result = result;
if(result == null){
listAdapter.clear();
} else {
for (GpxInfo v : result) {
listAdapter.addLocalIndexInfo(v);
}
listAdapter.notifyDataSetChanged();
onPostExecute(result);
}
}
@Override
protected void onPostExecute(List<GpxInfo> result) {
this.result = result;
getSherlockActivity().setSupportProgressBarIndeterminateVisibility(false);
}
private File[] listFilesSorted(File dir){
File[] listFiles = dir.listFiles();
if(listFiles == null) {
return new File[0];
}
Arrays.sort(listFiles);
return listFiles;
}
private void loadGPXData(File mapPath, List<GpxInfo> result, LoadGpxTask loadTask) {
if (mapPath.canRead()) {
List<GpxInfo> progress = new ArrayList<GpxInfo>();
loadGPXFolder(mapPath, result, loadTask, progress, "");
if (!progress.isEmpty()) {
loadTask.loadFile(progress.toArray(new GpxInfo[progress.size()]));
}
}
}
private void loadGPXFolder(File mapPath, List<GpxInfo> result, LoadGpxTask loadTask,
List<GpxInfo> progress, String gpxSubfolder) {
for (File gpxFile : listFilesSorted(mapPath)) {
if (gpxFile.isDirectory()) {
String sub = gpxSubfolder.length() == 0 ? gpxFile.getName() : gpxSubfolder + "/" + gpxFile.getName();
loadGPXFolder(gpxFile, result, loadTask, progress, sub);
} else if (gpxFile.isFile() && gpxFile.getName().endsWith(".gpx")) {
GpxInfo info = new GpxInfo();
info.subfolder = gpxSubfolder;
info.file = gpxFile;
result.add(info);
progress.add(info);
if (progress.size() > 7) {
loadTask.loadFile(progress.toArray(new GpxInfo[progress.size()]));
progress.clear();
}
}
}
}
public List<GpxInfo> getResult() {
return result;
}
}
protected class GpxIndexesAdapter extends OsmandBaseExpandableListAdapter implements Filterable {
Map<String, List<GpxInfo>> data = new LinkedHashMap<String, List<GpxInfo>>();
List<String> category = new ArrayList<String>();
int warningColor;
int okColor;
int defaultColor;
int corruptedColor;
private SearchFilter filter;
public GpxIndexesAdapter(Context ctx) {
warningColor = ctx.getResources().getColor(R.color.color_warning);
okColor = ctx.getResources().getColor(R.color.color_ok);
TypedArray ta = ctx.getTheme().obtainStyledAttributes(new int[]{android.R.attr.textColorPrimary});
defaultColor = ta.getColor(0, ctx.getResources().getColor(R.color.color_unknown));
ta.recycle();
}
public void clear() {
data.clear();
category.clear();
notifyDataSetChanged();
}
public void addLocalIndexInfo(GpxInfo info) {
int found = -1;
// search from end
for (int i = category.size() - 1; i >= 0; i--) {
String cat = category.get(i);
if (Algorithms.objectEquals(info.subfolder, cat)) {
found = i;
break;
}
}
if (found == -1) {
found = category.size();
category.add(info.subfolder);
}
if (!data.containsKey(category.get(found))) {
data.put(category.get(found), new ArrayList<GpxInfo>());
}
data.get(category.get(found)).add(info);
}
@Override
public GpxInfo getChild(int groupPosition, int childPosition) {
String cat = category.get(groupPosition);
return data.get(cat).get(childPosition);
}
@Override
public long getChildId(int groupPosition, int childPosition) {
// it would be unusable to have 10000 local indexes
return groupPosition * 10000 + childPosition;
}
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
View v = convertView;
final GpxInfo child = (GpxInfo) getChild(groupPosition, childPosition);
if (v == null ) {
LayoutInflater inflater = getActivity().getLayoutInflater();
v = inflater.inflate(net.osmand.plus.R.layout.local_index_list_item, parent, false);
}
TextView viewName = ((TextView) v.findViewById(R.id.local_index_name));
viewName.setText(child.getName());
if (child.isCorrupted()) {
viewName.setTextColor(corruptedColor);
viewName.setTypeface(Typeface.DEFAULT, Typeface.NORMAL);
} else {
viewName.setTextColor(defaultColor);
viewName.setTypeface(Typeface.DEFAULT, Typeface.NORMAL);
}
if (child.getSize() >= 0) {
String size;
if (child.getSize() > 100) {
size = formatMb.format(new Object[] { (float) child.getSize() / (1 << 10) });
} else {
size = child.getSize() + " kB";
}
((TextView) v.findViewById(R.id.local_index_size)).setText(size);
} else {
((TextView) v.findViewById(R.id.local_index_size)).setText("");
}
TextView descr = ((TextView) v.findViewById(R.id.local_index_descr));
if (child.isExpanded()) {
descr.setVisibility(View.VISIBLE);
descr.setText(child.getDescription());
} else {
descr.setVisibility(View.GONE);
}
final CheckBox checkbox = (CheckBox) v.findViewById(R.id.check_local_index);
checkbox.setVisibility(selectionMode ? View.VISIBLE : View.GONE);
if (selectionMode) {
checkbox.setChecked(selectedItems.contains(child));
checkbox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(checkbox.isChecked()){
selectedItems.add(child);
} else {
selectedItems.remove(child);
}
}
});
}
return v;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
View v = convertView;
String group = getGroup(groupPosition);
if (v == null) {
LayoutInflater inflater = getActivity().getLayoutInflater();
v = inflater.inflate(net.osmand.plus.R.layout.expandable_list_item_category, parent, false);
}
StringBuilder t = new StringBuilder(getString(R.string.local_indexes_cat_gpx) + " " + group);
adjustIndicator(groupPosition, isExpanded, v);
TextView nameView = ((TextView) v.findViewById(R.id.category_name));
List<GpxInfo> list = data.get(group);
int size = 0;
for (int i = 0; i < list.size(); i++) {
int sz = list.get(i).getSize();
if (sz < 0) {
size = 0;
break;
} else {
size += sz;
}
}
size = size / (1 << 10);
if (size > 0) {
t.append(" [").append(size).append(" MB]");
}
nameView.setText(t.toString());
nameView.setTypeface(Typeface.DEFAULT, Typeface.NORMAL);
return v;
}
@Override
public int getChildrenCount(int groupPosition) {
return data.get(category.get(groupPosition)).size();
}
@Override
public String getGroup(int groupPosition) {
return category.get(groupPosition) ;
}
@Override
public int getGroupCount() {
return category.size();
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
@Override
public Filter getFilter() {
if(filter == null) {
filter = new SearchFilter();
}
return filter;
}
public void delete(GpxInfo g) {
int found = -1;
// search from end
for (int i = category.size() - 1; i >= 0; i--) {
String cat = category.get(i);
if (Algorithms.objectEquals(g.subfolder, cat)) {
found = i;
break;
}
}
if(found != -1) {
data.get(category.get(found)).remove(g);
}
}
}
public class LoadLocalIndexDescriptionTask extends AsyncTask<GpxInfo, GpxInfo, GpxInfo[]> {
@Override
protected GpxInfo[] doInBackground(GpxInfo... params) {
for (GpxInfo i : params) {
i.updateGpxInfo(getMyApplication());
}
return params;
}
@Override
protected void onPreExecute() {
}
@Override
protected void onProgressUpdate(GpxInfo... values) {
listAdapter.notifyDataSetChanged();
}
@Override
protected void onPostExecute(GpxInfo[] result) {
listAdapter.notifyDataSetChanged();
}
}
public class DeleteGpxTask extends AsyncTask<GpxInfo, GpxInfo, String> {
@Override
protected String doInBackground(GpxInfo... params) {
int count = 0;
int total = 0;
for (GpxInfo info : params) {
if (!isCancelled()) {
boolean successfull = false;
successfull = Algorithms.removeAllFiles(info.file);
total++;
if (successfull) {
count++;
publishProgress(info);
}
}
}
return getString(R.string.local_index_items_deleted, count, total);
}
@Override
protected void onProgressUpdate(GpxInfo... values) {
for(GpxInfo g : values) {
listAdapter.delete(g);
}
listAdapter.notifyDataSetChanged();
}
@Override
protected void onPreExecute() {
getSherlockActivity().setProgressBarIndeterminateVisibility(true);
}
@Override
protected void onPostExecute(String result) {
getSherlockActivity().setProgressBarIndeterminateVisibility(false);
AccessibleToast.makeText(getSherlockActivity(), result, Toast.LENGTH_LONG).show();
}
}
private class SearchFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
final List<GpxInfo> raw = asyncLoader.getResult();
if (constraint == null || constraint.length() == 0 || raw == null) {
results.values = raw;
results.count = 1;
} else {
String cs = constraint.toString().toLowerCase();
List<GpxInfo> res = new ArrayList<GpxInfo>();
for(GpxInfo r : raw) {
if(r.getName().toLowerCase().indexOf(cs) == -1) {
res.add(r);
}
}
results.values = res;
results.count = res.size();
}
return results;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results.values != null) {
synchronized (listAdapter) {
listAdapter.clear();
for (GpxInfo i : ((List<GpxInfo>) results.values)) {
listAdapter.addLocalIndexInfo(i);
}
}
listAdapter.notifyDataSetChanged();
if (constraint != null && constraint.length() > 3) {
collapseTrees(10);
}
}
}
}
@Override
public void onDestroy() {
super.onDestroy();
if(descriptionLoader != null) {
descriptionLoader.cancel(true);
}
if(asyncLoader != null) {
asyncLoader.cancel(true);
}
}
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
GpxInfo item = listAdapter.getChild(groupPosition, childPosition);
item.setExpanded(!item.isExpanded());
if (item.isExpanded()) {
descriptionLoader = new LoadLocalIndexDescriptionTask();
descriptionLoader.execute(item);
}
if(selectionMode){
selectedItems.add(item);
}
listAdapter.notifyDataSetInvalidated();
return true;
}
}

View file

@ -9,6 +9,7 @@ import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
@ -38,7 +39,7 @@ public class FavouritesActivity extends SherlockFragmentActivity {
//This has to be called before setContentView and you must use the
//class in com.actionbarsherlock.view and NOT android.view
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
// getSherlock().setUiOptions(ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW);
getSherlock().setUiOptions(ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW);
super.onCreate(icicle);
@ -54,9 +55,9 @@ public class FavouritesActivity extends SherlockFragmentActivity {
mTabsAdapter.addTab(tabHost.newTabSpec(FAVOURITES_INFO).setIndicator(getString(R.string.my_favorites)),
FavouritesTreeFragment.class, null);
mTabsAdapter.addTab(tabHost.newTabSpec(TRACKS).setIndicator(getString(R.string.my_tracks)),
FavouritesTreeFragment.class, null);
AvailableGPXFragment.class, null);
mTabsAdapter.addTab(tabHost.newTabSpec(SELECTED_TRACK).setIndicator(getString(R.string.selected_track)),
FavouritesTreeFragment.class, null);
SelectedGPXFragment.class, null);
tabHost.setCurrentTab(tab);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);

View file

@ -34,6 +34,7 @@ import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Resources;
import android.os.AsyncTask;
import android.text.Spannable;
@ -782,30 +783,10 @@ public class FavouritesTreeFragment extends OsmandExpandableListFragment {
}
favouritesAdapter.notifyDataSetChanged();
if(constraint != null && constraint.length() > 1) {
collapseTrees();
collapseTrees(5);
}
}
}
public void collapseTrees() {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
synchronized (favouritesAdapter) {
final ExpandableListView expandableListView = getExpandableListView();
for (int i = 0; i < favouritesAdapter.getGroupCount(); i++) {
int cp = favouritesAdapter.getChildrenCount(i);
if (cp < 5) {
expandableListView.expandGroup(i);
} else {
expandableListView.collapseGroup(i);
}
}
}
}
});
}
}

View file

@ -132,7 +132,6 @@ public class LocalIndexHelper {
loadSrtmData(app.getAppPath(IndexConstants.SRTM_INDEX_DIR), result, loadTask);
loadVoiceData(app.getAppPath(IndexConstants.VOICE_INDEX_DIR), result, false, loadTask);
loadVoiceData(app.getAppPath(IndexConstants.TTSVOICE_INDEX_EXT_ZIP), result, true, loadTask);
loadGPXData(app.getAppPath(IndexConstants.GPX_INDEX_DIR), result, false, loadTask);
OsmandPlugin.onLoadLocalIndexes(result, loadTask);
return result;
@ -180,6 +179,15 @@ public class LocalIndexHelper {
}
}
}
private File[] listFilesSorted(File dir){
File[] listFiles = dir.listFiles();
if(listFiles == null) {
return new File[0];
}
Arrays.sort(listFiles);
return listFiles;
}
private void loadSrtmData(File mapPath, List<LocalIndexInfo> result, LoadLocalIndexTask loadTask) {
@ -210,48 +218,8 @@ public class LocalIndexHelper {
}
}
private void loadGPXData(File mapPath, List<LocalIndexInfo> result, boolean backup, LoadLocalIndexTask loadTask) {
if (mapPath.canRead()) {
List<LocalIndexInfo> progress = new ArrayList<LocalIndexInfo>();
loadGPXFolder(mapPath, result, backup, loadTask, progress, null);
if (!progress.isEmpty()) {
loadTask.loadFile(progress.toArray(new LocalIndexInfo[progress.size()]));
}
}
}
private void loadGPXFolder(File mapPath, List<LocalIndexInfo> result, boolean backup, LoadLocalIndexTask loadTask,
List<LocalIndexInfo> progress, String gpxSubfolder) {
for (File gpxFile : listFilesSorted(mapPath)) {
if (gpxFile.isDirectory()) {
String sub = gpxSubfolder == null ? gpxFile.getName() : gpxSubfolder + "/" + gpxFile.getName();
loadGPXFolder(gpxFile, result, backup, loadTask, progress, sub);
} else if (gpxFile.isFile() && gpxFile.getName().endsWith(".gpx")) {
LocalIndexInfo info = new LocalIndexInfo(LocalIndexType.GPX_DATA, gpxFile, backup);
info.setSubfolder(gpxSubfolder);
result.add(info);
progress.add(info);
if (progress.size() > 7) {
loadTask.loadFile(progress.toArray(new LocalIndexInfo[progress.size()]));
progress.clear();
}
}
}
}
private File[] listFilesSorted(File dir){
File[] listFiles = dir.listFiles();
if(listFiles == null) {
return new File[0];
}
Arrays.sort(listFiles);
return listFiles;
}
private MessageFormat format = new MessageFormat("\t {0}, {1} NE \n\t {2}, {3} NE", Locale.US);

View file

@ -10,17 +10,13 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
import android.net.Uri;
import net.osmand.IProgress;
import net.osmand.IndexConstants;
import net.osmand.access.AccessibleToast;
import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.ContextMenuAdapter.OnContextMenuClick;
import net.osmand.plus.GPXUtilities.WptPt;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.activities.EnumAdapter.IEnumWithResource;
import net.osmand.plus.activities.LocalIndexHelper.LocalIndexType;
import net.osmand.util.Algorithms;
import android.app.Activity;
@ -67,7 +63,6 @@ public class LocalIndexesActivity extends OsmandExpandableListActivity {
private boolean selectionMode = false;
private Set<LocalIndexInfo> selectedItems = new LinkedHashSet<LocalIndexInfo>();
private OsmandSettings settings;
protected static int DELETE_OPERATION = 1;
protected static int BACKUP_OPERATION = 2;
@ -89,7 +84,6 @@ public class LocalIndexesActivity extends OsmandExpandableListActivity {
// getSupportActionBar().setLogo(R.drawable.tab_download_screen_icon);
settings = getMyApplication().getSettings();
descriptionLoader = new LoadLocalIndexDescriptionTask();
listAdapter = new LocalIndexesAdapter(this);
@ -133,13 +127,8 @@ public class LocalIndexesActivity extends OsmandExpandableListActivity {
private void showContextMenu(final LocalIndexInfo info) {
Builder builder = new AlertDialog.Builder(this);
final ContextMenuAdapter adapter = new ContextMenuAdapter(this);
if (info.getType() == LocalIndexType.GPX_DATA) {
showGPXRouteAction(info, adapter);
descriptionLoader = new LoadLocalIndexDescriptionTask();
descriptionLoader.execute(info);
}
basicFileOperation(info, adapter);
OsmandPlugin.onContextMenuLocalIndexes(this, info, adapter);
OsmandPlugin.onContextMenuActivity(this, null, info, adapter);
String[] values = adapter.getItemNames();
builder.setItems(values, new DialogInterface.OnClickListener() {
@ -155,22 +144,6 @@ public class LocalIndexesActivity extends OsmandExpandableListActivity {
builder.show();
}
private void showGPXRouteAction(final LocalIndexInfo info, ContextMenuAdapter adapter) {
adapter.item(R.string.show_gpx_route).listen(new OnContextMenuClick() {
@Override
public void onContextMenuClick(int itemId, int pos, boolean isChecked, DialogInterface dialog) {
if (info != null && info.getGpxFile() != null) {
WptPt loc = info.getGpxFile().findPointToShow();
if (loc != null) {
settings.setMapLocationToShow(loc.lat, loc.lon, settings.getLastKnownMapZoom());
}
getMyApplication().setGpxFileToDisplay(info.getGpxFile(), false);
MapActivity.launchMapActivityMoveToTop(LocalIndexesActivity.this);
}
}
}).reg();
}
private void basicFileOperation(final LocalIndexInfo info, ContextMenuAdapter adapter) {
OnContextMenuClick listener = new OnContextMenuClick() {
@ -193,12 +166,6 @@ public class LocalIndexesActivity extends OsmandExpandableListActivity {
confirm.show();
} else if (resId == R.string.local_index_mi_backup) {
new LocalIndexOperationTask(BACKUP_OPERATION).execute(info);
} else if (resId == R.string.local_index_mi_export) {
final Uri fileUri = Uri.fromFile(new File(info.getPathToData()));
final Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri);
sendIntent.setType("application/gpx+xml");
startActivity(sendIntent);
}
}
};
@ -212,9 +179,6 @@ public class LocalIndexesActivity extends OsmandExpandableListActivity {
}
adapter.item(R.string.local_index_mi_rename).listen(listener).position(3).reg();
adapter.item(R.string.local_index_mi_delete).listen(listener).position(4).reg();
if (info.getType() == LocalIndexType.GPX_DATA) {
adapter.item(R.string.local_index_mi_export).listen(listener).position(5).reg();
}
}
private void renameFile(LocalIndexInfo info) {
@ -305,9 +269,7 @@ public class LocalIndexesActivity extends OsmandExpandableListActivity {
private File getFileToRestore(LocalIndexInfo i){
if(i.isBackupedData()){
File parent = new File(i.getPathToData()).getParentFile();
if(i.getType() == LocalIndexType.GPX_DATA){
parent = getMyApplication().getAppPath(IndexConstants.GPX_INDEX_DIR);
} else if(i.getType() == LocalIndexType.SRTM_DATA){
if(i.getType() == LocalIndexType.SRTM_DATA){
parent = getMyApplication().getAppPath(IndexConstants.SRTM_INDEX_DIR);
} else if(i.getType() == LocalIndexType.MAP_DATA){
parent = getMyApplication().getAppPath(IndexConstants.MAPS_PATH);
@ -413,25 +375,6 @@ public class LocalIndexesActivity extends OsmandExpandableListActivity {
}
}
public enum UploadVisibility implements IEnumWithResource {
Public(R.string.gpxup_public),
Identifiable(R.string.gpxup_identifiable),
Trackable(R.string.gpxup_trackable),
Private(R.string.gpxup_private);
private final int resourceId;
private UploadVisibility(int resourceId) {
this.resourceId = resourceId;
}
public String asURLparam() {
return name().toLowerCase();
}
@Override
public int stringResource() {
return resourceId;
}
}
public class LoadLocalIndexDescriptionTask extends AsyncTask<LocalIndexInfo, LocalIndexInfo, LocalIndexInfo[]> {
@ -530,7 +473,7 @@ public class LocalIndexesActivity extends OsmandExpandableListActivity {
optionsMenuAdapter.item(R.string.local_index_mi_delete)
.icons(R.drawable.ic_action_delete_dark, R.drawable.ic_action_delete_light)
.listen(listener).position(4).reg();
OsmandPlugin.onOptionsMenuLocalIndexes(this, optionsMenuAdapter);
OsmandPlugin.onOptionsMenuActivity(this, null, optionsMenuAdapter);
// doesn't work correctly
int max = getResources().getInteger(R.integer.abs__max_action_buttons);
SubMenu split = null;
@ -579,6 +522,7 @@ public class LocalIndexesActivity extends OsmandExpandableListActivity {
}
return super.onOptionsItemSelected(item);
}
public void doAction(int actionResId){
if(actionResId == R.string.local_index_mi_backup){
operationTask = new LocalIndexOperationTask(BACKUP_OPERATION);
@ -668,10 +612,6 @@ public class LocalIndexesActivity extends OsmandExpandableListActivity {
});
findViewById(R.id.DescriptionText).setVisibility(View.GONE);
if(R.string.local_index_mi_upload_gpx == actionResId){
((TextView) findViewById(R.id.DescriptionText)).setText(R.string.local_index_upload_gpx_description);
((TextView) findViewById(R.id.DescriptionText)).setVisibility(View.VISIBLE);
}
listAdapter.notifyDataSetChanged();
}

View file

@ -89,4 +89,25 @@ public abstract class OsmandExpandableListFragment extends SherlockFragment impl
public boolean isLightActionBar() {
return ((OsmandApplication) getActivity().getApplication()).getSettings().isLightActionBar();
}
public void collapseTrees(final int count) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
synchronized (adapter) {
final ExpandableListView expandableListView = getExpandableListView();
for (int i = 0; i < adapter.getGroupCount(); i++) {
int cp = adapter.getChildrenCount(i);
if (cp < count) {
expandableListView.expandGroup(i);
} else {
expandableListView.collapseGroup(i);
}
}
}
}
});
}
}

View file

@ -0,0 +1,340 @@
package net.osmand.plus.activities;
import java.text.Collator;
import net.osmand.plus.R;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ExpandableListView;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;
import com.actionbarsherlock.view.ActionMode;
import com.actionbarsherlock.view.ActionMode.Callback;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.widget.SearchView;
import com.actionbarsherlock.widget.SearchView.OnQueryTextListener;
public class SelectedGPXFragment extends OsmandExpandableListFragment {
public static final int SEARCH_ID = -1;
public static final int ACTION_ID = 0;
protected static final int DELETE_ACTION_ID = 1;
private boolean selectionMode = false;
private ActionMode actionMode;
private SearchView searchView;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
final Collator collator = Collator.getInstance();
collator.setStrength(Collator.SECONDARY);
}
@Override
public void onResume() {
super.onResume();
}
@Override
public boolean onOptionsItemSelected(com.actionbarsherlock.view.MenuItem item) {
if (item.getItemId() == ACTION_ID) {
return true;
} else {
return super.onOptionsItemSelected(item);
}
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
MenuItem mi = createMenuItem(menu, SEARCH_ID, R.string.export_fav, R.drawable.ic_action_search_light,
R.drawable.ic_action_search_dark, MenuItem.SHOW_AS_ACTION_ALWAYS
| MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
searchView = new com.actionbarsherlock.widget.SearchView(getActivity());
mi.setActionView(searchView);
searchView.setOnQueryTextListener(new OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
return true;
}
});
createMenuItem(menu, ACTION_ID, R.string.export_fav, R.drawable.ic_action_gsave_light,
R.drawable.ic_action_gsave_dark, MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
public void showProgressBar() {
getSherlockActivity().setSupportProgressBarIndeterminateVisibility(true);
}
public void hideProgressBar() {
getSherlockActivity().setSupportProgressBarIndeterminateVisibility(false);
}
private void enterDeleteMode() {
actionMode = getSherlockActivity().startActionMode(new Callback() {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
selectionMode = true;
createMenuItem(menu, DELETE_ACTION_ID, R.string.default_buttons_delete,
R.drawable.ic_action_delete_light, R.drawable.ic_action_delete_dark,
MenuItem.SHOW_AS_ACTION_IF_ROOM);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
selectionMode = false;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
if (item.getItemId() == DELETE_ACTION_ID) {
// TODO delete
}
return true;
}
});
}
class SelectedGPXAdapter extends OsmandBaseExpandableListAdapter implements Filterable {
Filter myFilter;
@Override
public Object getChild(int groupPosition, int childPosition) {
return null;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return groupPosition * 10000 + childPosition;
}
@Override
public int getChildrenCount(int groupPosition) {
return 0;
}
@Override
public String getGroup(int groupPosition) {
return "";
}
@Override
public int getGroupCount() {
return 0;
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
View row = convertView;
if (row == null) {
LayoutInflater inflater = getActivity().getLayoutInflater();
row = inflater.inflate(R.layout.expandable_list_item_category, parent, false);
fixBackgroundRepeat(row);
}
adjustIndicator(groupPosition, isExpanded, row);
TextView label = (TextView) row.findViewById(R.id.category_name);
final CheckBox ch = (CheckBox) row.findViewById(R.id.check_item);
// final String model = getGroup(groupPosition);
// label.setText(model);
//
// if (selectionMode) {
// ch.setVisibility(View.VISIBLE);
// ch.setChecked(groupsToDelete.contains(model));
//
// ch.setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View v) {
// if (ch.isChecked()) {
// groupsToDelete.add(model);
// List<FavouritePoint> fvs = helper.getFavoriteGroups().get(model);
// if (fvs != null) {
// favoritesToDelete.addAll(fvs);
// }
// favouritesAdapter.notifyDataSetInvalidated();
// } else {
// groupsToDelete.remove(model);
// }
// }
// });
// } else {
// ch.setVisibility(View.GONE);
// }
return row;
}
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView,
ViewGroup parent) {
View row = convertView;
if (row == null) {
LayoutInflater inflater = getActivity().getLayoutInflater();
row = inflater.inflate(R.layout.favourites_list_item, parent, false);
}
// TextView label = (TextView) row.findViewById(R.id.favourite_label);
// ImageView icon = (ImageView) row.findViewById(R.id.favourite_icon);
// final FavouritePoint model = (FavouritePoint) getChild(groupPosition, childPosition);
// row.setTag(model);
// if (model.isStored()) {
// icon.setImageResource(R.drawable.list_favorite);
// } else {
// icon.setImageResource(R.drawable.opened_poi);
// }
// LatLon lastKnownMapLocation = getMyApplication().getSettings().getLastKnownMapLocation();
// int dist = (int) (MapUtils.getDistance(model.getLatitude(), model.getLongitude(),
// lastKnownMapLocation.getLatitude(), lastKnownMapLocation.getLongitude()));
// String distance = OsmAndFormatter.getFormattedDistance(dist, getMyApplication()) + " ";
// label.setText(distance + model.getName(), TextView.BufferType.SPANNABLE);
// ((Spannable) label.getText()).setSpan(
// new ForegroundColorSpan(getResources().getColor(R.color.color_distance)), 0, distance.length() - 1,
// 0);
// final CheckBox ch = (CheckBox) row.findViewById(R.id.check_item);
// if (selectionMode && model.isStored()) {
// ch.setVisibility(View.VISIBLE);
// ch.setChecked(favoritesToDelete.contains(model));
// row.findViewById(R.id.favourite_icon).setVisibility(View.GONE);
// ch.setOnClickListener(new View.OnClickListener() {
//
// @Override
// public void onClick(View v) {
// if (ch.isChecked()) {
// favoritesToDelete.add(model);
// } else {
// favoritesToDelete.remove(model);
// if (groupsToDelete.contains(model.getCategory())) {
// groupsToDelete.remove(model.getCategory());
// favouritesAdapter.notifyDataSetInvalidated();
// }
// }
// }
// });
// } else {
// row.findViewById(R.id.favourite_icon).setVisibility(View.VISIBLE);
// ch.setVisibility(View.GONE);
// }
return row;
}
@Override
public Filter getFilter() {
if (myFilter == null) {
myFilter = new SearchFilter();
}
return myFilter;
}
}
private class SearchFilter extends Filter {
public SearchFilter() {
}
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
// if (constraint == null || constraint.length() == 0) {
// results.values = helper.getFavoriteGroups();
// results.count = 1;
// } else {
// TreeMap<String, List<FavouritePoint>> filter = new TreeMap<String, List<FavouritePoint>>(helper.getFavoriteGroups());
// TreeMap<String, List<FavouritePoint>> filterLists = new TreeMap<String, List<FavouritePoint>>();
// String cs = constraint.toString().toLowerCase();
// Iterator<Entry<String, List<FavouritePoint>>> ti = filter.entrySet().iterator();
// while(ti.hasNext()) {
// Entry<String, List<FavouritePoint>> next = ti.next();
// if(next.getKey().toLowerCase().indexOf(cs) == -1) {
// ti.remove();
// filterLists.put(next.getKey(), next.getValue());
// }
// }
// ti = filterLists.entrySet().iterator();
// while(ti.hasNext()) {
// Entry<String, List<FavouritePoint>> next = ti.next();
// final List<FavouritePoint> list = next.getValue();
// LinkedList<FavouritePoint> ll = new LinkedList<FavouritePoint>();
// for(FavouritePoint l : list) {
// if(l.getName().toLowerCase().indexOf(cs) != -1) {
// ll.add(l);
// }
//
// }
// if(ll.size() > 0) {
// filter.put(next.getKey(), ll);
// }
// }
// results.values = filter;
// results.count = filter.size();
// }
return results;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
// synchronized (adapter) {
// favouritesAdapter.setFavoriteGroups((Map<String, List<FavouritePoint>>) results.values);
// }
// favouritesAdapter.notifyDataSetChanged();
// if(constraint != null && constraint.length() > 1) {
// collapseTrees();
// }
}
}
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
return false;
}
}

View file

@ -50,6 +50,7 @@ import net.osmand.util.MapUtils;
import org.apache.commons.logging.Log;
import android.app.Activity;
import android.app.Dialog;
import android.content.ComponentName;
import android.content.Context;
@ -86,6 +87,8 @@ import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.Toast;
import com.actionbarsherlock.app.SherlockFragment;
public class AudioVideoNotesPlugin extends OsmandPlugin {
public static final String ID = "osmand.audionotes";
@ -1071,32 +1074,42 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
}
@Override
public void contextMenuLocalIndexes(final LocalIndexesActivity la, LocalIndexInfo info, ContextMenuAdapter adapter) {
if (info.getType() == LocalIndexType.AV_DATA) {
final RecordingLocalIndexInfo ri = (RecordingLocalIndexInfo) info;
OnContextMenuClick listener = new OnContextMenuClick() {
@Override
public void onContextMenuClick(int itemId, int pos, boolean isChecked, DialogInterface dialog) {
playRecording(la, ri.rec);
public void contextMenuLocalIndexes(Activity activity, SherlockFragment fragment, Object obj,
ContextMenuAdapter adapter) {
if (activity instanceof LocalIndexesActivity) {
final LocalIndexesActivity la = (LocalIndexesActivity) activity;
LocalIndexInfo info = (LocalIndexInfo) obj;
if (info.getType() == LocalIndexType.AV_DATA) {
final RecordingLocalIndexInfo ri = (RecordingLocalIndexInfo) info;
OnContextMenuClick listener = new OnContextMenuClick() {
@Override
public void onContextMenuClick(int itemId, int pos, boolean isChecked, DialogInterface dialog) {
playRecording(la, ri.rec);
}
};
if (ri.rec.isPhoto()) {
adapter.item(R.string.recording_context_menu_show)
.icons(R.drawable.ic_action_eye_dark, R.drawable.ic_action_eye_light).listen(listener)
.reg();
} else {
adapter.item(R.string.recording_context_menu_play)
.icons(R.drawable.ic_action_play_dark, R.drawable.ic_action_play_light).listen(listener)
.reg();
}
};
if (ri.rec.isPhoto()) {
adapter.item(R.string.recording_context_menu_show).icons(R.drawable.ic_action_eye_dark, R.drawable.ic_action_eye_light)
.listen(listener).reg();
} else {
adapter.item(R.string.recording_context_menu_play).icons(R.drawable.ic_action_play_dark, R.drawable.ic_action_play_light)
.listen(listener).reg();
}
adapter.item(R.string.show_location).icons(R.drawable.ic_action_marker_dark, R.drawable.ic_action_marker_light)
.listen(new OnContextMenuClick() {
@Override
public void onContextMenuClick(int itemId, int pos, boolean isChecked, DialogInterface dialog) {
SHOW_RECORDINGS.set(true);
app.getSettings().setMapLocationToShow(ri.rec.lat, ri.rec.lon, app.getSettings().getLastKnownMapZoom());
MapActivity.launchMapActivityMoveToTop(la);
adapter.item(R.string.show_location)
.icons(R.drawable.ic_action_marker_dark, R.drawable.ic_action_marker_light)
.listen(new OnContextMenuClick() {
@Override
public void onContextMenuClick(int itemId, int pos, boolean isChecked,
DialogInterface dialog) {
SHOW_RECORDINGS.set(true);
app.getSettings().setMapLocationToShow(ri.rec.lat, ri.rec.lon,
app.getSettings().getLastKnownMapZoom());
MapActivity.launchMapActivityMoveToTop(la);
}
}).reg();
}
}).reg();
}
}
}

View file

@ -1,5 +1,7 @@
package net.osmand.plus.osmedit;
import java.util.List;
import net.osmand.access.AccessibleToast;
import net.osmand.data.Amenity;
import net.osmand.plus.ContextMenuAdapter;
@ -8,15 +10,15 @@ import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.activities.AvailableGPXFragment;
import net.osmand.plus.activities.AvailableGPXFragment.GpxInfo;
import net.osmand.plus.activities.EnumAdapter;
import net.osmand.plus.activities.LocalIndexHelper.LocalIndexType;
import net.osmand.plus.activities.LocalIndexInfo;
import net.osmand.plus.activities.LocalIndexesActivity;
import net.osmand.plus.activities.LocalIndexesActivity.UploadVisibility;
import net.osmand.plus.activities.EnumAdapter.IEnumWithResource;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.SettingsActivity;
import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.util.Algorithms;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
@ -32,6 +34,9 @@ import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;
import com.actionbarsherlock.app.SherlockActivity;
import com.actionbarsherlock.app.SherlockFragment;
public class OsmEditingPlugin extends OsmandPlugin {
private static final String ID = "osm.editing";
private OsmandSettings settings;
@ -167,38 +172,64 @@ public class OsmEditingPlugin extends OsmandPlugin {
}
@Override
public void contextMenuLocalIndexes(final LocalIndexesActivity la, final LocalIndexInfo info, ContextMenuAdapter adapter) {
if (info.getType() == LocalIndexType.GPX_DATA) {
adapter.item(R.string.local_index_mi_upload_gpx).icons(R.drawable.ic_action_gup_dark, R.drawable.ic_action_gup_light)
public void contextMenuLocalIndexes(final Activity la, final SherlockFragment fragment, final Object info, ContextMenuAdapter adapter) {
if (fragment instanceof AvailableGPXFragment) {
adapter.item(R.string.local_index_mi_upload_gpx)
.icons(R.drawable.ic_action_gup_dark, R.drawable.ic_action_gup_light)
.listen(new OnContextMenuClick() {
@Override
public void onContextMenuClick(int itemId, int pos, boolean isChecked, DialogInterface dialog) {
sendGPXFiles(la, info);
sendGPXFiles(la, (AvailableGPXFragment) fragment, (GpxInfo) info);
}
}).reg();
}
}
@Override
public void optionsMenuLocalIndexes(final LocalIndexesActivity la, ContextMenuAdapter optionsMenuAdapter) {
optionsMenuAdapter.item(R.string.local_index_mi_upload_gpx)
.icons(R.drawable.ic_action_gup_dark, R.drawable.ic_action_gup_light).listen(new OnContextMenuClick() {
public void optionsMenuLocalIndexes(final Activity activity, final SherlockFragment fragment, ContextMenuAdapter optionsMenuAdapter) {
if (fragment instanceof AvailableGPXFragment) {
final AvailableGPXFragment f = ((AvailableGPXFragment) fragment);
optionsMenuAdapter.item(R.string.local_index_mi_upload_gpx)
.icons(R.drawable.ic_action_gup_dark, R.drawable.ic_action_gup_light)
.listen(new OnContextMenuClick() {
@Override
public void onContextMenuClick(int itemId, int pos, boolean isChecked, DialogInterface dialog) {
la.openSelectionMode(R.string.local_index_mi_upload_gpx, R.drawable.ic_action_gup_dark,
R.drawable.ic_action_gup_light, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
sendGPXFiles(la, la.getSelectedItems().toArray(new LocalIndexInfo[la.getSelectedItems().size()]));
}
}, null, LocalIndexType.GPX_DATA);
}
}).position(5).reg();
@Override
public void onContextMenuClick(int itemId, int pos, boolean isChecked, DialogInterface dialog) {
f.openSelectionMode(R.string.local_index_mi_upload_gpx, R.drawable.ic_action_gup_dark,
R.drawable.ic_action_gup_light, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
List<GpxInfo> selectedItems = f.getSelectedItems();
sendGPXFiles(activity, f,
selectedItems.toArray(new GpxInfo[selectedItems.size()]));
}
});
}
}).position(5).reg();
}
}
public boolean sendGPXFiles(final LocalIndexesActivity la, final LocalIndexInfo... info){
public enum UploadVisibility implements IEnumWithResource {
Public(R.string.gpxup_public),
Identifiable(R.string.gpxup_identifiable),
Trackable(R.string.gpxup_trackable),
Private(R.string.gpxup_private);
private final int resourceId;
private UploadVisibility(int resourceId) {
this.resourceId = resourceId;
}
public String asURLparam() {
return name().toLowerCase();
}
@Override
public int stringResource() {
return resourceId;
}
}
public boolean sendGPXFiles(final Activity la, AvailableGPXFragment f, final GpxInfo... info){
String name = settings.USER_NAME.get();
String pwd = settings.USER_PASSWORD.get();
if(Algorithms.isEmpty(name) || Algorithms.isEmpty(pwd)){
@ -226,7 +257,7 @@ public class OsmEditingPlugin extends OsmandPlugin {
@Override
public void onClick(DialogInterface dialog, int which) {
new UploadGPXFilesTask(la, descr.getText().toString(), tags.getText().toString(),
new UploadGPXFilesTask((SherlockActivity) la, descr.getText().toString(), tags.getText().toString(),
(UploadVisibility) visibility.getItemAtPosition(visibility.getSelectedItemPosition())
).execute(info);
}

View file

@ -4,20 +4,21 @@ import java.io.File;
import net.osmand.access.AccessibleToast;
import net.osmand.plus.R;
import net.osmand.plus.activities.LocalIndexInfo;
import net.osmand.plus.activities.LocalIndexesActivity;
import net.osmand.plus.activities.LocalIndexesActivity.UploadVisibility;
import net.osmand.plus.activities.AvailableGPXFragment.GpxInfo;
import net.osmand.plus.osmedit.OsmEditingPlugin.UploadVisibility;
import android.os.AsyncTask;
import android.widget.Toast;
public class UploadGPXFilesTask extends AsyncTask<LocalIndexInfo, String, String> {
import com.actionbarsherlock.app.SherlockActivity;
public class UploadGPXFilesTask extends AsyncTask<GpxInfo, String, String> {
private final String visibility;
private final String description;
private final String tagstring;
private LocalIndexesActivity la;
private SherlockActivity la;
public UploadGPXFilesTask(LocalIndexesActivity la,
public UploadGPXFilesTask(SherlockActivity la,
String description, String tagstring, UploadVisibility visibility) {
this.la = la;
this.description = description;
@ -27,13 +28,13 @@ public class UploadGPXFilesTask extends AsyncTask<LocalIndexInfo, String, String
}
@Override
protected String doInBackground(LocalIndexInfo... params) {
protected String doInBackground(GpxInfo... params) {
int count = 0;
int total = 0;
for (LocalIndexInfo info : params) {
for (GpxInfo info : params) {
if (!isCancelled()) {
String warning = null;
File file = new File(info.getPathToData());
File file = info.file;
warning = new OpenstreetmapRemoteUtil(la, null).uploadGPXFile(tagstring, description, visibility,
file);
total++;