Skip to content

Commit

Permalink
Fix cursor location on changing Text values
Browse files Browse the repository at this point in the history
Conflicts:
	tests/test_widgets.py
  • Loading branch information
peterbrittain committed Dec 5, 2017
1 parent 4d3c9fe commit 7d5e184
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 16 deletions.
1 change: 1 addition & 0 deletions asciimatics/screen.py
Original file line number Diff line number Diff line change
Expand Up @@ -2302,3 +2302,4 @@ def restore(self):
for signalnum, handler in self._old_signal_states:
signal.signal(signalnum, handler)
self._old_signal_states = []

32 changes: 17 additions & 15 deletions asciimatics/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -1620,17 +1620,14 @@ def process_event(self, event):
if isinstance(event, KeyboardEvent):
if event.key_code == Screen.KEY_BACK:
if self._column > 0:
# Delete character in front of cursor - use value to trigger
# events.
self.value = "".join([
self._value[:self._column - 1],
self._value[self._column:]])
# Delete character in front of cursor.
self._set_and_check_value("".join([self._value[:self._column - 1],
self._value[self._column:]]))
self._column -= 1
if event.key_code == Screen.KEY_DELETE:
if self._column < len(self._value):
self.value = "".join([
self._value[:self._column],
self._value[self._column + 1:]])
self._set_and_check_value("".join([self._value[:self._column],
self._value[self._column + 1:]]))
elif event.key_code == Screen.KEY_LEFT:
self._column -= 1
self._column = max(self._column, 0)
Expand All @@ -1643,9 +1640,8 @@ def process_event(self, event):
self._column = len(self._value)
elif event.key_code >= 32:
# Insert any visible text at the current cursor position.
self.value = chr(event.key_code).join([
self._value[:self._column],
self._value[self._column:]])
self._set_and_check_value(chr(event.key_code).join([self._value[:self._column],
self._value[self._column:]]))
self._column += 1
else:
# Ignore any other key press.
Expand All @@ -1670,20 +1666,25 @@ def process_event(self, event):
def required_height(self, offset, width):
return 1

@property
def value(self):
return self._value

@property
def frame_update_count(self):
# Force refresh for cursor if needed.
return 5 if self._has_focus and not self._frame.reduce_cpu else 0

@property
def value(self):
return self._value

@value.setter
def value(self, new_value):
self._set_and_check_value(new_value, reset=True)

def _set_and_check_value(self, new_value, reset=False):
# Only trigger the notification after we've changed the value.
old_value = self._value
self._value = new_value if new_value else ""
if reset:
self.reset()
if old_value != self._value and self._on_change:
self._on_change()
if self._validator:
Expand Down Expand Up @@ -2074,6 +2075,7 @@ def value(self, new_value):
self._value = new_value.split("\n")
else:
self._value = new_value
self.reset()
if old_value != self._value and self._on_change:
self._on_change()

Expand Down
33 changes: 32 additions & 1 deletion tests/test_widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -1716,12 +1716,43 @@ def test_password(self):
form.save()
self.assertEqual(text.value, "1234")

# Check that it is drawn with the obscuring charav=cter, though.
# Check that it is drawn with the obscuring character, though.
form.update(0)
self.assert_canvas_equals(
canvas,
"Password **** \n" +
" \n")

def test_change_values(self):
"""
Check changing Text values resets cursor position.
"""
# Create a dummy screen.
screen = MagicMock(spec=Screen, colours=8, unicode_aware=False)
scene = MagicMock(spec=Scene)
canvas = Canvas(screen, 10, 40, 0, 0)

# Create the form we want to test.
form = Frame(canvas, canvas.height, canvas.width, has_border=False)
layout = Layout([100], fill_frame=True)
form.add_layout(layout)
text = Text()
layout.add_widget(text)
form.fix()
form.register_scene(scene)
form.reset()

# Check that input is put at the end of the new text
text.value = "A test"
self.process_keys(form, ["A"])
form.save()
self.assertEqual(text.value, "A testA")

# Check that growing longer still puts it at the end.
text.value = "A longer test"
self.process_keys(form, ["A"])
form.save()
self.assertEqual(text.value, "A longer testA")

if __name__ == '__main__':
unittest.main()

0 comments on commit 7d5e184

Please sign in to comment.