Mercurial > dwindows
comparison android/DWindows.kt @ 2665:aca4b56f50dd
Android: Attempt at multi-window support using ViewPager2.
I tried initially with FragmentContainerView but ran into issues.
Seems to be having issues with nested ViewPager2s used in the notebooks.
Still needs a lot o work but the core is there now.
author | bsmith@81767d24-ef19-dc11-ae90-00e081727c95 |
---|---|
date | Tue, 12 Oct 2021 23:04:13 +0000 |
parents | 3a14d7fd4b99 |
children | 4f2d433747e2 |
comparison
equal
deleted
inserted
replaced
2664:b0712a3debe2 | 2665:aca4b56f50dd |
---|---|
766 return rowView | 766 return rowView |
767 } | 767 } |
768 } | 768 } |
769 | 769 |
770 class DWindows : AppCompatActivity() { | 770 class DWindows : AppCompatActivity() { |
771 var firstWindow: Boolean = true | 771 var windowLayout: ViewPager2? = null |
772 var windowLayout: LinearLayout? = null | |
773 var threadLock = ReentrantLock() | 772 var threadLock = ReentrantLock() |
774 var threadCond = threadLock.newCondition() | 773 var threadCond = threadLock.newCondition() |
775 var notificationID: Int = 0 | 774 var notificationID: Int = 0 |
776 var darkMode: Int = -1 | 775 var darkMode: Int = -1 |
777 var lastClickView: View? = null | 776 var lastClickView: View? = null |
778 private var paint = Paint() | 777 private var paint = Paint() |
779 private var bgcolor: Int? = null | 778 private var bgcolor: Int? = null |
780 private var menuBar: DWMenu? = null | 779 private var menuBar: DWMenu? = null |
781 private var defaultItem: View? = null | |
782 private var fileURI: Uri? = null | 780 private var fileURI: Uri? = null |
783 private var fileLock = ReentrantLock() | 781 private var fileLock = ReentrantLock() |
784 private var fileCond = threadLock.newCondition() | 782 private var fileCond = threadLock.newCondition() |
783 // Lists of data for our Windows | |
784 private var windowTitles = mutableListOf<String?>() | |
785 private var windowMenuBars = mutableListOf<DWMenu?>() | |
786 private var windowStyles = mutableListOf<Int>() | |
787 private var windowDefault = mutableListOf<View?>() | |
785 | 788 |
786 // Our version of runOnUiThread that waits for execution | 789 // Our version of runOnUiThread that waits for execution |
787 fun waitOnUiThread(runnable: Runnable) | 790 fun waitOnUiThread(runnable: Runnable) |
788 { | 791 { |
789 if(Looper.myLooper() == Looper.getMainLooper()) { | 792 if(Looper.myLooper() == Looper.getMainLooper()) { |
878 // Extract any non-resource assets to the cache directory | 881 // Extract any non-resource assets to the cache directory |
879 // So that our C code can access them as files, like on | 882 // So that our C code can access them as files, like on |
880 // other Dynamic Windows platforms | 883 // other Dynamic Windows platforms |
881 extractAssets() | 884 extractAssets() |
882 | 885 |
886 // Setup our ViewPager2 as our activty window container | |
887 windowLayout = ViewPager2(this) | |
888 windowLayout!!.id = View.generateViewId() | |
889 windowLayout!!.adapter = DWTabViewPagerAdapter() | |
890 windowLayout!!.isUserInputEnabled = false | |
891 windowLayout!!.layoutParams = | |
892 ViewGroup.LayoutParams( | |
893 ViewGroup.LayoutParams.MATCH_PARENT, | |
894 ViewGroup.LayoutParams.MATCH_PARENT | |
895 ) | |
896 | |
883 // Initialize the Dynamic Windows code... | 897 // Initialize the Dynamic Windows code... |
884 // This will start a new thread that calls the app's dwmain() | 898 // This will start a new thread that calls the app's dwmain() |
885 dwindowsInit(s, c, this.getPackageName()) | 899 dwindowsInit(s, c, this.getPackageName()) |
886 } | 900 } |
887 | 901 |
896 | 910 |
897 // Send a DW_SIGNAL_CONFIGURE on orientation change | 911 // Send a DW_SIGNAL_CONFIGURE on orientation change |
898 if(windowLayout != null) { | 912 if(windowLayout != null) { |
899 val width: Int = windowLayout!!.width | 913 val width: Int = windowLayout!!.width |
900 val height: Int = windowLayout!!.height | 914 val height: Int = windowLayout!!.height |
901 | 915 val adapter: DWTabViewPagerAdapter = windowLayout!!.adapter as DWTabViewPagerAdapter |
902 eventHandlerInt(windowLayout as View, DWEvent.CONFIGURE, width, height, 0, 0) | 916 val window = adapter.viewList[windowLayout!!.currentItem] |
917 | |
918 eventHandlerInt(window, DWEvent.CONFIGURE, width, height, 0, 0) | |
903 } | 919 } |
904 } | 920 } |
905 | 921 |
906 override fun onCreateOptionsMenu(menu: Menu?): Boolean { | 922 override fun onCreateOptionsMenu(menu: Menu?): Boolean { |
907 if(menuBar == null) { | 923 if(menuBar == null) { |
1044 } | 1060 } |
1045 } | 1061 } |
1046 } | 1062 } |
1047 | 1063 |
1048 fun windowNew(title: String, style: Int): LinearLayout? { | 1064 fun windowNew(title: String, style: Int): LinearLayout? { |
1049 if (firstWindow) { | 1065 var window: LinearLayout? = null |
1066 | |
1067 if(windowLayout != null) { | |
1050 waitOnUiThread { | 1068 waitOnUiThread { |
1051 val dataArrayMap = SimpleArrayMap<String, Long>() | 1069 val dataArrayMap = SimpleArrayMap<String, Long>() |
1052 windowLayout = LinearLayout(this) | 1070 val adapter: DWTabViewPagerAdapter = windowLayout!!.adapter as DWTabViewPagerAdapter |
1053 | 1071 |
1054 windowLayout!!.visibility = View.GONE | |
1055 windowLayout!!.tag = dataArrayMap | |
1056 setContentView(windowLayout) | 1072 setContentView(windowLayout) |
1057 this.title = title | 1073 |
1058 // For now we just return our DWindows' main activity layout... | 1074 window = LinearLayout(this) |
1059 // in the future, later calls should create new activities | 1075 window!!.visibility = View.GONE |
1060 firstWindow = false | 1076 window!!.tag = dataArrayMap |
1061 } | 1077 window!!.layoutParams = |
1062 return windowLayout | 1078 LinearLayout.LayoutParams( |
1063 } | 1079 LinearLayout.LayoutParams.MATCH_PARENT, |
1064 return null | 1080 LinearLayout.LayoutParams.MATCH_PARENT |
1081 ) | |
1082 | |
1083 // Update our window list | |
1084 adapter.viewList.add(window!!) | |
1085 windowTitles.add(title) | |
1086 windowMenuBars.add(null) | |
1087 windowStyles.add(style) | |
1088 windowDefault.add(null) | |
1089 | |
1090 // If this is our first/only window... | |
1091 // We can set stuff immediately | |
1092 if (adapter.viewList.count() == 1) { | |
1093 this.title = title | |
1094 windowLayout!!.setCurrentItem(0, false) | |
1095 } | |
1096 } | |
1097 } | |
1098 return window | |
1065 } | 1099 } |
1066 | 1100 |
1067 fun windowSetFocus(window: View) | 1101 fun windowSetFocus(window: View) |
1068 { | 1102 { |
1069 waitOnUiThread { | 1103 waitOnUiThread { |
1071 } | 1105 } |
1072 } | 1106 } |
1073 | 1107 |
1074 fun windowDefault(window: View, default: View) | 1108 fun windowDefault(window: View, default: View) |
1075 { | 1109 { |
1076 // TODO: Verify this is the correct activity... | 1110 if(windowLayout != null) { |
1077 defaultItem = default | 1111 val adapter: DWTabViewPagerAdapter = windowLayout!!.adapter as DWTabViewPagerAdapter |
1112 val index = adapter.viewList.indexOf(window) | |
1113 | |
1114 if (index != -1) { | |
1115 windowDefault[index] = default | |
1116 } | |
1117 } | |
1078 } | 1118 } |
1079 | 1119 |
1080 fun windowSetStyle(window: View, style: Int, mask: Int) | 1120 fun windowSetStyle(window: View, style: Int, mask: Int) |
1081 { | 1121 { |
1082 waitOnUiThread { | 1122 waitOnUiThread { |
1083 if (window is TextView && window !is EditText) { | 1123 if (window is TextView && window !is EditText) { |
1084 val text = window | |
1085 val ourmask = (Gravity.HORIZONTAL_GRAVITY_MASK or Gravity.VERTICAL_GRAVITY_MASK) and mask | 1124 val ourmask = (Gravity.HORIZONTAL_GRAVITY_MASK or Gravity.VERTICAL_GRAVITY_MASK) and mask |
1086 | 1125 |
1087 if (ourmask != 0) { | 1126 if (ourmask != 0) { |
1088 // Gravity with the masked parts zeroed out | 1127 // Gravity with the masked parts zeroed out |
1089 val newgravity = style and ourmask | 1128 val newgravity = style and ourmask |
1090 | 1129 |
1091 text.gravity = newgravity | 1130 window.gravity = newgravity |
1092 } | 1131 } |
1093 } | 1132 } |
1094 } | 1133 } |
1095 } | 1134 } |
1096 | 1135 |
1262 } | 1301 } |
1263 } | 1302 } |
1264 } | 1303 } |
1265 | 1304 |
1266 fun windowSetText(window: View, text: String) { | 1305 fun windowSetText(window: View, text: String) { |
1267 waitOnUiThread { | 1306 if(windowLayout != null) { |
1268 if (window is TextView) { | 1307 waitOnUiThread { |
1269 val textview: TextView = window | 1308 if (window is TextView) { |
1270 textview.text = text | 1309 val textview: TextView = window |
1271 } else if (window is Button) { | 1310 textview.text = text |
1272 val button: Button = window | 1311 } else if (window is Button) { |
1273 button.text = text | 1312 val button: Button = window |
1274 } else if (window is LinearLayout) { | 1313 button.text = text |
1275 // TODO: Make sure this is actually the top-level layout, not just a box | 1314 } else if (window is LinearLayout) { |
1276 this.title = text | 1315 val adapter: DWTabViewPagerAdapter = windowLayout!!.adapter as DWTabViewPagerAdapter |
1316 val index = adapter.viewList.indexOf(window) | |
1317 | |
1318 if(index != -1) { | |
1319 windowTitles[index] = text | |
1320 if(index == windowLayout!!.currentItem) { | |
1321 this.title = text | |
1322 } | |
1323 } | |
1324 } | |
1277 } | 1325 } |
1278 } | 1326 } |
1279 } | 1327 } |
1280 | 1328 |
1281 fun windowGetText(window: View): String? { | 1329 fun windowGetText(window: View): String? { |
1282 var text: String? = null | 1330 var text: String? = null |
1283 | 1331 |
1284 waitOnUiThread { | 1332 if(windowLayout != null) { |
1285 if (window is TextView) { | 1333 waitOnUiThread { |
1286 val textview: TextView = window | 1334 if (window is TextView) { |
1287 text = textview.text.toString() | 1335 val textview: TextView = window |
1288 } else if (window is Button) { | 1336 text = textview.text.toString() |
1289 val button: Button = window | 1337 } else if (window is Button) { |
1290 text = button.text.toString() | 1338 val button: Button = window |
1291 } else if (window is LinearLayout) { | 1339 text = button.text.toString() |
1292 // TODO: Make sure this is actually the top-level layout, not just a box | 1340 } else if (window is LinearLayout) { |
1293 text = this.title.toString() | 1341 val adapter: DWTabViewPagerAdapter = windowLayout!!.adapter as DWTabViewPagerAdapter |
1342 val index = adapter.viewList.indexOf(window) | |
1343 | |
1344 if(index != -1) { | |
1345 text = windowTitles[index] | |
1346 } | |
1347 } | |
1294 } | 1348 } |
1295 } | 1349 } |
1296 return text | 1350 return text |
1297 } | 1351 } |
1298 | 1352 |
1299 fun windowHideShow(window: View, state: Int) | 1353 fun windowHideShow(window: View, state: Int) |
1300 { | 1354 { |
1301 waitOnUiThread { | 1355 if(windowLayout != null) { |
1302 if(state == 0) { | 1356 waitOnUiThread { |
1303 window.visibility = View.GONE | 1357 val adapter: DWTabViewPagerAdapter = windowLayout!!.adapter as DWTabViewPagerAdapter |
1304 } else { | 1358 val index = adapter.viewList.indexOf(window) |
1305 window.visibility = View.VISIBLE | 1359 var defaultItem: View? = null |
1306 defaultItem?.requestFocus() | 1360 |
1361 if(state == 0) { | |
1362 window.visibility = View.GONE | |
1363 } else { | |
1364 window.visibility = View.VISIBLE | |
1365 } | |
1366 if (index != -1) { | |
1367 defaultItem = windowDefault[index] | |
1368 if(state != 0) { | |
1369 windowLayout!!.setCurrentItem(index, true) | |
1370 } | |
1371 } | |
1372 if(state != 0 && defaultItem != null) { | |
1373 defaultItem.requestFocus() | |
1374 } | |
1307 } | 1375 } |
1308 } | 1376 } |
1309 } | 1377 } |
1310 | 1378 |
1311 fun clipboardGetText(): String { | 1379 fun clipboardGetText(): String { |