package nliveroid.nlr.main;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.regex.Pattern;
import nliveroid.nlr.main.parser.XMLparser;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnShowListener;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TableLayout;
import android.widget.TextView;
public class EducationList extends Activity
implements OnClickListener {
private EducationList ACT;
private View parent;
private static final int SELECTED_BG_COLOR = Color.argb(128,255,255,255);
private static final int HOVER_BG_COLOR = Color.argb(128, 153,255,255);
private EducationArrayAdapter adapter = null;
private DragnDropListView listview;
private CheckBox chkSort;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.getWindow().requestFeature(Window.FEATURE_NO_TITLE);//requestFeature() must be called before adding content
parent = LayoutInflater.from(this).inflate(R.layout.education_list, null);
setContentView(parent);
ACT = this;
chkSort = (CheckBox) findViewById(R.id.chkSort);
chkSort.setOnClickListener(this);
//追加ボタン
Button addBt = (Button)findViewById(R.id.education_add);
addBt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//ダイアログ表示
final Dialog addDialog = new Dialog(ACT);
View dialogView = LayoutInflater.from(ACT).inflate(R.layout.education_add_dialog, null);
//KEY
final EditText keyEt = (EditText)dialogView.findViewById(R.id.education_addet_key);
final EditText valueEt = (EditText)dialogView.findViewById(R.id.education_addet_value);
//YES
Button yes = (Button)dialogView.findViewById(R.id.education_add_yes);
yes.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(keyEt.getText().toString().equals("")){
MyToast.customToastShow(ACT, "対象文字列を入力して下さい");
return;
}else if(keyEt.getText().toString().equals(valueEt.getText().toString())){
MyToast.customToastShow(ACT, "教育対象と違う文字列を入力して下さい");
return;
}
if(adapter == null)return;
//全く同じのをカット
String key = keyEt.getText().toString();
String value = valueEt.getText().toString();
String[] temp = null;
for(int i = 0; i < adapter.getCount(); i++){
temp = adapter.getItem(i);
if(temp[0].equals(key)){
MyToast.customToastShow(ACT, "同じ教育が既にあります");
return;
}
}
//Patternとして登録できるかチェック
try{
Pattern.compile(key);
}catch(Exception e){
e.printStackTrace();
MyToast.customToastShow(ACT, "正規表現のパターンとして登録できません");
return;
}
//変換文字列をマップに格納
//ファイルが無ければ生成
String filePath = getStorageFilePath();
if(filePath == null){
MyToast.customToastShow(ACT, "ストレージが利用できませんでした");
addDialog.dismiss();
return;
}
File file = new File(filePath,"Education.xml");
if(!file.exists()){
try {
file.createNewFile();
String xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"+
"<Education xmlns=\"http://nliveroid-tutorial.appspot.com/education/\">\n"+
"<data>\n" +
"<key>(http|https):([^\\x00-\\x20()\"<>\\x7F-\\xFF])*</key>\n" +
"<value>URL省略</value>\n"+
"</data>\n"+
"</Education>\n";
FileOutputStream fos = new FileOutputStream(file.getPath());
fos.write(xml.getBytes());
fos.close();
if(adapter != null){
adapter.add(new String[]{"(http|https):([^\\x00-\\x20()\"<>\\x7F-\\xFF])*", "URL省略"});
}
} catch (IOException e) {
e.printStackTrace();
MyToast.customToastShow(ACT, "ファイル生成に失敗しました");
addDialog.dismiss();
return;
}
}
//新たな入力を書き込む
if(adapter != null){
//表示する為のみなので<>エスケープしなくていい
adapter.add(new String[]{key,value});
//ファイルに保存する(エスケープしてる)
int returnValue = WriteEducation();
switch(returnValue){
case 0:
break;
case -1:
//画面回転でなっちゃうことがあるので無視
// MyToast.customToastShow(getApplication(), "保存する教育がありません");
break;
case -2:
MyToast.customToastShow(getApplication(), "保存に失敗\nストレージが利用できませんでした");
break;
case -3:
MyToast.customToastShow(getApplication(), "不明なエラーです");
break;
}
addDialog.dismiss();
}
}
});
//CANCEL
Button cancel = (Button)dialogView.findViewById(R.id.education_add_cancel);
cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
addDialog.dismiss();
}
});
//エディットテキストが伸びて行っちゃう対策
keyEt.setWidth(0);
valueEt.setWidth(0);
addDialog.setContentView(dialogView,new TableLayout.LayoutParams(-1,-1));
addDialog.setTitle("教育");
// addDialog.setOnShowListener(new OnShowListener(){
//
// @Override
// public void onShow(DialogInterface dialog) {
// Log.d("Log","DIALOG SHOW ------ " + addDialog.getWindow().getDecorView().getWidth());
// }
//
// });
addDialog.show();
}
});
//全て削除ボタン
Button allDelete = (Button)findViewById(R.id.education_all_delete);
allDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//アラート(本当に)
new AlertDialog.Builder(ACT)
.setMessage("教育ファイルを削除します\nよろしいですか?")
.setPositiveButton("YES", new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
if(adapter != null && adapter.getCount() > 0){
adapter.clear();
}
String filePath = getStorageFilePath();
if(filePath== null){
MyToast.customToastShow(ACT, "ストレージが利用できませんでした");
return;
}
File file = new File(filePath,"Education.xml");
file.delete();
}
})
.setNegativeButton("CANCEL",new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.create().show();
}
});
//ファイルから教育レコード読み込み
new EducationRead().execute();
}//End of onCreate
@Override
public void onClick(View v) {
boolean sortable = chkSort.isChecked();
listview.setSortMode(sortable);
}
class EducationArrayAdapter extends ArrayAdapter<String[]> implements SortableAdapter {
private LayoutInflater inflater;
private int selectedPosition = -1;
private int hoverPosition = -1;
public EducationArrayAdapter(Context context) {
super(context, R.layout.education_list_row);
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
ViewHolder holder = null;
if (convertView == null) {
view = inflater.inflate(R.layout.education_list_row, null);
holder = new ViewHolder();
holder.txtKey = (TextView) view.findViewById(R.id.txtString_key);
holder.txtValue = (TextView) view.findViewById(R.id.txtString_value);
view.setTag(holder);
} else {
view = convertView;
holder = (ViewHolder) view.getTag();
}
if (selectedPosition == hoverPosition) {
if (position == selectedPosition) {
view.setBackgroundColor(HOVER_BG_COLOR);
} else {
view.setBackgroundResource(android.R.drawable.list_selector_background);
}
} else {
if (position == selectedPosition) {
view.setBackgroundColor(SELECTED_BG_COLOR);
} else if (position == hoverPosition) {
view.setBackgroundColor(HOVER_BG_COLOR);
} else {
view.setBackgroundResource(android.R.drawable.list_selector_background);
}
}
String[] cellValue = getItem(position);
holder.txtKey.setText(cellValue[0]);
holder.txtValue.setText(cellValue[1]);
return view;
}
@Override
public void setSelectedPosition(int position) {
if (selectedPosition != position) {
selectedPosition = position;
notifyDataSetChanged();
}
}
@Override
public void setHoverPosition(int position) {
if (hoverPosition != position) {
hoverPosition = position;
notifyDataSetChanged();
}
}
}//End of EducationArrayAdapter
class ViewHolder {
TextView txtKey;
TextView txtValue;
}
/**
* コンテキストメニュー生成時処理
*/
@Override
public void onCreateContextMenu(ContextMenu menu, View view,
ContextMenuInfo info) {
super.onCreateContextMenu(menu, view, info);
final AdapterContextMenuInfo adapterInfo = (AdapterContextMenuInfo) info;
if(adapter == null || adapter.getCount() < adapterInfo.position){//立見などをタップした時におかしくなるArrayList.throwIndexOutOfBoundsException
return;
}
final String[] row = adapter.getItem(adapterInfo.position);
menu.add("編集");
menu.getItem(0).setOnMenuItemClickListener(
new OnMenuItemClickListener() {
@Override
// 引数はメニューのテキスト
public boolean onMenuItemClick(MenuItem arg0) {
//ダイアログ表示
final Dialog addDialog = new Dialog(ACT);
View dialogView = LayoutInflater.from(ACT).inflate(R.layout.education_add_dialog, null);
//KEY
final EditText keyEt = (EditText)dialogView.findViewById(R.id.education_addet_key);
final EditText valueEt = (EditText)dialogView.findViewById(R.id.education_addet_value);
keyEt.setText(row[0] == null? "":row[0]);
valueEt.setText(row[1]==null? "":row[1]);
//YES
Button yes = (Button)dialogView.findViewById(R.id.education_add_yes);
yes.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(keyEt.getText().toString().equals("")){
MyToast.customToastShow(ACT, "対象文字列を入力して下さい");
return;
}else if(keyEt.getText().toString().equals(valueEt.getText().toString())){
MyToast.customToastShow(ACT, "教育対象と違う文字列を入力して下さい");
return;
}
if(adapter == null)return;
//Patternとして登録できるかチェック
try{
Pattern.compile(keyEt.getText().toString());
}catch(Exception e){
e.printStackTrace();
MyToast.customToastShow(ACT, "正規表現のパターンとして登録できません");
return;
}
//変換文字列をマップに格納
//ファイルが無ければ生成
String filePath = getStorageFilePath();
if(filePath == null){
MyToast.customToastShow(ACT, "ストレージが利用できませんでした");
addDialog.dismiss();
return;
}
File file = new File(filePath,"Education.xml");
if(!file.exists()){
try {
file.createNewFile();
String xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"+
"<Education xmlns=\"http://nliveroid-tutorial.appspot.com/education/\">\n"+
"<data>\n" +
"<key>(http|https):([^\\x00-\\x20()\"<>\\x7F-\\xFF])*</key>\n" +
"<value>URL省略</value>\n"+
"</data>\n"+
"</Education>\n";
FileOutputStream fos = new FileOutputStream(file.getPath());
fos.write(xml.getBytes());
fos.close();
if(adapter != null){
adapter.add(new String[]{"(http|https):([^\\x00-\\x20()\"<>\\x7F-\\xFF])*", "URL省略"});
}
} catch (IOException e) {
e.printStackTrace();
MyToast.customToastShow(ACT, "ファイル生成に失敗しました");
addDialog.dismiss();
return;
}
}
//編集を対象に保存
if(adapter != null){
//表示する為のみなのでエスケープしなくていい
adapter.remove(row);
adapter.insert(new String[]{keyEt.getText().toString(),valueEt.getText().toString()},adapterInfo.position);
//ファイルに書き込む(エスケープしてる)
int returnValue = WriteEducation();
switch(returnValue){
case 0:
break;
case -1:
//画面回転でなっちゃうことがあるので無視
// MyToast.customToastShow(getApplication(), "保存する教育がありません");
break;
case -2:
MyToast.customToastShow(getApplication(), "保存に失敗\nストレージが利用できませんでした");
break;
case -3:
MyToast.customToastShow(getApplication(), "不明なエラーです");
break;
}
addDialog.dismiss();
}
}
});
//CANCEL
Button cancel = (Button)dialogView.findViewById(R.id.education_add_cancel);
cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
addDialog.dismiss();
}
});
addDialog.setContentView(dialogView,new TableLayout.LayoutParams(-1,-1));
addDialog.setTitle("教育");
addDialog.show();
return false;
}
});
menu.add("忘却");
menu.getItem(1).setOnMenuItemClickListener(
new OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuitem) {
//onStopで書き込むのでファイルからまだ消さなくていい
new AlertDialog.Builder(ACT)
.setMessage("忘却しますか?")
.setPositiveButton("YES", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
adapter.remove(row);
//ファイルに書き込んじゃう
WriteEducation();
}
})
.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.create().show();
return false;
}
});
}//End of onCreateContextMenu
class EducationRead extends AsyncTask<Void,Void,ArrayList<String>>{
private LinkedHashMap<String,String> educationList;
@Override
protected ArrayList<String> doInBackground(Void... arg0) {
educationList = new LinkedHashMap<String, String>();
//ファイルを読み込む
ArrayList<String> result = new ArrayList<String>();
String filePath = getStorageFilePath();
if(filePath == null){
result.add("-1");
return result;
}
File file = new File(filePath,"Education.xml");
if(!file.exists()){
try {
file.createNewFile();//ファイル無ければテンプレ作成
Log.d("Log","EDUCATION CREATGED ---- ");
String xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"+
"<Education xmlns=\"http://nliveroid-tutorial.appspot.com/education/\">\n"+
"<data>\n" +
"<key>(http|https):([^\\x00-\\x20()\"<>\\x7F-\\xFF])*</key>\n" +
"<value>URL省略</value>\n"+
"</data>\n"+
"<data>\n" +
"<key>^/.+</key>\n" +
"<value></value>\n"+
"</data>\n"+
"</Education>\n";
FileOutputStream fos = new FileOutputStream(file.getPath());
fos.write(xml.getBytes());
fos.close();
educationList.put("(http|https):([^\\x00-\\x20()\"<>\\x7F-\\xFF])*", "URL省略");
result.add("1");
return result;
//リストを生成(if文を抜ける)
} catch (FileNotFoundException e) {
e.printStackTrace();
result.add("-2");
return result;
} catch (IOException e) {
e.printStackTrace();
result.add("-3");
return result;
}
}else{//ファイルあった
ArrayList<String> resultList = new ArrayList<String>();
byte[] data = new byte[(int)((file).length())];
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
fis.read(data);
fis.close();
int parseError = XMLparser.parseLiveEducation(data,educationList);
if(parseError == -1){
resultList.add("-4");
return resultList;
}else if(parseError == -2){
resultList.add("-5");
return resultList;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
resultList.add("-2");
return resultList;
} catch (IOException e) {
resultList.add("-3");
return resultList;
}
//教育ファイル読み込み成功
//リストを生成(if文を抜ける)
}
//リスト生成
return null;
}
@Override
protected void onPostExecute(ArrayList<String> arg){
if(parent != null){
ProgressBar p = (ProgressBar)parent.findViewById(R.id.education_init_progressbar);
p.setVisibility(View.GONE);
}
if(arg == null){
//読み込み成功
adapter = new EducationArrayAdapter(ACT);
Iterator<String> it = educationList.keySet().iterator();
String tempKey = "";
while(it.hasNext()){
tempKey = it.next();
adapter.add(new String[]{tempKey,educationList.get(tempKey)});
}
listview = (DragnDropListView) findViewById(R.id.list);
//XMLじゃできなかった
listview.setFastScrollEnabled(true);
listview.setAdapter(adapter);
ACT.registerForContextMenu(listview);
}else if(arg.size() > 0){
if(arg.get(0).equals("1")){
//一番初期に、生成してアダプタ追加
MyToast.customToastShow(ACT, "教育ファイル生成しました");
adapter = new EducationArrayAdapter(ACT);
Iterator<String> it = educationList.keySet().iterator();
String tempKey = "";
while(it.hasNext()){
tempKey = it.next();
adapter.add(new String[]{tempKey,educationList.get(tempKey)});
}
listview = (DragnDropListView) findViewById(R.id.list);
listview.setAdapter(adapter);
ACT.registerForContextMenu(listview);
}else if(arg.get(0).equals("-1")){
MyToast.customToastShow(ACT, "ストレージが利用できませんでした");
}else if(arg.get(0).equals("-2")||arg.get(0).equals("-3")){
MyToast.customToastShow(ACT, "ファイルIOに失敗しました");
}else if(arg.get(0).equals("-4")||arg.get(0).equals("-5")){
MyToast.customToastShow(ACT, "教育ファイルの記述がおかしい");
}
}
}
}
private String getStorageFilePath(){
boolean isStorageAvalable = false;
boolean isStorageWriteable = false;
String state = Environment.getExternalStorageState();
if(state == null){
return null;
}else if (Environment.MEDIA_MOUNTED.equals(state)) {
//読み書きOK
isStorageAvalable = isStorageWriteable = true;
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
//読み込みだけOK
isStorageAvalable = true;
isStorageWriteable = false;
} else {
//ストレージが有効でない
isStorageAvalable = isStorageWriteable = false;
}
boolean notAvalable = !isStorageAvalable;
boolean notWritable = !isStorageWriteable;
if(notAvalable||notWritable){
return null;
}
//sdcard直下に、パッケージ名のフォルダを作りファイルを生成
String filePath = Environment.getExternalStorageDirectory().toString() + "/NLiveRoid";
File directory = new File(filePath);
if(directory.mkdirs()){//すでにあった場合も失敗する
Log.d("log","mkdir");
}
return filePath;
}
/**
* 今ある教育を保存する!!
*
*/
public int WriteEducation(){
if(adapter == null)return -1;
String filePath = getStorageFilePath();
if(filePath == null){
return -2;
}
File file = new File(filePath,"Education.xml");
if(!file.exists()){
//ファイル無ければなにかがおかしいので終了
return -3;
}
String xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"+
"<Education xmlns=\"http://nliveroid-tutorial.appspot.com/education/\">\n";
String[] tempStr = null;
for(int i = 0; i< adapter.getCount(); i++){
tempStr = adapter.getItem(i);
Log.d("LIST -- " , " " +tempStr[0]);
xml += "<data>\n" +
"<key>"+tempStr[0].replaceAll("<", "<")+"</key>\n"+
"<value>"+tempStr[1].replaceAll(">", ">")+"</value>\n" +
"</data>";
}
xml += "</Education>\n";
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file.getPath());
fos.write(xml.getBytes());
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return 0;
}
}//End of EducationList Activity
class DragnDropListView extends ListView {
private static final boolean DEBUG = false;
private static final int SCROLL_SPEED_FAST = 25;
private static final int SCROLL_SPEED_SLOW = 8;
private static final int MOVING_ITEM_BG_COLOR = Color.argb(128, 0, 0, 0);
private static final int HOVER_REMOVE_ITEM_BG_COLOR = Color.argb(200, 255, 0, 0);
private EducationList calledClass;
private static final String TAG = DragnDropListView.class.getSimpleName();
private boolean sortMode = false;
private DragListener mDrag = new DragListenerImpl();
private DropListener mDrop = new DropListenerImpl();
private RemoveListener mRemove = new RemoveListenerImpl();
public DragnDropListView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DragnDropListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
calledClass = (EducationList)context;
}
private SortableAdapter adapter;
private Bitmap mDragBitmap = null;
private ImageView mDragView = null;
private WindowManager.LayoutParams mWindowParams = null;
private int mFrom = -1;
private View mRemoveTile = null;
private Rect mRemoveHit = null;
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!sortMode) {
return super.onTouchEvent(event);
}
int index = -1;
final int x = (int) event.getX();
final int y = (int) event.getY();
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN) {
index = pointToIndex(event);
if (index < 0) {
return false;
}
mFrom = index;
startDrag();
adapter.setSelectedPosition(index);
return true;
} else if (action == MotionEvent.ACTION_MOVE) {
final int height = getHeight();
final int fastBound = height / 9;
final int slowBound = height / 4;
final int center = height / 2;
int speed = 0;
if (event.getEventTime() - event.getDownTime() < 500) {
// 500ミリ秒間はスクロールなし
} else if (y < slowBound) {
speed = y < fastBound ? -SCROLL_SPEED_FAST : -SCROLL_SPEED_SLOW;
} else if (y > height - slowBound) {
speed = y > height - fastBound ? SCROLL_SPEED_FAST : SCROLL_SPEED_SLOW;
}
if (DEBUG) {
Log.d(TAG, "ACTION_MOVE y=" + y + ", height=" + height + ", fastBound=" + fastBound + ", slowBound=" + slowBound + ", center=" + center + ", speed=" + speed);
}
View v = null;
if (speed != 0) {
// 横方向はとりあえず考えない
int centerPosition = pointToPosition(0, center);
if (centerPosition == AdapterView.INVALID_POSITION) {
centerPosition = pointToPosition(0, center + getDividerHeight() + 64);
}
v = getChildByIndex(centerPosition);
if (v != null) {
int pos = v.getTop();
setSelectionFromTop(centerPosition, pos - speed);
}
}
if (mDragView != null) {
if (mDragView.getHeight() < 0) {
mDragView.setVisibility(View.INVISIBLE);
} else {
mDragView.setVisibility(View.VISIBLE);
if (this.isHitRemoveTile(x, y)) {
mDragView.setBackgroundColor(HOVER_REMOVE_ITEM_BG_COLOR);
} else {
mDragView.setBackgroundColor(MOVING_ITEM_BG_COLOR);
}
}
mWindowParams.x = getLeft();
mWindowParams.y = getTop() + y;
WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
wm.updateViewLayout(mDragView, mWindowParams);
if (mDrag != null) {
index = pointToIndex(event);
mDrag.drag(mFrom, index);
}
adapter.setHoverPosition(index);
return true;
}
} else if (action == MotionEvent.ACTION_UP) {
if (isHitRemoveTile(x, y)) {
// 削除イメージにヒットしていた場合、削除する
if (mRemove != null)
mRemove.remove(mFrom);
} else {
// 削除イメージにヒットしていなければ、要素の入れ替えをする
if (mDrop != null) {
index = pointToIndex(event);
mDrop.drop(mFrom, index);
}
}
// ドラッグ中の項目の表示を削除する
endDrag();
adapter.setHoverPosition(-1);
adapter.setSelectedPosition(-1);
return true;
} else if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_OUTSIDE) {
// ドラッグ中の項目の表示を削除する
endDrag();
adapter.setHoverPosition(-1);
adapter.setSelectedPosition(-1);
return true;
} else {
Log.d(TAG, "Unknown event action=" + action);
}
return super.onTouchEvent(event);
}
/**
* ドラッグを開始したときに呼び出される<br />
* ドラッグ中の項目を表示する
*/
private void startDrag() {
WindowManager wm;
View view = getChildByIndex(mFrom);
final Bitmap.Config c = Bitmap.Config.ARGB_8888;
mDragBitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), c);
Canvas canvas = new Canvas();
canvas.setBitmap(mDragBitmap);
view.draw(canvas);
if (mWindowParams == null) {
mWindowParams = new WindowManager.LayoutParams();
mWindowParams.gravity = Gravity.TOP | Gravity.LEFT;
mWindowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
mWindowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
mWindowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
mWindowParams.format = PixelFormat.TRANSLUCENT;
mWindowParams.windowAnimations = 0;
mWindowParams.x = 0;
mWindowParams.y = 0;
}
ImageView v = new ImageView(getContext());
v.setBackgroundColor(MOVING_ITEM_BG_COLOR);
v.setImageBitmap(mDragBitmap);
wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
if (mDragView != null) {
wm.removeView(mDragView);
}
wm.addView(v, mWindowParams);
mDragView = v;
}
/**
* ドラッグアンドドロップが終了したときに呼び出される<br />
* ドラッグ中の項目の表示を削除する
*/
private void endDrag() {
if (mDragView == null) {
return;
}
WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
wm.removeView(mDragView);
mDragView = null;
// リサイクルするとたまに死ぬけどタイミング分からない
// Desireでおきる。ht-03aだと発生しない
// mDragBitmap.recycle();
mDragBitmap = null;
}
/**
* 指定された座標が削除画像に被っているか返す
*
* @param x
* @param y
* @return
*/
private boolean isHitRemoveTile(int x, int y) {
if (mRemoveTile != null && mRemoveTile.getVisibility() == View.VISIBLE) {
if (mRemoveHit == null) {
mRemoveHit = new Rect();
}
mRemoveTile.getHitRect(mRemoveHit);
if (mRemoveHit.contains(x + getLeft(), y + getTop())) {
return true;
} else {
return false;
}
} else {
return false;
}
}
/**
* 指定された要素番号のViewを返す<br />
* 要素番号はソースとなるListの要素番号を指定する
*
* @param index
* @return
*/
private View getChildByIndex(int index) {
return getChildAt(index - getFirstVisiblePosition());
}
/**
* MotionEventから要素番号に変換する
*
* @param ev
* @return
*/
private int pointToIndex(MotionEvent event) {
return pointToIndex((int) event.getX(), (int) event.getY());
}
/**
* 座標から要素番号に変換する
*
* @param x
* @param y
* @return
*/
private int pointToIndex(int x, int y) {
return (int) pointToPosition(x, y);
}
/**
* 削除画像の設定
*
* @param v
*/
public void setRemoveTile(View v) {
mRemoveTile = v;
}
public void setOnDragListener(DragListener listener) {
mDrag = listener;
}
public void setOnDropListener(DragListener listener) {
mDrag = listener;
}
public void setOnRemoveListener(RemoveListener listener) {
mRemove = listener;
}
class DragListenerImpl implements DragListener {
public void drag(int from, int to) {
if (DEBUG) {
Log.d(TAG, "DragListenerImpl drag event. from=" + from + ", to=" + to);
}
}
}
public class DropListenerImpl implements DropListener {
@SuppressWarnings("unchecked")
public void drop(int from, int to) {
if (DEBUG) {
Log.d(TAG, "DropListenerImpl drop event. from=" + from + ", to=" + to);
}
if (from == to || from < 0 || to < 0) {
return;
}
Adapter adapter = getAdapter();
if (adapter != null && adapter instanceof ArrayAdapter) {
ArrayAdapter arrayAdapter = (ArrayAdapter) adapter;
Object item = adapter.getItem(from);
arrayAdapter.remove(item);
arrayAdapter.insert(item, to);
//ファイルに書き込んじゃう
calledClass.WriteEducation();
}
}
}
public class RemoveListenerImpl implements RemoveListener {
@SuppressWarnings("unchecked")
public void remove(int which) {
if (DEBUG) {
Log.d(TAG, "RemoveListenerImpl remove event. which=" + which);
}
if (which < 0) {
return;
}
Adapter adapter = getAdapter();
if (adapter != null && adapter instanceof ArrayAdapter) {
ArrayAdapter arrayAdapter = (ArrayAdapter) adapter;
Object item = adapter.getItem(which);
arrayAdapter.remove(item);
}
}
}
/**
* 並び替えをするかを設定する
*
* @param sortMode
*/
public void setSortMode(boolean sortMode) {
this.sortMode = sortMode;
}
/**
* 並び替えをするかを返す
*
* @return
*/
public boolean isSortMode() {
return sortMode;
}
/**
* ListViewにAdapterを設定する<br />
* Sortableを実装したAdapter以外を受け付けません
*
* @param adapter
*/
@Override
public void setAdapter(ListAdapter adapter) {
if (adapter instanceof SortableAdapter) {
this.adapter = (SortableAdapter) adapter;
super.setAdapter(adapter);
} else {
throw new RuntimeException("Sortable未実装");
}
}
}//End of DragnDropListView
interface DragListener {
public void drag(int from, int to);
}
interface DropListener {
public void drop(int from, int to);
}
interface RemoveListener {
public void remove(int which);
}
interface SortableAdapter {
void setSelectedPosition(int position);
String[] getItem(int i);
int getCount();
void setHoverPosition(int position);
}