//
// anyRemote android client
// a bluetooth/wi-fi remote control for Linux.
//
// Copyright (C) 2011-2016 Mikhail Fedotov <anyremote@mail.ru>
//
// 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, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
package anyremote.client.android;
import java.util.ArrayList;
import android.os.Bundle;
import android.os.Handler;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.TextView;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.GestureDetector.OnGestureListener;
import android.view.GestureDetector;
import anyremote.client.android.util.ListScreenAdapter;
import anyremote.client.android.util.ListItem;
import anyremote.client.android.util.InfoMessage;
import anyremote.client.android.util.ProtocolMessage;
import anyremote.client.android.R;
public class ListScreen extends arActivity
implements OnItemClickListener,
AdapterView.OnItemSelectedListener,
KeyEvent.Callback,
OnGestureListener {
ListView list;
ListScreenAdapter dataSource;
Dispatcher.ArHandler hdlLocalCopy;
ArrayList<ListItem> listItems;
boolean skipDismissEditDialog = false;
private GestureDetector gestureScanner;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
prefix = "ListScreen"; // log stuff
log("onCreate");
listItems = new ArrayList<ListItem>();
dataSource = new ListScreenAdapter(this, R.layout.list_form_item, listItems);
hdlLocalCopy = new Dispatcher.ArHandler(anyRemote.LIST_FORM, new Handler(this));
anyRemote.protocol.addMessageHandler(hdlLocalCopy);
setContentView(R.layout.list_form);
list = (ListView) findViewById(R.id.list_form);
list.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
list.setAdapter(dataSource);
list.setOnItemSelectedListener(this);
list.setOnItemClickListener (this);
gestureScanner = new GestureDetector(this);
registerForContextMenu(list);
}
@Override
protected void onPause() {
log("onPause");
hidePopup();
super.onPause();
}
@Override
protected void onResume() {
log("onResume");
super.onResume();
if (anyRemote.status == anyRemote.DISCONNECTED) {
log("onResume no connection");
doFinish("");
}
//log("onResume UPDATE DATA SOURCE");
dataSource.update(anyRemote.protocol.listContent, anyRemote.protocol.listIcon);
//log("onResume notifyDataSetChanged");
dataSource.notifyDataSetChanged();
redraw();
exiting = false;
}
@Override
protected void onDestroy() {
log("onDestroy");
anyRemote.protocol.removeMessageHandler(hdlLocalCopy);
super.onDestroy();
}
//@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
//log("onItemClick "+arg2);
//list.setSelection(arg2);
//select(arg2);
final String itemText = (arg2 == -1 ? "" : dataSource.getItem(arg2).text);
commandAction("Push", itemText, arg2);
}
// Handle long-click
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
if (v.getId() == R.id.list_form) {
final AdapterContextMenuInfo info = (AdapterContextMenuInfo)menuInfo;
final TextView tv= (TextView) info.targetView.findViewById(R.id.list_item_text);
menu.setHeaderTitle(tv.getText());
addContextMenu(menu);
}
}
// Handle context menu, opened by long-click
@Override
public boolean onContextItemSelected(MenuItem item) {
final AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
final String itemText = dataSource.getItem(info.position).text;
commandAction(item.getTitle().toString(), itemText, info.position);
return super.onContextItemSelected(item);
}
@Override
protected void doFinish(String action) {
log("doFinish");
exiting = true;
finish();
}
/*@Override
public void onBackPressed() {
final String itemText = (selectedPosition == -1 ? "" : dataSource.getItem(selectedPosition).text);
commandAction(anyRemote.protocol.context.getString(R.string.back_item), itemText, selectedPosition);
}*/
// Selection handlers
//@Override
public void onItemSelected(AdapterView<?> parentView, View childView, int position, long id) {
anyRemote.protocol.listSelectPos = position;
selectUpdate();
}
//@Override
public void onNothingSelected(AdapterView<?> parentView) {
anyRemote.protocol.listSelectPos = -1;
}
public void selectUpdate() {
if (anyRemote.protocol.listSelectPos > 0) {
dataSource.setSelectedPosition(anyRemote.protocol.listSelectPos);
if (anyRemote.protocol.listCustomTextColor && anyRemote.protocol.listCustomBackColor) {
dataSource.notifyDataSetChanged();
}
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
//log("dispatchTouchEvent");
super.dispatchTouchEvent(ev);
return gestureScanner.onTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent me) {
return gestureScanner.onTouchEvent(me);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
log("onOptionsItemSelected "+anyRemote.protocol.listSelectPos);
final String itemText = (anyRemote.protocol.listSelectPos == -1 ? "" : dataSource.getItem(anyRemote.protocol.listSelectPos).text);
commandAction(item.getTitle().toString(), itemText, anyRemote.protocol.listSelectPos);
return true;
}
@Override
protected void onUserLeaveHint() {
log("onUserLeaveHint");
if (!exiting && anyRemote.protocol.messageQueueSize() == 0) {
log("onUserLeaveHint - make disconnect");
anyRemote.protocol.disconnect(false);
}
}
public void commandAction(String command, String value, int pos) {
if (command.equals(anyRemote.protocol.context.getString(R.string.back_item))) {
command = "Back"; // avoid national alphabets
}
anyRemote.protocol.queueCommand(command +
"(" + String.valueOf(pos+1) + "," + value + ")");
}
public void handleEvent(InfoMessage data) {
log("handleEvent " + Dispatcher.cmdStr(data.id) + " " + data.stage);
checkPopup();
if (data.stage == ProtocolMessage.FULL || data.stage == ProtocolMessage.FIRST) {
if (handleCommonCommand(data.id)) {
return;
}
// get info about data update
if (data.id == Dispatcher.CMD_LIST_UPDATE ||
data.id == Dispatcher.CMD_IMAGE || // some icon was uploaded, need to redraw
data.id == Dispatcher.CMD_REPAINT) {
dataSource.update(anyRemote.protocol.listContent, anyRemote.protocol.listIcon);
dataSource.notifyDataSetChanged();
}
// update all visuals
redraw();
} else if (data.stage == ProtocolMessage.INTERMED || data.stage == ProtocolMessage.LAST) {
dataSource.update(anyRemote.protocol.listContent, anyRemote.protocol.listIcon);
dataSource.notifyDataSetChanged();
}
// on update data
// + set title
// + select by index, if it >= 0
}
// update all visuals
void redraw() {
anyRemote.protocol.setFullscreen(this);
setTitle(anyRemote.protocol.listTitle);
if (anyRemote.protocol.listFSize > 0) {
dataSource.setFont(anyRemote.protocol.listFSize);
}
if (anyRemote.protocol.listCustomBackColor) {
//log("handleEvent setBackColor "+anyRemote.protocol.listBkgr);
dataSource.setBackColor(anyRemote.protocol.listBkgr);
list.setBackgroundColor(anyRemote.protocol.listBkgr);
}
if (anyRemote.protocol.listCustomTextColor) {
//log("handleEvent setTextColor "+anyRemote.protocol.listText);
dataSource.setTextColor(anyRemote.protocol.listText);
}
selectUpdate();
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
boolean lp = longPress;
longPress = false;
switch (keyCode) {
case KeyEvent.KEYCODE_CALL:
case KeyEvent.KEYCODE_SEARCH:
final String itemTextC = (anyRemote.protocol.listSelectPos == -1 ? "" :
dataSource.getItem(anyRemote.protocol.listSelectPos).text);
commandAction("Push", itemTextC, anyRemote.protocol.listSelectPos);
return true;
case KeyEvent.KEYCODE_BACK:
if (event.isTracking() && !event.isCanceled() && lp) {
log("onKeyUp KEYCODE_BACK long press - show menu");
new Handler().postDelayed(new Runnable() {
public void run() {
openOptionsMenu();
}
}, 1000);
return true;
}
final String itemTextB = (anyRemote.protocol.listSelectPos == -1 ? "" :
dataSource.getItem(anyRemote.protocol.listSelectPos).text);
commandAction("Back", itemTextB, anyRemote.protocol.listSelectPos);
return true;
case KeyEvent.KEYCODE_VOLUME_UP:
if (anyRemote.protocol.listSelectPos > 0) {
anyRemote.protocol.listSelectPos--;
}
dataSource.setSelectedPosition(anyRemote.protocol.listSelectPos);
list.setSelection(anyRemote.protocol.listSelectPos);
//selectUpdate();
return true;
case KeyEvent.KEYCODE_VOLUME_DOWN:
if (anyRemote.protocol.listSelectPos < dataSource.size() - 1) {
anyRemote.protocol.listSelectPos++;
}
//log("onKeyUp KEYCODE_VOLUME_DOWN "+anyRemote.protocol.listSelectPos);
dataSource.setSelectedPosition(anyRemote.protocol.listSelectPos);
list.setSelection(anyRemote.protocol.listSelectPos);
//selectUpdate();
return true;
}
return false;
}
@Override
public boolean onKeyDown (int keyCode, KeyEvent event) {
//log("onKeyDown "+keyCode);
switch (keyCode) {
case KeyEvent.KEYCODE_CALL:
case KeyEvent.KEYCODE_SEARCH:
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_DOWN:
return true;
case KeyEvent.KEYCODE_BACK:
event.startTracking();
return true;
}
return false;
}
public boolean onDown(MotionEvent e) {
//log("onDown");
return true;
}
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
//log("onFling " + e1.getX() + " " + e1.getY() + " "
// + e2.getX() + " " + e2.getY() + " "
// + velocityX + " " + velocityY);
try {
// right to left swipe
if (e1.getX() - e2.getX() > anyRemote.SWIPE_MIN_DISTANCE &&
Math.abs(velocityX) > anyRemote.SWIPE_THRESHOLD_VELOCITY) {
commandAction("ListSlideLeft","",-1);
} else if (e2.getX() - e1.getX() > anyRemote.SWIPE_MIN_DISTANCE &&
Math.abs(velocityX) > anyRemote.SWIPE_THRESHOLD_VELOCITY) {
commandAction("ListSlideRight","",-1);
} else {
return false;
}
} catch (Exception e) {
// nothing
}
return true;
}
public void onLongPress(MotionEvent e) {
//log("onLongPress");
}
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
//log("onScroll");
return true;
}
public void onShowPress(MotionEvent e) {
//log("onShowPress");
}
public boolean onSingleTapUp(MotionEvent e) {
//log("onSingleTapUp");
return true;
}
}