Mercurial > dwindows
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 |