Improve string resize flow
This commit is contained in:
1 parent
b5a6ee1d2a
commit
937b37b75a
5 files changed
+154
-37
No files matched your search
@@ -9,6 +9,15 @@ plugins {
|
|||||||
|
|
||||||
sourceCompatibility = 1.8
|
sourceCompatibility = 1.8
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.5.2'
|
||||||
|
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.5.2")
|
||||||
|
}
|
||||||
|
|
||||||
|
test {
|
||||||
|
useJUnitPlatform()
|
||||||
|
}
|
||||||
|
|
||||||
assemble.dependsOn clean
|
assemble.dependsOn clean
|
||||||
task generateLibs(type: GenerateLibs, dependsOn: assemble)
|
task generateLibs(type: GenerateLibs, dependsOn: assemble)
|
||||||
|
|
||||||
|
|||||||
@@ -2397,7 +2397,7 @@ public final class ImGui {
|
|||||||
jfieldID imTextInputDataIsDirtyID;
|
jfieldID imTextInputDataIsDirtyID;
|
||||||
jfieldID imTextInputDataIsResizedID;
|
jfieldID imTextInputDataIsResizedID;
|
||||||
|
|
||||||
char* resizedBuf;
|
int resizeValue;
|
||||||
|
|
||||||
struct InputTextCallbackUserData {
|
struct InputTextCallbackUserData {
|
||||||
JNIEnv* env;
|
JNIEnv* env;
|
||||||
@@ -2434,6 +2434,10 @@ public final class ImGui {
|
|||||||
imTextInputDataIsResizedID = env->GetFieldID(jImInputTextDataClass, "isResized", "Z");
|
imTextInputDataIsResizedID = env->GetFieldID(jImInputTextDataClass, "isResized", "Z");
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
private static native int nGetResizeValue(); /*
|
||||||
|
return resizeValue;
|
||||||
|
*/
|
||||||
|
|
||||||
public static boolean inputText(String label, ImString text) {
|
public static boolean inputText(String label, ImString text) {
|
||||||
return preInputText(false, label, text, 0, 0, 0);
|
return preInputText(false, label, text, 0, 0, 0);
|
||||||
}
|
}
|
||||||
@@ -2469,7 +2473,7 @@ public final class ImGui {
|
|||||||
|
|
||||||
if (inputData.isResized) {
|
if (inputData.isResized) {
|
||||||
inputData.isResized = false;
|
inputData.isResized = false;
|
||||||
text.set(nGetResizedStr(), true);
|
text.resize(nGetResizeValue(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return hasInput;
|
return hasInput;
|
||||||
@@ -2485,31 +2489,27 @@ public final class ImGui {
|
|||||||
if (strlen(allowedChars) > 0)
|
if (strlen(allowedChars) > 0)
|
||||||
flags |= ImGuiInputTextFlags_CallbackCharFilter;
|
flags |= ImGuiInputTextFlags_CallbackCharFilter;
|
||||||
|
|
||||||
bool hasInput;
|
bool valueChanged;
|
||||||
|
|
||||||
if (multiline) {
|
if (multiline) {
|
||||||
hasInput = ImGui::InputTextMultiline(label, buf, maxSize, ImVec2(width, height), flags, &TextEditCallbackStub, &userData);
|
valueChanged = ImGui::InputTextMultiline(label, buf, maxSize, ImVec2(width, height), flags, &TextEditCallbackStub, &userData);
|
||||||
} else {
|
} else {
|
||||||
hasInput = ImGui::InputText(label, buf, maxSize, flags, &TextEditCallbackStub, &userData);
|
valueChanged = ImGui::InputText(label, buf, maxSize, flags, &TextEditCallbackStub, &userData);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasInput) {
|
int size = strlen(buf);
|
||||||
int size = strlen(buf);
|
|
||||||
|
|
||||||
if (((size + 1) > maxSize) && (flags & ImGuiInputTextFlags_CallbackResize)) {
|
if ((flags & ImGuiInputTextFlags_CallbackResize) && ((size + 1) > maxSize)) {
|
||||||
env->SetBooleanField(textInputData, imTextInputDataIsResizedID, true);
|
env->SetBooleanField(textInputData, imTextInputDataIsResizedID, true);
|
||||||
resizedBuf = buf;
|
resizeValue = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (valueChanged) {
|
||||||
env->SetIntField(textInputData, imTextInputDataSizeID, size);
|
env->SetIntField(textInputData, imTextInputDataSizeID, size);
|
||||||
env->SetBooleanField(textInputData, imTextInputDataIsDirtyID, true);
|
env->SetBooleanField(textInputData, imTextInputDataIsDirtyID, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return hasInput;
|
return valueChanged;
|
||||||
*/
|
|
||||||
|
|
||||||
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) {
|
||||||
|
|||||||
@@ -261,8 +261,8 @@ public final class ImGuiIO {
|
|||||||
// (default to use native Win32 clipboard on Windows, otherwise uses a private clipboard. Override to access OS clipboard on other architectures)
|
// (default to use native Win32 clipboard on Windows, otherwise uses a private clipboard. Override to access OS clipboard on other architectures)
|
||||||
|
|
||||||
/*JNI
|
/*JNI
|
||||||
jobject _setClipboardTextCallback = nullptr;
|
jobject _setClipboardTextCallback = NULL;
|
||||||
jobject _getClipboardTextCallback = nullptr;
|
jobject _getClipboardTextCallback = NULL;
|
||||||
|
|
||||||
void setClipboardTextStub(void* userData, const char* text) {
|
void setClipboardTextStub(void* userData, const char* text) {
|
||||||
Jni::CallImStrConsumer(Jni::GetEnv(), _setClipboardTextCallback, text);
|
Jni::CallImStrConsumer(Jni::GetEnv(), _setClipboardTextCallback, text);
|
||||||
@@ -276,7 +276,7 @@ public final class ImGuiIO {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
public native void setSetClipboardTextFn(ImStrConsumer setClipboardTextCallback); /*
|
public native void setSetClipboardTextFn(ImStrConsumer setClipboardTextCallback); /*
|
||||||
if (_setClipboardTextCallback != nullptr) {
|
if (_setClipboardTextCallback != NULL) {
|
||||||
env->DeleteGlobalRef(_setClipboardTextCallback);
|
env->DeleteGlobalRef(_setClipboardTextCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,7 +285,7 @@ public final class ImGuiIO {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
public native void setGetClipboardTextFn(ImStrSupplier getClipboardTextCallback); /*
|
public native void setGetClipboardTextFn(ImStrSupplier getClipboardTextCallback); /*
|
||||||
if (_getClipboardTextCallback != nullptr) {
|
if (_getClipboardTextCallback != NULL) {
|
||||||
env->DeleteGlobalRef(_getClipboardTextCallback);
|
env->DeleteGlobalRef(_getClipboardTextCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,23 @@ import java.util.Objects;
|
|||||||
* Wrapper for {@link String} to use inside of th Dear ImGui input widgets.
|
* Wrapper for {@link String} to use inside of th Dear ImGui input widgets.
|
||||||
*/
|
*/
|
||||||
public final class ImString {
|
public final class ImString {
|
||||||
private static final short DEFAULT_LENGTH = 100;
|
/**
|
||||||
private static final short CARET_LEN = 1;
|
* Default size of the inner buffer, if {@link ImString} created with a constructor without args.
|
||||||
private static final short DEFAULT_RESIZE = 10;
|
*/
|
||||||
|
public static final short DEFAULT_LENGTH = 100;
|
||||||
|
/**
|
||||||
|
* Size of ImGui caret which is shown during the input text focus.
|
||||||
|
*/
|
||||||
|
public static final short CARET_LEN = 1;
|
||||||
|
/**
|
||||||
|
* Default resize value, used to set up {@link ImString#resizeFactor}.
|
||||||
|
*/
|
||||||
|
public static final short DEFAULT_RESIZE = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration class to setup some specific behaviour for current string.
|
||||||
|
* This is useful when string used inside of ImGui#InputText*() methods.
|
||||||
|
*/
|
||||||
public final ImGuiInputTextData inputData = new ImGuiInputTextData();
|
public final ImGuiInputTextData inputData = new ImGuiInputTextData();
|
||||||
/**
|
/**
|
||||||
* String will be resized to the value equal to a new size plus this resize factor.
|
* String will be resized to the value equal to a new size plus this resize factor.
|
||||||
@@ -19,19 +32,35 @@ public final class ImString {
|
|||||||
byte[] data;
|
byte[] data;
|
||||||
private String text = "";
|
private String text = "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an {@link ImString} instance with {@link ImString#DEFAULT_LENGTH} size for the inner buffer.
|
||||||
|
*/
|
||||||
public ImString() {
|
public ImString() {
|
||||||
this(DEFAULT_LENGTH);
|
this(DEFAULT_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an {@link ImString} instance with provided size for the inner buffer.
|
||||||
|
* @param length size of the inner buffer to use
|
||||||
|
*/
|
||||||
public ImString(final int length) {
|
public ImString(final int length) {
|
||||||
data = new byte[length + CARET_LEN];
|
data = new byte[length + CARET_LEN];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an {@link ImString} instance from provided string.
|
||||||
|
* Inner buffer size will be equal to the length of the string + {@link ImString#CARET_LEN}.
|
||||||
|
* @param text string to create a new {@link ImString}
|
||||||
|
*/
|
||||||
public ImString(final String text) {
|
public ImString(final String text) {
|
||||||
this(text.length());
|
set(text, true, 0);
|
||||||
set(text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an {@link ImString} instance from provided string with custom size for the inner buffer.
|
||||||
|
* @param text string to a create a new {@link ImString}
|
||||||
|
* @param length custom size for the inner buffer
|
||||||
|
*/
|
||||||
public ImString(final String text, final int length) {
|
public ImString(final String text, final int length) {
|
||||||
this(length);
|
this(length);
|
||||||
set(text);
|
set(text);
|
||||||
@@ -46,15 +75,46 @@ public final class ImString {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void set(final String value) {
|
public void set(final String value) {
|
||||||
set(value.getBytes());
|
set(value, inputData.isResizable, resizeFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set(final String value, final boolean resize) {
|
public void set(final String value, final boolean resize) {
|
||||||
final byte[] str = value.getBytes();
|
set(value, resize, resizeFactor);
|
||||||
if (resize && data.length - CARET_LEN < str.length) {
|
}
|
||||||
data = new byte[str.length + resizeFactor + CARET_LEN];
|
|
||||||
|
public void set(final String value, final boolean resize, final int resizeValue) {
|
||||||
|
final byte[] valueBuff = value.getBytes();
|
||||||
|
final int currentLen = data == null ? 0 : data.length;
|
||||||
|
byte[] newBuff = null;
|
||||||
|
|
||||||
|
if (resize && (currentLen - CARET_LEN) < valueBuff.length) {
|
||||||
|
newBuff = new byte[valueBuff.length + resizeValue + CARET_LEN];
|
||||||
|
inputData.size = valueBuff.length;
|
||||||
}
|
}
|
||||||
set(str);
|
|
||||||
|
if (newBuff == null) {
|
||||||
|
newBuff = new byte[currentLen];
|
||||||
|
inputData.size = Math.max(0, Math.min(valueBuff.length, currentLen - CARET_LEN));
|
||||||
|
}
|
||||||
|
|
||||||
|
System.arraycopy(valueBuff, 0, newBuff, 0, Math.min(valueBuff.length, newBuff.length - CARET_LEN));
|
||||||
|
data = newBuff;
|
||||||
|
inputData.isDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resize(final int newSize) {
|
||||||
|
resize(newSize, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resize(final int newSize, final boolean respectResizeFactor) {
|
||||||
|
if (newSize < data.length) {
|
||||||
|
throw new IllegalArgumentException("New size should be greater than current size of the buffer");
|
||||||
|
}
|
||||||
|
|
||||||
|
final int size = newSize + CARET_LEN + (respectResizeFactor ? resizeFactor : 0);
|
||||||
|
final byte[] newBuffer = new byte[size];
|
||||||
|
System.arraycopy(data, 0, newBuffer, 0, data.length);
|
||||||
|
data = newBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,13 +133,6 @@ public final class ImString {
|
|||||||
return data.length;
|
return data.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void set(final byte[] str) {
|
|
||||||
final int len = Math.min(str.length, data.length);
|
|
||||||
System.arraycopy(str, 0, data, 0, len);
|
|
||||||
inputData.isDirty = true;
|
|
||||||
inputData.size = len;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return get();
|
return get();
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package imgui;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
class ImStringTest {
|
||||||
|
@Test
|
||||||
|
public void testCreation() {
|
||||||
|
ImString str = new ImString(10);
|
||||||
|
assertEquals("", str.get());
|
||||||
|
assertEquals(0, str.getLength(), "String length should be 0, since no data was provided");
|
||||||
|
assertEquals(10 + 1, str.getBufferSize(), "Buffer size must be 'length + 1', +1 - size of the ImGui caret");
|
||||||
|
|
||||||
|
str = new ImString("test");
|
||||||
|
assertEquals("test", str.get());
|
||||||
|
assertEquals(4, str.getLength());
|
||||||
|
assertEquals(4 + 1, str.getBufferSize());
|
||||||
|
|
||||||
|
str = new ImString("test", 10);
|
||||||
|
assertEquals("test", str.get());
|
||||||
|
assertEquals(4, str.getLength());
|
||||||
|
assertEquals(10 + 1, str.getBufferSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGet() {
|
||||||
|
final ImString str = new ImString("test");
|
||||||
|
assertEquals("test", str.get());
|
||||||
|
assertEquals(str.get(), str.toString(), "ImString#toString() must return value which should be equal to ImString#get()");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSet() {
|
||||||
|
final ImString str = new ImString(3);
|
||||||
|
assertEquals("", str.get());
|
||||||
|
assertEquals(0, str.getLength());
|
||||||
|
assertEquals(3 + 1, str.getBufferSize());
|
||||||
|
|
||||||
|
str.set("test");
|
||||||
|
assertEquals("tes", str.get());
|
||||||
|
assertEquals(3, str.getLength());
|
||||||
|
assertEquals(3 + 1, str.getBufferSize());
|
||||||
|
|
||||||
|
str.set("test", true, 0);
|
||||||
|
assertEquals("test", str.get());
|
||||||
|
assertEquals(4, str.getLength());
|
||||||
|
assertEquals(4 + 1, str.getBufferSize());
|
||||||
|
|
||||||
|
str.set("0123456789", true);
|
||||||
|
assertEquals("0123456789", str.get());
|
||||||
|
assertEquals(10, str.getLength());
|
||||||
|
assertEquals(10 + str.resizeFactor + 1, str.getBufferSize());
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user