10000 Updated the position_cursor function of Textbox · matplotlib/matplotlib@971d59e · GitHub
[go: up one dir, main page]

Skip to content

Commit 971d59e

Browse files
committed
Updated the position_cursor function of Textbox
create char_index_at inside text class Update widgets.py Update widgets.py Update text.py solved bug in caching Simpler logic Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> make char_index_at private as suggested Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> refer to private method change __str__ to str mistake in applying a change fixed
1 parent fd5cf5c commit 971d59e

File tree

2 files changed

+37
-12
lines changed

2 files changed

+37
-12
lines changed

lib/matplotlib/text.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,41 @@ def _get_multialignment(self):
279279
else:
280280
return self._horizontalalignment
281281

282+
def _char_index_at(self, x):
283+
"""
284+
Calculates the index nearer to x, we accumulate
285+
the width of each character contained in the text
286+
and find the index at which the distance between the
287+
click position and the accumulated sum is minimal.
288+
This works only on single line texts.
289+
"""
290+
291+
if (not hasattr(self, "_saved_fontproperties") or
292+
str(self._fontproperties) != self._saved_fontproperties):
293+
294+
self._saved_fontproperties = str(self._fontproperties)
295+
self._chars_size = dict() # to cache results
296+
297+
text = self._text
298+
299+
if len(text) == 0:
300+
return 0
301+
302+
else:
303+
for char in set(text):
304+
if char not in self._chars_size:
305+
self.set_text(char)
306+
bb = self.get_window_extent()
307+
self._chars_size[char] = bb.x1 - bb.x0
308+
309+
10000 self.set_text(text)
310+
bb = self.get_window_extent()
311+
312+
size_accum = np.cumsum([0] + [self._chars_size[x] for x in text])
313+
314+
std_x = x - bb.x0
315+
return (np.abs(size_accum - std_x)).argmin()
316+
282317
def get_rotation(self):
283318
"""Return the text angle in degrees between 0 and 360."""
284319
if self.get_transform_rotates_text():

lib/matplotlib/widgets.py

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1315,17 +1315,6 @@ def stop_typing(self):
13151315
# call it once we've already done our cleanup.
13161316
self._observers.process('submit', self.text)
13171317

1318-
def position_cursor(self, x):
1319-
# now, we have to figure out where the cursor goes.
1320-
# approximate it based on assuming all characters the same length
1321-
if len(self.text) == 0:
1322-
self.cursor_index = 0
1323-
else:
1324-
bb = self.text_disp.get_window_extent()
1325-
ratio = np.clip((x - bb.x0) / bb.width, 0, 1)
1326-
self.cursor_index = int(len(self.text) * ratio)
1327-
self._rendercursor()
1328-
13291318
def _click(self, event):
13301319
if self.ignore(event):
13311320
return
@@ -1338,7 +1327,8 @@ def _click(self, event):
13381327
event.canvas.grab_mouse(self.ax)
13391328
if not self.capturekeystrokes:
13401329
self.begin_typing(event.x)
1341-
self.position_cursor(event.x)
1330+
self.cursor_index = self.text_disp._char_index_at(event.x)
1331+
self._rendercursor()
13421332

13431333
def _resize(self, event):
13441334
self.stop_typing()

0 commit comments

Comments
 (0)
0