Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello โ I'm @olemoritz on Twitter.
pythonista UI
-
@shinya.ta To be able to help you, I need more informations:
- is the problem reproductible? If yes, with which text and actions?
- is the problem disappearing if you remove Pythonista from the tasks list and restart it?
- where is the cursor when you have the problem?
-
When you add emoji, the cursor stops at the front of the cord that the first time it made.
Reading text and emoji to read emoji different from cursor position.
-
@shinya.ta Sorry I don't understand, could you, step by step, tell what you do, like:
- type letter a
- type emoji ๐ฏ๐ต
- tap left button
Etc...
-
They are texting aloud, emoji reading aloud, and precise cursor move.
I thought that it could be done by the combination of the program so far.
But it wasn't that simple.
-
@shinya.ta Sorry but without any information, I could not reproduce the error, thus no way to solve. If it happens, take a print screen and post the picture in this forum
-
It is not a code error but a false motion.
So, I don't think I can understand even when I see the image.
Can I play videos here?
-
I will use Voice over, so I don't think I can check it in the image.
When you use Voice over, there is always a description of text field editing and text mode at the place of emoji, and the explanation of the cursor position is not explained.
-
@shinya.ta could you try to reproduce an exact sequence which generates the problem...
-
There was another problem.
It has been all right until now, but when I press all cursor move button, there is an error.
There is a "Nameerror" in the "say _ char (TV)" button of all directions button "say".
Even if I restart it, even if I remodel the code, there is no change.
Why?
-
b_ = ui.Button()
b_top.frame = (190, 330, 95, 50)
b_top.title = 'begin'
b_top.background_color = 'white'
b_top.border_width = 1def b_top_action(sender):
tv = sender.superview['TextView']
tv.selected_range = (0, 0)
say_char(tv)โฆsay _ char (TV). There is a Name Error in the Name Error. I see Error in all buttons "say _ char". Why is that?
-
import ui
from objc_util import *v = ui.View()
v.frame = (0,0,500,320)
v.name = 'Move cursor in TextView'tv = ui.TextView()
tv.name = 'TextView'
tv.frame = (120,10,370,300)
tv.font = ('Arial Rounded MT Bold',24)
tv.text = 'aรฉ๐ข๐ฏ๐ต๐จโ๐จโ๐งโ๐ง'
v.add_subview(tv)def selected_range(i):
tvo = ObjCInstance(tv)
p1 = tvo.positionFromPosition_offset_(tvo.beginningOfDocument(), i)
p2 = p1
tvo.selectedTextRange = tvo.textRangeFromPosition_toPosition_(p1, p2)
returnsome emoji like flags count as 2 for len but as 4 for selected_range
def IndexToPos(type):
tvo = ObjCInstance(tv)
# build array index -> position in range
idxtopos = []
pre_x = -1
#print(tv.text)
for c in tv.text:
# nbr characters used e=1 รฉ=1 ๐=1 ๐ฏ๐ต=2 ๐จโ๐จโ๐งโ๐ง=7
# some emoji generate more than one character,
# sometimes counted for more than one in range
# 1,2,3->1 4->2
nb = 1 + int(len(c.encode('utf-8'))/4)
for j in range(0,nb):
p1 = tvo.positionFromPosition_offset_(tvo.beginningOfDocument(), len(idxtopos))
p2 = p1
rge = tvo.textRangeFromPosition_toPosition_(p1, p2)
rect = tvo.firstRectForRange_(rge) # CGRect
x = rect.origin.x
if x == float('inf') or x == pre_x:
# same x as previous one, composed character
pass
else:
pre_x = x
i = len(idxtopos)
idxtopos.append(i) # start position of c
#print(c,nb,len(idxtopos)-1,i,x)
idxtopos.append(i+1) # end position of last c
#print(idxtopos)
# get index of actual cursor
i = tv.selected_range[0] # actual position of cursor
# often p is one of sub_chars, not always the first one
p = idxtopos[i] # used to check if same base character
#print(p,i,idxtopos)
if type == 'left':
if i == 0:
return # already before character
while True:
i = i - 1
if idxtopos[i] != p:
q = idxtopos[i]
# seach first sub-character
while i > 0:
if idxtopos[i-1] != q:
break
i = i - 1
break
elif type == 'right':
if i == (len(idxtopos)-1):
return # already after last character
while True:
i = i + 1
if idxtopos[i] != p:
break
elif type == 'end':
i = len(idxtopos)-1
else:
return idxtopos
r = idxtopos[i]
selected_range(i)
return idxtoposb_top = ui.Button()
b_top.frame = (10,10,100,32)
b_top.title = 'begin'
b_top.background_color = 'white'
b_top.border_width = 1
def b_top_action(sender):
tv = sender.superview['TextView']
tv.selected_range = (0,0)
b_top.action = b_top_action
v.add_subview(b_top)b_left = ui.Button()
b_left.frame = (10,50,100,32)
b_left.title = 'left'
b_left.background_color = 'white'
b_left.border_width = 1
def b_left_action(sender):
idxtopos = IndexToPos('left') # list index to position
b_left.action = b_left_action
v.add_subview(b_left)b_right = ui.Button()
b_right.frame = (10,90,100,32)
b_right.title = 'right'
b_right.background_color = 'white'
b_right.border_width = 1
def b_right_action(sender):
idxtopos = IndexToPos('right') # list index to position
b_right.action = b_right_action
v.add_subview(b_right)b_bottom = ui.Button()
b_bottom.frame = (10,130,100,32)
b_bottom.title = 'end'
b_bottom.background_color = 'white'
b_bottom.border_width = 1
def b_bottom_action(sender):
idxtopos = IndexToPos('end') # list index to position
b_bottom.action = b_bottom_action
v.add_subview(b_bottom)def get_xy(tv):
idxtopos = IndexToPos('') # list index to position
tvo = ObjCInstance(tv)
x_y = []
for i in range(0,len(idxtopos)+1): # x,y of each character
p1 = tvo.positionFromPosition_offset_(tvo.beginningOfDocument(), i)
rge = tvo.textRangeFromPosition_toPosition_(p1,p1)
rect = tvo.firstRectForRange_(rge) # CGRect
x,y = rect.origin.x,rect.origin.y
if i == len(idxtopos):
if i > 0:
x,y = x_y[i-1]
else:
# text is empty
x,y = 0,0
if x == float('inf'):
x,y = x_prec+15,y_prec
x_prec,y_prec = x,y
x_y.append((x,y))
return x_yb_up = ui.Button()
b_up.frame = (10,170,100,32)
b_up.title = 'up'
b_up.background_color = 'white'
b_up.border_width = 1
def b_up_action(sender):
tv = sender.superview['TextView']
x_y = get_xy(tv)
c = tv.selected_range[0]
xc,yc = x_y[c]
i = c - 1
while i >= 0:
x,y = x_y[i]
if y < yc:
# previous row
if x <= xc:
selected_range(i)
return
i = i - 1
b_up.action = b_up_action
v.add_subview(b_up)b_down = ui.Button()
b_down.frame = (10,210,100,32)
b_down.title = 'down'
b_down.background_color = 'white'
b_down.border_width = 1
def b_down_action(sender):
tv = sender.superview['TextView']
idxtopos = IndexToPos('') # list index to position
x_y = get_xy(tv)
c = tv.selected_range[0]
#print(x_y,c)
xc,yc = x_y[c]
i = c# - 1 # I don't remember why this "- 1"
while i < len(idxtopos):
x,y = x_y[i]
if y > yc:
# next row
if x >= xc:
selected_range(i)
return
else:
if (i+1) < len(idxtopos):
if x_y[i+1][1] > y: # i = last character of row under cursor
selected_range(i)
return
else:
pass # try next x
else:
# last character of last row
selected_range(i)
return
i = i + 1
b_down.action = b_down_action
v.add_subview(b_down)v.present('sheet')
tv.selected_range = (0,0)
tv.begin_editing()I want to add a copy button and a clear button on this.
-
@shinya.ta what is this say_char? Don't you want to say speech.say?
Did you add the def?
def say_char(tv): # test speech character at cursor i = tv.selected_range[0] if i < len(tv.text): c = tv.text[i] if c == ' ': c ='space' speech.say(c,'en-US') tvo = ObjCInstance(tv) p1 = tvo.positionFromPosition_offset_(tvo.beginningOfDocument(), i) p2 = p1 tvo.selectedTextRange = tvo.textRangeFromPosition_toPosition_(p1,p2)
Before
def selected_range(i):
And
import speech
At the begin
-
@shinya.ta for the copy and clear button:
b_copy = ui.Button() b_copy.frame = (10,250,100,32) b_copy.title = 'copy' b_copy.background_color = 'white' b_copy.border_width = 1 def b_copy_action(sender): tv = sender.superview['TextView'] clipboard.set(tv.text) b_copy.action = b_copy_action v.add_subview(b_copy) b_clear = ui.Button() b_clear.frame = (10,290,100,32) b_clear.title = 'clear' b_clear.background_color = 'white' b_clear.border_width = 1 def b_clear_action(sender): tv = sender.superview['TextView'] tv.text = '' b_clear.action = b_clear_action v.add_subview(b_clear)
Before
v.present('sheet')
-
The clear button is okay, but the copy button does not copy the text and emoji. I copy the code.
-
@shinya.ta My error, the line
b_copy.action = b_copy_action
Must be left shifted...I put one indentation to much, sorry ๐ข
And I also forgot the
import clipboard
at the begin ๐ข
-
I inserted import clipboard, but I don't photocopy it.
-
@shinya.ta did you also shift left the line like this
def b_copy_action(sender): tv = sender.superview['TextView'] clipboard.set(tv.text) b_copy.action = b_copy_action
-
-
@shinya.ta ๐ until next problem ๐ข
-
Is it possible to make a speech for this?