diff --git a/MyTracks/res/drawable-hdpi/ic_menu_merge.png b/MyTracks/res/drawable-hdpi/ic_menu_merge.png new file mode 100644 index 000000000..c79743a70 Binary files /dev/null and b/MyTracks/res/drawable-hdpi/ic_menu_merge.png differ diff --git a/MyTracks/res/drawable-mdpi/ic_menu_merge.png b/MyTracks/res/drawable-mdpi/ic_menu_merge.png new file mode 100644 index 000000000..72522d205 Binary files /dev/null and b/MyTracks/res/drawable-mdpi/ic_menu_merge.png differ diff --git a/MyTracks/res/drawable-xhdpi/ic_menu_merge.png b/MyTracks/res/drawable-xhdpi/ic_menu_merge.png new file mode 100644 index 000000000..3d7979b21 Binary files /dev/null and b/MyTracks/res/drawable-xhdpi/ic_menu_merge.png differ diff --git a/MyTracks/res/menu/map.xml b/MyTracks/res/menu/map.xml index a9e39fadf..1d6e34430 100644 --- a/MyTracks/res/menu/map.xml +++ b/MyTracks/res/menu/map.xml @@ -17,7 +17,7 @@ limitations under the License. diff --git a/MyTracks/res/menu/track_detail.xml b/MyTracks/res/menu/track_detail.xml index 702160288..8b29cce1f 100644 --- a/MyTracks/res/menu/track_detail.xml +++ b/MyTracks/res/menu/track_detail.xml @@ -44,50 +44,55 @@ limitations under the License. android:id="@+id/track_detail_markers" android:orderInCategory="5" android:title="@string/menu_markers"/> - + + \ No newline at end of file diff --git a/MyTracks/res/menu/track_list.xml b/MyTracks/res/menu/track_list.xml index b3f3938ce..ae1a3ab1c 100644 --- a/MyTracks/res/menu/track_list.xml +++ b/MyTracks/res/menu/track_list.xml @@ -26,6 +26,10 @@ limitations under the License. android:id="@+id/track_list_start_gps" android:showAsAction="ifRoom" android:title="@string/menu_start_gps"/> + Markers + + Merge & play + onCreateLoader(int arg0, Bundle arg1) { return new CursorLoader(TrackListActivity.this, TracksColumns.CONTENT_URI, PROJECTION, null, - null, - "IFNULL(" + TracksColumns.SHAREDWITHME + ",0) ASC, " + TracksColumns.STARTTIME + " DESC"); + null, TrackUtils.TRACK_SORT_ORDER); } @Override @@ -531,6 +532,10 @@ public class TrackListActivity extends AbstractSendToGoogleActivity } myTracksLocationManager.close(); return true; + case R.id.track_list_merge: + MergeDialogFragment.newInstance(-1L) + .show(getSupportFragmentManager(), MergeDialogFragment.MERGE_DIALOG_TAG); + return true; case R.id.track_list_refresh: if (driveSync) { SyncUtils.syncNow(this); diff --git a/MyTracks/src/com/google/android/apps/mytracks/fragments/MergeDialogFragment.java b/MyTracks/src/com/google/android/apps/mytracks/fragments/MergeDialogFragment.java new file mode 100644 index 000000000..09602f6c2 --- /dev/null +++ b/MyTracks/src/com/google/android/apps/mytracks/fragments/MergeDialogFragment.java @@ -0,0 +1,136 @@ +/* + * Copyright 2013 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.android.apps.mytracks.fragments; + +import com.google.android.apps.mytracks.content.MyTracksProviderUtils; +import com.google.android.apps.mytracks.content.Track; +import com.google.android.apps.mytracks.util.TrackUtils; +import com.google.android.maps.mytracks.R; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.DialogInterface; +import android.database.Cursor; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.util.SparseBooleanArray; + +import java.util.ArrayList; + +/** + * A DialogFragment to merge and play tracks. + * + * @author Jimmy Shih + */ +public class MergeDialogFragment extends DialogFragment { + + public static final String MERGE_DIALOG_TAG = "mergeDialog"; + + /** + * Interface for caller of this dialog fragment. + * + * @author Jimmy Shih + */ + public interface MergeCaller { + + /** + * Called when merge is done. + */ + public void onMergeDone(long[] trackIds); + } + + private static final String KEY_TRACK_ID = "trackId"; + + public static MergeDialogFragment newInstance(long trackId) { + Bundle bundle = new Bundle(); + bundle.putLong(KEY_TRACK_ID, trackId); + + MergeDialogFragment fragment = new MergeDialogFragment(); + fragment.setArguments(bundle); + return fragment; + } + + private MergeCaller caller; + private String[] items; + private boolean[] checkedItems; + private long[] trackIds; + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + try { + caller = (MergeCaller) activity; + } catch (ClassCastException e) { + throw new ClassCastException( + activity.toString() + " must implement " + MergeCaller.class.getSimpleName()); + } + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + loadData(); + return new AlertDialog.Builder(getActivity()).setMultiChoiceItems(items, checkedItems, null) + .setNegativeButton(R.string.generic_cancel, null) + .setPositiveButton(R.string.menu_play, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + SparseBooleanArray array = ((AlertDialog) dialog).getListView() + .getCheckedItemPositions(); + caller.onMergeDone(getChecked(array)); + } + }).setTitle(R.string.menu_merge).create(); + } + + private long[] getChecked(SparseBooleanArray array) { + ArrayList checked = new ArrayList(); + for (int i = 0; i < array.size(); i++) { + if (array.valueAt(i)) { + checked.add(trackIds[i]); + } + } + long[] result = new long[checked.size()]; + for (int i = 0; i < checked.size(); i++) { + result[i] = checked.get(i).longValue(); + } + return result; + } + + private void loadData() { + long trackId = getArguments().getLong(KEY_TRACK_ID); + MyTracksProviderUtils myTracksProviderUtils = MyTracksProviderUtils.Factory.get(getActivity()); + Cursor cursor = myTracksProviderUtils.getTrackCursor(null, null, TrackUtils.TRACK_SORT_ORDER); + + if (cursor == null) { + items = new String[] {}; + checkedItems = new boolean[] {}; + trackIds = new long[] {}; + } else { + int count = cursor.getCount(); + items = new String[count]; + checkedItems = new boolean[count]; + trackIds = new long[count]; + for (int i = 0; i < count; i++) { + cursor.moveToPosition(i); + Track track = myTracksProviderUtils.createTrack(cursor); + items[i] = track.getName(); + checkedItems[i] = trackId != -1L && track.getId() == trackId; + trackIds[i] = track.getId(); + } + } + } +} \ No newline at end of file diff --git a/MyTracks/src/com/google/android/apps/mytracks/util/TrackUtils.java b/MyTracks/src/com/google/android/apps/mytracks/util/TrackUtils.java index d59825404..c1a96955c 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/util/TrackUtils.java +++ b/MyTracks/src/com/google/android/apps/mytracks/util/TrackUtils.java @@ -18,6 +18,7 @@ package com.google.android.apps.mytracks.util; import com.google.android.apps.mytracks.content.MyTracksProviderUtils; import com.google.android.apps.mytracks.content.Track; +import com.google.android.apps.mytracks.content.TracksColumns; import com.google.android.apps.mytracks.services.TrackRecordingServiceConnection; import com.google.android.maps.mytracks.R; @@ -32,6 +33,9 @@ public class TrackUtils { private TrackUtils() {} + public static String TRACK_SORT_ORDER = "IFNULL(" + TracksColumns.SHAREDWITHME + ",0) ASC, " + + TracksColumns.STARTTIME + " DESC"; + public static void updateTrack(Context context, Track track, String name, String category, String description, MyTracksProviderUtils myTracksProviderUtils, TrackRecordingServiceConnection trackRecordingServiceConnection, boolean newWeight) {