OSDN Git Service

データ送信時のintentの変更(強化)検討中。
[gokigen/JoggingTimer.git] / wear / src / main / java / net / osdn / gokigen / joggingtimer / recorddetail / DetailActivity.kt
1 package net.osdn.gokigen.joggingtimer.recorddetail
2
3 import android.annotation.SuppressLint
4 import android.os.Bundle
5 import android.util.Log
6 import android.view.MenuItem
7 import android.view.MotionEvent
8 import android.view.ViewConfiguration
9 import android.widget.Toast
10 import androidx.appcompat.app.AppCompatActivity
11 import androidx.core.view.InputDeviceCompat
12 import androidx.core.view.MotionEventCompat
13 import androidx.core.view.ViewConfigurationCompat
14 import androidx.recyclerview.widget.DividerItemDecoration
15 import androidx.wear.ambient.AmbientModeSupport
16 import androidx.wear.widget.WearableLinearLayoutManager
17 import androidx.wear.widget.WearableRecyclerView
18 import androidx.wear.widget.drawer.WearableActionDrawerView
19 import androidx.wear.widget.drawer.WearableNavigationDrawerView
20 import net.osdn.gokigen.joggingtimer.R
21 import net.osdn.gokigen.joggingtimer.utilities.CreateModelData.IEditedModelDataCallback
22 import net.osdn.gokigen.joggingtimer.utilities.DataEditDialog
23 import net.osdn.gokigen.joggingtimer.utilities.SetReferenceDialog
24 import net.osdn.gokigen.joggingtimer.utilities.SetReferenceDialog.SetReferenceCallback
25 import kotlin.math.roundToInt
26
27 class DetailActivity : AppCompatActivity(),
28     RecordDetailSetup.IDatabaseReadyNotify, MenuItem.OnMenuItemClickListener,
29     DataEditDialog.Callback, IEditedModelDataCallback, DetailSelectionMenuAdapter.ISelectedMenu,
30     AmbientModeSupport.AmbientCallbackProvider, SetReferenceCallback
31 {
32     private var detailAdapter: RecordDetailAdapter? = null
33     private var setupper: RecordDetailSetup? = null
34     private var actionDrawerView: WearableActionDrawerView? = null
35
36     override fun onCreate(savedInstanceState: Bundle?)
37     {
38         super.onCreate(savedInstanceState)
39         Log.v(TAG, "onCreate()")
40         setContentView(R.layout.activity_detail)
41
42         try
43         {
44             val ambientController = AmbientModeSupport.attach(this)
45             ambientController.setAutoResumeEnabled(true)
46         }
47         catch (e: Exception)
48         {
49             e.printStackTrace()
50         }
51
52         try
53         {
54             val naviView = findViewById<WearableNavigationDrawerView>(R.id.top_navigation_drawer)
55             val menuAdapter = DetailSelectionMenuAdapter(this, this)
56             naviView.setAdapter(menuAdapter)
57             naviView.addOnItemSelectedListener(menuAdapter)
58             val view = findViewById<WearableRecyclerView>(R.id.recycler_detail_view)
59             detailAdapter = RecordDetailAdapter()
60             val layoutManager = WearableLinearLayoutManager(this)
61
62             view.isCircularScrollingGestureEnabled = false
63             val dividerDecoration = DividerItemDecoration(view.context, layoutManager.orientation)
64             view.addItemDecoration(dividerDecoration)
65             view.layoutManager = layoutManager
66             view.adapter = detailAdapter
67         }
68         catch (e: Exception)
69         {
70             e.printStackTrace()
71             detailAdapter = null
72         }
73
74         try
75         {
76             // Bottom Action Drawer
77             actionDrawerView = findViewById(R.id.bottom_action_drawer)
78             actionDrawerView?.controller?.peekDrawer()
79             actionDrawerView?.setOnMenuItemClickListener(this)
80         }
81         catch (e: Exception)
82         {
83             e.printStackTrace()
84         }
85     }
86
87     override fun onResume()
88     {
89         super.onResume()
90         Log.v(TAG, "onResume() ")
91     }
92
93     override fun onPause()
94     {
95         super.onPause()
96         Log.v(TAG, "onPause()")
97     }
98
99     public override fun onStart()
100     {
101         super.onStart()
102         try
103         {
104             val indexId = intent.getLongExtra(INTENT_EXTRA_DATA_ID, -1)
105             Log.v(TAG, "onResume() $indexId")
106             setupper = RecordDetailSetup(this, indexId, this, detailAdapter, this)
107             setupper?.setup()
108         }
109         catch (e: Exception)
110         {
111             e.printStackTrace()
112         }
113     }
114
115     public override fun onStop()
116     {
117         super.onStop()
118         Log.v(TAG, "onStop()")
119         try
120         {
121             setupper?.closeDatabase()
122             setupper = null
123         }
124         catch (e: Exception)
125         {
126             e.printStackTrace()
127         }
128         System.gc()
129     }
130
131     override fun onGenericMotionEvent(ev: MotionEvent?): Boolean
132     {
133         try
134         {
135             if ((ev?.action == MotionEvent.ACTION_SCROLL)&& (ev.isFromSource(InputDeviceCompat.SOURCE_ROTARY_ENCODER)))
136             {
137                 // ロータリー入力でスクロールする
138                 // Log.v(TAG, "Rotary Encoder Input")
139                 val view = findViewById<WearableRecyclerView>(R.id.recycler_detail_view)
140                 val delta = -ev.getAxisValue(MotionEventCompat.AXIS_SCROLL) *
141                         ViewConfigurationCompat.getScaledVerticalScrollFactor(ViewConfiguration.get(this), this)
142                 view.scrollBy(0, delta.roundToInt())
143                 return (true)
144             }
145         }
146         catch (e: Exception)
147         {
148             e.printStackTrace()
149         }
150         return (super.onGenericMotionEvent(ev))
151     }
152
153     override fun databaseSetupFinished(result: Boolean)
154     {
155         Log.v(TAG, "databaseSetupFinished() : $result")
156     }
157
158     override fun updatedIndexData(isIconOnly: Boolean)
159     {
160         Log.v(TAG, "selectedReferenceData() : $isIconOnly")
161         runOnUiThread {
162             try
163             {
164                 val title: String = if (isIconOnly) {
165                     getString(R.string.action_set_reference)
166                 } else {
167                     getString(R.string.action_edited_data)
168                 }
169                 val toast =
170                     Toast.makeText(applicationContext, title, Toast.LENGTH_SHORT)
171                 toast.show()
172             }
173             catch (e: Exception)
174             {
175                 e.printStackTrace()
176             }
177         }
178     }
179
180     override fun onMenuItemClick(item: MenuItem): Boolean
181     {
182         Log.v(TAG, "onMenuItemClick(): $item")
183         val itemId = item.itemId
184         try
185         {
186             actionDrawerView?.controller?.closeDrawer()
187         }
188         catch (e: Exception)
189         {
190             e.printStackTrace()
191         }
192         return (itemSelected(itemId))
193     }
194
195     private fun itemSelected(itemId: Int): Boolean
196     {
197         var ret = false
198         when (itemId) {
199             R.id.menu_edit_title -> {
200                 // タイトルの編集
201                 var title = ""
202                 var iconId = R.drawable.ic_android_black_24dp
203                 val data = setupper?.getEditIndexData()
204                 if (data != null)
205                 {
206                     iconId = data.icon()
207                     title = data.title()
208                 }
209                 val dialog = DataEditDialog.newInstance(iconId, title, this)
210                 val manager = supportFragmentManager
211                 dialog.show(manager, "dialog")
212                 true.also { ret = it }
213             }
214             R.id.menu_set_reference -> {
215                 // 基準値の設定ダイアログを表示する
216                 val callback: SetReferenceCallback = this
217                 runOnUiThread {
218                     try {
219                         // 基準値設定ダイアログを表示する
220                         val dialog = SetReferenceDialog.newInstance(callback)
221                         val manager = supportFragmentManager
222                         dialog.show(manager, "dialog")
223                     } catch (e: Exception) {
224                         e.printStackTrace()
225                     }
226                 }
227                 true.also { ret = it }
228             }
229             R.id.menu_share_data -> {
230                 // 現在のデータを共有する
231                 setupper?.shareTheData(detailAdapter)
232                 true.also { ret = it }
233             }
234         }
235         return ret
236     }
237
238     override fun dataEdited(iconId: Int, title: String)
239     {
240         Log.v(TAG, "iconId : $iconId title : '$title'")
241         try
242         {
243             setupper?.setEditIndexData(title, iconId)
244             val view = findViewById<WearableRecyclerView>(R.id.recycler_detail_view)
245             view.postInvalidate()
246         }
247         catch (e: Exception)
248         {
249             e.printStackTrace()
250         }
251     }
252
253     private fun updateScreen()
254     {
255         try
256         {
257             val view = findViewById<WearableRecyclerView>(R.id.recycler_detail_view)
258             view.postInvalidate()
259         }
260         catch (e: Exception)
261         {
262             e.printStackTrace()
263         }
264     }
265
266     override fun cancelled()
267     {
268         updateScreen()
269     }
270
271     @SuppressLint("NotifyDataSetChanged")
272     override fun editedModelData(
273         indexId: Long,
274         detailId: Long,
275         lapCount: Int,
276         prevTime: Long,
277         newTime: Long
278     )
279     {
280         Log.v(
281             TAG,
282             "editedModelData() $indexId $detailId $lapCount ($prevTime -> $newTime)"
283         )
284         if (detailAdapter == null)
285         {
286             return
287         }
288         val diffTime = newTime - prevTime
289         val count = detailAdapter?.itemCount ?: 0
290         if (count > 1)
291         {
292             var totalTime: Long = 0
293             val modTime = diffTime * -1 / (count - 1)
294             for (index in 1..count)
295             {
296                 val record = detailAdapter?.getRecord(index - 1)
297                 totalTime = if (lapCount == index) {
298                     record?.addModifiedTime(diffTime, totalTime) ?: 0
299                 } else {
300                     record?.addModifiedTime(modTime, totalTime) ?: 0
301                 }
302                 detailAdapter?.notifyItemChanged(index - 1)
303             }
304             try
305             {
306                 val thread = Thread {
307                     if (setupper != null)
308                     {
309                         setupper?.updateDatabaseRecord(detailAdapter!!)
310                     }
311                 }
312                 thread.start()
313             }
314             catch (e: Exception)
315             {
316                 e.printStackTrace()
317             }
318         }
319         try
320         {
321             detailAdapter?.notifyDataSetChanged()
322         }
323         catch (e: Exception)
324         {
325             e.printStackTrace()
326         }
327     }
328
329     override fun selectedMenu(itemId: Int)
330     {
331         itemSelected(itemId)
332     }
333
334     override fun getAmbientCallback(): AmbientModeSupport.AmbientCallback
335     {
336         return object : AmbientModeSupport.AmbientCallback() {
337             override fun onEnterAmbient(ambientDetails: Bundle)
338             {
339                 Log.v(TAG, "onEnterAmbient()")
340             }
341         }
342     }
343
344     override fun confirmed(id: Int)
345     {
346         // 現在のデータを基準値として設定する
347         Log.v(TAG, " SET REFERENCE DATA ID: $id")
348         setupper?.setReferenceData(id)
349     }
350
351     companion object {
352         private val TAG = DetailActivity::class.java.simpleName
353         const val INTENT_EXTRA_DATA_ID = "Detail.dataId"
354     }
355 }