/*
* Tencent is pleased to support the open source community by making
* Tencent GT (Version 2.4 and subsequent versions) available.
*
* Notwithstanding anything to the contrary herein, any previous version
* of Tencent GT shall not be subject to the license hereunder.
* All right, title, and interest, including all intellectual property rights,
* in and to the previous version of Tencent GT (including any and all copies thereof)
* shall be owned and retained by Tencent and subject to the license under the
* Tencent GT End User License Agreement (http://gt.qq.com/wp-content/EULA_EN.html).
*
* Copyright (C) 2015 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the MIT License (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://opensource.org/licenses/MIT
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.wstt.gt.activity;
import java.util.Iterator;
import java.util.LinkedList;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Filter;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import com.tencent.wstt.gt.R;
import com.tencent.wstt.gt.log.GTLogInternal;
import com.tencent.wstt.gt.log.SearchLogAdapter;
import com.tencent.wstt.gt.log.logcat.SaveLogHelper;
import com.tencent.wstt.gt.ui.model.LogEntry;
public class GTLogSearchActivity extends GTBaseActivity {
private ImageView img_empty;
TextView tv_count;
ImageButton btn_pre;
ImageButton btn_next;
private ListView listView;
private SearchLogAdapter arrayAdapter;
private LogEntry[] dataSet;
private ListView filterListView;
// 有时候用户操作果过快,会导致crash,在不使用handler的情况需要加锁,TODO 先不加锁看看效果
// private Lock filterLock;
private EditText et_Msg;
private ImageButton btn_msg_clear;
private Button btn_back;
private Handler handler;
private TextWatcher msg_watcher = new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
String sCurSelectedMsg = s.toString();
GTLogInternal.setCurSearchMsg(sCurSelectedMsg);
((ArrayAdapter<?>) filterListView.getAdapter()).getFilter().filter(
sCurSelectedMsg);
if (filterListView.getAdapter().isEmpty()) {
img_empty.setVisibility(View.GONE);
}
if (sCurSelectedMsg.length() > 0) {
btn_msg_clear.setVisibility(View.VISIBLE);
} else {
btn_msg_clear.setVisibility(View.GONE);
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
}
};
private boolean msgWatched = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gt_log_search_activity);
handler = new Handler();
tv_count = (TextView)findViewById(R.id.log_search_count);
btn_pre = (ImageButton)findViewById(R.id.log_msg_pre);
btn_next = (ImageButton)findViewById(R.id.log_msg_next);
/*
* 用于覆盖整个屏幕的透明ImageView,
* 主要帮助点击非filterListView区域使filterListView消失
*/
img_empty = (ImageView) findViewById(R.id.log_search_view_empty);
img_empty.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
img_empty.setVisibility(View.GONE);
filterListView.setVisibility(View.GONE);
cancelFilterMsgInput(v);
break;
case MotionEvent.ACTION_UP:
v.performClick();
break;
default:
break;
}
return false;
}
});
// 过滤数据展示列表
filterListView = (ListView) findViewById(R.id.log_search_spinner_list);
// filterLock = new ReentrantLock();
filterListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View v, int position,
long arg3) {
img_empty.setVisibility(View.GONE);
filterListView.setVisibility(View.GONE);
String sCurSelectedMsg = (String) parent.getAdapter().getItem(position);
LinkedList<String> curShowDownMsgList = GTLogInternal.getCurShowDownMsgList();
LinkedList<String> msgHistory = GTLogInternal.getCurSearchMsgHistory();
GTLogInternal.setCurSearchMsg(sCurSelectedMsg);
msgWatched = false;
et_Msg.removeTextChangedListener(msg_watcher);
String s = curShowDownMsgList.remove(position);
curShowDownMsgList.addFirst(s);
msgHistory.remove(s);
msgHistory.addFirst(s);
et_Msg.setText(sCurSelectedMsg);
btn_msg_clear.setVisibility(View.VISIBLE);
cancelFilterMsgInput(parent);
// filterLock.lock();
((MsgAdaptor)filterListView.getAdapter()).getFilter().filter(sCurSelectedMsg);
// filterLock.unlock();
doSearch(sCurSelectedMsg);
}
});
// 过滤文本
et_Msg = (EditText) findViewById(R.id.log_search_msg);
// et_Msg.setText(BHLog.getCurSearchMsg());
et_Msg.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (!msgWatched) {
et_Msg.addTextChangedListener(msg_watcher);
msgWatched = true;
}
MsgAdaptor adapter = new MsgAdaptor(GTLogSearchActivity.this);
adapter.getFilter().filter(et_Msg.getText().toString());
// filterLock.lock();
filterListView.setAdapter(adapter);
// filterLock.unlock();
if (!filterListView.getAdapter().isEmpty()) {
filterListView.setVisibility(View.VISIBLE);
img_empty.setVisibility(View.VISIBLE);
}
}
});
et_Msg.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_ENTER:
// 要先把过滤showdown去掉,否则会多弹出一次
msgWatched = false;
et_Msg.removeTextChangedListener(msg_watcher);
String word = et_Msg.getText().toString();
filterListView.setVisibility(View.GONE);
img_empty.setVisibility(View.GONE);
cancelFilterMsgInput(v);
if (word.trim().length() == 0) {
return true;
}
LinkedList<String> curShowDownMsgList = GTLogInternal.getCurShowDownMsgList();
LinkedList<String> msgHistory = GTLogInternal.getCurSearchMsgHistory();
msgHistory.remove(word);
msgHistory.addFirst(word);
curShowDownMsgList.remove(word);
curShowDownMsgList.addFirst(word);
doSearch(word);
return true;
}
return false;
}
});
// 过滤文本的清理
btn_msg_clear = (ImageButton) findViewById(R.id.log_msg_search_clear);
btn_msg_clear.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
et_Msg.setText("");
// 清理本次搜索标记
GTLogInternal.clearLastSearchMarks();
tv_count.setText("0 / 0");
arrayAdapter.notifyDataSetChanged();
btn_msg_clear.setVisibility(View.GONE);
}
});
// 改成back功能了
btn_back = (Button) findViewById(R.id.log_msg_search_cancel);
btn_back.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 20130404 改成back功能了
finish();
}
});
btn_pre.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
int historySeq = GTLogInternal.getLastMatchedSeq();
if (historySeq > 0)
{
GTLogInternal.setLastMatchedSeq(historySeq - 1);
listView.setSelection(GTLogInternal.getLastMatchedEntryList().get(historySeq - 1).posionInDataSet);
tv_count.setText(historySeq + // 这里注意显示序号要比存储位置多1,因为从1开始算
" / " + GTLogInternal.getLastMatchedEntryList().size());
handler.post(new Runnable(){
@Override
public void run() {
// 这个刷新需要在UI线程排队,否则会被listView.setSelection方法冲突掉
arrayAdapter.notifyDataSetChanged();
}});
}
else if (historySeq == 0 && GTLogInternal.getLastMatchedEntryList().size() > 0)
{
GTLogInternal.setLastMatchedSeq(GTLogInternal.getLastMatchedEntryList().size() - 1);
listView.setSelection(GTLogInternal.getLastMatchedEntryList().get(
GTLogInternal.getLastMatchedEntryList().size() - 1).posionInDataSet);
tv_count.setText(GTLogInternal.getLastMatchedEntryList().size() +
" / " + GTLogInternal.getLastMatchedEntryList().size());
handler.post(new Runnable(){
@Override
public void run() {
// 这个刷新需要在UI线程排队,否则会被listView.setSelection方法冲突掉
arrayAdapter.notifyDataSetChanged();
}});
}
}});
btn_next.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
int historySeq = GTLogInternal.getLastMatchedSeq();
if (historySeq < GTLogInternal.getLastMatchedEntryList().size() - 1)
{
GTLogInternal.setLastMatchedSeq(historySeq + 1);
listView.setSelection(GTLogInternal.getLastMatchedEntryList().get(historySeq + 1).posionInDataSet);
int viewSeq = historySeq + 2;
tv_count.setText(viewSeq + // 这里注意显示序号要比存储位置多1,因为从1开始算
" / " + GTLogInternal.getLastMatchedEntryList().size());
handler.post(new Runnable(){
@Override
public void run() {
// 这个刷新需要在UI线程排队,否则会被listView.setSelection方法冲突掉
arrayAdapter.notifyDataSetChanged();
}});
}
else if (historySeq == GTLogInternal.getLastMatchedEntryList().size() - 1)
{
GTLogInternal.setLastMatchedSeq(0);
listView.setSelection(GTLogInternal.getLastMatchedEntryList().get(0).posionInDataSet);
tv_count.setText(1 + // 这里注意显示序号要比存储位置多1,因为从1开始算
" / " + GTLogInternal.getLastMatchedEntryList().size());
handler.post(new Runnable(){
@Override
public void run() {
// 这个刷新需要在UI线程排队,否则会被listView.setSelection方法冲突掉
arrayAdapter.notifyDataSetChanged();
}});
}
}});
// 准备日志列表数据
listView = (ListView) findViewById(R.id.log_search_list);
Intent intent = getIntent();
String openFileName = intent.getStringExtra("openFileName");
if (openFileName == null)
{
// 日志列表
dataSet = GTLogInternal.getCurFilteredLogs();
arrayAdapter = new SearchLogAdapter(this, dataSet);
listView.setAdapter(arrayAdapter);
}
// 打开历史日志
else
{
openLog(openFileName);
}
}
protected void onResume(){
super.onResume();
}
@Override
public void onDestroy()
{
GTLogInternal.setLastSearchMsg("");
GTLogInternal.setLastSearchDataSet(new LogEntry[]{});
GTLogInternal.clearLastSearchMarks();
super.onDestroy();
}
/*
* TODO 先准备数据,期间转菊花,数据完成后,跳到search页展示
* 注意日志的长度问题
*/
private ProgressDialog proDialog;
private void openLog(final String filename)
{
final AsyncTask<Void, Void, LogEntry[]> openFileTask = new AsyncTask<Void, Void, LogEntry[]>() {
@Override
protected void onPreExecute() {
super.onPreExecute();
// 转菊花
proDialog = ProgressDialog.show(GTLogSearchActivity.this,
"get data..", "geting data..wait...", true, true);
}
@Override
protected LogEntry[] doInBackground(Void... params) {
final int maxLines = 1000;
LogEntry[] logLines = SaveLogHelper.openLog(filename, maxLines);
return logLines;
}
@Override
protected void onPostExecute(LogEntry[] logLines) {
super.onPostExecute(logLines);
// 取消菊花
proDialog.dismiss();
proDialog = null;
dataSet = logLines;
arrayAdapter = new SearchLogAdapter(GTLogSearchActivity.this, dataSet);
listView.setAdapter(arrayAdapter);
}
};
openFileTask.execute((Void) null);
}
private void doSearch(String searchKey)
{
GTLogInternal.setLastSearchMsg(searchKey);
GTLogInternal.setLastSearchDataSet(dataSet);
arrayAdapter.notifyDataSetChanged();
/*
* TODO 下面这些应该写在Handler里
*/
handler.post(new Runnable(){
@Override
public void run() {
if (GTLogInternal.getLastMatchedEntryList().size() > 0)
{
// 选中最后一个作为选中的高亮点
listView.setSelection(GTLogInternal.getLastMatchedEntryList().get(
GTLogInternal.getLastMatchedEntryList().size() - 1).posionInDataSet);
GTLogInternal.setLastMatchedSeq(GTLogInternal.getLastMatchedEntryList().size() - 1);
}
}
});
tv_count.setText(GTLogInternal.getLastMatchedEntryList().size() +" / " + GTLogInternal.getLastMatchedEntryList().size());
}
private void cancelFilterMsgInput(View v) {
InputMethodManager imm = (InputMethodManager) v.getContext()
.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getApplicationWindowToken(), 0);
}
private class MsgAdaptor extends ArrayAdapter<String> {
Filter filter;
public MsgAdaptor(Context context) {
super(context, R.layout.gt_simple_dropdown_item,
GTLogInternal.getCurShowDownMsgList());
}
@Override
public Filter getFilter() {
if (filter == null) {
filter = new Filter() {
@Override
protected FilterResults performFiltering(
CharSequence constraint) {
FilterResults results = new FilterResults();
LinkedList<String> curShowDownMsgList = GTLogInternal.getCurShowDownMsgList();
LinkedList<String> msgHistory = GTLogInternal.getCurSearchMsgHistory();
curShowDownMsgList.clear();
if (constraint != null) {
for (Iterator<String> iter = msgHistory.iterator(); iter
.hasNext();) {
String s = iter.next();
if (s.contains(constraint)) {
curShowDownMsgList.add(s);
}
}
}
results.values = curShowDownMsgList;
results.count = curShowDownMsgList.size();
return results;
}
@Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
if (results.count > 0) {
notifyDataSetChanged();
if (msgWatched) {
filterListView.setVisibility(View.VISIBLE);
img_empty.setVisibility(View.VISIBLE);
}
} else {
filterListView.setVisibility(View.GONE);
img_empty.setVisibility(View.GONE);
notifyDataSetInvalidated();
}
}
};
}
return filter;
}
}
}