Skip to content
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

Feature #1850: Add Overlay mtb:scale #5726

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import de.westnordost.streetcomplete.data.overlays.OverlayRegistry
import de.westnordost.streetcomplete.overlays.address.AddressOverlay
import de.westnordost.streetcomplete.overlays.buildings.BuildingsOverlay
import de.westnordost.streetcomplete.overlays.cycleway.CyclewayOverlay
import de.westnordost.streetcomplete.overlays.mtb_scale.MtbScaleOverlay
import de.westnordost.streetcomplete.overlays.places.PlacesOverlay
import de.westnordost.streetcomplete.overlays.sidewalk.SidewalkOverlay
import de.westnordost.streetcomplete.overlays.street_parking.StreetParkingOverlay
Expand Down Expand Up @@ -59,4 +60,5 @@ fun overlaysRegistry(
4 to PlacesOverlay(getFeature),
8 to ThingsOverlay(getFeature),
7 to BuildingsOverlay(),
9 to MtbScaleOverlay(),
))
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package de.westnordost.streetcomplete.overlays.mtb_scale

import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import de.westnordost.streetcomplete.R

import de.westnordost.streetcomplete.view.image_select.GroupableDisplayItem
import de.westnordost.streetcomplete.view.image_select.Item

enum class MtbScale(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency, the the title, description, image, ... should be put into extension functions in a separate file, to clearly separate the data from the resources. See e.g. SurfaceItem.kt

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't worry, it was to improve readability and performance on my side, but I'll modify it for you without any worries.

val osmValue: String,
@DrawableRes val imageResId: Int?,
@StringRes val titleResId: Int,
@StringRes val descriptionResId: Int,
val color:String,
) {
ZERO(
osmValue = "0",
imageResId = R.drawable.mtb_scale_0,
titleResId = R.string.overlay_mtbScale_zero,
descriptionResId = R.string.overlay_mtbScale_zero_description,
color = "#DBECC0"
),
ONE(
osmValue = "1",
imageResId = R.drawable.mtb_scale_1,
titleResId = R.string.overlay_mtbScale_one,
descriptionResId = R.string.overlay_mtbScale_one_description,
color = "#8CC63E"
),
TWO(
osmValue = "2",
imageResId = R.drawable.mtb_scale_2,
titleResId = R.string.overlay_mtbScale_two,
descriptionResId = R.string.overlay_mtbScale_two_description,
color = "#00B2E6"
),
THREE(
osmValue = "3",
imageResId = R.drawable.mtb_scale_3,
titleResId = R.string.overlay_mtbScale_three,
descriptionResId = R.string.overlay_mtbScale_three_description,
color = "#FECB1B"
),
FOUR(
osmValue = "4",
imageResId = R.drawable.mtb_scale_4,
titleResId = R.string.overlay_mtbScale_four,
descriptionResId = R.string.overlay_mtbScale_four_description,
color = "#F47922"
),
FIVE(
osmValue = "5",
imageResId = R.drawable.mtb_scale_5,
titleResId = R.string.overlay_mtbScale_five,
descriptionResId = R.string.overlay_mtbScale_five_description,
color = "#874D99"
),
SIX(
osmValue = "6",
imageResId = R.drawable.mtb_scale_6,
titleResId = R.string.overlay_mtbScale_six,
descriptionResId = R.string.overlay_mtbScale_six_description,
color = "#000000"
)
}

fun Collection<MtbScale>.toItems() = map { it.asItem() }

fun MtbScale.asItem(): GroupableDisplayItem<MtbScale> {
return Item(
this,
drawableId = imageResId,
titleId = titleResId,
descriptionId = descriptionResId
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package de.westnordost.streetcomplete.overlays.mtb_scale

import de.westnordost.streetcomplete.R
import de.westnordost.streetcomplete.data.osm.mapdata.Element
import de.westnordost.streetcomplete.data.osm.mapdata.MapDataWithGeometry
import de.westnordost.streetcomplete.data.osm.mapdata.filter
import de.westnordost.streetcomplete.data.user.achievements.EditTypeAchievement
import de.westnordost.streetcomplete.data.user.achievements.EditTypeAchievement.*

import de.westnordost.streetcomplete.overlays.AbstractOverlayForm
import de.westnordost.streetcomplete.overlays.Color
import de.westnordost.streetcomplete.overlays.Overlay
import de.westnordost.streetcomplete.overlays.PolylineStyle
import de.westnordost.streetcomplete.overlays.StrokeStyle
import de.westnordost.streetcomplete.overlays.Style

class MtbScaleOverlay : Overlay {

override val title = R.string.overlay_mtb_scale
override val icon = R.drawable.ic_overlay_mtb_scale
override val changesetComment = "Specify mtb scale"
override val wikiLink: String = "Key:mtb:scale"
override val achievements: List<EditTypeAchievement> =
listOf(BICYCLIST, OUTDOORS)

override fun getStyledElements(mapData: MapDataWithGeometry): Sequence<Pair<Element, Style>> =
mapData.filter(
"""
ways with
highway ~ path|track
and ( access !~ no|private or foot ~ yes|permissive|designated or bicycle ~ yes|permissive|designated)
and (!lit or lit = no)
and surface ~ "grass|sand|dirt|soil|fine_gravel|compacted|wood|gravel|pebblestone|rock|ground|earth|mud|woodchips|snow|ice|salt|stone"
"""
).map {
it to getStyle(it)
}

override fun createForm(element: Element?): AbstractOverlayForm = MtbScaleOverlayForm()

private fun getStyle(element: Element): Style {
val color = MtbScale.entries.find { it.osmValue == element.tags["mtb:scale"]?.take(1) }.color

return PolylineStyle(StrokeStyle(color))
}

private val MtbScale?.color
get() = when (this) {
null -> Color.DATA_REQUESTED
MtbScale.ZERO -> "#DBECC0"
MtbScale.ONE -> "#8CC63E"
MtbScale.TWO -> "#00B2E6"
MtbScale.THREE -> "#FECB1B"
MtbScale.FOUR -> "#F47922"
MtbScale.FIVE -> "#874D99"
MtbScale.SIX -> "#000000"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package de.westnordost.streetcomplete.overlays.mtb_scale

import android.content.Context
import android.os.Bundle
import android.view.View
import androidx.core.view.isGone
import com.russhwolf.settings.ObservableSettings
import de.westnordost.streetcomplete.R
import de.westnordost.streetcomplete.data.osm.edits.update_tags.StringMapChangesBuilder
import de.westnordost.streetcomplete.data.osm.edits.update_tags.UpdateElementTagsAction
import de.westnordost.streetcomplete.databinding.FragmentOverlayMtbScaleSelectBinding
import de.westnordost.streetcomplete.overlays.AbstractOverlayForm
import de.westnordost.streetcomplete.util.LastPickedValuesStore
import de.westnordost.streetcomplete.util.ktx.valueOfOrNull
import de.westnordost.streetcomplete.util.logs.Log
import de.westnordost.streetcomplete.view.setImage
import org.koin.android.ext.android.inject

class MtbScaleOverlayForm : AbstractOverlayForm() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of code here and in that ViewController. Why can this not inherit from AImageSelectOverlayForm like the WayLitForm?


override val contentLayoutResId = R.layout.fragment_overlay_mtb_scale_select
private val binding by contentViewBinding(FragmentOverlayMtbScaleSelectBinding::bind)

private var originalMtbScale: MtbScale? = null

private lateinit var mtbScaleCtrl: MtbScaleViewController
private val prefs: ObservableSettings by inject()
private lateinit var favs: LastPickedValuesStore<MtbScale>
private val lastPickedMtbScale: MtbScale?
get() = favs.get().firstOrNull()

override fun hasChanges(): Boolean = mtbScaleCtrl.value != originalMtbScale

override fun isFormComplete(): Boolean = mtbScaleCtrl.value != null

override fun onClickOk() {
val changesBuilder = StringMapChangesBuilder(element!!.tags)

if (mtbScaleCtrl.value != null) {
favs.add(mtbScaleCtrl.value!!)
}
changesBuilder["mtb:scale"] = mtbScaleCtrl.value!!.osmValue

applyEdit(UpdateElementTagsAction(element!!, changesBuilder.create()))
}


override fun onAttach(ctx: Context) {
super.onAttach(ctx)
favs = LastPickedValuesStore(
prefs,
key = javaClass.simpleName,
serialize = { it.name },
deserialize = { valueOfOrNull<MtbScale>(it) }
)
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

originalMtbScale = MtbScale.entries.find { it.osmValue == element!!.tags["mtb:scale"]?.take(1) }
Log.e("TEST","originalMtbScale $originalMtbScale ${element!!.tags["mtb:scale"]}")
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

mtbScaleCtrl = MtbScaleViewController(
selectButton = binding.selectButton.root,
selectedCellView = binding.selectButton.selectedCellView,
selectTextView = binding.selectButton.selectTextView,
)
mtbScaleCtrl.onInputChanged = { checkIsFormComplete() }

binding.lastPickedButton.isGone = lastPickedMtbScale == null
binding.lastPickedButton.setImage(lastPickedMtbScale?.asItem()?.image)
binding.lastPickedButton.setOnClickListener {
mtbScaleCtrl.value = lastPickedMtbScale
binding.lastPickedButton.isGone = true
checkIsFormComplete()
}

if (savedInstanceState != null) {
onLoadInstanceState(savedInstanceState)
} else {
initStateFromTags()
}
checkIsFormComplete()
}


override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putString(MTB_SCALE, mtbScaleCtrl.value?.osmValue)

}

private fun onLoadInstanceState(inState: Bundle) {
mtbScaleCtrl.value = MtbScale.entries.find { it.osmValue == inState.getString(MTB_SCALE) }
}

private fun initStateFromTags() {
mtbScaleCtrl.value = originalMtbScale
}

companion object {
private const val MTB_SCALE = "selected_mtb_scale"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package de.westnordost.streetcomplete.overlays.mtb_scale

import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.TextView
import androidx.core.view.children
import androidx.core.view.isGone
import de.westnordost.streetcomplete.R
import de.westnordost.streetcomplete.view.image_select.DisplayItem
import de.westnordost.streetcomplete.view.image_select.ImageListPickerDialog
import de.westnordost.streetcomplete.view.image_select.ItemViewHolder

class MtbScaleViewController(
private val selectButton: ViewGroup,
private val selectedCellView: ViewGroup,
private val selectTextView: TextView,
) {
var value: MtbScale?
set(value) {
selectedMtbScaleItem = value?.asItem()
}
get() {
return selectedMtbScaleItem?.value
}

private var selectedMtbScaleItem: DisplayItem<MtbScale>? = null
set(value) {
field = value
updateSelectedCell()
}

private val cellLayoutId: Int = R.layout.cell_labeled_icon_select
private val dialogCellLayoutId: Int = R.layout.cell_labeled_icon_select_mtb_scale
private val items: List<DisplayItem<MtbScale>> = MtbScale.entries.toItems()

var onInputChanged: (() -> Unit)? = null

init {
selectButton.setOnClickListener {
collectMtbScaleData { sacScale: MtbScale ->
selectedMtbScaleItem = sacScale.asItem()
onInputChanged?.invoke()
}
}

LayoutInflater.from(selectButton.context).inflate(cellLayoutId, selectedCellView, true)
selectButton.children.first().background = null
}

private fun updateSelectedCell() {
val item = selectedMtbScaleItem
selectTextView.isGone = item != null
selectedCellView.isGone = item == null
if (item != null) {
ItemViewHolder(selectedCellView).bind(item)
}
}

private fun collectMtbScaleData(callback: (MtbScale) -> Unit) {
ImageListPickerDialog(selectButton.context, items, dialogCellLayoutId, 1) { item ->
callback(item.value!!)
}.show()
}
}
Binary file added app/src/main/res/drawable-hdpi/mtb_scale_0.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable-hdpi/mtb_scale_1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable-hdpi/mtb_scale_2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable-hdpi/mtb_scale_3.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable-hdpi/mtb_scale_4.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable-hdpi/mtb_scale_5.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable-hdpi/mtb_scale_6.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable-mdpi/mtb_scale_0.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable-mdpi/mtb_scale_1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable-mdpi/mtb_scale_2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable-mdpi/mtb_scale_3.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable-mdpi/mtb_scale_4.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable-mdpi/mtb_scale_5.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable-mdpi/mtb_scale_6.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable-xhdpi/mtb_scale_0.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable-xhdpi/mtb_scale_1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable-xhdpi/mtb_scale_2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable-xhdpi/mtb_scale_3.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable-xhdpi/mtb_scale_4.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable-xhdpi/mtb_scale_5.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable-xhdpi/mtb_scale_6.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable-xxhdpi/mtb_scale_0.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable-xxhdpi/mtb_scale_1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable-xxhdpi/mtb_scale_2.jpg
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better images are a hard requirement. Minimum resolution is 384x384 px

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable-xxhdpi/mtb_scale_3.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/main/res/drawable-xxhdpi/mtb_scale_4.jpg
Binary file added app/src/main/res/drawable-xxhdpi/mtb_scale_5.jpg
Binary file added app/src/main/res/drawable-xxhdpi/mtb_scale_6.jpg
Loading