-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve selecting shapes/traces #5463
Changes from all commits
109b06c
cba7df6
4b7d9ec
ad4c92e
7c9628d
3ca60fa
8800e18
7ced5df
128f691
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,14 +56,15 @@ class SelectionMapFragment( | |
@Inject | ||
lateinit var permissionsChecker: PermissionsChecker | ||
|
||
private val selectedFeatureViewModel by viewModels<SelectedFeatureViewModel>() | ||
private val selectedItemViewModel by viewModels<SelectedItemViewModel>() | ||
|
||
private lateinit var map: MapFragment | ||
private lateinit var summarySheetBehavior: BottomSheetBehavior<*> | ||
private lateinit var summarySheet: SelectionSummarySheet | ||
private lateinit var bottomSheetCallback: BottomSheetCallback | ||
|
||
private val itemsByFeatureId: MutableMap<Int, MappableSelectItem> = mutableMapOf() | ||
private val featureIdsByItemId: MutableMap<Long, Int> = mutableMapOf() | ||
|
||
/** | ||
* Points to be mapped. Note: kept separately from [.itemsByFeatureId] so we can | ||
|
@@ -234,10 +235,10 @@ class SelectionMapFragment( | |
|
||
bottomSheetCallback = object : BottomSheetCallback() { | ||
override fun onStateChanged(onStateChangedbottomSheet: View, newState: Int) { | ||
val selectedFeatureId = selectedFeatureViewModel.getSelectedFeatureId() | ||
if (newState == STATE_HIDDEN && selectedFeatureId != null) { | ||
selectedFeatureViewModel.setSelectedFeatureId(null) | ||
resetIcon(selectedFeatureId) | ||
val selectedItem = selectedItemViewModel.getSelectedItem() | ||
if (newState == STATE_HIDDEN && selectedItem != null) { | ||
selectedItemViewModel.setSelectedItem(null) | ||
resetIcon(selectedItem) | ||
|
||
closeSummarySheet.isEnabled = false | ||
} else { | ||
|
@@ -265,20 +266,25 @@ class SelectionMapFragment( | |
} | ||
|
||
private fun onFeatureClicked(featureId: Int, maintainZoom: Boolean = true) { | ||
val selectedFeatureId = selectedFeatureViewModel.getSelectedFeatureId() | ||
if (selectedFeatureId != null && selectedFeatureId != featureId) { | ||
resetIcon(selectedFeatureId) | ||
} | ||
|
||
val item = itemsByFeatureId[featureId] | ||
val selectedItem = selectedItemViewModel.getSelectedItem() | ||
|
||
if (item != null) { | ||
if (!skipSummary) { | ||
val point = item.points[0] | ||
if (selectedItem != null && selectedItem.id != item.id) { | ||
resetIcon(selectedItem) | ||
} | ||
|
||
if (maintainZoom) { | ||
map.zoomToPoint(MapPoint(point.latitude, point.longitude), map.zoom, true) | ||
if (!skipSummary) { | ||
if (item.points.size > 1) { | ||
map.zoomToBoundingBox(item.points, 0.8, true) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We're doing a "zoom to fit" when selecting a shape/trace rather than maintaining the user zoom. I think that addresses some of the feedback around it being hard to see which item is selected (without having to deal with color/shape changes), but as @lognaturel has pointed out to me, it isn't great in situations where the user taps on the wrong item and then loses context. |
||
} else { | ||
map.zoomToPoint(MapPoint(point.latitude, point.longitude), true) | ||
val point = item.points[0] | ||
|
||
if (maintainZoom) { | ||
map.zoomToPoint(MapPoint(point.latitude, point.longitude), map.zoom, true) | ||
} else { | ||
map.zoomToPoint(MapPoint(point.latitude, point.longitude), true) | ||
} | ||
} | ||
|
||
map.setMarkerIcon( | ||
|
@@ -298,7 +304,7 @@ class SelectionMapFragment( | |
} | ||
) | ||
|
||
selectedFeatureViewModel.setSelectedFeatureId(featureId) | ||
selectedItemViewModel.setSelectedItem(item) | ||
} else { | ||
parentFragmentManager.setFragmentResult( | ||
REQUEST_SELECT_ITEM, | ||
|
@@ -323,10 +329,13 @@ class SelectionMapFragment( | |
|
||
val previouslySelectedItem = | ||
itemsByFeatureId.filter { it.value.selected }.map { it.key }.firstOrNull() | ||
val selectedFeatureId = selectedFeatureViewModel.getSelectedFeatureId() | ||
val selectedItem = selectedItemViewModel.getSelectedItem() | ||
|
||
if (selectedFeatureId != null) { | ||
onFeatureClicked(selectedFeatureId) | ||
if (selectedItem != null) { | ||
val featureId = featureIdsByItemId[selectedItem.id] | ||
if (featureId != null) { | ||
onFeatureClicked(featureId) | ||
} | ||
} else if (previouslySelectedItem != null) { | ||
onFeatureClicked(previouslySelectedItem, maintainZoom = false) | ||
} else if (!map.hasCenter()) { | ||
|
@@ -341,12 +350,14 @@ class SelectionMapFragment( | |
} | ||
} | ||
|
||
private fun resetIcon(selectedFeatureId: Int) { | ||
val item = itemsByFeatureId[selectedFeatureId]!! | ||
map.setMarkerIcon( | ||
selectedFeatureId, | ||
MarkerIconDescription(item.smallIcon, item.color, item.symbol) | ||
) | ||
private fun resetIcon(selectedItem: MappableSelectItem) { | ||
val featureId = featureIdsByItemId[selectedItem.id] | ||
if (featureId != null) { | ||
map.setMarkerIcon( | ||
featureId, | ||
MarkerIconDescription(selectedItem.smallIcon, selectedItem.color, selectedItem.symbol) | ||
) | ||
} | ||
} | ||
|
||
/** | ||
|
@@ -376,8 +387,9 @@ class SelectionMapFragment( | |
ids + map.addPoly(item.points, false, false) | ||
} | ||
|
||
items.zip(pointIds + traceIds).forEach { (item, featureId) -> | ||
(singlePoints + traces).zip(pointIds + traceIds).forEach { (item, featureId) -> | ||
itemsByFeatureId[featureId] = item | ||
featureIdsByItemId[item.id] = featureId | ||
points.addAll(item.points) | ||
} | ||
|
||
|
@@ -391,16 +403,16 @@ class SelectionMapFragment( | |
} | ||
} | ||
|
||
internal class SelectedFeatureViewModel : ViewModel() { | ||
internal class SelectedItemViewModel : ViewModel() { | ||
|
||
private var selectedFeatureId: Int? = null | ||
private var selectedItem: MappableSelectItem? = null | ||
|
||
fun getSelectedFeatureId(): Int? { | ||
return selectedFeatureId | ||
fun getSelectedItem(): MappableSelectItem? { | ||
return selectedItem | ||
} | ||
|
||
fun setSelectedFeatureId(itemId: Int?) { | ||
selectedFeatureId = itemId | ||
fun setSelectedItem(item: MappableSelectItem?) { | ||
selectedItem = item | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It maybe feels excessive to have two
Map
indexes here, but otherwise we'd need to do linear searches on several click events, and we build these maps in a loop we're already performing.