• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright  2019 Google LLC
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     https://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.mobileer.androidfxlab
18 
19 import android.view.LayoutInflater
20 import android.view.MotionEvent
21 import android.view.View
22 import android.view.ViewGroup
23 import android.widget.LinearLayout
24 import android.widget.SeekBar
25 import android.widget.TextView
26 import androidx.recyclerview.widget.ItemTouchHelper
27 import androidx.recyclerview.widget.RecyclerView
28 import com.google.android.material.switchmaterial.SwitchMaterial
29 import com.mobileer.androidfxlab.datatype.Effect
30 import java.util.*
31 import kotlin.concurrent.timerTask
32 import kotlin.math.max
33 import kotlin.math.min
34 
35 object EffectsAdapter :
36     RecyclerView.Adapter<EffectsAdapter.EffectsHolder>() {
37     val effectList = arrayListOf<Effect>()
38     lateinit var mRecyclerView: RecyclerView
39 
40     // This class adapts view in effect_view.xml for Effect class
41     class EffectsHolder(val parentView: ViewGroup) : RecyclerView.ViewHolder(parentView) {
42         private val layoutContainer: LinearLayout = parentView.findViewById(R.id.effectContainer)
43         lateinit var effect: Effect
44         private val floatFormat = "%4.2f"
45         private var index: Int = -1
46         fun bindEffect(bindedEffect: Effect, position: Int) {
47             effect = bindedEffect
48             index = position
49             // Clear all views
50             layoutContainer.removeAllViews()
51             View.inflate(layoutContainer.context,
52                 R.layout.effect_header, layoutContainer)
53             val header: LinearLayout = layoutContainer.findViewById(R.id.effectHeader)
54             val dragHandleView: View = header.findViewById(R.id.cat_card_list_item_drag_handle)
55             val checkBoxView: SwitchMaterial = header.findViewById(R.id.effectEnabled)
56             val label: TextView = header.findViewById(R.id.effectLabel)
57             // Bind header views
58             label.text = effect.name
59             checkBoxView.isChecked = effectList[index].enable
60             checkBoxView.setOnCheckedChangeListener { _, checked ->
61                 effectList[index].enable = checked
62                 NativeInterface.enableEffectAt(checked, index)
63             }
64             dragHandleView.setOnTouchListener { _, event ->
65                 if (event.action == MotionEvent.ACTION_DOWN) {
66                     itemTouchHelper.startDrag(this@EffectsHolder)
67                     return@setOnTouchListener true
68                 }
69                 false
70             }
71             header.setOnTouchListener { _, event ->
72                 if (event.action == MotionEvent.ACTION_DOWN) {
73                     itemTouchHelper.startSwipe(this@EffectsHolder)
74                     return@setOnTouchListener true
75                 }
76                 false
77             }
78             // Add correct number of SeekBars based on effect
79             for (ind in effect.effectDescription.paramValues.withIndex()) {
80                 val param = ind.value
81                 val counter = ind.index
82                 val view = View.inflate(layoutContainer.context,
83                     R.layout.param_seek, null)
84                 layoutContainer.addView(view)
85                 val paramWrapper: LinearLayout = view.findViewById(R.id.paramWrapper)
86                 val paramLabelView: TextView = paramWrapper.findViewById(R.id.paramLabel)
87                 val minLabelView: TextView = paramWrapper.findViewById(R.id.minLabel)
88                 val maxLabelView: TextView = paramWrapper.findViewById(R.id.maxLabel)
89                 val curLabelView: TextView = paramWrapper.findViewById(R.id.curLabel)
90                 val seekBar: SeekBar = paramWrapper.findViewById(R.id.seekBar)
91                 paramLabelView.text = param.paramName
92                 minLabelView.text = floatFormat.format(param.minValue)
93                 maxLabelView.text = floatFormat.format(param.maxValue)
94                 seekBar.progress =
95                     ((param.defaultValue - param.minValue) * 100 / (param.maxValue - param.minValue)).toInt()
96                 curLabelView.text = floatFormat.format(param.defaultValue)
97                 // Bind param listeners to effects
98                 seekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
99                     val paramInd = counter
100                     var timer : Timer? = null
101 
102                     override fun onStartTrackingTouch(p0: SeekBar?) {}
103 
104                     override fun onStopTrackingTouch(seekbar: SeekBar?) {}
105 
106                     override fun onProgressChanged(
107                         seekBar: SeekBar?, progress: Int, fromUser: Boolean
108                     ) {
109                         val fracprogress =
110                             ((seekBar!!.progress / 100f) * (param.maxValue - param.minValue) + param.minValue)
111                         curLabelView.text = floatFormat.format(fracprogress)
112 
113                         timer?.cancel()
114                         timer = Timer()
115                         timer?.schedule(timerTask { updateEffectParam(fracprogress) }, 100)
116                     }
117 
118                     fun updateEffectParam(fracprogress : Float){
119                         effectList[index].paramValues[paramInd] = fracprogress
120                         NativeInterface.updateParamsAt(effect, index)
121                     }
122                 })
123             }
124         }
125 
126     }
127 
128     override fun onCreateViewHolder(
129         parent: ViewGroup,
130         viewType: Int
131     ): EffectsHolder {
132         val myView = LayoutInflater.from(parent.context)
133             .inflate(R.layout.effect_view, parent, false)
134         return EffectsHolder(myView as ViewGroup)
135     }
136 
137     override fun onBindViewHolder(holder: EffectsHolder, position: Int) {
138         holder.bindEffect(effectList[position], position)
139     }
140 
141     override fun getItemCount() = effectList.size
142 
143     override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
144         super.onAttachedToRecyclerView(recyclerView)
145         mRecyclerView = recyclerView
146         itemTouchHelper.attachToRecyclerView(mRecyclerView)
147     }
148 
149     private val itemTouchHelper = ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(
150         ItemTouchHelper.UP or ItemTouchHelper.DOWN, ItemTouchHelper.RIGHT or ItemTouchHelper.LEFT
151     ) {
152 
153         var dragFrom = -1
154         var dragTo = -1
155         override fun onMove(
156             recyclerView: RecyclerView,
157             viewHolder: RecyclerView.ViewHolder,
158             target: RecyclerView.ViewHolder
159         ): Boolean {
160 
161             val fromPos = viewHolder.adapterPosition
162             val toPos = target.adapterPosition
163             if (dragFrom == -1) {
164                 dragFrom = fromPos
165             }
166             dragTo = toPos
167             effectList.add(toPos, effectList.removeAt(fromPos))
168             recyclerView.adapter?.notifyItemMoved(fromPos, toPos)
169             return true
170         }
171 
172         override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
173             val position = viewHolder.adapterPosition
174             effectList.removeAt(position)
175             mRecyclerView.adapter?.notifyItemRemoved(position)
176             NativeInterface.removeEffectAt(position)
177             for (i in position until effectList.size) {
178                 var holder = mRecyclerView.findViewHolderForAdapterPosition(i) as EffectsHolder
179                 holder.bindEffect(holder.effect, i)
180             }
181         }
182 
183         override fun clearView(
184             recyclerView: RecyclerView,
185             viewHolder: RecyclerView.ViewHolder
186         ) {
187             super.clearView(recyclerView, viewHolder)
188             if (dragFrom != -1 && dragTo != -1 && dragFrom != dragTo) {
189                 rotateItems(dragFrom, dragTo)
190             }
191             dragFrom = -1
192             dragTo = -1
193         }
194 
195         override fun isLongPressDragEnabled(): Boolean = false
196         override fun isItemViewSwipeEnabled(): Boolean = false
197 
198         fun rotateItems(fromPos: Int, toPos: Int) {
199             val a = min(fromPos, toPos)
200             val b = max(fromPos, toPos)
201             for (i in a..b) {
202                 var holder = mRecyclerView.findViewHolderForAdapterPosition(i) as EffectsHolder
203                 holder.bindEffect(holder.effect, i)
204             }
205             NativeInterface.rotateEffectAt(fromPos, toPos)
206         }
207     })
208 
209 }
210