Changeset View
Changeset View
Standalone View
Standalone View
src/it/reyboz/bustorino/fragments/LinesFragment.kt
Show All 13 Lines | BusTO - Fragments components | ||||
You should have received a copy of the GNU General Public License | You should have received a copy of the GNU General Public License | ||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
*/ | */ | ||||
package it.reyboz.bustorino.fragments | package it.reyboz.bustorino.fragments | ||||
import android.content.Context | import android.content.Context | ||||
import android.os.Bundle | import android.os.Bundle | ||||
import android.os.Parcelable | |||||
import android.util.Log | import android.util.Log | ||||
import android.view.* | import android.view.* | ||||
import android.widget.* | import android.widget.* | ||||
import android.widget.AdapterView.INVALID_POSITION | import android.widget.AdapterView.INVALID_POSITION | ||||
import android.widget.AdapterView.OnItemSelectedListener | import android.widget.AdapterView.OnItemSelectedListener | ||||
import androidx.lifecycle.ViewModelProvider | import androidx.lifecycle.ViewModelProvider | ||||
import androidx.recyclerview.widget.LinearLayoutManager | import androidx.recyclerview.widget.LinearLayoutManager | ||||
import androidx.recyclerview.widget.RecyclerView | import androidx.recyclerview.widget.RecyclerView | ||||
import it.reyboz.bustorino.R | import it.reyboz.bustorino.R | ||||
import it.reyboz.bustorino.adapters.NameCapitalize | import it.reyboz.bustorino.adapters.NameCapitalize | ||||
import it.reyboz.bustorino.adapters.StopAdapterListener | import it.reyboz.bustorino.adapters.StopAdapterListener | ||||
import it.reyboz.bustorino.adapters.StopRecyclerAdapter | import it.reyboz.bustorino.adapters.StopRecyclerAdapter | ||||
import it.reyboz.bustorino.backend.Stop | import it.reyboz.bustorino.backend.Stop | ||||
import it.reyboz.bustorino.data.gtfs.GtfsRoute | import it.reyboz.bustorino.data.gtfs.GtfsRoute | ||||
import it.reyboz.bustorino.data.gtfs.MatoPatternWithStops | import it.reyboz.bustorino.data.gtfs.MatoPatternWithStops | ||||
import it.reyboz.bustorino.data.gtfs.PatternStop | import it.reyboz.bustorino.data.gtfs.PatternStop | ||||
import it.reyboz.bustorino.util.LinesNameSorter | import it.reyboz.bustorino.util.LinesNameSorter | ||||
import it.reyboz.bustorino.util.PatternWithStopsSorter | import it.reyboz.bustorino.util.PatternWithStopsSorter | ||||
class LinesFragment : ScreenBaseFragment() { | class LinesFragment : ScreenBaseFragment() { | ||||
companion object { | companion object { | ||||
fun newInstance(){ | fun newInstance(){ | ||||
val fragment = LinesFragment() | LinesFragment() | ||||
} | } | ||||
const val DEBUG_TAG="BusTO-LinesFragment" | const val DEBUG_TAG="BusTO-LinesFragment" | ||||
const val FRAGMENT_TAG="LinesFragment" | const val FRAGMENT_TAG="LinesFragment" | ||||
val patternStopsComparator = PatternWithStopsSorter() | val patternStopsComparator = PatternWithStopsSorter() | ||||
} | } | ||||
Show All 12 Lines | class LinesFragment : ScreenBaseFragment() { | ||||
private var linesAdapter: ArrayAdapter<String>? = null | private var linesAdapter: ArrayAdapter<String>? = null | ||||
private var patternsAdapter: ArrayAdapter<String>? = null | private var patternsAdapter: ArrayAdapter<String>? = null | ||||
private var mListener: CommonFragmentListener? = null | private var mListener: CommonFragmentListener? = null | ||||
private val linesNameSorter = LinesNameSorter() | private val linesNameSorter = LinesNameSorter() | ||||
private val linesComparator = Comparator<GtfsRoute> { a,b -> | private val linesComparator = Comparator<GtfsRoute> { a,b -> | ||||
return@Comparator linesNameSorter.compare(a.shortName, b.shortName) | return@Comparator linesNameSorter.compare(a.shortName, b.shortName) | ||||
} | } | ||||
private var firstClick = true; | private var firstClick = true | ||||
private var recyclerViewState:Parcelable? = null | |||||
private var patternsSpinnerState:Parcelable? = null | |||||
private val adapterListener = object : StopAdapterListener { | private val adapterListener = object : StopAdapterListener { | ||||
override fun onTappedStop(stop: Stop?) { | override fun onTappedStop(stop: Stop?) { | ||||
//var r = "" | //var r = "" | ||||
//stop?.let { r= it.stopDisplayName.toString() } | //stop?.let { r= it.stopDisplayName.toString() } | ||||
if(viewModel.shouldShowMessage) { | if(viewModel.shouldShowMessage) { | ||||
Toast.makeText(context, R.string.long_press_stop_4_options, Toast.LENGTH_SHORT).show() | Toast.makeText(context, R.string.long_press_stop_4_options, Toast.LENGTH_SHORT).show() | ||||
viewModel.shouldShowMessage=false | viewModel.shouldShowMessage=false | ||||
Show All 10 Lines | private val adapterListener = object : StopAdapterListener { | ||||
} | } | ||||
override fun onLongPressOnStop(stop: Stop?): Boolean { | override fun onLongPressOnStop(stop: Stop?): Boolean { | ||||
Log.d(DEBUG_TAG, "LongPressOnStop") | Log.d(DEBUG_TAG, "LongPressOnStop") | ||||
return true | return true | ||||
} | } | ||||
} | } | ||||
override fun onSaveInstanceState(outState: Bundle) { | |||||
super.onSaveInstanceState(outState) | |||||
Log.d(DEBUG_TAG, "saveInstanceState bundle: $outState") | |||||
} | |||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, | ||||
savedInstanceState: Bundle?): View? { | savedInstanceState: Bundle?): View? { | ||||
val rootView = inflater.inflate(R.layout.fragment_lines, container, false) | val rootView = inflater.inflate(R.layout.fragment_lines, container, false) | ||||
linesSpinner = rootView.findViewById(R.id.linesSpinner) | linesSpinner = rootView.findViewById(R.id.linesSpinner) | ||||
patternsSpinner = rootView.findViewById(R.id.patternsSpinner) | patternsSpinner = rootView.findViewById(R.id.patternsSpinner) | ||||
routeDescriptionTextView = rootView.findViewById(R.id.routeDescriptionTextView) | routeDescriptionTextView = rootView.findViewById(R.id.routeDescriptionTextView) | ||||
stopsRecyclerView = rootView.findViewById(R.id.patternStopsRecyclerView) | stopsRecyclerView = rootView.findViewById(R.id.patternStopsRecyclerView) | ||||
val llManager = LinearLayoutManager(context) | val llManager = LinearLayoutManager(context) | ||||
llManager.orientation = LinearLayoutManager.VERTICAL | llManager.orientation = LinearLayoutManager.VERTICAL | ||||
stopsRecyclerView.layoutManager = llManager | stopsRecyclerView.layoutManager = llManager | ||||
//allow the context menu to be opened | //allow the context menu to be opened | ||||
registerForContextMenu(stopsRecyclerView) | registerForContextMenu(stopsRecyclerView) | ||||
Log.d(DEBUG_TAG, "Called onCreateView for LinesFragment") | |||||
Log.d(DEBUG_TAG, "OnCreateView, selected line spinner pos: ${linesSpinner.selectedItemPosition}") | |||||
Log.d(DEBUG_TAG, "OnCreateView, selected patterns spinner pos: ${patternsSpinner.selectedItemPosition}") | |||||
//set requests | |||||
viewModel.routesGTTLiveData.observe(viewLifecycleOwner) { | |||||
setRoutes(it) | |||||
} | |||||
viewModel.patternsWithStopsByRouteLiveData.observe(viewLifecycleOwner){ | |||||
patterns -> | |||||
run { | |||||
currentPatterns = patterns.sortedBy { p-> p.pattern.code } | |||||
//patterns. //sortedBy {-1*it.stopsIndices.size}// "${p.pattern.directionId} - ${p.pattern.headsign}" } | |||||
patternsAdapter?.let { | |||||
it.clear() | |||||
it.addAll(currentPatterns.map { p->"${p.pattern.directionId} - ${p.pattern.headsign}" }) | |||||
it.notifyDataSetChanged() | |||||
} | |||||
val pos = patternsSpinner.selectedItemPosition | |||||
//might be possible that the selectedItem is different (larger than list size) | |||||
if(pos!= INVALID_POSITION && pos >= 0 && (pos < currentPatterns.size)){ | |||||
val p = currentPatterns[pos] | |||||
Log.d(DEBUG_TAG, "Setting patterns with pos $pos and p gtfsID ${p.pattern.code}") | |||||
setPatternAndReqStops(currentPatterns[pos]) | |||||
} | |||||
} | |||||
} | |||||
viewModel.stopsForPatternLiveData.observe(viewLifecycleOwner){stops-> | |||||
Log.d("BusTO-LinesFragment", "Setting stops from DB") | |||||
setCurrentStops(stops) | |||||
} | |||||
if(context!=null) { | if(context!=null) { | ||||
patternsAdapter = ArrayAdapter(context!!, android.R.layout.simple_spinner_dropdown_item, ArrayList<String>()) | patternsAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_dropdown_item, ArrayList<String>()) | ||||
patternsSpinner.adapter = patternsAdapter | patternsSpinner.adapter = patternsAdapter | ||||
linesAdapter = ArrayAdapter(context!!, android.R.layout.simple_spinner_dropdown_item, ArrayList<String>()) | linesAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_dropdown_item, ArrayList<String>()) | ||||
linesSpinner.adapter = linesAdapter | linesSpinner.adapter = linesAdapter | ||||
if (linesSpinner.onItemSelectedListener != null){ | |||||
Log.d(DEBUG_TAG, "linesSpinner listener != null") | |||||
} | |||||
linesSpinner.onItemSelectedListener = object: OnItemSelectedListener{ | linesSpinner.onItemSelectedListener = object: OnItemSelectedListener{ | ||||
override fun onItemSelected(p0: AdapterView<*>?, p1: View?, pos: Int, p3: Long) { | override fun onItemSelected(p0: AdapterView<*>?, p1: View?, pos: Int, p3: Long) { | ||||
val selRoute = currentRoutes.get(pos) | val selRoute = currentRoutes.get(pos) | ||||
routeDescriptionTextView.text = selRoute.longName | routeDescriptionTextView.text = selRoute.longName | ||||
val oldRoute = viewModel.getRouteIDQueried() | val oldRoute = viewModel.getRouteIDQueried() | ||||
val resetSpinner = (oldRoute != null) && (oldRoute.trim() != selRoute.gtfsId.trim()) | val resetSpinner = (oldRoute != null) && (oldRoute.trim() != selRoute.gtfsId.trim()) | ||||
Log.d(DEBUG_TAG, "Selected route: ${selRoute.gtfsId}, reset spinner: $resetSpinner") | Log.d(DEBUG_TAG, "Selected route: ${selRoute.gtfsId}, reset spinner: $resetSpinner, oldRoute: $oldRoute") | ||||
//launch query for this gtfsID | //launch query for this gtfsID | ||||
viewModel.setRouteIDQuery(selRoute.gtfsId) | viewModel.setRouteIDQuery(selRoute.gtfsId) | ||||
//reset spinner position | //reset spinner position | ||||
if(resetSpinner) patternsSpinner.setSelection(0) | if(resetSpinner) patternsSpinner.setSelection(0) | ||||
} | } | ||||
override fun onNothingSelected(p0: AdapterView<*>?) { | override fun onNothingSelected(p0: AdapterView<*>?) { | ||||
Show All 23 Lines | override fun onAttach(context: Context) { | ||||
mListener = context | mListener = context | ||||
else throw RuntimeException(context.toString() | else throw RuntimeException(context.toString() | ||||
+ " must implement CommonFragmentListener") | + " must implement CommonFragmentListener") | ||||
} | } | ||||
override fun onResume() { | override fun onResume() { | ||||
super.onResume() | super.onResume() | ||||
mListener?.readyGUIfor(FragmentKind.LINES) | mListener?.readyGUIfor(FragmentKind.LINES) | ||||
Log.d(DEBUG_TAG, "Resuming lines fragment") | |||||
//Log.d(DEBUG_TAG, "OnResume, selected line spinner pos: ${linesSpinner.selectedItemPosition}") | |||||
//Log.d(DEBUG_TAG, "OnResume, selected patterns spinner pos: ${patternsSpinner.selectedItemPosition}") | |||||
} | } | ||||
override fun onActivityCreated(savedInstanceState: Bundle?) { | override fun onCreate(savedInstanceState: Bundle?) { | ||||
super.onActivityCreated(savedInstanceState) | super.onCreate(savedInstanceState) | ||||
viewModel = ViewModelProvider(this).get(LinesViewModel::class.java) | viewModel = ViewModelProvider(this).get(LinesViewModel::class.java) | ||||
Log.d(DEBUG_TAG, "Fragment onCreate") | |||||
//val lines = viewModel.(); | |||||
viewModel.routesGTTLiveData.observe(this) { | |||||
setRoutes(it) | |||||
} | } | ||||
viewModel.patternsWithStopsByRouteLiveData.observe(this){ | override fun getBaseViewForSnackBar(): View? { | ||||
patterns -> | return null | ||||
run { | |||||
currentPatterns = patterns.sortedBy { p-> p.pattern.code } | |||||
//patterns. //sortedBy {-1*it.stopsIndices.size}// "${p.pattern.directionId} - ${p.pattern.headsign}" } | |||||
patternsAdapter?.let { | |||||
it.clear() | |||||
it.addAll(currentPatterns.map { p->"${p.pattern.directionId} - ${p.pattern.headsign}" }) | |||||
it.notifyDataSetChanged() | |||||
} | } | ||||
val pos = patternsSpinner.selectedItemPosition | private fun setRoutes(routes: List<GtfsRoute>){ | ||||
//might be possible that the selectedItem is different (larger than list size) | Log.d(DEBUG_TAG, "Resetting routes") | ||||
if(pos!= INVALID_POSITION && pos >= 0 && (pos < currentPatterns.size)){ | currentRoutes = routes.sortedWith<GtfsRoute>(linesComparator) | ||||
setPatternAndReqStops(currentPatterns[pos]) | |||||
} | |||||
} | if (linesAdapter!=null){ | ||||
} | |||||
viewModel.stopsForPatternLiveData.observe(this){stops-> | var selGtfsRoute = viewModel.getRouteIDQueried() | ||||
Log.d("BusTO-LinesFragment", "Setting stops from DB") | var selPatternIndex = 0 | ||||
setCurrentStops(stops) | if(selGtfsRoute == null){ | ||||
selGtfsRoute ="" | |||||
} | } | ||||
val adapter = linesAdapter!! | |||||
if (adapter.isEmpty) { | |||||
Log.d(DEBUG_TAG, "Lines adapter is empty") | |||||
} | } | ||||
else{ | |||||
adapter.clear() | |||||
override fun getBaseViewForSnackBar(): View? { | |||||
return null | |||||
} | } | ||||
adapter.addAll(currentRoutes.map { r -> r.shortName }) | |||||
private fun setRoutes(routes: List<GtfsRoute>){ | adapter.notifyDataSetChanged() | ||||
currentRoutes = routes.sortedWith<GtfsRoute>(linesComparator) | for(j in 0 until currentRoutes.size){ | ||||
val route = currentRoutes[j] | |||||
if (route.gtfsId == selGtfsRoute) { | |||||
selPatternIndex = j | |||||
Log.d(DEBUG_TAG, "Route $selGtfsRoute has index $j") | |||||
} | |||||
} | |||||
linesSpinner.setSelection(selPatternIndex) | |||||
// | |||||
} | |||||
/* | |||||
linesAdapter?.clear() | linesAdapter?.clear() | ||||
linesAdapter?.addAll(currentRoutes.map { r -> r.shortName }) | linesAdapter?.addAll(currentRoutes.map { r -> r.shortName }) | ||||
linesAdapter?.notifyDataSetChanged() | linesAdapter?.notifyDataSetChanged() | ||||
*/ | |||||
} | } | ||||
private fun setCurrentStops(stops: List<Stop>){ | private fun setCurrentStops(stops: List<Stop>){ | ||||
val orderBy = currentPatternStops.withIndex().associate{it.value.stopGtfsId to it.index} | val orderBy = currentPatternStops.withIndex().associate{it.value.stopGtfsId to it.index} | ||||
val stopsSorted = stops.sortedBy { s -> orderBy[s.gtfsID] } | val stopsSorted = stops.sortedBy { s -> orderBy[s.gtfsID] } | ||||
val numStops = stopsSorted.size | val numStops = stopsSorted.size | ||||
Log.d(DEBUG_TAG, "RecyclerView adapter is: ${stopsRecyclerView.adapter}") | Log.d(DEBUG_TAG, "RecyclerView adapter is: ${stopsRecyclerView.adapter}") | ||||
var setNewAdapter = true; | var setNewAdapter = true | ||||
if(stopsRecyclerView.adapter is StopRecyclerAdapter){ | if(stopsRecyclerView.adapter is StopRecyclerAdapter){ | ||||
val adapter = stopsRecyclerView.adapter as StopRecyclerAdapter | val adapter = stopsRecyclerView.adapter as StopRecyclerAdapter | ||||
if(adapter.stops.size == stopsSorted.size && (adapter.stops.get(0).gtfsID == stopsSorted.get(0).gtfsID) | if(adapter.stops.size == stopsSorted.size && (adapter.stops.get(0).gtfsID == stopsSorted.get(0).gtfsID) | ||||
&& (adapter.stops.get(numStops-1).gtfsID == stopsSorted.get(numStops-1).gtfsID) | && (adapter.stops.get(numStops-1).gtfsID == stopsSorted.get(numStops-1).gtfsID) | ||||
){ | ){ | ||||
Log.d(DEBUG_TAG, "Found same stops on recyclerview") | Log.d(DEBUG_TAG, "Found same stops on recyclerview") | ||||
setNewAdapter = false | setNewAdapter = false | ||||
} | } | ||||
Show All 24 Lines | class LinesFragment : ScreenBaseFragment() { | ||||
override fun onCreateContextMenu(menu: ContextMenu, v: View, menuInfo: ContextMenu.ContextMenuInfo?) { | override fun onCreateContextMenu(menu: ContextMenu, v: View, menuInfo: ContextMenu.ContextMenuInfo?) { | ||||
super.onCreateContextMenu(menu, v, menuInfo) | super.onCreateContextMenu(menu, v, menuInfo) | ||||
Log.d("BusTO-LinesFragment", "Creating context menu ") | Log.d("BusTO-LinesFragment", "Creating context menu ") | ||||
if (v.id == R.id.patternStopsRecyclerView) { | if (v.id == R.id.patternStopsRecyclerView) { | ||||
// if we aren't attached to activity, return null | // if we aren't attached to activity, return null | ||||
if (activity == null) return | if (activity == null) return | ||||
val inflater = activity!!.menuInflater | val inflater = requireActivity().menuInflater | ||||
inflater.inflate(R.menu.menu_line_item, menu) | inflater.inflate(R.menu.menu_line_item, menu) | ||||
} | } | ||||
} | } | ||||
override fun onContextItemSelected(item: MenuItem): Boolean { | override fun onContextItemSelected(item: MenuItem): Boolean { | ||||
if (stopsRecyclerView.getAdapter() !is StopRecyclerAdapter) return false | if (stopsRecyclerView.getAdapter() !is StopRecyclerAdapter) return false | ||||
val adapter =stopsRecyclerView.adapter as StopRecyclerAdapter | val adapter =stopsRecyclerView.adapter as StopRecyclerAdapter | ||||
val stop = adapter.stops.get(adapter.getPosition()) | val stop = adapter.stops.get(adapter.getPosition()) | ||||
val acId = item.itemId | val acId = item.itemId | ||||
if(acId == R.id.action_view_on_map){ | if(acId == R.id.action_view_on_map){ | ||||
// view on the map | // view on the map | ||||
if ((stop.latitude == null) or (stop.longitude == null) or (mListener == null) ) { | if ((stop.latitude == null) or (stop.longitude == null) or (mListener == null) ) { | ||||
Toast.makeText(context, R.string.cannot_show_on_map_no_position, Toast.LENGTH_SHORT).show() | Toast.makeText(context, R.string.cannot_show_on_map_no_position, Toast.LENGTH_SHORT).show() | ||||
return true | return true | ||||
} | } | ||||
mListener!!.showMapCenteredOnStop(stop) | mListener!!.showMapCenteredOnStop(stop) | ||||
return true | return true | ||||
} else if (acId == R.id.action_show_arrivals){ | } else if (acId == R.id.action_show_arrivals){ | ||||
mListener?.requestArrivalsForStopID(stop.ID); | mListener?.requestArrivalsForStopID(stop.ID) | ||||
return true | return true | ||||
} | } | ||||
return false | return false | ||||
} | } | ||||
override fun onStop() { | |||||
super.onStop() | |||||
Log.d(DEBUG_TAG, "Fragment stopped") | |||||
recyclerViewState = stopsRecyclerView.layoutManager?.onSaveInstanceState() | |||||
patternsSpinnerState = patternsSpinner.onSaveInstanceState() | |||||
} | |||||
override fun onStart() { | |||||
super.onStart() | |||||
Log.d(DEBUG_TAG, "OnStart, selected line spinner pos: ${linesSpinner.selectedItemPosition}") | |||||
Log.d(DEBUG_TAG, "OnStart, selected patterns spinner pos: ${patternsSpinner.selectedItemPosition}") | |||||
if (recyclerViewState!=null){ | |||||
stopsRecyclerView.layoutManager?.onRestoreInstanceState(recyclerViewState) | |||||
} | |||||
if(patternsSpinnerState!=null){ | |||||
patternsSpinner.onRestoreInstanceState(patternsSpinnerState) | |||||
} | |||||
} | |||||
/* | |||||
override fun onDestroyView() { | |||||
super.onDestroyView() | |||||
Log.d(DEBUG_TAG, "Fragment view destroyed") | |||||
} | |||||
override fun onDestroy() { | |||||
super.onDestroy() | |||||
Log.d(DEBUG_TAG, "Fragment destroyed") | |||||
} | |||||
*/ | |||||
override fun onViewStateRestored(savedInstanceState: Bundle?) { | |||||
super.onViewStateRestored(savedInstanceState) | |||||
Log.d(DEBUG_TAG, "OnViewStateRes, bundled saveinstancestate: $savedInstanceState") | |||||
Log.d(DEBUG_TAG, "OnViewStateRes, selected line spinner pos: ${linesSpinner.selectedItemPosition}") | |||||
Log.d(DEBUG_TAG, "OnViewStateRes, selected patterns spinner pos: ${patternsSpinner.selectedItemPosition}") | |||||
} | |||||
} | } | ||||
No newline at end of file | No newline at end of file |
Public contents are in Creative Commons Attribution-ShareAlike 4.0 (CC-BY-SA) or GNU Free Documentation License (at your option) unless otherwise noted. · Contact / Register