Skip to content

Commit ed57772

Browse files
committed
Merge branch 'development'
2 parents 6c590f0 + 3e8d9be commit ed57772

22 files changed

+232
-15
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
package be.hyperrail.android.adapter;
2+
3+
import android.database.DataSetObserver;
4+
import android.view.LayoutInflater;
5+
import android.view.View;
6+
import android.view.ViewGroup;
7+
import android.widget.Filter;
8+
import android.widget.Filterable;
9+
import android.widget.ListAdapter;
10+
import android.widget.TextView;
11+
12+
import androidx.collection.ArraySet;
13+
import androidx.fragment.app.FragmentActivity;
14+
15+
import java.util.ArrayList;
16+
import java.util.Collection;
17+
import java.util.Collections;
18+
import java.util.Comparator;
19+
import java.util.List;
20+
import java.util.Set;
21+
22+
import be.hyperrail.opentransportdata.common.models.StopLocation;
23+
24+
public class MultilangAutocompleteAdapter implements Filterable, ListAdapter {
25+
26+
private final FragmentActivity activity;
27+
private final int layoutResourceId;
28+
private final StopLocation[] stations;
29+
30+
private List<StopLocation> visibleStops = new ArrayList<>();
31+
private Set<DataSetObserver> observers = new ArraySet<>();
32+
33+
public MultilangAutocompleteAdapter(FragmentActivity activity, int layoutResourceId, StopLocation[] stations) {
34+
this.activity = activity;
35+
this.layoutResourceId = layoutResourceId;
36+
this.stations = stations;
37+
}
38+
39+
@Override
40+
public Filter getFilter() {
41+
return new Filter() {
42+
class MultilangFilterResults extends FilterResults {
43+
public MultilangFilterResults(List<StopLocation> results) {
44+
this.values = results;
45+
this.count = results.size();
46+
}
47+
}
48+
49+
@Override
50+
protected FilterResults performFiltering(CharSequence constraint) {
51+
constraint = constraint.toString().toLowerCase();
52+
List<StopLocation> list = new ArrayList<>();
53+
for (StopLocation s : stations) {
54+
if (stationNameContains(constraint, s)) {
55+
list.add(s);
56+
}
57+
}
58+
Collections.sort(list, new AutocompleteSortComparator(constraint));
59+
return new MultilangFilterResults(list);
60+
}
61+
62+
private boolean stationNameContains(CharSequence constraint, StopLocation s) {
63+
if (s.getName().toLowerCase().contains(constraint)) {
64+
return true; // primary name is not always included in the translations
65+
}
66+
for (String name : s.getTranslations().values()) {
67+
if (name.toLowerCase().contains(constraint)) {
68+
return true;
69+
}
70+
}
71+
return false;
72+
}
73+
74+
@Override
75+
protected void publishResults(CharSequence constraint, FilterResults results) {
76+
//noinspection unchecked
77+
updateVisibleStops((List<StopLocation>) results.values);
78+
}
79+
};
80+
}
81+
82+
private void updateVisibleStops(List<StopLocation> stops) {
83+
this.visibleStops = stops;
84+
for (DataSetObserver observer : observers) {
85+
observer.onChanged();
86+
}
87+
}
88+
89+
@Override
90+
public boolean areAllItemsEnabled() {
91+
return true; // No separators or other similar elements in this adapter
92+
}
93+
94+
@Override
95+
public boolean isEnabled(int position) {
96+
return true; // No separators or other similar elements in this adapter
97+
}
98+
99+
@Override
100+
public void registerDataSetObserver(DataSetObserver observer) {
101+
this.observers.add(observer);
102+
}
103+
104+
@Override
105+
public void unregisterDataSetObserver(DataSetObserver observer) {
106+
this.observers.remove(observer);
107+
}
108+
109+
@Override
110+
public int getCount() {
111+
return visibleStops.size();
112+
}
113+
114+
@Override
115+
public StopLocation getItem(int position) {
116+
return visibleStops.get(position);
117+
}
118+
119+
@Override
120+
public long getItemId(int position) {
121+
return getItem(position).getSemanticId().hashCode();
122+
}
123+
124+
@Override
125+
public boolean hasStableIds() {
126+
return true;
127+
}
128+
129+
@Override
130+
public View getView(int position, View convertView, ViewGroup parent) {
131+
return createViewFromResource(activity.getLayoutInflater(), position, convertView, parent, layoutResourceId);
132+
}
133+
134+
@Override
135+
public int getItemViewType(int position) {
136+
return 0;
137+
}
138+
139+
@Override
140+
public int getViewTypeCount() {
141+
return 1;
142+
}
143+
144+
@Override
145+
public boolean isEmpty() {
146+
return visibleStops.isEmpty();
147+
}
148+
149+
// From ArrayAdapter
150+
private View createViewFromResource(LayoutInflater inflater, int position, View convertView, ViewGroup parent, int resource) {
151+
final View view;
152+
final TextView text;
153+
154+
if (convertView == null) {
155+
view = inflater.inflate(resource, parent, false);
156+
} else {
157+
view = convertView;
158+
}
159+
160+
// If no custom field is assigned, assume the whole resource is a TextView
161+
text = (TextView) view;
162+
163+
final StopLocation item = getItem(position);
164+
text.setText(item.getLocalizedName());
165+
166+
return view;
167+
}
168+
169+
private static class AutocompleteSortComparator implements Comparator<StopLocation> {
170+
private final String lowerCaseConstraint;
171+
172+
public AutocompleteSortComparator(CharSequence lowerCaseConstraint) {
173+
this.lowerCaseConstraint = lowerCaseConstraint.toString();
174+
}
175+
176+
@Override
177+
public int compare(StopLocation o1, StopLocation o2) {
178+
boolean o1nameAdvantage = nameStartsWith(o1, lowerCaseConstraint);
179+
boolean o2nameAdvantage = nameStartsWith(o2, lowerCaseConstraint);
180+
if (o1nameAdvantage && !o2nameAdvantage) {
181+
return -1;
182+
}
183+
if (o2nameAdvantage && !o1nameAdvantage) {
184+
return 1;
185+
}
186+
return Float.compare(o2.getAvgStopTimes(), o1.getAvgStopTimes());
187+
}
188+
189+
private boolean nameStartsWith(StopLocation location, String prefix) {
190+
if (location.getName().toLowerCase().startsWith(prefix)) {
191+
return true; // Name is not always included in the translations
192+
}
193+
for (String name : location.getTranslations().values()) {
194+
if (name.toLowerCase().startsWith(prefix)) {
195+
return true;
196+
}
197+
}
198+
return false;
199+
}
200+
}
201+
}

Hyperrail/src/main/java/be/hyperrail/android/fragments/RouteSearchFragment.java

+6-10
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252

5353
import be.hyperrail.android.R;
5454
import be.hyperrail.android.activities.searchresult.RouteActivity;
55+
import be.hyperrail.android.adapter.MultilangAutocompleteAdapter;
5556
import be.hyperrail.android.adapter.OnRecyclerItemClickListener;
5657
import be.hyperrail.android.adapter.OnRecyclerItemLongClickListener;
5758
import be.hyperrail.android.adapter.RouteSuggestionsCardAdapter;
@@ -76,8 +77,6 @@ public class RouteSearchFragment extends Fragment implements OnRecyclerItemClick
7677
private AutoCompleteTextView vToText;
7778
private TextView vDatetime;
7879
private Spinner vArriveDepart;
79-
private LinearLayout vArriveDepartContainer;
80-
8180
private DateTime searchDateTime = null;
8281

8382
private PersistentQueryProvider persistentQueryProvider;
@@ -123,8 +122,6 @@ public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
123122
createKeyListeners();
124123
createClickListeners(view);
125124

126-
vArriveDepartContainer = view.findViewById(R.id.container_arrivedepart);
127-
128125
if (this.getArguments() != null && (this.getArguments().containsKey("from") || this.getArguments().containsKey("to"))) {
129126
prefillFieldsFromArguments();
130127
} else if (savedInstanceState != null) {
@@ -433,7 +430,7 @@ protected void onPostExecute(List<Suggestion<RoutePlanningRequest>> suggestions)
433430
}
434431
}
435432

436-
private static class LoadAutoCompleteTask extends AsyncTask<TransportStopsDataSource, Void, String[]> {
433+
private static class LoadAutoCompleteTask extends AsyncTask<TransportStopsDataSource, Void, StopLocation[]> {
437434

438435
private WeakReference<RouteSearchFragment> fragmentReference;
439436

@@ -443,15 +440,14 @@ private static class LoadAutoCompleteTask extends AsyncTask<TransportStopsDataSo
443440
}
444441

445442
@Override
446-
protected String[] doInBackground(TransportStopsDataSource... provider) {
443+
protected StopLocation[] doInBackground(TransportStopsDataSource... provider) {
447444
Thread.currentThread().setName("LoadAutoCompleteTask");
448-
// TODO: "make use of translations" a setting
449-
return provider[0].getStoplocationsNames(provider[0].getStoplocationsOrderedBySize(), false);
445+
return provider[0].getStoplocationsOrderedBySize();
450446

451447
}
452448

453449
@Override
454-
protected void onPostExecute(String[] stations) {
450+
protected void onPostExecute(StopLocation[] stations) {
455451
super.onPostExecute(stations);
456452

457453
// get a reference to the activity if it is still there
@@ -461,7 +457,7 @@ protected void onPostExecute(String[] stations) {
461457
}
462458

463459
// Initialize autocomplete
464-
ArrayAdapter<String> autocompleteAdapter = new ArrayAdapter<>(fragment.getActivity(),
460+
MultilangAutocompleteAdapter autocompleteAdapter = new MultilangAutocompleteAdapter(fragment.getActivity(),
465461
android.R.layout.simple_dropdown_item_1line, stations);
466462

467463
fragment.vFromText.setAdapter(autocompleteAdapter);

build.gradle

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ buildscript {
88
}
99
dependencies {
1010
classpath 'com.android.tools.build:gradle:8.2.0'
11-
classpath 'com.google.gms:google-services:4.3.15'
12-
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.2'
11+
classpath 'com.google.gms:google-services:4.4.0'
12+
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.9'
1313
}
1414
}
1515

opentransport_be/src/main/java/be/hyperrail/opentransportdata/be/irail/NmbsToMlgDessinsAdapter.java

+23-3
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,29 @@ private static NmbsTrainType convertCarriage(String parentType, String subType,
6262
}
6363
break;
6464
case "M7":
65-
// Fallback on M6 icons
66-
newParentType = "M6";
67-
// Continue into M6 subtype handling
65+
switch (subType) {
66+
// Just handle all known M6 variants
67+
case "BYU":
68+
// BU + Y // With a little conductor room?
69+
case "BU":
70+
// 140/133 2nd class
71+
newSubType = "B";
72+
break;
73+
case "BUH":
74+
// BU + H
75+
case "BAU":
76+
// Mixed 1st/2nd class
77+
case "AU":
78+
case "ABUH":
79+
// 124/133 1st class
80+
newSubType = "AB";
81+
break;
82+
case "BDXH":
83+
case "BMX":
84+
newSubType = "BDX";
85+
break;
86+
}
87+
break;
6888
case "M6":
6989
switch (subType) {
7090
case "BXAA":
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading

0 commit comments

Comments
 (0)