-
-
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 ?
-
Enez Houad
I have been using Pythonista occasionally for two years now. With the help of the forum and by rummaging through the web, I manage to make some nice little applications. However, I regularly come up against basic problems related to my lack of Python skills. This is the case today ;-)
I can't understand why my script doesn't work.
I just want to make a class of Buttons... but my title doesn't display.
My mistake must be stupid, but I can't find it!import ui class MyButton (ui.View): def __init__(self, *args, **kwargs): self.btn = ui.Button() for name in kwargs.keys(): value = kwargs[name] self.__setattr__(name, value) self.add_subview(self.btn) def __setattr__(self, name, value): print(f'β’ setattr : {name} = {value}') if name != 'btn': self.btn.__setattr__(name, value) super().__setattr__(name, value) if __name__ == '__main__': mainView = ui.View( name='MyButton Demo', bg_color='lightgrey', frame=(0, 0, 400, 400)) myBtn = MyButton( name='MyButton', title='Press me', width=200) myBtn.center = mainView.center myBtn.y = 200 myBtn.background_color = 'red' myBtn.tint_color = 'white' mainView.add_subview(myBtn) mainView.present('sheet')
-
Enez Houad
@mikael, Perfect ππππ
Thank you very much, I would find it hard to do without Scripter! -
Enez Houad
@mikael, Yes, Iβve updated Scripter (even uninstall and reinstall) and restarted Pythonista. And nowβ¦ it works the first time, doesnβt the second and crash the third !
-
Enez Houad
@mikael , unfortunately, the problem persists ! Do I need to reinstall something ?
-
Enez Houad
@mikael , Iβve got a simular problem ! My animations with calls to scripter only works one time π’. I need to restart Pythonista !
I take this opportunity to thank you for your fantastic modules. iPadOS 14.3 beta on iPad mini 4 -
Enez Houad
Has someone found a solution ? π₯΅ the problem appears quite all the time for me and itβs really difficult to type text in rhe reduced special key row - Iβve got an iPad mini and the keyboard is small ;-)
-
Enez Houad
@cvp Perfect, it works for me π always so impressive π
-
Enez Houad
@mikael, this is not only a iPhone problem as it appears on my iPad mini 4 with both orientations : portrait and landscape.
It's a pity that there is no other solution than to use a fullscreen present mode as I only wanted to present a choice view with a tableView, never mind I will adapt ! -
Enez Houad
Iβve not been using Pythonista for a long time, ios version have changed and now I have some problems with my scripts :
The first is that my keyboard loose the extra line at the top, but Iβve seen on the forum that Iβm the only one ;-) the second (but my search on the forum doesβnt help me to find a solution - my bad english is really a problem) is that now a view in sheet mode close when I slide down with one finger. I would like to block this process.
Thanks for a solution ! -