diff --git a/imgui-binding/src/main/java/imgui/ImGuiListClipper.java b/imgui-binding/src/main/java/imgui/ImGuiListClipper.java
new file mode 100644
index 0000000..f6f5b3a
--- /dev/null
+++ b/imgui-binding/src/main/java/imgui/ImGuiListClipper.java
@@ -0,0 +1,65 @@
+package imgui;
+
+import imgui.callbacks.ImListClipperCallback;
+
+/**
+ * Helper: Manually clip large list of items.
+ * If you are submitting lots of evenly spaced items and you have a random access to the list, you can perform coarse clipping based on visibility to save yourself from processing those items at all.
+ * The clipper calculates the range of visible items and advance the cursor to compensate for the non-visible items we have skipped.
+ * ImGui already clip items based on their bounds but it needs to measure text size to do so. Coarse clipping before submission makes this cost and your own data fetching/submission cost null.
+ * Usage:
+ *
+ * ImGuiListClipper clipper(1000); // we have 1000 elements, evenly spaced.
+ * while (clipper.Step())
+ * for (int i = clipper.DisplayStart; i {@code <} clipper.DisplayEnd; i++)
+ * ImGui::Text("line number %d", i);
+ *
+ * - Step 0: the clipper let you process the first element, regardless of it being visible or not, so we can measure the element height (step skipped if we passed a known height as second arg to constructor).
+ * - Step 1: the clipper infer height from first element, calculate the actual range of elements to display, and position the cursor before the first element.
+ * - (Step 2: dummy step only required if an explicit items_height was passed to constructor or Begin() and user call Step(). Does nothing and switch to Step 3.)
+ * - Step 3: the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd), advance the cursor to the end of the list and then returns 'false' to end the loop.
+ *
+ * BINDING NOTICE:
+ * It's impossible to implement the same API like in the original. Method {@link #forEach(int, int, ImListClipperCallback)} could be used instead.
+ *
+ * ImGuiListClipper.forEach(1000, new ImListClipperCallback() {
+ * public void accept(int index) {
+ * ImGui.text(String.format("line number %d", index));
+ * }
+ * });
+ *
+ */
+public final class ImGuiListClipper {
+ private ImGuiListClipper() {
+ }
+
+ /*JNI
+ #include
+ #include "jni_callbacks.h"
+ */
+
+ /**
+ * @param itemsCount Use -1 to ignore (you can call Begin later).
+ * Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step).
+ * @param callback action to do in iterations
+ */
+ public static void forEach(final int itemsCount, final ImListClipperCallback callback) {
+ forEach(itemsCount, -1, callback);
+ }
+
+ /**
+ * @param itemsCount Use -1 to ignore (you can call Begin later).
+ * Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step).
+ * @param itemsHeight Use -1.0f to be calculated automatically on first step.
+ * Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or GetFrameHeightWithSpacing().
+ * @param callback action to do in iterations
+ */
+ public static native void forEach(int itemsCount, int itemsHeight, ImListClipperCallback callback); /*
+ ImGuiListClipper clipper(itemsCount);
+ while (clipper.Step()) {
+ for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
+ Jni::CallImListClipperCallback(env, callback, i);
+ }
+ }
+ */
+}
diff --git a/imgui-binding/src/main/java/imgui/callbacks/ImListClipperCallback.java b/imgui-binding/src/main/java/imgui/callbacks/ImListClipperCallback.java
new file mode 100644
index 0000000..de459bc
--- /dev/null
+++ b/imgui-binding/src/main/java/imgui/callbacks/ImListClipperCallback.java
@@ -0,0 +1,8 @@
+package imgui.callbacks;
+
+/**
+ * Callback for {@link imgui.ImGuiListClipper} class.
+ */
+public abstract class ImListClipperCallback {
+ public abstract void accept(int index);
+}
diff --git a/imgui-binding/src/main/java/imgui/callbacks/ImStrConsumer.java b/imgui-binding/src/main/java/imgui/callbacks/ImStrConsumer.java
index 89042e8..d0d2ac1 100644
--- a/imgui-binding/src/main/java/imgui/callbacks/ImStrConsumer.java
+++ b/imgui-binding/src/main/java/imgui/callbacks/ImStrConsumer.java
@@ -1,11 +1,8 @@
package imgui.callbacks;
-import java.util.function.Consumer;
-
/**
* Callback to supply Java string form native code.
*/
-public abstract class ImStrConsumer implements Consumer {
- @Override
+public abstract class ImStrConsumer {
public abstract void accept(String str);
}
diff --git a/imgui-binding/src/main/java/imgui/callbacks/ImStrSupplier.java b/imgui-binding/src/main/java/imgui/callbacks/ImStrSupplier.java
index 64781f1..d8f2be8 100644
--- a/imgui-binding/src/main/java/imgui/callbacks/ImStrSupplier.java
+++ b/imgui-binding/src/main/java/imgui/callbacks/ImStrSupplier.java
@@ -1,11 +1,8 @@
package imgui.callbacks;
-import java.util.function.Supplier;
-
/**
* Callback to get Java string from native code.
*/
-public abstract class ImStrSupplier implements Supplier {
- @Override
+public abstract class ImStrSupplier {
public abstract String get();
}
diff --git a/imgui-binding/src/main/native/jni_callbacks.cpp b/imgui-binding/src/main/native/jni_callbacks.cpp
index da41dba..2eee850 100644
--- a/imgui-binding/src/main/native/jni_callbacks.cpp
+++ b/imgui-binding/src/main/native/jni_callbacks.cpp
@@ -1,23 +1,32 @@
#include "jni_callbacks.h"
+jmethodID jImListClipperCallbackAcceptMID;
+
jmethodID jImStrConsumerAcceptMID;
jmethodID jImStrSupplierGetMID;
namespace Jni
{
-void InitCallbacks(JNIEnv* env) {
- jclass jImStrConsumer = env->FindClass("imgui/callbacks/ImStrConsumer");
- jImStrConsumerAcceptMID = env->GetMethodID(jImStrConsumer, "accept", "(Ljava/lang/String;)V");
+ void InitCallbacks(JNIEnv* env) {
+ jclass jImListClipperCallback = env->FindClass("imgui/callbacks/ImListClipperCallback");
+ jImListClipperCallbackAcceptMID = env->GetMethodID(jImListClipperCallback, "accept", "(I)V");
- jclass jImStrSupplier = env->FindClass("imgui/callbacks/ImStrSupplier");
- jImStrSupplierGetMID = env->GetMethodID(jImStrSupplier, "get", "()Ljava/lang/String;");
-}
+ jclass jImStrConsumer = env->FindClass("imgui/callbacks/ImStrConsumer");
+ jImStrConsumerAcceptMID = env->GetMethodID(jImStrConsumer, "accept", "(Ljava/lang/String;)V");
-void CallImStrConsumer(JNIEnv* env, jobject consumer, const char* str) {
- env->CallVoidMethod(consumer, jImStrConsumerAcceptMID, env->NewStringUTF(str));
-}
+ jclass jImStrSupplier = env->FindClass("imgui/callbacks/ImStrSupplier");
+ jImStrSupplierGetMID = env->GetMethodID(jImStrSupplier, "get", "()Ljava/lang/String;");
+ }
-jstring CallImStrSupplier(JNIEnv* env, jobject supplier) {
- return (jstring)env->CallObjectMethod(supplier, jImStrSupplierGetMID);
-}
+ void CallImListClipperCallback(JNIEnv* env, jobject consumer, int index) {
+ env->CallVoidMethod(consumer, jImListClipperCallbackAcceptMID, index);
+ }
+
+ void CallImStrConsumer(JNIEnv* env, jobject consumer, const char* str) {
+ env->CallVoidMethod(consumer, jImStrConsumerAcceptMID, env->NewStringUTF(str));
+ }
+
+ jstring CallImStrSupplier(JNIEnv* env, jobject supplier) {
+ return (jstring)env->CallObjectMethod(supplier, jImStrSupplierGetMID);
+ }
}
diff --git a/imgui-binding/src/main/native/jni_callbacks.h b/imgui-binding/src/main/native/jni_callbacks.h
index a85caac..4307b86 100644
--- a/imgui-binding/src/main/native/jni_callbacks.h
+++ b/imgui-binding/src/main/native/jni_callbacks.h
@@ -5,10 +5,13 @@
namespace Jni
{
-void InitCallbacks(JNIEnv* env);
+ void InitCallbacks(JNIEnv* env);
-void CallImStrConsumer(JNIEnv* env, jobject consumer, const char* str);
-jstring CallImStrSupplier(JNIEnv* env, jobject supplier);
+ void CallImListClipperCallback(JNIEnv* env, jobject consumer, int index);
+
+ void CallImStrConsumer(JNIEnv* env, jobject consumer, const char* str);
+
+ jstring CallImStrSupplier(JNIEnv* env, jobject supplier);
}
#endif
diff --git a/imgui-binding/src/main/native/jni_common.cpp b/imgui-binding/src/main/native/jni_common.cpp
index b2e8599..aa2a5ef 100644
--- a/imgui-binding/src/main/native/jni_common.cpp
+++ b/imgui-binding/src/main/native/jni_common.cpp
@@ -12,58 +12,58 @@ static JavaVM* jvm;
namespace Jni
{
-void InitCommon(JNIEnv* env) {
- env->GetJavaVM(&jvm);
+ void InitCommon(JNIEnv* env) {
+ env->GetJavaVM(&jvm);
- jclass jImVec2Class = env->FindClass("imgui/ImVec2");
- imVec2XID = env->GetFieldID(jImVec2Class, "x", "F");
- imVec2YID = env->GetFieldID(jImVec2Class, "y", "F");
+ jclass jImVec2Class = env->FindClass("imgui/ImVec2");
+ imVec2XID = env->GetFieldID(jImVec2Class, "x", "F");
+ imVec2YID = env->GetFieldID(jImVec2Class, "y", "F");
- jclass jImVec4Class = env->FindClass("imgui/ImVec4");
- imVec4XID = env->GetFieldID(jImVec4Class, "x", "F");
- imVec4YID = env->GetFieldID(jImVec4Class, "y", "F");
- imVec4ZID = env->GetFieldID(jImVec4Class, "z", "F");
- imVec4WID = env->GetFieldID(jImVec4Class, "w", "F");
-}
+ jclass jImVec4Class = env->FindClass("imgui/ImVec4");
+ imVec4XID = env->GetFieldID(jImVec4Class, "x", "F");
+ imVec4YID = env->GetFieldID(jImVec4Class, "y", "F");
+ imVec4ZID = env->GetFieldID(jImVec4Class, "z", "F");
+ imVec4WID = env->GetFieldID(jImVec4Class, "w", "F");
+ }
-JNIEnv* GetEnv() {
- JNIEnv* env;
- jint res = jvm->GetEnv((void**)(&env), JNI_VERSION_1_8);
- assert(res == JNI_OK);
- return env;
-}
+ JNIEnv* GetEnv() {
+ JNIEnv* env;
+ jint res = jvm->GetEnv((void**)(&env), JNI_VERSION_1_8);
+ assert(res == JNI_OK);
+ return env;
+ }
-void ImVec2Cpy(JNIEnv* env, ImVec2* src, jobject dst) {
- env->SetFloatField(dst, imVec2XID, src->x);
- env->SetFloatField(dst, imVec2YID, src->y);
-}
+ void ImVec2Cpy(JNIEnv* env, ImVec2* src, jobject dst) {
+ env->SetFloatField(dst, imVec2XID, src->x);
+ env->SetFloatField(dst, imVec2YID, src->y);
+ }
-void ImVec2Cpy(JNIEnv* env, ImVec2 src, jobject dst) {
- env->SetFloatField(dst, imVec2XID, src.x);
- env->SetFloatField(dst, imVec2YID, src.y);
-}
+ void ImVec2Cpy(JNIEnv* env, ImVec2 src, jobject dst) {
+ env->SetFloatField(dst, imVec2XID, src.x);
+ env->SetFloatField(dst, imVec2YID, src.y);
+ }
-void ImVec2Cpy(JNIEnv* env, jobject src, ImVec2* dst) {
- dst->x = env->GetFloatField(src, imVec2XID);
- dst->y = env->GetFloatField(src, imVec2YID);
-}
+ void ImVec2Cpy(JNIEnv* env, jobject src, ImVec2* dst) {
+ dst->x = env->GetFloatField(src, imVec2XID);
+ dst->y = env->GetFloatField(src, imVec2YID);
+ }
-void ImVec2Cpy(JNIEnv* env, jobject src, ImVec2 dst) {
- dst.x = env->GetFloatField(src, imVec2XID);
- dst.y = env->GetFloatField(src, imVec2YID);
-}
+ void ImVec2Cpy(JNIEnv* env, jobject src, ImVec2 dst) {
+ dst.x = env->GetFloatField(src, imVec2XID);
+ dst.y = env->GetFloatField(src, imVec2YID);
+ }
-void ImVec4Cpy(JNIEnv* env, ImVec4* src, jobject dst) {
- env->SetFloatField(dst, imVec4XID, src->x);
- env->SetFloatField(dst, imVec4YID, src->y);
- env->SetFloatField(dst, imVec4ZID, src->z);
- env->SetFloatField(dst, imVec4WID, src->w);
-}
+ void ImVec4Cpy(JNIEnv* env, ImVec4* src, jobject dst) {
+ env->SetFloatField(dst, imVec4XID, src->x);
+ env->SetFloatField(dst, imVec4YID, src->y);
+ env->SetFloatField(dst, imVec4ZID, src->z);
+ env->SetFloatField(dst, imVec4WID, src->w);
+ }
-void ImVec4Cpy(JNIEnv* env, ImVec4 src, jobject dst) {
- env->SetFloatField(dst, imVec4XID, src.x);
- env->SetFloatField(dst, imVec4YID, src.y);
- env->SetFloatField(dst, imVec4ZID, src.z);
- env->SetFloatField(dst, imVec4WID, src.w);
-}
+ void ImVec4Cpy(JNIEnv* env, ImVec4 src, jobject dst) {
+ env->SetFloatField(dst, imVec4XID, src.x);
+ env->SetFloatField(dst, imVec4YID, src.y);
+ env->SetFloatField(dst, imVec4ZID, src.z);
+ env->SetFloatField(dst, imVec4WID, src.w);
+ }
}
diff --git a/imgui-binding/src/main/native/jni_common.h b/imgui-binding/src/main/native/jni_common.h
index 63150e3..056cc92 100644
--- a/imgui-binding/src/main/native/jni_common.h
+++ b/imgui-binding/src/main/native/jni_common.h
@@ -6,18 +6,18 @@
namespace Jni
{
-void InitCommon(JNIEnv* env);
+ void InitCommon(JNIEnv* env);
-JNIEnv* GetEnv();
+ JNIEnv* GetEnv();
-void ImVec2Cpy(JNIEnv* env, ImVec2* src, jobject dst);
-void ImVec2Cpy(JNIEnv* env, ImVec2 src, jobject dst);
+ void ImVec2Cpy(JNIEnv* env, ImVec2* src, jobject dst);
+ void ImVec2Cpy(JNIEnv* env, ImVec2 src, jobject dst);
-void ImVec2Cpy(JNIEnv* env, jobject src, ImVec2* dst);
-void ImVec2Cpy(JNIEnv* env, jobject src, ImVec2 dst);
+ void ImVec2Cpy(JNIEnv* env, jobject src, ImVec2* dst);
+ void ImVec2Cpy(JNIEnv* env, jobject src, ImVec2 dst);
-void ImVec4Cpy(JNIEnv* env, ImVec4* src, jobject dst);
-void ImVec4Cpy(JNIEnv* env, ImVec4 src, jobject dst);
+ void ImVec4Cpy(JNIEnv* env, ImVec4* src, jobject dst);
+ void ImVec4Cpy(JNIEnv* env, ImVec4 src, jobject dst);
}
#endif