/**
* Copyright (C) 2011 Brian Ferris <bdferris@onebusaway.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onebusaway.webapp.gwt.where_library.view;
import java.util.List;
import org.onebusaway.presentation.client.RoutePresenter;
import org.onebusaway.presentation.client.StopPresenter;
import org.onebusaway.transit_data.model.AgencyBean;
import org.onebusaway.transit_data.model.RouteBean;
import org.onebusaway.transit_data.model.StopBean;
import org.onebusaway.transit_data.model.StopsForRouteBean;
import org.onebusaway.webapp.gwt.common.control.Place;
import org.onebusaway.webapp.gwt.common.widgets.DivPanel;
import org.onebusaway.webapp.gwt.common.widgets.DivWidget;
import org.onebusaway.webapp.gwt.where_library.rpc.WebappServiceAsync;
import org.onebusaway.webapp.gwt.where_library.services.CombinedSearchResult;
import org.onebusaway.webapp.gwt.where_library.view.constraints.OperationContext;
import org.onebusaway.webapp.gwt.where_library.view.stops.PlaceClickHandler;
import org.onebusaway.webapp.gwt.where_library.view.stops.TransitMapManager;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.maps.client.InfoWindow;
import com.google.gwt.maps.client.InfoWindowContent;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.geom.LatLng;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Panel;
public class ResultsPanelManager {
private static WebappServiceAsync _service = WebappServiceAsync.SERVICE;
private OperationContext _context;
private StopFinderCssResource _css;
private StopFinderInterface _stopFinder;
private Panel _panel;
private TransitMapManager _transitMapManager;
public ResultsPanelManager(OperationContext context) {
_context = context;
_css = context.getWidget().getCss();
_stopFinder = context.getStopFinder();
_transitMapManager = context.getTransitMapManager();
_panel = context.getPanel();
}
public void addNoResultsMessage() {
_panel.clear();
_panel.add(new DivWidget("No results were found for your search",
_css.resultListWarning()));
}
public void setResults(CombinedSearchResult result) {
_panel.clear();
addClearSearchLinkToResultsPanel();
Object primary = getPrimaryResult(result);
addPrimaryResult(primary);
if (!result.isEmpty()) {
DivPanel panel = new DivPanel(_css.resultListAdditional());
_panel.add(panel);
panel.add(new DivWidget("Did you mean:", _css.resultListWarning()));
List<RouteBean> routes = result.getRoutes();
addElementsToPanel(panel, routes, "Routes");
List<StopBean> stops = result.getStops();
addElementsToPanel(panel, stops, "Stops");
List<Place> addresses = result.getAddresses();
DivPanel addressesPanel = addElementsToPanel(panel, addresses,
"Addresses");
if (!addresses.isEmpty()) {
ShowPlacesOnMapToggleHandler handler = addShowOnMapLink(addressesPanel,
addresses, primary);
if (primary == null && routes.isEmpty() && stops.isEmpty())
handler.setShowingOnMap(true);
}
List<Place> places = result.getPlaces();
DivPanel placesPanel = addElementsToPanel(panel, places, "Places");
if (!places.isEmpty()) {
ShowPlacesOnMapToggleHandler handler = addShowOnMapLink(placesPanel,
places, primary);
if (primary == null && routes.isEmpty() && stops.isEmpty()
&& addresses.isEmpty())
handler.setShowingOnMap(true);
}
}
}
public void setResult(Object result) {
_panel.clear();
addClearSearchLinkToResultsPanel();
addPrimaryResult(result);
}
/****
* Private Methods
****/
private void addPrimaryResult(Object primary) {
if (primary != null) {
DivPanel primaryPanel = new DivPanel(_css.resultListPrimary());
_panel.add(primaryPanel);
addResultToPanel(primaryPanel, primary);
displayPrimaryResult(primary);
}
}
protected void addClearSearchLinkToResultsPanel() {
Anchor anchor = new Anchor("Clear this search");
anchor.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent arg0) {
_stopFinder.queryCurrentView();
}
});
DivPanel p = new DivPanel(_css.resultListClear());
p.add(anchor);
_panel.add(p);
}
private Object getPrimaryResult(CombinedSearchResult result) {
List<RouteBean> routes = result.getRoutes();
List<Place> addresses = result.getAddresses();
List<StopBean> stops = result.getStops();
List<Place> places = result.getPlaces();
if (routes.size() == 1)
return routes.remove(0);
if (routes.isEmpty() && addresses.size() == 1)
return addresses.remove(0);
if (routes.isEmpty() && addresses.isEmpty() && stops.size() == 1)
return stops.remove(0);
if (routes.isEmpty() && addresses.isEmpty() && stops.isEmpty()
&& places.size() == 1)
return places.remove(0);
return null;
}
private void displayPrimaryResult(Object primary) {
if (primary instanceof RouteBean) {
RouteBean route = (RouteBean) primary;
_service.getStopsForRoute(route.getId(), new StopsForRouteCallback(route));
} else if (primary instanceof StopBean) {
StopBean stop = (StopBean) primary;
_transitMapManager.showStop(stop, true);
} else if (primary instanceof Place) {
Place place = (Place) primary;
_transitMapManager.showPlace(place, true, null);
}
}
private DivPanel addElementsToPanel(DivPanel parentPanel, List<?> objects,
String label) {
if (objects.isEmpty())
return null;
DivPanel panel = new DivPanel(_css.resultList());
parentPanel.add(panel);
panel.add(new DivWidget(label + ":", _css.resultListHeader()));
for (Object bean : objects)
addResultToPanel(panel, bean);
return panel;
}
protected void addResultToPanel(DivPanel panel, Object primary) {
if (primary instanceof RouteBean) {
addRouteBeanToPanel((RouteBean) primary, panel);
} else if (primary instanceof StopBean) {
addStopBeanToPanel((StopBean) primary, panel);
} else if (primary instanceof Place) {
addPlaceBeanToPanel((Place) primary, panel);
}
}
private void addRouteBeanToPanel(final RouteBean route, DivPanel panel) {
DivPanel resultPanel = new DivPanel(_css.resultListEntry());
panel.add(resultPanel);
DivPanel routeRow = new DivPanel(_css.resultListEntryName());
resultPanel.add(routeRow);
String name = getRouteName(route);
Anchor anchor = new Anchor(name);
anchor.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
_stopFinder.queryRoute(route.getId());
}
});
routeRow.add(anchor);
AgencyBean agency = route.getAgency();
String agencyLink = agency.getName();
if (agency.getUrl() != null)
agencyLink = "<a href=\"" + agency.getUrl() + "\">" + agency.getName()
+ "</a>";
resultPanel.add(new DivWidget("Operated by " + agencyLink,
_css.resultListEntryDescription()));
}
protected void addStopBeanToPanel(StopBean stop, DivPanel panel) {
DivPanel resultPanel = new DivPanel(_css.resultListEntry());
panel.add(resultPanel);
DivPanel nameRow = new DivPanel(_css.resultListEntryName());
resultPanel.add(nameRow);
Anchor anchor = new Anchor(stop.getName(), false,
_stopFinder.getStopQueryLink(stop.getId()));
nameRow.add(anchor);
String desc = "Stop # " + StopPresenter.getCodeForStop(stop);
if (stop.getDirection() != null)
desc += " - " + stop.getDirection() + " bound";
resultPanel.add(new DivWidget(desc, _css.resultListEntryDescription()));
}
protected void addPlaceBeanToPanel(final Place place, DivPanel panel) {
DivPanel resultPanel = new DivPanel(_css.resultListEntry());
panel.add(resultPanel);
DivPanel routeRow = new DivPanel(_css.resultListEntryName());
resultPanel.add(routeRow);
String name = place.getName();
Anchor anchor = new Anchor(name);
anchor.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
_stopFinder.queryLocation(place.getLocation(), place.getAccuracy());
}
});
routeRow.add(anchor);
String description = place.getDescriptionAsString();
if (description.length() > 0)
routeRow.add(new DivWidget(description, _css.resultListEntryDescription()));
}
private String getRouteName(RouteBean route) {
String name = RoutePresenter.getNameForRoute(route);
String desc = RoutePresenter.getDescriptionForRoute(route);
if (desc != null)
name += " - " + desc;
return name;
}
private ShowPlacesOnMapToggleHandler addShowOnMapLink(DivPanel parentPanel,
final List<Place> addresses, final Object primaryResult) {
DivPanel row = new DivPanel(_css.resultListMoreInfoLink());
parentPanel.add(row);
final Anchor anchor = new Anchor("Show all on map");
row.add(anchor);
ShowPlacesOnMapToggleHandler handler = new ShowPlacesOnMapToggleHandler(
anchor, addresses, primaryResult);
anchor.addClickHandler(handler);
return handler;
}
private class StopsForRouteCallback implements
AsyncCallback<StopsForRouteBean> {
private RouteBean _route;
public StopsForRouteCallback(RouteBean route) {
_route = route;
}
@Override
public void onSuccess(StopsForRouteBean stopsForRoute) {
boolean centerViewOnRoute = !_context.isLocationSet();
_transitMapManager.showStopsForRoute(_route, stopsForRoute,
centerViewOnRoute);
}
@Override
public void onFailure(Throwable arg0) {
}
}
private class ShowPlacesOnMapToggleHandler implements ClickHandler,
PlaceClickHandler {
private boolean _showing = false;
private Anchor _anchor;
private List<Place> _places;
private Object _primaryResult;
public ShowPlacesOnMapToggleHandler(Anchor anchor, List<Place> places,
Object primaryResult) {
_anchor = anchor;
_places = places;
_primaryResult = primaryResult;
}
@Override
public void onClick(ClickEvent arg0) {
setShowingOnMap(!_showing);
}
public void setShowingOnMap(boolean showing) {
_showing = showing;
_anchor.setText(_showing ? "Hide all on map" : "Show all on map");
if (_showing) {
_transitMapManager.showPlaces(_places, true, this);
} else {
if (_primaryResult != null)
displayPrimaryResult(_primaryResult);
else
_transitMapManager.showStopsInCurrentView();
}
}
@Override
public void onPlaceClicked(final Place place) {
LatLng p = place.getLocation();
MapWidget _map = _transitMapManager.getMap();
InfoWindow window = _map.getInfoWindow();
FlowPanel panel = new FlowPanel();
panel.add(new DivWidget(place.getName()));
String desc = place.getDescriptionAsString();
if (desc.length() > 0)
panel.add(new DivWidget(desc));
DivPanel row = new DivPanel();
panel.add(row);
Anchor anchor = new Anchor("Show nearby transit stops");
row.add(anchor);
anchor.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent arg0) {
_transitMapManager.showPlace(place, true,
ShowPlacesOnMapToggleHandler.this);
}
});
window.open(p, new InfoWindowContent(panel));
}
}
}