
-
-
Enez Houad
@mikael , I regularly use your modules and I thank you for it. Unfortunately, since the last version of ui3, I have an error when I want to use it.
Here is the Traceback :Traceback (most recent call last): File "/private/var/mobile/Library/Mobile Documents/iCloud~com~omz-software~Pythonista3/Documents/ui3-master/sheet.py", line 7, in <module> from ui3.anchor import * File "/private/var/mobile/Library/Mobile Documents/iCloud~com~omz-software~Pythonista3/Documents/ui3-master/ui3/__init__.py", line 12, in <module> from ui3.anchor import * File "/private/var/mobile/Library/Mobile Documents/iCloud~com~omz-software~Pythonista3/Documents/ui3-master/ui3/anchor/__init__.py", line 821, in <module> via_screen, NameError: name 'via_screen' is not defined ```
-
Enez Houad
@cvp Thanks a lot ! Iβm happy to see that I progress slowlyβ¦
I had foundtextView().becomeFirstResponder()
but couldnβt find to witch element it had to be applied. The_get_editor_tab
is not documented ! To find it, do you openeditor.py
in thesite-packages
ofStandard Library
?
It's very instructive π€, I'm going to end up managing on my own. π -
Enez Houad
@cvp I learn a lot adapting your scripts to my needs !
You will find after this message my/your script to add a keyboard icon in the titlebar to call my script to add my special key row to the keyboard.
The system is rather practical, but to make the handling as transparent as possible : when I add my key row, I hide the keyboard withtv.endEditing(True)
, and I would like to make it reappear with my special key row : but Iβve not found a command as simple as tv.startEditing π ; itβs perharps possible to simulate a touch in the TextView, but I neither canβt find a solution to do it π₯Ά
After several hours of searching, I throw in the towel and ask for helpβ¦π₯΅from objc_util import * import ui from ui3.sfsymbol import * w = ObjCClass('UIApplication').sharedApplication().keyWindow() main_view = w.rootViewController().view() def get_toolbar(view): # get main editor toolbar, by recursively walking the view sv = view.subviews() for v in sv: if v._get_objc_classname().startswith(b'OMTabViewToolbar'): return v tb = get_toolbar(v) if tb: return tb # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ def keyboard_btn_action(sender): def run_script(scriptPath): import os from objc_util import ObjCInstance,ObjCClass dir = os.path.expanduser(scriptPath) I3=ObjCClass('PYK3Interpreter').sharedInterpreter() I3.runScriptAtPath_argv_resetEnvironment_(dir, [''], True) iCloudPath = "/private/var/mobile/Library/Mobile Documents/iCloud~com~omz-software~Pythonista3/Documents/" iPadPath = '~/Documents/' scriptPath = 'PROJETS/KEYBOARD/my_special_key_row.py' run_script(iCloudPath + scriptPath) # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ def create_keyboard_button(action,index=0): global __persistent_views assert(callable(action)) tb = get_toolbar(main_view) try: __persistent_views except NameError: __persistent_views={} #check for existing button in this index and delete if needed remove_toolbar_button(index) btn = ui.Button() btn.frame = (110, 24, 40, 40) if ui.get_ui_style() == 'dark': btn.tint_color = 'white' else: btn.tint_color = '#0D89B5' btn.image = SymbolImage('keyboard', point_size=14, weight=THIN, scale=SMALL) btn.image = btn.image.with_rendering_mode(ui.RENDERING_MODE_AUTOMATIC) btn.action=action btn_obj=ObjCInstance(btn) __persistent_views[index]=(btn,action) tb.superview().superview().addSubview_(btn_obj) # in front of all buttons return btn # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ def remove_toolbar_button(index): global __persistent_views try: btn,action = __persistent_views.pop(index) btn.action= None ObjCInstance(btn).removeFromSuperview() except KeyError: pass # =================================================================== #if __name__=='__main__': # if imported by pythonista startup create_keyboard_button(keyboard_btn_action) create_keyboard_button(keyboard_btn_action)
-
Enez Houad
Here is my scrolling special key row to replace the standard one.
This script is a mix between @cvpe's script AddButtonsToPythonistaKeyboard https://github.com/cvpe/Pythonista-scripts/blob/master/AddButtonsToPythonistaKeyboard.py
and my own work.
It uses module ui3.sfsymbol of @mikaelho https://github.com/mikaelho/ui3
Thanks for all their work for Pythonista's community.
It certainly contains errors as I am not an expert coder like the majority of you but it does work for me π
Feel free to improve and adapt it to your needs!# ================================================================= # This script is a mix between @cvpe's script AddButtonsToPythonistaKeyboard # https://github.com/cvpe/Pythonista-scripts/blob/master/AddButtonsToPythonistaKeyboard.py # and my own work. # It uses module ui3.sfsymbol of @mikaelho # https://github.com/mikaelho/ui3 # # enez.houad@free.fr # ================================================================= import ui, editor, clipboard from objc_util import * from ui3.sfsymbol import * @on_main_thread def tv_find(tv): import console, re tv.find = console.input_alert('Expression Γ rechercher :', '', tv.find, hide_cancel_button=True) txt = tv.find for sv in tv.subviews(): if 'SUIButton_PY3' in str(sv._get_objc_classname()): sv.removeFromSuperview() if txt == '': return t = str(tv.text()) for m in re.finditer(txt, t): st,en = m.span() p1 = tv.positionFromPosition_offset_(tv.beginningOfDocument(), st) p2 = tv.positionFromPosition_offset_(tv.beginningOfDocument(), en) rge = tv.textRangeFromPosition_toPosition_(p1,p2) rect = tv.firstRectForRange_(rge) x,y = rect.origin.x,rect.origin.y w,h = rect.size.width,rect.size.height l = ui.Button() l.frame = (x,y,w,h) if '|' not in txt: l.background_color = (1,0,0,0.2) else: # search multiple strings wrds = txt.split('|') idx = wrds.index(t[st:en]) cols = [(1,0,0,0.2), (0,1,0,0.2), (0,0,1,0.2), (1,1,0,0.2), (1,0,1,0.2), (0,1,1,0.2)] col = cols[idx % len(cols)] l.background_color = col l.corner_radius = 4 l.border_width = 1 tv.addSubview_(l) # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ def key_pressed(sender): tv = sender.objc_instance.firstResponder() # associated TextView cursor = tv.offsetFromPosition_toPosition_(tv.beginningOfDocument(), tv.selectedTextRange().start()) # get actual cursor position if sender.name == 'tab': tv.insertText_('\t') elif sender.name == 'paste': tv.insertText_(clipboard.get()) elif sender.name == 'undo': tv.undoManager().undo() elif sender.name == 'redo': tv.undoManager().redo() elif sender.name == 'del_right': # delete at right = delete at left of next if cursor == (len(str(tv.text()))-1): # already after last character return cursor_position = tv.positionFromPosition_offset_(tv.beginningOfDocument(), cursor+1) tv.selectedTextRange = tv.textRangeFromPosition_toPosition_(cursor_position, cursor_position) tv.deleteBackward() elif sender.name == 'find': tv_find(tv) elif sender.name == 'line-': tv.insertText_('# ' + 65 * 'β') elif sender.name == 'line=': tv.insertText_('# ' + 65 * '=') elif sender.name == 'line#': tv.insertText_(67 * '#') else: # all other keys > insert button title tv.insertText_(sender.title) # =================================================================== class SpecialKeyRow(ui.View): def __init__(self, pad, *args, **kwargs): self.pad = pad sw, sh = ui.get_screen_size() self.uiStyle = ui.get_ui_style() self.buttonsList = [] self.buttonWidth = (sw - (2*8) - (24*4)) / 25 self.buttonHeight = 40 # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ # MAIN VIEW self.width, self.height = sw, 50 self.alpha = 0.98 # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ # SCROLL VIEW sv = ui.ScrollView(name='scrollview') sv.width, sv.height = (sw, 50) sv.content_size = (2*sw, 50) sv.bounces = False sv.shows_horizontal_scroll_indicator = False sv.paging_enabled = True sv.x, sv.y = (0, 0) colorDict = {'light':'#D6D8DD', 'dark':'#343639'} sv.background_color = colorDict[self.uiStyle] self.add_subview(sv) # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ # BUTTONS IN SCROLL VIEW # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ for pad_elem in self.pad: if not 'style' in pad_elem: bStyle = 'light' else: bStyle = pad_elem['style'] if 'title' in pad_elem: b = self.add_text_button(name=pad_elem['key'], title=pad_elem['title'], style=bStyle) elif 'symbol' in pad_elem: b = self.add_symbol_button(name=pad_elem['key'], symbol_name=pad_elem['symbol'], style=bStyle) self.add_scrollview_button(b) # =================================================================== def add_scrollview_button(self, b): b.y = 10 if self.buttonsList == []: b.x = 8 # 1er bouton else: lastButton = self.buttonsList[-1] b.x = lastButton.x + lastButton.width + 4 # intervalle 4 px if len(self.buttonsList) == 25: b.x += 12 # 2e page b.action = key_pressed retain_global(b) self['scrollview'].add_subview(b) self.buttonsList.append(b) # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ def add_text_button(self, name='', title='', width=40, style='light'): b = self.add_button(name, style) b.title = title b.font = ('<system>', 18) if width == None: b.width = ui.measure_string(b.title,font=b.font)[0] + 28 else: b.width = self.buttonWidth return b # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ def add_symbol_button(self, name='', symbol_name='', style='light'): b = self.add_button(name, style) symbol_image = SymbolImage(symbol_name, point_size=11, weight=LIGHT, scale=SMALL) b.image = symbol_image b.width = self.buttonWidth return b # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ def add_button(self, name='', backgroundStyle='light'): b = ui.Button(name=name) b.corner_radius = 8 colorsDict = { 'light' :({'light':'#FFFFFF', 'dark':'#B4B9C1'}, 'black'), 'dark' :({'light':'#717274', 'dark':'#4D4F50'}, 'white') } b.background_color = colorsDict[self.uiStyle][0][backgroundStyle] b.tint_color = colorsDict[self.uiStyle][1] b.alpha = self.alpha b.font = ('<system>', 18) b.height = self.buttonHeight return b # =================================================================== @on_main_thread def AddButtonsToPythonistaKeyboard(pad=None): def numeric_keys(): list = [] for i in range(1, 10): list.append({'key':str(i), 'title':str(i)}) list.append({'key':'0', 'title':'0'}) return list if not pad: pad = [ {'key':'tab', 'symbol':'arrow.right.to.line.alt'}, {'key':'undo', 'symbol':'arrow.uturn.left', 'style':'dark'}, {'key':'redo','symbol':'arrow.uturn.right', 'style':'dark'}, {'key':'paste', 'symbol':'doc.on.clipboard'}, {'key':'#', 'title':'#'}, {'key':'_', 'title':'_'}, {'key':"'", 'title':"'"}, {'key':'"', 'title':'"'}, {'key':"'''", 'title':"'''"}, {'key':'(', 'title':'('}, {'key':')', 'title':')'}, {'key':'[', 'title':'['}, {'key':']', 'title':']'}, {'key':'{', 'title':'{'}, {'key':'}', 'title':'}'}, {'key':'+', 'title':'+'}, {'key':'-', 'title':'-'}, {'key':'*', 'title':'*'}, {'key':'/', 'title':'/'}, {'key':"\\", 'title':"\\"}, {'key':'<', 'title':'<'}, {'key':'>', 'title':'>'}, {'key':'=', 'title':'='}, {'key':':', 'title':':'}, {'key':'del_right', 'symbol':'delete.right', 'style':'dark'}, {'key':'find', 'symbol':'magnifyingglass', 'style':'dark'} ] pad += numeric_keys() pad += [ {'key':'+', 'title':'+'}, {'key':'-', 'title':'-'}, {'key':'*', 'title':'*'}, {'key':'/', 'title':'/'}, {'key':'<', 'title':'<'}, {'key':'>', 'title':'>'}, {'key':'=', 'title':'='}, {'key':'line-', 'title':'---'}, {'key':'line=', 'title':'==='}, {'key':'line#', 'title':'###'} ] ev = editor._get_editor_tab().editorView() tv = ev.textView() v = SpecialKeyRow(pad) vo = ObjCInstance(v) retain_global(v) tv.setInputAccessoryView_(vo) # attach accessory to textview tv.find = '' # =================================================================== if __name__ == '__main__': AddButtonsToPythonistaKeyboard() ```
-
-
Enez Houad
@cvp Thanks a lot for your work. But my goal is to get a reduced row of keys as I think that the original one is to large for the small screen of my iPad mini 4. I regret that itβs not possible to assign the fonction to a normal ui button.
-
Enez Houad
@cvp Please, how do you insert directly your pictures in comments ?
-
-
Enez Houad
The only solution I've found is to make my own special key row with the help of the cvp example ;-). It's quite easy for normal keys, but I don't find solution to implement the undo/redo key? Perhaps with objC ?