changeset 2492:e2ca6c1a4661

Android: Implement: slider, percent, scrollbar, checkbox_set/get box_unpack_at_index(), and entryfield_set_limit().
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Sat, 01 May 2021 00:41:53 +0000
parents bf4fe6bb512b
children bca7e0ab0ccc
files android/DWindows.kt android/dw.cpp
diffstat 2 files changed, 247 insertions(+), 82 deletions(-) [+]
line wrap: on
line diff
--- a/android/DWindows.kt	Fri Apr 30 20:21:05 2021 +0000
+++ b/android/DWindows.kt	Sat May 01 00:41:53 2021 +0000
@@ -10,6 +10,8 @@
 import android.os.Bundle
 import android.os.Handler
 import android.os.Looper
+import android.text.InputFilter
+import android.text.InputFilter.LengthFilter
 import android.text.method.PasswordTransformationMethod
 import android.util.Log
 import android.view.Gravity
@@ -17,6 +19,7 @@
 import android.view.View
 import android.view.ViewGroup
 import android.widget.*
+import android.widget.SeekBar.OnSeekBarChangeListener
 import androidx.appcompat.app.AlertDialog
 import androidx.appcompat.app.AppCompatActivity
 import androidx.collection.SimpleArrayMap
@@ -68,10 +71,8 @@
      * These are the Android calls to actually create the UI...
      * forwarded from the C Dynamic Windows API
      */
-    fun windowNew(title: String, style: Int): LinearLayout?
-    {
-        if(firstWindow)
-        {
+    fun windowNew(title: String, style: Int): LinearLayout? {
+        if (firstWindow) {
             var windowLayout: LinearLayout = LinearLayout(this)
             var dataArrayMap = SimpleArrayMap<String, Long>()
 
@@ -86,33 +87,26 @@
         return null
     }
 
-    fun windowFromId(window: View, cid: Int): View
-    {
+    fun windowFromId(window: View, cid: Int): View {
         return window.findViewById(cid)
     }
 
-    fun windowSetData(window: View, name: String, data: Long)
-    {
-        if(window.tag != null)
-        {
+    fun windowSetData(window: View, name: String, data: Long) {
+        if (window.tag != null) {
             var dataArrayMap: SimpleArrayMap<String, Long> = window.tag as SimpleArrayMap<String, Long>
 
-            if(data != 0L) {
+            if (data != 0L) {
                 dataArrayMap.put(name, data)
-            }
-            else
-            {
+            } else {
                 dataArrayMap.remove(name)
             }
         }
     }
 
-    fun windowGetData(window: View, name: String): Long
-    {
+    fun windowGetData(window: View, name: String): Long {
         var retval: Long = 0L
 
-        if (window.tag != null)
-        {
+        if (window.tag != null) {
             var dataArrayMap: SimpleArrayMap<String, Long> = window.tag as SimpleArrayMap<String, Long>
 
             retval = dataArrayMap.get(name)!!
@@ -120,78 +114,61 @@
         return retval
     }
 
-    fun windowSetEnabled(window: View, state: Boolean)
-    {
+    fun windowSetEnabled(window: View, state: Boolean) {
         window.setEnabled(state)
     }
 
-    fun windowSetText(window: View, text: String)
-    {
-        if(window is TextView)
-        {
+    fun windowSetText(window: View, text: String) {
+        if (window is TextView) {
             var textview: TextView = window
             textview.text = text
-        }
-        else if(window is Button)
-        {
+        } else if (window is Button) {
             var button: Button = window
             button.text = text
-        }
-        else if(window is LinearLayout)
-        {
+        } else if (window is LinearLayout) {
             // TODO: Make sure this is actually the top-level layout, not just a box
             this.title = text
         }
     }
 
-    fun windowGetText(window: View): String?
-    {
-        if(window is TextView)
-        {
+    fun windowGetText(window: View): String? {
+        if (window is TextView) {
             var textview: TextView = window
             return textview.text.toString()
-        }
-        else if(window is Button)
-        {
+        } else if (window is Button) {
             var button: Button = window
             return button.text.toString()
-        }
-        else if(window is LinearLayout)
-        {
+        } else if (window is LinearLayout) {
             // TODO: Make sure this is actually the top-level layout, not just a box
             return this.title.toString()
         }
         return null
     }
 
-    fun clipboardGetText(): String
-    {
+    fun clipboardGetText(): String {
         var cm: ClipboardManager = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
         var clipdata = cm.primaryClip
 
-        if(clipdata != null && clipdata.itemCount > 0)
-        {
+        if (clipdata != null && clipdata.itemCount > 0) {
             return clipdata.getItemAt(0).coerceToText(this).toString()
         }
         return ""
     }
 
-    fun clipboardSetText(text: String)
-    {
+    fun clipboardSetText(text: String) {
         var cm: ClipboardManager = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
         var clipdata = ClipData.newPlainText("text", text)
 
         cm.setPrimaryClip(clipdata)
     }
 
-    fun boxNew(type: Int, pad: Int): LinearLayout
-    {
+    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)
+                LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
         if (type > 0) {
             box.orientation = LinearLayout.VERTICAL
         } else {
@@ -201,13 +178,12 @@
         return box
     }
 
-    fun boxPack(box: LinearLayout, item: View, index: Int, width: Int, height: Int, hsize: Int, vsize: Int, pad: Int)
-    {
+    fun boxPack(box: LinearLayout, item: View, index: Int, width: Int, height: Int, hsize: Int, vsize: Int, pad: Int) {
         var w: Int = LinearLayout.LayoutParams.WRAP_CONTENT
         var h: Int = LinearLayout.LayoutParams.WRAP_CONTENT
 
-        if(item is LinearLayout) {
-            if(box.orientation == LinearLayout.VERTICAL) {
+        if (item is LinearLayout) {
+            if (box.orientation == LinearLayout.VERTICAL) {
                 if (hsize > 0) {
                     w = LinearLayout.LayoutParams.MATCH_PARENT
                 }
@@ -219,20 +195,20 @@
         }
         var params: LinearLayout.LayoutParams = LinearLayout.LayoutParams(w, h)
 
-        if(item !is LinearLayout && (width != -1 || height != -1)) {
+        if (item !is LinearLayout && (width != -1 || height != -1)) {
             item.measure(0, 0)
             if (width > 0) {
                 w = width
-            } else if(width == -1) {
+            } else if (width == -1) {
                 w = item.getMeasuredWidth()
             }
             if (height > 0) {
                 h = height
-            } else if(height == -1) {
+            } else if (height == -1) {
                 h = item.getMeasuredHeight()
             }
         }
-        if(box.orientation == LinearLayout.VERTICAL) {
+        if (box.orientation == LinearLayout.VERTICAL) {
             if (vsize > 0) {
                 if (w > 0) {
                     params.weight = w.toFloat()
@@ -249,29 +225,36 @@
                 }
             }
         }
-        if(pad > 0) {
+        if (pad > 0) {
             params.setMargins(pad, pad, pad, pad)
         }
         var grav: Int = Gravity.CLIP_HORIZONTAL or Gravity.CLIP_VERTICAL
-        if(hsize > 0 && vsize > 0) {
+        if (hsize > 0 && vsize > 0) {
             params.gravity = Gravity.FILL or grav
-        } else if(hsize > 0) {
+        } else if (hsize > 0) {
             params.gravity = Gravity.FILL_HORIZONTAL or grav
-        } else if(vsize > 0) {
+        } else if (vsize > 0) {
             params.gravity = Gravity.FILL_VERTICAL or grav
         }
         item.layoutParams = params
         box.addView(item, index)
     }
 
-    fun boxUnpack(item: View)
-    {
+    fun boxUnpack(item: View) {
         var box: LinearLayout = item.parent as LinearLayout
         box.removeView(item)
     }
 
-    fun buttonNew(text: String, cid: Int): Button
-    {
+    fun boxUnpackAtIndex(box: LinearLayout, index: Int): View? {
+        var item: View = box.getChildAt(index)
+
+        if (item != null) {
+            box.removeView(item)
+        }
+        return item
+    }
+
+    fun buttonNew(text: String, cid: Int): Button {
         val button = Button(this)
         var dataArrayMap = SimpleArrayMap<String, Long>()
 
@@ -284,23 +267,24 @@
         return button
     }
 
-    fun entryfieldNew(text: String, cid: Int, password: Int): EditText
-    {
+    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)
-        {
+        if (password > 0) {
             entryfield.transformationMethod = PasswordTransformationMethod.getInstance()
         }
         entryfield.setText(text)
         return entryfield
     }
 
-    fun radioButtonNew(text: String, cid: Int): RadioButton
-    {
+    fun entryfieldSetLimit(entryfield: EditText, limit: Long) {
+        entryfield.filters = arrayOf<InputFilter>(LengthFilter(limit.toInt()))
+    }
+
+    fun radioButtonNew(text: String, cid: Int): RadioButton {
         val radiobutton = RadioButton(this)
         var dataArrayMap = SimpleArrayMap<String, Long>()
 
@@ -313,8 +297,7 @@
         return radiobutton
     }
 
-    fun checkboxNew(text: String, cid: Int): CheckBox
-    {
+    fun checkboxNew(text: String, cid: Int): CheckBox {
         val checkbox = CheckBox(this)
         var dataArrayMap = SimpleArrayMap<String, Long>()
 
@@ -327,16 +310,37 @@
         return checkbox
     }
 
-    fun textNew(text: String, cid: Int, status: Int): TextView
+    fun checkOrRadioSetChecked(control: View, state: Int)
     {
+        if(control is CheckBox) {
+            var checkbox: CheckBox = control
+            checkbox.isChecked = state != 0
+        } else if(control is RadioButton) {
+            var radiobutton: RadioButton = control
+            radiobutton.isChecked = state != 0
+        }
+    }
+
+    fun checkOrRadioGetChecked(control: View): Boolean
+    {
+        if(control is CheckBox) {
+            var checkbox: CheckBox = control
+            return checkbox.isChecked
+        } else if(control is RadioButton) {
+            var radiobutton: RadioButton = control
+            return radiobutton.isChecked
+        }
+        return false
+    }
+
+    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
-        if(status != 0)
-        {
+        if (status != 0) {
             val border = GradientDrawable()
 
             // Set a black border on white background...
@@ -349,8 +353,7 @@
         return textview
     }
 
-    fun notebookNew(cid: Int, top: Int)
-    {
+    fun notebookNew(cid: Int, top: Int) {
         val notebook = RelativeLayout(this)
         val pager = ViewPager2(this)
         val tabs = TabLayout(this)
@@ -368,13 +371,62 @@
         var params: RelativeLayout.LayoutParams = RelativeLayout.LayoutParams(w, h)
         tabs.layoutParams = params
         notebook.addView(tabs)
-        if(top != 0) {
+        if (top != 0) {
             notebook.addView(pager, 0)
         } else {
             notebook.addView(pager)
         }
     }
 
+    fun sliderNew(vertical: Int, increments: Int, cid: Int): SeekBar
+    {
+        val slider = SeekBar(this)
+        var dataArrayMap = SimpleArrayMap<String, Long>()
+
+        slider.tag = dataArrayMap
+        slider.id = cid
+        slider.max = increments
+        if(vertical != 0) {
+            slider.rotation = 270F
+        }
+        slider.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
+            override fun onStopTrackingTouch(seekBar: SeekBar) {
+            }
+            override fun onStartTrackingTouch(seekBar: SeekBar) {
+            }
+            override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
+                eventHandler(slider, null, 14, null, null, slider.progress, 0, 0, 0)
+            }
+        })
+        return slider
+    }
+
+    fun percentNew(cid: Int): ProgressBar
+    {
+        val percent = ProgressBar(this)
+        var dataArrayMap = SimpleArrayMap<String, Long>()
+
+        percent.tag = dataArrayMap
+        percent.id = cid
+        percent.max = 100
+        return percent
+    }
+
+    fun percentGetPos(percent: ProgressBar): Int
+    {
+        return percent.progress
+    }
+
+    fun percentSetPos(percent: ProgressBar, position: Int)
+    {
+        percent.progress = position
+    }
+
+    fun percentSetRange(percent: ProgressBar, range: Int)
+    {
+        percent.max = range
+    }
+
     fun timerConnect(interval: Long, sigfunc: Long, data: Long): Timer
     {
         // creating timer task, timer
--- a/android/dw.cpp	Fri Apr 30 20:21:05 2021 +0000
+++ b/android/dw.cpp	Sat May 01 00:41:53 2021 +0000
@@ -888,7 +888,19 @@
  */
 HWND API dw_box_unpack_at_index(HWND box, int index)
 {
-    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 boxUnpackAtIndex = env->GetMethodID(clazz, "boxUnpackAtIndex",
+                                                      "(Landroid/widget/LinearLayout;I)Landroid/view/View;");
+        // Call the method on the object
+        retval = env->CallObjectMethod(_dw_obj, boxUnpackAtIndex, box, index);
+    }
+    return retval;
 }
 
 /*
@@ -1024,6 +1036,18 @@
  */
 void API dw_entryfield_set_limit(HWND handle, ULONG limit)
 {
+    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 entryfieldSetLimit = env->GetMethodID(clazz, "entryfieldSetLimit",
+                                                        "(Landroid/widget/EditText;J)V");
+        // Call the method on the object
+        env->CallVoidMethod(_dw_obj, entryfieldSetLimit, handle, (jlong)limit);
+    }
 }
 
 /*
@@ -1156,6 +1180,18 @@
  */
 HWND API dw_slider_new(int vertical, int increments, ULONG cid)
 {
+    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 sliderNew = env->GetMethodID(clazz, "sliderNew", "(III)Landroid/widget/SeekBar;");
+        // Call the method on the object
+        jobject result = env->NewWeakGlobalRef(env->CallObjectMethod(_dw_obj, sliderNew, vertical, increments, (jint)cid));
+        return result;
+    }
     return 0;
 }
 
@@ -1168,6 +1204,18 @@
  */
 unsigned int API dw_slider_get_pos(HWND handle)
 {
+    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 percentGetPos = env->GetMethodID(clazz, "percentGetPos",
+                                                   "(Landroid/widget/ProgressBar;)I");
+        // Call the method on the object
+        return env->CallIntMethod(_dw_obj, percentGetPos, handle);
+    }
     return 0;
 }
 
@@ -1179,6 +1227,7 @@
  */
 void API dw_slider_set_pos(HWND handle, unsigned int position)
 {
+    dw_percent_set_pos(handle, position);
 }
 
 /*
@@ -1191,7 +1240,7 @@
  */
 HWND API dw_scrollbar_new(int vertical, ULONG cid)
 {
-    return 0;
+    return dw_slider_new(vertical, 100, cid);
 }
 
 /*
@@ -1203,7 +1252,7 @@
  */
 unsigned int API dw_scrollbar_get_pos(HWND handle)
 {
-    return 0;
+    return dw_slider_get_pos(handle);
 }
 
 /*
@@ -1214,6 +1263,7 @@
  */
 void API dw_scrollbar_set_pos(HWND handle, unsigned int position)
 {
+    dw_percent_set_pos(handle, position);
 }
 
 /*
@@ -1225,6 +1275,18 @@
  */
 void API dw_scrollbar_set_range(HWND handle, unsigned int range, unsigned int visible)
 {
+    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 percentSetRange = env->GetMethodID(clazz, "percentSetRange",
+                                                     "(Landroid/widget/ProgressBar;I)V");
+        // Call the method on the object
+        env->CallVoidMethod(_dw_obj, percentSetRange, handle, (jint)range);
+    }
 }
 
 /*
@@ -1236,6 +1298,19 @@
  */
 HWND API dw_percent_new(ULONG cid)
 {
+    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 percentNew = env->GetMethodID(clazz, "percentNew",
+                                               "(I)Landroid/widget/ProgressBar;");
+        // Call the method on the object
+        jobject result = env->NewWeakGlobalRef(env->CallObjectMethod(_dw_obj, percentNew, (jint)cid));
+        return result;
+    }
     return 0;
 }
 
@@ -1247,6 +1322,18 @@
  */
 void API dw_percent_set_pos(HWND handle, unsigned int position)
 {
+    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 percentSetPos = env->GetMethodID(clazz, "percentSetPos",
+                                                   "(Landroid/widget/ProgressBar;I)V");
+        // Call the method on the object
+        env->CallVoidMethod(_dw_obj, percentSetPos, handle, (jint)position);
+    }
 }
 
 /*
@@ -1286,6 +1373,19 @@
  */
 int API dw_checkbox_get(HWND handle)
 {
+    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);
+        jclass clazz = env->FindClass(DW_CLASS_NAME);
+        // Get the method that you want to call
+        jmethodID checkOrRadioGetChecked = env->GetMethodID(clazz, "checkOrRadioGetChecked",
+                                                            "(Landroid/view/View;)Z");
+        // Call the method on the object
+        return env->CallBooleanMethod(_dw_obj, checkOrRadioGetChecked, handle);
+    }
     return FALSE;
 }
 
@@ -1297,6 +1397,19 @@
  */
 void API dw_checkbox_set(HWND handle, int value)
 {
+    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);
+        jclass clazz = env->FindClass(DW_CLASS_NAME);
+        // Get the method that you want to call
+        jmethodID checkOrRadioSetChecked = env->GetMethodID(clazz, "checkOrRadioSetChecked",
+                                                            "(Landroid/view/View;I)V");
+        // Call the method on the object
+        env->CallVoidMethod(_dw_obj, checkOrRadioSetChecked, handle, value);
+    }
 }
 
 /*