diff --git a/res/drawable-xxxhdpi/bus_stop_background.xml b/res/drawable/bus_stop_background.xml rename from res/drawable-xxxhdpi/bus_stop_background.xml rename to res/drawable/bus_stop_background.xml diff --git a/res/drawable-xxxhdpi/bus_stop_background.xml b/res/drawable/bus_stop_background_pattern.xml rename from res/drawable-xxxhdpi/bus_stop_background.xml rename to res/drawable/bus_stop_background_pattern.xml --- a/res/drawable-xxxhdpi/bus_stop_background.xml +++ b/res/drawable/bus_stop_background_pattern.xml @@ -1,8 +1,8 @@ - + \ No newline at end of file diff --git a/res/drawable/line.xml b/res/drawable/line.xml new file mode 100644 --- /dev/null +++ b/res/drawable/line.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/res/drawable/line_drawable.xml b/res/drawable/line_drawable.xml new file mode 100644 --- /dev/null +++ b/res/drawable/line_drawable.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/res/drawable/thumb.xml b/res/drawable/thumb.xml new file mode 100644 --- /dev/null +++ b/res/drawable/thumb.xml @@ -0,0 +1,18 @@ + + + + + + + + + + \ No newline at end of file diff --git a/res/drawable/thumb_drawable.xml b/res/drawable/thumb_drawable.xml new file mode 100644 --- /dev/null +++ b/res/drawable/thumb_drawable.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/res/layout/arrivals_nearby_card.xml b/res/layout/arrivals_nearby_card.xml --- a/res/layout/arrivals_nearby_card.xml +++ b/res/layout/arrivals_nearby_card.xml @@ -8,8 +8,8 @@ android:focusable="true" android:layout_width="match_parent" android:layout_height="wrap_content" - card_view:cardCornerRadius="1dp" - android:layout_margin="8dp" android:padding="4dp"> + card_view:cardCornerRadius="5dp" + android:layout_margin="5dp" android:padding="6dp"> + android:gravity="center_vertical" + android:textStyle="normal" android:layout_marginRight="10dp" android:layout_marginEnd="10dp" + android:layout_marginBottom="10dp" android:layout_marginTop="10dp"/> + android:layout_marginStart="10dp"/> + android:paddingBottom="8dip" + android:background="?android:attr/selectableItemBackground" +> + app:layout_constraintHorizontal_bias="0.0" + app:fastScrollEnabled="true" + app:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable" + app:fastScrollHorizontalTrackDrawable="@drawable/line_drawable" + app:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable" + app:fastScrollVerticalTrackDrawable="@drawable/line_drawable" + + /> - Tocca a lungo per le opzioni + Tocca a lungo la fermata per le opzioni diff --git a/res/values/colors.xml b/res/values/colors.xml --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -4,7 +4,12 @@ #ff9800 #F57C00 #2196F3 + #2a65e8 #2060dd + + #2378e8 + #0079f5 + #009688 #4DB6AC #80cbc4 @@ -16,5 +21,6 @@ #2060DD #FFFFFF #000000 + @color/blue_mid_2 \ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -201,7 +201,10 @@ CAPITALIZE_FIRST + Show arrivals touching on stop + Enable experiments - Long press for options + Long press the stop for options + diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml --- a/res/xml/preferences.xml +++ b/res/xml/preferences.xml @@ -1,12 +1,7 @@ - - - + + + + + + diff --git a/src/it/reyboz/bustorino/adapters/StopRecyclerAdapter.java b/src/it/reyboz/bustorino/adapters/StopRecyclerAdapter.java --- a/src/it/reyboz/bustorino/adapters/StopRecyclerAdapter.java +++ b/src/it/reyboz/bustorino/adapters/StopRecyclerAdapter.java @@ -17,7 +17,6 @@ */ package it.reyboz.bustorino.adapters; -import android.util.Log; import android.view.ContextMenu; import android.view.LayoutInflater; import android.view.MenuInflater; @@ -36,7 +35,7 @@ public class StopRecyclerAdapter extends RecyclerView.Adapter { private List stops; private static final int ITEM_LAYOUT_FAVORITES = R.layout.entry_bus_stop; - private static final int ITEM_LAYOUT_LINES = R.layout.bus_stop_line_elmt; + private static final int ITEM_LAYOUT_LINES = R.layout.stop_line_element; private static final int busIcon = R.drawable.bus; private static final int trainIcon = R.drawable.subway; private static final int tramIcon = R.drawable.tram; @@ -213,7 +212,7 @@ vh.bottomStub.setVisibility(View.VISIBLE); vh.topStub.setVisibility(View.VISIBLE); if(position == 0) { - vh.topStub.setVisibility(View.GONE); + vh.topStub.setVisibility(View.INVISIBLE); } else if (position == stops.size()-1) { vh.bottomStub.setVisibility(View.GONE); diff --git a/src/it/reyboz/bustorino/backend/utils.java b/src/it/reyboz/bustorino/backend/utils.java --- a/src/it/reyboz/bustorino/backend/utils.java +++ b/src/it/reyboz/bustorino/backend/utils.java @@ -1,3 +1,20 @@ +/* + BusTO (backend components) + Copyright (C) 2019 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.backend; import android.content.Context; @@ -146,13 +163,26 @@ sb.append(subs); continue; } - sb.append(Character.toUpperCase(subs.charAt(0))); + //SPLIT ON ', check if contains "D'" + if(subs.toLowerCase(Locale.ROOT).startsWith("d'")){ + sb.append("D'"); + subs = subs.substring(2); + } + int index = 0; + char c = subs.charAt(index); + if(subs.length() > 1 && c=='('){ + sb.append(c); + index += 1; + c = subs.charAt(index); + } + sb.append(Character.toUpperCase(c)); if (lowercaseRest) - sb.append(subs.substring(1).toLowerCase(Locale.ROOT)); + sb.append(subs.substring(index+1).toLowerCase(Locale.ROOT)); else - sb.append(subs.substring(1)); + sb.append(subs.substring(index+1)); } + if(addPoint && allsubs.length == 1) sb.append('.'); sb.append(" "); /*sb.append(Character.toUpperCase(arr[i].charAt(0))); if (lowercaseRest) diff --git a/src/it/reyboz/bustorino/fragments/LinesFragment.kt b/src/it/reyboz/bustorino/fragments/LinesFragment.kt --- a/src/it/reyboz/bustorino/fragments/LinesFragment.kt +++ b/src/it/reyboz/bustorino/fragments/LinesFragment.kt @@ -36,6 +36,7 @@ import it.reyboz.bustorino.data.gtfs.MatoPatternWithStops import it.reyboz.bustorino.data.gtfs.PatternStop import it.reyboz.bustorino.util.LinesNameSorter +import it.reyboz.bustorino.util.PatternWithStopsSorter class LinesFragment : ScreenBaseFragment() { @@ -45,6 +46,8 @@ } const val DEBUG_TAG="BusTO-LinesFragment" const val FRAGMENT_TAG="LinesFragment" + + val patternStopsComparator = PatternWithStopsSorter() } @@ -68,16 +71,29 @@ private val linesComparator = Comparator { a,b -> return@Comparator linesNameSorter.compare(a.shortName, b.shortName) } + private var firstClick = true; private val adapterListener = object : StopAdapterListener { override fun onTappedStop(stop: Stop?) { //var r = "" //stop?.let { r= it.stopDisplayName.toString() } - Toast.makeText(context,R.string.long_press_for_options,Toast.LENGTH_SHORT).show() + if(viewModel.shouldShowMessage) { + Toast.makeText(context, R.string.long_press_stop_4_options, Toast.LENGTH_SHORT).show() + viewModel.shouldShowMessage=false + } + stop?.let { + mListener?.requestArrivalsForStopID(it.ID) + } + if(stop == null){ + Log.e(DEBUG_TAG,"Passed wrong stop") + } + if(mListener == null){ + Log.e(DEBUG_TAG, "Listener is null") + } } override fun onLongPressOnStop(stop: Stop?): Boolean { - Log.d("BusTO-LinesFrag", "LongPressOnStop") + Log.d(DEBUG_TAG, "LongPressOnStop") return true } } @@ -93,16 +109,6 @@ routeDescriptionTextView = rootView.findViewById(R.id.routeDescriptionTextView) stopsRecyclerView = rootView.findViewById(R.id.patternStopsRecyclerView) - /* - Stop busStop = (Stop) parent.getItemAtPosition(position); - - if(mListener!=null){ - mListener.requestArrivalsForStopID(busStop.ID); - } - - }); - - */ val llManager = LinearLayoutManager(context) llManager.orientation = LinearLayoutManager.VERTICAL @@ -122,8 +128,13 @@ val selRoute = currentRoutes.get(pos) routeDescriptionTextView.text = selRoute.longName - + val oldRoute = viewModel.getRouteIDQueried() + val resetSpinner = (oldRoute != null) && (oldRoute.trim() != selRoute.gtfsId.trim()) + Log.d(DEBUG_TAG, "Selected route: ${selRoute.gtfsId}, reset spinner: $resetSpinner") + //launch query for this gtfsID viewModel.setRouteIDQuery(selRoute.gtfsId) + //reset spinner position + if(resetSpinner) patternsSpinner.setSelection(0) } @@ -135,7 +146,7 @@ patternsSpinner.onItemSelectedListener = object : OnItemSelectedListener{ override fun onItemSelected(p0: AdapterView<*>?, p1: View?, position: Int, p3: Long) { val patternWithStops = currentPatterns.get(position) - + // setPatternAndReqStops(patternWithStops) } @@ -173,7 +184,8 @@ viewModel.patternsWithStopsByRouteLiveData.observe(this){ patterns -> run { - currentPatterns = patterns.sortedBy { p->"${p.pattern.directionId} - ${p.pattern.headsign}" } + 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}" }) @@ -181,7 +193,8 @@ } val pos = patternsSpinner.selectedItemPosition - if(pos!= INVALID_POSITION){ + //might be possible that the selectedItem is different (larger than list size) + if(pos!= INVALID_POSITION && pos >= 0 && (pos < currentPatterns.size)){ setPatternAndReqStops(currentPatterns[pos]) } @@ -264,7 +277,6 @@ override fun onContextItemSelected(item: MenuItem): Boolean { - val info = item.getMenuInfo(); if (stopsRecyclerView.getAdapter() !is StopRecyclerAdapter) return false val adapter =stopsRecyclerView.adapter as StopRecyclerAdapter diff --git a/src/it/reyboz/bustorino/fragments/LinesViewModel.kt b/src/it/reyboz/bustorino/fragments/LinesViewModel.kt --- a/src/it/reyboz/bustorino/fragments/LinesViewModel.kt +++ b/src/it/reyboz/bustorino/fragments/LinesViewModel.kt @@ -46,6 +46,11 @@ routeIDToSearch.value = routeID } + fun getRouteIDQueried(): String?{ + return routeIDToSearch.value + } + var shouldShowMessage = true; + fun requestStopsForGTFSIDs(gtfsIDs: List){ oldRepo.requestStopsWithGtfsIDs(gtfsIDs) { if (it.isSuccess) { diff --git a/src/it/reyboz/bustorino/util/LinesNameSorter.java b/src/it/reyboz/bustorino/util/LinesNameSorter.java --- a/src/it/reyboz/bustorino/util/LinesNameSorter.java +++ b/src/it/reyboz/bustorino/util/LinesNameSorter.java @@ -18,9 +18,16 @@ package it.reyboz.bustorino.util; +import android.util.Log; +import androidx.annotation.NonNull; + import java.util.Comparator; public class LinesNameSorter implements Comparator { + final static private int cc = 100; + final static private int ERROR_PARSING = -10; + final static private int FIRST_1_LETTER = 120; + final static private int FIRST_2_LETTERS=220; @Override public int compare(String name1, String name2) { name1 = name1.trim(); @@ -49,7 +56,7 @@ } return name1.compareTo(name2); } - }**/ + }* //One of them is not int num1 = -1; if(isInteger(name1)) num1 = Integer.parseInt(name1); @@ -58,14 +65,21 @@ if(num1 >= 0 && num2 >=0){ //we're very happy - return (num1-num2)*10; + return (num1-num2)*cc; } else if (num1>=0) { //name2 is not fully integer + if(name2.contains(" ")){ + final String[] allStr = name2.split(" "); + if(isInteger(allStr[0])) { + return (num1-Integer.parseInt(allStr[0]))*cc - incrementFromLastChar(allStr[1].trim().charAt(0)); + } + //sennĂ² si fa come sotto + } final String name2sub = name2.substring(0, name2.length()-1).trim(); char lastchar = name2.charAt(name2.length()-1); if(isInteger(name2sub)){ num2 = Integer.parseInt(name2sub); - int diff = (num1-num2)*10; + int diff = (num1-num2)*cc; return diff - incrementFromLastChar(lastchar); } else{ //failed @@ -77,7 +91,7 @@ char lastchar = name1.charAt(name1.length()-1); if (isInteger(name1sub)){ num1 = Integer.parseInt(name1sub); - int diff = (num1-num2)*10; + int diff = (num1-num2)*cc; return diff + incrementFromLastChar(lastchar); } else { return name1.compareTo(name2); @@ -85,9 +99,72 @@ } //last case return name1.compareTo(name2); + **/ + //DO ALL CASES + final CompareHolder c1 = getValueOfComplexName(name1); + final CompareHolder c2 = getValueOfComplexName(name2); + if (c1.value != ERROR_PARSING && c2.value != ERROR_PARSING){ + + return (c1.value-c2.value)*100+c1.extra.compareTo(c2.extra); + } else { + if(c2.value== ERROR_PARSING && c1.value==ERROR_PARSING){ + return c1.extra.compareTo(c2.extra); + } + else if(c1.value == ERROR_PARSING){ + return 1; + } + else { + return -1; + } + //Log.e("BusTo-Parsing","Error with the string"); + //throw new IllegalArgumentException("Error with the string name parsing"); + } } + private static CompareHolder getValueOfComplexName(String name){ + String namec = name.trim(); + + if (isInteger(namec)) return new CompareHolder(Integer.parseInt(namec),""); + + //check for the first part + if(namec.contains(" ")){ + final String[] allStr = namec.split(" "); + if(isInteger(allStr[0])) { + int g = Integer.parseInt(allStr[0]); + return new CompareHolder(g, allStr[1]); + } + else return new CompareHolder(-7, namec); + }else { + final String name1sub = namec.substring(0, namec.length()-1).trim(); + String lastPart = namec.substring(namec.length()-1); + int g; + if (isInteger(name1sub)) { + return new CompareHolder(Integer.parseInt(name1sub), lastPart); + } else if(name1sub.equals("M1")){ + return new CompareHolder(-1, lastPart); + } else { + //check NightBuster (X+name) + if(isInteger(namec.substring(1))){ + g = Integer.parseInt((namec.substring(1))); + return new CompareHolder(FIRST_1_LETTER, namec); + } else if (isInteger(namec.substring(2))) { + return new CompareHolder(FIRST_2_LETTERS, namec); + } + return new CompareHolder(ERROR_PARSING, namec); + } + } + } + + private static class CompareHolder { + int value; + String extra; + + public CompareHolder(int value,@NonNull String extra) { + this.value = value; + this.extra = extra; + } + } public static boolean isInteger(String strNum) { if (strNum == null) { return false; @@ -109,7 +186,7 @@ case 'N': return 3; default: - return 6; + return 1; } } } diff --git a/src/it/reyboz/bustorino/util/PatternWithStopsSorter.kt b/src/it/reyboz/bustorino/util/PatternWithStopsSorter.kt new file mode 100644 --- /dev/null +++ b/src/it/reyboz/bustorino/util/PatternWithStopsSorter.kt @@ -0,0 +1,21 @@ +package it.reyboz.bustorino.util + +import it.reyboz.bustorino.data.gtfs.MatoPatternWithStops + +/** + * Sorter for the patterns, which takes into account direction and length of pattern + */ +class PatternWithStopsSorter: Comparator { + override fun compare(p0: MatoPatternWithStops?, p1: MatoPatternWithStops?): Int { + if (p0 != null && p1!=null) { + if(p0.pattern.directionId != p1.pattern.directionId){ + return p0.pattern.directionId - p1.pattern.directionId + } + val g = -1*(p0.stopsIndices.size - p1.stopsIndices.size) + if(g!=0) + return g; + else return p0.pattern.code.compareTo(p1.pattern.code) + } + else return 0; + } +} \ No newline at end of file