diff --git a/src/pyj/read_book/gestures.pyj b/src/pyj/read_book/gestures.pyj index 642af79c73..6dd53be9d8 100644 --- a/src/pyj/read_book/gestures.pyj +++ b/src/pyj/read_book/gestures.pyj @@ -32,7 +32,7 @@ def get_action_descriptions(): }, 'highlight_or_inspect': { 'short': _('Highlight or inspect'), - 'long': _('Highlight the word under the tap point or') + 'long': _('Highlight the word under the tap point or view the image under the tap or select the highlight under the tap') }, 'decrease_font_size': { 'short': _('Make text smaller'), @@ -67,14 +67,14 @@ def get_action_descriptions(): only_flow_swipe_mode_actions = {'pan': True, 'animated_scroll': True} only_tap_actions = {'highlight_or_inspect': True} - default_actions_for_gesture = { 'common': { GESTURE.back_zone_tap: 'prev_page', GESTURE.forward_zone_tap: 'next_page', GESTURE.control_zone_tap: 'show_chrome', - GESTURE.two_finger_tap: 'show_chrome', GESTURE.long_tap: 'highlight_or_inspect', + + GESTURE.two_finger_tap: 'show_chrome', GESTURE.pinch_in: 'decrease_font_size', GESTURE.pinch_out: 'increase_font_size', }, @@ -98,15 +98,30 @@ default_actions_for_gesture = { }, } -def action_for_gesture(gesture, in_flow_mode): - overrides = opts.gesture_overrides +def current_action_for_gesture_type(overrides, gesture_type, in_flow_mode): mode = 'flow_mode' if in_flow_mode else 'paged_mode' mode_overrides = overrides[mode] or {} - if mode_overrides[gesture.type]: - return mode_overrides[gesture.type] + if mode_overrides[gesture_type]: + return mode_overrides[gesture_type] common_overrides = overrides.common or {} - if common_overrides[gesture.type]: - return common_overrides[gesture.type] - if default_actions_for_gesture[mode][gesture.type]: - return default_actions_for_gesture[mode][gesture.type] - return default_actions_for_gesture.common[gesture.type] or 'none' + if common_overrides[gesture_type]: + return common_overrides[gesture_type] + if default_actions_for_gesture[mode][gesture_type]: + return default_actions_for_gesture[mode][gesture_type] + return default_actions_for_gesture.common[gesture_type] or 'none' + +def action_for_gesture(gesture, in_flow_mode): + return current_action_for_gesture_type(opts.gesture_overrides, gesture.type, in_flow_mode) + +def allowed_actions_for_tap(): + return [ac for ac in Object.keys(get_action_descriptions()) if not only_flow_swipe_mode_actions[ac]] + +def allowed_actions_for_paged_mode_swipe(): + return [ac for ac in Object.keys(get_action_descriptions()) if not only_flow_swipe_mode_actions[ac] and not only_tap_actions[ac]] +allowed_actions_for_two_fingers = allowed_actions_for_paged_mode_swipe + +def allowed_actions_for_flow_mode_flick(): + return [ac for ac in Object.keys(get_action_descriptions()) if not only_tap_actions[ac]] + +def allowed_actions_for_flow_mode_drag(): + return ['pan', 'none'] diff --git a/src/pyj/read_book/prefs/main.pyj b/src/pyj/read_book/prefs/main.pyj index dd2947eab3..0f297f3283 100644 --- a/src/pyj/read_book/prefs/main.pyj +++ b/src/pyj/read_book/prefs/main.pyj @@ -17,6 +17,7 @@ from read_book.prefs.layout import commit_layout, create_layout_panel from read_book.prefs.misc import commit_misc, create_misc_panel from read_book.prefs.scrolling import commit_scrolling, create_scrolling_panel from read_book.prefs.selection import commit_selection, create_selection_panel +from read_book.prefs.touch import commit_touch, create_touch_panel from read_book.prefs.user_stylesheet import ( commit_user_stylesheet, create_user_stylesheet_panel ) @@ -106,6 +107,7 @@ class Prefs: ci(_('Headers and footers'), 'head_foot', _('Customize the headers and footers')) ci(_('Scrolling behavior'), 'scrolling', _('Control how the viewer scrolls')) ci(_('Selection behavior'), 'selection', _('Control how the viewer selects text')) + ci(_('Touch behavior'), 'touch', _('Customize what various touchscreen gestures do')) ci(_('Keyboard shortcuts'), 'keyboard', _('Customize the keyboard shortcuts')) if runtime.is_standalone_viewer: ci(_('Fonts'), 'fonts', _('Font choices')) @@ -166,6 +168,13 @@ class Prefs: def close_selection(self): commit_selection(self.onchange, self.container) + def display_touch(self, container): + self.create_panel(container, 'touch', create_touch_panel) + + def close_touch(self): + commit_touch(self.onchange, self.container) + + def create_prefs_panel(container, close_func, on_change): return Prefs(container, close_func, on_change) diff --git a/src/pyj/read_book/prefs/touch.pyj b/src/pyj/read_book/prefs/touch.pyj new file mode 100644 index 0000000000..61a3e8f7c0 --- /dev/null +++ b/src/pyj/read_book/prefs/touch.pyj @@ -0,0 +1,170 @@ +# vim:fileencoding=utf-8 +# License: GPL v3 Copyright: 2016, Kovid Goyal +from __python__ import bound_methods, hash_literals + +from elementmaker import E + +from book_list.globals import get_session_data +from dom import unique_id +from gettext import gettext as _ +from read_book.gestures import ( + allowed_actions_for_flow_mode_drag, allowed_actions_for_flow_mode_flick, + allowed_actions_for_paged_mode_swipe, allowed_actions_for_tap, + allowed_actions_for_two_fingers, current_action_for_gesture_type, + get_action_descriptions +) +from read_book.prefs.utils import create_button_box +from read_book.touch import GESTURE, GESTURE_NAMES + +CONTAINER = unique_id('touch-settings') + +def restore_defaults(): + apply_settings_to_ui({}) + +def get_container(): + return document.getElementById(CONTAINER) + + +def apply_settings_to_ui(overrides): + overrides = overrides or {} + for group in get_container().querySelectorAll('[data-group]'): + group_name = group.dataset.group + in_flow_mode = group_name.indexOf('flow') >= 0 + for select in group.querySelectorAll('select'): + allowed_actions = v'[]' + for option in select.querySelectorAll('option'): + allowed_actions.push(option.value) + gesture_type = select.name + current_action = current_action_for_gesture_type(overrides, gesture_type, in_flow_mode) + if allowed_actions.indexOf(current_action) < 0: + current_action = current_action_for_gesture_type({}, gesture_type, in_flow_mode) + if not current_action or allowed_actions.indexOf(current_action) < 0: + current_action = 'none' + select.value = current_action + +def get_overrides_from_ui(): + ans = {} + for group in get_container().querySelectorAll('[data-group]'): + group_name = group.dataset.group + in_flow_mode = group_name.indexOf('flow') >= 0 + if group_name is 'paged_swipe': + attr = 'paged_mode' + elif group_name is 'flow_swipe': + attr = 'flow_mode' + else: + attr = 'common' + if not ans[attr]: + ans[attr] = {} + for select in group.querySelectorAll('select'): + val = select.value + defval = current_action_for_gesture_type({}, select.name, in_flow_mode) + if val is not defval: + ans[attr][select.name] = val + for which in Object.keys(ans): + if Object.keys(ans[which]).length is 0: + v'delete ans[which]' + return ans + + +def create_touch_panel(container, apply_func, cancel_func): + container.appendChild(E.div(id=CONTAINER, style='margin: 1rem')) + container = container.lastChild + sd = get_session_data() + overrides = sd.get('gesture_overrides') + action_descriptions = get_action_descriptions() + in_flow_mode = False + + def on_select_change(ev): + select = ev.target + ad = action_descriptions[select.value] + span = select.parentNode.querySelector('span') + span.textContent = ad.long + + def make_setting(gesture_type, allowed_actions): + ans = E.div(style='margin-top: 1ex') + title = GESTURE_NAMES[gesture_type] + sid = unique_id(gesture_type) + ans.appendChild(E.h4(E.label(title, 'for'=sid))) + select = E.select(name=gesture_type, id=sid) + for action in allowed_actions: + ad = action_descriptions[action] + select.appendChild(E.option(ad.short, value=action)) + select.addEventListener('change', on_select_change) + ans.appendChild(E.div(select, '\xa0', E.span(style='font-size: smaller; font-style: italic'))) + on_select_change({'target': select}) + return ans + + container.appendChild(E.h2(_('Tapping'))) + container.appendChild(E.div(_( + 'There are three tap zones, depending on where on the screen you tap. When the tap is' + ' on a link, the link is followed, otherwise a configurable action based on the zone is performed.'))) + c = E.div('data-group'='tap') + container.appendChild(c) + aat = allowed_actions_for_tap() + c.appendChild(make_setting(GESTURE.control_zone_tap, aat)) + c.appendChild(make_setting(GESTURE.forward_zone_tap, aat)) + c.appendChild(make_setting(GESTURE.back_zone_tap, aat)) + c.appendChild(make_setting(GESTURE.long_tap, aat)) + container.appendChild(E.hr()) + + container.appendChild(E.h2(_('Two finger gestures'))) + c = E.div('data-group'='two_finger') + container.appendChild(c) + aat = allowed_actions_for_two_fingers() + c.appendChild(make_setting(GESTURE.two_finger_tap, aat)) + c.appendChild(make_setting(GESTURE.pinch_in, aat)) + c.appendChild(make_setting(GESTURE.pinch_out, aat)) + container.appendChild(E.hr()) + + + container.appendChild(E.h2(_('Swiping'))) + container.appendChild(E.div(_( + 'Swiping works differently in paged and flow mode, with different actions. For an English like language, swiping in' + ' the writing direction means swiping horizontally. For languages written vertically, it means swiping vertically.' + ' For languages written left-to-right "going forward" means swiping right-to-left, like turning a page with your finger.' + ))) + container.appendChild(E.h3(_('Swiping in paged mode'), style='padding-top: 1ex')) + c = E.div('data-group'='paged_swipe') + container.appendChild(c) + aap = allowed_actions_for_paged_mode_swipe() + c.appendChild(make_setting(GESTURE.flick_block_forward, aap)) + c.appendChild(make_setting(GESTURE.flick_block_backward, aap)) + c.appendChild(make_setting(GESTURE.flick_inline_forward, aap)) + c.appendChild(make_setting(GESTURE.flick_inline_backward, aap)) + c.appendChild(make_setting(GESTURE.swipe_inline_forward_hold, aap)) + c.appendChild(make_setting(GESTURE.swipe_inline_backward_hold, aap)) + c.appendChild(make_setting(GESTURE.swipe_block_forward_hold, aap)) + c.appendChild(make_setting(GESTURE.swipe_block_backward_hold, aap)) + container.appendChild(E.hr()) + container.appendChild(E.h3(_('Swiping in flow mode'), style='padding-top: 1ex')) + c = E.div('data-group'='flow_swipe') + container.appendChild(c) + in_flow_mode = True + in_flow_mode + aaf = allowed_actions_for_flow_mode_flick() + c.appendChild(make_setting(GESTURE.flick_block_forward, aaf)) + c.appendChild(make_setting(GESTURE.flick_block_backward, aaf)) + c.appendChild(make_setting(GESTURE.flick_inline_forward, aaf)) + c.appendChild(make_setting(GESTURE.flick_inline_backward, aaf)) + aaf = allowed_actions_for_flow_mode_drag() + c.appendChild(make_setting(GESTURE.swipe_inline_backward_in_progress, aaf)) + c.appendChild(make_setting(GESTURE.swipe_inline_forward_in_progress, aaf)) + c.appendChild(make_setting(GESTURE.swipe_block_backward_in_progress, aaf)) + c.appendChild(make_setting(GESTURE.swipe_block_forward_in_progress, aaf)) + + container.appendChild(E.hr()) + container.appendChild(create_button_box(restore_defaults, apply_func, cancel_func)) + apply_settings_to_ui(overrides) + + +develop = create_touch_panel + + +def commit_touch(onchange): + sd = get_session_data() + current_overrides = sd.get('gesture_overrides') + overrides = get_overrides_from_ui() + changed = overrides != current_overrides + if changed: + sd.set('gesture_overrides', overrides) + onchange() diff --git a/src/pyj/read_book/touch.pyj b/src/pyj/read_book/touch.pyj index 9c968931a2..a2dd1fd027 100644 --- a/src/pyj/read_book/touch.pyj +++ b/src/pyj/read_book/touch.pyj @@ -21,18 +21,20 @@ GESTURE_NAMES = { 'pinch_in': _('Pinch in'), 'pinch_out': _('Pinch out'), - 'flick_inline_backward': _('Flick in writing direction, backwards'), - 'flick_inline_forward': _('Flick in writing direction, forwards'), - 'flick_block_backward': _('Flick perpendicular to writing direction, backwards'), - 'flick_block_forward': _('Flick perpendicular to writing direction, forwards'), - 'swipe_inline_backward_in_progress': _('Swipe in writing direction, backwards, in-progress'), - 'swipe_inline_forward_in_progress': _('Swipe in writing direction, forwards, in-progress'), - 'swipe_block_backward_in_progress': _('Swipe perpendicular to writing direction, backwards, in-progress'), - 'swipe_block_forward_in_progress': _('Swipe perpendicular to writing direction, forwards, in-progress'), - 'swipe_inline_backward_hold': _('Swipe in writing direction, backwards and hold'), - 'swipe_inline_forward_hold': _('Swipe in writing direction, forwards and hold'), - 'swipe_block_backward_hold': _('Swipe perpendicular to writing direction, backwards and hold'), - 'swipe_block_forward_hold': _('Swipe perpendicular to writing direction, forwards and hold'), + 'flick_inline_backward': _('Flick in writing direction, to go back'), + 'flick_inline_forward': _('Flick in writing direction, to go forward'), + 'flick_block_backward': _('Flick perpendicular to writing direction, to go forward'), + 'flick_block_forward': _('Flick perpendicular to writing direction, to go back'), + + 'swipe_inline_backward_in_progress': _('Drag finger in writing direction, to go back'), + 'swipe_inline_forward_in_progress': _('Drag finger in writing direction, to go forward'), + 'swipe_block_backward_in_progress': _('Drag finger perpendicular to writing direction, to go back'), + 'swipe_block_forward_in_progress': _('Drag finger perpendicular to writing direction, to go forward'), + + 'swipe_inline_backward_hold': _('Drag and hold finger in writing direction, to go back'), + 'swipe_inline_forward_hold': _('Drag and hold finger in writing direction, to go forward'), + 'swipe_block_backward_hold': _('Drag and hold finger perpendicular to writing direction, to go back'), + 'swipe_block_forward_hold': _('Drag and hold finger perpendicular to writing direction, to go forward'), } GESTURE = {k:k for k in Object.keys(GESTURE_NAMES)} GESTURE.tap = 'tap'