diff --git a/build.gradle b/build.gradle index 41dcd4f..d04058b 100644 --- a/build.gradle +++ b/build.gradle @@ -1,84 +1,85 @@ buildscript { repositories { jcenter() maven { url 'https://maven.google.com' } google() } dependencies { classpath 'com.android.tools.build:gradle:3.1.0' } ext { support_ver = "25.4.0" } } allprojects { repositories { jcenter() maven { url 'https://maven.google.com' } google() } } apply plugin: 'com.android.application' android { compileSdkVersion 25 buildToolsVersion '27.0.3' defaultConfig { applicationId "it.reyboz.bustorino" minSdkVersion 9 targetSdkVersion 25 versionCode 27 versionName "1.11" + vectorDrawables.useSupportLibrary = true } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } sourceSets { main { manifest.srcFile 'AndroidManifest.xml' java.srcDirs = ['src'] resources.srcDirs = ['src'] aidl.srcDirs = ['src'] renderscript.srcDirs = ['src'] res.srcDirs = ['res'] assets.srcDirs = ['assets'] } } buildTypes { debug { applicationIdSuffix ".debug" versionNameSuffix "-dev" } } lintOptions { abortOnError false } repositories { jcenter() mavenLocal() } dependencies { implementation "com.android.support:support-v4:$support_ver" implementation "com.android.support:appcompat-v7:$support_ver" implementation "com.android.support:design:$support_ver" implementation "com.android.support:recyclerview-v7:$support_ver" implementation "com.android.support:preference-v7:$support_ver" implementation "com.android.support:cardview-v7:$support_ver" implementation 'org.jsoup:jsoup:1.11.3' implementation 'com.readystatesoftware.sqliteasset:sqliteassethelper:2.0.1' implementation 'com.android.volley:volley:1.1.1' } } diff --git a/gradlew.bat b/gradlew.bat old mode 100755 new mode 100644 diff --git a/res/drawable/ic_star_filled.xml b/res/drawable/ic_star_filled.xml new file mode 100644 index 0000000..c41f592 --- /dev/null +++ b/res/drawable/ic_star_filled.xml @@ -0,0 +1,9 @@ + + + diff --git a/res/drawable/ic_star_outline.xml b/res/drawable/ic_star_outline.xml new file mode 100644 index 0000000..bdb5efe --- /dev/null +++ b/res/drawable/ic_star_outline.xml @@ -0,0 +1,9 @@ + + + diff --git a/res/layout/fragment_list_view.xml b/res/layout/fragment_list_view.xml index 9b20d64..93d5958 100644 --- a/res/layout/fragment_list_view.xml +++ b/res/layout/fragment_list_view.xml @@ -1,28 +1,46 @@ + android:layout_height="match_parent"> + + + android:id="@+id/messageTextView" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="16dp" + android:layout_marginLeft="16dp" + android:layout_marginTop="10dp" + android:layout_marginEnd="307dp" + android:layout_marginRight="10dp" + android:layout_marginBottom="10dp" + android:layout_toStartOf="@+id/addToFavorites" + android:layout_toLeftOf="@+id/addToFavorites" + android:gravity="center_vertical" + android:minHeight="48dp" + android:textAppearance="?android:attr/textAppearanceMedium" /> + + + \ No newline at end of file diff --git a/res/layout/stop_card.xml b/res/layout/stop_card.xml old mode 100755 new mode 100644 diff --git a/src/it/reyboz/bustorino/ActivityMain.java b/src/it/reyboz/bustorino/ActivityMain.java index fac0dc1..5bccbaf 100644 --- a/src/it/reyboz/bustorino/ActivityMain.java +++ b/src/it/reyboz/bustorino/ActivityMain.java @@ -1,877 +1,903 @@ /* BusTO - Arrival times for Turin public transports. Copyright (C) 2014 Valerio Bozzolan This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ package it.reyboz.bustorino; import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.database.sqlite.SQLiteDatabase; import android.location.*; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.support.annotation.NonNull; import android.support.design.widget.Snackbar; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.support.v4.app.NavUtils; import android.support.v4.widget.SwipeRefreshLayout; import android.util.Log; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.*; import com.google.zxing.integration.android.IntentIntegrator; import com.google.zxing.integration.android.IntentResult; import android.support.design.widget.FloatingActionButton; import it.reyboz.bustorino.backend.*; import it.reyboz.bustorino.fragments.*; import it.reyboz.bustorino.middleware.*; import java.util.List; public class ActivityMain extends GeneralActivity implements FragmentListener { /* * Layout elements */ private EditText busStopSearchByIDEditText; private EditText busStopSearchByNameEditText; private ProgressBar progressBar; private TextView howDoesItWorkTextView; private Button hideHintButton; private MenuItem actionHelpMenuItem; private SwipeRefreshLayout swipeRefreshLayout; private FloatingActionButton floatingActionButton; private FragmentManager framan; private Snackbar snackbar; /* * Search mode */ private static final int SEARCH_BY_NAME = 0; private static final int SEARCH_BY_ID = 1; private static final int SEARCH_BY_ROUTE = 2; // TODO: implement this -- https://gitpull.it/T12 private int searchMode; + private ImageButton addToFavorites; /* * Options */ private final String OPTION_SHOW_LEGEND = "show_legend"; private final String LOCATION_PERMISSION_GIVEN = "loc_permission"; /* * Status */ private DBStatusManager prefsManager; private DBStatusManager.OnDBUpdateStatusChangeListener updatelistener; - private static final String DEBUG_TAG="BusTO - MainActivity"; + private static final String DEBUG_TAG = "BusTO - MainActivity"; /* // useful for testing: public class MockFetcher implements ArrivalsFetcher { @Override public Palina ReadArrivalTimesAll(String routeID, AtomicReference res) { SystemClock.sleep(5000); res.set(result.SERVER_ERROR); return new Palina(); } } private ArrivalsFetcher[] ArrivalFetchers = {new MockFetcher(), new MockFetcher(), new MockFetcher(), new MockFetcher(), new MockFetcher()};*/ - private RecursionHelper ArrivalFetchersRecursionHelper = new RecursionHelper<>(new ArrivalsFetcher[] {new GTTJSONFetcher(), new FiveTScraperFetcher()}); - private RecursionHelper StopsFindersByNameRecursionHelper = new RecursionHelper<>(new StopsFinderByName[] {new GTTStopsFetcher(), new FiveTStopsFetcher()}); + private RecursionHelper ArrivalFetchersRecursionHelper = new RecursionHelper<>(new ArrivalsFetcher[]{new GTTJSONFetcher(), new FiveTScraperFetcher()}); + private RecursionHelper StopsFindersByNameRecursionHelper = new RecursionHelper<>(new StopsFinderByName[]{new GTTStopsFetcher(), new FiveTStopsFetcher()}); /* * Position */ //Fine location criteria private final Criteria cr = new Criteria(); private boolean pendingNearbyStopsRequest = false; private LocationManager locmgr; /* * Database Access */ private StopsDB stopsDB; private UserDB userDB; private FragmentHelper fh; ///////////////////////////////// EVENT HANDLERS /////////////////////////////////////////////// /* * @see swipeRefreshLayout */ private Handler handler = new Handler(); private final Runnable refreshing = new Runnable() { public void run() { - if(framan.findFragmentById(R.id.resultFrame) instanceof ArrivalsFragment){ - ArrivalsFragment fragment = (ArrivalsFragment) framan.findFragmentById(R.id.resultFrame); - String stopName = fragment.getStopID(); - new AsyncDataDownload(AsyncDataDownload.RequestType.ARRIVALS,fh).execute(stopName); - } else - new AsyncDataDownload(AsyncDataDownload.RequestType.ARRIVALS,fh).execute(); + if (framan.findFragmentById(R.id.resultFrame) instanceof ArrivalsFragment) { + ArrivalsFragment fragment = (ArrivalsFragment) framan.findFragmentById(R.id.resultFrame); + String stopName = fragment.getStopID(); + new AsyncDataDownload(AsyncDataDownload.RequestType.ARRIVALS, fh).execute(stopName); + } else + new AsyncDataDownload(AsyncDataDownload.RequestType.ARRIVALS, fh).execute(); } }; //// MAIN METHOD /// @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); framan = getSupportFragmentManager(); this.stopsDB = new StopsDB(getApplicationContext()); this.userDB = new UserDB(getApplicationContext()); setContentView(R.layout.activity_main); busStopSearchByIDEditText = (EditText) findViewById(R.id.busStopSearchByIDEditText); busStopSearchByNameEditText = (EditText) findViewById(R.id.busStopSearchByNameEditText); progressBar = (ProgressBar) findViewById(R.id.progressBar); howDoesItWorkTextView = (TextView) findViewById(R.id.howDoesItWorkTextView); hideHintButton = (Button) findViewById(R.id.hideHintButton); swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.listRefreshLayout); floatingActionButton = (FloatingActionButton) findViewById(R.id.floatingActionButton); framan.addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() { @Override public void onBackStackChanged() { Log.d("MainActivity, BusTO", "BACK STACK CHANGED"); } }); busStopSearchByIDEditText.setSelectAllOnFocus(true); busStopSearchByIDEditText .setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { // IME_ACTION_SEARCH alphabetical option if (actionId == EditorInfo.IME_ACTION_SEARCH) { onSearchClick(v); return true; } return false; } }); busStopSearchByNameEditText .setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { // IME_ACTION_SEARCH alphabetical option if (actionId == EditorInfo.IME_ACTION_SEARCH) { onSearchClick(v); return true; } return false; } }); // Called when the layout is pulled down swipeRefreshLayout .setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { handler.post(refreshing); } }); /** * @author Marco Gagino!!! */ //swipeRefreshLayout.setColorSchemeColors(R.color.blue_500, R.color.orange_500); // setColorScheme is deprecated, setColorSchemeColors isn't - swipeRefreshLayout.setColorSchemeResources(R.color.blue_500,R.color.orange_500); - fh = new FragmentHelper(this,R.id.listRefreshLayout,R.id.resultFrame); + swipeRefreshLayout.setColorSchemeResources(R.color.blue_500, R.color.orange_500); + fh = new FragmentHelper(this, R.id.listRefreshLayout, R.id.resultFrame); setSearchModeBusStopID(); //---------------------------- START INTENT CHECK QUEUE ------------------------------------ // Intercept calls from URL intent boolean tryedFromIntent = false; String busStopID = null; String busStopDisplayName = null; Uri data = getIntent().getData(); if (data != null) { busStopID = getBusStopIDFromUri(data); tryedFromIntent = true; } // Intercept calls from other activities if (!tryedFromIntent) { Bundle b = getIntent().getExtras(); if (b != null) { busStopID = b.getString("bus-stop-ID"); busStopDisplayName = b.getString("bus-stop-display-name"); /** * I'm not very sure if you are coming from an Intent. * Some launchers work in strange ways. */ tryedFromIntent = busStopID != null; } } //---------------------------- END INTENT CHECK QUEUE -------------------------------------- if (busStopID == null) { // Show keyboard if can't start from intent // JUST DON'T // showKeyboard(); // You haven't obtained anything... from an intent? if (tryedFromIntent) { // This shows a luser warning ArrivalFetchersRecursionHelper.reset(); Toast.makeText(getApplicationContext(), R.string.insert_bus_stop_number_error, Toast.LENGTH_SHORT).show(); } } else { // If you are here an intent has worked successfully setBusStopSearchByIDEditText(busStopID); /* //THIS PART SHOULDN'T BE NECESSARY SINCE THE LAST SUCCESSFULLY SEARCHED BUS // STOP IS ADDED AUTOMATICALLY Stop nextStop = new Stop(busStopID); // forcing it as user name even though it could be standard name, it doesn't really matter nextStop.setStopUserName(busStopDisplayName); //set stop as last succe fh.setLastSuccessfullySearchedBusStop(nextStop); */ createFragmentForStop(busStopID); } //Try (hopefully) database update //TODO: Start the service in foreground, check last time it ran before DatabaseUpdateService.startDBUpdate(getApplicationContext()); /* Set database update */ - updatelistener = new DBStatusManager.OnDBUpdateStatusChangeListener(){ + updatelistener = new DBStatusManager.OnDBUpdateStatusChangeListener() { @Override public boolean defaultStatusValue() { return true; } @Override public void onDBStatusChanged(boolean updating) { - if(updating){ + if (updating) { createDefaultSnackbar(); - } - else if(snackbar!=null){ + } else if (snackbar != null) { snackbar.dismiss(); snackbar = null; } } }; - prefsManager = new DBStatusManager(getApplicationContext(),updatelistener); + prefsManager = new DBStatusManager(getApplicationContext(), updatelistener); prefsManager.registerListener(); //locationHandler = new GPSLocationAdapter(getApplicationContext()); //--------- NEARBY STOPS--------// //SETUP LOCATION locmgr = (LocationManager) getSystemService(LOCATION_SERVICE); cr.setAccuracy(Criteria.ACCURACY_FINE); cr.setAltitudeRequired(false); cr.setBearingRequired(false); cr.setCostAllowed(true); cr.setPowerRequirement(Criteria.NO_REQUIREMENT); //We want the nearby bus stops! handler.post(new NearbyStopsRequester()); //If there are no providers available, then, wait for them Log.d("MainActivity", "Created"); } /** * Reload bus stop timetable when it's fulled resumed from background. */ /** - @Override - protected void onPostResume() { - super.onPostResume(); - Log.d("ActivityMain", "onPostResume fired. Last successfully bus stop ID: " + fh.getLastSuccessfullySearchedBusStop()); - if (searchMode == SEARCH_BY_ID && fh.getLastSuccessfullySearchedBusStop() != null) { - setBusStopSearchByIDEditText(fh.getLastSuccessfullySearchedBusStop().ID); - //new asyncWgetBusStopFromBusStopID(lastSuccessfullySearchedBusStop.ID, ArrivalFetchersRecursionHelper, lastSuccessfullySearchedBusStop); - new AsyncDataDownload(AsyncDataDownload.RequestType.ARRIVALS,fh).execute(); - } else { - //we have new activity or we don't have a new searched stop. - //Let's search stops nearby - LocationManager locManager = (LocationManager) getSystemService(LOCATION_SERVICE); - Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.resultFrame); - - - } - //show the FAB since it remains hidden - floatingActionButton.show(); - - } + * @Override protected void onPostResume() { + * super.onPostResume(); + * Log.d("ActivityMain", "onPostResume fired. Last successfully bus stop ID: " + fh.getLastSuccessfullySearchedBusStop()); + * if (searchMode == SEARCH_BY_ID && fh.getLastSuccessfullySearchedBusStop() != null) { + * setBusStopSearchByIDEditText(fh.getLastSuccessfullySearchedBusStop().ID); + * //new asyncWgetBusStopFromBusStopID(lastSuccessfullySearchedBusStop.ID, ArrivalFetchersRecursionHelper, lastSuccessfullySearchedBusStop); + * new AsyncDataDownload(AsyncDataDownload.RequestType.ARRIVALS,fh).execute(); + * } else { + * //we have new activity or we don't have a new searched stop. + * //Let's search stops nearby + * LocationManager locManager = (LocationManager) getSystemService(LOCATION_SERVICE); + * Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.resultFrame); + *

+ *

+ * } + * //show the FAB since it remains hidden + * floatingActionButton.show(); + *

+ * } **/ @Override protected void onPause() { super.onPause(); fh.stopLastRequestIfNeeded(); fh.setBlockAllActivities(true); - if(updatelistener!=null && prefsManager!=null) prefsManager.unregisterListener(); + if (updatelistener != null && prefsManager != null) prefsManager.unregisterListener(); locmgr.removeUpdates(locListener); } @Override protected void onResume() { super.onResume(); fh.setBlockAllActivities(false); - if(updatelistener!=null && prefsManager!=null) { + if (updatelistener != null && prefsManager != null) { prefsManager.registerListener(); - if(prefsManager.isDBUpdating(true)){ + if (prefsManager.isDBUpdating(true)) { createDefaultSnackbar(); } } - if(pendingNearbyStopsRequest) + if (pendingNearbyStopsRequest) handler.post(new NearbyStopsRequester()); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); actionHelpMenuItem = menu.findItem(R.id.action_help); return true; } /** * Callback fired when a MenuItem is selected * * @param item * @return */ @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. switch (item.getItemId()) { case android.R.id.home: // Respond to the action bar's Up/Home button NavUtils.navigateUpFromSameTask(this); return true; case R.id.action_help: showHints(); return true; case R.id.action_favorites: startActivity(new Intent(ActivityMain.this, ActivityFavorites.class)); return true; case R.id.action_about: startActivity(new Intent(ActivityMain.this, ActivityAbout.class)); return true; case R.id.action_news: openIceweasel("https://gitpull.it/w/librebusto/#how-to-get-news"); return true; case R.id.action_bugs: openIceweasel("https://gitpull.it/w/librebusto/#how-to-create-a-bug-feature"); return true; case R.id.action_source: openIceweasel("https://gitpull.it/w/librebusto/#how-to-hack-busto"); return true; case R.id.action_licence: openIceweasel("https://www.gnu.org/licenses/gpl-3.0.html"); return true; case R.id.action_settings: - Log.d("MAINBusTO","Pressed button preferences"); - startActivity(new Intent(ActivityMain.this,ActivitySettings.class)); + Log.d("MAINBusTO", "Pressed button preferences"); + startActivity(new Intent(ActivityMain.this, ActivitySettings.class)); } return super.onOptionsItemSelected(item); } /** * OK this is pure shit * * @param v View clicked */ public void onSearchClick(View v) { if (searchMode == SEARCH_BY_ID) { String busStopID = busStopSearchByIDEditText.getText().toString(); //OLD ASYNCTASK //new asyncWgetBusStopFromBusStopID(busStopID, ArrivalFetchersRecursionHelper, lastSuccessfullySearchedBusStop); - if(busStopID == null || busStopID.length() <= 0) { + if (busStopID == null || busStopID.length() <= 0) { showMessage(R.string.insert_bus_stop_number_error); toggleSpinner(false); - } else{ - new AsyncDataDownload(AsyncDataDownload.RequestType.ARRIVALS,fh).execute(busStopID); - Log.d("MainActiv","Started search for arrivals of stop "+busStopID); + } else { + new AsyncDataDownload(AsyncDataDownload.RequestType.ARRIVALS, fh).execute(busStopID); + Log.d("MainActiv", "Started search for arrivals of stop " + busStopID); } } else { // searchMode == SEARCH_BY_NAME String query = busStopSearchByNameEditText.getText().toString(); //new asyncWgetBusStopSuggestions(query, stopsDB, StopsFindersByNameRecursionHelper); - new AsyncDataDownload(AsyncDataDownload.RequestType.STOPS,fh).execute(query); + new AsyncDataDownload(AsyncDataDownload.RequestType.STOPS, fh).execute(query); } } - /** PERMISSION STUFF **/ + + /** + * PERMISSION STUFF + **/ @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - switch (requestCode){ + switch (requestCode) { case PERMISSION_REQUEST_POSITION: - if(grantResults.length>0 && grantResults[0]==PackageManager.PERMISSION_GRANTED){ - setOption(LOCATION_PERMISSION_GIVEN,true); + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + setOption(LOCATION_PERMISSION_GIVEN, true); //if we sent a request for a new NearbyStopsFragment - if(pendingNearbyStopsRequest){ - pendingNearbyStopsRequest=false; + if (pendingNearbyStopsRequest) { + pendingNearbyStopsRequest = false; handler.post(new NearbyStopsRequester()); } } else { //permission denied - setOption(LOCATION_PERMISSION_GIVEN,false); + setOption(LOCATION_PERMISSION_GIVEN, false); } - //add other cases for permissions + //add other cases for permissions } } @Override public void createFragmentForStop(String ID) { //new asyncWgetBusStopFromBusStopID(ID, ArrivalFetchersRecursionHelper,lastSuccessfullySearchedBusStop); - if(ID == null || ID.length() <= 0) { + if (ID == null || ID.length() <= 0) { // we're still in UI thread, no need to mess with Progress showMessage(R.string.insert_bus_stop_number_error); toggleSpinner(false); } else { - new AsyncDataDownload(AsyncDataDownload.RequestType.ARRIVALS,fh).execute(ID); - Log.d("MainActiv","Started search for arrivals of stop "+ID); + new AsyncDataDownload(AsyncDataDownload.RequestType.ARRIVALS, fh).execute(ID); + Log.d("MainActiv", "Started search for arrivals of stop " + ID); } } - /** * QR scan button clicked * * @param v View QRButton clicked */ public void onQRButtonClick(View v) { IntentIntegrator integrator = new IntentIntegrator(this); integrator.initiateScan(); } /** * Receive the Barcode Scanner Intent - * */ public void onActivityResult(int requestCode, int resultCode, Intent intent) { IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent); Uri uri; try { uri = Uri.parse(scanResult != null ? scanResult.getContents() : null); // this apparently prevents NullPointerException. Somehow. } catch (NullPointerException e) { Toast.makeText(getApplicationContext(), R.string.no_qrcode, Toast.LENGTH_SHORT).show(); return; } String busStopID = getBusStopIDFromUri(uri); busStopSearchByIDEditText.setText(busStopID); createFragmentForStop(busStopID); } public void onHideHint(View v) { hideHints(); setOption(OPTION_SHOW_LEGEND, false); } public void onToggleKeyboardLayout(View v) { if (searchMode == SEARCH_BY_NAME) { setSearchModeBusStopID(); if (busStopSearchByIDEditText.requestFocus()) { showKeyboard(); } } else { // searchMode == SEARCH_BY_ID setSearchModeBusStopName(); if (busStopSearchByNameEditText.requestFocus()) { showKeyboard(); } } } - private void createDefaultSnackbar(){ - if(snackbar==null){ - snackbar = Snackbar.make(findViewById(R.id.searchButton),R.string.database_update_message,Snackbar.LENGTH_INDEFINITE); + + private void createDefaultSnackbar() { + if (snackbar == null) { + snackbar = Snackbar.make(findViewById(R.id.searchButton), R.string.database_update_message, Snackbar.LENGTH_INDEFINITE); } snackbar.show(); } ///////////////////////////////// POSITION STUFF////////////////////////////////////////////// - private void resolveStopRequest(String provider){ - Log.d(DEBUG_TAG,"Provider "+provider+" got enabled"); - if(locmgr!=null && pendingNearbyStopsRequest && locmgr.getProvider(provider).meetsCriteria(cr)){ + private void resolveStopRequest(String provider) { + Log.d(DEBUG_TAG, "Provider " + provider + " got enabled"); + if (locmgr != null && pendingNearbyStopsRequest && locmgr.getProvider(provider).meetsCriteria(cr)) { pendingNearbyStopsRequest = false; handler.post(new NearbyStopsRequester()); } } + final LocationListener locListener = new LocationListener() { @Override public void onLocationChanged(Location location) { - Log.d(DEBUG_TAG,"Location changed"); + Log.d(DEBUG_TAG, "Location changed"); } @Override public void onStatusChanged(String provider, int status, Bundle extras) { - Log.d(DEBUG_TAG,"Location provider status: "+status); - if(status== LocationProvider.AVAILABLE){ - resolveStopRequest(provider); - } + Log.d(DEBUG_TAG, "Location provider status: " + status); + if (status == LocationProvider.AVAILABLE) { + resolveStopRequest(provider); + } } @Override public void onProviderEnabled(String provider) { resolveStopRequest(provider); } @Override public void onProviderDisabled(String provider) { } }; - class NearbyStopsRequester implements Runnable{ + class NearbyStopsRequester implements Runnable { @SuppressLint("MissingPermission") @Override public void run() { final boolean canRunPosition = Build.VERSION.SDK_INT < Build.VERSION_CODES.M || getOption(LOCATION_PERMISSION_GIVEN, false); - if(!canRunPosition){ + if (!canRunPosition) { pendingNearbyStopsRequest = true; assertLocationPermissions(); return; - } else setOption(LOCATION_PERMISSION_GIVEN,true); + } else setOption(LOCATION_PERMISSION_GIVEN, true); LocationManager locManager = (LocationManager) getSystemService(LOCATION_SERVICE); - if(locManager == null) { + if (locManager == null) { Log.e(DEBUG_TAG, "location manager is nihil, cannot create NearbyStopsFragment"); return; } - if(anyLocationProviderMatchesCriteria(locManager,cr,true) && fh.getLastSuccessfullySearchedBusStop()==null) { + if (anyLocationProviderMatchesCriteria(locManager, cr, true) && fh.getLastSuccessfullySearchedBusStop() == null) { //Go ahead with the request - Log.d("mainActivity","Recreating stop fragment"); + Log.d("mainActivity", "Recreating stop fragment"); swipeRefreshLayout.setVisibility(View.VISIBLE); NearbyStopsFragment fragment = NearbyStopsFragment.newInstance(NearbyStopsFragment.TYPE_STOPS); Fragment oldFrag = framan.findFragmentById(R.id.resultFrame); FragmentTransaction ft = framan.beginTransaction(); - if(oldFrag!=null) + if (oldFrag != null) ft.remove(oldFrag); - ft.add(R.id.resultFrame,fragment,"nearbyStop_correct"); + ft.add(R.id.resultFrame, fragment, "nearbyStop_correct"); ft.commit(); framan.executePendingTransactions(); pendingNearbyStopsRequest = false; - } else if(!anyLocationProviderMatchesCriteria(locManager,cr,true)){ + } else if (!anyLocationProviderMatchesCriteria(locManager, cr, true)) { //Wait for the providers - Log.d(DEBUG_TAG,"Queuing position request"); + Log.d(DEBUG_TAG, "Queuing position request"); pendingNearbyStopsRequest = true; - locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,10,0.1f,locListener); + locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10, 0.1f, locListener); } } } - private boolean anyLocationProviderMatchesCriteria(LocationManager mng, Criteria cr, boolean enabled){ - List providers = mng.getProviders(cr,enabled); - Log.d(DEBUG_TAG,"Getting enabled location providers: "); - for(String s: providers){ - Log.d(DEBUG_TAG,"Provider "+s); + private boolean anyLocationProviderMatchesCriteria(LocationManager mng, Criteria cr, boolean enabled) { + List providers = mng.getProviders(cr, enabled); + Log.d(DEBUG_TAG, "Getting enabled location providers: "); + for (String s : providers) { + Log.d(DEBUG_TAG, "Provider " + s); } - return providers.size()>0; + return providers.size() > 0; } - ///////////////////////////////// OTHER STUFF ////////////////////////////////////////////////// /** * Get the last successfully searched bus stop or NULL * * @return */ @Override public Stop getLastSuccessfullySearchedBusStop() { return fh.getLastSuccessfullySearchedBusStop(); } /** * Get the last successfully searched bus stop ID or NULL * * @return */ @Override public String getLastSuccessfullySearchedBusStopID() { Stop stop = getLastSuccessfullySearchedBusStop(); return stop == null ? null : stop.ID; } /** * Update the star "Add to favorite" icon */ @Override public void updateStarIconFromLastBusStop() { + + // no favorites no party! + addToFavorites = (ImageButton) findViewById(R.id.addToFavorites); + if (addToFavorites == null) { + Log.d("MainActivity", "Why the fuck the star is not here?!"); + return; + } + // check if there is a last Stop String stopID = getLastSuccessfullySearchedBusStopID(); - if(stopID == null) { - // TODO: hide the star + if (stopID == null) { + addToFavorites.setVisibility(View.INVISIBLE); } else { // filled or outline? - if(isStopInFavorites(stopID)) { - // TODO: fill star + if (isStopInFavorites(stopID)) { + addToFavorites.setImageResource(R.drawable.ic_star_filled); } else { - // TODO: outline star + addToFavorites.setImageResource(R.drawable.ic_star_outline); } - // TODO: show the star + addToFavorites.setVisibility(View.VISIBLE); } } /** * Check if the last Bus Stop is in the favorites * * @return */ public boolean isStopInFavorites(String busStopId) { boolean found = false; // no stop no party - if(busStopId != null) { + if (busStopId != null) { SQLiteDatabase userDB = new UserDB(getApplicationContext()).getReadableDatabase(); found = UserDB.isStopInFavorites(userDB, busStopId); } return found; } /** * Add the last Stop to favorites */ @Override public void toggleLastStopToFavorites() { Stop stop = getLastSuccessfullySearchedBusStop(); - if(stop != null) { + if (stop != null) { // toggle the status in background new AsyncStopFavoriteAction(getApplicationContext(), AsyncStopFavoriteAction.Action.TOGGLE) { /** * Callback fired when the Stop is saved in the favorites * @param result */ @Override protected void onPostExecute(Boolean result) { super.onPostExecute(result); + // update the star icon updateStarIconFromLastBusStop(); } }.execute(stop); } else { // this case have no sense, but just immediately update the favorite icon updateStarIconFromLastBusStop(); } } @Override public void showFloatingActionButton(boolean yes) { - if(yes) floatingActionButton.show(); + if (yes) floatingActionButton.show(); else floatingActionButton.hide(); } @Override public void enableRefreshLayout(boolean yes) { swipeRefreshLayout.setEnabled(yes); } ////////////////////////////////////// GUI HELPERS ///////////////////////////////////////////// @Override public void showKeyboard() { InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); View view = searchMode == SEARCH_BY_ID ? busStopSearchByIDEditText : busStopSearchByNameEditText; imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT); } @Override public void showMessage(int messageID) { Toast.makeText(getApplicationContext(), messageID, Toast.LENGTH_SHORT).show(); } private void setSearchModeBusStopID() { searchMode = SEARCH_BY_ID; busStopSearchByNameEditText.setVisibility(View.GONE); busStopSearchByNameEditText.setText(""); busStopSearchByIDEditText.setVisibility(View.VISIBLE); floatingActionButton.setImageResource(R.drawable.alphabetical); } private void setSearchModeBusStopName() { searchMode = SEARCH_BY_NAME; busStopSearchByIDEditText.setVisibility(View.GONE); busStopSearchByIDEditText.setText(""); busStopSearchByNameEditText.setVisibility(View.VISIBLE); floatingActionButton.setImageResource(R.drawable.numeric); } /** * Having that cursor at the left of the edit text makes me cancer. + * * @param busStopID bus stop ID */ private void setBusStopSearchByIDEditText(String busStopID) { busStopSearchByIDEditText.setText(busStopID); busStopSearchByIDEditText.setSelection(busStopID.length()); } private void showHints() { howDoesItWorkTextView.setVisibility(View.VISIBLE); hideHintButton.setVisibility(View.VISIBLE); actionHelpMenuItem.setVisible(false); } private void hideHints() { howDoesItWorkTextView.setVisibility(View.GONE); hideHintButton.setVisibility(View.GONE); actionHelpMenuItem.setVisible(true); } //TODO: toggle spinner from mainActivity @Override public void toggleSpinner(boolean enable) { if (enable) { //already set by the RefreshListener when needed //swipeRefreshLayout.setRefreshing(true); progressBar.setVisibility(View.VISIBLE); } else { swipeRefreshLayout.setRefreshing(false); progressBar.setVisibility(View.GONE); } } private void prepareGUIForBusLines() { swipeRefreshLayout.setEnabled(true); swipeRefreshLayout.setVisibility(View.VISIBLE); actionHelpMenuItem.setVisible(true); } private void prepareGUIForBusStops() { swipeRefreshLayout.setEnabled(false); swipeRefreshLayout.setVisibility(View.VISIBLE); actionHelpMenuItem.setVisible(false); } /** * This provides a temporary fix to make the transition * to a single asynctask go smoother + * * @param fragmentType the type of fragment created */ @Override public void readyGUIfor(FragmentKind fragmentType) { hideKeyboard(); //if we are getting results, already, stop waiting for nearbyStops - if(pendingNearbyStopsRequest && (fragmentType==FragmentKind.ARRIVALS || fragmentType==FragmentKind.STOPS)) { + if (pendingNearbyStopsRequest && (fragmentType == FragmentKind.ARRIVALS || fragmentType == FragmentKind.STOPS)) { locmgr.removeUpdates(locListener); pendingNearbyStopsRequest = false; } - if(fragmentType==null) Log.e("ActivityMain","Problem with fragmentType"); + if (fragmentType == null) Log.e("ActivityMain", "Problem with fragmentType"); else - switch (fragmentType){ - case ARRIVALS: - prepareGUIForBusLines(); - if (getOption(OPTION_SHOW_LEGEND, true)) { - showHints(); - } - break; - case STOPS: - prepareGUIForBusStops(); - break; - default: - Log.e("BusTO Activity","Called readyGUI with unsupported type of Fragment"); - return; - } + switch (fragmentType) { + case ARRIVALS: + prepareGUIForBusLines(); + if (getOption(OPTION_SHOW_LEGEND, true)) { + showHints(); + } + break; + case STOPS: + prepareGUIForBusStops(); + break; + default: + Log.e("BusTO Activity", "Called readyGUI with unsupported type of Fragment"); + return; + } // Shows hints } /** * Open an URL in the default browser. * * @param url URL */ public void openIceweasel(String url) { Intent browserIntent1 = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); startActivity(browserIntent1); } ///////////////////// INTENT HELPER //////////////////////////////////////////////////////////// /** * Try to extract the bus stop ID from a URi * * @param uri The URL * @return bus stop ID or null */ public static String getBusStopIDFromUri(Uri uri) { String busStopID; // everithing catches fire when passing null to a switch. String host = uri.getHost(); - if(host == null) { + if (host == null) { Log.e("ActivityMain", "Not an URL: " + uri); return null; } - switch(host) { + switch (host) { case "m.gtt.to.it": // http://m.gtt.to.it/m/it/arrivi.jsp?n=1254 busStopID = uri.getQueryParameter("n"); if (busStopID == null) { Log.e("ActivityMain", "Expected ?n from: " + uri); } break; case "www.gtt.to.it": case "gtt.to.it": // http://www.gtt.to.it/cms/percorari/arrivi?palina=1254 busStopID = uri.getQueryParameter("palina"); if (busStopID == null) { Log.e("ActivityMain", "Expected ?palina from: " + uri); } break; default: Log.e("ActivityMain", "Unexpected intent URL: " + uri); busStopID = null; } return busStopID; } + public void changeStarType(String stopID) { + if (isStopInFavorites(stopID)) { + changeStarFilled(); + } else { + changeStarOutline(); + } + } + + public void changeStarFilled() { + addToFavorites.setImageResource(R.drawable.ic_star_filled); + } + public void changeStarOutline() { + addToFavorites.setImageResource(R.drawable.ic_star_outline); + } } \ No newline at end of file diff --git a/src/it/reyboz/bustorino/fragments/ArrivalsFragment.java b/src/it/reyboz/bustorino/fragments/ArrivalsFragment.java index 026ff70..eca8f1a 100644 --- a/src/it/reyboz/bustorino/fragments/ArrivalsFragment.java +++ b/src/it/reyboz/bustorino/fragments/ArrivalsFragment.java @@ -1,212 +1,215 @@ /* BusTO - Fragments components Copyright (C) 2018 Fabio Mazza This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ package it.reyboz.bustorino.fragments; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.util.Log; +import android.widget.ImageButton; import android.widget.TextView; import it.reyboz.bustorino.R; import it.reyboz.bustorino.backend.DBStatusManager; import it.reyboz.bustorino.middleware.AppDataProvider; import it.reyboz.bustorino.middleware.NextGenDB; import it.reyboz.bustorino.middleware.UserDB; public class ArrivalsFragment extends ResultListFragment implements LoaderManager.LoaderCallbacks { private final static String KEY_STOP_ID = "stopid"; private final static String KEY_STOP_NAME = "stopname"; private final static String DEBUG_TAG = "BUSTOArrivalsFragment"; private final static int loaderFavId = 2; private final static int loaderStopId = 1; private @Nullable String stopID,stopName; private TextView messageTextView; private DBStatusManager prefs; private DBStatusManager.OnDBUpdateStatusChangeListener listener; private boolean justCreated = false; + private ImageButton addToFavorites; + public static ArrivalsFragment newInstance(String stopID){ Bundle args = new Bundle(); args.putString(KEY_STOP_ID,stopID); ArrivalsFragment fragment = new ArrivalsFragment(); //parameter for ResultListFragment args.putSerializable(LIST_TYPE,FragmentKind.ARRIVALS); fragment.setArguments(args); return fragment; } public static ArrivalsFragment newInstance(String stopID,String stopName){ ArrivalsFragment fragment = newInstance(stopID); Bundle args = fragment.getArguments(); args.putString(KEY_STOP_NAME,stopName); fragment.setArguments(args); return fragment; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); stopID = getArguments().getString(KEY_STOP_ID); //this might really be null stopName = getArguments().getString(KEY_STOP_NAME); final ArrivalsFragment f = this; listener = new DBStatusManager.OnDBUpdateStatusChangeListener() { @Override public void onDBStatusChanged(boolean updating) { if(!updating){ getLoaderManager().restartLoader(loaderFavId,getArguments(),f); } else { final LoaderManager lm = getLoaderManager(); lm.destroyLoader(loaderFavId); lm.destroyLoader(loaderStopId); } } @Override public boolean defaultStatusValue() { return true; } }; prefs = new DBStatusManager(getContext().getApplicationContext(),listener); justCreated = true; } @Override public void onResume() { super.onResume(); LoaderManager loaderManager = getLoaderManager(); if(stopID!=null){ //refresh the arrivals if(!justCreated) mListener.createFragmentForStop(stopID); else justCreated = false; //start the loader if(prefs.isDBUpdating(true)){ prefs.registerListener(); } else { loaderManager.restartLoader(loaderFavId, getArguments(), this); } updateMessage(); } } @Nullable public String getStopID() { return stopID; } /** * Update the message in the fragment * * It may eventually change the "Add to Favorite" icon */ private void updateMessage(){ String message = null; if (stopName != null && stopID != null && stopName.length() > 0) { message = (stopID.concat(" - ").concat(stopName)); } else if(stopID!=null) { message = stopID; } else { Log.e("ArrivalsFragm"+getTag(),"NO ID FOR THIS FRAGMENT - something went horribly wrong"); } if(message!=null) { setTextViewMessage(getString(R.string.passages,message)); } // whatever is the case, update the star icon mListener.updateStarIconFromLastBusStop(); } @Override public Loader onCreateLoader(int id, Bundle args) { if(args.getString(KEY_STOP_ID)==null) return null; final String stopID = args.getString(KEY_STOP_ID); final Uri.Builder builder = AppDataProvider.getUriBuilderToComplete(); CursorLoader cl; switch (id){ case loaderFavId: builder.appendPath("favorites").appendPath(stopID); cl = new CursorLoader(getContext(),builder.build(),UserDB.getFavoritesColumnNamesAsArray,null,null,null); break; case loaderStopId: builder.appendPath("stop").appendPath(stopID); cl = new CursorLoader(getContext(),builder.build(),new String[]{NextGenDB.Contract.StopsTable.COL_NAME}, null,null,null); break; default: return null; } cl.setUpdateThrottle(500); return cl; } @Override public void onLoadFinished(Loader loader, Cursor data) { switch (loader.getId()){ case loaderFavId: final int colUserName = data.getColumnIndex(UserDB.getFavoritesColumnNamesAsArray[1]); if(data.getCount()>0){ data.moveToFirst(); final String probableName = data.getString(colUserName); if(probableName!=null && !probableName.isEmpty()){ stopName = probableName; updateMessage(); } } if(stopName == null){ //stop is not inside the favorites and wasn't provided Log.d("ArrivalsFragment"+getTag(),"Stop wasn't in the favorites and has no name, looking in the DB"); getLoaderManager().restartLoader(loaderStopId,getArguments(),this); } break; case loaderStopId: if(data.getCount()>0){ data.moveToFirst(); stopName = data.getString(data.getColumnIndex( NextGenDB.Contract.StopsTable.COL_NAME )); updateMessage(); } else { Log.w("ArrivalsFragment"+getTag(),"Stop is not inside the database... CLOISTER BELL"); } } } @Override public void onPause() { if(listener!=null) prefs.unregisterListener(); super.onPause(); } @Override public void onLoaderReset(Loader loader) { //NOTHING TO DO } } diff --git a/src/it/reyboz/bustorino/fragments/ResultListFragment.java b/src/it/reyboz/bustorino/fragments/ResultListFragment.java index 5f60158..31e5341 100644 --- a/src/it/reyboz/bustorino/fragments/ResultListFragment.java +++ b/src/it/reyboz/bustorino/fragments/ResultListFragment.java @@ -1,294 +1,314 @@ /* BusTO - Fragments components Copyright (C) 2016 Fabio Mazza This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ package it.reyboz.bustorino.fragments; import android.content.Context; +import android.database.sqlite.SQLiteDatabase; import android.os.Bundle; import android.os.Parcelable; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.widget.SwipeRefreshLayout; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.*; import android.support.design.widget.FloatingActionButton; import it.reyboz.bustorino.R; import it.reyboz.bustorino.backend.FiveTNormalizer; import it.reyboz.bustorino.backend.Palina; import it.reyboz.bustorino.backend.Route; import it.reyboz.bustorino.backend.Stop; +import it.reyboz.bustorino.middleware.UserDB; /** * This is a generalized fragment that can be used both for * * */ public class ResultListFragment extends Fragment{ // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER static final String LIST_TYPE = "list-type"; private static final String STOP_TITLE = "messageExtra"; protected static final String LIST_STATE = "list_state"; private static final String MESSAGE_TEXT_VIEW = "message_text_view"; private FragmentKind adapterKind; private boolean adapterSet = false; protected FragmentListener mListener; private TextView messageTextView; + private ImageButton addToFavorites; private FloatingActionButton fabutton; private ListView resultsListView; private ListAdapter mListAdapter = null; boolean listShown; private Parcelable mListInstanceState = null; public ResultListFragment() { // Required empty public constructor } public ListView getResultsListView() { return resultsListView; } /** * Use this factory method to create a new instance of * this fragment using the provided parameters. * * @param listType whether the list is used for STOPS or LINES (Orari) * @return A new instance of fragment ResultListFragment. */ public static ResultListFragment newInstance(FragmentKind listType, String eventualStopTitle) { ResultListFragment fragment = new ResultListFragment(); Bundle args = new Bundle(); args.putSerializable(LIST_TYPE, listType); if (eventualStopTitle != null) { args.putString(STOP_TITLE, eventualStopTitle); } fragment.setArguments(args); return fragment; } public static ResultListFragment newInstance(FragmentKind listType) { return newInstance(listType, null); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { adapterKind = (FragmentKind) getArguments().getSerializable(LIST_TYPE); } } + /** + * Check if the last Bus Stop is in the favorites + * @return + */ + public boolean isStopInFavorites(String busStopId) { + boolean found = false; + + // no stop no party + if(busStopId != null) { + SQLiteDatabase userDB = new UserDB(getContext()).getReadableDatabase(); + found = UserDB.isStopInFavorites(userDB, busStopId); + } + + return found; + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View root = inflater.inflate(R.layout.fragment_list_view, container, false); messageTextView = (TextView) root.findViewById(R.id.messageTextView); - + addToFavorites = (ImageButton) root.findViewById(R.id.addToFavorites); if (adapterKind != null) { resultsListView = (ListView) root.findViewById(R.id.resultsListView); switch (adapterKind) { case STOPS: resultsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { /* * Casting because of Javamerda * @url http://stackoverflow.com/questions/30549485/androids-list-view-parameterized-type-in-adapterview-onitemclicklistener */ Stop busStop = (Stop) parent.getItemAtPosition(position); mListener.createFragmentForStop(busStop.ID); } }); //set the textviewMessage setTextViewMessage(getString(R.string.results)); break; case ARRIVALS: resultsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { String routeName; Route r = (Route) parent.getItemAtPosition(position); routeName = FiveTNormalizer.routeInternalToDisplay(r.getNameForDisplay()); if (routeName == null) { routeName = r.getNameForDisplay(); } if (r.destinazione == null || r.destinazione.length() == 0) { Toast.makeText(getContext(), getString(R.string.route_towards_unknown, routeName), Toast.LENGTH_SHORT).show(); } else { Toast.makeText(getContext(), getString(R.string.route_towards_destination, routeName, r.destinazione), Toast.LENGTH_SHORT).show(); } } }); String displayName = getArguments().getString(STOP_TITLE); setTextViewMessage(String.format( getString(R.string.passages), displayName)); break; default: throw new IllegalStateException("Argument passed was not of a supported type"); } String probablemessage = getArguments().getString(MESSAGE_TEXT_VIEW); if (probablemessage != null) { //Log.d("BusTO fragment " + this.getTag(), "We have a possible message here in the savedInstaceState: " + probablemessage); messageTextView.setText(probablemessage); messageTextView.setVisibility(View.VISIBLE); } } else Log.d(getString(R.string.list_fragment_debug), "No content root for fragment"); return root; } public boolean isFragmentForTheSameStop(Palina p) { return adapterKind.equals(FragmentKind.ARRIVALS) && getTag().equals(getFragmentTag(p)); } public static String getFragmentTag(Palina p) { return p.ID; } @Override public void onResume() { super.onResume(); //Log.d(getString(R.string.list_fragment_debug),"Fragment restored, saved listAdapter is "+(mListAdapter)); if (mListAdapter != null) { ListAdapter adapter = mListAdapter; mListAdapter = null; setListAdapter(adapter); } if (mListInstanceState != null) { Log.d("resultsListView", "trying to restore instance state"); resultsListView.onRestoreInstanceState(mListInstanceState); } switch (adapterKind) { case ARRIVALS: resultsListView.setOnScrollListener(new CommonScrollListener(mListener, true)); fabutton.show(); break; case STOPS: resultsListView.setOnScrollListener(new CommonScrollListener(mListener, false)); break; default: //NONE } mListener.readyGUIfor(adapterKind); } @Override public void onPause() { if (adapterKind.equals(FragmentKind.ARRIVALS)) { SwipeRefreshLayout reflay = (SwipeRefreshLayout) getActivity().findViewById(R.id.listRefreshLayout); reflay.setEnabled(false); Log.d("BusTO Fragment " + this.getTag(), "RefreshLayout disabled"); } super.onPause(); } @Override public void onAttach(Context context) { super.onAttach(context); if (context instanceof FragmentListener) { mListener = (FragmentListener) context; fabutton = (FloatingActionButton) getActivity().findViewById(R.id.floatingActionButton); } else { throw new RuntimeException(context.toString() + " must implement ResultFragmentListener"); } } @Override public void onDetach() { mListener = null; if (fabutton != null) fabutton.show(); super.onDetach(); } @Override public void onDestroyView() { resultsListView = null; //Log.d(getString(R.string.list_fragment_debug), "called onDestroyView"); getArguments().putString(MESSAGE_TEXT_VIEW, messageTextView.getText().toString()); super.onDestroyView(); } @Override public void onViewStateRestored(@Nullable Bundle savedInstanceState) { super.onViewStateRestored(savedInstanceState); Log.d("ResultListFragment", "onViewStateRestored"); if (savedInstanceState != null) { mListInstanceState = savedInstanceState.getParcelable(LIST_STATE); Log.d("ResultListFragment", "listInstanceStatePresent :" + mListInstanceState); } } public void setListAdapter(ListAdapter adapter) { boolean hadAdapter = mListAdapter != null; mListAdapter = adapter; if (resultsListView != null) { resultsListView.setAdapter(adapter); resultsListView.setVisibility(View.VISIBLE); } } /** * Set the message textView * @param message the whole message to write in the textView */ public void setTextViewMessage(String message) { messageTextView.setText(message); switch (adapterKind) { case ARRIVALS: - messageTextView.setClickable(true); - messageTextView.setOnClickListener(new View.OnClickListener() { + addToFavorites.setClickable(true); + addToFavorites.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // add/remove the stop in the favorites mListener.toggleLastStopToFavorites(); } }); break; case STOPS: - messageTextView.setClickable(false); + addToFavorites.setClickable(false); break; } + messageTextView.setVisibility(View.VISIBLE); } -} +} \ No newline at end of file