ScheduleLayout.java 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. package com.ivalentin.margolariak;
  2. import java.text.DateFormat;
  3. import java.text.ParseException;
  4. import java.text.SimpleDateFormat;
  5. import java.util.Calendar;
  6. import java.util.Date;
  7. import java.util.Locale;
  8. import com.google.android.gms.maps.CameraUpdate;
  9. import com.google.android.gms.maps.CameraUpdateFactory;
  10. import com.google.android.gms.maps.GoogleMap;
  11. import com.google.android.gms.maps.MapView;
  12. import com.google.android.gms.maps.MapsInitializer;
  13. import com.google.android.gms.maps.OnMapReadyCallback;
  14. import com.google.android.gms.maps.model.LatLng;
  15. import com.google.android.gms.maps.model.MarkerOptions;
  16. import android.annotation.SuppressLint;
  17. import android.app.Dialog;
  18. import android.content.Context;
  19. import android.content.DialogInterface;
  20. import android.content.DialogInterface.OnCancelListener;
  21. import android.content.DialogInterface.OnShowListener;
  22. import android.database.Cursor;
  23. import android.database.sqlite.SQLiteDatabase;
  24. import android.os.Bundle;
  25. import android.app.Fragment;
  26. import android.text.Editable;
  27. import android.text.TextWatcher;
  28. import android.util.Log;
  29. import android.view.Gravity;
  30. import android.view.LayoutInflater;
  31. import android.view.View;
  32. import android.view.Window;
  33. import android.view.View.OnClickListener;
  34. import android.view.ViewGroup;
  35. import android.view.WindowManager;
  36. import android.widget.Button;
  37. import android.widget.EditText;
  38. import android.widget.ImageView;
  39. import android.widget.LinearLayout;
  40. import android.widget.TextView;
  41. /**
  42. * Fragment to be inflated showing the festivals schedule.
  43. * Contains a date selector and a ScrollView with all the activities for the day.
  44. *
  45. * @author Inigo Valentin
  46. *
  47. */
  48. public class ScheduleLayout extends Fragment implements OnMapReadyCallback{
  49. Bundle bund;
  50. private String dates[] = new String[20];
  51. private int dateCount = 0;
  52. private int selected = 0;
  53. //Indicates official schedule
  54. private int schedule;
  55. //Map stuff for the dialog
  56. private MapView mapView;
  57. private GoogleMap map;
  58. private LatLng location;
  59. private View view;
  60. private String markerName = "";
  61. /**
  62. * Run when the fragment is inflated.
  63. * Assigns views, gets the date and does the first call to the populateSchedule function.
  64. *
  65. * @param inflater A LayoutInflater to manage views
  66. * @param container The container View
  67. * @param savedInstanceState Bundle containing the state
  68. *
  69. * @see android.support.v4.app.Fragment#onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle)
  70. */
  71. @SuppressLint("InflateParams") //Throws unknown error when done properly.
  72. @Override
  73. public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
  74. Calendar calendar = Calendar.getInstance();
  75. String year = Integer.toString(calendar.get(Calendar.YEAR));
  76. //Set bundle for the map
  77. bund = savedInstanceState;
  78. //Load the layout
  79. view = inflater.inflate(R.layout.fragment_layout_schedule, null);
  80. //Get schedule type
  81. Bundle bundle = this.getArguments();
  82. schedule = bundle.getInt(GM.SCHEDULE, GM.SECTION_LABLANCA_SCHEDULE);
  83. //Set the title
  84. if (schedule == GM.SECTION_LABLANCA_SCHEDULE)
  85. ((MainActivity) getActivity()).setSectionTitle(view.getContext().getString(R.string.menu_lablanca_schedule));
  86. else
  87. ((MainActivity) getActivity()).setSectionTitle(view.getContext().getString(R.string.menu_lablanca_gm_schedule));
  88. //Populate the dates array
  89. SQLiteDatabase db = getActivity().openOrCreateDatabase(GM.DB_NAME, Context.MODE_PRIVATE, null);
  90. Cursor cursor;
  91. if (schedule == GM.SECTION_LABLANCA_GM_SCHEDULE) {
  92. cursor = db.rawQuery("SELECT DISTINCT date(start) FROM festival_event WHERE strftime('%Y', start) = '" + year + "' AND strftime('%H', start) > '06' AND gm = 1;", null);
  93. }
  94. else{
  95. cursor = db.rawQuery("SELECT DISTINCT date(start) FROM festival_event WHERE strftime('%Y', start) = '" + year + "' AND strftime('%H', start) > '06' AND gm = 0;", null);
  96. }
  97. while (cursor.moveToNext()){
  98. dates[dateCount] = cursor.getString(0);
  99. dateCount ++;
  100. //TODO: Check if some date is of today, and set selected
  101. }
  102. cursor.close();
  103. db.close();
  104. //Assign buttons
  105. Button btL = (Button) view.findViewById(R.id.bt_schedule_l);
  106. Button btR = (Button) view.findViewById(R.id.bt_schedule_r);
  107. btL.setOnClickListener(new OnClickListener() {
  108. @Override
  109. public void onClick(View v) {
  110. selected --;
  111. populateSchedule();
  112. }
  113. });
  114. btR.setOnClickListener(new OnClickListener() {
  115. @Override
  116. public void onClick(View v) {
  117. selected ++;
  118. populateSchedule();
  119. }
  120. });
  121. //Assign the filter text
  122. EditText etFilter = (EditText) view.findViewById(R.id.et_schedule_filter);
  123. etFilter.addTextChangedListener(new TextWatcher() {
  124. @Override
  125. public void afterTextChanged(Editable s) { }
  126. @Override
  127. public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
  128. @Override
  129. public void onTextChanged(CharSequence s, int start, int before, int count) {
  130. //Repopulate when the text is changed
  131. populateSchedule();
  132. }
  133. });
  134. //Populate the activity list
  135. populateSchedule();
  136. //Return the fragment view
  137. return view;
  138. }
  139. /**
  140. * Populates the list of activities with the ones n the selected day.
  141. *
  142. */
  143. @SuppressLint("InflateParams") //Views are added from a loop: I can't specify the parent when inflating.
  144. private int populateSchedule() {
  145. int eventCount = 0;
  146. //Hide or show buttons
  147. Button btNext = (Button) view.findViewById(R.id.bt_schedule_r);
  148. Button btPrevious = (Button) view.findViewById(R.id.bt_schedule_l);
  149. if (selected <= 0) {
  150. btPrevious.setVisibility(View.INVISIBLE);
  151. } else {
  152. btPrevious.setVisibility(View.VISIBLE);
  153. }
  154. if (selected >= dateCount - 1) {
  155. btNext.setVisibility(View.INVISIBLE);
  156. } else {
  157. btNext.setVisibility(View.VISIBLE);
  158. }
  159. //If there are no events,return now
  160. if (selected < 0 || selected >= dateCount) {
  161. return eventCount;
  162. }
  163. //Search filter
  164. String filter = ((EditText) view.findViewById(R.id.et_schedule_filter)).getText().toString().toLowerCase(Locale.US);
  165. Calendar calendar = Calendar.getInstance();
  166. DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss", Locale.US);
  167. try {
  168. calendar.setTime(dateFormat.parse(dates[selected] + " 06:00:00"));
  169. } catch (Exception ex) {
  170. Log.e("Datetime error", ex.toString());
  171. }
  172. SQLiteDatabase db = getActivity().openOrCreateDatabase(GM.DB_NAME, Context.MODE_PRIVATE, null);
  173. String lang = GM.getLang();
  174. //A layout to be populated with one activity
  175. LinearLayout entry, list;
  176. //An inflater
  177. LayoutInflater factory = LayoutInflater.from(getActivity());
  178. //Views in each row
  179. TextView tvRowTitle, tvRowTime, tvRowDesc, tvRowPlace, tvRowId, tvRowAddress;
  180. //Set date selector texts
  181. TextView tvDayNumber = (TextView) view.findViewById(R.id.tv_schedule_day_number);
  182. TextView tvDayMonth = (TextView) view.findViewById(R.id.tv_schedule_day_month);
  183. TextView tvDayTitle = (TextView) view.findViewById(R.id.tv_schedule_day_title);
  184. tvDayNumber.setText(String.valueOf(calendar.get(Calendar.DAY_OF_MONTH)));
  185. switch (calendar.get(Calendar.MONTH)) {
  186. case 6:
  187. tvDayMonth.setText(getString(R.string.schedule_month_july));
  188. break;
  189. case 7:
  190. tvDayMonth.setText(getString(R.string.schedule_month_august));
  191. break;
  192. }
  193. if (schedule == GM.SECTION_LABLANCA_GM_SCHEDULE) {
  194. Cursor cursorDay = db.rawQuery("SELECT name_" + lang + " FROM festival_day WHERE date(date) = '" + dates[selected] + "';", null);
  195. if (cursorDay.getCount() > 0) {
  196. cursorDay.moveToFirst();
  197. tvDayTitle.setText(cursorDay.getString(0));
  198. } else {
  199. tvDayTitle.setText("");
  200. }
  201. cursorDay.close();
  202. }
  203. //Get day end date
  204. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
  205. Calendar c = Calendar.getInstance();
  206. try {
  207. c.setTime(sdf.parse(dates[selected]));
  208. } catch (Exception ex) {
  209. Log.e("Date parsing error", ex.toString());
  210. return eventCount;
  211. }
  212. c.add(Calendar.DATE, 1); // number of days to add
  213. String endDate = sdf.format(c.getTime());
  214. String query = "SELECT festival_event.id, title_" + lang + ", description_" + lang + ", place, start, end, name_" + lang + ", address_" + lang + ", lat, lon FROM festival_event, place WHERE place = place.id AND start >= '" + dates[selected] + " 06:00:00' AND start < '" + endDate + " 05:59:59' AND ";
  215. if (schedule == GM.SECTION_LABLANCA_GM_SCHEDULE) {
  216. query = query + "gm = 1 ";
  217. } else {
  218. query = query + "gm = 0 ";
  219. }
  220. if (filter.length() > 0) {
  221. query = query + "AND (title_" + lang + " like '%" + filter + "%' OR description_" + lang + " like '%" + filter + "%' OR name_" + lang + " like '%" + filter + "%' OR address_" + lang + " like '%" + filter + "%') ";
  222. }
  223. Cursor cursor = db.rawQuery(query, null);
  224. //If there are entries, clear the list
  225. list = (LinearLayout) view.findViewById(R.id.ll_schedule_list);
  226. if (cursor.getCount() > 0) {
  227. list.removeAllViews();
  228. }
  229. while (cursor.moveToNext()) {
  230. eventCount++;
  231. entry = (LinearLayout) factory.inflate(R.layout.row_schedule, null);
  232. //Set id
  233. tvRowId = (TextView) entry.findViewById(R.id.tv_row_schedule_id);
  234. tvRowId.setText(cursor.getString(0));
  235. //Set title
  236. tvRowTitle = (TextView) entry.findViewById(R.id.tv_row_schedule_title);
  237. tvRowTitle.setText(cursor.getString(1));
  238. //Set description
  239. tvRowDesc = (TextView) entry.findViewById(R.id.tv_row_schedule_description);
  240. if (cursor.getString(2).length() <= 0 || cursor.getString(2).equals(cursor.getString(1))) {
  241. tvRowDesc.setVisibility(View.GONE);
  242. } else {
  243. tvRowDesc.setText(cursor.getString(2));
  244. }
  245. //Set place
  246. tvRowPlace = (TextView) entry.findViewById(R.id.tv_row_schedule_place);
  247. tvRowPlace.setText(cursor.getString(6));
  248. //Set address
  249. tvRowAddress = (TextView) entry.findViewById(R.id.tv_row_schedule_address);
  250. if (cursor.getString(7).length() <= 0 || cursor.getString(7).equals(cursor.getString(6))) {
  251. tvRowAddress.setVisibility(View.GONE);
  252. } else {
  253. tvRowAddress.setText(cursor.getString(7));
  254. }
  255. //Set icon
  256. if (schedule == GM.SECTION_LABLANCA_GM_SCHEDULE) {
  257. ImageView pinPoint = (ImageView) entry.findViewById(R.id.iv_row_schedule_pinpoint);
  258. pinPoint.setImageResource(getResources().getIdentifier("com.ivalentin.gm:drawable/pinpoint_gm", null, null));
  259. }
  260. //Set time
  261. tvRowTime = (TextView) entry.findViewById(R.id.tv_row_schedule_time);
  262. String tm = cursor.getString(4).substring(cursor.getString(4).length() - 8, cursor.getString(4).length() - 3);
  263. tvRowTime.setText(tm);
  264. //Set clisk listener
  265. entry.setOnClickListener(new OnClickListener() {
  266. @Override
  267. public void onClick(View v) {
  268. TextView tvId = (TextView) v.findViewById(R.id.tv_row_schedule_id);
  269. int id = Integer.parseInt(tvId.getText().toString());
  270. showDialog(id);
  271. }
  272. });
  273. //Add the view
  274. list.addView(entry);
  275. }
  276. cursor.close();
  277. db.close();
  278. return eventCount;
  279. }
  280. /**
  281. * Shows a dialog with info about the selected event.
  282. *
  283. * @param id The event id
  284. */
  285. private void showDialog(final int id){
  286. //Create the dialog
  287. final Dialog dialog = new Dialog(getActivity());
  288. //Set up dialog window
  289. dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
  290. dialog.setContentView(R.layout.dialog_schedule);
  291. //Date formatters
  292. SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
  293. SimpleDateFormat dayFormat = new SimpleDateFormat("yyyy-MM-dd-", Locale.US);
  294. SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm", Locale.US);
  295. //Set the custom dialog components - text, image and button
  296. TextView tvTitle = (TextView) dialog.findViewById(R.id.tv_dialog_schedule_title);
  297. TextView tvDescription = (TextView) dialog.findViewById(R.id.tv_dialog_schedule_description);
  298. TextView tvHost = (TextView) dialog.findViewById(R.id.tv_dialog_schedule_host);
  299. TextView tvDate = (TextView) dialog.findViewById(R.id.tv_dialog_schedule_date);
  300. TextView tvTime = (TextView) dialog.findViewById(R.id.tv_dialog_schedule_time);
  301. TextView tvPlace = (TextView) dialog.findViewById(R.id.tv_dialog_schedule_place);
  302. TextView tvAddress = (TextView) dialog.findViewById(R.id.tv_dialog_schedule_address);
  303. Button btClose = (Button) dialog.findViewById(R.id.bt_schedule_close);
  304. //Get info about the event
  305. SQLiteDatabase db = getActivity().openOrCreateDatabase(GM.DB_NAME, Context.MODE_PRIVATE, null);
  306. String lang = GM.getLang();
  307. //Cursor cursor = db.rawQuery("SELECT event.id, event.name, description, start, end, place.name, address, lat, lon, host FROM event, place WHERE place.id = event.place AND event.id = " + id + ";", null);
  308. Cursor cursor = db.rawQuery("SELECT festival_event.id, title_" + lang + ", description_" + lang + ", place, start, end, name_" + lang + ", address_" + lang + ", lat, lon, host FROM festival_event, place WHERE place = place.id AND festival_event.id = " + id + ";", null);
  309. if (cursor.getCount() > 0){
  310. cursor.moveToNext();
  311. //Set title
  312. tvTitle.setText(cursor.getString(1));
  313. markerName = cursor.getString(1);
  314. //Set description
  315. tvDescription.setText(cursor.getString(2));
  316. //Set host
  317. if (cursor.getString(10) != null){
  318. Cursor hostCursor = db.rawQuery("SELECT name_" + lang + " FROM people WHERE id = " + cursor.getString(10) + ";", null);
  319. if (hostCursor.moveToNext()){
  320. tvHost.setVisibility(View.VISIBLE);
  321. tvHost.setText(String.format(getString(R.string.schedule_host), hostCursor.getString(0)));
  322. }
  323. hostCursor.close();
  324. }
  325. else{
  326. tvHost.setVisibility(View.GONE);
  327. }
  328. //Set date
  329. try{
  330. Date day = dateFormat.parse(cursor.getString(4));
  331. Date date = new Date();
  332. //If the event is today, show "Today" instead of the date
  333. if (dayFormat.format(day).equals(dayFormat.format(date)))
  334. tvDate.setText(dialog.getContext().getString(R.string.today));
  335. else{
  336. Calendar cal = Calendar.getInstance();
  337. cal.setTime(date);
  338. cal.add(Calendar.HOUR_OF_DAY, 24);
  339. //If the event is tomorrow, show "Tomorrow" instead of the date
  340. if (dayFormat.format(cal.getTime()).equals(dayFormat.format(date))){
  341. tvDate.setText(dialog.getContext().getString(R.string.tomorrow));
  342. }
  343. //Else, show the date
  344. else{
  345. SimpleDateFormat printFormat = new SimpleDateFormat("dd MMMM", Locale.US);
  346. tvDate.setText(printFormat.format(day));
  347. }
  348. }
  349. }
  350. catch (Exception ex){
  351. Log.e("Error parsing date", ex.toString());
  352. }
  353. //Set time
  354. try{
  355. if (cursor.getString(5).length() == 0) {
  356. tvTime.setText(timeFormat.format(dateFormat.parse(cursor.getString(4))));
  357. }
  358. else {
  359. String time = timeFormat.format(dateFormat.parse(cursor.getString(4))) + " - " + timeFormat.format(dateFormat.parse(cursor.getString(5)));
  360. tvTime.setText(time);
  361. }
  362. }
  363. catch (ParseException ex){
  364. Log.e("Error parsing time", ex.toString());
  365. }
  366. //Set the place
  367. tvPlace.setText(cursor.getString(6));
  368. tvAddress.setText(cursor.getString(7));
  369. //Set up map
  370. location = new LatLng(Double.parseDouble(cursor.getString(8)), Double.parseDouble(cursor.getString(9)));
  371. mapView = (MapView) dialog.findViewById(R.id.mv_dialog_schedule_map);
  372. mapView.onCreate(bund);
  373. //Close the db connection
  374. cursor.close();
  375. db.close();
  376. //Set close button
  377. btClose.setOnClickListener(new OnClickListener() {
  378. @Override
  379. public void onClick(View v) {
  380. dialog.dismiss();
  381. }
  382. });
  383. //Actions to take when the dialog is cancelled
  384. dialog.setOnCancelListener(new OnCancelListener(){
  385. @Override
  386. public void onCancel(DialogInterface dialog) {
  387. if (map != null)
  388. map.setMyLocationEnabled(false);
  389. if (mapView != null){
  390. mapView.onResume();
  391. mapView.onDestroy();
  392. }
  393. }
  394. });
  395. //Show the dialog
  396. WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
  397. lp.copyFrom(dialog.getWindow().getAttributes());
  398. lp.width = WindowManager.LayoutParams.MATCH_PARENT;
  399. lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
  400. lp.gravity = Gravity.CENTER;
  401. lp.dimAmount = 0.0f;
  402. dialog.getWindow().setAttributes(lp);
  403. //Show dialog
  404. dialog.show();
  405. //Start the map
  406. startMap();
  407. mapView.onResume();
  408. dialog.setOnShowListener(new OnShowListener(){
  409. @Override
  410. public void onShow(DialogInterface dialog) {
  411. // Gets to GoogleMap from the MapView and does initialization stuff
  412. startMap();
  413. }
  414. });
  415. }
  416. }
  417. /**
  418. * Starts the map in the dialog.
  419. */
  420. private void startMap(){
  421. mapView.getMapAsync(this);
  422. }
  423. /**
  424. * Called when the fragment is brought back into the foreground.
  425. * Resumes the map and the location manager.
  426. *
  427. * @see android.app.Fragment#onResume()
  428. */
  429. @Override
  430. public void onResume() {
  431. if (mapView != null)
  432. mapView.onResume();
  433. if (map != null)
  434. map.setMyLocationEnabled(true);
  435. super.onResume();
  436. }
  437. /**
  438. * Called when the fragment is destroyed.
  439. * Finishes the map.
  440. *
  441. * @see android.app.Fragment#onDestroy()
  442. */
  443. @Override
  444. public void onDestroy() {
  445. super.onDestroy();
  446. if (map != null)
  447. map.setMyLocationEnabled(false);
  448. if (mapView != null){
  449. //mapView.onResume();
  450. mapView.onDestroy();
  451. }
  452. }
  453. /**
  454. * Called when the fragment is paused.
  455. * Finishes the map.
  456. *
  457. * @see android.app.Fragment#onPause()
  458. */
  459. @Override
  460. public void onPause() {
  461. super.onDestroy();
  462. if (map != null) {
  463. map.setMyLocationEnabled(false);
  464. }
  465. //if (mapView != null){
  466. //mapView.onPause();
  467. //}
  468. }
  469. /**
  470. * Called in a situation of low memory.
  471. * Lets the map handle this situation.
  472. *
  473. * @see android.app.Fragment#onLowMemory()
  474. */
  475. @Override
  476. public void onLowMemory() {
  477. super.onLowMemory();
  478. if (mapView != null){
  479. mapView.onResume();
  480. mapView.onLowMemory();
  481. }
  482. }
  483. /**
  484. * Called when the map is ready to be displayed.
  485. * Sets the map options and a marker for the map.
  486. *
  487. * @param googleMap The map to be shown
  488. *
  489. * @see com.google.android.gms.maps.OnMapReadyCallback#onMapReady(com.google.android.gms.maps.GoogleMap)
  490. */
  491. @Override
  492. public void onMapReady(GoogleMap googleMap) {
  493. this.map = googleMap;
  494. map.setMyLocationEnabled(true);
  495. map.getUiSettings().setMyLocationButtonEnabled(false);
  496. map.setMyLocationEnabled(true);
  497. // Needs to call MapsInitializer before doing any CameraUpdateFactory calls
  498. try {
  499. MapsInitializer.initialize(this.getActivity());
  500. CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(location, 14);
  501. map.animateCamera(cameraUpdate);
  502. } catch (Exception e) {
  503. Log.e("Error initializing maps", e.toString());
  504. }
  505. //Set GM marker
  506. MarkerOptions mo = new MarkerOptions();
  507. mo.title(markerName);
  508. mo.position(location);
  509. map.addMarker(mo);
  510. }
  511. }