Advertisement
Guest User

Untitled

a guest
Mar 21st, 2019
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.35 KB | None | 0 0
  1. import ui
  2. from objc_util import *
  3. import clipboard
  4. import speech
  5.  
  6. v = ui.View()
  7. v.frame = (0,0,500,320)
  8. v.name = 'Move cursor in TextView'
  9.  
  10. tv = ui.TextView()
  11. tv.name = 'TextView'
  12. tv.frame = (120,10,370,140)
  13. tv.font = ('Arial Rounded MT Bold',24)
  14. tv.text = 'aรฉ๐Ÿ˜ข๐Ÿ‡ฏ๐Ÿ‡ต๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ฉโ€๐ŸŽจ'
  15. v.add_subview(tv)
  16.  
  17. tv2 = ui.TextView()
  18. tv2.name = 'TextView2'
  19. tv2.frame = (120,160,370,140)
  20. tv2.font = ('Arial Rounded MT Bold',24)
  21. tv2.text = 'second'
  22. v.add_subview(tv2)
  23.  
  24. def say_char(tv):
  25. # test speech character at cursor
  26. idxtopos = IndexToPos(tv,'') # list index to position
  27. i = tv.selected_range[0]
  28. #print(i,idxtopos)
  29. i = idxtopos[i] # used to check if same base character
  30. if i < len(tv.text):
  31. c = tv.text[i]
  32. if c == ' ':
  33. c ='space'
  34. speech.say(c,'jp-JP')
  35.  
  36. def selected_range(tv,i):
  37. tvo = ObjCInstance(tv)
  38. p1 = tvo.positionFromPosition_offset_(tvo.beginningOfDocument(), i)
  39. p2 = p1
  40. #p2 = tvo.positionFromPosition_offset_(tvo.beginningOfDocument(), i+1)
  41. tvo.selectedTextRange = tvo.textRangeFromPosition_toPosition_(p1, p2)
  42. say_char(tv)
  43. return
  44.  
  45. # some emoji like flags count as 2 for len but as 4 for selected_range
  46. def IndexToPos(tv,type):
  47. tvo = ObjCInstance(tv)
  48. # build array index -> position in range
  49. idxtopos = []
  50. pre_x = -1
  51. #print(tv.text)
  52. i = 0
  53. for c in tv.text:
  54. # nbr characters used e=1 รฉ=1 ๐Ÿ˜‚=1 ๐Ÿ‡ฏ๐Ÿ‡ต=2 ๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง=7
  55. # some emoji generate more than one character,
  56. # sometimes counted for more than one in range
  57. # 1,2,3->1 4->2
  58. nb = 1 + int(len(c.encode('utf-8'))/4)
  59. for j in range(0,nb):
  60. p1 = tvo.positionFromPosition_offset_(tvo.beginningOfDocument(), len(idxtopos))
  61. p2 = p1
  62. rge = tvo.textRangeFromPosition_toPosition_(p1, p2)
  63. rect = tvo.firstRectForRange_(rge) # CGRect
  64. x = rect.origin.x
  65. if x == float('inf') or x == pre_x:
  66. # same x as previous one, composed character
  67. pass
  68. else:
  69. pre_x = x
  70. i = len(idxtopos)
  71. idxtopos.append(i) # start position of c
  72. #print(c,nb,len(idxtopos)-1,i,x)
  73. idxtopos.append(i+1) # end position of last c
  74. #print(idxtopos)
  75. # get index of actual cursor
  76. i = tv.selected_range[0] # actual position of cursor
  77. # often p is one of sub_chars, not always the first one
  78. p = idxtopos[i] # used to check if same base character
  79. #print(p,i,idxtopos)
  80. if type == 'left':
  81. if i == 0:
  82. return # already before character
  83. while True:
  84. i = i - 1
  85. if idxtopos[i] != p:
  86. q = idxtopos[i]
  87. # seach first sub-character
  88. while i > 0:
  89. if idxtopos[i-1] != q:
  90. break
  91. i = i - 1
  92. break
  93. elif type == 'right':
  94. if i == (len(idxtopos)-1):
  95. return # already after last character
  96. while True:
  97. i = i + 1
  98. if idxtopos[i] != p:
  99. break
  100. elif type == 'end':
  101. i = len(idxtopos)-1
  102. else:
  103. return idxtopos
  104. r = idxtopos[i]
  105. selected_range(tv,i)
  106. return idxtopos
  107.  
  108. b_top = ui.Button()
  109. b_top.frame = (10,10,100,32)
  110. b_top.title = 'begin'
  111. b_top.background_color = 'white'
  112. b_top.border_width = 1
  113. def b_top_action(sender):
  114. name = str(ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder().name())
  115. tv = sender.superview[name]
  116. tv.selected_range = (0,0)
  117. say_char(tv)
  118. b_top.action = b_top_action
  119. v.add_subview(b_top)
  120.  
  121. b_left = ui.Button()
  122. b_left.frame = (10,50,100,32)
  123. b_left.title = 'left'
  124. b_left.background_color = 'white'
  125. b_left.border_width = 1
  126. def b_left_action(sender):
  127. name = str(ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder().name())
  128. tv = sender.superview[name]
  129. idxtopos = IndexToPos(tv,'left') # list index to position
  130. b_left.action = b_left_action
  131. v.add_subview(b_left)
  132.  
  133. b_right = ui.Button()
  134. b_right.frame = (10,90,100,32)
  135. b_right.title = 'right'
  136. b_right.background_color = 'white'
  137. b_right.border_width = 1
  138. def b_right_action(sender):
  139. name = str(ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder().name())
  140. tv = sender.superview[name]
  141. idxtopos = IndexToPos(tv,'right') # list index to position
  142. b_right.action = b_right_action
  143. v.add_subview(b_right)
  144.  
  145. b_bottom = ui.Button()
  146. b_bottom.frame = (10,130,100,32)
  147. b_bottom.title = 'end'
  148. b_bottom.background_color = 'white'
  149. b_bottom.border_width = 1
  150. def b_bottom_action(sender):
  151. name = str(ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder().name())
  152. tv = sender.superview[name]
  153. idxtopos = IndexToPos(tv,'end') # list index to position
  154. b_bottom.action = b_bottom_action
  155. v.add_subview(b_bottom)
  156.  
  157. def get_xy(tv):
  158. idxtopos = IndexToPos(tv,'') # list index to position
  159. tvo = ObjCInstance(tv)
  160. x_y = []
  161. for i in range(0,len(idxtopos)+1): # x,y of each character
  162. p1 = tvo.positionFromPosition_offset_(tvo.beginningOfDocument(), i)
  163. rge = tvo.textRangeFromPosition_toPosition_(p1,p1)
  164. rect = tvo.firstRectForRange_(rge) # CGRect
  165. x,y = rect.origin.x,rect.origin.y
  166. if i == len(idxtopos):
  167. if i > 0:
  168. x,y = x_y[i-1]
  169. else:
  170. # text is empty
  171. x,y = 0,0
  172. if x == float('inf'):
  173. x,y = x_prec+15,y_prec
  174. x_prec,y_prec = x,y
  175. x_y.append((x,y))
  176. return x_y
  177.  
  178. b_up = ui.Button()
  179. b_up.frame = (10,170,100,32)
  180. b_up.title = 'up'
  181. b_up.background_color = 'white'
  182. b_up.border_width = 1
  183. def b_up_action(sender):
  184. name = str(ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder().name())
  185. tv = sender.superview[name]
  186. x_y = get_xy(tv)
  187. c = tv.selected_range[0]
  188. xc,yc = x_y[c]
  189. i = c - 1
  190. while i >= 0:
  191. x,y = x_y[i]
  192. if y < yc:
  193. # previous row
  194. if x <= xc:
  195. selected_range(tv,i)
  196. return
  197. i = i - 1
  198. b_up.action = b_up_action
  199. v.add_subview(b_up)
  200.  
  201. b_down = ui.Button()
  202. b_down.frame = (10,210,100,32)
  203. b_down.title = 'down'
  204. b_down.background_color = 'white'
  205. b_down.border_width = 1
  206. def b_down_action(sender):
  207. name = str(ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder().name())
  208. tv = sender.superview[name]
  209. idxtopos = IndexToPos(tv,'') # list index to position
  210. x_y = get_xy(tv)
  211. c = tv.selected_range[0]
  212. #print(x_y,c)
  213. xc,yc = x_y[c]
  214. i = c# - 1 # I don't remember why this "- 1"
  215. while i < len(idxtopos):
  216. x,y = x_y[i]
  217. if y > yc:
  218. # next row
  219. if x >= xc:
  220. selected_range(tv,i)
  221. return
  222. else:
  223. if (i+1) < len(idxtopos):
  224. if x_y[i+1][1] > y: # i = last character of row under cursor
  225. selected_range(tv,i)
  226. return
  227. else:
  228. pass # try next x
  229. else:
  230. # last character of last row
  231. selected_range(tv,i)
  232. return
  233. i = i + 1
  234. b_down.action = b_down_action
  235. v.add_subview(b_down)
  236.  
  237. b_copy = ui.Button()
  238. b_copy.frame = (10,250,100,32)
  239. b_copy.title = 'copy'
  240. b_copy.background_color = 'white'
  241. b_copy.border_width = 1
  242. def b_copy_action(sender):
  243. name = str(ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder().name())
  244. tv = sender.superview[name]
  245. clipboard.set(tv.text)
  246. b_copy.action = b_copy_action
  247. v.add_subview(b_copy)
  248.  
  249. b_clear = ui.Button()
  250. b_clear.frame = (10,290,100,32)
  251. b_clear.title = 'clear'
  252. b_clear.background_color = 'white'
  253. b_clear.border_width = 1
  254. def b_clear_action(sender):
  255. name = str(ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder().name())
  256. tv = sender.superview[name]
  257. tv.text = ''
  258. b_clear.action = b_clear_action
  259. v.add_subview(b_clear)
  260.  
  261. def typeChar(sender):
  262. '''finds active textinput, and types the button's title'''
  263. tf=sender.objc_instance.firstResponder()
  264. tf.insertText_(sender.title)
  265.  
  266. #create special keys
  267. def prev(sender):
  268. '''simulates 'tab' key, go to next field '''
  269.  
  270. s=sender.objc_instance.firstResponder()._previousKeyResponder().becomeFirstResponder()
  271. buttons.append(ui.Button(image=ui.Image.named('iob:ios7_arrow_back_32'),action=prev))
  272.  
  273. def next(sender):
  274. '''simulates 'tab' key, go to next field '''
  275. s=sender.objc_instance.firstResponder()._nextKeyResponder().becomeFirstResponder()
  276. buttons.append(ui.Button(image=ui.Image.named('iob:ios7_arrow_forward_32'),action=next))
  277.  
  278.  
  279. #create normal keys
  280. d = 32
  281. dd = 4
  282. emojis = '๐Ÿ˜Š๐Ÿ˜œ๐Ÿ˜ฑ๐Ÿ’ฆโ˜”๏ธ๐Ÿ˜€๐Ÿ˜ƒ๐Ÿ˜„๐Ÿ˜๐Ÿ˜†๐Ÿ˜…๐Ÿ˜‚๐Ÿคฃโ˜บ๏ธ๐Ÿ˜Š๐Ÿ˜‡๐Ÿ™‚๐Ÿ™ƒ๐Ÿ˜‰๐Ÿ˜Œ๐Ÿ˜๐Ÿฅฐ๐Ÿ˜˜๐Ÿ˜—๐Ÿ˜™๐Ÿ˜š๐Ÿ˜‹๐Ÿ˜›๐Ÿ˜๐Ÿ˜œ๐Ÿคช๐Ÿคจ๐Ÿง๐Ÿค“๐Ÿ˜Ž๐Ÿคฉ๐Ÿฅณ๐Ÿ˜๐Ÿ˜’๐Ÿ˜ž๐Ÿ˜”๐Ÿ˜Ÿ๐Ÿ˜•๐Ÿ™โ˜น๏ธ๐Ÿ˜ฃ๐Ÿ˜–๐Ÿ˜ซ๐Ÿ˜ฉ๐Ÿฅบ๐Ÿ˜ข๐Ÿ˜ญ๐Ÿ˜ค๐Ÿ˜ ๐Ÿ˜ก๐Ÿคฌ๐Ÿคฏ๐Ÿ˜ณ๐Ÿฅต๐Ÿฅถ๐Ÿ˜ฑ๐Ÿ˜จ๐Ÿ˜ฐ๐Ÿ˜ฅ๐Ÿ˜“๐Ÿค—๐Ÿค”๐Ÿคญ๐Ÿคซ๐Ÿคฅ๐Ÿ˜ถ๐Ÿ˜๐Ÿ˜‘๐Ÿ˜ฌ๐Ÿ˜ฆ๐Ÿ˜ง๐Ÿ˜ฎ๐Ÿ˜ฒ๐Ÿ˜ด๐Ÿคค๐Ÿ˜ช๐Ÿ˜ต๐Ÿค๐Ÿฅด๐Ÿคข๐Ÿคฎ๐Ÿคง๐Ÿ˜ท๐Ÿค’๐Ÿค•๐Ÿค‘๐Ÿค ๐Ÿ˜ˆ'
  283. n_emojis_in_set = 20
  284. n_sets = 1 + int((len(emojis)-1)/n_emojis_in_set)
  285.  
  286. tv.i_set = 0
  287. tv.n_sets = n_sets
  288. def nextSet(sender):
  289. name = str(ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder().name())
  290. tv = v[name]
  291. tv.i_set = tv.i_set + 1
  292. if tv.i_set == tv.n_sets:
  293. tv.i_set = 0
  294. #attach our accessory to the textfield, and textview
  295. ww = vv_array[tv.i_set]
  296. tvo = tv.objc_instance
  297. #print(dir(tvo))
  298. tvo.setInputAccessoryView_(ObjCInstance(ww))
  299. tvo.reloadInputViews()
  300.  
  301. vv_array = []
  302. for i_set in range(0,n_sets):
  303. l = int(len(emojis)/n_sets)
  304. i = i_set * l
  305. set_emojis = emojis[i:i+l]
  306. w, h = ui.get_screen_size()
  307. vv = ui.View(name='set'+str(i_set))
  308. vv.background_color = 'lightgray'
  309. h = 0
  310. x = dd
  311. y = dd
  312. for button_title in set_emojis:
  313. b = ui.Button(title=button_title)
  314. b_action = typeChar
  315. b.action=b_action
  316. b.frame = (x,y,d,d)
  317. b.font = ('.SFUIText', d)
  318. if (y+d+dd) > h:
  319. h = y + d + dd
  320. vv.add_subview(b)
  321. x = x + d + dd
  322. if (x+d+dd) > w:
  323. x = dd
  324. y = y + d + dd
  325. device = ObjCClass('UIDevice').currentDevice().model()
  326. if str(device) == 'iPhone':
  327. bb_target = ui.Button()
  328. bb_target.title = 'next emojis'
  329. wb,hb = ui.measure_string(bb_target.title,font=bb_target.font)
  330. bb_target.action = nextSet
  331. bb_target.frame = (dd,h,wb+2,d)
  332. vv.add_subview(bb_target)
  333. h = h + d + dd
  334. vv.frame = (0,0,w,h)
  335. vv_array.append(vv)
  336.  
  337. #nextSet(vv_array[n_sets-1]['nextSet']) # display 1st set
  338.  
  339. device = ObjCClass('UIDevice').currentDevice().model()
  340. if str(device) == 'iPad':
  341. # add a button at right of "typing suggestions", just above the keyboard
  342. bb_target = ui.Button()
  343. bb_target.action = nextSet
  344.  
  345. UIBarButtonItem = ObjCClass('UIBarButtonItem').alloc().initWithTitle_style_target_action_('next emojis',0,bb_target,sel('invokeAction:')).autorelease()
  346. #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()
  347.  
  348. UIBarButtonItemGroup = ObjCClass('UIBarButtonItemGroup').alloc().initWithBarButtonItems_representativeItem_([UIBarButtonItem],None)
  349.  
  350. for tv in v.subviews:
  351. if 'TextView' in str(type(tv)):
  352. tv.i_set = 0
  353. tv.n_sets = n_sets
  354.  
  355. tvo = tv.objc_instance
  356.  
  357. if str(device) == 'iPad':
  358. #tvo.inputAssistantItem().setTrailingBarButtonGroups([UIBarButtonItemGroup])
  359. tvo.inputAssistantItem().setLeadingBarButtonGroups([UIBarButtonItemGroup])
  360. #print(dir(tvo))
  361. #print(dir(tvo.inputAssistantItem()))
  362.  
  363. ww = vv_array[tv.i_set]
  364. tvo.setInputAccessoryView_(ObjCInstance(ww))
  365. tvo.reloadInputViews()
  366. v.present('sheet')
  367. v['TextView'].selected_range = (0,0)
  368. v['TextView'].begin_editing()
  369. #nextSet(vv_array[n_sets-1]['nextSet']) # display 1st set
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement