Merge remote-tracking branch 'poretsky/accessibility-proposals'

Conflicts:
	OsmAnd/res/layout/tips_and_tricks.xml
This commit is contained in:
Pavol Zibrita 2012-04-27 03:24:58 +02:00
parent efcf8c4c72
commit 399c5f0a7d
34 changed files with 610 additions and 335 deletions

View file

@ -1,84 +1,84 @@
:- op('==', xfy, 500).
version(101).
language(zh).
% before each announcement (beep)
preamble - [].
%% TURNS
turn('left', ['左轉 ']).
turn('left_sh', ['向左急轉 ']).
turn('left_sl', ['稍向左轉 ']).
turn('right', ['右轉 ']).
turn('right_sh', ['向右急轉 ']).
turn('right_sl', ['稍向右轉 ']).
prepare_turn(Turn, Dist) == ['請準備 ', D, ' 後 ', M] :- distance(Dist) == D, turn(Turn, M).
turn(Turn, Dist) == [D, ' 後 ',M] :- distance(Dist) == D, turn(Turn, M).
turn(Turn) == M :- turn(Turn, M).
prepare_make_ut(Dist) == ['請準備', D, ' 後迴轉 '] :- distance(Dist) == D.
make_ut(Dist) == [D, ' 後請迴轉'] :- distance(Dist) == D.
make_ut == ['請迴轉 '].
make_ut_wp == ['可能的話, 請迴轉 '].
prepare_roundabout(Dist) == ['請準備', D,' 後進入圓環 '] :- distance(Dist) == D.
roundabout(Dist, _Angle, Exit) == [D, ' 後進入圓環, 然後在 ', E, ' 出口離開'] :- distance(Dist) == D, nth(Exit, E).
roundabout(_Angle, Exit) == ['在 ', E, ' 出口離開'] :- nth(Exit, E).
go_ahead == ['直直往前開 '].
go_ahead(Dist) == ['沿著馬路往前 ', D]:- distance(Dist) == D.
and_arrive_destination == ['然後可達終點 '].
then == ['然後 '].
reached_destination == ['抵達終點 '].
bear_right == ['靠右 '].
bear_left == ['靠左 '].
route_new_calc(Dist) == ['路程有 ', D, ' 遠'] :- distance(Dist) == D.
route_recalc(Dist) == ['重新計算路程, 距離有 ', D] :- distance(Dist) == D.
location_lost == ['接收不到 g p s 信號 '].
%%
nth(1, '第一個 ').
nth(2, '第二個 ').
nth(3, '第三個 ').
nth(4, '第四個 ').
nth(5, '第五個 ').
nth(6, '第六個 ').
nth(7, '第七個 ').
nth(8, '第八個 ').
nth(9, '第九個 ').
nth(10, '第十個 ').
nth(11, '第十一個 ').
nth(12, '第十二個 ').
nth(13, '第十三個 ').
nth(14, '第十四個 ').
nth(15, '第十五個 ').
nth(16, '第十六個 ').
nth(17, '第十七個 ').
%%% distance measure
distance(Dist) == [ X, ' 公尺'] :- Dist < 100, D is round(Dist/10)*10, num_atom(D, X).
distance(Dist) == [ X, ' 公尺'] :- Dist < 1000, D is round(2*Dist/100)*50, num_atom(D, X).
distance(Dist) == ['約 1 公里 '] :- Dist < 1500.
distance(Dist) == ['約 ', X, ' 公里 '] :- Dist < 10000, D is round(Dist/1000), num_atom(D, X).
distance(Dist) == [ X, ' 公里 '] :- D is round(Dist/1000), num_atom(D, X).
%% resolve command main method
%% if you are familar with Prolog you can input specific to the whole mechanism,
%% by adding exception cases.
flatten(X, Y) :- flatten(X, [], Y), !.
flatten([], Acc, Acc).
flatten([X|Y], Acc, Res):- flatten(Y, Acc, R), flatten(X, R, Res).
flatten(X, Acc, [X|Acc]).
resolve(X, Y) :- resolve_impl(X,Z), flatten(Z, Y).
resolve_impl([],[]).
:- op('==', xfy, 500).
version(101).
language(zh).
% before each announcement (beep)
preamble - [].
%% TURNS
turn('left', ['左轉 ']).
turn('left_sh', ['向左急轉 ']).
turn('left_sl', ['稍向左轉 ']).
turn('right', ['右轉 ']).
turn('right_sh', ['向右急轉 ']).
turn('right_sl', ['稍向右轉 ']).
prepare_turn(Turn, Dist) == ['請準備 ', D, ' 後 ', M] :- distance(Dist) == D, turn(Turn, M).
turn(Turn, Dist) == [D, ' 後 ',M] :- distance(Dist) == D, turn(Turn, M).
turn(Turn) == M :- turn(Turn, M).
prepare_make_ut(Dist) == ['請準備', D, ' 後迴轉 '] :- distance(Dist) == D.
make_ut(Dist) == [D, ' 後請迴轉'] :- distance(Dist) == D.
make_ut == ['請迴轉 '].
make_ut_wp == ['可能的話, 請迴轉 '].
prepare_roundabout(Dist) == ['請準備', D,' 後進入圓環 '] :- distance(Dist) == D.
roundabout(Dist, _Angle, Exit) == [D, ' 後進入圓環, 然後在 ', E, ' 出口離開'] :- distance(Dist) == D, nth(Exit, E).
roundabout(_Angle, Exit) == ['在 ', E, ' 出口離開'] :- nth(Exit, E).
go_ahead == ['直直往前開 '].
go_ahead(Dist) == ['沿著馬路往前 ', D]:- distance(Dist) == D.
and_arrive_destination == ['然後可達終點 '].
then == ['然後 '].
reached_destination == ['抵達終點 '].
bear_right == ['靠右 '].
bear_left == ['靠左 '].
route_new_calc(Dist) == ['路程有 ', D, ' 遠'] :- distance(Dist) == D.
route_recalc(Dist) == ['重新計算路程, 距離有 ', D] :- distance(Dist) == D.
location_lost == ['接收不到 g p s 信號 '].
%%
nth(1, '第一個 ').
nth(2, '第二個 ').
nth(3, '第三個 ').
nth(4, '第四個 ').
nth(5, '第五個 ').
nth(6, '第六個 ').
nth(7, '第七個 ').
nth(8, '第八個 ').
nth(9, '第九個 ').
nth(10, '第十個 ').
nth(11, '第十一個 ').
nth(12, '第十二個 ').
nth(13, '第十三個 ').
nth(14, '第十四個 ').
nth(15, '第十五個 ').
nth(16, '第十六個 ').
nth(17, '第十七個 ').
%%% distance measure
distance(Dist) == [ X, ' 公尺'] :- Dist < 100, D is round(Dist/10)*10, num_atom(D, X).
distance(Dist) == [ X, ' 公尺'] :- Dist < 1000, D is round(2*Dist/100)*50, num_atom(D, X).
distance(Dist) == ['約 1 公里 '] :- Dist < 1500.
distance(Dist) == ['約 ', X, ' 公里 '] :- Dist < 10000, D is round(Dist/1000), num_atom(D, X).
distance(Dist) == [ X, ' 公里 '] :- D is round(Dist/1000), num_atom(D, X).
%% resolve command main method
%% if you are familar with Prolog you can input specific to the whole mechanism,
%% by adding exception cases.
flatten(X, Y) :- flatten(X, [], Y), !.
flatten([], Acc, Acc).
flatten([X|Y], Acc, Res):- flatten(Y, Acc, R), flatten(X, R, Res).
flatten(X, Acc, [X|Acc]).
resolve(X, Y) :- resolve_impl(X,Z), flatten(Z, Y).
resolve_impl([],[]).
resolve_impl([X|Rest], List) :- resolve_impl(Rest, Tail), ((X == L) -> append(L, Tail, List); List = Tail).

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<net.osmand.access.AccessibleLayout xmlns:android="http://schemas.android.com/apk/res/android"
class="net.osmand.access.AccessibleLayout"
android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/background">
<LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical">
<LinearLayout android:layout_height="wrap_content" android:layout_width="fill_parent" android:gravity="center_horizontal">
@ -86,4 +87,4 @@ android:layout_width="fill_parent" android:layout_height="fill_parent" android:b
</TableRow>
</TableLayout>
</LinearLayout>
</FrameLayout>
</net.osmand.access.AccessibleLayout>

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<net.osmand.access.AccessibleLayout xmlns:android="http://schemas.android.com/apk/res/android"
class="net.osmand.access.AccessibleLayout"
android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/background">
<LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical">
<LinearLayout android:layout_height="wrap_content" android:layout_width="fill_parent" android:gravity="center_horizontal">
@ -89,4 +90,4 @@ android:layout_width="fill_parent" android:layout_height="fill_parent" android:b
</TableRow>
</TableLayout>
</LinearLayout>
</FrameLayout>
</net.osmand.access.AccessibleLayout>

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<net.osmand.access.AccessibleLayout xmlns:android="http://schemas.android.com/apk/res/android"
class="net.osmand.access.AccessibleLayout"
android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/background">
<LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical">
<LinearLayout android:layout_height="wrap_content" android:layout_width="fill_parent" android:gravity="center_horizontal">
@ -77,4 +78,4 @@ android:layout_width="fill_parent" android:layout_height="fill_parent" android:b
</TableRow>
</TableLayout>
</LinearLayout>
</FrameLayout>
</net.osmand.access.AccessibleLayout>

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<net.osmand.access.AccessibleLayout xmlns:android="http://schemas.android.com/apk/res/android"
class="net.osmand.access.AccessibleLayout"
android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/background">
<LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical">
<LinearLayout android:layout_height="wrap_content" android:layout_width="fill_parent" android:gravity="center_horizontal">
@ -77,4 +78,4 @@ android:layout_width="fill_parent" android:layout_height="fill_parent" android:b
</TableRow>
</TableLayout>
</LinearLayout>
</FrameLayout>
</net.osmand.access.AccessibleLayout>

View file

@ -2,7 +2,7 @@
<LinearLayout android:layout_width="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent" android:orientation="vertical" android:background="@color/color_light_gray">
<TextView android:text="" android:id="@+id/TipDescription" android:layout_marginLeft="4dp" android:scrollbars="vertical"
<net.osmand.access.ExplorableTextView android:text="" android:id="@+id/TipDescription" android:layout_marginLeft="4dp" android:scrollbars="vertical"
android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_marginRight="4dp" android:layout_weight="1"
android:textColor="@color/color_black" android:textSize="18sp" android:gravity="fill_horizontal"
android:background= "@drawable/textlines" />

View file

@ -478,7 +478,7 @@
<string name="background_service_provider">Источник позиционирования</string>
<string name="background_router_service_descr">Включить фоновый сервис для обновления через долгий период времени</string>
<string name="background_router_service">Сервис навигации</string>
<string name="off_router_service_no_gps_available">Сервис маршрутизации OsmAnd включен, отключив позиционирование, он перестает вести по маршруту.</string>
<string name="off_router_service_no_gps_available">Сервис маршрутизации OsmAnd включен, если отключить позиционирование, он перестанет вести по маршруту.</string>
<string name="routing_settings_descr">Изменить настройки навигации</string>
<string name="routing_settings">- Навигация</string>
<string name="hide_poi_filter">Скрыть фильтр</string>

View file

@ -131,10 +131,14 @@
</PreferenceScreen>
<PreferenceScreen android:key="accessibility_preferences" android:title="@string/accessibility_preferences" android:summary="@string/accessibility_preferences_descr">
<ListPreference android:summary="@string/settings_direction_style_descr" android:title="@string/settings_direction_style" android:key="direction_style"></ListPreference>
<CheckBoxPreference android:key="zoom_by_trackball" android:title="@string/zoom_by_trackball" android:summary="@string/zoom_by_trackball_descr"></CheckBoxPreference>
<CheckBoxPreference android:key="scroll_map_by_gestures" android:title="@string/scroll_map_by_gestures" android:summary="@string/scroll_map_by_gestures_descr"></CheckBoxPreference>
<CheckBoxPreference android:key="use_short_object_names" android:title="@string/use_short_object_names" android:summary="@string/use_short_object_names_descr"></CheckBoxPreference>
<ListPreference android:summary="@string/accessibility_mode_descr" android:title="@string/accessibility_mode" android:key="accessibility_mode"></ListPreference>
<PreferenceCategory android:key="accessibility_options">
<ListPreference android:summary="@string/settings_direction_style_descr" android:title="@string/settings_direction_style" android:key="direction_style"></ListPreference>
<CheckBoxPreference android:key="zoom_by_trackball" android:title="@string/zoom_by_trackball" android:summary="@string/zoom_by_trackball_descr"></CheckBoxPreference>
<CheckBoxPreference android:key="scroll_map_by_gestures" android:title="@string/scroll_map_by_gestures" android:summary="@string/scroll_map_by_gestures_descr"></CheckBoxPreference>
<CheckBoxPreference android:key="use_short_object_names" android:title="@string/use_short_object_names" android:summary="@string/use_short_object_names_descr"></CheckBoxPreference>
<CheckBoxPreference android:key="accessibility_extensions" android:title="@string/accessibility_extensions" android:summary="@string/accessibility_extensions_descr"></CheckBoxPreference>
</PreferenceCategory>
</PreferenceScreen>
<Preference android:title="@string/support_new_features" android:key="bidforfix">

View file

@ -1,5 +1,7 @@
package net.osmand.access;
import net.osmand.access.AccessibleLayout;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;

View file

@ -0,0 +1,22 @@
package net.osmand.access;
import net.osmand.plus.R;
import android.content.Context;
public enum AccessibilityMode {
ON(R.string.accessibility_on),
OFF(R.string.accessibility_off),
DEFAULT(R.string.accessibility_default);
private final int key;
AccessibilityMode(int key) {
this.key = key;
}
public String toHumanString(Context ctx) {
return ctx.getResources().getString(key);
}
}

View file

@ -1,8 +1,9 @@
package net.osmand.access;
import net.osmand.access.AccessibleContent;
import android.app.Activity;
import android.view.MotionEvent;
import android.view.View;
// Provide some additional accessibility means for activity view elements.
//
@ -16,22 +17,6 @@ public class AccessibleActivity extends Activity implements AccessibleContent.Ca
// to add element to it.
public final AccessibleContent accessibleContent = new AccessibleContent();
// Below are two helper methods to improve AlertDialog accessibility.
//
// Since usual message in an AlertDialog that is set by
// AlertDialog.Builder.setMessage() is spoken only once at the best case
// and there is no way to repeat it, use following two methods
// to wrap it into a View and set it by AlertDialog.Builder.setView().
// Such message will be focusable and so it can be repeated by selecting.
public View accessibleMessage(CharSequence msg) {
return TextMessage.makeView(this, msg);
}
public View accessibleMessage(int msgid) {
return TextMessage.makeView(this, msgid);
}
@Override
public boolean dispatchNativeTouchEvent(MotionEvent event) {
return super.dispatchTouchEvent(event);

View file

@ -0,0 +1,51 @@
package net.osmand.access;
import net.osmand.access.TextMessage;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import android.app.AlertDialog.Builder;
import android.content.Context;
// Since usual message in an AlertDialog that is set by
// AlertDialog.Builder.setMessage() is spoken only once
// at the best case and there is no way to explore or even repeat it,
// this class provides more accessible alternative
// that wraps the message into a dedicated view.
// Such message will be focusable and so it can be repeated
// by selecting.
//
// Note: when accessibility extensions option is not checked
// or system accessibility service is turned off this class
// acts just identical to it's direct parent.
//
public class AccessibleAlertBuilder extends Builder {
// The method getContext() is only available
// starting from API level 11, so store it here.
private final Context context;
// Conventional constructor.
public AccessibleAlertBuilder(Context context) {
super(context);
this.context = context;
}
// Provided setMessage() alternatives.
@Override
public Builder setMessage(CharSequence msg) {
if (OsmandApplication.getSettings().ACCESSIBILITY_EXTENSIONS.get())
return setView(TextMessage.makeView(context, msg, R.layout.alert));
return super.setMessage(msg);
}
@Override
public Builder setMessage(int msgid) {
if (OsmandApplication.getSettings().ACCESSIBILITY_EXTENSIONS.get())
return setView(TextMessage.makeView(context, msgid, R.layout.alert));
return super.setMessage(msgid);
}
}

View file

@ -2,6 +2,8 @@ package net.osmand.access;
import java.util.ArrayList;
import net.osmand.plus.OsmandApplication;
import android.graphics.Rect;
import android.os.SystemClock;
import android.view.MotionEvent;
@ -19,7 +21,7 @@ import android.view.accessibility.AccessibilityEvent;
//
public class AccessibleContent extends ArrayList<View> {
public interface Callback {
protected interface Callback {
public boolean dispatchNativeTouchEvent(MotionEvent event);
}
@ -36,39 +38,41 @@ public class AccessibleContent extends ArrayList<View> {
}
public boolean dispatchTouchEvent(MotionEvent event, Callback callback) {
int action = event.getAction();
View newTouch;
switch (action) {
case MotionEvent.ACTION_MOVE:
newTouch = findTouch(event);
if ((newTouch != null) && (newTouch != nowTouched)) {
float x = event.getX();
float y = event.getY();
float pressure = event.getPressure();
float size = event.getSize();
int metaState = event.getMetaState();
float xPrecision = event.getXPrecision();
float yPrecision = event.getYPrecision();
int deviceId = event.getDeviceId();
int edgeFlags = event.getEdgeFlags();
event.setAction(MotionEvent.ACTION_CANCEL);
callback.dispatchNativeTouchEvent(event);
newTouch.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
long now = SystemClock.uptimeMillis();
event.recycle();
event = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, x, y, pressure, size,
metaState, xPrecision, yPrecision, deviceId, edgeFlags);
if (OsmandApplication.getSettings().ACCESSIBILITY_EXTENSIONS.get()) {
int action = event.getAction();
View newTouch;
switch (action) {
case MotionEvent.ACTION_MOVE:
newTouch = findTouch(event);
if ((newTouch != null) && (newTouch != nowTouched)) {
float x = event.getX();
float y = event.getY();
float pressure = event.getPressure();
float size = event.getSize();
int metaState = event.getMetaState();
float xPrecision = event.getXPrecision();
float yPrecision = event.getYPrecision();
int deviceId = event.getDeviceId();
int edgeFlags = event.getEdgeFlags();
event.setAction(MotionEvent.ACTION_CANCEL);
callback.dispatchNativeTouchEvent(event);
newTouch.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
long now = SystemClock.uptimeMillis();
event.recycle();
event = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, x, y, pressure, size,
metaState, xPrecision, yPrecision, deviceId, edgeFlags);
}
nowTouched = newTouch;
break;
case MotionEvent.ACTION_DOWN:
nowTouched = findTouch(event);
if (nowTouched != null)
nowTouched.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
break;
default:
nowTouched = null;
break;
}
nowTouched = newTouch;
break;
case MotionEvent.ACTION_DOWN:
nowTouched = findTouch(event);
if (nowTouched != null)
nowTouched.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
break;
default:
nowTouched = null;
break;
}
return callback.dispatchNativeTouchEvent(event);
}

View file

@ -1,5 +1,7 @@
package net.osmand.access;
import net.osmand.plus.OsmandApplication;
import android.content.Context;
import android.graphics.Rect;
import android.os.SystemClock;
@ -72,44 +74,46 @@ public class AccessibleLayout extends FrameLayout {
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
int action = event.getAction();
View newTouch;
switch (action) {
case MotionEvent.ACTION_MOVE:
newTouch = findTouch(event);
if ((newTouch != null) && (newTouch != nowTouched)) {
if (newTouch.isClickable()) {
float x = event.getX();
float y = event.getY();
float pressure = event.getPressure();
float size = event.getSize();
int metaState = event.getMetaState();
float xPrecision = event.getXPrecision();
float yPrecision = event.getYPrecision();
int deviceId = event.getDeviceId();
int edgeFlags = event.getEdgeFlags();
event.setAction(MotionEvent.ACTION_CANCEL);
super.dispatchTouchEvent(event);
long now = SystemClock.uptimeMillis();
event.recycle();
event = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, x, y, pressure, size,
metaState, xPrecision, yPrecision, deviceId, edgeFlags);
final boolean swallow = OsmandApplication.getSettings().ACCESSIBILITY_EXTENSIONS.get();
if (swallow) {
int action = event.getAction();
View newTouch;
switch (action) {
case MotionEvent.ACTION_MOVE:
newTouch = findTouch(event);
if ((newTouch != null) && (newTouch != nowTouched)) {
if (newTouch.isClickable()) {
float x = event.getX();
float y = event.getY();
float pressure = event.getPressure();
float size = event.getSize();
int metaState = event.getMetaState();
float xPrecision = event.getXPrecision();
float yPrecision = event.getYPrecision();
int deviceId = event.getDeviceId();
int edgeFlags = event.getEdgeFlags();
event.setAction(MotionEvent.ACTION_CANCEL);
super.dispatchTouchEvent(event);
long now = SystemClock.uptimeMillis();
event.recycle();
event = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, x, y, pressure, size,
metaState, xPrecision, yPrecision, deviceId, edgeFlags);
}
newTouch.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
}
newTouch.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
nowTouched = newTouch;
break;
case MotionEvent.ACTION_DOWN:
nowTouched = findTouch(event);
if (nowTouched != null)
nowTouched.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
break;
default:
nowTouched = null;
break;
}
nowTouched = newTouch;
break;
case MotionEvent.ACTION_DOWN:
nowTouched = findTouch(event);
if (nowTouched != null)
nowTouched.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
break;
default:
nowTouched = null;
break;
}
super.dispatchTouchEvent(event);
return true;
return super.dispatchTouchEvent(event) || swallow;
}
}

View file

@ -1,6 +1,9 @@
package net.osmand.access;
import net.osmand.access.TextMessage;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import android.content.Context;
import android.view.accessibility.AccessibilityEvent;
import android.widget.Toast;
@ -15,25 +18,23 @@ public class AccessibleToast extends Toast {
}
public static Toast makeText(Context context, int msg, int duration) {
if(true){
// currently disabled (waiting for settings)
return Toast.makeText(context, msg, duration);
}
final Toast toast = new AccessibleToast(context);
toast.setView(TextMessage.makeView(context, msg, R.layout.notification));
toast.setDuration(duration);
return toast;
if (OsmandApplication.getSettings().ACCESSIBILITY_EXTENSIONS.get()) {
final Toast toast = new AccessibleToast(context);
toast.setView(TextMessage.makeView(context, msg, R.layout.notification));
toast.setDuration(duration);
return toast;
}
return Toast.makeText(context, msg, duration);
}
public static Toast makeText(Context context, CharSequence msg, int duration) {
if(true){
// currently disabled (waiting for settings)
return Toast.makeText(context, msg, duration);
}
final Toast toast = new AccessibleToast(context);
toast.setView(TextMessage.makeView(context, msg, R.layout.notification));
toast.setDuration(duration);
return toast;
if (OsmandApplication.getSettings().ACCESSIBILITY_EXTENSIONS.get()) {
final Toast toast = new AccessibleToast(context);
toast.setView(TextMessage.makeView(context, msg, R.layout.notification));
toast.setDuration(duration);
return toast;
}
return Toast.makeText(context, msg, duration);
}
@Override

View file

@ -1,45 +0,0 @@
package net.osmand.access;
import android.app.Activity;
import android.view.MotionEvent;
import android.view.View;
// Provide some additional accessibility means for activity view elements.
//
// To make use of these capabilities simply derive your activity from this class
// and then add view elements you wish to be accessible
// to the accessibleContent list.
//
public class AccessibleTrackedActivity extends Activity implements AccessibleContent.Callback {
// List of accessible views. Use accessibleContent.add(element)
// to add element to it.
public final AccessibleContent accessibleContent = new AccessibleContent();
// Below are two helper methods to improve AlertDialog accessibility.
//
// Since usual message in an AlertDialog that is set by
// AlertDialog.Builder.setMessage() is spoken only once at the best case
// and there is no way to repeat it, use following two methods
// to wrap it into a View and set it by AlertDialog.Builder.setView().
// Such message will be focusable and so it can be repeated by selecting.
public View accessibleMessage(CharSequence msg) {
return TextMessage.makeView(this, msg);
}
public View accessibleMessage(int msgid) {
return TextMessage.makeView(this, msgid);
}
@Override
public boolean dispatchNativeTouchEvent(MotionEvent event) {
return super.dispatchTouchEvent(event);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
return accessibleContent.dispatchTouchEvent(event, this);
}
}

View file

@ -1,5 +1,7 @@
package net.osmand.access;
import net.osmand.plus.OsmandApplication;
import android.content.Context;
import android.text.Layout;
import android.text.method.ArrowKeyMovementMethod;
@ -38,6 +40,8 @@ public class ExplorableTextView extends TextView {
@Override
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
if (!OsmandApplication.getSettings().ACCESSIBILITY_EXTENSIONS.get())
return super.dispatchPopulateAccessibilityEvent(event);
cursorTrackingEnabled = false;
boolean result = super.dispatchPopulateAccessibilityEvent(event);
if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED) {
@ -57,13 +61,15 @@ public class ExplorableTextView extends TextView {
@Override
protected MovementMethod getDefaultMovementMethod() {
return ArrowKeyMovementMethod.getInstance();
if (OsmandApplication.getSettings().ACCESSIBILITY_EXTENSIONS.get())
return ArrowKeyMovementMethod.getInstance();
return super.getDefaultMovementMethod();
}
@Override
protected void onTextChanged(CharSequence text, int start, int before, int after) {
super.onTextChanged(text, start, before, after);
if (!isFocused()) {
if (OsmandApplication.getSettings().ACCESSIBILITY_EXTENSIONS.get() && !isFocused()) {
selectionLength = Math.min(text.length(), AccessibilityEvent.MAX_TEXT_LENGTH);
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
}
@ -72,7 +78,7 @@ public class ExplorableTextView extends TextView {
@Override
protected void onSelectionChanged(int start, int end) {
super.onSelectionChanged(start, end);
if (cursorTrackingEnabled && isFocused()) {
if (OsmandApplication.getSettings().ACCESSIBILITY_EXTENSIONS.get() && cursorTrackingEnabled && isFocused()) {
if (end >= getText().length()) {
cursor = getText().length();
} else if (cursor != end) {

View file

@ -75,16 +75,15 @@ public class MapExplorer implements OnGestureListener, IContextMenuProvider {
contextProvider = this;
}
if (different(newSelections, selectedObjects)) {
// FIXME Map explorer
// ContextMenuLayer contextMenuLayer = mapView.getContextMenuLayer();
// if (contextMenuLayer != null) {
// contextMenuLayer.setSelections(newSelections, contextProvider);
// if (!newSelections.isEmpty())
// mapView.showMessage(mapView.getSettings().USE_SHORT_OBJECT_NAMES.get() ?
// contextMenuLayer.getSelectedObjectName() :
// contextMenuLayer.getSelectedObjectDescription());
// }
// selectedObjects = newSelections;
ContextMenuLayer contextMenuLayer = mapView.getLayerByClass(ContextMenuLayer.class);
if (contextMenuLayer != null) {
contextMenuLayer.setSelections(newSelections, contextProvider);
if (!newSelections.isEmpty())
mapView.showMessage(mapView.getSettings().USE_SHORT_OBJECT_NAMES.get() ?
contextMenuLayer.getSelectedObjectName() :
contextMenuLayer.getSelectedObjectDescription());
}
selectedObjects = newSelections;
}
}
@ -96,9 +95,8 @@ public class MapExplorer implements OnGestureListener, IContextMenuProvider {
if (mapView.getSettings().SCROLL_MAP_BY_GESTURES.get())
return fallback.onDown(e);
ContextMenuLayer contextMenuLayer = mapView.getLayerByClass(ContextMenuLayer.class);
// FIXME
// if (contextMenuLayer != null)
// contextMenuLayer.setSelections(null, null);
if (contextMenuLayer != null)
contextMenuLayer.setSelections(null, null);
selectedObjects = null;
describePointedObjects(e);
return false;

View file

@ -4,6 +4,8 @@ import java.util.ArrayList;
import java.util.List;
import net.osmand.OsmAndFormatter;
import net.osmand.access.AccessibleToast;
import net.osmand.access.RelativeDirectionStyle;
import net.osmand.osm.LatLon;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandSettings;
@ -100,7 +102,7 @@ public class NavigationInfo {
private int directionTo(final Location point, float heading) {
final float bearing = currentLocation.bearingTo(point) - heading;
final int nSectors = (style == RelativeDirectionStyle.CLOCKWISE) ? 12 : direction.length;
int sector = (int)Math.round(Math.abs(bearing) * (float)nSectors / FULL_CIRCLE) % nSectors;
int sector = Math.round(Math.abs(bearing) * (float)nSectors / FULL_CIRCLE) % nSectors;
if ((bearing < 0) && (sector != 0))
sector = nSectors - sector;
return sector;
@ -139,7 +141,7 @@ public class NavigationInfo {
public NavigationInfo(final Context context) {
this.context = context;
settings = ((OsmandApplication)(context.getApplicationContext())).getSettings();
settings = OsmandApplication.getSettings();
currentLocation = null;
lastDirection = new RelativeDirection();
lastNotificationTime = SystemClock.uptimeMillis();
@ -158,7 +160,7 @@ public class NavigationInfo {
// The argument must be not null as well as the currentLocation
private String absoluteDirectionString(float bearing) {
int direction = (int)Math.round(Math.abs(bearing) * (float)cardinal.length / FULL_CIRCLE) % cardinal.length;
int direction = Math.round(Math.abs(bearing) * (float)cardinal.length / FULL_CIRCLE) % cardinal.length;
if ((bearing < 0) && (direction != 0))
direction = cardinal.length - direction;
return getString(cardinal[direction]);
@ -234,7 +236,7 @@ public class NavigationInfo {
public synchronized void setLocation(Location location) {
currentLocation = location;
if (autoAnnounce) {
if (autoAnnounce && ((OsmandApplication)(context.getApplicationContext())).accessibilityEnabled()) {
final LatLon point = settings.getPointToNavigate();
if (point != null) {
if ((currentLocation != null) && currentLocation.hasBearing()) {

View file

@ -14,8 +14,8 @@ public enum RelativeDirectionStyle {
this.key = key;
}
public static String toHumanString(RelativeDirectionStyle style, Context ctx) {
return ctx.getResources().getString(style.key);
public String toHumanString(Context ctx) {
return ctx.getResources().getString(key);
}
}

View file

@ -1,6 +1,8 @@
package net.osmand.access;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
@ -9,14 +11,6 @@ import android.widget.TextView;
// This class contains only static methods intended to improve
// accessibility for AlertDialog and Toast messages.
//
// Since usual message in an AlertDialog that is set by
// AlertDialog.Builder.setMessage() is spoken only once
// at the best case and there is no way to explore or even repeat it,
// use public methods of this class to wrap it into a View
// and set it by AlertDialog.Builder.setView().
// Such message will be focusable and so it can be repeated
// by selecting.
//
public class TextMessage {
protected static View makeView(Context ctx, CharSequence msg, int resid) {
@ -31,12 +25,4 @@ public class TextMessage {
return layout;
}
public static View makeView(Context ctx, CharSequence msg) {
return makeView(ctx, msg, R.layout.alert);
}
public static View makeView(Context ctx, int msgid) {
return makeView(ctx, msgid, R.layout.alert);
}
}

View file

@ -21,6 +21,7 @@ import net.osmand.plus.OsmandSettings;
import net.osmand.plus.PoiFiltersHelper;
import net.osmand.plus.ProgressDialogImplementation;
import net.osmand.LogUtil;
import net.osmand.access.AccessibilityMode;
import net.osmand.access.AccessibleToast;
import net.osmand.plus.activities.DayNightHelper;
import net.osmand.plus.activities.SavingTrackHelper;
@ -43,6 +44,7 @@ import android.content.Intent;
import android.content.res.Configuration;
import android.os.Handler;
import android.text.format.DateFormat;
import android.view.accessibility.AccessibilityManager;
import android.widget.Toast;
import com.bidforfix.andorid.BidForFixHelper;
@ -488,4 +490,14 @@ public class OsmandApplication extends Application {
}
}
public boolean accessibilityEnabled() {
final AccessibilityMode mode = getSettings().ACCESSIBILITY_MODE.get();
if (mode == AccessibilityMode.ON)
return true;
else if (mode == AccessibilityMode.OFF)
return false;
return ((AccessibilityManager)getSystemService(ACCESSIBILITY_SERVICE)).isEnabled();
}
}

View file

@ -8,8 +8,8 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import net.osmand.LogUtil;
import net.osmand.Version;
import net.osmand.access.AccessibilityMode;
import net.osmand.access.AccessibleToast;
import net.osmand.access.RelativeDirectionStyle;
import net.osmand.map.ITileSource;
@ -300,6 +300,32 @@ public class OsmandSettings {
return prefs.edit().putBoolean(getId(), val).commit();
}
}
private class BooleanAccessibilityPreference extends BooleanPreference {
private BooleanAccessibilityPreference(String id, boolean defaultValue, boolean global) {
super(id, defaultValue, global);
}
private BooleanAccessibilityPreference(String id, boolean defaultValue, boolean global, boolean cache) {
super(id, defaultValue, global, cache);
}
@Override
protected Boolean getValue(SharedPreferences prefs, Boolean defaultValue) {
return ctx.accessibilityEnabled() ?
super.getValue(prefs, defaultValue) :
defaultValue;
}
@Override
protected boolean setValue(SharedPreferences prefs, Boolean val) {
return ctx.accessibilityEnabled() ?
super.setValue(prefs, val) :
false;
}
}
private class IntPreference extends CommonPreference<Integer> {
@ -384,14 +410,13 @@ public class OsmandSettings {
protected E getValue(SharedPreferences prefs, E defaultValue) {
try {
int i = prefs.getInt(getId(), -1);
if(i < 0 || i >= values.length){
return defaultValue;
if(i >= 0 && i < values.length){
return values[i];
}
return values[i];
} catch (Exception e) {
android.util.Log.e(LogUtil.TAG, "Error getting value for: " + this.getId(), e);
return defaultValue;
} catch (ClassCastException ex) {
setValue(prefs, defaultValue);
}
return defaultValue;
}
@Override
@ -414,32 +439,36 @@ public class OsmandSettings {
// cache of metrics constants as they are used very often
public final OsmandPreference<MetricsConstants> METRIC_SYSTEM = new EnumIntPreference<MetricsConstants>(
"default_metric_system", MetricsConstants.KILOMETERS_AND_METERS, true, true, MetricsConstants.values());
public String getId() {
return "direction_style";
};
// this value string is synchronized with settings_pref.xml preference name
// cache of metrics constants as they are used very often
public final OsmandPreference<RelativeDirectionStyle> DIRECTION_STYLE = new EnumIntPreference<RelativeDirectionStyle>(
"direction_style", RelativeDirectionStyle.SIDEWISE, true, true, RelativeDirectionStyle.values());
// this value string is synchronized with settings_pref.xml preference name
// cache of metrics constants as they are used very often
public final OsmandPreference<AccessibilityMode> ACCESSIBILITY_MODE = new EnumIntPreference<AccessibilityMode>(
"accessibility_mode", AccessibilityMode.DEFAULT, true, true, AccessibilityMode.values());
// this value string is synchronized with settings_pref.xml preference name
public final OsmandPreference<Boolean> USE_TRACKBALL_FOR_MOVEMENTS =
new BooleanPreference("use_trackball_for_movements", true, true);
// this value string is synchronized with settings_pref.xml preference name
public final OsmandPreference<Boolean> ZOOM_BY_TRACKBALL =
new BooleanPreference("zoom_by_trackball", true, true);
new BooleanAccessibilityPreference("zoom_by_trackball", true, true);
// this value string is synchronized with settings_pref.xml preference name
public final OsmandPreference<Boolean> SCROLL_MAP_BY_GESTURES =
new BooleanPreference("scroll_map_by_gestures", true, true);
new BooleanAccessibilityPreference("scroll_map_by_gestures", true, true);
// this value string is synchronized with settings_pref.xml preference name
public final OsmandPreference<Boolean> USE_SHORT_OBJECT_NAMES =
new BooleanPreference("use_short_object_names", false, true);
new BooleanAccessibilityPreference("use_short_object_names", false, true);
// this value string is synchronized with settings_pref.xml preference name
public final OsmandPreference<Boolean> ACCESSIBILITY_EXTENSIONS =
new BooleanAccessibilityPreference("accessibility_extensions", false, true);
// this value string is synchronized with settings_pref.xml preference name

View file

@ -5,6 +5,7 @@ import java.text.MessageFormat;
import java.util.Random;
import net.osmand.Version;
import net.osmand.access.AccessibleAlertBuilder;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.ResourceManager;
@ -58,7 +59,7 @@ public class MainMenuActivity extends Activity {
if (file.exists() && file.length() > 0) {
if (size != file.length() && !firstTime) {
String msg = MessageFormat.format(getString(R.string.previous_run_crashed), OsmandApplication.EXCEPTION_PATH);
Builder builder = new AlertDialog.Builder(MainMenuActivity.this);
Builder builder = new AccessibleAlertBuilder(MainMenuActivity.this);
builder.setMessage(msg).setNeutralButton(getString(R.string.close), null);
builder.setPositiveButton(R.string.send_report, new DialogInterface.OnClickListener() {
@Override
@ -287,12 +288,12 @@ public class MainMenuActivity extends Activity {
}
if(netOsmandWasInstalled){
Builder builder = new AlertDialog.Builder(this);
Builder builder = new AccessibleAlertBuilder(this);
builder.setMessage(R.string.osmand_net_previously_installed);
builder.setPositiveButton(R.string.default_buttons_ok, null);
builder.show();
} else {
Builder builder = new AlertDialog.Builder(this);
Builder builder = new AccessibleAlertBuilder(this);
builder.setMessage(R.string.first_time_msg);
builder.setPositiveButton(R.string.first_time_download, new DialogInterface.OnClickListener() {
@ -313,7 +314,7 @@ public class MainMenuActivity extends Activity {
boolean check = pref.getBoolean(VECTOR_INDEXES_CHECK, true);
// do not show each time
if (check && new Random().nextInt() % 5 == 1) {
Builder builder = new AlertDialog.Builder(this);
Builder builder = new AccessibleAlertBuilder(this);
if(maps.isEmpty()){
builder.setMessage(R.string.vector_data_missing);
} else if(!maps.basemapExists()){

View file

@ -10,7 +10,10 @@ import net.osmand.GPXUtilities.GPXFile;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.LogUtil;
import net.osmand.Version;
import net.osmand.access.AccessibleActivity;
import net.osmand.access.AccessibleAlertBuilder;
import net.osmand.access.AccessibleToast;
import net.osmand.access.NavigationInfo;
import net.osmand.data.MapTileDownloader.DownloadRequest;
import net.osmand.data.MapTileDownloader.IMapDownloaderCallback;
import net.osmand.map.IMapLocationListener;
@ -77,7 +80,7 @@ import android.view.animation.Animation;
import android.view.animation.Transformation;
import android.widget.Toast;
public class MapActivity extends Activity implements IMapLocationListener, SensorEventListener {
public class MapActivity extends AccessibleActivity implements IMapLocationListener, SensorEventListener {
private static final String GPS_STATUS_ACTIVITY = "com.eclipsim.gpsstatus2.GPSStatus"; //$NON-NLS-1$
private static final String GPS_STATUS_COMPONENT = "com.eclipsim.gpsstatus2"; //$NON-NLS-1$
@ -96,8 +99,8 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
private static final int LOST_LOCATION_MSG_ID = 10;
private static final long LOST_LOCATION_CHECK_DELAY = 20000;
// private static final int LONG_KEYPRESS_MSG_ID = 28;
// private static final int LONG_KEYPRESS_DELAY = 500;
private static final int LONG_KEYPRESS_MSG_ID = 28;
private static final int LONG_KEYPRESS_DELAY = 500;
private long lastTimeAutoZooming = 0;
@ -108,6 +111,7 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
final private MapActivityActions mapActions = new MapActivityActions(this);
private EditingPOIActivity poiActions;
final private MapActivityLayers mapLayers = new MapActivityLayers(this);
private NavigationInfo navigationInfo;
private SavingTrackHelper savingTrackHelper;
private LiveMonitoringHelper liveMonitoringHelper;
@ -150,6 +154,7 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
settings = getMyApplication().getSettings();
navigationInfo = new NavigationInfo(this);
requestWindowFeature(Window.FEATURE_NO_TITLE);
// Full screen is not used here
//getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
@ -327,7 +332,7 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
if (pointToNavigate == null && gpxPath == null) {
notRestoreRoutingMode();
} else {
Builder builder = new AlertDialog.Builder(MapActivity.this);
Builder builder = new AccessibleAlertBuilder(MapActivity.this);
builder.setMessage(R.string.continue_follow_previous_route);
builder.setPositiveButton(R.string.default_buttons_yes, new DialogInterface.OnClickListener() {
@Override
@ -410,6 +415,8 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
public void changeZoom(int newZoom){
boolean changeLocation = settings.AUTO_ZOOM_MAP.get();
mapView.getAnimatedDraggingThread().startZooming(newZoom, changeLocation);
if (getMyApplication().accessibilityEnabled())
AccessibleToast.makeText(this, getString(R.string.zoomIs) + " " + String.valueOf(newZoom), Toast.LENGTH_SHORT).show(); //$NON-NLS-1$
showAndHideMapPosition();
}
@ -515,6 +522,18 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
//that they could do some key combinations with it...
// Victor : doing in that way doesn't close dialog properly!
//return true;
} else if (getMyApplication().accessibilityEnabled() && (keyCode == KeyEvent.KEYCODE_DPAD_CENTER)) {
if (!uiHandler.hasMessages(LONG_KEYPRESS_MSG_ID)) {
Message msg = Message.obtain(uiHandler, new Runnable() {
@Override
public void run() {
emitNavigationHint();
}
});
msg.what = LONG_KEYPRESS_MSG_ID;
uiHandler.sendMessageDelayed(msg, LONG_KEYPRESS_DELAY);
}
return true;
} else if (keyCode == KeyEvent.KEYCODE_SEARCH && event.getRepeatCount() == 0) {
Intent newIntent = new Intent(MapActivity.this, SearchActivity.class);
// causes wrong position caching: newIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
@ -540,6 +559,51 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
return super.onKeyDown(keyCode, event);
}
public String getNavigationHint(LatLon point) {
String hint = navigationInfo.getDirectionString(point, mapLayers.getLocationLayer().getHeading());
if (hint == null)
hint = getString(R.string.no_info);
return hint;
}
private void emitNavigationHint() {
final LatLon point = settings.getPointToNavigate();
if (point != null) {
if (routingHelper.isRouteCalculated()) {
routingHelper.getVoiceRouter().announceCurrentDirection();
} else {
AccessibleToast.makeText(this, getNavigationHint(point), Toast.LENGTH_LONG).show();
}
} else {
AccessibleToast.makeText(this, R.string.mark_final_location_first, Toast.LENGTH_SHORT).show();
}
}
private void whereAmIDialog() {
final List<String> items = new ArrayList<String>();
items.add(getString(R.string.show_location));
items.add(getString(R.string.show_details));
AlertDialog.Builder menu = new AlertDialog.Builder(this);
menu.setItems(items.toArray(new String[items.size()]),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int item) {
dialog.dismiss();
switch (item) {
case 0:
backToLocationImpl();
break;
case 1:
navigationInfo.show(settings.getPointToNavigate(), mapLayers.getLocationLayer().getHeading());
break;
default:
break;
}
}
});
menu.show();
}
public void setMapLocation(double lat, double lon){
mapView.setLatLon(lat, lon);
locationChanged(lat, lon, this);
@ -695,6 +759,7 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
registerUnregisterSensor(location);
updateSpeedBearing(location);
mapLayers.getLocationLayer().setLastKnownLocation(location);
navigationInfo.setLocation(location);
if(routingHelper.isFollowingMode()){
if(location == null || !location.hasAccuracy() || location.getAccuracy() < ACCURACY_FOR_GPX_AND_ROUTING) {
// Update routing position
@ -958,16 +1023,22 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
//onBackPressed();
//return true;
} else if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
contextMenuPoint(mapView.getLatitude(), mapView.getLongitude());
if (!getMyApplication().accessibilityEnabled()) {
contextMenuPoint(mapView.getLatitude(), mapView.getLongitude());
} else if (uiHandler.hasMessages(LONG_KEYPRESS_MSG_ID)) {
uiHandler.removeMessages(LONG_KEYPRESS_MSG_ID);
contextMenuPoint(mapView.getLatitude(), mapView.getLongitude());
}
return true;
} else
} else if (settings.ZOOM_BY_TRACKBALL.get()) {
// Parrot device has only dpad left and right
if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
changeZoom(mapView.getZoom() - 1);
return true;
} else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
changeZoom(mapView.getZoom() + 1);
return true;
} else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
changeZoom(mapView.getZoom() + 1);
return true;
}
}
return super.onKeyUp(keyCode,event);
}
@ -1103,7 +1174,11 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
startActivity(intentSettings);
return true;
} else if (itemId == R.id.map_where_am_i) {
backToLocationImpl();
if (getMyApplication().accessibilityEnabled()) {
whereAmIDialog();
} else {
backToLocationImpl();
}
return true;
} else if (itemId == R.id.map_show_gps_status) {
startGpsStatusIntent();
@ -1181,7 +1256,7 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
if (resolved != null) {
startActivity(intent);
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
AlertDialog.Builder builder = new AccessibleAlertBuilder(this);
builder.setMessage(getString(R.string.gps_status_app_not_found));
builder.setPositiveButton(
getString(R.string.default_buttons_yes),

View file

@ -13,6 +13,7 @@ import net.osmand.FavouritePoint;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.LogUtil;
import net.osmand.access.AccessibleAlertBuilder;
import net.osmand.access.AccessibleToast;
import net.osmand.data.Amenity;
import net.osmand.map.ITileSource;
@ -233,7 +234,7 @@ public class MapActivityActions implements DialogProvider {
private Dialog createReloadTitleDialog(final Bundle args) {
Builder builder = new AlertDialog.Builder(mapActivity);
Builder builder = new AccessibleAlertBuilder(mapActivity);
builder.setMessage(R.string.context_menu_item_update_map_confirm);
builder.setNegativeButton(R.string.default_buttons_cancel, null);
final OsmandMapTileView mapView = mapActivity.getMapView();
@ -414,7 +415,7 @@ public class MapActivityActions implements DialogProvider {
saveDirections();
}
};
Builder builder = new AlertDialog.Builder(mapActivity);
Builder builder = new AccessibleAlertBuilder(mapActivity);
builder.setTitle(R.string.show_route);
builder.setMessage(mapActivity.getRoutingHelper().getGeneralRouteInformation());
builder.setPositiveButton(R.string.default_buttons_save, saveDirections);

View file

@ -155,7 +155,7 @@ public class MapActivityLayers {
mapInfoLayer = new MapInfoLayer(activity, routeLayer);
mapView.addLayer(mapInfoLayer, 9);
// 10. route info layer
routeInfoLayer = new RouteInfoLayer(routingHelper, (LinearLayout) activity.findViewById(R.id.RouteLayout), contextMenuLayer);
routeInfoLayer = new RouteInfoLayer(routingHelper, activity, contextMenuLayer);
mapView.addLayer(routeInfoLayer, 10);
// 11. route info layer
mapControlsLayer = new MapControlsLayer(activity);

View file

@ -12,6 +12,7 @@ import java.util.Set;
import net.osmand.ResultMatcher;
import net.osmand.Version;
import net.osmand.access.AccessibilityMode;
import net.osmand.access.AccessibleToast;
import net.osmand.access.RelativeDirectionStyle;
import net.osmand.map.TileSourceManager;
@ -84,6 +85,9 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
private ListPreference dayNightModePreference;
private ListPreference routerServicePreference;
private ListPreference accessibilityModePreference;
private ListPreference directionStylePreference;
private CheckBoxPreference routeServiceEnabled;
private BroadcastReceiver broadcastReceiver;
@ -184,6 +188,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
registerBooleanPreference(osmandSettings.ZOOM_BY_TRACKBALL,screen);
registerBooleanPreference(osmandSettings.SCROLL_MAP_BY_GESTURES,screen);
registerBooleanPreference(osmandSettings.USE_SHORT_OBJECT_NAMES,screen);
registerBooleanPreference(osmandSettings.ACCESSIBILITY_EXTENSIONS,screen);
registerBooleanPreference(osmandSettings.USE_HIGH_RES_MAPS,screen);
registerBooleanPreference(osmandSettings.USE_ENGLISH_NAMES,screen);
registerBooleanPreference(osmandSettings.AUTO_ZOOM_MAP,screen);
@ -283,9 +288,15 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
}
registerListPreference(osmandSettings.MAP_TEXT_SIZE, screen, entries, floatValues);
entries = new String[AccessibilityMode.values().length];
for(int i=0; i<entries.length; i++){
entries[i] = AccessibilityMode.values()[i].toHumanString(this);
}
registerListPreference(osmandSettings.ACCESSIBILITY_MODE, screen, entries, AccessibilityMode.values());
entries = new String[RelativeDirectionStyle.values().length];
for(int i=0; i<entries.length; i++){
entries[i] = RelativeDirectionStyle.toHumanString(RelativeDirectionStyle.values()[i], this);
entries[i] = RelativeDirectionStyle.values()[i].toHumanString(this);
}
registerListPreference(osmandSettings.DIRECTION_STYLE, screen, entries, RelativeDirectionStyle.values());
@ -349,6 +360,11 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
routerServicePreference = (ListPreference) screen.findPreference(osmandSettings.ROUTER_SERVICE.getId());
routerServicePreference.setOnPreferenceChangeListener(this);
accessibilityModePreference = (ListPreference)screen.findPreference(osmandSettings.ACCESSIBILITY_MODE.getId());
accessibilityModePreference.setOnPreferenceChangeListener(this);
directionStylePreference = (ListPreference)screen.findPreference(osmandSettings.DIRECTION_STYLE.getId());
directionStylePreference.setOnPreferenceChangeListener(this);
Preference localIndexes =(Preference) screen.findPreference(OsmandSettings.LOCAL_INDEXES);
localIndexes.setOnPreferenceClickListener(this);
saveCurrentTrack =(Preference) screen.findPreference(OsmandSettings.SAVE_CURRENT_TRACK);
@ -508,6 +524,9 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
dayNightModePreference.setSummary(getString(R.string.daynight_descr) + " [" + osmandSettings.DAYNIGHT_MODE.get().toHumanString(this) + "]");
routerServicePreference.setSummary(getString(R.string.router_service_descr) + " [" + osmandSettings.ROUTER_SERVICE.get() + "]");
accessibilityModePreference.setSummary(getString(R.string.accessibility_mode_descr) + " [" + osmandSettings.ACCESSIBILITY_MODE.get().toHumanString(this) + "]");
directionStylePreference.setSummary(getString(R.string.settings_direction_style_descr) + " [" + osmandSettings.DIRECTION_STYLE.get().toHumanString(this) + "]");
/*
// TODO: Add Profile name to screen title (only, not to Preference title) of Profile specific settings
PreferenceScreen screen = getPreferenceScreen();
@ -629,6 +648,13 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
dayNightModePreference.setSummary(getString(R.string.daynight_descr) + " [" + osmandSettings.DAYNIGHT_MODE.get().toHumanString(this) + "]");
} else if (listPref.getId().equals(osmandSettings.ROUTER_SERVICE.getId())) {
routerServicePreference.setSummary(getString(R.string.router_service_descr) + " [" + osmandSettings.ROUTER_SERVICE.get() + "]");
} else if (listPref.getId().equals(osmandSettings.ACCESSIBILITY_MODE.getId())) {
PreferenceCategory accessibilityOptions = ((PreferenceCategory)(getPreferenceScreen().findPreference("accessibility_options")));
if (accessibilityOptions != null)
accessibilityOptions.setEnabled(getMyApplication().accessibilityEnabled());
accessibilityModePreference.setSummary(getString(R.string.accessibility_mode_descr) + " [" + osmandSettings.ACCESSIBILITY_MODE.get().toHumanString(this) + "]");
} else if (listPref.getId().equals(osmandSettings.DIRECTION_STYLE.getId())) {
directionStylePreference.setSummary(getString(R.string.settings_direction_style_descr) + " [" + osmandSettings.DIRECTION_STYLE.get().toHumanString(this) + "]");
}
}
if (listPref.getId().equals(osmandSettings.RENDERER.getId())) {

View file

@ -4,6 +4,7 @@ import gnu.trove.list.array.TIntArrayList;
import java.util.Arrays;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import android.app.Dialog;
import android.content.Context;
@ -107,7 +108,8 @@ public class TipsAndTricksActivity {
dlg.setContentView(R.layout.tips_and_tricks);
dlg.getWindow().setLayout(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
final TextView tipDescription = (TextView) dlg.findViewById(R.id.TipDescription);
tipDescription.setMovementMethod(ScrollingMovementMethod.getInstance());
if (!OsmandApplication.getSettings().ACCESSIBILITY_EXTENSIONS.get())
tipDescription.setMovementMethod(ScrollingMovementMethod.getInstance());
int nextInd = 0;
final TIntArrayList toShow = new TIntArrayList();
final int[] historyInd = new int[1];

View file

@ -20,6 +20,7 @@ import net.osmand.LogUtil;
import net.osmand.OsmAndFormatter;
import net.osmand.ResultMatcher;
import net.osmand.access.AccessibleToast;
import net.osmand.access.NavigationInfo;
import net.osmand.data.Amenity;
import net.osmand.data.AmenityType;
import net.osmand.osm.LatLon;
@ -89,6 +90,8 @@ public class SearchPOIActivity extends OsmandListActivity implements SensorEvent
private static final int MIN_DISTANCE_TO_RESEARCH = 70;
private static final int MIN_DISTANCE_TO_UPDATE = 6;
private NavigationInfo navigationInfo;
private Button searchPOILevel;
private ImageButton showOnMap;
@ -115,6 +118,7 @@ public class SearchPOIActivity extends OsmandListActivity implements SensorEvent
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
navigationInfo = new NavigationInfo(this);
CustomTitleBar titleBar = new CustomTitleBar(this, R.string.searchpoi_activity, R.drawable.tab_search_poi_icon);
setContentView(R.layout.searchpoi);
titleBar.afterSetContentView();
@ -347,6 +351,7 @@ public class SearchPOIActivity extends OsmandListActivity implements SensorEvent
public void setLocation(Location l){
registerUnregisterSensor(l);
navigationInfo.setLocation(l);
boolean handled = false;
if (l != null && filter != null) {
Location searchedLocation = getSearchedLocation();
@ -401,12 +406,22 @@ public class SearchPOIActivity extends OsmandListActivity implements SensorEvent
AccessibleToast.makeText(this, format + " " + getString(R.string.opening_hours) + " : " + amenity.getOpeningHours(), Toast.LENGTH_LONG).show();
}
List<String> items = new ArrayList<String>();
items.add(getString(R.string.show_poi_on_map));
items.add(getString(R.string.navigate_to));
if (((OsmandApplication)getApplication()).accessibilityEnabled())
items.add(getString(R.string.show_details));
AlertDialog.Builder builder = new AlertDialog.Builder(SearchPOIActivity.this);
builder.setTitle(format);
builder.setItems(new String[]{getString(R.string.show_poi_on_map), getString(R.string.navigate_to)}, new DialogInterface.OnClickListener(){
builder.setItems(items.toArray(new String[items.size()]), new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
if(which == 2){
showPOIDetails(amenity, settings.usingEnglishNames());
return;
}
if(which == 0){
int z = settings.getLastKnownMapZoom();
String poiSimpleFormat = OsmAndFormatter.getPoiSimpleFormat(amenity, SearchPOIActivity.this, settings.usingEnglishNames());
@ -762,7 +777,34 @@ public class SearchPOIActivity extends OsmandListActivity implements SensorEvent
}
}
private void showPOIDetails(final Amenity amenity, boolean en) {
AlertDialog.Builder b = new AlertDialog.Builder(SearchPOIActivity.this);
b.setTitle(OsmAndFormatter.getPoiSimpleFormat(amenity, SearchPOIActivity.this, en));
b.setPositiveButton(R.string.default_buttons_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
List<String> attributes = new ArrayList<String>();
String direction = navigationInfo.getDirectionString(amenity.getLocation(), heading);
if (direction != null)
attributes.add(direction);
if (amenity.getPhone() != null)
attributes.add(getString(R.string.phone) + " " + amenity.getPhone());
if (amenity.getOpeningHours() != null)
attributes.add(getString(R.string.opening_hours) + " " + amenity.getOpeningHours());
attributes.add(getString(R.string.navigate_point_latitude) + " " + Double.toString(amenity.getLocation().getLatitude()));
attributes.add(getString(R.string.navigate_point_longitude) + " " + Double.toString(amenity.getLocation().getLongitude()));
b.setItems(attributes.toArray(new String[attributes.size()]),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
b.show();
}
// Working with location listeners
private LocationListener networkListener = new LocationListener(){
@Override

View file

@ -150,8 +150,26 @@ public class ContextMenuLayer extends OsmandMapLayer {
}
public void setSelections(List<Object> selections, IContextMenuProvider contextProvider) {
if (selections != null) {
selectedObjects = selections;
} else {
selectedObjects.clear();
}
if (!selectedObjects.isEmpty()) {
selectedContextProvider = contextProvider;
latLon = contextProvider.getObjectLocation(selectedObjects.get(0));
}
}
@Override
public boolean onLongPressEvent(PointF point) {
if (!view.getSettings().SCROLL_MAP_BY_GESTURES.get()) {
if (!selectedObjects.isEmpty())
view.showMessage(activity.getNavigationHint(latLon));
return true;
}
if(pressedInTextView(point.x, point.y)){
setLocation(null, ""); //$NON-NLS-1$
view.refreshMap();
@ -171,22 +189,15 @@ public class ContextMenuLayer extends OsmandMapLayer {
}
LatLon latLon = view.getLatLonFromScreenPoint(point.x, point.y);
StringBuilder description = new StringBuilder();
String description = getSelectedObjectDescription();
if (!selectedObjects.isEmpty()) {
if (selectedObjects.size() > 1) {
description.append("1. ");
}
description.append(selectedContextProvider.getObjectDescription(selectedObjects.get(0)));
for (int i = 1; i < selectedObjects.size(); i++) {
description.append("\n" + (i + 1) + ". ").append(selectedContextProvider.getObjectDescription(selectedObjects.get(i)));
}
LatLon l = selectedContextProvider.getObjectLocation(selectedObjects.get(0));
if (l != null) {
latLon = l;
}
}
setLocation(latLon, description.toString());
setLocation(latLon, description);
view.refreshMap();
return true;
}
@ -212,17 +223,37 @@ public class ContextMenuLayer extends OsmandMapLayer {
public String getSelectedObjectName(){
if(!selectedObjects.isEmpty() && selectedContextProvider != null){
return selectedContextProvider.getObjectName(selectedObjects);
StringBuilder name = new StringBuilder();
if (selectedObjects.size() > 1)
name.append("1. ");
name.append(selectedContextProvider.getObjectName(selectedObjects.get(0)));
for (int i = 1; i < selectedObjects.size(); i++)
name.append("\n" + (i + 1) + ". ").append(selectedContextProvider.getObjectName(selectedObjects.get(i)));
return name.toString();
}
return null;
}
public String getSelectedObjectDescription(){
if(!selectedObjects.isEmpty() && selectedContextProvider != null){
StringBuilder description = new StringBuilder();
if (selectedObjects.size() > 1)
description.append("1. ");
description.append(selectedContextProvider.getObjectDescription(selectedObjects.get(0)));
for (int i = 1; i < selectedObjects.size(); i++)
description.append("\n" + (i + 1) + ". ").append(selectedContextProvider.getObjectDescription(selectedObjects.get(i)));
return description.toString();
}
return null;
}
@Override
public boolean onSingleTap(PointF point) {
if (pressedInTextView(point.x, point.y)) {
boolean nativeMode = view.getSettings().SCROLL_MAP_BY_GESTURES.get();
if ((!nativeMode) || pressedInTextView(point.x, point.y)) {
if (!selectedObjects.isEmpty()) {
showContextMenuForSelectedObjects();
} else {
} else if (nativeMode) {
activity.contextMenuPoint(latLon.getLatitude(), latLon.getLongitude());
}
return true;

View file

@ -228,7 +228,9 @@ public class MapControlsLayer extends OsmandMapLayer {
private void initBackToMenuButton(final OsmandMapTileView view, FrameLayout parent) {
android.widget.FrameLayout.LayoutParams params;
backToMenuButton = new Button(view.getContext());
Context ctx = view.getContext();
backToMenuButton = new Button(ctx);
backToMenuButton.setContentDescription(ctx.getString(R.string.backToMenu));
backToMenuButton.setBackgroundResource(R.drawable.map_btn_menu);
params = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
Gravity.BOTTOM | Gravity.LEFT);
@ -244,6 +246,8 @@ public class MapControlsLayer extends OsmandMapLayer {
activity.backToMainMenu();
}
});
activity.accessibleContent.add(backToMenuButton);
}
private void initRuler(OsmandMapTileView view, FrameLayout parent) {
@ -291,6 +295,9 @@ public class MapControlsLayer extends OsmandMapLayer {
zoomOutButton.setContentDescription(ctx.getString(R.string.zoomOut));
parent.addView(zoomOutButton, params);
activity.accessibleContent.add(zoomInButton);
activity.accessibleContent.add(zoomOutButton);
zoomInButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {

View file

@ -7,7 +7,9 @@ import java.util.List;
import java.util.Map;
import net.osmand.LogUtil;
import net.osmand.OsmAndFormatter;
import net.osmand.access.AccessibleToast;
import net.osmand.access.MapExplorer;
import net.osmand.data.MapTileDownloader.DownloadRequest;
import net.osmand.data.MapTileDownloader.IMapDownloaderCallback;
import net.osmand.map.IMapLocationListener;
@ -15,6 +17,7 @@ import net.osmand.osm.LatLon;
import net.osmand.osm.MapUtils;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.views.MultiTouchSupport.MultiTouchZoomListener;
import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
@ -36,6 +39,7 @@ import android.util.FloatMath;
import android.view.GestureDetector;
import android.view.GestureDetector.OnDoubleTapListener;
import android.view.GestureDetector.OnGestureListener;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
@ -160,7 +164,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
getHolder().addCallback(this);
animatedDraggingThread = new AnimateDraggingMapThread(this);
gestureDetector = new GestureDetector(getContext(), new MapTileViewOnGestureListener());
gestureDetector = new GestureDetector(getContext(), new MapExplorer(this, new MapTileViewOnGestureListener()));
multiTouchSupport = new MultiTouchSupport(getContext(), new MapTileViewMultiTouchZoomListener());
gestureDetector.setOnDoubleTapListener(new MapTileViewOnDoubleTapListener());
@ -184,6 +188,11 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
public void surfaceDestroyed(SurfaceHolder holder) {
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
return application.accessibilityEnabled() ? false : super.onKeyDown(keyCode, event);
}
public void addLayer(OsmandMapLayer layer, float zOrder) {
int i = 0;
for (i = 0; i < layers.size(); i++) {
@ -209,7 +218,7 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
@SuppressWarnings("unchecked")
public <T extends OsmandMapLayer> T getLayerByClass(Class<T> cl) {
for(OsmandMapLayer lr : layers) {
if(cl.isInstance(cl)){
if(cl.isInstance(lr)){
return (T) lr;
}
}
@ -765,7 +774,17 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
float dz = (float) (Math.log(relativeToStart) / Math.log(2) * 1.5);
float calcZoom = initialMultiTouchZoom + dz;
setZoom(Math.round(calcZoom));
zoomPositionChanged(getZoom());
final int newZoom = getZoom();
zoomPositionChanged(newZoom);
if (application.accessibilityEnabled()) {
if (newZoom != initialMultiTouchZoom) {
showMessage(getContext().getString(R.string.zoomIs) + " " + String.valueOf(newZoom)); //$NON-NLS-1$
} else {
final LatLon p1 = getLatLonFromScreenPoint(x1, y1);
final LatLon p2 = getLatLonFromScreenPoint(x2, y2);
showMessage(OsmAndFormatter.getFormattedDistance((float)MapUtils.getDistance(p1.getLatitude(), p1.getLongitude(), p2.getLatitude(), p2.getLongitude()), getContext()));
}
}
}
@Override

View file

@ -3,6 +3,7 @@ package net.osmand.plus.views;
import net.osmand.osm.LatLon;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.ShowRouteInfoActivity;
import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.routing.RoutingHelper.IRouteInformationListener;
@ -35,7 +36,8 @@ public class RouteInfoLayer extends OsmandMapLayer implements IRouteInformationL
public RouteInfoLayer(RoutingHelper routingHelper, LinearLayout layout, ContextMenuLayer contextMenu){
public RouteInfoLayer(RoutingHelper routingHelper, MapActivity activity, ContextMenuLayer contextMenu){
final LinearLayout layout = (LinearLayout) activity.findViewById(R.id.RouteLayout);
this.routingHelper = routingHelper;
this.contextMenu = contextMenu;
prev = (Button) layout.findViewById(R.id.PreviousButton);
@ -44,6 +46,10 @@ public class RouteInfoLayer extends OsmandMapLayer implements IRouteInformationL
routingHelper.addListener(this);
attachListeners();
updateVisibility();
activity.accessibleContent.add(prev);
activity.accessibleContent.add(next);
activity.accessibleContent.add(info);
}
@Override