blob: 756c06439b47f89a63e8d96e171df9962f4e7754 [file] [log] [blame]
/*
* Copyright 2019 Google LLC
*
* 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
*
* https://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.mobileer.androidfxlab
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.SeekBar
import android.widget.TextView
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.switchmaterial.SwitchMaterial
import com.mobileer.androidfxlab.datatype.Effect
import java.util.*
import kotlin.concurrent.timerTask
import kotlin.math.max
import kotlin.math.min
object EffectsAdapter :
RecyclerView.Adapter<EffectsAdapter.EffectsHolder>() {
val effectList = arrayListOf<Effect>()
lateinit var mRecyclerView: RecyclerView
// This class adapts view in effect_view.xml for Effect class
class EffectsHolder(val parentView: ViewGroup) : RecyclerView.ViewHolder(parentView) {
private val layoutContainer: LinearLayout = parentView.findViewById(R.id.effectContainer)
lateinit var effect: Effect
private val floatFormat = "%4.2f"
private var index: Int = -1
fun bindEffect(bindedEffect: Effect, position: Int) {
effect = bindedEffect
index = position
// Clear all views
layoutContainer.removeAllViews()
View.inflate(layoutContainer.context,
R.layout.effect_header, layoutContainer)
val header: LinearLayout = layoutContainer.findViewById(R.id.effectHeader)
val dragHandleView: View = header.findViewById(R.id.cat_card_list_item_drag_handle)
val checkBoxView: SwitchMaterial = header.findViewById(R.id.effectEnabled)
val label: TextView = header.findViewById(R.id.effectLabel)
// Bind header views
label.text = effect.name
checkBoxView.isChecked = effectList[index].enable
checkBoxView.setOnCheckedChangeListener { _, checked ->
effectList[index].enable = checked
NativeInterface.enableEffectAt(checked, index)
}
dragHandleView.setOnTouchListener { _, event ->
if (event.action == MotionEvent.ACTION_DOWN) {
itemTouchHelper.startDrag(this@EffectsHolder)
return@setOnTouchListener true
}
false
}
header.setOnTouchListener { _, event ->
if (event.action == MotionEvent.ACTION_DOWN) {
itemTouchHelper.startSwipe(this@EffectsHolder)
return@setOnTouchListener true
}
false
}
// Add correct number of SeekBars based on effect
for (ind in effect.effectDescription.paramValues.withIndex()) {
val param = ind.value
val counter = ind.index
val view = View.inflate(layoutContainer.context,
R.layout.param_seek, null)
layoutContainer.addView(view)
val paramWrapper: LinearLayout = view.findViewById(R.id.paramWrapper)
val paramLabelView: TextView = paramWrapper.findViewById(R.id.paramLabel)
val minLabelView: TextView = paramWrapper.findViewById(R.id.minLabel)
val maxLabelView: TextView = paramWrapper.findViewById(R.id.maxLabel)
val curLabelView: TextView = paramWrapper.findViewById(R.id.curLabel)
val seekBar: SeekBar = paramWrapper.findViewById(R.id.seekBar)
paramLabelView.text = param.paramName
minLabelView.text = floatFormat.format(param.minValue)
maxLabelView.text = floatFormat.format(param.maxValue)
seekBar.progress =
((param.defaultValue - param.minValue) * 100 / (param.maxValue - param.minValue)).toInt()
curLabelView.text = floatFormat.format(param.defaultValue)
// Bind param listeners to effects
seekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
val paramInd = counter
var timer : Timer? = null
override fun onStartTrackingTouch(p0: SeekBar?) {}
override fun onStopTrackingTouch(seekbar: SeekBar?) {}
override fun onProgressChanged(
seekBar: SeekBar?, progress: Int, fromUser: Boolean
) {
val fracprogress =
((seekBar!!.progress / 100f) * (param.maxValue - param.minValue) + param.minValue)
curLabelView.text = floatFormat.format(fracprogress)
timer?.cancel()
timer = Timer()
timer?.schedule(timerTask { updateEffectParam(fracprogress) }, 100)
}
fun updateEffectParam(fracprogress : Float){
effectList[index].paramValues[paramInd] = fracprogress
NativeInterface.updateParamsAt(effect, index)
}
})
}
}
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): EffectsHolder {
val myView = LayoutInflater.from(parent.context)
.inflate(R.layout.effect_view, parent, false)
return EffectsHolder(myView as ViewGroup)
}
override fun onBindViewHolder(holder: EffectsHolder, position: Int) {
holder.bindEffect(effectList[position], position)
}
override fun getItemCount() = effectList.size
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
super.onAttachedToRecyclerView(recyclerView)
mRecyclerView = recyclerView
itemTouchHelper.attachToRecyclerView(mRecyclerView)
}
private val itemTouchHelper = ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(
ItemTouchHelper.UP or ItemTouchHelper.DOWN, ItemTouchHelper.RIGHT or ItemTouchHelper.LEFT
) {
var dragFrom = -1
var dragTo = -1
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
val fromPos = viewHolder.adapterPosition
val toPos = target.adapterPosition
if (dragFrom == -1) {
dragFrom = fromPos
}
dragTo = toPos
effectList.add(toPos, effectList.removeAt(fromPos))
recyclerView.adapter?.notifyItemMoved(fromPos, toPos)
return true
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
val position = viewHolder.adapterPosition
effectList.removeAt(position)
mRecyclerView.adapter?.notifyItemRemoved(position)
NativeInterface.removeEffectAt(position)
for (i in position until effectList.size) {
var holder = mRecyclerView.findViewHolderForAdapterPosition(i) as EffectsHolder
holder.bindEffect(holder.effect, i)
}
}
override fun clearView(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
) {
super.clearView(recyclerView, viewHolder)
if (dragFrom != -1 && dragTo != -1 && dragFrom != dragTo) {
rotateItems(dragFrom, dragTo)
}
dragFrom = -1
dragTo = -1
}
override fun isLongPressDragEnabled(): Boolean = false
override fun isItemViewSwipeEnabled(): Boolean = false
fun rotateItems(fromPos: Int, toPos: Int) {
val a = min(fromPos, toPos)
val b = max(fromPos, toPos)
for (i in a..b) {
var holder = mRecyclerView.findViewHolderForAdapterPosition(i) as EffectsHolder
holder.bindEffect(holder.effect, i)
}
NativeInterface.rotateEffectAt(fromPos, toPos)
}
})
}