Skip to content

Commit 7d5e184

Browse files
committed
Fix cursor location on changing Text values
Conflicts: tests/test_widgets.py
1 parent 4d3c9fe commit 7d5e184

File tree

3 files changed

+50
-16
lines changed

3 files changed

+50
-16
lines changed

asciimatics/screen.py

+1
Original file line numberDiff line numberDiff line change
@@ -2302,3 +2302,4 @@ def restore(self):
23022302
for signalnum, handler in self._old_signal_states:
23032303
signal.signal(signalnum, handler)
23042304
self._old_signal_states = []
2305+

asciimatics/widgets.py

+17-15
Original file line numberDiff line numberDiff line change
@@ -1620,17 +1620,14 @@ def process_event(self, event):
16201620
if isinstance(event, KeyboardEvent):
16211621
if event.key_code == Screen.KEY_BACK:
16221622
if self._column > 0:
1623-
# Delete character in front of cursor - use value to trigger
1624-
# events.
1625-
self.value = "".join([
1626-
self._value[:self._column - 1],
1627-
self._value[self._column:]])
1623+
# Delete character in front of cursor.
1624+
self._set_and_check_value("".join([self._value[:self._column - 1],
1625+
self._value[self._column:]]))
16281626
self._column -= 1
16291627
if event.key_code == Screen.KEY_DELETE:
16301628
if self._column < len(self._value):
1631-
self.value = "".join([
1632-
self._value[:self._column],
1633-
self._value[self._column + 1:]])
1629+
self._set_and_check_value("".join([self._value[:self._column],
1630+
self._value[self._column + 1:]]))
16341631
elif event.key_code == Screen.KEY_LEFT:
16351632
self._column -= 1
16361633
self._column = max(self._column, 0)
@@ -1643,9 +1640,8 @@ def process_event(self, event):
16431640
self._column = len(self._value)
16441641
elif event.key_code >= 32:
16451642
# Insert any visible text at the current cursor position.
1646-
self.value = chr(event.key_code).join([
1647-
self._value[:self._column],
1648-
self._value[self._column:]])
1643+
self._set_and_check_value(chr(event.key_code).join([self._value[:self._column],
1644+
self._value[self._column:]]))
16491645
self._column += 1
16501646
else:
16511647
# Ignore any other key press.
@@ -1670,20 +1666,25 @@ def process_event(self, event):
16701666
def required_height(self, offset, width):
16711667
return 1
16721668

1673-
@property
1674-
def value(self):
1675-
return self._value
1676-
16771669
@property
16781670
def frame_update_count(self):
16791671
# Force refresh for cursor if needed.
16801672
return 5 if self._has_focus and not self._frame.reduce_cpu else 0
16811673

1674+
@property
1675+
def value(self):
1676+
return self._value
1677+
16821678
@value.setter
16831679
def value(self, new_value):
1680+
self._set_and_check_value(new_value, reset=True)
1681+
1682+
def _set_and_check_value(self, new_value, reset=False):
16841683
# Only trigger the notification after we've changed the value.
16851684
old_value = self._value
16861685
self._value = new_value if new_value else ""
1686+
if reset:
1687+
self.reset()
16871688
if old_value != self._value and self._on_change:
16881689
self._on_change()
16891690
if self._validator:
@@ -2074,6 +2075,7 @@ def value(self, new_value):
20742075
self._value = new_value.split("\n")
20752076
else:
20762077
self._value = new_value
2078+
self.reset()
20772079
if old_value != self._value and self._on_change:
20782080
self._on_change()
20792081

tests/test_widgets.py

+32-1
Original file line numberDiff line numberDiff line change
@@ -1716,12 +1716,43 @@ def test_password(self):
17161716
form.save()
17171717
self.assertEqual(text.value, "1234")
17181718

1719-
# Check that it is drawn with the obscuring charav=cter, though.
1719+
# Check that it is drawn with the obscuring character, though.
17201720
form.update(0)
17211721
self.assert_canvas_equals(
17221722
canvas,
17231723
"Password **** \n" +
17241724
" \n")
17251725

1726+
def test_change_values(self):
1727+
"""
1728+
Check changing Text values resets cursor position.
1729+
"""
1730+
# Create a dummy screen.
1731+
screen = MagicMock(spec=Screen, colours=8, unicode_aware=False)
1732+
scene = MagicMock(spec=Scene)
1733+
canvas = Canvas(screen, 10, 40, 0, 0)
1734+
1735+
# Create the form we want to test.
1736+
form = Frame(canvas, canvas.height, canvas.width, has_border=False)
1737+
layout = Layout([100], fill_frame=True)
1738+
form.add_layout(layout)
1739+
text = Text()
1740+
layout.add_widget(text)
1741+
form.fix()
1742+
form.register_scene(scene)
1743+
form.reset()
1744+
1745+
# Check that input is put at the end of the new text
1746+
text.value = "A test"
1747+
self.process_keys(form, ["A"])
1748+
form.save()
1749+
self.assertEqual(text.value, "A testA")
1750+
1751+
# Check that growing longer still puts it at the end.
1752+
text.value = "A longer test"
1753+
self.process_keys(form, ["A"])
1754+
form.save()
1755+
self.assertEqual(text.value, "A longer testA")
1756+
17261757
if __name__ == '__main__':
17271758
unittest.main()

0 commit comments

Comments
 (0)