# HG changeset patch # User bsmith@81767d24-ef19-dc11-ae90-00e081727c95 # Date 1620552674 0 # Node ID 5f92284e2b0852f7ab66c11c258ab61193571453 # Parent 167af4b0004ba4477a8010a652338f3a186cde47 Android: Implement bitmap buttons, implement dw_listbox_selected_multi(). Added a number of safety checks to prevent java exceptions. diff -r 167af4b0004b -r 5f92284e2b08 android/DWindows.kt --- a/android/DWindows.kt Sat May 08 23:22:52 2021 +0000 +++ b/android/DWindows.kt Sun May 09 09:31:14 2021 +0000 @@ -1,6 +1,6 @@ package org.dbsoft.dwindows -import android.app.Activity +import android.R.attr import android.content.ClipData import android.content.ClipboardManager import android.content.Context @@ -8,6 +8,7 @@ import android.content.pm.ActivityInfo import android.content.res.Configuration import android.graphics.Bitmap +import android.graphics.BitmapFactory import android.graphics.drawable.GradientDrawable import android.media.AudioManager import android.media.ToneGenerator @@ -21,6 +22,7 @@ import android.text.method.PasswordTransformationMethod import android.util.Base64 import android.util.Log +import android.util.SparseBooleanArray import android.view.Gravity import android.view.MotionEvent import android.view.View @@ -41,6 +43,9 @@ import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout.OnTabSelectedListener import com.google.android.material.tabs.TabLayoutMediator +import java.io.File +import java.io.FileInputStream +import java.io.FileNotFoundException import java.util.* import java.util.concurrent.locks.ReentrantLock @@ -102,17 +107,35 @@ if (event.x >= v.width - (v as EditText) .compoundDrawables[DRAWABLE_RIGHT].bounds.width() ) { - value += 1 + val newvalue = this.text.toString().toLong() + + if(newvalue != null) { + value = newvalue + 1 + } else { + value += 1 + } if(value > maximum) { value = maximum } + if(value < minimum) { + value = minimum + } setText(value.toString()) eventHandlerInt(14, value.toInt(), 0, 0, 0) return true } else if (event.x <= (v as EditText) .compoundDrawables[DRAWABLE_LEFT].bounds.width() ) { - value -= 1 + val newvalue = this.text.toString().toLong() + + if(newvalue != null) { + value = newvalue - 1 + } else { + value -= 1 + } + if(value > maximum) { + value = maximum + } if(value < minimum) { value = minimum } @@ -559,6 +582,63 @@ return button } + fun bitmapButtonNew(text: String, resid: Int): ImageButton? { + var button: ImageButton? = null + waitOnUiThread { + button = ImageButton(this) + var dataArrayMap = SimpleArrayMap() + + button!!.tag = dataArrayMap + button!!.id = resid + button!!.setImageResource(resid) + button!!.setOnClickListener { + eventHandlerSimple(button!!, 8) + } + } + return button + } + + fun bitmapButtonNewFromFile(text: String, cid: Int, filename: String): ImageButton? { + var button: ImageButton? = null + waitOnUiThread { + button = ImageButton(this) + var dataArrayMap = SimpleArrayMap() + + button!!.tag = dataArrayMap + button!!.id = cid + button!!.setOnClickListener { + eventHandlerSimple(button!!, 8) + } + // Try to load the image, and protect against exceptions + try { + val f = File(filename) + val b = BitmapFactory.decodeStream(FileInputStream(f)) + button!!.setImageBitmap(b) + } + catch (e: FileNotFoundException) + { + } + } + return button + } + + fun bitmapButtonNewFromData(text: String, cid: Int, data: ByteArray, length: Int): ImageButton? { + var button: ImageButton? = null + waitOnUiThread { + button = ImageButton(this) + var dataArrayMap = SimpleArrayMap() + val b = BitmapFactory.decodeByteArray(data,0, length) + + button!!.tag = dataArrayMap + button!!.id = cid + button!!.setOnClickListener { + eventHandlerSimple(button!!, 8) + } + button!!.setImageBitmap(b) + } + return button + } + fun entryfieldNew(text: String, cid: Int, password: Int): EditText? { var entryfield: EditText? = null @@ -1269,12 +1349,12 @@ if(window is DWComboBox) { val combobox = window - if(index < combobox.list.count()) + if(index > -1 && index < combobox.list.count()) combobox.list[index] = text } else if(window is DWListBox) { val listbox = window - if(index < listbox.list.count()) + if(index > -1 && index < listbox.list.count()) listbox.list[index] = text } } @@ -1288,12 +1368,12 @@ if(window is DWComboBox) { val combobox = window - if(index < combobox.list.count()) + if(index > -1 && index < combobox.list.count()) retval = combobox.list[index] } else if(window is DWListBox) { val listbox = window - if(index < listbox.list.count()) + if(index > -1 && index < listbox.list.count()) retval = listbox.list[index] } } @@ -1362,7 +1442,7 @@ } } - fun listSetTop(window: View, top: Int) + fun listBoxSetTop(window: View, top: Int) { waitOnUiThread { if(window is DWListBox) { @@ -1375,6 +1455,36 @@ } } + fun listBoxSelectedMulti(window: View, where: Int): Int + { + var retval: Int = -1 + + waitOnUiThread { + if(window is DWListBox) { + val listbox = window + val checked: SparseBooleanArray = listbox.getCheckedItemPositions() + + // If we are starting over.... + if(where == -1 && checked.size() > 0) { + retval = checked.keyAt(0) + } else { + // Otherwise loop until we find our current place + for (i in 0 until checked.size()) { + // Item position in adapter + val position: Int = checked.keyAt(i) + // If we are at our current point... check to see + // if there is another one, and return it... + // otherwise we will return -1 to indicated we are done. + if (where == position && (i+1) < checked.size()) { + retval = checked.keyAt(i+1) + } + } + } + } + } + return retval + } + fun timerConnect(interval: Long, sigfunc: Long, data: Long): Timer { // creating timer task, timer diff -r 167af4b0004b -r 5f92284e2b08 android/dw.cpp --- a/android/dw.cpp Sat May 08 23:22:52 2021 +0000 +++ b/android/dw.cpp Sun May 09 09:31:14 2021 +0000 @@ -1177,6 +1177,21 @@ */ HWND API dw_bitmapbutton_new(const char *text, ULONG resid) { + JNIEnv *env; + + if((env = (JNIEnv *)pthread_getspecific(_dw_env_key))) + { + // Construct a String + jstring jstr = env->NewStringUTF(text); + // 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 bitmapButtonNew = env->GetMethodID(clazz, "bitmapButtonNew", + "(Ljava/lang/String;I)Landroid/widget/ImageButton;"); + // Call the method on the object + jobject result = env->NewWeakGlobalRef(env->CallObjectMethod(_dw_obj, bitmapButtonNew, jstr, (int)resid)); + return result; + } return 0; } @@ -1193,6 +1208,22 @@ */ HWND API dw_bitmapbutton_new_from_file(const char *text, unsigned long cid, const char *filename) { + JNIEnv *env; + + if((env = (JNIEnv *)pthread_getspecific(_dw_env_key))) + { + // Construct a String + jstring jstr = env->NewStringUTF(text); + jstring path = env->NewStringUTF(text); + // 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 bitmapButtonNewFromFile = env->GetMethodID(clazz, "bitmapButtonNewFromFile", + "(Ljava/lang/String;ILjava/lang/String;)Landroid/widget/ImageButton;"); + // Call the method on the object + jobject result = env->NewWeakGlobalRef(env->CallObjectMethod(_dw_obj, bitmapButtonNewFromFile, jstr, (int)cid, path)); + return result; + } return 0; } @@ -1209,6 +1240,26 @@ */ HWND API dw_bitmapbutton_new_from_data(const char *text, unsigned long cid, const char *data, int len) { + JNIEnv *env; + + if(data && len > 0 && (env = (JNIEnv *)pthread_getspecific(_dw_env_key))) + { + // Construct a String + jstring jstr = env->NewStringUTF(text); + // Construct a byte array + jbyteArray bytearray = env->NewByteArray(len); + env->SetByteArrayRegion(bytearray, 0, len, reinterpret_cast(data)); + // 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 bitmapButtonNewFromData = env->GetMethodID(clazz, "bitmapButtonNewFromData", + "(Ljava/lang/String;I[BI)Landroid/widget/ImageButton;"); + // Call the method on the object + jobject result = env->NewWeakGlobalRef(env->CallObjectMethod(_dw_obj, bitmapButtonNewFromData, jstr, (int)cid, bytearray, len)); + // Clean up after the array now that we are finished + //env->ReleaseByteArrayElements(bytearray, (jbyte *) data, 0); + return result; + } return 0; } @@ -1731,10 +1782,10 @@ // 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 listSetTop = env->GetMethodID(clazz, "listSetTop", + jmethodID listBoxSetTop = env->GetMethodID(clazz, "listBoxSetTop", "(Landroid/view/View;I)V"); // Call the method on the object - env->CallVoidMethod(_dw_obj, listSetTop, handle, top); + env->CallVoidMethod(_dw_obj, listBoxSetTop, handle, top); } } @@ -1756,7 +1807,7 @@ jclass clazz = _dw_find_class(env, DW_CLASS_NAME); // Get the method that you want to call jmethodID listOrComboBoxGetText = env->GetMethodID(clazz, "listOrComboBoxGetText", - "(Landroid/view/View;)ILjava/lang/String;"); + "(Landroid/view/View;I)Ljava/lang/String;"); // Call the method on the object jstring result = (jstring)env->CallObjectMethod(_dw_obj, listOrComboBoxGetText, handle, index); // Get the UTF8 string result @@ -1829,7 +1880,20 @@ */ int API dw_listbox_selected_multi(HWND handle, int where) { - return DW_ERROR_UNKNOWN; + JNIEnv *env; + int retval = DW_ERROR_UNKNOWN; + + if(handle && (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 listBoxSelectedMulti = env->GetMethodID(clazz, "listBoxSelectedMulti", + "(Landroid/view/View;I)I"); + // Call the method on the object + retval = env->CallIntMethod(_dw_obj, listBoxSelectedMulti, handle, where); + } + return retval; } /* diff -r 167af4b0004b -r 5f92284e2b08 dwtest.c --- a/dwtest.c Sat May 08 23:22:52 2021 +0000 +++ b/dwtest.c Sun May 09 09:31:14 2021 +0000 @@ -643,9 +643,9 @@ unsigned int idx; int len; long spvalue; - char buf1[100]; - char buf2[100]; - char buf3[500]; + char buf1[100] = {0}; + char buf2[100] = {0}; + char buf3[500] = {0}; idx = dw_listbox_selected(combobox1); dw_listbox_get_text(combobox1, idx, buf1, 99);