comparison android/DWindows.kt @ 2526:d3f09b3f3703

Android: Initial dw_file_browse() implementation, still needs some work. Fix minor issues with the Calendar control.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Mon, 10 May 2021 02:01:28 +0000
parents d5c3c573c74e
children eec926265888
comparison
equal deleted inserted replaced
2525:9fd26efff9da 2526:d3f09b3f3703
1 package org.dbsoft.dwindows 1 package org.dbsoft.dwindows
2 2
3 import android.R.attr 3 import android.R
4 import android.app.Activity
5 import android.app.Dialog
4 import android.app.NotificationChannel 6 import android.app.NotificationChannel
5 import android.app.NotificationManager 7 import android.app.NotificationManager
6 import android.content.ClipData 8 import android.content.ClipData
7 import android.content.ClipboardManager 9 import android.content.ClipboardManager
8 import android.content.Context 10 import android.content.Context
43 import androidx.viewpager2.widget.ViewPager2 45 import androidx.viewpager2.widget.ViewPager2
44 import com.google.android.material.tabs.TabLayout 46 import com.google.android.material.tabs.TabLayout
45 import com.google.android.material.tabs.TabLayout.OnTabSelectedListener 47 import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
46 import com.google.android.material.tabs.TabLayoutMediator 48 import com.google.android.material.tabs.TabLayoutMediator
47 import java.io.File 49 import java.io.File
50 import java.io.FileFilter
48 import java.io.FileInputStream 51 import java.io.FileInputStream
49 import java.io.FileNotFoundException 52 import java.io.FileNotFoundException
50 import java.util.* 53 import java.util.*
51 import java.util.concurrent.locks.ReentrantLock 54 import java.util.concurrent.locks.ReentrantLock
52 55
232 inta: Int, 235 inta: Int,
233 intb: Int, 236 intb: Int,
234 intc: Int, 237 intc: Int,
235 intd: Int 238 intd: Int
236 ) 239 )
240 }
241
242 class DWFileChooser(private val activity: Activity) {
243 private val list: ListView = ListView(activity)
244 private val dialog: Dialog = Dialog(activity)
245 private var currentPath: File? = null
246
247 // filter on file extension
248 private var extension: String? = null
249 fun setExtension(extension: String?) {
250 this.extension = extension?.toLowerCase(Locale.ROOT)
251 }
252
253 // file selection event handling
254 interface FileSelectedListener {
255 fun fileSelected(file: File?)
256 }
257
258 fun setFileListener(fileListener: FileSelectedListener?): DWFileChooser {
259 this.fileListener = fileListener
260 return this
261 }
262
263 private var fileListener: FileSelectedListener? = null
264 fun showDialog() {
265 dialog.show()
266 }
267
268 /**
269 * Sort, filter and display the files for the given path.
270 */
271 private fun refresh(path: File?) {
272 currentPath = path
273 if (path != null) {
274 if (path.exists()) {
275 val dirs = path.listFiles { file -> file.isDirectory && file.canRead() }
276 val files = path.listFiles { file ->
277 if (!file.isDirectory) {
278 if (!file.canRead()) {
279 false
280 } else if (extension == null) {
281 true
282 } else {
283 file.name.toLowerCase(Locale.ROOT).endsWith(extension!!)
284 }
285 } else {
286 false
287 }
288 }
289
290 // convert to an array
291 var i = 0
292 val fileList: Array<String?>
293 var filecount = 0
294 var dircount = 0
295 if(files != null) {
296 filecount = files.size
297 }
298 if(dirs != null) {
299 dircount = dirs.size
300 }
301 if (path.parentFile == null) {
302 fileList = arrayOfNulls(dircount + filecount)
303 } else {
304 fileList = arrayOfNulls(dircount + filecount + 1)
305 fileList[i++] = PARENT_DIR
306 }
307 if(dirs != null) {
308 Arrays.sort(dirs)
309 for (dir in dirs) {
310 fileList[i++] = dir.name
311 }
312 }
313 if(files != null) {
314 Arrays.sort(files)
315 for (file in files) {
316 fileList[i++] = file.name
317 }
318 }
319
320 // refresh the user interface
321 dialog.setTitle(currentPath!!.path)
322 list.adapter = object : ArrayAdapter<Any?>(
323 activity,
324 R.layout.simple_list_item_1, fileList
325 ) {
326 override fun getView(pos: Int, view: View?, parent: ViewGroup): View {
327 val thisview = super.getView(pos, view, parent)
328 (thisview as TextView).isSingleLine = true
329 return thisview
330 }
331 }
332 }
333 }
334 }
335
336 /**
337 * Convert a relative filename into an actual File object.
338 */
339 private fun getChosenFile(fileChosen: String): File? {
340 return if (fileChosen == PARENT_DIR) {
341 currentPath!!.parentFile
342 } else {
343 File(currentPath, fileChosen)
344 }
345 }
346
347 companion object {
348 private const val PARENT_DIR = ".."
349 }
350
351 init {
352 list.onItemClickListener =
353 OnItemClickListener { parent, view, which, id ->
354 val fileChosen = list.getItemAtPosition(which) as String
355 val chosenFile: File? = getChosenFile(fileChosen)
356 if (chosenFile != null) {
357 if (chosenFile.isDirectory) {
358 refresh(chosenFile)
359 } else {
360 if (fileListener != null) {
361 fileListener!!.fileSelected(chosenFile)
362 }
363 dialog.dismiss()
364 }
365 }
366 }
367 dialog.setContentView(list)
368 dialog.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
369 refresh(Environment.getExternalStorageDirectory())
370 }
237 } 371 }
238 372
239 class DWindows : AppCompatActivity() { 373 class DWindows : AppCompatActivity() {
240 var firstWindow: Boolean = true 374 var firstWindow: Boolean = true
241 var windowLayout: LinearLayout? = null 375 var windowLayout: LinearLayout? = null
1553 } 1687 }
1554 1688
1555 fun debugMessage(text: String) 1689 fun debugMessage(text: String)
1556 { 1690 {
1557 Log.d(null, text) 1691 Log.d(null, text)
1692 }
1693
1694 fun fileBrowse(title: String, defpath: String?, ext: String?, flags: Int): String?
1695 {
1696 var retval: String? = null
1697
1698 waitOnUiThread {
1699 val fc = DWFileChooser(this)
1700 fc.setFileListener(object: DWFileChooser.FileSelectedListener {
1701 override fun fileSelected(file: File?) {
1702 // do something with the file
1703 retval = file!!.absolutePath
1704 throw java.lang.RuntimeException()
1705 }
1706 })
1707 if(ext != null) {
1708 fc.setExtension(ext)
1709 }
1710 fc.showDialog()
1711 }
1712
1713 // loop till a runtime exception is triggered.
1714 try {
1715 Looper.loop()
1716 } catch (e2: RuntimeException) {
1717 }
1718
1719 return retval
1558 } 1720 }
1559 1721
1560 fun messageBox(title: String, body: String, flags: Int): Int 1722 fun messageBox(title: String, body: String, flags: Int): Int
1561 { 1723 {
1562 var retval: Int = 0 1724 var retval: Int = 0