/TalkBack/src/com/google/android/marvin/talkback/ProcessorScrollPosition.java

http://eyes-free.googlecode.com/ · Java · 127 lines · 71 code · 22 blank · 34 comment · 10 complexity · de31af636d089e63f48cd2cb25ca1872 MD5 · raw file

  1. /*
  2. * Copyright (C) 2011 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.google.android.marvin.talkback;
  17. import android.content.Context;
  18. import android.os.Handler;
  19. import android.os.Message;
  20. import android.speech.tts.TextToSpeech;
  21. import android.text.TextUtils;
  22. import android.view.accessibility.AccessibilityEvent;
  23. import com.google.android.marvin.talkback.TalkBackService.EventProcessor;
  24. class ProcessorScrollPosition implements EventProcessor {
  25. private final Context mContext;
  26. private final SpeechController mSpeechController;
  27. private final ScrollPositionHandler mHandler;
  28. public ProcessorScrollPosition(Context context, SpeechController speechController) {
  29. mContext = context;
  30. mSpeechController = speechController;
  31. mHandler = new ScrollPositionHandler();
  32. }
  33. @Override
  34. public void process(AccessibilityEvent event) {
  35. final int eventType = event.getEventType();
  36. mHandler.cancelScrollTimeout();
  37. if (eventType != AccessibilityEvent.TYPE_VIEW_SCROLLED) {
  38. return;
  39. }
  40. final CharSequence text = Utils.getEventText(mContext, event);
  41. if (!TextUtils.isEmpty(text)) {
  42. return;
  43. }
  44. mHandler.startScrollTimeout(event);
  45. }
  46. /**
  47. * Given an {@link AccessibilityEvent}, speaks a scroll position.
  48. *
  49. * @param event The source event.
  50. */
  51. private void handleScrollTimeout(AccessibilityEvent event) {
  52. final int fromIndex = event.getFromIndex() + 1;
  53. final int toIndex = event.getToIndex() + 1;
  54. final int itemCount = event.getItemCount();
  55. // If the from index or the item count are invalid, don't announce
  56. // anything.
  57. if (fromIndex < 0 || itemCount < 0) {
  58. return;
  59. }
  60. final String text;
  61. // If the from and to indices are the same, or if the to index is
  62. // invalid, only announce the item at the from index. Otherwise,
  63. // announce the range of visible items.
  64. if ((fromIndex == toIndex) || toIndex < 0) {
  65. text = mContext.getString(R.string.template_scroll_from_count, fromIndex, itemCount);
  66. } else {
  67. text =
  68. mContext.getString(R.string.template_scroll_from_to_count, fromIndex, toIndex,
  69. itemCount);
  70. }
  71. mSpeechController.cleanUpAndSpeak(text, TextToSpeech.QUEUE_FLUSH);
  72. }
  73. private class ScrollPositionHandler extends Handler {
  74. /** Message identifier for a scroll position notification. */
  75. private static final int SCROLL_TIMEOUT = 1;
  76. /** Timeout before reading a scroll position notification. */
  77. private static final long DELAY_SCROLL_TIMEOUT = 1000;
  78. @Override
  79. public void handleMessage(Message msg) {
  80. switch (msg.what) {
  81. case SCROLL_TIMEOUT: {
  82. final AccessibilityEvent event = (AccessibilityEvent) msg.obj;
  83. handleScrollTimeout(event);
  84. event.recycle();
  85. break;
  86. }
  87. }
  88. }
  89. /**
  90. * Starts the scroll position timeout. Call this for every VIEW_SCROLLED
  91. * event.
  92. */
  93. private void startScrollTimeout(AccessibilityEvent event) {
  94. final AccessibilityEvent eventClone = AccessibilityEvent.obtain(event);
  95. final Message msg = obtainMessage(SCROLL_TIMEOUT, eventClone);
  96. sendMessageDelayed(msg, DELAY_SCROLL_TIMEOUT);
  97. }
  98. /**
  99. * Removes the scroll position timeout. Call this for every event.
  100. */
  101. private void cancelScrollTimeout() {
  102. removeMessages(SCROLL_TIMEOUT);
  103. }
  104. }
  105. }