diff --git a/example/src/main/java/ExampleInputTextCallback.java b/example/src/main/java/ExampleInputTextCallback.java new file mode 100644 index 0000000..de6b23d --- /dev/null +++ b/example/src/main/java/ExampleInputTextCallback.java @@ -0,0 +1,44 @@ +import imgui.ImGui; +import imgui.ImGuiInputTextCallbackData; +import imgui.callback.ImGuiInputTextCallback; +import imgui.flag.ImGuiCond; +import imgui.flag.ImGuiInputTextFlags; +import imgui.type.ImBoolean; +import imgui.type.ImString; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +public class ExampleInputTextCallback { + private static final ImString STR = new ImString(); + private static final StringBuilder OUTPUT = new StringBuilder(); + private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"); + + private static final ImGuiInputTextCallback CALLBACK = new ImGuiInputTextCallback() { + @Override + public void accept(final ImGuiInputTextCallbackData data) { + final char c = (char) data.getEventChar(); + if (c == 'h' || c == 'H') { + data.setEventChar('!'); + OUTPUT.append(DATE_FORMAT.format(LocalDateTime.now())).append(" :: Replaced!\n"); + } else if (c == 'w' || c == 'W') { + data.setEventChar(0); + OUTPUT.append(DATE_FORMAT.format(LocalDateTime.now())).append(" :: Discarded!\n"); + } else { + OUTPUT.append(DATE_FORMAT.format(LocalDateTime.now())).append(" :: Typed: ").append(c).append('\n'); + } + } + }; + + public static void show(final ImBoolean showInputTextCallback) { + ImGui.setNextWindowSize(400, 300, ImGuiCond.Once); + if (ImGui.begin("Input Text Callback Demo", showInputTextCallback)) { + ImGui.alignTextToFramePadding(); + ImGui.text("Try to input \"Hello World!\":"); + ImGui.sameLine(); + ImGui.inputText("##input", STR, ImGuiInputTextFlags.CallbackCharFilter, CALLBACK); + ImGui.text(OUTPUT.toString()); + } + ImGui.end(); + } +} diff --git a/example/src/main/java/Extra.java b/example/src/main/java/Extra.java index bc9ce4c..6f1d599 100644 --- a/example/src/main/java/Extra.java +++ b/example/src/main/java/Extra.java @@ -13,6 +13,7 @@ public class Extra { private static final ImBoolean SHOW_IMGUI_FILE_DIALOG_WINDOW = new ImBoolean(false); private static final ImBoolean SHOW_IMGUI_MEMORY_EDITOR_WINDOW = new ImBoolean(false); private static final ImBoolean SHOW_IMGUI_CANVAS_EDITOR_WINDOW = new ImBoolean(false); + private static final ImBoolean SHOW_IMGUI_INPUT_CALLBACK_WINDOW = new ImBoolean(false); private static final Graph GRAPH = new Graph(); @@ -28,6 +29,7 @@ public class Extra { ImGui.checkbox("Show ImGuiFileDialog Demo Window", SHOW_IMGUI_FILE_DIALOG_WINDOW); ImGui.checkbox("Show ImGui MemoryEditor Demo Window", SHOW_IMGUI_MEMORY_EDITOR_WINDOW); ImGui.checkbox("Show ImGui Canvas Demo Window", SHOW_IMGUI_CANVAS_EDITOR_WINDOW); + ImGui.checkbox("Show Imgui InputText Callback Window", SHOW_IMGUI_INPUT_CALLBACK_WINDOW); if (SHOW_DEMO_WINDOW.get()) { ImGui.showDemoWindow(SHOW_DEMO_WINDOW); @@ -68,5 +70,9 @@ public class Extra { if (SHOW_IMGUI_CANVAS_EDITOR_WINDOW.get()) { ExampleCanvasEditor.show(SHOW_IMGUI_CANVAS_EDITOR_WINDOW); } + + if (SHOW_IMGUI_INPUT_CALLBACK_WINDOW.get()) { + ExampleInputTextCallback.show(SHOW_IMGUI_INPUT_CALLBACK_WINDOW); + } } } diff --git a/imgui-binding/src/main/java/imgui/ImGui.java b/imgui-binding/src/main/java/imgui/ImGui.java index 05dacda..3994780 100644 --- a/imgui-binding/src/main/java/imgui/ImGui.java +++ b/imgui-binding/src/main/java/imgui/ImGui.java @@ -1,6 +1,7 @@ package imgui; import imgui.assertion.ImAssertCallback; +import imgui.callback.ImGuiInputTextCallback; import imgui.flag.ImGuiCond; import imgui.flag.ImGuiDragDropFlags; import imgui.flag.ImGuiInputTextFlags; @@ -2988,11 +2989,13 @@ public class ImGui { /*JNI jmethodID jImStringResizeInternalMID; + jmethodID jInputTextCallbackMID; jfieldID inputDataSizeID; jfieldID inputDataIsDirtyID; jfieldID inputDataIsResizedID; + struct InputTextCallbackUserData { JNIEnv* env; jobject* imString; @@ -3001,6 +3004,7 @@ public class ImGui { char* resizedBuf; jobject* textInputData; char* allowedChars; + jobject* handler; }; static int TextEditCallbackStub(ImGuiInputTextCallbackData* data) { @@ -3033,6 +3037,11 @@ public class ImGui { } } + if (userData->handler != NULL) { + JNIEnv* env = userData->env; + env->CallObjectMethod(*userData->handler, jInputTextCallbackMID, data); + } + return 0; } */ @@ -3045,41 +3054,68 @@ public class ImGui { jclass jImString = env->FindClass("imgui/type/ImString"); jImStringResizeInternalMID = env->GetMethodID(jImString, "resizeInternal", "(I)[B"); + + jclass jCallback = env->FindClass("imgui/callback/ImGuiInputTextCallback"); + jInputTextCallbackMID = env->GetMethodID(jCallback, "accept", "(J)V"); */ public static boolean inputText(String label, ImString text) { - return preInputText(false, label, null, text, 0, 0, ImGuiInputTextFlags.None); + return preInputText(false, label, null, text); } public static boolean inputText(String label, ImString text, int imGuiInputTextFlags) { return preInputText(false, label, null, text, 0, 0, imGuiInputTextFlags); } + public static boolean inputText(String label, ImString text, int imGuiInputTextFlags, ImGuiInputTextCallback callback) { + return preInputText(false, label, null, text, 0, 0, imGuiInputTextFlags, callback); + } + public static boolean inputTextMultiline(String label, ImString text) { - return preInputText(true, label, null, text, 0, 0, ImGuiInputTextFlags.None); + return preInputText(true, label, null, text); } public static boolean inputTextMultiline(String label, ImString text, float width, float height) { - return preInputText(true, label, null, text, width, height, ImGuiInputTextFlags.None); + return preInputText(true, label, null, text, width, height); } public static boolean inputTextMultiline(String label, ImString text, int imGuiInputTextFlags) { return preInputText(true, label, null, text, 0, 0, imGuiInputTextFlags); } + public static boolean inputTextMultiline(String label, ImString text, int imGuiInputTextFlags, ImGuiInputTextCallback callback) { + return preInputText(true, label, null, text, 0, 0, imGuiInputTextFlags, callback); + } + public static boolean inputTextMultiline(String label, ImString text, float width, float height, int imGuiInputTextFlags) { return preInputText(true, label, null, text, width, height, imGuiInputTextFlags); } + public static boolean inputTextMultiline(String label, ImString text, float width, float height, int imGuiInputTextFlags, ImGuiInputTextCallback callback) { + return preInputText(true, label, null, text, width, height, imGuiInputTextFlags, callback); + } + public static boolean inputTextWithHint(String label, String hint, ImString text) { - return preInputText(false, label, hint, text, 0, 0, ImGuiInputTextFlags.None); + return preInputText(false, label, hint, text); } public static boolean inputTextWithHint(String label, String hint, ImString text, int imGuiInputTextFlags) { return preInputText(false, label, hint, text, 0, 0, imGuiInputTextFlags); } + private static boolean preInputText(boolean multiline, String label, String hint, ImString text) { + return preInputText(multiline, label, hint, text, 0, 0); + } + + private static boolean preInputText(boolean multiline, String label, String hint, ImString text, float width, float height) { + return preInputText(multiline, label, hint, text, width, height, ImGuiInputTextFlags.None); + } + private static boolean preInputText(boolean multiline, String label, String hint, ImString text, float width, float height, int flags) { + return preInputText(multiline, label, hint, text, width, height, flags, null); + } + + private static boolean preInputText(boolean multiline, String label, String hint, ImString text, float width, float height, int flags, ImGuiInputTextCallback callback) { final ImString.InputData inputData = text.inputData; if (inputData.isResizable) { @@ -3095,10 +3131,10 @@ public class ImGui { hintLabel = ""; } - return nInputText(multiline, hint != null, label, hintLabel, text, text.getData(), text.getData().length, width, height, flags, inputData, inputData.allowedChars); + return nInputText(multiline, hint != null, label, hintLabel, text, text.getData(), text.getData().length, width, height, flags, inputData, inputData.allowedChars, callback); } - private static native boolean nInputText(boolean multiline, boolean hint, String label, String hintLabel, ImString imString, byte[] buf, int maxSize, float width, float height, int flags, ImString.InputData textInputData, String allowedChars); /* + private static native boolean nInputText(boolean multiline, boolean hint, String label, String hintLabel, ImString imString, byte[] buf, int maxSize, float width, float height, int flags, ImString.InputData textInputData, String allowedChars, ImGuiInputTextCallback callback); /* InputTextCallbackUserData userData; userData.imString = &imString; userData.maxSize = maxSize; @@ -3107,6 +3143,7 @@ public class ImGui { userData.textInputData = &textInputData; userData.env = env; userData.allowedChars = allowedChars; + userData.handler = &callback; bool valueChanged; diff --git a/imgui-binding/src/main/java/imgui/ImGuiInputTextCallbackData.java b/imgui-binding/src/main/java/imgui/ImGuiInputTextCallbackData.java new file mode 100644 index 0000000..c5943eb --- /dev/null +++ b/imgui-binding/src/main/java/imgui/ImGuiInputTextCallbackData.java @@ -0,0 +1,182 @@ +package imgui; + +import imgui.binding.ImGuiStruct; + +/** + * Shared state of InputText(), passed as an argument to your callback when a ImGuiInputTextFlags_Callback* flag is used.
+ * The callback function should return 0 by default.
+ * Callbacks (follow a flag name and see comments in ImGuiInputTextFlags_ declarations for more details)
+ * - ImGuiInputTextFlags_CallbackEdit: Callback on buffer edit (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the underlying buffer while focus is active)
+ * - ImGuiInputTextFlags_CallbackAlways: Callback on each iteration
+ * - ImGuiInputTextFlags_CallbackCompletion: Callback on pressing TAB
+ * - ImGuiInputTextFlags_CallbackHistory: Callback on pressing Up/Down arrows
+ * - ImGuiInputTextFlags_CallbackCharFilter: Callback on character inputs to replace or discard them. Modify 'EventChar' to replace or discard, or return 1 in callback to discard.
+ * - ImGuiInputTextFlags_CallbackResize: Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow.
+ */ +public class ImGuiInputTextCallbackData extends ImGuiStruct { + public ImGuiInputTextCallbackData(final long ptr) { + super(ptr); + } + + /*JNI + #include "_common.h" + + #define IMGUI_CALLBACK_DATA ((ImGuiInputTextCallbackData*)STRUCT_PTR) + */ + + /** + * One ImGuiInputTextFlags_Callback* + * + * @return ImGuiInputTextFlags + */ + public native int getEventFlag(); /* + return IMGUI_CALLBACK_DATA->EventFlag; + */ + + /** + * What user passed to InputText() + * + * @return ImGuiInputTextFlags + */ + public native int getFlags(); /* + return IMGUI_CALLBACK_DATA->Flags; + */ + + /** + * [CharFilter] Character input; + * + * @return Character input + */ + public native int getEventChar(); /* + return IMGUI_CALLBACK_DATA->EventChar; + */ + + /** + * [CharFilter] Replace character with another one, or set to zero to drop. return 1 is equivalent to setting EventChar=0; + * + * @param c Replaced characters + */ + public void setEventChar(final char c) { + setEventChar((int) c); + } + + /** + * [CharFilter] Replace character with another one, or set to zero to drop. return 1 is equivalent to setting EventChar=0; + * + * @param c Replaced characters + */ + public native void setEventChar(int c); /* + IMGUI_CALLBACK_DATA->EventChar = c; + */ + + /** + * [Completion,History] + * + * @return Key pressed (Up/Down/TAB) + */ + public native int getEventKey(); /* + return IMGUI_CALLBACK_DATA->EventKey; + */ + + /** + * [Resize] Can replace pointer
+ * [Completion,History,Always] Only write to pointed data, don't replace the actual pointer!
+ *
+ * @return Buf
+ */
+ public native String getBuf(); /*
+ return env->NewStringUTF(IMGUI_CALLBACK_DATA->Buf);
+ */
+
+ /**
+ * Set if you modify Buf/BufTextLen!
+ *
+ * @return Dirty
+ */
+ public native boolean getBufDirty(); /*
+ return IMGUI_CALLBACK_DATA->BufDirty;
+ */
+
+ /**
+ * Set if you modify Buf/BufTextLen!
+ *
+ * @param dirty Dirty
+ */
+ public native void setBufDirty(boolean dirty); /*
+ IMGUI_CALLBACK_DATA->BufDirty = dirty;
+ */
+
+ /**
+ * Current cursor position
+ *
+ * @return Current cursor position
+ */
+ public native int getCursorPos(); /*
+ return IMGUI_CALLBACK_DATA->CursorPos;
+ */
+
+ /**
+ * Set the current cursor position
+ *
+ * @param pos Set the current cursor position
+ */
+ public native void setCursorPos(int pos); /*
+ IMGUI_CALLBACK_DATA->CursorPos = pos;
+ */
+
+ /**
+ * Selection Start
+ *
+ * @return Selection Start
+ */
+ public native int getSelectionStart(); /*
+ return IMGUI_CALLBACK_DATA->SelectionStart;
+ */
+
+ /**
+ * Set Selection Start
+ *
+ * @param pos Selection Start
+ */
+ public native void setSelectionStart(int pos); /*
+ IMGUI_CALLBACK_DATA->SelectionStart = pos;
+ */
+
+ /**
+ * Selection End
+ *
+ * @return Selection End
+ */
+ public native int getSelectionEnd(); /*
+ return IMGUI_CALLBACK_DATA->SelectionEnd;
+ */
+
+ /**
+ * Set Selection End
+ *
+ * @param pos Selection End
+ */
+ public native void setSelectionEnd(int pos); /*
+ IMGUI_CALLBACK_DATA->SelectionEnd = pos;
+ */
+
+ /**
+ * Delete Chars
+ *
+ * @param pos Start Delete Pos
+ * @param bytesCount Delete Char Count
+ */
+ public native void deleteChars(int pos, int bytesCount); /*
+ IMGUI_CALLBACK_DATA->DeleteChars(pos, bytesCount);
+ */
+
+ /**
+ * Insert Chars
+ *
+ * @param pos insert Psos
+ * @param str insert String
+ */
+ public native void insertChars(int pos, String str); /*
+ IMGUI_CALLBACK_DATA->InsertChars(pos, str);
+ */
+}
diff --git a/imgui-binding/src/main/java/imgui/callback/ImGuiInputTextCallback.java b/imgui-binding/src/main/java/imgui/callback/ImGuiInputTextCallback.java
new file mode 100644
index 0000000..7cbc047
--- /dev/null
+++ b/imgui-binding/src/main/java/imgui/callback/ImGuiInputTextCallback.java
@@ -0,0 +1,17 @@
+package imgui.callback;
+
+import imgui.ImGuiInputTextCallbackData;
+
+import java.util.function.Consumer;
+
+/**
+ * Callback to use in {@link imgui.ImGui#inputText(String, imgui.type.ImString, int, ImGuiInputTextCallback)}.
+ */
+public abstract class ImGuiInputTextCallback implements Consumer