Skip to content

Commit e99ec0e

Browse files
committed
Merge pull request #174 from pennlabs/buildings-mapview
Buildings mapview
2 parents e1c90e5 + 5d72658 commit e99ec0e

22 files changed

Lines changed: 402 additions & 15 deletions

File tree

PennMobile/PennMobile.iml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,18 +85,19 @@
8585
</content>
8686
<orderEntry type="jdk" jdkName="Android API 21 Platform" jdkType="Android SDK" />
8787
<orderEntry type="sourceFolder" forTests="false" />
88-
<orderEntry type="library" exported="" name="appcompat-v7-21.0.3" level="project" />
8988
<orderEntry type="library" exported="" name="crashlytics-1.1.13" level="project" />
90-
<orderEntry type="library" exported="" name="support-annotations-21.0.3" level="project" />
89+
<orderEntry type="library" exported="" name="picasso-2.5.0" level="project" />
9190
<orderEntry type="library" exported="" name="play-services-maps-6.5.87" level="project" />
9291
<orderEntry type="library" exported="" name="support-v4-21.0.3" level="project" />
93-
<orderEntry type="library" exported="" name="butterknife-6.0.0" level="project" />
94-
<orderEntry type="library" exported="" name="joda-time-2.5" level="project" />
95-
<orderEntry type="library" exported="" name="play-services-base-6.5.87" level="project" />
9692
<orderEntry type="library" exported="" name="retrofit-1.8.0" level="project" />
93+
<orderEntry type="library" exported="" name="play-services-base-6.5.87" level="project" />
9794
<orderEntry type="library" exported="" name="library-1.0.6" level="project" />
98-
<orderEntry type="library" exported="" name="gson-2.3" level="project" />
9995
<orderEntry type="library" exported="" name="commons-lang3-3.3.2" level="project" />
96+
<orderEntry type="library" exported="" name="appcompat-v7-21.0.3" level="project" />
97+
<orderEntry type="library" exported="" name="support-annotations-21.0.3" level="project" />
98+
<orderEntry type="library" exported="" name="butterknife-6.0.0" level="project" />
99+
<orderEntry type="library" exported="" name="joda-time-2.5" level="project" />
100+
<orderEntry type="library" exported="" name="gson-2.3" level="project" />
100101
</component>
101102
</module>
102103

PennMobile/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,5 @@ dependencies {
4141
compile 'com.jpardogo.materialtabstrip:library:1.0.6'
4242
compile 'com.jakewharton:butterknife:6.0.0'
4343
compile 'com.squareup.retrofit:retrofit:1.8.0'
44+
compile 'com.squareup.picasso:picasso:2.5.0'
4445
}

PennMobile/src/main/java/com/pennapps/labs/pennmobile/MainActivity.java

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.pennapps.labs.pennmobile.adapters.NavDrawerListAdapter;
2626
import com.pennapps.labs.pennmobile.api.Labs;
2727
import com.pennapps.labs.pennmobile.api.Serializer;
28+
import com.pennapps.labs.pennmobile.classes.Building;
2829
import com.pennapps.labs.pennmobile.classes.Course;
2930
import com.pennapps.labs.pennmobile.classes.NewDiningHall;
3031
import com.pennapps.labs.pennmobile.classes.Person;
@@ -53,8 +54,8 @@ protected void onCreate(Bundle savedInstanceState) {
5354
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
5455
StrictMode.setThreadPolicy(policy);
5556

56-
mFeatureTitles = new String[]{"Home", "Courses", "Directory", "Dining", "Transit", "News", "Support", "About"};
57-
int[] icons = new int[]{R.drawable.ic_home, R.drawable.ic_book, R.drawable.ic_contacts,
57+
mFeatureTitles = new String[]{"Home", "Courses", "Directory", "Map", "Dining", "Transit", "News", "Support", "About"};
58+
int[] icons = new int[]{R.drawable.ic_home, R.drawable.ic_book, R.drawable.ic_contacts, R.drawable.ic_map,
5859
R.drawable.ic_restaurant, R.drawable.ic_directions_bus, R.drawable.ic_announcement,
5960
R.drawable.ic_help, R.drawable.ic_info
6061
};
@@ -171,14 +172,16 @@ private void selectItem(int position) {
171172
} else if (position == 2) {
172173
fragment = new DirectorySearchFragment();
173174
} else if (position == 3) {
174-
fragment = new DiningFragment();
175+
fragment = new MapFragment();
175176
} else if (position == 4) {
176-
fragment = new TransitFragment();
177+
fragment = new DiningFragment();
177178
} else if (position == 5) {
178-
fragment = new EventsFragment();
179+
fragment = new TransitFragment();
179180
} else if (position == 6) {
180-
fragment = new SupportFragment();
181+
fragment = new EventsFragment();
181182
} else if (position == 7) {
183+
fragment = new SupportFragment();
184+
} else if (position == 8) {
182185
fragment = new AboutFragment();
183186
}
184187

@@ -209,11 +212,13 @@ public void onHomeButtonClick(View v) {
209212
} else if (v.getId() == R.id.directory_img || v.getId() == R.id.directory_cont || v.getId() == R.id.directory_button) {
210213
selectItem(2);
211214
} else if (v.getId() == R.id.dining_img || v.getId() == R.id.dining_cont || v.getId() == R.id.dining_button) {
212-
selectItem(3);
213-
} else if (v.getId() == R.id.transit_img || v.getId() == R.id.transit_cont || v.getId() == R.id.transit_button) {
214215
selectItem(4);
215-
} else if (v.getId() == R.id.news_img || v.getId() == R.id.news_cont || v.getId() == R.id.news_button) {
216+
} else if (v.getId() == R.id.transit_img || v.getId() == R.id.transit_cont || v.getId() == R.id.transit_button) {
216217
selectItem(5);
218+
} else if (v.getId() == R.id.news_img || v.getId() == R.id.news_cont || v.getId() == R.id.news_button) {
219+
selectItem(6);
220+
} else if (v.getId() == R.id.map_img || v.getId() == R.id.map_cont || v.getId() == R.id.map_button) {
221+
selectItem(3);
217222
}
218223
}
219224

@@ -231,6 +236,7 @@ public Labs getLabsInstance() {
231236
if (mLabs == null) {
232237
GsonBuilder gsonBuilder = new GsonBuilder();
233238
gsonBuilder.registerTypeAdapter(new TypeToken<List<Course>>(){}.getType(), new Serializer.CourseSerializer());
239+
gsonBuilder.registerTypeAdapter(new TypeToken<List<Building>>(){}.getType(), new Serializer.BuildingSerializer());
234240
gsonBuilder.registerTypeAdapter(new TypeToken<List<Person>>(){}.getType(), new Serializer.DataSerializer());
235241
gsonBuilder.registerTypeAdapter(new TypeToken<List<Venue>>(){}.getType(), new Serializer.VenueSerializer());
236242
gsonBuilder.registerTypeAdapter(NewDiningHall.class, new Serializer.MenuSerializer());
Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
package com.pennapps.labs.pennmobile;
2+
3+
import android.content.Context;
4+
import android.location.Location;
5+
import android.os.AsyncTask;
6+
import android.os.Bundle;
7+
import android.support.v4.app.Fragment;
8+
import android.support.v7.widget.SearchView;
9+
import android.view.Gravity;
10+
import android.view.LayoutInflater;
11+
import android.view.Menu;
12+
import android.view.MenuInflater;
13+
import android.view.MenuItem;
14+
import android.view.View;
15+
import android.view.ViewGroup;
16+
import android.view.inputmethod.InputMethodManager;
17+
import android.widget.ImageView;
18+
import android.widget.TextView;
19+
import android.widget.Toast;
20+
21+
import com.google.android.gms.maps.CameraUpdateFactory;
22+
import com.google.android.gms.maps.GoogleMap;
23+
import com.google.android.gms.maps.MapView;
24+
import com.google.android.gms.maps.MapsInitializer;
25+
import com.google.android.gms.maps.model.LatLng;
26+
import com.google.android.gms.maps.model.LatLngBounds;
27+
import com.google.android.gms.maps.model.Marker;
28+
import com.google.android.gms.maps.model.MarkerOptions;
29+
import com.pennapps.labs.pennmobile.api.Labs;
30+
import com.pennapps.labs.pennmobile.classes.Building;
31+
import com.squareup.picasso.Callback;
32+
import com.squareup.picasso.Picasso;
33+
34+
import java.util.HashSet;
35+
import java.util.List;
36+
import java.util.Map;
37+
import java.util.Set;
38+
39+
public class MapFragment extends Fragment {
40+
41+
private Labs mLabs;
42+
private MapView mapView;
43+
private GoogleMap googleMap;
44+
private SearchView searchView;
45+
private String query = "";
46+
private static Marker currentMarker;
47+
private static Set<Marker> loadedMarkers;
48+
49+
@Override
50+
public void onCreate(Bundle savedInstanceState) {
51+
super.onCreate(savedInstanceState);
52+
mLabs = ((MainActivity) getActivity()).getLabsInstance();
53+
loadedMarkers = new HashSet<>();
54+
55+
InputMethodManager inputMethodManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
56+
inputMethodManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(), 0);
57+
}
58+
59+
@Override
60+
public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
61+
View v = inflater.inflate(R.layout.fragment_map, container, false);
62+
63+
mapView = (MapView) v.findViewById(R.id.mapView);
64+
mapView.onCreate(savedInstanceState);
65+
66+
googleMap = mapView.getMap();
67+
googleMap.getUiSettings().setMyLocationButtonEnabled(false);
68+
googleMap.setMyLocationEnabled(true);
69+
70+
googleMap.setInfoWindowAdapter(new CustomWindowAdapter(inflater));
71+
72+
try {
73+
MapsInitializer.initialize(this.getActivity());
74+
} catch (Exception e) {
75+
e.printStackTrace();
76+
}
77+
Location location = googleMap.getMyLocation();
78+
LatLng myLocation = new LatLng(39.9529, -75.197098);
79+
80+
if (location != null) {
81+
myLocation = new LatLng(location.getLatitude(),
82+
location.getLongitude());
83+
}
84+
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(myLocation, 14));
85+
86+
return v;
87+
}
88+
89+
private class CustomWindowAdapter implements GoogleMap.InfoWindowAdapter {
90+
91+
private View view;
92+
LayoutInflater inflater = null;
93+
94+
public CustomWindowAdapter(LayoutInflater inflater) {
95+
this.inflater = inflater;
96+
view = inflater.inflate(R.layout.info_window, null);
97+
}
98+
99+
@Override
100+
public View getInfoWindow(Marker arg0) {
101+
return null;
102+
}
103+
104+
@Override
105+
public View getInfoContents(final Marker arg0) {
106+
currentMarker = arg0;
107+
108+
ImageView imageView= (ImageView) view.findViewById(R.id.building_image);
109+
TextView name = (TextView) view.findViewById(R.id.building_name);
110+
name.setText(arg0.getTitle());
111+
112+
if (arg0.getSnippet().isEmpty()) {
113+
imageView.setVisibility(View.GONE);
114+
} else if (loadedMarkers.contains(currentMarker)) {
115+
Picasso.with(getActivity()).load(arg0.getSnippet()).into(imageView);
116+
} else {
117+
loadedMarkers.add(currentMarker);
118+
Picasso.with(getActivity()).load(arg0.getSnippet()).into(imageView, new Callback() {
119+
@Override
120+
public void onSuccess() {
121+
currentMarker.hideInfoWindow();
122+
currentMarker.showInfoWindow();
123+
}
124+
125+
@Override
126+
public void onError() {}
127+
});
128+
}
129+
return view;
130+
}
131+
}
132+
133+
@Override
134+
public void onActivityCreated(Bundle savedInstanceState) {
135+
super.onActivityCreated(savedInstanceState);
136+
setHasOptionsMenu(true);
137+
}
138+
139+
@Override
140+
public void onResume() {
141+
mapView.onResume();
142+
super.onResume();
143+
}
144+
145+
@Override
146+
public void onDestroy() {
147+
super.onDestroy();
148+
mapView.onDestroy();
149+
}
150+
151+
@Override
152+
public void onLowMemory() {
153+
super.onLowMemory();
154+
mapView.onLowMemory();
155+
}
156+
157+
@Override
158+
public boolean onOptionsItemSelected(MenuItem item) {
159+
// Handle presses on the action bar items
160+
switch (item.getItemId()) {
161+
case R.id.building_search:
162+
return true;
163+
default:
164+
return super.onOptionsItemSelected(item);
165+
}
166+
}
167+
168+
@Override
169+
public void onPrepareOptionsMenu(Menu menu) {
170+
searchView = (SearchView) menu.findItem(R.id.building_search).getActionView();
171+
searchView.setIconifiedByDefault(true);
172+
searchView.setIconified(true);
173+
}
174+
175+
@Override
176+
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
177+
inflater.inflate(R.menu.building, menu);
178+
179+
searchView = (SearchView) menu.findItem(R.id.building_search).getActionView();
180+
final SearchView.OnQueryTextListener queryListener = new SearchView.OnQueryTextListener() {
181+
182+
@Override
183+
public boolean onQueryTextChange(String arg0) {
184+
return true;
185+
}
186+
187+
@Override
188+
public boolean onQueryTextSubmit(String arg0) {
189+
query = arg0;
190+
new GetRequestTask().execute();
191+
return true;
192+
}
193+
};
194+
searchView.setOnQueryTextListener(queryListener);
195+
}
196+
197+
private class GetRequestTask extends AsyncTask<Void, Void, Boolean> {
198+
private List<Building> buildings;
199+
200+
@Override
201+
protected Boolean doInBackground(Void... params) {
202+
boolean success = true;
203+
try {
204+
buildings = mLabs.buildings(query);
205+
} catch (Exception ignored) {
206+
ignored.printStackTrace();
207+
success = false;
208+
}
209+
return success;
210+
}
211+
212+
@Override
213+
protected void onPostExecute(Boolean valid) {
214+
if (!valid) {
215+
// TODO:
216+
return;
217+
}
218+
try {
219+
googleMap.clear();
220+
if (!buildings.isEmpty()) {
221+
LatLngBounds.Builder boundsBuilder = new LatLngBounds.Builder();
222+
for (Building building : buildings) {
223+
double latitude = Double.parseDouble(building.latitude);
224+
double longitude = Double.parseDouble(building.longitude);
225+
LatLng point = new LatLng(latitude, longitude);
226+
boundsBuilder.include(point);
227+
googleMap.addMarker(new MarkerOptions()
228+
.position(point)
229+
.title(building.title)
230+
.snippet(building.getImageURL()));
231+
}
232+
LatLngBounds bounds = boundsBuilder.build();
233+
Location NECorner = new Location("");
234+
Location SWCorner = new Location("");
235+
LatLng northeast = bounds.northeast;
236+
LatLng southwest = bounds.southwest;
237+
NECorner.setLatitude(northeast.latitude);
238+
NECorner.setLatitude(northeast.longitude);
239+
SWCorner.setLatitude(southwest.latitude);
240+
SWCorner.setLatitude(southwest.longitude);
241+
int padding = 100;
242+
if (SWCorner.distanceTo(NECorner) < 40) {
243+
padding = 500;
244+
}
245+
googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, padding));
246+
} else {
247+
Toast.makeText(getActivity().getApplicationContext(), "No results found.",
248+
Toast.LENGTH_LONG).show();
249+
}
250+
searchView.clearFocus();
251+
} catch (NullPointerException ignored) {
252+
253+
}
254+
}
255+
}
256+
}

PennMobile/src/main/java/com/pennapps/labs/pennmobile/api/Labs.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.pennapps.labs.pennmobile.api;
22

3+
import com.pennapps.labs.pennmobile.classes.Building;
34
import com.pennapps.labs.pennmobile.classes.Course;
45
import com.pennapps.labs.pennmobile.classes.DiningHall;
56
import com.pennapps.labs.pennmobile.classes.NewDiningHall;
@@ -25,6 +26,10 @@ List<Course> courses(
2526
List<Person> people(
2627
@Query("name") String name);
2728

29+
@GET("/buildings/search")
30+
List<Building> buildings(
31+
@Query("q") String name);
32+
2833
@GET("/dining/venues")
2934
List<Venue> venues();
3035

PennMobile/src/main/java/com/pennapps/labs/pennmobile/api/Serializer.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.google.gson.JsonElement;
77
import com.google.gson.JsonParseException;
88
import com.google.gson.reflect.TypeToken;
9+
import com.pennapps.labs.pennmobile.classes.Building;
910
import com.pennapps.labs.pennmobile.classes.Course;
1011
import com.pennapps.labs.pennmobile.classes.NewDiningHall;
1112
import com.pennapps.labs.pennmobile.classes.Venue;
@@ -27,6 +28,15 @@ public List<Course> deserialize(JsonElement je, Type type, JsonDeserializationCo
2728
}
2829
}
2930

31+
public static class BuildingSerializer implements JsonDeserializer<List<Building>> {
32+
@Override
33+
public List<Building> deserialize(JsonElement je, Type type, JsonDeserializationContext jdc)
34+
throws JsonParseException {
35+
JsonElement content = je.getAsJsonObject().get("result_data");
36+
return new Gson().fromJson(content, new TypeToken<List<Building>>(){}.getType());
37+
}
38+
}
39+
3040
public static class DataSerializer<T> implements JsonDeserializer<T> {
3141
@Override
3242
public T deserialize(JsonElement je, Type type, JsonDeserializationContext jdc)

0 commit comments

Comments
 (0)