Add ImString resize support

This commit is contained in:
SpaiR committed 2020-01-01 13:41:44 +03:00
1 parent 295471930f
commit fbf1c0d1c2
4 files changed
+155 -103

No files matched your search

+69 -75
View File
@@ -1,5 +1,7 @@
package imgui; package imgui;
import imgui.enums.ImGuiInputTextFlags;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
public final class ImGui { public final class ImGui {
@@ -2382,25 +2384,26 @@ public final class ImGui {
/*JNI /*JNI
jfieldID imTextInputDataSizeID; jfieldID imTextInputDataSizeID;
jfieldID imTextInputDataIsDirtyID; jfieldID imTextInputDataIsDirtyID;
jfieldID imTextInputDataIsResizedID;
struct InputTextCallback_UserData { char* resizedBuf;
jobject* textInputData;
struct InputTextCallbackUserData {
JNIEnv* env; JNIEnv* env;
int maxChar; jobject* textInputData;
char* allowedChar; char* buf;
int allowedCharLength; char* allowedChars;
int maxSize;
int curSize;
}; };
static int TextEditCallbackStub(ImGuiInputTextCallbackData* data) { static int TextEditCallbackStub(ImGuiInputTextCallbackData* data) {
InputTextCallback_UserData* userData = (InputTextCallback_UserData*)data->UserData; InputTextCallbackUserData* userData = (InputTextCallbackUserData*)data->UserData;
if (data->EventFlag == ImGuiInputTextFlags_CallbackCharFilter) { if (data->EventFlag == ImGuiInputTextFlags_CallbackCharFilter) {
if(userData->allowedCharLength > 0) { int allowedCharLength = strlen(userData->allowedChars);
if(allowedCharLength > 0) {
bool found = false; bool found = false;
for(int i = 0; i < userData->allowedCharLength; i++) { for(int i = 0; i < allowedCharLength; i++) {
if(userData->allowedChar[i] == data->EventChar) { if(userData->allowedChars[i] == data->EventChar) {
found = true; found = true;
break; break;
} }
@@ -2417,94 +2420,85 @@ public final class ImGui {
jclass jImInputTextDataClass = env->FindClass("imgui/ImGuiInputTextData"); jclass jImInputTextDataClass = env->FindClass("imgui/ImGuiInputTextData");
imTextInputDataSizeID = env->GetFieldID(jImInputTextDataClass, "size", "I"); imTextInputDataSizeID = env->GetFieldID(jImInputTextDataClass, "size", "I");
imTextInputDataIsDirtyID = env->GetFieldID(jImInputTextDataClass, "isDirty", "Z"); imTextInputDataIsDirtyID = env->GetFieldID(jImInputTextDataClass, "isDirty", "Z");
imTextInputDataIsResizedID = env->GetFieldID(jImInputTextDataClass, "isResized", "Z");
*/ */
public static boolean InputText(String label, ImString text) { public static boolean InputText(String label, ImString text) {
return nInputText(label, text.data, text.data.length, 0, text.inputData, text.inputData.maxChar, text.inputData.allowedChar, text.inputData.allowedChar.length()); return preInputText(false, label, text, 0, 0, 0);
} }
public static boolean InputText(String label, ImString text, int imGuiInputTextFlags) { public static boolean InputText(String label, ImString text, int imGuiInputTextFlags) {
return nInputText(label, text.data, text.data.length, imGuiInputTextFlags, text.inputData, text.inputData.maxChar, text.inputData.allowedChar, text.inputData.allowedChar.length()); return preInputText(false, label, text, 0, 0, imGuiInputTextFlags);
} }
private static native boolean nInputText(String label, byte[] buff, int maxSize, int flags, ImGuiInputTextData textInputData, int maxChar, String allowedChar, int allowedCharLength); /*
int size = (int)strlen(buff);
InputTextCallback_UserData cb_user_data;
cb_user_data.textInputData = &textInputData;
cb_user_data.env = env;
cb_user_data.curSize = size;
cb_user_data.maxSize = maxSize;
cb_user_data.maxChar = maxChar;
cb_user_data.allowedChar = allowedChar;
cb_user_data.allowedCharLength = allowedCharLength;
char tempArray[maxSize];
memset(tempArray, 0, sizeof(tempArray));
memcpy(tempArray, buff, size);
if(maxChar >= 0 && maxChar < maxSize) {
maxSize = maxChar;
}
bool flag = ImGui::InputText(label, tempArray, maxSize, flags | ImGuiInputTextFlags_CallbackCharFilter, &TextEditCallbackStub, &cb_user_data);
if (flag) {
size = (int)strlen(tempArray);
env->SetIntField(textInputData, imTextInputDataSizeID, size);
env->SetBooleanField(textInputData, imTextInputDataIsDirtyID, true);
memset(buff, 0, maxSize);
memcpy(buff, tempArray, size);
}
return flag;
*/
public static boolean InputTextMultiline(String label, ImString text) { public static boolean InputTextMultiline(String label, ImString text) {
return nInputTextMultiline(label, text.data, text.data.length, 0, 0, 0, text.inputData, text.inputData.maxChar, text.inputData.allowedChar, text.inputData.allowedChar.length()); return preInputText(true, label, text, 0, 0, 0);
} }
public static boolean InputTextMultiline(String label, ImString text, float width, float height) { public static boolean InputTextMultiline(String label, ImString text, float width, float height) {
return nInputTextMultiline(label, text.data, text.data.length, width, height, 0, text.inputData, text.inputData.maxChar, text.inputData.allowedChar, text.inputData.allowedChar.length()); return preInputText(true, label, text, width, height, 0);
}
public static boolean InputTextMultiline(String label, ImString text, int imGuiInputTextFlags) {
return preInputText(true, label, text, 0, 0, imGuiInputTextFlags);
} }
public static boolean InputTextMultiline(String label, ImString text, float width, float height, int imGuiInputTextFlags) { public static boolean InputTextMultiline(String label, ImString text, float width, float height, int imGuiInputTextFlags) {
return nInputTextMultiline(label, text.data, text.data.length, width, height, imGuiInputTextFlags, text.inputData, text.inputData.maxChar, text.inputData.allowedChar, text.inputData.allowedChar.length()); return preInputText(true, label, text, width, height, imGuiInputTextFlags);
} }
private static native boolean nInputTextMultiline(String label, byte[] buff, int maxSize, float width, float height, int flags, ImGuiInputTextData textInputData, int maxChar, String allowedChar, int allowedCharLength); /* private static boolean preInputText(boolean multiline, String label, ImString text, float width, float height, int flags) {
int size = (int)strlen(buff); ImGuiInputTextData inputData = text.inputData;
InputTextCallback_UserData cb_user_data; if (inputData.isResizable) {
cb_user_data.textInputData = &textInputData; flags |= ImGuiInputTextFlags.CallbackResize;
cb_user_data.env = env;
cb_user_data.curSize = size;
cb_user_data.maxSize = maxSize;
cb_user_data.maxChar = maxChar;
cb_user_data.allowedChar = allowedChar;
cb_user_data.allowedCharLength = allowedCharLength;
char tempArray[maxSize];
memset(tempArray, 0, sizeof(tempArray));
memcpy(tempArray, buff, size);
if(maxChar >= 0 && maxChar < maxSize) {
maxSize = maxChar;
} }
bool flag = ImGui::InputTextMultiline(label, tempArray, maxSize, ImVec2(width, height), flags | ImGuiInputTextFlags_CallbackCharFilter, &TextEditCallbackStub, &cb_user_data); boolean hasInput = nInputText(multiline, label, text.data, text.data.length, width, height, flags, inputData, inputData.allowedChars);
if (inputData.isResized) {
inputData.isResized = false;
text.set(nGetResizedStr(), true);
}
return hasInput;
}
private static native boolean nInputText(boolean multiline, String label, byte[] buf, int maxSize, float width, float height, int flags, ImGuiInputTextData textInputData, String allowedChars); /*
InputTextCallbackUserData userData;
userData.textInputData = &textInputData;
userData.env = env;
userData.buf = buf;
userData.allowedChars = allowedChars;
if (strlen(allowedChars) > 0)
flags |= ImGuiInputTextFlags_CallbackCharFilter;
bool hasInput;
if (multiline) {
hasInput = ImGui::InputTextMultiline(label, buf, maxSize, ImVec2(width, height), flags, &TextEditCallbackStub, &userData);
} else {
hasInput = ImGui::InputText(label, buf, maxSize, flags, &TextEditCallbackStub, &userData);
}
if (hasInput) {
int size = strlen(buf);
if (((size + 1) > maxSize) && (flags & ImGuiInputTextFlags_CallbackResize)) {
env->SetBooleanField(textInputData, imTextInputDataIsResizedID, true);
resizedBuf = buf;
}
if (flag) {
size = (int)strlen(tempArray);
env->SetIntField(textInputData, imTextInputDataSizeID, size); env->SetIntField(textInputData, imTextInputDataSizeID, size);
env->SetBooleanField(textInputData, imTextInputDataIsDirtyID, true); env->SetBooleanField(textInputData, imTextInputDataIsDirtyID, true);
memset(buff, 0, maxSize);
memcpy(buff, tempArray, size);
} }
return flag; return hasInput;
*/
private static native String nGetResizedStr(); /*
return env->NewStringUTF(resizedBuf);
*/ */
public static boolean InputFloat(String label, ImFloat v) { public static boolean InputFloat(String label, ImFloat v) {
@@ -4522,7 +4516,7 @@ public final class ImGui {
*/ */
// Clipboard Utilities (also see the LogToClipboard() function to capture or output text data to the clipboard) // Clipboard Utilities (also see the LogToClipboard() function to capture or output text data to the clipboard)
public static native String GetClipboardText(); /* public static native String GetClipboardText(); /*
return env->NewStringUTF(ImGui::GetClipboardText()); return env->NewStringUTF(ImGui::GetClipboardText());
*/ */
@@ -1,8 +1,25 @@
package imgui; package imgui;
final class ImGuiInputTextData { /**
public int size; * Use this class to customize your ImGui input.
public int maxChar = -1; */
public String allowedChar = ""; public final class ImGuiInputTextData {
/**
* If not empty, then other chars which are different from provided will be filtered during the {@link ImGui#InputText(String, ImString)}
* and {@link ImGui#InputTextMultiline} methods.
*/
public String allowedChars = "";
/**
* If true, then string will be resized during the the {@link ImGui#InputText(String, ImString)} and {@link ImGui#InputTextMultiline} methods.
* Alternatively you can provide {@link imgui.enums.ImGuiInputTextFlags#CallbackResize} flag to the input text widgets to enable string resizing.
*/
public boolean isResizable;
int size;
boolean isDirty; boolean isDirty;
boolean isResized = false;
ImGuiInputTextData() {
}
} }
+52 -15
View File
@@ -1,20 +1,30 @@
package imgui; package imgui;
import java.util.Arrays; import java.util.Objects;
/**
* Wrapper for {@link String} to use inside of ImGui input widgets.
*/
public final class ImString { public final class ImString {
private static final int DEFAULT_SIZE = 100; private static final short DEFAULT_LENGTH = 100;
private static final short CARET_LEN = 1;
private static final short DEFAULT_RESIZE = 10;
public final ImGuiInputTextData inputData = new ImGuiInputTextData();
/**
* String will be resized to the value equal to a new size plus this resize factor.
*/
public int resizeFactor = DEFAULT_RESIZE;
ImGuiInputTextData inputData = new ImGuiInputTextData();
byte[] data; byte[] data;
private String text; private String text = "";
public ImString() { public ImString() {
this(DEFAULT_SIZE); this(DEFAULT_LENGTH);
} }
public ImString(int size) { public ImString(int length) {
data = new byte[size]; data = new byte[length + CARET_LEN];
} }
public ImString(String text) { public ImString(String text) {
@@ -22,8 +32,8 @@ public final class ImString {
set(text); set(text);
} }
public ImString(String text, int size) { public ImString(String text, int length) {
this(size); this(length);
set(text); set(text);
} }
@@ -36,11 +46,38 @@ public final class ImString {
} }
public void set(String value) { public void set(String value) {
inputData.size = value.length(); set(value.getBytes());
text = value; }
for (int i = 0; i < inputData.size; i++) {
data[i] = (byte) value.charAt(i); public void set(String value, boolean resize) {
byte[] str = value.getBytes();
if (resize && data.length - CARET_LEN < str.length) {
data = new byte[str.length + resizeFactor + CARET_LEN];
} }
set(str);
}
/**
* Get the length of the text inside of the data buffer.
* @return length of the text inside of the data buffer
*/
public int getLength() {
return get().length();
}
/**
* Get the size of the data buffer. Buffer size will always have '+1' to its size, since it's used by the Dear ImGui to draw a caret.
* @return size of the data buffer
*/
public int getBufferSize() {
return data.length;
}
private void set(byte[] str) {
int len = Math.min(str.length, data.length);
System.arraycopy(str, 0, data, 0, len);
inputData.isDirty = true;
inputData.size = len;
} }
@Override @Override
@@ -53,11 +90,11 @@ public final class ImString {
if (this == o) return true; if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false; if (o == null || getClass() != o.getClass()) return false;
ImString imString = (ImString) o; ImString imString = (ImString) o;
return Arrays.equals(data, imString.data); return Objects.equals(text, imString.text);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Arrays.hashCode(data); return text.hashCode();
} }
} }
@@ -47,11 +47,12 @@ public final class ImGuiGlfwExample {
private final ImGuiImplGl3 imGuiGl3 = new ImGuiImplGl3(); private final ImGuiImplGl3 imGuiGl3 = new ImGuiImplGl3();
// Local app variables go here // Local app variables go here
private final ImString imguiDemoLink = new ImString("https://raw.githubusercontent.com/ocornut/imgui/v1.74/imgui_demo.cpp", 100); private final String imguiDemoLink = "https://raw.githubusercontent.com/ocornut/imgui/v1.74/imgui_demo.cpp";
private float[] backgroundColor = new float[]{0.5f, 0, 0};
private int clickCount = 0;
private final byte[] testPayload = "Test Payload".getBytes(); private final byte[] testPayload = "Test Payload".getBytes();
private String dropTargetText = "Drop Here"; private String dropTargetText = "Drop Here";
private float[] backgroundColor = new float[]{0.5f, 0, 0};
private int clickCount = 0;
private final ImString resizableStr = new ImString(5);
private final ImBool showDemoWindow = new ImBool(); private final ImBool showDemoWindow = new ImBool();
@@ -273,11 +274,12 @@ public final class ImGuiGlfwExample {
} }
private void showUi() { private void showUi() {
ImGui.SetNextWindowSize(600, 210, ImGuiCond.Once); ImGui.SetNextWindowSize(600, 300, ImGuiCond.Once);
ImGui.SetNextWindowPos(10, 10, ImGuiCond.Once); ImGui.SetNextWindowPos(10, 10, ImGuiCond.Once);
ImGui.Begin("Custom window"); ImGui.Begin("Custom window");
ImGui.Text("Hello from Java!"); ImGui.Text("Hello from Java!");
ImGui.Button("Drag me"); ImGui.Button("Drag me");
if (ImGui.BeginDragDropSource()) { if (ImGui.BeginDragDropSource()) {
ImGui.SetDragDropPayload("payload_type", testPayload, testPayload.length); ImGui.SetDragDropPayload("payload_type", testPayload, testPayload.length);
@@ -298,6 +300,7 @@ public final class ImGuiGlfwExample {
ImGui.Text("Background color:"); ImGui.Text("Background color:");
ImGui.SameLine(); ImGui.SameLine();
ImGui.ColorEdit3("##click_counter_col", backgroundColor, ImGuiColorEditFlags.NoInputs | ImGuiColorEditFlags.NoDragDrop); ImGui.ColorEdit3("##click_counter_col", backgroundColor, ImGuiColorEditFlags.NoInputs | ImGuiColorEditFlags.NoDragDrop);
if (ImGui.Button("Click")) { if (ImGui.Button("Click")) {
clickCount++; clickCount++;
} }
@@ -309,16 +312,17 @@ public final class ImGuiGlfwExample {
ImGui.Checkbox("Show demo window", showDemoWindow); ImGui.Checkbox("Show demo window", showDemoWindow);
ImGui.NewLine(); ImGui.NewLine();
ImGui.InputText("Resizable input", resizableStr, ImGuiInputTextFlags.CallbackResize);
ImGui.Text(String.format("text len: %d | buffer size: %d", resizableStr.getLength(), resizableStr.getBufferSize()));
ImGui.NewLine();
ImGui.Separator(); ImGui.Separator();
ImGui.Text("Consider to look the original ImGui demo: "); ImGui.Text("Consider to look the original ImGui demo: ");
ImGui.SetNextItemWidth(500); ImGui.SetNextItemWidth(500);
ImGui.InputText("##input_to_copy_link", imguiDemoLink, ImGuiInputTextFlags.ReadOnly); ImGui.TextColored(0, .8f, 0, 1, imguiDemoLink);
if (ImGui.IsItemHovered()) {
ImGui.SetMouseCursor(ImGuiMouseCursor.TextInput);
}
ImGui.SameLine(); ImGui.SameLine();
if (ImGui.Button("Copy")) { if (ImGui.Button("Copy")) {
ImGui.SetClipboardText(imguiDemoLink.get()); ImGui.SetClipboardText(imguiDemoLink);
} }
} }