annotate src/uk/ac/qmul/eecs/ccmi/accessibility/AccessibleDialogBuilder.java @ 1:66b3a838feca logging tip

Added logging of user interaction
author Fiore Martin <fiore@eecs.qmul.ac.uk>
date Tue, 12 Feb 2013 15:31:48 +0000
parents e0ee6ac3a45f
children
rev   line source
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.accessibility.AccessibilityService.SoundEvent;
fiore@0 22 import uk.ac.qmul.eecs.ccmi.activities.R;
fiore@1 23 import uk.ac.qmul.eecs.ccmi.utilities.ILogger;
fiore@0 24 import android.app.AlertDialog;
fiore@0 25 import android.app.Dialog;
fiore@0 26 import android.content.Context;
fiore@0 27 import android.content.DialogInterface;
fiore@0 28 import android.os.Bundle;
fiore@0 29 import android.support.v4.app.DialogFragment;
fiore@0 30 import android.support.v4.app.FragmentManager;
fiore@0 31 import android.view.LayoutInflater;
fiore@0 32 import android.view.MotionEvent;
fiore@0 33 import android.view.View;
fiore@0 34 import android.view.ViewGroup;
fiore@0 35 import android.widget.ArrayAdapter;
fiore@0 36 import android.widget.Button;
fiore@0 37 import android.widget.EditText;
fiore@0 38
fiore@0 39 public class AccessibleDialogBuilder {
fiore@0 40 private FragmentManager fragmentManager;
fiore@0 41 private AccessibilityService accessibilityService;
fiore@0 42
fiore@0 43 public AccessibleDialogBuilder(FragmentManager fragmentManager) {
fiore@0 44 this.fragmentManager = fragmentManager;
fiore@0 45 }
fiore@0 46
fiore@0 47 /**
fiore@0 48 * Sets the {@code AccessibilityService} for the dialogs. The call to this method must happen before
fiore@0 49 * any dialog is displayed. The dialogs will be then accessible through a {@code LayoutSonifier}.
fiore@0 50 *
fiore@0 51 * @param accessibilityService the {@code AccessibilityService} instance for this class.
fiore@0 52 */
fiore@0 53 public void setAccessibilityService(AccessibilityService accessibilityService){
fiore@0 54 this.accessibilityService = accessibilityService;
fiore@0 55 }
fiore@0 56
fiore@0 57 /**
fiore@0 58 * Returns the instance of accessibility service in use. This can be useful to the client of this class to play
fiore@0 59 * speech and sound when showing and dismissing dialogs.
fiore@0 60 *
fiore@0 61 * @return a reference to the {@code AccessibilityService} class in use
fiore@0 62 */
fiore@0 63 public AccessibilityService getAccessibilityService(){
fiore@0 64 return accessibilityService;
fiore@0 65 }
fiore@0 66
fiore@0 67 /**
fiore@0 68 * Displays an accessible dialog
fiore@0 69 *
fiore@0 70 * @param type ID for an XML layout resource to load (e.g., R.layout.main_page)
fiore@0 71 * @param tag the tag for this dialog. It's also used uttered out through the speech
fiore@0 72 * synthesizer to notify the user the dialog has been displayed
fiore@0 73 * @param buttonClickListener a listener that will be called when any of the buttons
fiore@0 74 * of the dialog will be pressed
fiore@0 75 */
fiore@0 76 public void displayDialog(int type, String tag, ButtonClickListener buttonClickListener){
fiore@0 77 AccessibleDialogFragment accessibleDialogFragment = new AccessibleDialogFragment();
fiore@0 78
fiore@0 79 accessibleDialogFragment.buttonClickListener = buttonClickListener;
fiore@0 80 accessibleDialogFragment.accessibilityService = accessibilityService;
fiore@0 81
fiore@0 82 /* args to be used in onCreateDialog by the dialog fragment */
fiore@0 83 Bundle args = new Bundle();
fiore@0 84 args.putInt("dialogType", type);
fiore@0 85 args.putString("tag", tag);
fiore@0 86 accessibleDialogFragment.setArguments(args);
fiore@1 87
fiore@1 88 ILogger.logDialog(tag);
fiore@0 89 /* show the dialog */
fiore@0 90 accessibleDialogFragment.show(fragmentManager,tag);
fiore@0 91 }
fiore@0 92
fiore@0 93 /**
fiore@0 94 * Displays an accessible text dialog. The dialog has one text field for text input, and buttons
fiore@0 95 * to confirm or cancel your input.
fiore@0 96 *
fiore@0 97 * @param tag the tag for this dialog. It's also used uttered out through the speech
fiore@0 98 * synthesizer to notify the user the dialog has been displayed
fiore@0 99 * @param text optional text to set in the text field before shoing the dialog
fiore@0 100 * @param buttonClickListener a listener that will be called when any of the buttons
fiore@0 101 * of the dialog will be pressed
fiore@0 102 */
fiore@0 103 public void displayTextDialog(String tag, String text, ButtonClickListener buttonClickListener){
fiore@0 104 AccessibleDialogFragment accessibleDialogFragment = new AccessibleDialogFragment();
fiore@0 105
fiore@0 106 accessibleDialogFragment.buttonClickListener = buttonClickListener;
fiore@0 107 accessibleDialogFragment.accessibilityService = accessibilityService;
fiore@0 108
fiore@0 109 /* args to be used in onCreateDialog by the dialog fragment */
fiore@0 110 Bundle args = new Bundle();
fiore@0 111 args.putInt("dialogType", R.layout.text_dialog);
fiore@0 112 args.putString("tag", tag);
fiore@0 113 if(text != null)
fiore@0 114 args.putString("text", text);
fiore@0 115 accessibleDialogFragment.setArguments(args);
fiore@1 116
fiore@1 117 ILogger.logDialog(tag);
fiore@0 118 /* show the dialog */
fiore@0 119 accessibleDialogFragment.show(fragmentManager,tag);
fiore@0 120 }
fiore@0 121
fiore@0 122 /**
fiore@0 123 * Displays an accessible selection dialog. The dialog has one selection box for selection input, and buttons
fiore@0 124 * to confirm or cancel your input.
fiore@0 125 *
fiore@0 126 * @param tag tag the tag for this dialog. It's also used uttered out through the speech
fiore@0 127 * synthesizer to notify the user the dialog has been displayed
fiore@0 128 * @param values the possible values of the selection box
fiore@0 129 * @param buttonClickListener a listener that will be called when any of the buttons
fiore@0 130 * of the dialog will be pressed
fiore@0 131 */
fiore@0 132 public void displaySelectionDialog(String tag, String[] values, ButtonClickListener buttonClickListener ){
fiore@0 133 AccessibleDialogFragment accessibleDialogFragment = new AccessibleDialogFragment();
fiore@0 134
fiore@0 135 accessibleDialogFragment.buttonClickListener = buttonClickListener;
fiore@0 136 accessibleDialogFragment.accessibilityService = accessibilityService;
fiore@0 137 accessibleDialogFragment.values = values;
fiore@0 138
fiore@0 139 /* args to be used in onCreateDialog by the dialog fragment */
fiore@0 140 Bundle args = new Bundle();
fiore@0 141 args.putInt("dialogType", R.layout.selection_dialog);
fiore@0 142 args.putString("tag", tag);
fiore@0 143 accessibleDialogFragment.setArguments(args);
fiore@1 144
fiore@1 145 ILogger.logDialog(tag);
fiore@0 146 /* show the dialog */
fiore@0 147 accessibleDialogFragment.show(fragmentManager,tag);
fiore@0 148 }
fiore@0 149
fiore@0 150 /**
fiore@0 151 * Displays an accessible check box dialog. The dialog has one check box for selection input, and buttons
fiore@0 152 * to confirm or cancel your input.
fiore@0 153 *
fiore@0 154 * @param tag tag the tag for this dialog. It's also used uttered out through the speech
fiore@0 155 * synthesizer to notify the user the dialog has been displayed
fiore@0 156 * @param values the possible values that can be checked
fiore@0 157 * @param checks The initial checks. If {@code valueChecks[i]} is {@code true} then {@code values[i]} will be
fiore@0 158 * checked when displayed to the user
fiore@0 159 * @param buttonClickListener a listener that will be called when any of the buttons
fiore@0 160 * of the dialog will be pressed
fiore@0 161 */
fiore@0 162 public void displayCheckDialog(String tag, String[] values, boolean[] checks, ButtonClickListener buttonClickListener){
fiore@0 163 AccessibleDialogFragment accessibleDialogFragment = new AccessibleDialogFragment();
fiore@0 164
fiore@0 165 accessibleDialogFragment.buttonClickListener = buttonClickListener;
fiore@0 166 accessibleDialogFragment.accessibilityService = accessibilityService;
fiore@0 167 accessibleDialogFragment.values = values;
fiore@0 168 accessibleDialogFragment.checks = checks;
fiore@0 169
fiore@0 170 /* args to be used in onCreateDialog by the dialog fragment */
fiore@0 171 Bundle args = new Bundle();
fiore@0 172 args.putInt("dialogType", R.layout.checkbox_dialog);
fiore@0 173 args.putString("tag", tag);
fiore@0 174 accessibleDialogFragment.setArguments(args);
fiore@1 175
fiore@1 176 ILogger.logDialog(tag);
fiore@0 177 /* show the dialog */
fiore@0 178 accessibleDialogFragment.show(fragmentManager,tag);
fiore@0 179 }
fiore@0 180
fiore@0 181 public static class AccessibleDialogFragment extends DialogFragment {
fiore@0 182 private String[] values;
fiore@0 183 private boolean[] checks;
fiore@0 184 private ButtonClickListener buttonClickListener;
fiore@0 185 private AccessibilityService accessibilityService;
fiore@0 186
fiore@0 187 @Override
fiore@0 188 public Dialog onCreateDialog(final Bundle savedInstanceState) {
fiore@0 189 /* Get layout inflater */
fiore@0 190 LayoutInflater inflater = getActivity().getLayoutInflater();
fiore@0 191 /* inflate the view with layout and pass it to the builder for creation */
fiore@0 192 ViewGroup layout = (ViewGroup)inflater.inflate(getArguments().getInt("dialogType"), null);
fiore@0 193
fiore@0 194 if(values != null){
fiore@0 195 if(checks == null){ //selection dialog
fiore@0 196 AccessibleSpinner spinner = (AccessibleSpinner)layout.findViewById(R.id.selectionSpinner);
fiore@0 197 spinner.setAccessibilityService(accessibilityService);
fiore@0 198 spinner.setAdapter(new ArrayAdapter<String>(getActivity(), R.layout.list_item_1 ,values));
fiore@0 199 }else{ // check box dialog
fiore@0 200 AccessibleCheckbox checkbox = (AccessibleCheckbox)layout.findViewById(R.id.checkBox);
fiore@0 201 checkbox.setValues(values, checks);
fiore@0 202 checkbox.setAccessibilityService(accessibilityService);
fiore@0 203 }
fiore@0 204 }
fiore@0 205 if(getArguments().getString("text") != null){
fiore@0 206 EditText textField = (EditText)layout.findViewById(R.id.text_edit);
fiore@0 207 textField.setText(getArguments().getString("text"));
fiore@0 208 }
fiore@0 209
fiore@0 210 AlertDialog createdDialog = new AccessibleDialog(getActivity(),accessibilityService,layout);
fiore@0 211 createdDialog.setCancelable(false);
fiore@0 212 createdDialog.setCanceledOnTouchOutside(false);
fiore@0 213
fiore@0 214 /* go through the layout and look for any buttons to hook them up with the button listener */
fiore@0 215 for(int i=0; i< layout.getChildCount(); i++){
fiore@0 216 if(layout.getChildAt(i) instanceof Button){
fiore@0 217 Button b = (Button)layout.getChildAt(i);
fiore@0 218 b.setOnClickListener(new View.OnClickListener() {
fiore@0 219 @Override
fiore@0 220 public void onClick(View v) {
fiore@0 221 buttonClickListener.onClick(v, AccessibleDialogFragment.this, getArguments().getString("tag"));
fiore@0 222 }
fiore@0 223 });
fiore@0 224 }
fiore@0 225 }
fiore@0 226
fiore@0 227 /* when showing a dialog a background sound is played in loop to notify the user they *
fiore@0 228 * have changed mode. More over the tag ( = the title) of the dialog is uttered out */
fiore@0 229 accessibilityService.playSound(SoundEvent.V_EDITING_MODE, true);
fiore@0 230 accessibilityService.speak(getArguments().getString("tag"));
fiore@0 231 return createdDialog;
fiore@0 232 }
fiore@0 233
fiore@0 234 @Override
fiore@0 235 public void onDismiss (DialogInterface dialog){
fiore@0 236 /* when the dialog is dismissed the ambient sound is stopped to *
fiore@0 237 * notify the userhe is back in the non edit mode */
fiore@0 238 accessibilityService.stopSound();
fiore@0 239 }
fiore@0 240
fiore@0 241 }
fiore@0 242
fiore@0 243 /**
fiore@0 244 * A listener for the click of buttons in the dialogs displayed through {@code AccessibleDialogBuilder}.
fiore@0 245 */
fiore@0 246 public interface ButtonClickListener {
fiore@0 247 /**
fiore@0 248 * When a button of a displayed dialog is clicked this method is called.
fiore@0 249 *
fiore@0 250 * @param v the clicked button
fiore@0 251 * @param dialogFragment the fragment used to show the dialog
fiore@0 252 * @param tag the tag of the dialog. Passed as argument to the display methods
fiore@0 253 */
fiore@0 254 public void onClick(View v, DialogFragment dialogFragment, String tag);
fiore@0 255 }
fiore@0 256
fiore@0 257 private static class AccessibleDialog extends AlertDialog {
fiore@0 258 AccessibilityService accessibilityService;
fiore@0 259 ViewGroup layout;
fiore@0 260
fiore@0 261 private AccessibleDialog(Context context, AccessibilityService accessibilityService, ViewGroup layout) {
fiore@0 262 super(context);
fiore@0 263 this.accessibilityService = accessibilityService;
fiore@0 264 this.layout = layout;
fiore@0 265 setView(layout);
fiore@0 266 }
fiore@0 267
fiore@0 268 @Override
fiore@0 269 public boolean dispatchTouchEvent(MotionEvent evt){
fiore@0 270 LayoutSonifier.getInstance().onTouch(layout, evt, accessibilityService);
fiore@0 271 return super.dispatchTouchEvent(evt);
fiore@0 272 }
fiore@1 273
fiore@1 274 @Override
fiore@1 275 public void onBackPressed(){
fiore@1 276 super.onBackPressed();
fiore@1 277 ILogger.logTap("back (cancel)");
fiore@1 278 }
fiore@0 279 }
fiore@0 280
fiore@0 281 }