package org.tyszecki.rozkladpkp; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.tyszecki.rozkladpkp.R; import org.tyszecki.rozkladpkp.TimetableItem.DateItem; import org.tyszecki.rozkladpkp.TimetableItem.ScrollItem; import org.tyszecki.rozkladpkp.TimetableItem.TrainItem; import org.tyszecki.rozkladpkp.TimetableItem.WarningItem; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import android.content.Context; import android.content.Intent; import android.text.Html; import android.text.format.Time; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ProgressBar; import android.widget.TextView; public class TimetableItemAdapter extends BaseAdapter { boolean arrival,saved = false; Time top,bottom,passed; String stationID; String productString; final int ITEM_HEADER = 0; final int ITEM_NORMAL = 1; final int ITEM_SCROLL = 2; final int ITEM_WARNING = 3; private ArrayList<TimetableItem> items; Context c; public TimetableItemAdapter(String stationID, String products, Time time, boolean arrival, Context context) { this.stationID = stationID; this.arrival = arrival; top = new Time(time); bottom = new Time(time); passed = time; productString = products; c = context; if(!arrival) moveBackward(); items = new ArrayList<TimetableItem>(); } public TimetableItemAdapter(String stationID, String products, Time time, boolean arrival, Context context, String filename) { this(stationID, products, time, arrival, context); saved = true; FileInputStream fis; try { fis = RozkladPKPApplication.getAppContext().openFileInput(filename); } catch (FileNotFoundException e) { return; } ByteArrayOutputStream content = new ByteArrayOutputStream(); byte[] sBuffer = new byte[256]; int readBytes = 0; try { while ((readBytes = fis.read(sBuffer)) != -1) content.write(sBuffer, 0, readBytes); } catch (IOException e) { e.printStackTrace(); } setXML(content.toString(), true); } public void fetch() { items.clear(); items.add(ScrollItem.progressItem()); notifyDataSetChanged(); fetchMore(true); } private Time moveForward(Time t) { if(t.hour < 23) t.hour++; else if(t.minute == 59) { t.hour = 1; t.minute = 0; t.monthDay++; } else t.minute = 59; t.normalize(false); bottom = t; return t; } private void moveBackward() { if(top.hour != 1) top.hour--; else if(top.minute != 0) top.minute = 0; else { top.hour -= 2; top.minute = 59; } top.normalize(false); } public Time getBottomTime() { Time t; if(items.size() < 3) //Tylko nagłówki t = passed; else { TrainItem ti = (TrainItem)getItem(items.size()-2); t = CommonUtils.timeFromString(new Time(), ti.date, ti.time); } if(bottom.after(t)) t = bottom; if(arrival) t = moveForward(t); return t; } public void fetchMore(boolean next) { if(next) { ((ScrollItem)items.get(getCount()-1)).inProgress = true; notifyDataSetChanged(); download(getBottomTime(), next); } else { download(new Time(top), next); moveBackward(); } } public void download(Time time, boolean next) { TimetableTask task = new TimetableTask(productString, time, stationID, arrival, next); task.execute(); } private class TimetableTask extends TimetableFetcher{ boolean n; public TimetableTask(String products, Time datetime, String stationID, boolean arrival, boolean next) { super(products, datetime, stationID, arrival); n = next; } @Override protected void onPostExecute(String result) { super.onPostExecute(result); ((ScrollItem)items.get(getCount()-1)).inProgress = false; notifyDataSetChanged(); setXML(result, n); //Zapisywanie w pamięci try{ Intent in = new Intent(RozkladPKPApplication.getAppContext(), RememberedService.class); in.putExtra("timetable", result.getBytes()); in.putExtra("SID", stationID); in.putExtra("departure", !arrival); in.putExtra("time", getBottomTime().format2445()); RozkladPKPApplication.getAppContext().startService(in); } catch(Exception e){} } } public void setXML(String xmlstring, boolean next) { try{ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder db = factory.newDocumentBuilder(); InputSource inStream = new InputSource(); inStream.setCharacterStream(new StringReader(xmlstring)); Document doc = db.parse(inStream); NodeList list = doc.getElementsByTagName("Journey"); int j = list.getLength(); String cdate = null, pdate = ""; if(items.size() < 2) { items.clear(); //items.add(ScrollItem.scrollItem(true)); if(saved) items.add(new WarningItem()); items.add(ScrollItem.scrollItem(false)); } else { if(next) pdate = ((TrainItem)items.get(items.size()-2)).date; else if(j > 0) { cdate = ((DateItem)items.get(0)).date; items.remove(0); } } int lastRes = -1; for(int i = 0; i < j; i++) { TrainItem o = new TrainItem(); Node n = list.item(i); o.station = n.getAttributes().getNamedItem("targetLoc").getNodeValue(); o.time = n.getAttributes().getNamedItem("fpTime").getNodeValue(); o.date = n.getAttributes().getNamedItem("fpDate").getNodeValue(); o.delay = n.getAttributes().getNamedItem("delay").getNodeValue(); o.number = n.getAttributes().getNamedItem("prod").getNodeValue(); int hix = o.number.indexOf('#'); if(hix > 0) o.number = o.number.substring(0, hix); if(!pdate.equals(o.date)){ DateItem d = new DateItem(); d.date = o.date; pdate = o.date; lastRes = addItem(d,lastRes,next); } /*NodeList msgs = n.getChildNodes(); for(int k = 0; k < msgs.getLength(); k++) { Node c = msgs.item(k); if(c.getNodeName().equals("HIMMessage")) o.message += c.getAttributes().getNamedItem("header").getNodeValue(); }*/ lastRes = addItem(o,lastRes,next); } if(cdate != null && !cdate.equals(pdate)) { DateItem d = new DateItem(); d.date = cdate; addItem(d,lastRes,next); } }catch (Exception e) {e.printStackTrace();} notifyDataSetChanged(); } private int addItem(TimetableItem item, int lastResult, boolean next) { if(lastResult == -1) { if(next) lastResult = items.size()-1; else lastResult = 0; } //TODO: Można to ładniej zrobić - wyszukiwanie duplikatów if(item instanceof TrainItem) { TrainItem u = (TrainItem)item; for(TimetableItem i : items) if(i instanceof TrainItem) { TrainItem t = (TrainItem)i; if(t.number.equals(u.number) && t.date.equals(u.date) && t.time.equals(u.time)) return lastResult; } } items.add(lastResult, item); return ++lastResult; } @Override public int getCount() { return items.size(); } @Override public TimetableItem getItem(int position) { return items.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { View v = convertView; TimetableItem b = items.get(position); if (v == null) { LayoutInflater vi = (LayoutInflater)c.getSystemService(Context.LAYOUT_INFLATER_SERVICE); if (b instanceof TrainItem) v = vi.inflate(R.layout.timetable_row, null); else if(b instanceof DateItem) v = vi.inflate(R.layout.common_date_header_row, null); else if(b instanceof ScrollItem) v = vi.inflate(R.layout.scrollitem, null); else v = vi.inflate(R.layout.warning_item, null); } if (b instanceof TrainItem) { TrainItem o = (TrainItem)b; ((TextView) v.findViewById(R.id.time)).setText(Html.fromHtml("<b>"+o.time+"</b> ")); ((TextView) v.findViewById(R.id.station)).setText(Html.fromHtml(((!arrival)?"do ":"z ")+"<b>"+o.station+"</b> ")); TextView type = (TextView) v.findViewById(R.id.train_type); type.requestLayout(); //Przeliczenie wymiarów, dzięki tej linijce po kilkukrotnym przewinięciu listy, elementy nie będą tej samej długości type.setText(o.number); type.setBackgroundResource(CommonUtils.drawableForTrainType(CommonUtils.trainType(o.number))); } else if(b instanceof DateItem){ TextView head = (TextView) v.findViewById(R.id.conn_header); head.setText(((DateItem)b).date); } else if(b instanceof ScrollItem) { ScrollItem s = (ScrollItem)b; TextView text = (TextView) v.findViewById(R.id.scrollitem_text); ProgressBar progress = (ProgressBar) v.findViewById(R.id.progress); if(s.inProgress) { progress.setVisibility(View.VISIBLE); text.setText("Trwa pobieranie rozkładu..."); } else { progress.setVisibility(View.GONE); if(s.up) text.setText("Poprzednie połączenia"); else text.setText("Następne połączenia"); } } else ((TextView) v.findViewById(R.id.text)).setText("Oglądasz zapisany rozkład. Dotknij tutaj, aby rozpocząć nowe wyszukiwanie"); return v; } @Override public int getItemViewType(int arg0) { TimetableItem it = items.get(arg0); if(it instanceof DateItem) return ITEM_HEADER; if(it instanceof TrainItem) return ITEM_NORMAL; if(it instanceof ScrollItem) return ITEM_SCROLL; return ITEM_WARNING; } @Override public int getViewTypeCount() { return 4; } @Override public boolean hasStableIds() { return false; } @Override public boolean isEmpty() { return items.size() == 0; } public boolean areAllItemsSelectable() { return false; } @Override public boolean isEnabled(int position) { int type = getItemViewType(position); if(type == ITEM_HEADER) return false; else if(type == ITEM_NORMAL | type == ITEM_WARNING) return true; return !((ScrollItem) getItem(position)).inProgress; } public String getContentForSharing() { String ret = ""; for(TimetableItem i : items) { if(i instanceof DateItem) ret += ((DateItem)i).date + "\n"; else if(i instanceof TrainItem) { TrainItem o = (TrainItem)i; ret += o.time; ret += " " + o.number; ret += (arrival) ? " z " : " do "; ret += o.station + "\n"; } } return ret; } }