/* * Copyright (c) 2010, 2011 Mashery, Inc. All Rights Reserved. * * 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 com.mashery.examples.api.client; import java.util.Date; import com.google.gwt.core.client.JsArray; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.MouseOverEvent; import com.google.gwt.event.dom.client.MouseOverHandler; import com.google.gwt.event.logical.shared.CloseEvent; import com.google.gwt.event.logical.shared.CloseHandler; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.http.client.Request; import com.google.gwt.http.client.RequestBuilder; import com.google.gwt.http.client.RequestCallback; import com.google.gwt.http.client.RequestException; import com.google.gwt.http.client.Response; import com.google.gwt.http.client.URL; import com.google.gwt.i18n.client.DateTimeFormat; import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat; import com.google.gwt.i18n.client.NumberFormat; import com.google.gwt.maps.client.base.HasLatLng; import com.google.gwt.maps.client.base.LatLng; import com.google.gwt.maps.client.overlay.Marker; import com.google.gwt.maps.client.overlay.MarkerOptions; import com.google.gwt.user.client.ui.Anchor; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlexTable; import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.FormPanel; import com.google.gwt.user.client.ui.FormPanel.SubmitEvent; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.InlineHTML; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.PopupPanel; import com.google.gwt.user.client.ui.ScrollPanel; import com.google.gwt.user.client.ui.SubmitButton; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.ToggleButton; import com.google.gwt.user.datepicker.client.CalendarUtil; import com.google.gwt.user.datepicker.client.DatePicker; import com.mashery.examples.api.client.hotwire.jso.HotelDeal; import com.mashery.examples.api.client.hotwire.jso.HotwireResponse; public class HotwireExample extends Composite { private final PopupPanel infoPanel; private final FlexTable infoGrid; private final Anchor visitLink; private HotelDeal selectedResult; public HotwireExample(final PopupMapWidget mapWidget) { FlowPanel panel = new FlowPanel(); panel.add(new HTML("<h1>Hotel Deals</h1>")); FormPanel form = new FormPanel(); panel.add(form); FlexTable entryGrid = new FlexTable(); form.add(entryGrid); FlexTable.FlexCellFormatter formatter = (FlexCellFormatter) entryGrid.getCellFormatter(); entryGrid.setWidget(0, 0, new Label("Destination:")); formatter.setHorizontalAlignment(0, 0, HasHorizontalAlignment.ALIGN_RIGHT); FlowPanel destPanel = new FlowPanel(); entryGrid.setWidget(0, 1, destPanel); formatter.setColSpan(0, 1, 5); final TextBox destText = new TextBox(); destPanel.add(destText); destText.setWidth("220px"); Anchor fromMapLink = new Anchor("<- from Map"); fromMapLink.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { HasLatLng center = mapWidget.getMap().getCenter(); destText.setText(center.getLatitude() + "," + center.getLongitude()); } }); destPanel.add(new InlineHTML(" ")); destPanel.add(fromMapLink); entryGrid.setWidget(1, 0, new Label("From:")); formatter.setHorizontalAlignment(1, 0, HasHorizontalAlignment.ALIGN_RIGHT); final TextBox startDateText = new TextBox(); entryGrid.setWidget(1, 1, startDateText); startDateText.setWidth("100px"); final PopupPanel startDatePanel = new PopupPanel(true); startDatePanel.setAutoHideOnHistoryEventsEnabled(true); final ToggleButton startDateButton = new ToggleButton(new Image("resources/img/date-picker.gif")); entryGrid.setWidget(1, 2, startDateButton); startDateButton.setPixelSize(16, 16); startDatePanel.addAutoHidePartner(startDateButton.getElement()); startDateButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { startDatePanel.showRelativeTo(startDateButton); } }); startDatePanel.addCloseHandler(new CloseHandler<PopupPanel>() { @Override public void onClose(CloseEvent<PopupPanel> event) { startDateButton.setDown(false); } }); final DateTimeFormat dateFormat = DateTimeFormat.getFormat("MM/dd/yyyy"); final DatePicker startDatePicker = new DatePicker(); startDatePanel.setWidget(startDatePicker); startDatePicker.addValueChangeHandler(new ValueChangeHandler<Date>() { @Override public void onValueChange(ValueChangeEvent<Date> event) { startDateText.setText(dateFormat.format(event.getValue())); startDatePanel.hide(); } }); startDateText.addValueChangeHandler(new ValueChangeHandler<String>() { @Override public void onValueChange(ValueChangeEvent<String> event) { try { Date date = dateFormat.parse(event.getValue()); startDatePicker.setValue(date); } catch (IllegalArgumentException e) { // ignore } } }); Date date = new Date(); startDatePicker.setValue(date, true); entryGrid.setWidget(1, 3, new Label("To:")); formatter.setHorizontalAlignment(1, 2, HasHorizontalAlignment.ALIGN_RIGHT); final TextBox endDateText = new TextBox(); entryGrid.setWidget(1, 4, endDateText); endDateText.setWidth("100px"); final PopupPanel endDatePanel = new PopupPanel(true); endDatePanel.setAutoHideOnHistoryEventsEnabled(true); final ToggleButton endDateButton = new ToggleButton(new Image("resources/img/date-picker.gif")); entryGrid.setWidget(1, 5, endDateButton); endDateButton.setPixelSize(16, 16); endDatePanel.addAutoHidePartner(endDateButton.getElement()); endDateButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { endDatePanel.showRelativeTo(endDateButton); } }); endDatePanel.addCloseHandler(new CloseHandler<PopupPanel>() { @Override public void onClose(CloseEvent<PopupPanel> event) { endDateButton.setDown(false); } }); final DatePicker endDatePicker = new DatePicker(); endDatePanel.setWidget(endDatePicker); endDatePicker.addValueChangeHandler(new ValueChangeHandler<Date>() { @Override public void onValueChange(ValueChangeEvent<Date> event) { endDateText.setText(dateFormat.format(event.getValue())); endDatePanel.hide(); } }); endDateText.addValueChangeHandler(new ValueChangeHandler<String>() { @Override public void onValueChange(ValueChangeEvent<String> event) { try { Date date = dateFormat.parse(event.getValue()); endDatePicker.setValue(date); } catch (IllegalArgumentException e) { // ignore } } }); date = CalendarUtil.copyDate(date); CalendarUtil.addDaysToDate(date, 1); endDatePicker.setValue(date, true); SubmitButton submitButton = new SubmitButton("Search"); entryGrid.setWidget(2, 0, submitButton); formatter.setColSpan(2, 0, 6); formatter.setHorizontalAlignment(2, 0, HasHorizontalAlignment.ALIGN_RIGHT); final HotelDealsTable table = new HotelDealsTable(10); panel.add(table); table.setWidth("500px"); form.addSubmitHandler(new FormPanel.SubmitHandler() { @Override public void onSubmit(SubmitEvent event) { String dest = destText.getValue().trim(); String start = startDateText.getValue().trim(); String end = endDateText.getValue().trim(); table.loadData(dest.length() == 0 ? null : dest, start.length() == 0 ? null : start, end.length() == 0 ? null : end); event.cancel(); } }); infoPanel = new PopupPanel(true); infoPanel.setAutoHideOnHistoryEventsEnabled(true); infoGrid = new FlexTable(); infoPanel.setWidget(infoGrid); FlowPanel linkPanel = new FlowPanel(); infoGrid.setWidget(3, 0, linkPanel); Anchor mapLink = new Anchor("Map", "#"); linkPanel.add(mapLink); mapLink.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { event.preventDefault(); if (selectedResult == null) return; MarkerOptions opt = new MarkerOptions(); opt.setTitle(selectedResult.getHeadline()); LatLng latLng = new LatLng(selectedResult.getNeighborhoodLatitude(), selectedResult.getNeighborhoodLongitude()); opt.setPosition(latLng); opt.setClickable(true); opt.setVisible(true); mapWidget.show(new Marker(opt)); } }); mapWidget.addAutoHidePartner(mapLink.getElement()); linkPanel.add(new InlineHTML(" | ")); linkPanel.add(visitLink = new Anchor("Visit", "#")); initWidget(new ScrollPanel(panel)); } private class HotelDealsTable extends PagedTable<HotwireResponse> { public HotelDealsTable(int pageSize) { super(pageSize); table.setHTML(0, 0, "<strong>#</strong>"); table.setHTML(0, 1, "<strong>Headline</strong>"); table.setHTML(0, 2, "<strong>Rating</strong>"); table.getCellFormatter().setWidth(0, 1, "100%"); table.setText(1, 1, "No data"); } @Override protected void reloadData(Object... args) { search((String) args[0], (String) args[1], (String) args[2]); } private void search(String dest, String start, String end) { StringBuilder buf = new StringBuilder("/examples/hotwire/hoteldeals?limit="); buf.append(pageSize); if (pageIndex > 0) buf.append("%7C").append(pageIndex * pageSize); if (dest != null) buf.append("&dest=").append(URL.encodeQueryString(dest)); if (start != null) buf.append("&startdate=").append(URL.encodeQueryString(start)); if (end != null) buf.append("&enddate=").append(URL.encodeQueryString(end)); RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, buf.toString()); try { builder.sendRequest(null, new RequestCallback() { @Override public void onResponseReceived(Request request, Response response) { if (response.getStatusCode() == 200) { String text = response.getText(); HotwireResponse result = HotwireResponse.fromSource(text); dataLoadedCallback.onSuccess(result); } else { dataLoadedCallback.onFailure(new RuntimeException(response.getStatusText())); } } @Override public void onError(Request request, Throwable exception) { dataLoadedCallback.onFailure(exception); } }); } catch (RequestException e) { dataLoadedCallback.onFailure(e); } } @Override protected void dataLoaded(HotwireResponse response) { // TODO handle error responses int n = 0; JsArray<HotelDeal> hotelDeals = response.getHotelDeals(); if (hotelDeals != null) { n = hotelDeals.length(); pageCount = n >= pageSize ? pageIndex + 2 : pageIndex + 1; int offset = pageIndex * pageSize; for (int i = 0; i < n; ++i) { final HotelDeal hotelDeal = hotelDeals.get(i); table.setText(i + 1, 0, i + offset + 1 + "."); final HTML label = new HTML(hotelDeal.getHeadline()); table.setWidget(i + 1, 1, label); double r = hotelDeal.getStarRating(); int w = (int) r * 17; Image img = new Image("resources/img/stars.gif", 0, 0, w + 2, 15); table.setWidget(i + 1, 2, img); if (r == 1d) img.setTitle("1 star"); else img.setTitle((r == Math.rint(r) ? Integer.toString((int) r) : Double.toString(r)) + " stars"); label.addMouseOverHandler(new MouseOverHandler() { @Override public void onMouseOver(MouseOverEvent event) { selectedResult = hotelDeal; visitLink.setHref(hotelDeal.getUrl() == null ? "#" : hotelDeal.getUrl()); StringBuilder buf = new StringBuilder(); if (hotelDeal.getNeighborhood() != null) buf.append("<strong>").append(hotelDeal.getNeighborhood()).append("</strong>"); if (hotelDeal.getCity() != null) { if (buf.length() > 0) buf.append(", "); buf.append(hotelDeal.getCity()); } if (hotelDeal.getStateCode() != null) { if (buf.length() > 0) buf.append(", "); buf.append(hotelDeal.getStateCode()); } if (hotelDeal.getCountryCode() != null && !hotelDeal.getCountryCode().equals(hotelDeal.getStateCode())) { if (buf.length() > 0) buf.append(", "); buf.append(hotelDeal.getCountryCode()); } infoGrid.setHTML(0, 0, buf.toString()); infoGrid.setText(1, 0, "Found on: " + DateTimeFormat.getFormat(PredefinedFormat.DATE_MEDIUM).format(new Date((long) hotelDeal.getFoundDate()))); infoGrid.setHTML(2, 0, "Price per night: <strong>" + NumberFormat.getCurrencyFormat().format(hotelDeal.getPrice()) + "</strong>"); infoPanel.showRelativeTo(label); } }); } } for (int i = Math.min(pageSize + 1, table.getRowCount()) - 1; i > n; --i) { table.removeRow(i); } } } }