/** * 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.oba_application.view; import org.onebusaway.transit_data.model.oba.LocalSearchResult; import org.onebusaway.webapp.gwt.common.model.ModelListener; import org.onebusaway.webapp.gwt.common.widgets.SpanPanel; import org.onebusaway.webapp.gwt.common.widgets.SpanWidget; import org.onebusaway.webapp.gwt.oba_application.control.CommonControl; import org.onebusaway.webapp.gwt.oba_application.control.Filter; import org.onebusaway.webapp.gwt.oba_application.control.StateEvent; import org.onebusaway.webapp.gwt.oba_application.model.ResultsModel; import org.onebusaway.webapp.gwt.oba_application.model.TimedLocalSearchResult; import org.onebusaway.webapp.gwt.oba_application.resources.OneBusAwayCssResource; import org.onebusaway.webapp.gwt.oba_application.resources.OneBusAwayStandardResources; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Widget; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; public class ResultsFilterPresenter { private static OneBusAwayCssResource _css = OneBusAwayStandardResources.INSTANCE.getCss(); private FlowPanel _widget = new FlowPanel(); private FilterImpl _filter = new FilterImpl(); private List<String> _categories = new ArrayList<String>(); private CommonControl _control; private Set<String> _activeCategories = new HashSet<String>(); private boolean _minimized = true; public ResultsFilterPresenter() { this(true); } public ResultsFilterPresenter(boolean minimized) { _widget.addStyleName(_css.ResultsFilter()); _minimized = minimized; } public void setControl(CommonControl control) { _control = control; } public Widget getWidget() { return _widget; } public ModelListener<ResultsModel> getResultsModelHandler() { return new PlacesModelHandler(); } public ModelListener<StateEvent> getStateEventHandler() { throw new IllegalStateException(); } private void refresh() { _widget.clear(); _activeCategories.clear(); if (!_categories.isEmpty()) _activeCategories.add(_categories.get(0)); refreshFilter(); if (_minimized) buildMinimizedWidget(); else { buildMaxmizedWidget(); } } private void buildMinimizedWidget() { _widget.add(new SpanWidget("Categories:", "ResultsFilter-Label")); for (int i = 0; i < Math.min(3, _categories.size()); i++) { SpanPanel panel = new SpanPanel(); final String categoryName = _categories.get(i); final CheckBox box = new CheckBox(); box.addStyleName(_css.ResultsFilterButton()); box.setText(categoryName); box.setValue(_activeCategories.contains(categoryName)); box.addClickHandler(new ClickHandler() { public void onClick(ClickEvent arg0) { boolean update = false; if (box.getValue()) update = _activeCategories.add(categoryName); else update = _activeCategories.remove(categoryName); if (update) { refreshFilter(); } } }); panel.add(box); _widget.add(panel); } } private void buildMaxmizedWidget() { _widget.add(new SpanWidget("Categories:", "ResultsFilter-Label")); for (int i = 0; i < Math.min(3, _categories.size()); i++) { SpanPanel panel = new SpanPanel(); final String categoryName = _categories.get(i); final CheckBox box = new CheckBox(); box.addStyleName(_css.ResultsFilterButton()); box.setText(categoryName); box.setValue(_activeCategories.contains(categoryName)); box.addClickHandler(new ClickHandler() { public void onClick(ClickEvent arg0) { boolean update = false; if (box.getValue()) update = _activeCategories.add(categoryName); else update = _activeCategories.remove(categoryName); if (update) { refreshFilter(); } } }); panel.add(box); _widget.add(panel); } } private void refreshFilter() { _control.filterResults(_filter); } private class PlacesModelHandler implements ModelListener<ResultsModel> { public void handleUpdate(ResultsModel model) { List<TimedLocalSearchResult> results = model.getResults(); Map<String, Integer> counts = new HashMap<String, Integer>(); for (TimedLocalSearchResult result : results) { LocalSearchResult r = result.getLocalSearchResult(); for (String category : r.getCategories()) { Integer count = counts.get(category); if (count == null) count = 0; counts.put(category, count + 1); } } _categories.clear(); _categories.addAll(counts.keySet()); Collections.sort(_categories, new MComparator<String, Integer>(counts, false)); refresh(); } } private static class MComparator<K, V extends Comparable<V>> implements Comparator<K> { private Map<K, V> _m; private boolean _ascending; public MComparator(Map<K, V> m, boolean ascending) { _m = m; _ascending = ascending; } public int compare(K o1, K o2) { V v1 = _m.get(o1); V v2 = _m.get(o2); int c = v1.compareTo(v2); return _ascending ? c : -c; } } private class FilterImpl implements Filter<TimedLocalSearchResult> { public boolean isEnabled(TimedLocalSearchResult element) { if (_activeCategories.isEmpty()) return true; LocalSearchResult result = element.getLocalSearchResult(); for (String category : _activeCategories) { if (result.getCategories().contains(category)) return true; } return false; } } }