diff --git a/Android/res/drawable-hdpi/ic_action_copy.png b/Android/res/drawable-hdpi/ic_action_copy.png
new file mode 100644
index 0000000000..5ff5f86239
Binary files /dev/null and b/Android/res/drawable-hdpi/ic_action_copy.png differ
diff --git a/Android/res/drawable-hdpi/ic_action_copy_blue.png b/Android/res/drawable-hdpi/ic_action_copy_blue.png
new file mode 100644
index 0000000000..4e5e4a6b46
Binary files /dev/null and b/Android/res/drawable-hdpi/ic_action_copy_blue.png differ
diff --git a/Android/res/drawable-hdpi/ic_action_playback_schuffle.png b/Android/res/drawable-hdpi/ic_action_playback_schuffle.png
new file mode 100644
index 0000000000..5de3096cac
Binary files /dev/null and b/Android/res/drawable-hdpi/ic_action_playback_schuffle.png differ
diff --git a/Android/res/drawable-hdpi/ic_action_trash.png b/Android/res/drawable-hdpi/ic_action_trash.png
new file mode 100644
index 0000000000..a937aea060
Binary files /dev/null and b/Android/res/drawable-hdpi/ic_action_trash.png differ
diff --git a/Android/res/drawable-mdpi/ic_action_copy.png b/Android/res/drawable-mdpi/ic_action_copy.png
new file mode 100644
index 0000000000..efafdf7263
Binary files /dev/null and b/Android/res/drawable-mdpi/ic_action_copy.png differ
diff --git a/Android/res/drawable-mdpi/ic_action_copy_blue.png b/Android/res/drawable-mdpi/ic_action_copy_blue.png
new file mode 100644
index 0000000000..01ad9456d6
Binary files /dev/null and b/Android/res/drawable-mdpi/ic_action_copy_blue.png differ
diff --git a/Android/res/drawable-mdpi/ic_action_playback_schuffle.png b/Android/res/drawable-mdpi/ic_action_playback_schuffle.png
new file mode 100644
index 0000000000..25a72c77cd
Binary files /dev/null and b/Android/res/drawable-mdpi/ic_action_playback_schuffle.png differ
diff --git a/Android/res/drawable-mdpi/ic_action_trash.png b/Android/res/drawable-mdpi/ic_action_trash.png
new file mode 100644
index 0000000000..a13e62c0e8
Binary files /dev/null and b/Android/res/drawable-mdpi/ic_action_trash.png differ
diff --git a/Android/res/drawable-xhdpi/ic_action_copy.png b/Android/res/drawable-xhdpi/ic_action_copy.png
new file mode 100644
index 0000000000..5e55f4eb98
Binary files /dev/null and b/Android/res/drawable-xhdpi/ic_action_copy.png differ
diff --git a/Android/res/drawable-xhdpi/ic_action_copy_blue.png b/Android/res/drawable-xhdpi/ic_action_copy_blue.png
new file mode 100644
index 0000000000..2830d29442
Binary files /dev/null and b/Android/res/drawable-xhdpi/ic_action_copy_blue.png differ
diff --git a/Android/res/drawable-xhdpi/ic_action_playback_schuffle.png b/Android/res/drawable-xhdpi/ic_action_playback_schuffle.png
new file mode 100644
index 0000000000..bf7c199459
Binary files /dev/null and b/Android/res/drawable-xhdpi/ic_action_playback_schuffle.png differ
diff --git a/Android/res/drawable-xhdpi/ic_action_trash.png b/Android/res/drawable-xhdpi/ic_action_trash.png
new file mode 100644
index 0000000000..9f910f5960
Binary files /dev/null and b/Android/res/drawable-xhdpi/ic_action_trash.png differ
diff --git a/Android/res/drawable-xxhdpi/ic_action_copy.png b/Android/res/drawable-xxhdpi/ic_action_copy.png
new file mode 100644
index 0000000000..2db460b89b
Binary files /dev/null and b/Android/res/drawable-xxhdpi/ic_action_copy.png differ
diff --git a/Android/res/drawable-xxhdpi/ic_action_copy_blue.png b/Android/res/drawable-xxhdpi/ic_action_copy_blue.png
new file mode 100644
index 0000000000..3668f4277f
Binary files /dev/null and b/Android/res/drawable-xxhdpi/ic_action_copy_blue.png differ
diff --git a/Android/res/drawable-xxhdpi/ic_action_playback_schuffle.png b/Android/res/drawable-xxhdpi/ic_action_playback_schuffle.png
new file mode 100644
index 0000000000..fa62ad4134
Binary files /dev/null and b/Android/res/drawable-xxhdpi/ic_action_playback_schuffle.png differ
diff --git a/Android/res/drawable-xxhdpi/ic_action_trash.png b/Android/res/drawable-xxhdpi/ic_action_trash.png
new file mode 100644
index 0000000000..e3d92c10e8
Binary files /dev/null and b/Android/res/drawable-xxhdpi/ic_action_trash.png differ
diff --git a/Android/res/layout/fragment_editor_detail_circle.xml b/Android/res/layout/fragment_editor_detail_circle.xml
index ef91de91cc..6e309c1be3 100644
--- a/Android/res/layout/fragment_editor_detail_circle.xml
+++ b/Android/res/layout/fragment_editor_detail_circle.xml
@@ -2,7 +2,6 @@
-
+
+ android:layout_alignParentTop="true"
+ android:entries="@array/ExampleWaypointType"/>
-
+ android:layout_height="64dp"
+ android:layout_alignParentTop="true"
+ android:layout_centerVertical="true"
+ android:gravity="center_vertical"
+ android:paddingLeft="25dp"
+ android:paddingRight="25dp"
+ android:background="@drawable/wp_title_rectangle"
+ android:text="Select Waypoint Type"
+ android:textAllCaps="true"/>
-
-
-
-
+
-
-
-
+
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/Android/res/layout/fragment_editor_detail_loiter.xml b/Android/res/layout/fragment_editor_detail_loiter.xml
deleted file mode 100644
index de6647bfcf..0000000000
--- a/Android/res/layout/fragment_editor_detail_loiter.xml
+++ /dev/null
@@ -1,72 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Android/res/layout/fragment_editor_detail_waypoint.xml b/Android/res/layout/fragment_editor_detail_waypoint.xml
index ee3c26ed03..2da5b4f32c 100644
--- a/Android/res/layout/fragment_editor_detail_waypoint.xml
+++ b/Android/res/layout/fragment_editor_detail_waypoint.xml
@@ -98,7 +98,7 @@
android:orientation="vertical" >
+
+
\ No newline at end of file
diff --git a/Android/res/values/strings.xml b/Android/res/values/strings.xml
index 2204d8b3bb..877ac9cab8 100644
--- a/Android/res/values/strings.xml
+++ b/Android/res/values/strings.xml
@@ -209,6 +209,7 @@
Delay before next waypoint
Loiter Radius
CCW
+ Circle Radius
Altitude
Yaw Angle
Target Altitude
@@ -483,5 +484,8 @@
Arm propellers?
Warning! Propellers will spin and drone may begin to fly.
Radius
+ Delete
+ Reverse
+ Multi-Edit
diff --git a/Android/src/org/droidplanner/android/activities/EditorActivity.java b/Android/src/org/droidplanner/android/activities/EditorActivity.java
index 2ed05899c9..8d65c51702 100644
--- a/Android/src/org/droidplanner/android/activities/EditorActivity.java
+++ b/Android/src/org/droidplanner/android/activities/EditorActivity.java
@@ -26,7 +26,9 @@
import org.droidplanner.core.helpers.coordinates.Coord2D;
import org.droidplanner.core.helpers.units.Length;
import org.droidplanner.core.helpers.units.Speed;
+import org.droidplanner.core.mission.MissionItemType;
import org.droidplanner.core.model.Drone;
+import org.droidplanner.core.util.Pair;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
@@ -76,9 +78,11 @@ public class EditorActivity extends DrawerNavigationUI implements OnPathFinished
private View mSplineToggleContainer;
private boolean mIsSplineEnabled;
- private View mLocationButtonsContainer;
private TextView infoView;
+ //TODO: change the multi edit icon based on its state.
+ private boolean mMultiEditEnabled;
+
/**
* This view hosts the mission item detail fragment. On phone, or device
* with limited screen estate, it's removed from the layout, and the item
@@ -109,8 +113,6 @@ public void onCreate(Bundle savedInstanceState) {
infoView = (TextView) findViewById(R.id.editorInfoWindow);
- mLocationButtonsContainer = findViewById(R.id.location_button_container);
-
final ImageButton resetMapBearing = (ImageButton) findViewById(R.id.map_orientation_button);
resetMapBearing.setOnClickListener(new View.OnClickListener() {
@Override
@@ -285,10 +287,8 @@ public void onDroneEvent(DroneEventsType event, Drone drone) {
// Remove detail window if item is removed
- if (itemDetailFragment != null) {
- if (!missionProxy.contains(itemDetailFragment.getItem())) {
+ if (missionProxy.selection.getSelected().isEmpty() && itemDetailFragment != null) {
removeItemDetail();
- }
}
break;
@@ -379,16 +379,16 @@ private void enableSplineToggle(boolean isEnabled) {
}
}
- private void showItemDetail(MissionItemProxy item) {
+ private void showItemDetail(MissionDetailFragment itemDetail) {
if (itemDetailFragment == null) {
- addItemDetail(item);
+ addItemDetail(itemDetail);
} else {
- switchItemDetail(item);
+ switchItemDetail(itemDetail);
}
}
- private void addItemDetail(MissionItemProxy item) {
- itemDetailFragment = item.getDetailFragment();
+ private void addItemDetail(MissionDetailFragment itemDetail) {
+ itemDetailFragment = itemDetail;
if (itemDetailFragment == null)
return;
@@ -401,9 +401,9 @@ private void addItemDetail(MissionItemProxy item) {
}
}
- public void switchItemDetail(MissionItemProxy item) {
+ public void switchItemDetail(MissionDetailFragment itemDetail) {
removeItemDetail();
- addItemDetail(item);
+ addItemDetail(itemDetail);
}
private void removeItemDetail() {
@@ -445,27 +445,42 @@ public void onPathFinished(List path) {
}
@Override
- public void onDetailDialogDismissed(MissionItemProxy item) {
- missionProxy.selection.removeItemFromSelection(item);
+ public void onDetailDialogDismissed(List itemList) {
+ missionProxy.selection.removeItemsFromSelection(itemList);
}
@Override
- public void onWaypointTypeChanged(MissionItemProxy newItem, MissionItemProxy oldItem) {
- missionProxy.replace(oldItem, newItem);
+ public void onWaypointTypeChanged(List> oldNewItemsList) {
+ missionProxy.replaceAll(oldNewItemsList);
}
- private static final int MENU_DELETE = 1;
- private static final int MENU_REVERSE = 2;
-
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
- case MENU_DELETE:
+ case R.id.menu_action_multi_edit:
+ if(mMultiEditEnabled){
+ removeItemDetail();
+ enableMultiEdit(false);
+ return true;
+ }
+
+ final List selectedProxies = missionProxy.selection.getSelected();
+ if(selectedProxies.size() >= 1){
+ showItemDetail(selectMissionDetailType(selectedProxies));
+ enableMultiEdit(true);
+ return true;
+ }
+
+ Toast.makeText(getApplicationContext(), "No Waypoint(s) selected.", Toast.LENGTH_LONG)
+ .show();
+ return true;
+
+ case R.id.menu_action_delete:
missionProxy.removeSelection(missionProxy.selection);
mode.finish();
return true;
- case MENU_REVERSE:
+ case R.id.menu_action_reverse:
missionProxy.reverse();
return true;
@@ -474,10 +489,28 @@ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
}
}
+ private MissionDetailFragment selectMissionDetailType(List proxies){
+ if(proxies == null || proxies.isEmpty())
+ return null;
+
+ MissionItemType referenceType = null;
+ for(MissionItemProxy proxy: proxies){
+ final MissionItemType proxyType = proxy.getMissionItem().getType();
+ if(referenceType == null){
+ referenceType = proxyType;
+ }
+ else if(referenceType != proxyType){
+ //Return a generic mission detail.
+ return new MissionDetailFragment();
+ }
+ }
+
+ return MissionDetailFragment.newInstance(referenceType);
+ }
+
@Override
- public boolean onCreateActionMode(ActionMode arg0, Menu menu) {
- menu.add(0, MENU_DELETE, 0, "Delete");
- menu.add(0, MENU_REVERSE, 0, "Reverse");
+ public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+ mode.getMenuInflater().inflate(R.menu.action_mode_editor, menu);
editorToolsFragment.getView().setVisibility(View.INVISIBLE);
return true;
}
@@ -486,12 +519,27 @@ public boolean onCreateActionMode(ActionMode arg0, Menu menu) {
public void onDestroyActionMode(ActionMode arg0) {
missionListFragment.updateChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
missionProxy.selection.clearSelection();
- contextualActionBar = null;
+
+ contextualActionBar = null;
+ enableMultiEdit(false);
+
editorToolsFragment.getView().setVisibility(View.VISIBLE);
}
+ private void enableMultiEdit(boolean enable){
+ mMultiEditEnabled = enable;
+
+ if(contextualActionBar != null){
+ final Menu menu = contextualActionBar.getMenu();
+ final MenuItem multiEdit = menu.findItem(R.id.menu_action_multi_edit);
+ multiEdit.setIcon(mMultiEditEnabled
+ ? R.drawable.ic_action_copy_blue
+ : R.drawable.ic_action_copy);
+ }
+ }
+
@Override
- public boolean onPrepareActionMode(ActionMode arg0, Menu arg1) {
+ public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
@@ -514,6 +562,7 @@ public boolean onItemLongClick(MissionItemProxy item) {
@Override
public void onItemClick(MissionItemProxy item) {
+ enableMultiEdit(false);
switch (getTool()) {
default:
if (contextualActionBar != null) {
@@ -552,17 +601,17 @@ protected boolean enableMissionMenus(){
@Override
public void onSelectionUpdate(List selected) {
- final int selectedCount = selected.size();
+ final boolean isEmpty = selected.isEmpty();
- missionListFragment.setArrowsVisibility(selectedCount > 0);
+ missionListFragment.setArrowsVisibility(!isEmpty);
- if (selectedCount != 1) {
+ if (isEmpty) {
removeItemDetail();
} else {
- if (contextualActionBar != null)
+ if (contextualActionBar != null && !mMultiEditEnabled)
removeItemDetail();
else {
- showItemDetail(selected.get(0));
+ showItemDetail(selected.get(0).getDetailFragment());
}
}
diff --git a/Android/src/org/droidplanner/android/proxy/mission/MissionProxy.java b/Android/src/org/droidplanner/android/proxy/mission/MissionProxy.java
index d07c1f5afb..e2f1cb14c3 100644
--- a/Android/src/org/droidplanner/android/proxy/mission/MissionProxy.java
+++ b/Android/src/org/droidplanner/android/proxy/mission/MissionProxy.java
@@ -20,8 +20,7 @@
import org.droidplanner.core.mission.waypoints.SpatialCoordItem;
import org.droidplanner.core.mission.waypoints.SplineWaypoint;
import org.droidplanner.core.mission.waypoints.Waypoint;
-
-import android.util.Pair;
+import org.droidplanner.core.util.Pair;
/**
* This class is used to render a {@link org.droidplanner.core.mission.Mission}
@@ -262,6 +261,49 @@ public void replace(MissionItemProxy oldItem, MissionItemProxy newItem) {
}
}
+ public void replaceAll(List> oldNewList){
+ if(oldNewList == null){
+ return;
+ }
+
+ final int pairSize = oldNewList.size();
+ if(pairSize == 0){
+ return;
+ }
+
+ final List> missionItemsToUpdate = new
+ ArrayList>(pairSize);
+
+ final List selectionsToRemove = new ArrayList(pairSize);
+ final List itemsToSelect = new ArrayList(pairSize);
+
+ for(int i = 0; i < pairSize; i++){
+ final MissionItemProxy oldItem = oldNewList.get(i).first;
+ final int index = mMissionItems.indexOf(oldItem);
+ if(index == -1){
+ continue;
+ }
+
+ final MissionItemProxy newItem = oldNewList.get(i).second;
+ mMissionItems.remove(index);
+ mMissionItems.add(index, newItem);
+
+ missionItemsToUpdate.add(Pair.create(oldItem.getMissionItem(), newItem.getMissionItem()));
+
+ if(selection.selectionContains(oldItem)){
+ selectionsToRemove.add(oldItem);
+ itemsToSelect.add(newItem);
+ }
+ }
+
+ //Update the mission objects
+ mMission.replaceAll(missionItemsToUpdate);
+
+ //Update the selection list.
+ selection.removeItemsFromSelection(selectionsToRemove);
+ selection.addToSelection(itemsToSelect);
+ }
+
/**
* Reverse the order of the mission items renders.
*/
diff --git a/Android/src/org/droidplanner/android/proxy/mission/MissionSelection.java b/Android/src/org/droidplanner/android/proxy/mission/MissionSelection.java
index 08679a858e..f7addedfbe 100644
--- a/Android/src/org/droidplanner/android/proxy/mission/MissionSelection.java
+++ b/Android/src/org/droidplanner/android/proxy/mission/MissionSelection.java
@@ -17,24 +17,38 @@ public interface OnSelectionUpdateListener {
/**
* Stores the selected mission items renders.
*/
- public List mSelectedItems = new ArrayList();
+ public final List mSelectedItems = new ArrayList();
/**
* Stores the list of selection update listeners.
*/
public List mSelectionsListeners = new ArrayList();
/**
- * Removes the given mission item render from the selected list. TODO: check
- * the argument belongs to this mission render
+ * Removes the given mission item render from the selected list.
*
* @param item
- * mission item rendere to remove from the selected list
+ * mission item render to remove from the selected list
*/
public void removeItemFromSelection(MissionItemProxy item) {
mSelectedItems.remove(item);
notifySelectionUpdate();
}
+ /**
+ * Removes the mission items in the given list from the selected list.
+ * @param itemList list of mission items to remove from the selected list.
+ */
+ public void removeItemsFromSelection(List itemList){
+ if(itemList == null || itemList.isEmpty()){
+ return;
+ }
+
+ for(MissionItemProxy item : itemList){
+ mSelectedItems.remove(item);
+ }
+ notifySelectionUpdate();
+ }
+
/**
* Selects only the given mission items renders. TODO: check the mission
* items renders belong to this mission render
diff --git a/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionCircleFragment.java b/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionCircleFragment.java
index 6b73090340..5373ab1992 100644
--- a/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionCircleFragment.java
+++ b/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionCircleFragment.java
@@ -13,6 +13,8 @@
import android.widget.CheckBox;
import android.widget.CompoundButton;
+import java.util.List;
+
public class MissionCircleFragment extends MissionDetailFragment implements
CardWheelHorizontalView.OnCardWheelChangedListener, CompoundButton.OnCheckedChangeListener {
@@ -21,7 +23,7 @@ public class MissionCircleFragment extends MissionDetailFragment implements
private CheckBox checkBoxAdvanced;
- private Circle mItem;
+ private List mItemsList;
private CardWheelHorizontalView mNumberStepsPicker;
private CardWheelHorizontalView mAltitudeStepPicker;
@@ -38,21 +40,33 @@ public void onViewCreated(View view, Bundle savedInstanceState) {
typeSpinner.setSelection(commandAdapter.getPosition(MissionItemType.CIRCLE));
- mItem = (Circle) this.itemRender.getMissionItem();
+ mItemsList = (List) getMissionItems();
+
+ //Use the first one as reference.
+ final Circle firstItem = mItemsList.get(0);
+
+ boolean isAdvanced = DEFAULT_IS_ADVANCED_ON;
+ if (savedInstanceState != null) {
+ isAdvanced = savedInstanceState
+ .getBoolean(EXTRA_IS_ADVANCED_ON, DEFAULT_IS_ADVANCED_ON);
+ }
+ checkBoxAdvanced = (CheckBox) view.findViewById(R.id.checkBoxAdvanced);
+ checkBoxAdvanced.setOnCheckedChangeListener(this);
+ checkBoxAdvanced.setChecked(isAdvanced);
final NumericWheelAdapter altitudeStepAdapter = new NumericWheelAdapter(context,
R.layout.wheel_text_centered, 1, 10, "%d m");
mAltitudeStepPicker = (CardWheelHorizontalView) view.findViewById(R.id.altitudeStepPicker);
mAltitudeStepPicker.setViewAdapter(altitudeStepAdapter);
- mAltitudeStepPicker.setCurrentValue((int) mItem.getAltitudeStep());
- mAltitudeStepPicker.addChangingListener(this);
+ mAltitudeStepPicker.addChangingListener(this);
+ mAltitudeStepPicker.setCurrentValue((int) firstItem.getAltitudeStep());
final NumericWheelAdapter numberStepsAdapter = new NumericWheelAdapter(context,
R.layout.wheel_text_centered, 1, 10, "%d");
mNumberStepsPicker = (CardWheelHorizontalView) view.findViewById(R.id.numberStepsPicker);
mNumberStepsPicker.setViewAdapter(numberStepsAdapter);
- mNumberStepsPicker.setCurrentValue(mItem.getNumberOfSteps());
- mNumberStepsPicker.addChangingListener(this);
+ mNumberStepsPicker.addChangingListener(this);
+ mNumberStepsPicker.setCurrentValue(firstItem.getNumberOfSteps());
final NumericWheelAdapter altitudeAdapter = new NumericWheelAdapter(context, MIN_ALTITUDE,
MAX_ALTITUDE, "%d m");
@@ -60,16 +74,17 @@ public void onViewCreated(View view, Bundle savedInstanceState) {
final CardWheelHorizontalView altitudePicker = (CardWheelHorizontalView) view
.findViewById(R.id.altitudePicker);
altitudePicker.setViewAdapter(altitudeAdapter);
- altitudePicker.setCurrentValue((int) mItem.getCoordinate().getAltitude().valueInMeters());
- altitudePicker.addChangingListener(this);
+ altitudePicker.addChangingListener(this);
+ altitudePicker.setCurrentValue((int) firstItem.getCoordinate().getAltitude().valueInMeters
+ ());
final NumericWheelAdapter loiterTurnAdapter = new NumericWheelAdapter(context,
R.layout.wheel_text_centered, 0, 10, "%d");
final CardWheelHorizontalView loiterTurnPicker = (CardWheelHorizontalView) view
.findViewById(R.id.loiterTurnPicker);
loiterTurnPicker.setViewAdapter(loiterTurnAdapter);
- loiterTurnPicker.setCurrentValue(mItem.getNumberOfTurns());
- loiterTurnPicker.addChangingListener(this);
+ loiterTurnPicker.addChangingListener(this);
+ loiterTurnPicker.setCurrentValue(firstItem.getNumberOfTurns());
final NumericWheelAdapter loiterRadiusAdapter = new NumericWheelAdapter(context, 0, 50,
"%d m");
@@ -77,17 +92,8 @@ public void onViewCreated(View view, Bundle savedInstanceState) {
final CardWheelHorizontalView loiterRadiusPicker = (CardWheelHorizontalView) view
.findViewById(R.id.loiterRadiusPicker);
loiterRadiusPicker.setViewAdapter(loiterRadiusAdapter);
- loiterRadiusPicker.setCurrentValue((int) mItem.getRadius());
- loiterRadiusPicker.addChangingListener(this);
-
- boolean isAdvanced = DEFAULT_IS_ADVANCED_ON;
- if (savedInstanceState != null) {
- isAdvanced = savedInstanceState
- .getBoolean(EXTRA_IS_ADVANCED_ON, DEFAULT_IS_ADVANCED_ON);
- }
- checkBoxAdvanced = (CheckBox) view.findViewById(R.id.checkBoxAdvanced);
- checkBoxAdvanced.setOnCheckedChangeListener(this);
- checkBoxAdvanced.setChecked(isAdvanced);
+ loiterRadiusPicker.addChangingListener(this);
+ loiterRadiusPicker.setCurrentValue((int) firstItem.getRadius());
}
@Override
@@ -103,11 +109,15 @@ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
int visibility;
if (isChecked) {
visibility = View.VISIBLE;
- mItem.setNumberOfSteps(mNumberStepsPicker.getCurrentValue());
- mItem.setAltitudeStep(mAltitudeStepPicker.getCurrentValue());
+ for(Circle item: mItemsList) {
+ item.setNumberOfSteps(mNumberStepsPicker.getCurrentValue());
+ item.setAltitudeStep(mAltitudeStepPicker.getCurrentValue());
+ }
} else {
visibility = View.GONE;
- mItem.setNumberOfSteps(1);
+ for(Circle item: mItemsList) {
+ item.setNumberOfSteps(1);
+ }
}
mAltitudeStepPicker.setVisibility(visibility);
@@ -119,27 +129,37 @@ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
public void onChanged(CardWheelHorizontalView cardWheel, int oldValue, int newValue) {
switch (cardWheel.getId()) {
case R.id.altitudePicker:
- mItem.setAltitude(new Altitude(newValue));
+ for(Circle item: mItemsList) {
+ item.setAltitude(new Altitude(newValue));
+ }
break;
case R.id.loiterRadiusPicker:
- mItem.setRadius(newValue);
- mItem.getMission().notifyMissionUpdate();
+ for(Circle item: mItemsList) {
+ item.setRadius(newValue);
+ }
+ getMissionProxy().getMission().notifyMissionUpdate();
break;
case R.id.loiterTurnPicker:
- mItem.setTurns(newValue);
+ for(Circle item: mItemsList) {
+ item.setTurns(newValue);
+ }
break;
case R.id.numberStepsPicker:
if (checkBoxAdvanced.isChecked()) {
- mItem.setNumberOfSteps(newValue);
+ for(Circle item: mItemsList) {
+ item.setNumberOfSteps(newValue);
+ }
}
break;
case R.id.altitudeStepPicker:
if (checkBoxAdvanced.isChecked()) {
- mItem.setAltitudeStep(newValue);
+ for(Circle item: mItemsList) {
+ item.setAltitudeStep(newValue);
+ }
}
break;
}
diff --git a/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionDetailFragment.java b/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionDetailFragment.java
index d3f6a0791b..b3d449595e 100644
--- a/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionDetailFragment.java
+++ b/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionDetailFragment.java
@@ -1,5 +1,6 @@
package org.droidplanner.android.proxy.mission.item.fragments;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
@@ -14,7 +15,7 @@
import org.droidplanner.core.mission.MissionItemType;
import org.droidplanner.core.mission.commands.MissionCMD;
import org.droidplanner.core.mission.survey.Survey;
-import org.droidplanner.core.mission.waypoints.SpatialCoordItem;
+import org.droidplanner.core.util.Pair;
import android.app.Activity;
import android.content.DialogInterface;
@@ -24,47 +25,47 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.Spinner;
import android.widget.TextView;
-public abstract class MissionDetailFragment extends DialogFragment implements
- OnItemSelectedListener {
+public class MissionDetailFragment extends DialogFragment implements SpinnerSelfSelect.OnSpinnerItemSelectedListener {
private static final String TAG = MissionDetailFragment.class.getSimpleName();
protected static final int MIN_ALTITUDE = 0; // meter
protected static final int MAX_ALTITUDE = 200; // meters
- public interface OnMissionDetailListener {
+ public interface OnMissionDetailListener {
/**
* Only fired when the mission detail is shown as a dialog. Notifies the
* listener that the mission detail dialog has been dismissed.
*
- * @param item
- * mission item proxy whose details the dialog is showing.
+ * @param itemList
+ * list of mission items proxies whose details the dialog is showing.
*/
- public void onDetailDialogDismissed(MissionItemProxy item);
+ public void onDetailDialogDismissed(List itemList);
/**
* Notifies the listener that the mission item proxy was changed.
- *
- * @param newItem
- * previous mission item proxy
- * @param oldItem
- * new mission item proxy
+ *
+ * @param oldNewItemsList a list of pairs containing the previous,
+ * and the new mission item proxy.
*/
- public void onWaypointTypeChanged(MissionItemProxy newItem, MissionItemProxy oldItem);
+ public void onWaypointTypeChanged(List> oldNewItemsList);
}
- protected abstract int getResource();
+ protected int getResource(){
+ return R.layout.fragment_editor_detail_generic;
+ }
protected SpinnerSelfSelect typeSpinner;
protected AdapterMissionItems commandAdapter;
private OnMissionDetailListener mListener;
- private MissionProxy mMissionProxy;
- protected MissionItemProxy itemRender;
+ private MissionProxy mMissionProxy;
+ private List mSelectedItems;
+ private List mSelectedProxies;
public static MissionDetailFragment newInstance(MissionItemType itemType) {
MissionDetailFragment fragment;
@@ -108,77 +109,102 @@ public void onCreate(Bundle savedInstanceState) {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- final MissionProxy missionProxy = ((DroidPlannerApp) getActivity().getApplication()).missionProxy;
- final List selections = missionProxy.selection.getSelected();
- if (selections.isEmpty()) {
+ mMissionProxy = ((DroidPlannerApp) getActivity().getApplication()).missionProxy;
+ mSelectedProxies = new ArrayList(mMissionProxy.selection.getSelected());
+ if (mSelectedProxies.isEmpty()) {
return null;
}
- itemRender = selections.get(0);
+ mSelectedItems = new ArrayList(mSelectedProxies.size());
+ for(MissionItemProxy mip : mSelectedProxies){
+ mSelectedItems.add(mip.getMissionItem());
+ }
+
return inflater.inflate(getResource(), container, false);
}
+ protected MissionProxy getMissionProxy(){
+ return mMissionProxy;
+ }
+
+ protected List extends MissionItem> getMissionItems(){
+ return mSelectedItems;
+ }
+
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
- mMissionProxy = itemRender.getMissionProxy();
- List list = new LinkedList(Arrays.asList(MissionItemType
- .values()));
- MissionItem currentItem = itemRender.getMissionItem();
-
- if ((currentItem instanceof Survey)) {
- list.clear();
- list.add(MissionItemType.SURVEY);
- }else{
- list.remove(MissionItemType.SURVEY);
- }
-
- if (mMissionProxy.getItems().indexOf(itemRender) != 0) {
- list.remove(MissionItemType.TAKEOFF);
- }
+ List list = new LinkedList(Arrays.asList(MissionItemType.values()));
- if (mMissionProxy.getItems().indexOf(itemRender) != (mMissionProxy.getItems().size() - 1)) {
- list.remove(MissionItemType.LAND);
- list.remove(MissionItemType.RTL);
- }
-
- if(currentItem instanceof MissionCMD) {
- list.remove(MissionItemType.LAND);
- list.remove(MissionItemType.SPLINE_WAYPOINT);
- list.remove(MissionItemType.CIRCLE);
- list.remove(MissionItemType.ROI);
- list.remove(MissionItemType.WAYPOINT);
- }
-
-
- commandAdapter = new AdapterMissionItems(this.getActivity(),
- android.R.layout.simple_list_item_1, list.toArray(new MissionItemType[0]));
+ if(mSelectedProxies.size() == 1) {
+ final MissionItemProxy itemProxy = mSelectedProxies.get(0);
+ final MissionItem currentItem = itemProxy.getMissionItem();
- typeSpinner = (SpinnerSelfSelect) view.findViewById(R.id.spinnerWaypointType);
- typeSpinner.setAdapter(commandAdapter);
- typeSpinner.setOnItemSelectedListener(this);
+ if ((currentItem instanceof Survey)) {
+ list.clear();
+ list.add(MissionItemType.SURVEY);
+ } else {
+ list.remove(MissionItemType.SURVEY);
+ }
- final TextView waypointIndex = (TextView) view.findViewById(R.id.WaypointIndex);
- if (waypointIndex != null) {
- final int itemOrder = mMissionProxy.getOrder(itemRender);
- waypointIndex.setText(String.valueOf(itemOrder));
- }
+ if (mMissionProxy.getItems().indexOf(itemProxy) != 0) {
+ list.remove(MissionItemType.TAKEOFF);
+ }
- final TextView distanceView = (TextView) view.findViewById(R.id.DistanceValue);
- if (distanceView != null) {
- try {
- distanceView.setText(mMissionProxy.getDistanceFromLastWaypoint(itemRender)
- .toString());
- } catch (IllegalArgumentException e) {
- Log.w(TAG, e.getMessage(), e);
- }
- }
+ if (mMissionProxy.getItems().indexOf(itemProxy) != (mMissionProxy.getItems().size() - 1)) {
+ list.remove(MissionItemType.LAND);
+ list.remove(MissionItemType.RTL);
+ }
- final TextView distanceLabelView = (TextView) view.findViewById(R.id.DistanceLabel);
- if (distanceLabelView != null) {
- distanceLabelView.setVisibility(View.VISIBLE);
- }
+ if (currentItem instanceof MissionCMD) {
+ list.remove(MissionItemType.LAND);
+ list.remove(MissionItemType.SPLINE_WAYPOINT);
+ list.remove(MissionItemType.CIRCLE);
+ list.remove(MissionItemType.ROI);
+ list.remove(MissionItemType.WAYPOINT);
+ }
+
+ final TextView waypointIndex = (TextView) view.findViewById(R.id.WaypointIndex);
+ if (waypointIndex != null) {
+ final int itemOrder = mMissionProxy.getOrder(itemProxy);
+ waypointIndex.setText(String.valueOf(itemOrder));
+ }
+
+ final TextView distanceView = (TextView) view.findViewById(R.id.DistanceValue);
+ if (distanceView != null) {
+ try {
+ distanceView.setText(mMissionProxy.getDistanceFromLastWaypoint(itemProxy)
+ .toString());
+ } catch (IllegalArgumentException e) {
+ Log.w(TAG, e.getMessage(), e);
+ }
+ }
+
+ final TextView distanceLabelView = (TextView) view.findViewById(R.id.DistanceLabel);
+ if (distanceLabelView != null) {
+ distanceLabelView.setVisibility(View.VISIBLE);
+ }
+ }
+ else if(mSelectedProxies.size() > 1){
+ //Remove the mission item types that don't apply to multiple items.
+ list.remove(MissionItemType.TAKEOFF);
+ list.remove(MissionItemType.LAND);
+ list.remove(MissionItemType.RTL);
+ list.remove(MissionItemType.SURVEY);
+ }
+ else{
+ //Invalid state. We should not have been able to get here.
+ throw new IllegalStateException("Mission Detail Fragment cannot be shown when no " +
+ "mission items is selected.");
+ }
+
+ commandAdapter = new AdapterMissionItems(getActivity(),
+ android.R.layout.simple_list_item_1, list.toArray(new MissionItemType[list.size()]));
+
+ typeSpinner = (SpinnerSelfSelect) view.findViewById(R.id.spinnerWaypointType);
+ typeSpinner.setAdapter(commandAdapter);
+ typeSpinner.setOnSpinnerItemSelectedListener(this);
}
@Override
@@ -202,33 +228,35 @@ public void onDetach() {
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
if (mListener != null) {
- mListener.onDetailDialogDismissed(itemRender);
+ mListener.onDetailDialogDismissed(mSelectedProxies);
}
}
- @Override
- public void onItemSelected(AdapterView> arg0, View v, int position, long id) {
- MissionItemType selected = commandAdapter.getItem(position);
- try {
- final MissionItem oldItem = itemRender.getMissionItem();
- if (oldItem.getType() != selected) {
- Log.d("CLASS", "Different waypoint Classes");
- MissionItem newItem = selected.getNewItem(oldItem);
- mListener.onWaypointTypeChanged(new MissionItemProxy(itemRender.getMissionProxy(),
- newItem), itemRender);
- dismiss();
- }
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- }
- }
+ @Override
+ public void onSpinnerItemSelected(Spinner spinner, int position) {
+ final MissionItemType selectedType = commandAdapter.getItem(position);
- @Override
- public void onNothingSelected(AdapterView> arg0) {
- }
+ try {
+ if (mSelectedProxies == null || mSelectedProxies.isEmpty())
+ return;
- public MissionItemProxy getItem() {
- return itemRender;
- }
+ final List> updatesList = new ArrayList>(
+ mSelectedProxies.size());
+
+ for (MissionItemProxy missionItemProxy : mSelectedProxies) {
+ final MissionItem oldItem = missionItemProxy.getMissionItem();
+ if (oldItem.getType() != selectedType) {
+ updatesList.add(Pair.create(missionItemProxy, new MissionItemProxy(
+ mMissionProxy, selectedType.getNewItem(oldItem))));
+ }
+ }
+ if(!updatesList.isEmpty()) {
+ mListener.onWaypointTypeChanged(updatesList);
+ dismiss();
+ }
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ }
+ }
}
\ No newline at end of file
diff --git a/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionRegionOfInterestFragment.java b/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionRegionOfInterestFragment.java
index 8be0273066..b0d734fb88 100644
--- a/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionRegionOfInterestFragment.java
+++ b/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionRegionOfInterestFragment.java
@@ -4,6 +4,7 @@
import org.droidplanner.android.widgets.spinnerWheel.CardWheelHorizontalView;
import org.droidplanner.android.widgets.spinnerWheel.adapters.NumericWheelAdapter;
import org.droidplanner.core.helpers.units.Altitude;
+import org.droidplanner.core.mission.MissionItem;
import org.droidplanner.core.mission.MissionItemType;
import org.droidplanner.core.mission.waypoints.RegionOfInterest;
@@ -24,21 +25,23 @@ public void onViewCreated(View view, Bundle savedInstanceState) {
typeSpinner.setSelection(commandAdapter.getPosition(MissionItemType.ROI));
final NumericWheelAdapter altitudeAdapter = new NumericWheelAdapter(getActivity()
- .getApplicationContext(), MIN_ALTITUDE, MAX_ALTITUDE, "%d m");
- altitudeAdapter.setItemResource(R.layout.wheel_text_centered);
+ .getApplicationContext(), R.layout.wheel_text_centered, MIN_ALTITUDE,
+ MAX_ALTITUDE, "%d m");
final CardWheelHorizontalView altitudePicker = (CardWheelHorizontalView) view
.findViewById(R.id.altitudePicker);
altitudePicker.setViewAdapter(altitudeAdapter);
- altitudePicker.setCurrentValue((int) ((RegionOfInterest) itemRender.getMissionItem())
+ altitudePicker.addChangingListener(this);
+ altitudePicker.setCurrentValue((int) ((RegionOfInterest) getMissionItems().get(0))
.getCoordinate().getAltitude().valueInMeters());
- altitudePicker.addChangingListener(this);
}
@Override
public void onChanged(CardWheelHorizontalView wheel, int oldValue, int newValue) {
switch (wheel.getId()) {
case R.id.altitudePicker:
- ((RegionOfInterest) itemRender.getMissionItem()).setAltitude(new Altitude(newValue));
+ for(MissionItem missionItem: getMissionItems()) {
+ ((RegionOfInterest) missionItem).setAltitude(new Altitude(newValue));
+ }
break;
}
}
diff --git a/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionSplineWaypointFragment.java b/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionSplineWaypointFragment.java
index 29dccf04d1..43fac1b320 100644
--- a/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionSplineWaypointFragment.java
+++ b/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionSplineWaypointFragment.java
@@ -4,6 +4,7 @@
import org.droidplanner.android.widgets.spinnerWheel.CardWheelHorizontalView;
import org.droidplanner.android.widgets.spinnerWheel.adapters.NumericWheelAdapter;
import org.droidplanner.core.helpers.units.Altitude;
+import org.droidplanner.core.mission.MissionItem;
import org.droidplanner.core.mission.MissionItemType;
import org.droidplanner.core.mission.waypoints.SplineWaypoint;
@@ -29,39 +30,39 @@ public void onViewCreated(View view, Bundle savedInstanceState) {
typeSpinner.setSelection(commandAdapter.getPosition(MissionItemType.SPLINE_WAYPOINT));
- SplineWaypoint item = (SplineWaypoint) this.itemRender.getMissionItem();
+ SplineWaypoint item = (SplineWaypoint) getMissionItems().get(0);
- final NumericWheelAdapter delayAdapter = new NumericWheelAdapter(context, 0, 60, "%d s");
- delayAdapter.setItemResource(R.layout.wheel_text_centered);
+ final NumericWheelAdapter delayAdapter = new NumericWheelAdapter(context,
+ R.layout.wheel_text_centered, 0, 60, "%d s");
final CardWheelHorizontalView delayPicker = (CardWheelHorizontalView) view
.findViewById(R.id.waypointDelayPicker);
delayPicker.setViewAdapter(delayAdapter);
+ delayPicker.addChangingListener(this);
delayPicker.setCurrentValue((int) item.getDelay());
- delayPicker.addChangingListener(this);
- final NumericWheelAdapter altitudeAdapter = new NumericWheelAdapter(context, MIN_ALTITUDE,
- MAX_ALTITUDE, "%d m");
- altitudeAdapter.setItemResource(R.layout.wheel_text_centered);
+ final NumericWheelAdapter altitudeAdapter = new NumericWheelAdapter(context,
+ R.layout.wheel_text_centered, MIN_ALTITUDE, MAX_ALTITUDE, "%d m");
final CardWheelHorizontalView altitudePicker = (CardWheelHorizontalView) view
.findViewById(R.id.altitudePicker);
altitudePicker.setViewAdapter(altitudeAdapter);
+ altitudePicker.addChangingListener(this);
altitudePicker.setCurrentValue((int) item.getCoordinate().getAltitude().valueInMeters());
- altitudePicker.addChangingListener(this);
}
@Override
public void onChanged(CardWheelHorizontalView wheel, int oldValue, int newValue) {
- final SplineWaypoint item = (SplineWaypoint) this.itemRender.getMissionItem();
-
switch (wheel.getId()) {
case R.id.altitudePicker:
- item.setAltitude(new Altitude(newValue));
+ for(MissionItem item: getMissionItems()) {
+ ((SplineWaypoint)item).setAltitude(new Altitude(newValue));
+ }
break;
case R.id.waypointDelayPicker:
- item.setDelay(newValue);
+ for(MissionItem item: getMissionItems()) {
+ ((SplineWaypoint)item).setDelay(newValue);
+ }
break;
}
-
}
}
diff --git a/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionSurveyFragment.java b/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionSurveyFragment.java
index c955cbb312..53b9fc0f04 100644
--- a/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionSurveyFragment.java
+++ b/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionSurveyFragment.java
@@ -10,6 +10,7 @@
import org.droidplanner.core.drone.DroneInterfaces;
import org.droidplanner.core.helpers.units.Altitude;
import org.droidplanner.core.mission.MissionItemType;
+import org.droidplanner.core.mission.survey.CameraInfo;
import org.droidplanner.core.mission.survey.Survey;
import org.droidplanner.core.model.Drone;
@@ -23,6 +24,8 @@
import android.widget.Spinner;
import android.widget.TextView;
+import java.util.List;
+
public class MissionSurveyFragment extends MissionDetailFragment implements OnClickListener,
CardWheelHorizontalView.OnCardWheelChangedListener,
SpinnerSelfSelect.OnSpinnerItemSelectedListener, DroneInterfaces.OnDroneListener {
@@ -47,7 +50,7 @@ public class MissionSurveyFragment extends MissionDetailFragment implements OnCl
public CheckBox footprintCheckBox;
private CamerasAdapter cameraAdapter;
- private Survey survey;
+ private List surveyList;
@Override
protected int getResource() {
@@ -71,10 +74,14 @@ public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
final Context context = getActivity().getApplicationContext();
- this.survey = ((Survey) itemRender.getMissionItem());
- typeSpinner.setSelection(commandAdapter.getPosition(MissionItemType.SURVEY));
+ cameraAdapter = new CamerasAdapter(getActivity(),
+ android.R.layout.simple_spinner_dropdown_item);
+
+ this.surveyList = ((List) getMissionItems());
cameraSpinner = (SpinnerSelfSelect) view.findViewById(id.cameraFileSpinner);
+ cameraSpinner.setAdapter(cameraAdapter);
+
footprintCheckBox = (CheckBox) view.findViewById(id.CheckBoxFootprints);
mAnglePicker = (CardWheelHorizontalView) view.findViewById(id.anglePicker);
@@ -105,25 +112,27 @@ public void onViewCreated(View view, Bundle savedInstanceState) {
numberOfStripsView = (TextView) view.findViewById(id.numberOfStripsTextView);
lengthView = (TextView) view.findViewById(id.lengthTextView);
- cameraAdapter = new CamerasAdapter(getActivity(),
- android.R.layout.simple_spinner_dropdown_item);
- cameraSpinner.setAdapter(cameraAdapter);
-
footprintCheckBox.setOnClickListener(this);
innerWPsCheckbox.setOnClickListener(this);
cameraSpinner.setOnSpinnerItemSelectedListener(this);
+ mAnglePicker.addChangingListener(this);
+ mOverlapPicker.addChangingListener(this);
+ mSidelapPicker.addChangingListener(this);
+ mAltitudePicker.addChangingListener(this);
+
updateViews();
- mAnglePicker.addChangingListener(this);
- mOverlapPicker.addChangingListener(this);
- mSidelapPicker.addChangingListener(this);
- mAltitudePicker.addChangingListener(this);
+ typeSpinner.setSelection(commandAdapter.getPosition(MissionItemType.SURVEY));
}
@Override
public void onSpinnerItemSelected(Spinner spinner, int position) {
- survey.setCameraInfo(cameraAdapter.getCamera(position));
+ final CameraInfo cameraInfo = cameraAdapter.getCamera(position);
+ for(Survey survey: surveyList) {
+ survey.setCameraInfo(cameraInfo);
+ }
+
onChanged(mAnglePicker, 0, 0);
}
@@ -134,13 +143,15 @@ public void onChanged(CardWheelHorizontalView cardWheel, int oldValue, int newVa
case R.id.altitudePicker:
case R.id.overlapPicker:
case R.id.sidelapPicker:
- survey.update(mAnglePicker.getCurrentValue(),
- new Altitude(mAltitudePicker.getCurrentValue()),
- mOverlapPicker.getCurrentValue(), mSidelapPicker.getCurrentValue());
-
try {
- survey.build();
- mAltitudePicker.setBackgroundResource(R.drawable.bg_cell_white);
+ for (Survey survey : surveyList) {
+ survey.update(mAnglePicker.getCurrentValue(),
+ new Altitude(mAltitudePicker.getCurrentValue()),
+ mOverlapPicker.getCurrentValue(), mSidelapPicker.getCurrentValue());
+
+ survey.build();
+ }
+ mAltitudePicker.setBackgroundResource(R.drawable.bg_cell_white);
} catch (Exception e) {
Log.e(TAG, "Error while building the survey.", e);
mAltitudePicker.setBackgroundColor(Color.RED);
@@ -173,36 +184,36 @@ private void updateViews() {
}
private void updateCameraSpinner() {
- cameraAdapter.setTitle(survey.surveyData.getCameraName());
+ cameraAdapter.setTitle(surveyList.get(0).surveyData.getCameraName());
}
private void updateSeekBars() {
- mAnglePicker.setCurrentValue(survey.surveyData.getAngle().intValue());
- mOverlapPicker.setCurrentValue((int) survey.surveyData.getOverlap());
- mSidelapPicker.setCurrentValue((int) survey.surveyData.getSidelap());
- mAltitudePicker.setCurrentValue((int) survey.surveyData.getAltitude().valueInMeters());
+ mAnglePicker.setCurrentValue(surveyList.get(0).surveyData.getAngle().intValue());
+ mOverlapPicker.setCurrentValue((int) surveyList.get(0).surveyData.getOverlap());
+ mSidelapPicker.setCurrentValue((int) surveyList.get(0).surveyData.getSidelap());
+ mAltitudePicker.setCurrentValue((int) surveyList.get(0).surveyData.getAltitude().valueInMeters());
}
private void updateTextViews() {
Context context = getActivity();
try {
footprintTextView.setText(context.getString(R.string.footprint) + ": "
- + survey.surveyData.getLateralFootPrint() + " x"
- + survey.surveyData.getLongitudinalFootPrint());
+ + surveyList.get(0).surveyData.getLateralFootPrint() + " x"
+ + surveyList.get(0).surveyData.getLongitudinalFootPrint());
groundResolutionTextView.setText(context.getString(R.string.ground_resolution) + ": "
- + survey.surveyData.getGroundResolution() + "/px");
+ + surveyList.get(0).surveyData.getGroundResolution() + "/px");
distanceTextView.setText(context.getString(R.string.distance_between_pictures) + ": "
- + survey.surveyData.getLongitudinalPictureDistance());
+ + surveyList.get(0).surveyData.getLongitudinalPictureDistance());
distanceBetweenLinesTextView.setText(context.getString(R.string.distance_between_lines)
- + ": " + survey.surveyData.getLateralPictureDistance());
+ + ": " + surveyList.get(0).surveyData.getLateralPictureDistance());
areaTextView
- .setText(context.getString(R.string.area) + ": " + survey.polygon.getArea());
+ .setText(context.getString(R.string.area) + ": " + surveyList.get(0).polygon.getArea());
lengthView.setText(context.getString(R.string.mission_length) + ": "
- + survey.grid.getLength());
+ + surveyList.get(0).grid.getLength());
numberOfPicturesView.setText(context.getString(R.string.pictures) + ": "
- + survey.grid.getCameraCount());
+ + surveyList.get(0).grid.getCameraCount());
numberOfStripsView.setText(context.getString(R.string.number_of_strips) + ": "
- + survey.grid.getNumberOfLines());
+ + surveyList.get(0).grid.getNumberOfLines());
} catch (Exception e) {
footprintTextView.setText(context.getString(R.string.footprint) + ": " + "???");
groundResolutionTextView.setText(context.getString(R.string.ground_resolution) + ": "
diff --git a/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionTakeoffFragment.java b/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionTakeoffFragment.java
index 84a0320f2a..f73fa2a0f2 100644
--- a/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionTakeoffFragment.java
+++ b/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionTakeoffFragment.java
@@ -4,6 +4,7 @@
import org.droidplanner.android.widgets.spinnerWheel.CardWheelHorizontalView;
import org.droidplanner.android.widgets.spinnerWheel.adapters.NumericWheelAdapter;
import org.droidplanner.core.helpers.units.Altitude;
+import org.droidplanner.core.mission.MissionItem;
import org.droidplanner.core.mission.MissionItemType;
import org.droidplanner.core.mission.commands.Takeoff;
@@ -23,24 +24,26 @@ public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
typeSpinner.setSelection(commandAdapter.getPosition(MissionItemType.TAKEOFF));
- Takeoff item = (Takeoff) this.itemRender.getMissionItem();
+ Takeoff item = (Takeoff) getMissionItems().get(0);
final NumericWheelAdapter altitudeAdapter = new NumericWheelAdapter(getActivity()
- .getApplicationContext(), MIN_ALTITUDE, MAX_ALTITUDE, "%d m");
- altitudeAdapter.setItemResource(R.layout.wheel_text_centered);
+ .getApplicationContext(), R.layout.wheel_text_centered, MIN_ALTITUDE,
+ MAX_ALTITUDE, "%d m");
final CardWheelHorizontalView cardAltitudePicker = (CardWheelHorizontalView) view
.findViewById(R.id.altitudePicker);
cardAltitudePicker.setViewAdapter(altitudeAdapter);
+ cardAltitudePicker.addChangingListener(this);
cardAltitudePicker.setCurrentValue((int) item.getFinishedAlt().valueInMeters());
- cardAltitudePicker.addChangingListener(this);
}
@Override
public void onChanged(CardWheelHorizontalView wheel, int oldValue, int newValue) {
switch (wheel.getId()) {
case R.id.altitudePicker:
- Takeoff item = (Takeoff) this.itemRender.getMissionItem();
- item.setFinishedAlt(new Altitude(newValue));
+ for(MissionItem missionItem : getMissionItems()) {
+ Takeoff item = (Takeoff) missionItem;
+ item.setFinishedAlt(new Altitude(newValue));
+ }
break;
}
}
diff --git a/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionWaypointFragment.java b/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionWaypointFragment.java
index 38bf8000ae..6cd4ca6025 100644
--- a/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionWaypointFragment.java
+++ b/Android/src/org/droidplanner/android/proxy/mission/item/fragments/MissionWaypointFragment.java
@@ -4,6 +4,7 @@
import org.droidplanner.android.widgets.spinnerWheel.CardWheelHorizontalView;
import org.droidplanner.android.widgets.spinnerWheel.adapters.NumericWheelAdapter;
import org.droidplanner.core.helpers.units.Altitude;
+import org.droidplanner.core.mission.MissionItem;
import org.droidplanner.core.mission.MissionItemType;
import org.droidplanner.core.mission.waypoints.Waypoint;
@@ -26,38 +27,38 @@ public void onViewCreated(View view, Bundle savedInstanceState) {
typeSpinner.setSelection(commandAdapter.getPosition(MissionItemType.WAYPOINT));
- final Waypoint item = (Waypoint) this.itemRender.getMissionItem();
+ final Waypoint item = (Waypoint) getMissionItems().get(0);
- final NumericWheelAdapter delayAdapter = new NumericWheelAdapter(context, 0, 60, "%d s");
- delayAdapter.setItemResource(R.layout.wheel_text_centered);
+ final NumericWheelAdapter delayAdapter = new NumericWheelAdapter(context,
+ R.layout.wheel_text_centered, 0, 60, "%d s");
final CardWheelHorizontalView delayPicker = (CardWheelHorizontalView) view
.findViewById(R.id.waypointDelayPicker);
delayPicker.setViewAdapter(delayAdapter);
+ delayPicker.addChangingListener(this);
delayPicker.setCurrentValue((int) item.getDelay());
- delayPicker.addChangingListener(this);
- final NumericWheelAdapter altitudeAdapter = new NumericWheelAdapter(context, MIN_ALTITUDE,
- MAX_ALTITUDE, "%d m");
- altitudeAdapter.setItemResource(R.layout.wheel_text_centered);
+ final NumericWheelAdapter altitudeAdapter = new NumericWheelAdapter(context,
+ R.layout.wheel_text_centered, MIN_ALTITUDE, MAX_ALTITUDE, "%d m");
final CardWheelHorizontalView altitudePicker = (CardWheelHorizontalView) view
.findViewById(R.id.altitudePicker);
altitudePicker.setViewAdapter(altitudeAdapter);
+ altitudePicker.addChangingListener(this);
altitudePicker.setCurrentValue((int) item.getCoordinate().getAltitude().valueInMeters());
- altitudePicker.addChangingListener(this);
-
}
@Override
public void onChanged(CardWheelHorizontalView wheel, int oldValue, int newValue) {
- final Waypoint item = (Waypoint) this.itemRender.getMissionItem();
-
switch (wheel.getId()) {
case R.id.altitudePicker:
- item.setAltitude(new Altitude(newValue));
+ for(MissionItem item: getMissionItems()) {
+ ((Waypoint)item).setAltitude(new Altitude(newValue));
+ }
break;
case R.id.waypointDelayPicker:
- item.setDelay(newValue);
+ for(MissionItem item: getMissionItems()) {
+ ((Waypoint)item).setDelay(newValue);
+ }
break;
}
diff --git a/Core/src/org/droidplanner/core/mission/Mission.java b/Core/src/org/droidplanner/core/mission/Mission.java
index baeb713fd3..2d3e2401b2 100644
--- a/Core/src/org/droidplanner/core/mission/Mission.java
+++ b/Core/src/org/droidplanner/core/mission/Mission.java
@@ -20,6 +20,7 @@
import org.droidplanner.core.mission.waypoints.SplineWaypoint;
import org.droidplanner.core.mission.waypoints.Waypoint;
import org.droidplanner.core.model.Drone;
+import org.droidplanner.core.util.Pair;
import com.MAVLink.Messages.ardupilotmega.msg_mission_ack;
import com.MAVLink.Messages.ardupilotmega.msg_mission_item;
@@ -134,12 +135,41 @@ public Altitude getLastAltitude() {
* new mission item
*/
public void replace(MissionItem oldItem, MissionItem newItem) {
- int index = items.indexOf(oldItem);
+ final int index = items.indexOf(oldItem);
+ if(index == -1){
+ return;
+ }
+
items.remove(index);
items.add(index, newItem);
notifyMissionUpdate();
}
+ public void replaceAll(List> updatesList){
+ if(updatesList == null || updatesList.isEmpty()){
+ return;
+ }
+
+ boolean wasUpdated = false;
+ for(Pair updatePair : updatesList){
+ final MissionItem oldItem = updatePair.first;
+ final int index = items.indexOf(oldItem);
+ if(index == -1){
+ continue;
+ }
+
+ final MissionItem newItem = updatePair.second;
+ items.remove(index);
+ items.add(index, newItem);
+
+ wasUpdated = true;
+ }
+
+ if(wasUpdated) {
+ notifyMissionUpdate();
+ }
+ }
+
/**
* Reverse the order of the mission items.
*/
diff --git a/Core/src/org/droidplanner/core/util/Pair.java b/Core/src/org/droidplanner/core/util/Pair.java
new file mode 100644
index 0000000000..d6288d0e41
--- /dev/null
+++ b/Core/src/org/droidplanner/core/util/Pair.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 org.droidplanner.core.util;
+
+/**
+ * Container to ease passing around a tuple of two objects. This object provides a sensible
+ * implementation of equals(), returning true if equals() is true on each of the contained
+ * objects.
+ */
+public class Pair {
+ public final F first;
+ public final S second;
+
+ /**
+ * Constructor for a Pair.
+ *
+ * @param first the first object in the Pair
+ * @param second the second object in the pair
+ */
+ public Pair(F first, S second) {
+ this.first = first;
+ this.second = second;
+ }
+
+ /**
+ * Checks the two objects for equality by delegating to their respective
+ * {@link Object#equals(Object)} methods.
+ *
+ * @param o the {@link Pair} to which this one is to be checked for equality
+ * @return true if the underlying objects of the Pair are both considered
+ * equal
+ */
+ @Override
+ public boolean equals(Object o) {
+ if(o == this)
+ return true;
+
+ if (!(o instanceof Pair)) {
+ return false;
+ }
+ Pair, ?> p = (Pair, ?>) o;
+ return (p.first == null) ? (first == null) : p.first.equals(first)
+ && (p.second == null) ? (second == null) : p.second.equals(second);
+ }
+
+ /**
+ * Compute a hash code using the hash codes of the underlying objects
+ *
+ * @return a hashcode of the Pair
+ */
+ @Override
+ public int hashCode() {
+ return (first == null ? 0 : first.hashCode()) ^ (second == null ? 0 : second.hashCode());
+ }
+
+ /**
+ * Convenience method for creating an appropriately typed pair.
+ * @param a the first object in the Pair
+ * @param b the second object in the pair
+ * @return a Pair that is templatized with the types of a and b
+ */
+ public static Pair create(A a, B b) {
+ return new Pair(a, b);
+ }
+}