fiore@0
|
1 /*
|
fiore@0
|
2 CCmI Diagram Editor for Android
|
fiore@0
|
3
|
fiore@0
|
4 Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/)
|
fiore@0
|
5
|
fiore@0
|
6 This program is free software: you can redistribute it and/or modify
|
fiore@0
|
7 it under the terms of the GNU General Public License as published by
|
fiore@0
|
8 the Free Software Foundation, either version 3 of the License, or
|
fiore@0
|
9 (at your option) any later version.
|
fiore@0
|
10
|
fiore@0
|
11 This program is distributed in the hope that it will be useful,
|
fiore@0
|
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
fiore@0
|
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
fiore@0
|
14 GNU General Public License for more details.
|
fiore@0
|
15
|
fiore@0
|
16 You should have received a copy of the GNU General Public License
|
fiore@0
|
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
|
fiore@0
|
18 */
|
fiore@0
|
19 package uk.ac.qmul.eecs.ccmi.accessibility;
|
fiore@0
|
20
|
fiore@0
|
21 import uk.ac.qmul.eecs.ccmi.activities.R;
|
fiore@1
|
22 import uk.ac.qmul.eecs.ccmi.utilities.ILogger;
|
fiore@0
|
23 import android.content.Context;
|
fiore@0
|
24 import android.util.AttributeSet;
|
fiore@0
|
25 import android.view.MotionEvent;
|
fiore@0
|
26 import android.view.View;
|
fiore@0
|
27 import android.view.accessibility.AccessibilityEvent;
|
fiore@0
|
28 import android.widget.ArrayAdapter;
|
fiore@0
|
29 import android.widget.LinearLayout;
|
fiore@0
|
30 import android.widget.Spinner;
|
fiore@0
|
31
|
fiore@0
|
32 /**
|
fiore@0
|
33 *
|
fiore@0
|
34 * A check box list that can be operated without looking at the display.
|
fiore@0
|
35 *
|
fiore@0
|
36 */
|
fiore@0
|
37 public class AccessibleCheckbox extends LinearLayout{
|
fiore@0
|
38 private NoClickSpinner spinner;
|
fiore@0
|
39 private AccessibilityService service;
|
fiore@0
|
40 private boolean[] checks;
|
fiore@0
|
41
|
fiore@0
|
42 public AccessibleCheckbox(Context context, AttributeSet attrs) {
|
fiore@0
|
43 super(context, attrs);
|
fiore@0
|
44 init(context);
|
fiore@0
|
45 }
|
fiore@0
|
46
|
fiore@0
|
47 public AccessibleCheckbox(Context context) {
|
fiore@0
|
48 super(context);
|
fiore@0
|
49 init(context);
|
fiore@0
|
50 }
|
fiore@0
|
51
|
fiore@0
|
52 private void init(Context context){
|
fiore@0
|
53 spinner = new NoClickSpinner(context);
|
fiore@0
|
54 spinner.setContentDescription("selection box: ");
|
fiore@0
|
55 spinner.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
|
fiore@0
|
56 setTag("CHECKBOX");
|
fiore@0
|
57 addView(spinner);
|
fiore@0
|
58 }
|
fiore@0
|
59
|
fiore@0
|
60 /**
|
fiore@0
|
61 * Sets the {@code accessibility} service for this class.
|
fiore@0
|
62 *
|
fiore@0
|
63 * @param service the {@code AccessibilityService} for this class
|
fiore@0
|
64 */
|
fiore@0
|
65 public void setAccessibilityService(AccessibilityService service){
|
fiore@0
|
66 this.service = service;
|
fiore@0
|
67 }
|
fiore@0
|
68
|
fiore@0
|
69 /**
|
fiore@0
|
70 * Returns a reference to the {@code accessibility} service for this class.
|
fiore@0
|
71 *
|
fiore@0
|
72 * @return the {@code AccessibilityService} for this class
|
fiore@0
|
73 */
|
fiore@0
|
74 public AccessibilityService getAccessibilityService(){
|
fiore@0
|
75 return service;
|
fiore@0
|
76 }
|
fiore@0
|
77
|
fiore@0
|
78 /**
|
fiore@0
|
79 * Sets the values to display to the user.
|
fiore@0
|
80 *
|
fiore@0
|
81 * @param values the values to display
|
fiore@0
|
82 * @param valueChecks The initial checks. If {@code valueChecks[i]} is {@code true} then {@code values[i]} will be
|
fiore@0
|
83 * checked when displayed to the user
|
fiore@0
|
84 */
|
fiore@0
|
85 public void setValues(String[] values, boolean[] valueChecks){
|
fiore@0
|
86 /* initialize the string array with the labels of the spinner, which are going to be between
|
fiore@0
|
87 * "<" and ">" if they are checked (according to valueChecks).
|
fiore@0
|
88 * checks is also initialized with valueChecks values, this will modified according
|
fiore@0
|
89 * to the user's selections and then returned by getValues() when the dialog is closed.
|
fiore@0
|
90 */
|
fiore@0
|
91 final String[] markedValues = new String[values.length];
|
fiore@0
|
92 checks = new boolean[valueChecks.length];
|
fiore@0
|
93 for(int i=0; i<values.length; i++){
|
fiore@0
|
94 checks[i] = valueChecks[i];
|
fiore@0
|
95 markedValues[i] = (checks[i] ? "<"+values[i]+">" : values[i] );
|
fiore@0
|
96 }
|
fiore@0
|
97
|
fiore@0
|
98 spinner.setAdapter(new ArrayAdapter<String>(getContext(),R.layout.list_item_1,markedValues));
|
fiore@0
|
99
|
fiore@0
|
100 setOnClickListener(new View.OnClickListener(){
|
fiore@0
|
101 @Override
|
fiore@0
|
102 public void onClick(View view) {
|
fiore@0
|
103 spinner.setSelection((spinner.getSelectedItemPosition()+1) % spinner.getCount());
|
fiore@1
|
104 ILogger.logTap("checkbox (new value="+spinner.getSelectedItem().toString()+')');
|
fiore@0
|
105 if(service != null){
|
fiore@0
|
106 service.speak(spinner.getSelectedItem().toString()+(checks[spinner.getSelectedItemPosition()] ? " " : " un")+"checked");
|
fiore@0
|
107 }
|
fiore@0
|
108 }
|
fiore@0
|
109 });
|
fiore@0
|
110
|
fiore@0
|
111 setOnLongClickListener(new View.OnLongClickListener(){
|
fiore@0
|
112 @Override
|
fiore@0
|
113 public boolean onLongClick(View view) {
|
fiore@0
|
114 int itemPosition = spinner.getSelectedItemPosition();
|
fiore@0
|
115 checks[itemPosition] = !checks[itemPosition];
|
fiore@0
|
116 if(checks[itemPosition]){
|
fiore@0
|
117 markedValues[itemPosition] = "<"+markedValues[itemPosition]+">";
|
fiore@0
|
118 }else{
|
fiore@0
|
119 markedValues[itemPosition] = markedValues[itemPosition].replaceAll("(^<)|(>$)", "");
|
fiore@0
|
120 }
|
fiore@0
|
121 if(service != null)
|
fiore@0
|
122 service.speak(spinner.getSelectedItem().toString()+(checks[spinner.getSelectedItemPosition()] ? "" : "un")+"checked");
|
fiore@1
|
123 ILogger.log("user long tap: spinner");
|
fiore@1
|
124 ILogger.log(spinner.getSelectedItem().toString()+' '+(checks[spinner.getSelectedItemPosition()] ? "" : "un")+"checked");
|
fiore@0
|
125 spinner.setAdapter(new ArrayAdapter<String>(getContext(),R.layout.list_item_1,markedValues));
|
fiore@0
|
126 spinner.setSelection(itemPosition);
|
fiore@0
|
127 return true;
|
fiore@0
|
128 }
|
fiore@0
|
129 });
|
fiore@0
|
130 }
|
fiore@0
|
131
|
fiore@0
|
132 /**
|
fiore@0
|
133 * Returns the checks of the current values. To be called after this checkbox has been displayed
|
fiore@0
|
134 * to the user to collect their checks.
|
fiore@0
|
135 *
|
fiore@0
|
136 * @return the current checks
|
fiore@0
|
137 */
|
fiore@0
|
138 public boolean[] getChecks(){
|
fiore@0
|
139 return checks;
|
fiore@0
|
140 }
|
fiore@0
|
141
|
fiore@0
|
142 /**
|
fiore@0
|
143 * Returns the currently selected value of the list.
|
fiore@0
|
144 *
|
fiore@0
|
145 * @return the currently selected value of the list
|
fiore@0
|
146 */
|
fiore@0
|
147 public String getSelectedValue(){
|
fiore@0
|
148 return spinner.getSelectedItem().toString();
|
fiore@0
|
149 }
|
fiore@0
|
150
|
fiore@0
|
151 /**
|
fiore@0
|
152 * Returns the position in the list of the currently selected value.
|
fiore@0
|
153 *
|
fiore@0
|
154 * @return the position in the list of the currently selected value
|
fiore@0
|
155 */
|
fiore@0
|
156 public int getSelectedValuePosition(){
|
fiore@0
|
157 return spinner.getSelectedItemPosition();
|
fiore@0
|
158 }
|
fiore@0
|
159
|
fiore@0
|
160 /**
|
fiore@0
|
161 * This method is empty to prevent the screen reader to speak when clicking on this text view.
|
fiore@0
|
162 */
|
fiore@0
|
163 @Override
|
fiore@0
|
164 public void sendAccessibilityEvent(int eventType){
|
fiore@0
|
165
|
fiore@0
|
166 }
|
fiore@0
|
167
|
fiore@0
|
168 /**
|
fiore@0
|
169 * This method is empty to prevent the screen reader to speak when clicking on this text view.
|
fiore@0
|
170 */
|
fiore@0
|
171 @Override
|
fiore@0
|
172 public void sendAccessibilityEventUnchecked(AccessibilityEvent event){
|
fiore@0
|
173
|
fiore@0
|
174 }
|
fiore@0
|
175
|
fiore@0
|
176 private static class NoClickSpinner extends Spinner {
|
fiore@0
|
177
|
fiore@0
|
178 public NoClickSpinner(Context context) {
|
fiore@0
|
179 super(context);
|
fiore@0
|
180 }
|
fiore@0
|
181
|
fiore@0
|
182 public NoClickSpinner(Context context, AttributeSet attrs, int defStyle) {
|
fiore@0
|
183 super(context, attrs, defStyle);
|
fiore@0
|
184 }
|
fiore@0
|
185
|
fiore@0
|
186 public NoClickSpinner(Context context, AttributeSet attrs) {
|
fiore@0
|
187 super(context, attrs);
|
fiore@0
|
188 }
|
fiore@0
|
189
|
fiore@0
|
190 @Override
|
fiore@0
|
191 public boolean dispatchTouchEvent(MotionEvent evt){
|
fiore@0
|
192 return false;
|
fiore@0
|
193 }
|
fiore@0
|
194 }
|
fiore@0
|
195
|
fiore@0
|
196 }
|