view src/uk/ac/qmul/eecs/ccmi/activities/AccessibleActivity.java @ 0:e0ee6ac3a45f

first import
author Fiore Martin <fiore@eecs.qmul.ac.uk>
date Thu, 13 Dec 2012 20:00:21 +0000
parents
children 66b3a838feca
line wrap: on
line source
/*  
 CCmI Diagram Editor for Android 
  
 Copyright (C) 2012  Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/)

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package uk.ac.qmul.eecs.ccmi.activities;

import uk.ac.qmul.eecs.ccmi.accessibility.AccessibilityService;
import uk.ac.qmul.eecs.ccmi.accessibility.AccessibilityService.SoundEvent;
import uk.ac.qmul.eecs.ccmi.accessibility.AccessibleDialogBuilder;
import uk.ac.qmul.eecs.ccmi.accessibility.LayoutSonifier;
import android.content.pm.PackageManager;
import android.media.AudioManager;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;

/**
 * An abstract accessible activity, displaying items of a list in a ListView and a text header.
 */
public abstract class AccessibleActivity extends FragmentActivity {
	private TextView header;
	private ViewGroup mainLayout;
	private Button scrollButton;
	private boolean activityNameUttered = false;

	/**
	 * the class used to generate audio and tactile cues when exploring the activity  
	 */
	protected AccessibilityService accessibilityService;
	/**
	 * The list item list of the activity 
	 */
	protected ListView list;
	/**
	 * used to generate dialogs when the user clicks or long-clicks on an item
	 */
	protected AccessibleDialogBuilder dialogBuilder;  
	
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// Set the hardware buttons to control the music 
		this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
		
		/* makes the activity run on a full screen. */
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
				WindowManager.LayoutParams.FLAG_FULLSCREEN);
		mainLayout = (ViewGroup)getLayoutInflater().inflate(R.layout.main, null);
		setContentView(mainLayout);

		dialogBuilder = new AccessibleDialogBuilder(this.getSupportFragmentManager());
		
		/* place the main list in the view */
		LinearLayout listLayout = (LinearLayout)findViewById(R.id.listView1); 
		/* avoid scrolling upon touching, we rather want the user to hear the content */
		list = new ListView(this){
			@Override
			public boolean dispatchTouchEvent(MotionEvent ev){
				//returning true prevents the scrolling action on the listview
				if(ev.getAction()==MotionEvent.ACTION_MOVE && ev.getPointerCount() == 1)
					return true;
				return super.dispatchTouchEvent(ev);
			}
			
			@Override
			public void	setAdapter(final ListAdapter adapter){
				super.setAdapter(adapter);
				if(scrollButton != null){
					post(new Runnable(){ // need to be posted in order to work, as the list is not rendered yet at this point
						public void run(){
							boolean thereIsMore = (list.getLastVisiblePosition() < adapter.getCount()-1);
							scrollButton.setEnabled(thereIsMore);
							scrollButton.setContentDescription(
									thereIsMore ? "scroll button" : "scroll button disabled");
						}
					});
				}
			}
		};
		list.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
		listLayout.addView(list);
	
		/* init header with a button to scroll down an up the list */
		header = (TextView)findViewById(R.id.txtHeader);
		scrollButton = (Button)findViewById(R.id.scrollButton);
		
		/* if the device supports double finger touch screen then the user will scroll by 
		 * swiping with two fingers. Otherwise a button at the very bottom will be created that will scroll the
		 * list of one item each time it's pressed and when the bottom is reached it will scroll up to the top.
		 */
		if(getPackageManager().hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH)){
			mainLayout.removeView(scrollButton);
			scrollButton = null;
		}else{ 
			scrollButton.setOnClickListener(new View.OnClickListener() {
				boolean doOnceMore = true;
	
				@Override
				public void onClick(View v) {
					if(list.getLastVisiblePosition() == list.getCount()-1){
						/* when the last item becomes visible it's not entirely visible. So don't go immediately * 
						 * to the top but let the user scroll once more and make it entirely visible             */
						if(doOnceMore){
							doOnceMore = false;
							accessibilityService.playSound(SoundEvent.V_OK, false);
							list.smoothScrollToPosition(list.getLastVisiblePosition());
							scrollButton.setText(R.string.scrollBtnUp);
						}else{
							doOnceMore = true;
							accessibilityService.playSound(SoundEvent.V_ENDOFLIST, false);
							list.smoothScrollToPosition(0);
							scrollButton.setText(R.string.scrollBtnDown);
						}
					}else{
						accessibilityService.playSound(SoundEvent.V_OK, false);
						list.smoothScrollToPosition(list.getLastVisiblePosition());
					}
				}
			});
		}
	}
	
	@Override
	protected void onResume(){
		super.onResume();
		accessibilityService = new AccessibilityService(this);
		accessibilityService.loadSounds();
		dialogBuilder.setAccessibilityService(accessibilityService);
		
	}
	
	/**
	 * When the activity is resumed the header text is uttered thought the text to speech sinthesizer
	 */
	@Override
	public void  onPostResume(){
		super.onPostResume();
		header.post(new Runnable(){
			@Override
			public void run() {
				if(!activityNameUttered){
					accessibilityService.speak(getName()+". Displaying "+getHeaderText());
					activityNameUttered = true;
				}else{
					accessibilityService.speak("Displaying "+getHeaderText());
				}
			}
		});
	}
	
	@Override
	protected void onPause(){
		super.onPause();
		accessibilityService.stopSound();
		accessibilityService.dispose();
		dialogBuilder.setAccessibilityService(null);
	}
	
	@Override
	public boolean dispatchTouchEvent(MotionEvent evt){
		//returning true prevents the scrolling action on the listview
		if(evt.getAction()==MotionEvent.ACTION_MOVE && evt.getPointerCount() == 1){
			LayoutSonifier.getInstance().onTouch(mainLayout, evt, accessibilityService);
			return true;
		}
		
		if(evt.getAction() == MotionEvent.ACTION_UP)
			LayoutSonifier.getInstance().onTouch(mainLayout, evt, accessibilityService);
		return super.dispatchTouchEvent(evt);
	}

	/**
	 * Set the header text. The text is uttered when the user hover over the header. 
	 * 
	 * @param headerText the header text 
	 */
	protected void setHeaderText(CharSequence headerText){
		header.setText(headerText);
	}
	
	/**
	 * Returns the header text. The text is uttered when the user hover over the header.
	 * 
	 * @return the header text
	 */
	protected CharSequence getHeaderText(){
		return header.getText();
	}
	
	public abstract String getName();
}