Skip to content

Commit 937b37b

Browse files
committed
Improve string resize flow
1 parent b5a6ee1 commit 937b37b

File tree

5 files changed

+154
-37
lines changed

5 files changed

+154
-37
lines changed

imgui-binding/build.gradle

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,15 @@ plugins {
99

1010
sourceCompatibility = 1.8
1111

12+
dependencies {
13+
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.5.2'
14+
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.5.2")
15+
}
16+
17+
test {
18+
useJUnitPlatform()
19+
}
20+
1221
assemble.dependsOn clean
1322
task generateLibs(type: GenerateLibs, dependsOn: assemble)
1423

imgui-binding/src/main/java/imgui/ImGui.java

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2397,7 +2397,7 @@ public static boolean vSliderScalar(String label, float sizeX, float sizeY, int
23972397
jfieldID imTextInputDataIsDirtyID;
23982398
jfieldID imTextInputDataIsResizedID;
23992399
2400-
char* resizedBuf;
2400+
int resizeValue;
24012401
24022402
struct InputTextCallbackUserData {
24032403
JNIEnv* env;
@@ -2434,6 +2434,10 @@ static int TextEditCallbackStub(ImGuiInputTextCallbackData* data) {
24342434
imTextInputDataIsResizedID = env->GetFieldID(jImInputTextDataClass, "isResized", "Z");
24352435
*/
24362436

2437+
private static native int nGetResizeValue(); /*
2438+
return resizeValue;
2439+
*/
2440+
24372441
public static boolean inputText(String label, ImString text) {
24382442
return preInputText(false, label, text, 0, 0, 0);
24392443
}
@@ -2469,7 +2473,7 @@ private static boolean preInputText(boolean multiline, String label, ImString te
24692473

24702474
if (inputData.isResized) {
24712475
inputData.isResized = false;
2472-
text.set(nGetResizedStr(), true);
2476+
text.resize(nGetResizeValue(), true);
24732477
}
24742478

24752479
return hasInput;
@@ -2485,31 +2489,27 @@ private static boolean preInputText(boolean multiline, String label, ImString te
24852489
if (strlen(allowedChars) > 0)
24862490
flags |= ImGuiInputTextFlags_CallbackCharFilter;
24872491
2488-
bool hasInput;
2492+
bool valueChanged;
24892493
24902494
if (multiline) {
2491-
hasInput = ImGui::InputTextMultiline(label, buf, maxSize, ImVec2(width, height), flags, &TextEditCallbackStub, &userData);
2495+
valueChanged = ImGui::InputTextMultiline(label, buf, maxSize, ImVec2(width, height), flags, &TextEditCallbackStub, &userData);
24922496
} else {
2493-
hasInput = ImGui::InputText(label, buf, maxSize, flags, &TextEditCallbackStub, &userData);
2497+
valueChanged = ImGui::InputText(label, buf, maxSize, flags, &TextEditCallbackStub, &userData);
24942498
}
24952499
2496-
if (hasInput) {
2497-
int size = strlen(buf);
2500+
int size = strlen(buf);
24982501
2499-
if (((size + 1) > maxSize) && (flags & ImGuiInputTextFlags_CallbackResize)) {
2500-
env->SetBooleanField(textInputData, imTextInputDataIsResizedID, true);
2501-
resizedBuf = buf;
2502-
}
2502+
if ((flags & ImGuiInputTextFlags_CallbackResize) && ((size + 1) > maxSize)) {
2503+
env->SetBooleanField(textInputData, imTextInputDataIsResizedID, true);
2504+
resizeValue = size;
2505+
}
25032506
2507+
if (valueChanged) {
25042508
env->SetIntField(textInputData, imTextInputDataSizeID, size);
25052509
env->SetBooleanField(textInputData, imTextInputDataIsDirtyID, true);
25062510
}
25072511
2508-
return hasInput;
2509-
*/
2510-
2511-
private static native String nGetResizedStr(); /*
2512-
return env->NewStringUTF(resizedBuf);
2512+
return valueChanged;
25132513
*/
25142514

25152515
public static boolean inputFloat(String label, ImFloat v) {

imgui-binding/src/main/java/imgui/ImGuiIO.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,8 @@ public final class ImGuiIO {
261261
// (default to use native Win32 clipboard on Windows, otherwise uses a private clipboard. Override to access OS clipboard on other architectures)
262262

263263
/*JNI
264-
jobject _setClipboardTextCallback = nullptr;
265-
jobject _getClipboardTextCallback = nullptr;
264+
jobject _setClipboardTextCallback = NULL;
265+
jobject _getClipboardTextCallback = NULL;
266266
267267
void setClipboardTextStub(void* userData, const char* text) {
268268
Jni::CallImStrConsumer(Jni::GetEnv(), _setClipboardTextCallback, text);
@@ -276,7 +276,7 @@ void setClipboardTextStub(void* userData, const char* text) {
276276
*/
277277

278278
public native void setSetClipboardTextFn(ImStrConsumer setClipboardTextCallback); /*
279-
if (_setClipboardTextCallback != nullptr) {
279+
if (_setClipboardTextCallback != NULL) {
280280
env->DeleteGlobalRef(_setClipboardTextCallback);
281281
}
282282
@@ -285,7 +285,7 @@ void setClipboardTextStub(void* userData, const char* text) {
285285
*/
286286

287287
public native void setGetClipboardTextFn(ImStrSupplier getClipboardTextCallback); /*
288-
if (_getClipboardTextCallback != nullptr) {
288+
if (_getClipboardTextCallback != NULL) {
289289
env->DeleteGlobalRef(_getClipboardTextCallback);
290290
}
291291

imgui-binding/src/main/java/imgui/ImString.java

Lines changed: 70 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,23 @@
66
* Wrapper for {@link String} to use inside of th Dear ImGui input widgets.
77
*/
88
public final class ImString {
9-
private static final short DEFAULT_LENGTH = 100;
10-
private static final short CARET_LEN = 1;
11-
private static final short DEFAULT_RESIZE = 10;
9+
/**
10+
* Default size of the inner buffer, if {@link ImString} created with a constructor without args.
11+
*/
12+
public static final short DEFAULT_LENGTH = 100;
13+
/**
14+
* Size of ImGui caret which is shown during the input text focus.
15+
*/
16+
public static final short CARET_LEN = 1;
17+
/**
18+
* Default resize value, used to set up {@link ImString#resizeFactor}.
19+
*/
20+
public static final short DEFAULT_RESIZE = 10;
1221

22+
/**
23+
* Configuration class to setup some specific behaviour for current string.
24+
* This is useful when string used inside of ImGui#InputText*() methods.
25+
*/
1326
public final ImGuiInputTextData inputData = new ImGuiInputTextData();
1427
/**
1528
* String will be resized to the value equal to a new size plus this resize factor.
@@ -19,19 +32,35 @@ public final class ImString {
1932
byte[] data;
2033
private String text = "";
2134

35+
/**
36+
* Creates an {@link ImString} instance with {@link ImString#DEFAULT_LENGTH} size for the inner buffer.
37+
*/
2238
public ImString() {
2339
this(DEFAULT_LENGTH);
2440
}
2541

42+
/**
43+
* Creates an {@link ImString} instance with provided size for the inner buffer.
44+
* @param length size of the inner buffer to use
45+
*/
2646
public ImString(final int length) {
2747
data = new byte[length + CARET_LEN];
2848
}
2949

50+
/**
51+
* Creates an {@link ImString} instance from provided string.
52+
* Inner buffer size will be equal to the length of the string + {@link ImString#CARET_LEN}.
53+
* @param text string to create a new {@link ImString}
54+
*/
3055
public ImString(final String text) {
31-
this(text.length());
32-
set(text);
56+
set(text, true, 0);
3357
}
3458

59+
/**
60+
* Create an {@link ImString} instance from provided string with custom size for the inner buffer.
61+
* @param text string to a create a new {@link ImString}
62+
* @param length custom size for the inner buffer
63+
*/
3564
public ImString(final String text, final int length) {
3665
this(length);
3766
set(text);
@@ -46,15 +75,46 @@ public String get() {
4675
}
4776

4877
public void set(final String value) {
49-
set(value.getBytes());
78+
set(value, inputData.isResizable, resizeFactor);
5079
}
5180

5281
public void set(final String value, final boolean resize) {
53-
final byte[] str = value.getBytes();
54-
if (resize && data.length - CARET_LEN < str.length) {
55-
data = new byte[str.length + resizeFactor + CARET_LEN];
82+
set(value, resize, resizeFactor);
83+
}
84+
85+
public void set(final String value, final boolean resize, final int resizeValue) {
86+
final byte[] valueBuff = value.getBytes();
87+
final int currentLen = data == null ? 0 : data.length;
88+
byte[] newBuff = null;
89+
90+
if (resize && (currentLen - CARET_LEN) < valueBuff.length) {
91+
newBuff = new byte[valueBuff.length + resizeValue + CARET_LEN];
92+
inputData.size = valueBuff.length;
93+
}
94+
95+
if (newBuff == null) {
96+
newBuff = new byte[currentLen];
97+
inputData.size = Math.max(0, Math.min(valueBuff.length, currentLen - CARET_LEN));
98+
}
99+
100+
System.arraycopy(valueBuff, 0, newBuff, 0, Math.min(valueBuff.length, newBuff.length - CARET_LEN));
101+
data = newBuff;
102+
inputData.isDirty = true;
103+
}
104+
105+
public void resize(final int newSize) {
106+
resize(newSize, false);
107+
}
108+
109+
public void resize(final int newSize, final boolean respectResizeFactor) {
110+
if (newSize < data.length) {
111+
throw new IllegalArgumentException("New size should be greater than current size of the buffer");
56112
}
57-
set(str);
113+
114+
final int size = newSize + CARET_LEN + (respectResizeFactor ? resizeFactor : 0);
115+
final byte[] newBuffer = new byte[size];
116+
System.arraycopy(data, 0, newBuffer, 0, data.length);
117+
data = newBuffer;
58118
}
59119

60120
/**
@@ -73,13 +133,6 @@ public int getBufferSize() {
73133
return data.length;
74134
}
75135

76-
private void set(final byte[] str) {
77-
final int len = Math.min(str.length, data.length);
78-
System.arraycopy(str, 0, data, 0, len);
79-
inputData.isDirty = true;
80-
inputData.size = len;
81-
}
82-
83136
@Override
84137
public String toString() {
85138
return get();
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package imgui;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import static org.junit.jupiter.api.Assertions.assertEquals;
6+
7+
class ImStringTest {
8+
@Test
9+
public void testCreation() {
10+
ImString str = new ImString(10);
11+
assertEquals("", str.get());
12+
assertEquals(0, str.getLength(), "String length should be 0, since no data was provided");
13+
assertEquals(10 + 1, str.getBufferSize(), "Buffer size must be 'length + 1', +1 - size of the ImGui caret");
14+
15+
str = new ImString("test");
16+
assertEquals("test", str.get());
17+
assertEquals(4, str.getLength());
18+
assertEquals(4 + 1, str.getBufferSize());
19+
20+
str = new ImString("test", 10);
21+
assertEquals("test", str.get());
22+
assertEquals(4, str.getLength());
23+
assertEquals(10 + 1, str.getBufferSize());
24+
}
25+
26+
@Test
27+
public void testGet() {
28+
final ImString str = new ImString("test");
29+
assertEquals("test", str.get());
30+
assertEquals(str.get(), str.toString(), "ImString#toString() must return value which should be equal to ImString#get()");
31+
}
32+
33+
@Test
34+
public void testSet() {
35+
final ImString str = new ImString(3);
36+
assertEquals("", str.get());
37+
assertEquals(0, str.getLength());
38+
assertEquals(3 + 1, str.getBufferSize());
39+
40+
str.set("test");
41+
assertEquals("tes", str.get());
42+
assertEquals(3, str.getLength());
43+
assertEquals(3 + 1, str.getBufferSize());
44+
45+
str.set("test", true, 0);
46+
assertEquals("test", str.get());
47+
assertEquals(4, str.getLength());
48+
assertEquals(4 + 1, str.getBufferSize());
49+
50+
str.set("0123456789", true);
51+
assertEquals("0123456789", str.get());
52+
assertEquals(10, str.getLength());
53+
assertEquals(10 + str.resizeFactor + 1, str.getBufferSize());
54+
}
55+
}

0 commit comments

Comments
 (0)