Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import ui
- from objc_util import *
- import clipboard
- import speech
- 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,140)
- tv.font = ('Arial Rounded MT Bold',24)
- tv.text = 'aรฉ๐ข๐ฏ๐ต๐จโ๐จโ๐งโ๐ฉโ๐จ'
- v.add_subview(tv)
- tv2 = ui.TextView()
- tv2.name = 'TextView2'
- tv2.frame = (120,160,370,140)
- tv2.font = ('Arial Rounded MT Bold',24)
- tv2.text = 'second'
- v.add_subview(tv2)
- def say_char(tv):
- # test speech character at cursor
- idxtopos = IndexToPos(tv,'') # list index to position
- i = tv.selected_range[0]
- #print(i,idxtopos)
- i = idxtopos[i] # used to check if same base character
- if i < len(tv.text):
- c = tv.text[i]
- if c == ' ':
- c ='space'
- speech.say(c,'jp-JP')
- def selected_range(tv,i):
- tvo = ObjCInstance(tv)
- p1 = tvo.positionFromPosition_offset_(tvo.beginningOfDocument(), i)
- p2 = p1
- #p2 = tvo.positionFromPosition_offset_(tvo.beginningOfDocument(), i+1)
- tvo.selectedTextRange = tvo.textRangeFromPosition_toPosition_(p1, p2)
- say_char(tv)
- return
- # some emoji like flags count as 2 for len but as 4 for selected_range
- def IndexToPos(tv,type):
- tvo = ObjCInstance(tv)
- # build array index -> position in range
- idxtopos = []
- pre_x = -1
- #print(tv.text)
- i = 0
- 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(tv,i)
- return idxtopos
- b_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):
- name = str(ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder().name())
- tv = sender.superview[name]
- tv.selected_range = (0,0)
- say_char(tv)
- 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):
- name = str(ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder().name())
- tv = sender.superview[name]
- idxtopos = IndexToPos(tv,'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):
- name = str(ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder().name())
- tv = sender.superview[name]
- idxtopos = IndexToPos(tv,'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):
- name = str(ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder().name())
- tv = sender.superview[name]
- idxtopos = IndexToPos(tv,'end') # list index to position
- b_bottom.action = b_bottom_action
- v.add_subview(b_bottom)
- def get_xy(tv):
- idxtopos = IndexToPos(tv,'') # 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_y
- b_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):
- name = str(ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder().name())
- tv = sender.superview[name]
- 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(tv,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):
- name = str(ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder().name())
- tv = sender.superview[name]
- idxtopos = IndexToPos(tv,'') # 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(tv,i)
- return
- else:
- if (i+1) < len(idxtopos):
- if x_y[i+1][1] > y: # i = last character of row under cursor
- selected_range(tv,i)
- return
- else:
- pass # try next x
- else:
- # last character of last row
- selected_range(tv,i)
- return
- i = i + 1
- b_down.action = b_down_action
- v.add_subview(b_down)
- 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):
- name = str(ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder().name())
- tv = sender.superview[name]
- 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):
- name = str(ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder().name())
- tv = sender.superview[name]
- tv.text = ''
- b_clear.action = b_clear_action
- v.add_subview(b_clear)
- def typeChar(sender):
- '''finds active textinput, and types the button's title'''
- tf=sender.objc_instance.firstResponder()
- tf.insertText_(sender.title)
- #create special keys
- def prev(sender):
- '''simulates 'tab' key, go to next field '''
- s=sender.objc_instance.firstResponder()._previousKeyResponder().becomeFirstResponder()
- buttons.append(ui.Button(image=ui.Image.named('iob:ios7_arrow_back_32'),action=prev))
- def next(sender):
- '''simulates 'tab' key, go to next field '''
- s=sender.objc_instance.firstResponder()._nextKeyResponder().becomeFirstResponder()
- buttons.append(ui.Button(image=ui.Image.named('iob:ios7_arrow_forward_32'),action=next))
- #create normal keys
- d = 32
- dd = 4
- emojis = '๐๐๐ฑ๐ฆโ๏ธ๐๐๐๐๐๐ ๐๐คฃโบ๏ธ๐๐๐๐๐๐๐๐ฅฐ๐๐๐๐๐๐๐๐๐คช๐คจ๐ง๐ค๐๐คฉ๐ฅณ๐๐๐๐๐๐๐โน๏ธ๐ฃ๐๐ซ๐ฉ๐ฅบ๐ข๐ญ๐ค๐ ๐ก๐คฌ๐คฏ๐ณ๐ฅต๐ฅถ๐ฑ๐จ๐ฐ๐ฅ๐๐ค๐ค๐คญ๐คซ๐คฅ๐ถ๐๐๐ฌ๐ฆ๐ง๐ฎ๐ฒ๐ด๐คค๐ช๐ต๐ค๐ฅด๐คข๐คฎ๐คง๐ท๐ค๐ค๐ค๐ค ๐'
- n_emojis_in_set = 20
- n_sets = 1 + int((len(emojis)-1)/n_emojis_in_set)
- tv.i_set = 0
- tv.n_sets = n_sets
- def nextSet(sender):
- name = str(ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder().name())
- tv = v[name]
- tv.i_set = tv.i_set + 1
- if tv.i_set == tv.n_sets:
- tv.i_set = 0
- #attach our accessory to the textfield, and textview
- ww = vv_array[tv.i_set]
- tvo = tv.objc_instance
- #print(dir(tvo))
- tvo.setInputAccessoryView_(ObjCInstance(ww))
- tvo.reloadInputViews()
- vv_array = []
- for i_set in range(0,n_sets):
- l = int(len(emojis)/n_sets)
- i = i_set * l
- set_emojis = emojis[i:i+l]
- w, h = ui.get_screen_size()
- vv = ui.View(name='set'+str(i_set))
- vv.background_color = 'lightgray'
- h = 0
- x = dd
- y = dd
- for button_title in set_emojis:
- b = ui.Button(title=button_title)
- b_action = typeChar
- b.action=b_action
- b.frame = (x,y,d,d)
- b.font = ('.SFUIText', d)
- if (y+d+dd) > h:
- h = y + d + dd
- vv.add_subview(b)
- x = x + d + dd
- if (x+d+dd) > w:
- x = dd
- y = y + d + dd
- device = ObjCClass('UIDevice').currentDevice().model()
- if str(device) == 'iPhone':
- bb_target = ui.Button()
- bb_target.title = 'next emojis'
- wb,hb = ui.measure_string(bb_target.title,font=bb_target.font)
- bb_target.action = nextSet
- bb_target.frame = (dd,h,wb+2,d)
- vv.add_subview(bb_target)
- h = h + d + dd
- vv.frame = (0,0,w,h)
- vv_array.append(vv)
- #nextSet(vv_array[n_sets-1]['nextSet']) # display 1st set
- device = ObjCClass('UIDevice').currentDevice().model()
- if str(device) == 'iPad':
- # add a button at right of "typing suggestions", just above the keyboard
- bb_target = ui.Button()
- bb_target.action = nextSet
- UIBarButtonItem = ObjCClass('UIBarButtonItem').alloc().initWithTitle_style_target_action_('next emojis',0,bb_target,sel('invokeAction:')).autorelease()
- #UIBarButtonItem = ObjCClass('UIBarButtonItem').alloc().initWithImage_style_target_action_(ns(ui.Image.named('emj:Bicycle').with_rendering_mode(ui.RENDERING_MODE_ORIGINAL)),0,bb_target,sel('invokeAction:')).autorelease()
- UIBarButtonItemGroup = ObjCClass('UIBarButtonItemGroup').alloc().initWithBarButtonItems_representativeItem_([UIBarButtonItem],None)
- for tv in v.subviews:
- if 'TextView' in str(type(tv)):
- tv.i_set = 0
- tv.n_sets = n_sets
- tvo = tv.objc_instance
- if str(device) == 'iPad':
- #tvo.inputAssistantItem().setTrailingBarButtonGroups([UIBarButtonItemGroup])
- tvo.inputAssistantItem().setLeadingBarButtonGroups([UIBarButtonItemGroup])
- #print(dir(tvo))
- #print(dir(tvo.inputAssistantItem()))
- ww = vv_array[tv.i_set]
- tvo.setInputAccessoryView_(ObjCInstance(ww))
- tvo.reloadInputViews()
- v.present('sheet')
- v['TextView'].selected_range = (0,0)
- v['TextView'].begin_editing()
- #nextSet(vv_array[n_sets-1]['nextSet']) # display 1st set
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement