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.
Braille application.
-
I am thinking of an application to input text using Braille.
I'm thinking about Braille in Japanese.
Is it possible for Pythonisa?
-
Have you looked at the built in braile input?
https://support.apple.com/guide/iphone/type-onscreen-braille-using-voiceover-iph10366cc30/ios
-
@shinya.ta Does the iOS standard Braille also support Japanese Braille like Wikipedia?
If not, do you want to entirely write yourself a script to allow Japanese Braille input in Pythonista? If this is the case, could you describe how you imagine that?
-
@shinya.ta Please, try this, with these remarks:
- I really don't know nor Japonese, nor Braille, thus...
- this script is obviously quick and dirty, only to show what is possible
- positions of the 6 buttons could be parametrized for each user
1 4
2 5
3 6 - standard keyboard could be removed or replaced by some keys (left delete...)
- I only can test on iPad, sorry if not works on iPhone
- the script needs Gestures of @mikael, our Ukko Ylijumala from Finland 😀
- use of 3 fingers needs you disable Settings/General/Accessibilty/Zoom
- it only supports a few points combinations for testing
but you can easily add other ones
Japanese_Braille = { '1':'あ', '12':'い', '14':'う', '124':'え', '24':'お', '16':'か', '1246':'け' }
- I'm ready do continue the script development, with your requests, but at my speed and availability
import ui from objc_util import * from Gestures import Gestures def SetTextFieldPad(tf, pad=None, clearButtonMode=False, undo_redo_pasteBarButtons=False, textfield_did_change=None): if not pad: pad = [ {'key':'1','x':2,'y':1}, {'key':'2','x':2,'y':2}, {'key':'3','x':2,'y':3}, {'key':'4','x':5,'y':1}, {'key':'5','x':5,'y':2}, {'key':'6','x':5,'y':3}, ] Japanese_Braille = { '1':'あ', '12':'い', '14':'う', '124':'え', '24':'お', '16':'か', '1246':'け' } tfo = ObjCInstance(tf).textField() # UITextField is subview of ui.TextField def key_pressed(key): if key not in Japanese_Braille: return ch = Japanese_Braille[key] cursor = tfo.offsetFromPosition_toPosition_(tfo.beginningOfDocument(), tfo.selectedTextRange().start()) tf.text = tf.text[:cursor] + ch + tf.text[cursor:] cursor = cursor + 1 if textfield_did_change: textfield_did_change(tfb) # set cursor cursor_position = tfo.positionFromPosition_offset_(tfo.beginningOfDocument(), cursor) tfo.selectedTextRange = tfo.textRangeFromPosition_toPosition_(cursor_position, cursor_position) def tapped(data): #print('tapped',data.number_of_touches) #print(len(data.recognizer.touches())) bs = [] for t in data.recognizer.touches(): pt = t.locationInView_(ObjCInstance(v)) for b in v.subviews: r = b.width/2 x = b.x + r y = b.y + r if ((pt.x-x)**2+(pt.y-y)**2) <= r**2: # touch in circle of button if b.name not in bs: # avoid two times same button bs.append(b.name) if len(bs) != data.number_of_touches: # at least one touch outside buttons, no way to recognize return seq = '' for b in sorted(bs): seq = seq + b key_pressed(seq) # design your keyboard v = ui.View() v.border_color = 'red' v.border_width = 4 w,h = ui.get_screen_size() h = h - 350 db = w/6 dd = (h-3*db)/4 y_max = 0 for pad_elem in pad: b = ui.Button() b.name = pad_elem['key'] b.background_color = (1,0,0,0.5) b.tint_color = 'red' b.font = ('Academy Engraved LET',36) b.corner_radius = db/2 b.title = b.name x = (pad_elem['x']-1)*db y = dd + (pad_elem['y']-1)*(db+dd) b.frame = (x,y,db,db) b.TextField = tf # store tf as key attribute needed when pressed b.enabled = False v.add_subview(b) y_max = max(y_max,y+db+dd) v.width = ui.get_screen_size()[0] v.height = h g = Gestures() for n in range(1,7): g.add_tap(v, tapped,number_of_touches_required=n) # view of keyboard retain_global(v) # see https://forum.omz-software.com/topic/4653/button-action-not-called-when-view-is-added-to-native-view tfo.setInputAccessoryView_(ObjCInstance(v)) # attach accessory to textview #print(dir(tfo)) if __name__ == '__main__': import ui tf = ui.TextField() SetTextFieldPad(tf) tf.text = '' tf.width = 200 tf.name = 'Japanese Braille' tf.present('sheet') tf.begin_editing() tf.wait_modal()
-
Special gestures can also be added like in standard IOS Braille.
For example, here-after:- swipe from right to left to back space, delete at left
- swipe from left to right to add a space
- swipe from bottom to top with 3 fingers to return and dismiss the keyboard
Sorry to post two similar scripts so, next time, if any, I would post it on GitHub
import ui from objc_util import * from Gestures import Gestures def SetTextFieldPad(tf, pad=None, clearButtonMode=False, undo_redo_pasteBarButtons=False, textfield_did_change=None): if not pad: pad = [ {'key':'1','x':2,'y':1}, {'key':'2','x':2,'y':2}, {'key':'3','x':2,'y':3}, {'key':'4','x':5,'y':1}, {'key':'5','x':5,'y':2}, {'key':'6','x':5,'y':3}, ] Japanese_Braille = { '1':'あ', '12':'い', '14':'う', '124':'え', '24':'お', '16':'か', '1246':'け' } tfo = ObjCInstance(tf).textField() # UITextField is subview of ui.TextField def key_pressed(key): cursor = tfo.offsetFromPosition_toPosition_(tfo.beginningOfDocument(), tfo.selectedTextRange().start()) if key == 'back space': if cursor > 0: #if tfb.text != '': tf.text = tf.text[:cursor-1] + tf.text[cursor:] cursor = cursor - 1 elif key == 'return': tf.end_editing() return elif key == ' ': ch = ' ' tf.text = tf.text[:cursor] + ch + tf.text[cursor:] cursor = cursor + 1 elif key not in Japanese_Braille: return else: ch = Japanese_Braille[key] tf.text = tf.text[:cursor] + ch + tf.text[cursor:] cursor = cursor + 1 if textfield_did_change: textfield_did_change(tfb) # set cursor cursor_position = tfo.positionFromPosition_offset_(tfo.beginningOfDocument(), cursor) tfo.selectedTextRange = tfo.textRangeFromPosition_toPosition_(cursor_position, cursor_position) def tapped(data): #print('tapped',data.number_of_touches) #print(len(data.recognizer.touches())) bs = [] for t in data.recognizer.touches(): pt = t.locationInView_(ObjCInstance(v)) for b in v.subviews: r = b.width/2 x = b.x + r y = b.y + r if ((pt.x-x)**2+(pt.y-y)**2) <= r**2: # touch in circle of button if b.name not in bs: # avoid two times same button bs.append(b.name) if len(bs) != data.number_of_touches: # at least one touch outside buttons, no way to recognize return seq = '' for b in sorted(bs): seq = seq + b key_pressed(seq) # like IOS left swipe: delete at left def left_swipe_handler(data): key_pressed('back space') # like IOS right swipe: space def right_swipe_handler(data): key_pressed(' ') # like IOS up swipe with 3 fingers: return def up_swipe_handler(data): key_pressed('return') # design your keyboard v = ui.View() v.border_color = 'red' v.border_width = 4 w,h = ui.get_screen_size() h = h - 350 db = w/6 dd = (h-3*db)/4 y_max = 0 for pad_elem in pad: b = ui.Button() b.name = pad_elem['key'] b.background_color = (1,0,0,0.5) b.tint_color = 'red' b.font = ('Academy Engraved LET',36) b.corner_radius = db/2 b.title = b.name x = (pad_elem['x']-1)*db y = dd + (pad_elem['y']-1)*(db+dd) b.frame = (x,y,db,db) b.TextField = tf # store tf as key attribute needed when pressed b.enabled = False v.add_subview(b) y_max = max(y_max,y+db+dd) v.width = ui.get_screen_size()[0] v.height = h g = Gestures() for n in range(1,7): g.add_tap(v, tapped,number_of_touches_required=n) g.add_swipe(v, left_swipe_handler, direction = Gestures.LEFT) g.add_swipe(v, right_swipe_handler, direction = Gestures.RIGHT) g.add_swipe(v, up_swipe_handler, direction = Gestures.UP, number_of_touches_required=3) # view of keyboard retain_global(v) # see https://forum.omz-software.com/topic/4653/button-action-not-called-when-view-is-added-to-native-view tfo.setInputAccessoryView_(ObjCInstance(v)) # attach accessory to textview #print(dir(tfo)) if __name__ == '__main__': import ui tf = ui.TextField() SetTextFieldPad(tf) tf.text = '' tf.width = 200 tf.name = 'Japanese Braille' tf.present('sheet') tf.begin_editing() tf.wait_modal()
-
Version without standard keyboard is Braille_Input.py
Don't forget to swipe with 3 fingers from bottom to top to dismiss the (Braille) keyboard
-
My wife is having trouble using the rotor function, so I've been thinking about a special application.
-
-
@shinya.ta It uses a module that you have to import and copy in your site-packages folder: Gestures
-
@shinya.ta Other version here
-
version without Gestures module (see here-after for the reason)
-
while at least one finger stays on screen, another one may "arrive"
-
move of fingers allowed, not only a tap
-
character only added when all fingers leave the screen
-
speech of added character could be programmed but does not work actually
-
special sound could be played when a finger arrives or leave a circle
-
position of circles could be changed and stored per device and orientation
-
... waiting for your requests
-
-
@shinya.ta The GitHub BrailleInput2.py now supports
- put 6 fingers on the screen and move them to position the circles where you want.
- you may move until all fingers leave the screen
- the positions will be automatically saved in keychain memory of your device, for the current orientation, either portrait, either landscape.
- the saved positions will be reused at next run
That will say that, actually, the character using the 6 dots is not supported. In a close future, I'll try to distinguish between this operation and the 6 dots character.
I'm still waiting for some feedback from you, even very negative if I didn't understand how your wife could use it.
- put 6 fingers on the screen and move them to position the circles where you want.
-
@shinya.ta Six dots character (め) also supported now.
Setting of the circles positions needs to put six fingers on the screen, where you want, during at least 3 seconds.
The six dots character needs 6 fingers in the circles, during less than 3 seconds.Of course, if this way to process is unusable, let me know how to do.
-
Dear.cvp
I tried a new version.
Another problem has come up.
The application cannot be shut down.That's why you can't open any other Pythonisa apps.
What should I do?
-
@shinya.ta As I said previously, you have to swipe 3 fingers up to close the keyboard.
And after, the x button is available to close the script.But, first, use of 3 fingers needs you disable Settings/General/Accessibilty/Zoom.
Edit: if you prefer another gesture, let me know, but this is the standard IOS Braille gesture to simulate a return key, thus dismiss the keyboard.
-
My wife is used to closing buttons.
-
@shinya.ta Yes, but in the Braille keyboard with only 6 circles, where do you want to put a close button, and you want that this button dismisses the keyboard, please confirm!
And, please, don't forget that this script is only a starting point to show what could be done.
You have to do your job also 😀, that will say explain your requests.
My little script creates a code for any TextField. I don't know how or where you want to use this kind of Braille keyboard. -
@shinya.ta Just added a "close keyboard button" in the GitHub version BrailleInput2.py
Don't hesitate to ask any change but don't hope a quick answer today.
Easter Monday is a bank holiday in Belgium and all my children and grandchildren come for the lunch 🍾 -
-
@shinya.ta new version:
- rename module into BrailleKeyboardForTextField.py
- rename some functions and classes
- define all characters in Japanese Braille dictionnary with comment showing dots, like:
'156':'さ', # ⠱ '1256':'し', # ⠳ '1456':'す', # ⠹ '12456':'せ', # ⠻ '2456':'そ', # ⠺
- displaying tapped dots, dots symbol and character outside TextField name
-
@shinya.ta No news, good news?