changeset 2488:666af45f33b5

Android: Implment a bunch of window functions: enable/disable/data/id Add basic structure for the notebook control.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Fri, 30 Apr 2021 00:51:33 +0000
parents 83f8f4f58a98
children 6c01b0132813
files android/DWindows.kt android/dw.cpp
diffstat 2 files changed, 197 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/android/DWindows.kt	Tue Apr 27 09:19:29 2021 +0000
+++ b/android/DWindows.kt	Fri Apr 30 00:51:33 2021 +0000
@@ -7,16 +7,45 @@
 import android.text.method.PasswordTransformationMethod
 import android.util.Log
 import android.view.Gravity
+import android.view.LayoutInflater
 import android.view.View
+import android.view.ViewGroup
 import android.widget.*
 import androidx.appcompat.app.AlertDialog
 import androidx.appcompat.app.AppCompatActivity
+import androidx.collection.SimpleArrayMap
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentActivity
+import androidx.fragment.app.FragmentManager
+import androidx.fragment.app.FragmentStatePagerAdapter
+import androidx.recyclerview.widget.RecyclerView
+import androidx.viewpager.widget.ViewPager
+import androidx.viewpager2.adapter.FragmentStateAdapter
+import androidx.viewpager2.widget.ViewPager2
+import com.google.android.material.tabs.TabLayout
+import com.google.android.material.tabs.TabLayoutMediator
 
+class TabViewPagerAdapter : RecyclerView.Adapter<TabViewPagerAdapter.EventViewHolder>() {
+    val eventList = listOf("0", "1", "2")
 
-class DWindows : AppCompatActivity()
-{
-    override fun onCreate(savedInstanceState: Bundle?)
-    {
+    // Layout "layout_demo_viewpager2_cell.xml" will be defined later
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
+            EventViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.dwindows_main, parent, false))
+
+    override fun getItemCount() = eventList.count()
+    override fun onBindViewHolder(holder: EventViewHolder, position: Int) {
+        (holder.view as? TextView)?.also{
+            it.text = "Page " + eventList.get(position)
+        }
+    }
+
+    class EventViewHolder(val view: View) : RecyclerView.ViewHolder(view)
+}
+
+class DWindows : AppCompatActivity() {
+    var firstWindow: Boolean = true
+
+    override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
 
         // Turn on rotation
@@ -32,23 +61,74 @@
         // This will start a new thread that calls the app's dwmain()
         dwindowsInit(s)
     }
+
     /*
      * These are the Android calls to actually create the UI...
      * forwarded from the C Dynamic Windows API
      */
-    fun windowNew(title: String, style: Int): LinearLayout
+    fun windowNew(title: String, style: Int): LinearLayout?
+    {
+        if(firstWindow)
+        {
+            var windowLayout: LinearLayout = LinearLayout(this)
+            var dataArrayMap = SimpleArrayMap<String, Long>()
+
+            windowLayout.tag = dataArrayMap
+            setContentView(windowLayout)
+            this.title = title
+            // For now we just return our DWindows' main activity layout...
+            // in the future, later calls should create new activities
+            firstWindow = false
+            return windowLayout
+        }
+        return null
+    }
+
+    fun windowFromId(window: View, cid: Int): View
+    {
+        return window.findViewById(cid)
+    }
+
+    fun windowSetData(window: View, name: String, data: Long)
     {
-        var windowLayout: LinearLayout = LinearLayout(this)
-        setContentView(windowLayout)
-        this.title = title
-        // For now we just return our DWindows' main activity layout...
-        // in the future, later calls should create new activities
-        return windowLayout
+        if(window.tag != null)
+        {
+            var dataArrayMap: SimpleArrayMap<String, Long> = window.tag as SimpleArrayMap<String, Long>
+
+            if(data != 0L) {
+                dataArrayMap.put(name, data)
+            }
+            else
+            {
+                dataArrayMap.remove(name)
+            }
+        }
+    }
+
+    fun windowGetData(window: View, name: String): Long
+    {
+        var retval: Long = 0L
+
+        if (window.tag != null)
+        {
+            var dataArrayMap: SimpleArrayMap<String, Long> = window.tag as SimpleArrayMap<String, Long>
+
+            retval = dataArrayMap.get(name)!!
+        }
+        return retval
+    }
+
+    fun windowSetEnabled(window: View, state: Boolean)
+    {
+        window.setEnabled(state)
     }
 
     fun boxNew(type: Int, pad: Int): LinearLayout
     {
         val box = LinearLayout(this)
+        var dataArrayMap = SimpleArrayMap<String, Long>()
+
+        box.tag = dataArrayMap
         box.layoutParams =
             LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
         if (type > 0) {
@@ -119,7 +199,7 @@
             params.gravity = Gravity.FILL_VERTICAL or grav
         }
         item.layoutParams = params
-        box.addView(item)
+        box.addView(item, index)
     }
 
     fun boxUnpack(item: View)
@@ -131,7 +211,11 @@
     fun buttonNew(text: String, cid: Int): Button
     {
         val button = Button(this)
+        var dataArrayMap = SimpleArrayMap<String, Long>()
+
+        button.tag = dataArrayMap
         button.text = text
+        button.id = cid
         button.setOnClickListener {
             eventHandlerSimple(button, 8)
         }
@@ -141,6 +225,10 @@
     fun entryfieldNew(text: String, cid: Int, password: Int): EditText
     {
         val entryfield = EditText(this)
+        var dataArrayMap = SimpleArrayMap<String, Long>()
+
+        entryfield.tag = dataArrayMap
+        entryfield.id = cid
         if(password > 0) {
             entryfield.transformationMethod = PasswordTransformationMethod.getInstance()
         }
@@ -151,6 +239,10 @@
     fun radioButtonNew(text: String, cid: Int): RadioButton
     {
         val radiobutton = RadioButton(this)
+        var dataArrayMap = SimpleArrayMap<String, Long>()
+
+        radiobutton.tag = dataArrayMap
+        radiobutton.id = cid
         radiobutton.text = text
         radiobutton.setOnClickListener {
             eventHandlerSimple(radiobutton, 8)
@@ -161,6 +253,10 @@
     fun checkboxNew(text: String, cid: Int): CheckBox
     {
         val checkbox = CheckBox(this)
+        var dataArrayMap = SimpleArrayMap<String, Long>()
+
+        checkbox.tag = dataArrayMap
+        checkbox.id = cid
         checkbox.text = text
         checkbox.setOnClickListener {
             eventHandlerSimple(checkbox, 8)
@@ -171,10 +267,36 @@
     fun textNew(text: String, cid: Int, status: Int): TextView
     {
         val textview = TextView(this)
+        var dataArrayMap = SimpleArrayMap<String, Long>()
+
+        textview.tag = dataArrayMap
+        textview.id = cid
         textview.text = text
         return textview
     }
 
+    fun notebookNew(cid: Int, top: Int)
+    {
+        val notebook = RelativeLayout(this)
+        val pager = ViewPager2(this)
+        val tabs = TabLayout(this)
+        var w: Int = RelativeLayout.LayoutParams.MATCH_PARENT
+        var h: Int = RelativeLayout.LayoutParams.WRAP_CONTENT
+        var dataArrayMap = SimpleArrayMap<String, Long>()
+
+        notebook.tag = dataArrayMap
+        notebook.id = cid
+        pager.adapter = TabViewPagerAdapter()
+        TabLayoutMediator(tabs, pager) { tab, position ->
+            tab.text = "OBJECT ${(position + 1)}"
+        }.attach()
+
+        var params: RelativeLayout.LayoutParams = RelativeLayout.LayoutParams(w, h)
+        tabs.layoutParams = params
+        notebook.addView(tabs)
+        notebook.addView(pager)
+    }
+
     fun debugMessage(text: String)
     {
         Log.d(null, text)
--- a/android/dw.cpp	Tue Apr 27 09:19:29 2021 +0000
+++ b/android/dw.cpp	Fri Apr 30 00:51:33 2021 +0000
@@ -901,7 +901,7 @@
     /* 65536 is the table limit on GTK...
      * seems like a high enough value we will never hit it here either.
      */
-    _dw_box_pack(box, item, 65536, width, height, hsize, vsize, pad, "dw_box_pack_start()");
+    _dw_box_pack(box, item, -1, width, height, hsize, vsize, pad, "dw_box_pack_start()");
 }
 
 /*
@@ -3140,6 +3140,22 @@
 {
 }
 
+void _dw_window_set_enabled(HWND handle, jboolean state)
+{
+    JNIEnv *env;
+
+    if((env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
+    {
+        // First get the class that contains the method you need to call
+        jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
+        // Get the method that you want to call
+        jmethodID windowSetEnabled = env->GetMethodID(clazz, "windowSetEnabled",
+                                                      "(Landroid/view/View;Z)V");
+        // Call the method on the object
+        env->CallVoidMethod(_dw_obj, windowSetEnabled, handle, state);
+    }
+}
+
 /*
  * Disables given window (widget).
  * Parameters:
@@ -3147,6 +3163,7 @@
  */
 void API dw_window_disable(HWND handle)
 {
+    _dw_window_set_enabled(handle, JNI_FALSE);
 }
 
 /*
@@ -3156,6 +3173,7 @@
  */
 void API dw_window_enable(HWND handle)
 {
+    _dw_window_set_enabled(handle, JNI_TRUE);
 }
 
 /*
@@ -3207,7 +3225,20 @@
  */
 HWND API dw_window_from_id(HWND handle, int id)
 {
-    return 0;
+    JNIEnv *env;
+    HWND retval = 0;
+
+    if((env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
+    {
+        // First get the class that contains the method you need to call
+        jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
+        // Get the method that you want to call
+        jmethodID windowFromId = env->GetMethodID(clazz, "windowFromId",
+                                                  "(Landroid/view/View;I)Landroid/view/View;");
+        // Call the method on the object
+        retval = env->CallObjectMethod(_dw_obj, windowFromId, handle, id);
+    }
+    return retval;
 }
 
 /*
@@ -3394,6 +3425,20 @@
  */
 void API dw_window_set_data(HWND window, const char *dataname, void *data)
 {
+    JNIEnv *env;
+
+    if((env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
+    {
+        // Construct a String
+        jstring jstr = env->NewStringUTF(dataname);
+        // First get the class that contains the method you need to call
+        jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
+        // Get the method that you want to call
+        jmethodID windowSetData = env->GetMethodID(clazz, "windowSetData",
+                                                   "(Landroid/view/View;Ljava/lang/String;J)V");
+        // Call the method on the object
+        env->CallVoidMethod(_dw_obj, windowSetData, window, jstr);
+    }
 }
 
 /*
@@ -3406,7 +3451,22 @@
  */
 void * API dw_window_get_data(HWND window, const char *dataname)
 {
-    return NULL;
+    JNIEnv *env;
+    void *retval = NULL;
+
+    if((env = (JNIEnv *)pthread_getspecific(_dw_env_key)))
+    {
+        // Construct a String
+        jstring jstr = env->NewStringUTF(dataname);
+        // First get the class that contains the method you need to call
+        jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
+        // Get the method that you want to call
+        jmethodID windowGetData = env->GetMethodID(clazz, "windowGetData",
+                                                   "(Landroid/view/View;Ljava/lang/String;)J");
+        // Call the method on the object
+        retval = DW_INT_TO_POINTER(env->CallLongMethod(_dw_obj, windowGetData, window, jstr));
+    }
+    return retval;
 }
 
 /*