1 /******************************************************************************* 2 * This file is part of BOINC. 3 * http://boinc.berkeley.edu 4 * Copyright (C) 2012 University of California 5 * 6 * BOINC is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU Lesser General Public License 8 * as published by the Free Software Foundation, 9 * either version 3 of the License, or (at your option) any later version. 10 * 11 * BOINC is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 14 * See the GNU Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public License 17 * along with BOINC. If not, see <http://www.gnu.org/licenses/>. 18 ******************************************************************************/ 19 package edu.berkeley.boinc; 20 21 import edu.berkeley.boinc.adapter.ClientLogListAdapter; 22 import edu.berkeley.boinc.rpc.Message; 23 import edu.berkeley.boinc.utils.*; 24 25 import java.util.ArrayList; 26 import java.util.List; 27 import android.os.AsyncTask; 28 import android.os.Bundle; 29 import android.os.RemoteException; 30 import android.support.v4.app.Fragment; 31 import android.util.Log; 32 import android.view.LayoutInflater; 33 import android.view.View; 34 import android.view.ViewGroup; 35 import android.widget.AbsListView; 36 import android.widget.ListView; 37 import android.widget.AbsListView.OnScrollListener; 38 39 public class EventLogClientFragment extends Fragment { 40 41 // message retrieval 42 private Integer pastMsgsLoadingRange = 50; // amount messages loaded when end of list is reached 43 private EventLogActivity a; 44 45 @Override onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)46 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 47 a = ((EventLogActivity)getActivity()); 48 49 View layout = inflater.inflate(R.layout.eventlog_client_layout, container, false); 50 51 a.clientLogList = (ListView) layout.findViewById(R.id.clientLogList); 52 a.clientLogListAdapter = new ClientLogListAdapter(getActivity(), a.clientLogList, R.id.clientLogList, a.clientLogData); 53 a.clientLogList.setOnScrollListener(new EndlessScrollListener(5)); 54 55 return layout; 56 } 57 init()58 public void init() { 59 new RetrievePastClientMsgs().execute(); // read messages 60 } 61 update()62 public void update() { 63 new RetrieveRecentClientMsgs().execute(); // refresh messages 64 } 65 66 // appends older messages to data list loadPastMsgs(List<edu.berkeley.boinc.rpc.Message> tmpA)67 private void loadPastMsgs(List<edu.berkeley.boinc.rpc.Message> tmpA) { 68 // Append old messages to the event log 69 try { 70 for(int x = tmpA.size()-1; x >= 0; x--) { 71 a.clientLogData.add(tmpA.get(x)); 72 } 73 } catch (Exception e) {} //IndexOutOfBoundException 74 75 a.clientLogListAdapter.notifyDataSetChanged(); 76 } 77 78 // updates data list with most recent messages loadRecentMsgs(ArrayList<edu.berkeley.boinc.rpc.Message> tmpA)79 private void loadRecentMsgs(ArrayList<edu.berkeley.boinc.rpc.Message> tmpA) { 80 // Prepend new messages to the event log 81 try { 82 int y = 0; 83 for (int x = tmpA.size()-1; x >= 0; x--) { 84 a.clientLogData.add(y, tmpA.get(x)); 85 y++; 86 } 87 } catch (Exception e) {} //IndexOutOfBoundException 88 a.clientLogListAdapter.notifyDataSetChanged(); 89 } 90 91 // onScrollListener for list view, implementing "endless scrolling" 92 public final class EndlessScrollListener implements OnScrollListener { 93 94 private int visibleThreshold = 5; 95 private int previousTotal = 0; 96 private boolean loading = true; 97 EndlessScrollListener(int visibleThreshold)98 public EndlessScrollListener(int visibleThreshold) { 99 this.visibleThreshold = visibleThreshold; 100 } 101 102 @Override onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)103 public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { 104 if (loading) { 105 if (totalItemCount > previousTotal) { 106 loading = false; 107 previousTotal = totalItemCount; 108 } 109 } 110 if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) { 111 new RetrievePastClientMsgs().execute(); 112 loading = true; 113 } 114 } 115 116 @Override onScrollStateChanged(AbsListView view, int scrollState)117 public void onScrollStateChanged(AbsListView view, int scrollState) { 118 } 119 } 120 121 private final class RetrieveRecentClientMsgs extends AsyncTask<Void,Void,ArrayList<edu.berkeley.boinc.rpc.Message>> { 122 123 private Integer mostRecentSeqNo = 0; 124 125 @Override onPreExecute()126 protected void onPreExecute() { 127 if(!a.clientLogData.isEmpty()) mostRecentSeqNo = a.clientLogData.get(0).seqno; 128 } 129 130 @Override doInBackground(Void... params)131 protected ArrayList<edu.berkeley.boinc.rpc.Message> doInBackground(Void... params) { 132 try { 133 return (ArrayList<edu.berkeley.boinc.rpc.Message>) ((EventLogActivity)getActivity()).getMonitorService().getMessages(mostRecentSeqNo); 134 } catch (RemoteException e) { 135 // TODO Auto-generated catch block 136 e.printStackTrace(); 137 return new ArrayList<edu.berkeley.boinc.rpc.Message>(); 138 } 139 } 140 141 @Override onPostExecute(ArrayList<edu.berkeley.boinc.rpc.Message> result)142 protected void onPostExecute(ArrayList<edu.berkeley.boinc.rpc.Message> result) { 143 // back in UI thread 144 loadRecentMsgs(result); 145 } 146 } 147 148 private final class RetrievePastClientMsgs extends AsyncTask<Void,Void,List<edu.berkeley.boinc.rpc.Message>> { 149 150 //private int mostRecentSeqNo = 0; // most recent (highest) seqNo 151 private int pastSeqNo = -1; // oldest (lowest) seqNo currently loaded to GUI 152 //private int lastclientLogDataListIndex = 0; // index of last element (oldest message) in clientLogData 153 154 @Override onPreExecute()155 protected void onPreExecute() { 156 if(!a.clientLogData.isEmpty()) { 157 pastSeqNo = a.clientLogData.get(a.clientLogData.size() - 1).seqno; 158 if(pastSeqNo==0) { 159 if(Logging.DEBUG) Log.d("RetrievePastMsgs", "cancel, oldest messages already loaded"); 160 cancel(true); // cancel if all past messages are present 161 } 162 } 163 } 164 165 @Override doInBackground(Void... params)166 protected List<Message> doInBackground(Void... params) { 167 if(Logging.DEBUG) Log.d("RetrievePastMsgs", "calling monitor with: " + pastSeqNo + " / " + pastMsgsLoadingRange); 168 try { 169 return ((EventLogActivity)getActivity()).getMonitorService().getEventLogMessages(pastSeqNo, pastMsgsLoadingRange); 170 } catch (RemoteException e) { 171 // TODO Auto-generated catch block 172 e.printStackTrace(); 173 return new ArrayList<edu.berkeley.boinc.rpc.Message>(); 174 } 175 } 176 177 @Override onPostExecute(List<edu.berkeley.boinc.rpc.Message> result)178 protected void onPostExecute(List<edu.berkeley.boinc.rpc.Message> result) { 179 // back in UI thread 180 loadPastMsgs(result); 181 } 182 } 183 } 184