Skip to content

Commit 8d454d9

Browse files
authored
TextArea: revalidate parent when growByContent row count changes (#4741)
1 parent 7beaad1 commit 8d454d9

2 files changed

Lines changed: 102 additions & 0 deletions

File tree

CodenameOne/src/com/codename1/ui/TextArea.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,13 @@ public void setText(String t) {
597597
//zero the ArrayList in order to initialize it on the next paint
598598
rowStrings = null;
599599
}
600+
if (growByContent
601+
&& !Objects.equals(text, old)
602+
&& getParent() != null
603+
&& Display.getInstance().isTextEditing(this)
604+
&& textMightGrowByContent(old, text)) {
605+
getParent().revalidateLater();
606+
}
600607
if (!Objects.equals(text, old)) {
601608
fireDataChanged(DataChangedListener.CHANGED, -1);
602609
}
@@ -610,6 +617,53 @@ public void setText(String t) {
610617
repaint();
611618
}
612619

620+
private boolean textMightGrowByContent(String oldText, String newText) {
621+
int oldNewLines = countNewLines(oldText);
622+
int newNewLines = countNewLines(newText);
623+
if (newNewLines > oldNewLines) {
624+
return true;
625+
}
626+
if (newText == null || oldText == null || newText.length() <= oldText.length()) {
627+
return false;
628+
}
629+
int cols = getColumns();
630+
if (cols > 1) {
631+
return estimateLineCount(newText, cols) > estimateLineCount(oldText, cols);
632+
}
633+
return false;
634+
}
635+
636+
private int countNewLines(String value) {
637+
if (value == null || value.length() == 0) {
638+
return 0;
639+
}
640+
int count = 0;
641+
for (int i = 0; i < value.length(); i++) {
642+
if (value.charAt(i) == '\n') {
643+
count++;
644+
}
645+
}
646+
return count;
647+
}
648+
649+
private int estimateLineCount(String value, int cols) {
650+
if (value == null || value.length() == 0) {
651+
return 1;
652+
}
653+
int lines = 0;
654+
int segmentLength = 0;
655+
for (int i = 0; i < value.length(); i++) {
656+
if (value.charAt(i) == '\n') {
657+
lines += Math.max(1, (segmentLength + cols - 1) / cols);
658+
segmentLength = 0;
659+
} else {
660+
segmentLength++;
661+
}
662+
}
663+
lines += Math.max(1, (segmentLength + cols - 1) / cols);
664+
return lines;
665+
}
666+
613667
/// Convenience method for numeric text fields, returns the value as a number or invalid if the value in the
614668
/// text field isn't a number
615669
///

maven/core-unittests/src/test/java/com/codename1/ui/TextAreaTest.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,41 @@ void testGrowByContent() {
137137
assertFalse(textArea.isGrowByContent());
138138
}
139139

140+
@FormTest
141+
void testGrowByContentRevalidatesParentWhenRowsGrowDuringEditing() {
142+
TextArea textArea = new TextArea();
143+
textArea.setRows(1);
144+
textArea.setSingleLineTextArea(false);
145+
textArea.setGrowByContent(true);
146+
TrackingContainer parent = new TrackingContainer();
147+
parent.add(textArea);
148+
parent.revalidatedLater = false;
149+
Display.impl.setFocusedEditingText(textArea);
150+
try {
151+
textArea.setText("Line 1");
152+
parent.revalidatedLater = false;
153+
textArea.setText("Line 1\nLine 2");
154+
assertTrue(parent.revalidatedLater, "Parent should be revalidated when growByContent row count increases");
155+
} finally {
156+
Display.impl.setFocusedEditingText(null);
157+
}
158+
}
159+
160+
@FormTest
161+
void testGrowByContentDoesNotRevalidateWhenNotEditing() {
162+
TextArea textArea = new TextArea();
163+
textArea.setRows(2);
164+
textArea.setGrowByContent(true);
165+
TrackingContainer parent = new TrackingContainer();
166+
parent.add(textArea);
167+
parent.revalidatedLater = false;
168+
169+
Display.impl.setFocusedEditingText(null);
170+
textArea.setText("Line 1");
171+
172+
assertFalse(parent.revalidatedLater, "Parent should not be revalidated when text changes outside active editing");
173+
}
174+
140175
@FormTest
141176
void testEndsWith3Points() {
142177
TextArea textArea = new TextArea();
@@ -413,4 +448,17 @@ private TextArea createOverflowSample(int valign) {
413448
sample.setVerticalAlignment(valign);
414449
return sample;
415450
}
451+
452+
private static class TrackingContainer extends Container {
453+
private boolean revalidatedLater;
454+
455+
TrackingContainer() {
456+
super(BoxLayout.y());
457+
}
458+
459+
@Override
460+
public void revalidateLater() {
461+
revalidatedLater = true;
462+
}
463+
}
416464
}

0 commit comments

Comments
 (0)