001 package com.google.gwt.maps.client;
002
003 import java.util.Collection;
004 import java.util.HashMap;
005 import java.util.Iterator;
006
007 import com.google.gwt.core.client.JavaScriptObject;
008 import com.google.gwt.dom.client.Element;
009 import com.google.gwt.event.shared.HandlerRegistration;
010 import com.google.gwt.maps.client.base.LatLng;
011 import com.google.gwt.maps.client.base.LatLngBounds;
012 import com.google.gwt.maps.client.controls.ControlPosition;
013 import com.google.gwt.maps.client.events.MapHandlerRegistration;
014 import com.google.gwt.maps.client.events.MapPanel;
015 import com.google.gwt.maps.client.events.bounds.BoundsChangeMapHandler;
016 import com.google.gwt.maps.client.events.center.CenterChangeMapHandler;
017 import com.google.gwt.maps.client.events.click.ClickMapHandler;
018 import com.google.gwt.maps.client.events.dblclick.DblClickMapHandler;
019 import com.google.gwt.maps.client.events.drag.DragMapHandler;
020 import com.google.gwt.maps.client.events.dragend.DragEndMapHandler;
021 import com.google.gwt.maps.client.events.dragstart.DragStartMapHandler;
022 import com.google.gwt.maps.client.events.heading.HeadingChangeMapHandler;
023 import com.google.gwt.maps.client.events.idle.IdleMapHandler;
024 import com.google.gwt.maps.client.events.maptypeid.MapTypeIdChangeMapHandler;
025 import com.google.gwt.maps.client.events.mousemove.MouseMoveMapHandler;
026 import com.google.gwt.maps.client.events.mouseout.MouseOutMapHandler;
027 import com.google.gwt.maps.client.events.mouseover.MouseOverMapHandler;
028 import com.google.gwt.maps.client.events.projection.ProjectionChangeMapHandler;
029 import com.google.gwt.maps.client.events.resize.ResizeMapHandler;
030 import com.google.gwt.maps.client.events.rightclick.RightClickMapHandler;
031 import com.google.gwt.maps.client.events.tiles.TilesLoadedMapHandler;
032 import com.google.gwt.maps.client.events.tilt.TiltChangeMapHandler;
033 import com.google.gwt.maps.client.events.zoom.ZoomChangeMapHandler;
034 import com.google.gwt.maps.client.maptypes.MapTypeRegistry;
035 import com.google.gwt.maps.client.maptypes.Projection;
036 import com.google.gwt.maps.client.maptypes.StyledMapType;
037 import com.google.gwt.maps.client.mvc.MVCArray;
038 import com.google.gwt.maps.client.mvc.MVCObjectWidget;
039 import com.google.gwt.maps.client.streetview.StreetViewPanoramaImpl;
040 import com.google.gwt.user.client.DOM;
041 import com.google.gwt.user.client.ui.Widget;
042
043 public class MapWidget extends MVCObjectWidget<MapImpl> {
044
045 /**
046 * added controls, must remove them when finished
047 */
048 private HashMap<Integer, Widget> controls = null;
049
050 /**
051 * Reconstruct the mapWidget from JSO
052 *
053 * @param impl
054 * @return NULL if input is NULL
055 */
056 public static MapWidget newInstance(MapImpl impl) {
057 if (impl == null) {
058 return null;
059 }
060 return new MapWidget(impl);
061 }
062
063 /**
064 * create a new Map Widget
065 *
066 * @param options
067 * {@link MapOptions}
068 */
069 public MapWidget(MapOptions options) {
070 Element div = DOM.createDiv();
071 setElement(div);
072 impl = MapImpl.newInstance(div, options);
073 setStyleName("gwt-map-MapWidget-div");
074 }
075
076 @Override
077 protected void onDetach() {
078 removeControls();
079 super.onDetach();
080 }
081
082 private void removeControls() {
083 if (controls == null) {
084 return;
085 }
086 Collection<Widget> widgets = controls.values();
087 Iterator<Widget> itr = widgets.iterator();
088 while (itr.hasNext()) {
089 Widget w = itr.next();
090 w.removeFromParent();
091 }
092 }
093
094 /**
095 * reconstruct the mapWidget from jso
096 *
097 * @param impl
098 * JavaScriptObject
099 */
100 private MapWidget(MapImpl impl) {
101 this.impl = impl;
102 setElement(impl.getDiv());
103 setStyleName("gwt-map-MapWidget-div");
104 }
105
106 /**
107 * get JavaScriptObject instance.
108 *
109 * @return {@link MapImpl}
110 */
111 public MapImpl getJso() {
112 return impl;
113 }
114
115 /**
116 * sets JavaScriptObject instance.
117 *
118 * @param impl
119 * {@link MapImpl}
120 */
121 public void setJso(MapImpl impl) {
122 this.impl = impl;
123 }
124
125 /**
126 * Sets the viewport to contain the given bounds.
127 *
128 * @param bounds
129 * {@link LatLngBounds}
130 */
131 public void fitBounds(LatLngBounds bounds) {
132 impl.fitBounds(bounds);
133 }
134
135 /**
136 * Returns the lat/lng bounds of the current viewport. If the map is not yet
137 * initialized (i.e. the mapType is still null), or center and zoom have not
138 * been set then the result is null or undefined.
139 *
140 * @return {@link LatLngBounds}
141 */
142 public LatLngBounds getBounds() {
143 return impl.getBounds();
144 }
145
146 /**
147 * get Center
148 *
149 * @return {@link LatLng}
150 */
151 public LatLng getCenter() {
152 return impl.getCenter();
153 }
154
155 /**
156 * get Element
157 */
158 public Element getDiv() {
159 return impl.getDiv();
160 }
161
162 /**
163 * Returns the compass heading of aerial imagery. The heading value is
164 * measured in degrees (clockwise) from cardinal direction North.
165 *
166 * @return int
167 */
168 public int getHeading() {
169 return impl.getHeading();
170 }
171
172 /**
173 * gets {@link MapTypeId}
174 *
175 * @return {@link MapTypeId}
176 */
177 public final MapTypeId getMapTypeId() {
178 return impl.getMapTypeId();
179 }
180
181 /**
182 * Returns the current Projection. If the map is not yet initialized (i.e.
183 * the mapType is still null) then the result is null. Listen to
184 * projection_changed and check its value to ensure it is not null.
185 *
186 * @return {@link Projection}
187 */
188 public Projection getProjection() {
189 return impl.getProjection();
190 }
191
192 /**
193 * Returns the default StreetViewPanorama bound to the map, which may be a
194 * default panorama embedded within the map, or the panorama set using
195 * setStreetView(). Changes to the map's streetViewControl will be reflected
196 * in the display of such a bound panorama.
197 *
198 * @return {@link StreetViewPanoramaImpl}
199 */
200 public StreetViewPanoramaImpl getStreetView() {
201 return impl.getStreetView();
202 };
203
204 /**
205 * gets Returns the angle of incidence for aerial imagery (available for
206 * SATELLITE and HYBRID map types) measured in degrees from the viewport
207 * plane to the map plane. A value of 0 indicates no angle of incidence (no
208 * tilt) while 45° imagery will return a value of 45.
209 */
210 public int getTilt() {
211 return impl.getTilt();
212 };
213
214 /**
215 * get zoom
216 */
217 public int getZoom() {
218 return impl.getZoom();
219 };
220
221 /**
222 * Changes the center of the map by the given distance in pixels. If the
223 * distance is less than both the width and height of the map, the
224 * transition will be smoothly animated. Note that the map coordinate system
225 * increases from west to east (for x values) and north to south (for y
226 * values).
227 *
228 * @param x
229 * @param y
230 */
231 public void panBy(int x, int y) {
232 impl.panBy(x, y);
233 };
234
235 /**
236 * Changes the center of the map to the given LatLng. If the change is less
237 * than both the width and height of the map, the transition will be
238 * smoothly animated.
239 *
240 * @param latLng
241 */
242 public void panTo(LatLng latLng) {
243 impl.panTo(latLng);
244 };
245
246 /**
247 * Pans the map by the minimum amount necessary to contain the given
248 * LatLngBounds. It makes no guarantee where on the map the bounds will be,
249 * except that as much of the bounds as possible will be visible. The bounds
250 * will be positioned inside the area bounded by the map type and navigation
251 * (pan, zoom, and Street View) controls, if they are present on the map. If
252 * the bounds is larger than the map, the map will be shifted to include the
253 * northwest corner of the bounds. If the change in the map's position is
254 * less than both the width and height of the map, the transition will be
255 * smoothly animated.
256 *
257 * @param latLngBounds
258 */
259 public void panToBounds(LatLngBounds latLngBounds) {
260 impl.panToBounds(latLngBounds);
261 };
262
263 /**
264 * set center
265 *
266 * @param latlng
267 */
268 public void setCenter(LatLng latlng) {
269 impl.setCenter(latlng);
270 };
271
272 /**
273 * Sets the compass heading for aerial imagery measured in degrees from
274 * cardinal direction North.
275 *
276 * @param heading
277 */
278 public void setHeading(int heading) {
279 impl.setHeading(heading);
280 };
281
282 /**
283 * set MapTypeId
284 *
285 * @param mapTypeId
286 */
287 public final void setMapTypeId(MapTypeId mapTypeId) {
288 impl.setMapTypeId(mapTypeId);
289 }
290
291 /**
292 * set MapOptions
293 *
294 * @param options
295 */
296 public void setOptions(MapOptions options) {
297 impl.setOptions(options);
298 };
299
300 /**
301 * Sets the angle of incidence for aerial imagery (available for SATELLITE
302 * and HYBRID map types) measured in degrees from the viewport plane to the
303 * map plane. The only supported values are 0, indicating no angle of
304 * incidence (no tilt), and 45 indicating a tilt of 45°.
305 *
306 * @param panorama
307 */
308 public void setStreetView(StreetViewPanoramaImpl panorama) {
309 impl.setStreetView(panorama);
310 };
311
312 /**
313 * Sets the angle of incidence for aerial imagery (available for SATELLITE
314 * and HYBRID map types) measured in degrees from the viewport plane to the
315 * map plane. The only supported values are 0, indicating no angle of
316 * incidence (no tilt), and 45 indicating a tilt of 45°.
317 *
318 * @param tilt
319 */
320 public void setTilt(int tilt) {
321 impl.setTilt(tilt);
322 };
323
324 /**
325 * sets map zoom
326 *
327 * @param zoom
328 */
329 public void setZoom(int zoom) {
330 impl.setZoom(zoom);
331 };
332
333 /**
334 * TODO sets Additional controls to attach to the map. To add a control to
335 * the map, add the control's <code><div></code> to the MVCArray
336 * corresponding to the ControlPosition where it should be rendered.
337 *
338 * @param controls
339 */
340 public void setControls(MVCArray<Element> controls) {
341 impl.setControls(controls);
342 };
343
344 /**
345 * sets Additional controls to attach to the map. To add a control to the
346 * map, add the control's <code><div></code> to the MVCArray
347 * corresponding to the ControlPosition where it should be rendered.
348 *
349 * @param controlPosition
350 * @param element
351 */
352 public void setControls(ControlPosition controlPosition, Element element) {
353 impl.setControls(controlPosition, element);
354 };
355
356 /**
357 * sets Additional controls to attach to the map. To add a control to the
358 * map, add the control's <code><div></code> to the MVCArray
359 * corresponding to the ControlPosition where it should be rendered.
360 *
361 * @param controlPosition
362 * @param widget
363 */
364 public void setControls(ControlPosition controlPosition, Widget widget) {
365
366 // remove any pre-existing controls
367 removePriorControlFirst(controlPosition);
368
369 // use a panel that controls onAttatch
370 MapPanel mapPanel = new MapPanel();
371 mapPanel.add(widget);
372
373 // add it to array for detaching
374 if (controls == null) {
375 controls = new HashMap<Integer, Widget>();
376 }
377 controls.put(controlPosition.value(), mapPanel);
378
379 // add it to the map
380 impl.setControls(controlPosition, mapPanel.getElement());
381 };
382
383 /**
384 * remove an pre-existing control so we don't get a mem leak
385 *
386 * @param controlPosition
387 * @param widget
388 */
389 private void removePriorControlFirst(ControlPosition controlPosition) {
390 if (controls == null) {
391 return;
392 }
393 Widget w = controls.get(controlPosition.value());
394 if (w == null) {
395 return;
396 }
397 w.removeFromParent();
398 }
399
400 /**
401 * TODO gets Additional controls to attach to the map. To add a control to
402 * the map, add the control's <code><div></code> to the MVCArray
403 * corresponding to the ControlPosition where it should be rendered.
404 */
405 public MVCArray<Element> getControls() {
406 return impl.getControls();
407 };
408
409 /**
410 * TODO sets A registry of MapType instances by string ID.
411 *
412 * @param mapTypes
413 */
414 public void setMapTypesRegistry(MapTypeRegistry mapTypes) {
415 impl.setMapTypesRegistry(mapTypes);
416 };
417
418 /**
419 * Set the custom map type into the map's registry
420 *
421 * @param mapTypeId
422 * @param styledType
423 */
424 public void setCustomMapType(String mapTypeId, StyledMapType styledType) {
425 impl.setCustomMapType(mapTypeId, styledType);
426 }
427
428 /**
429 * gets a registry of MapType instances
430 */
431 public MapTypeRegistry getMapTypeRegistry() {
432 return impl.getMapTypeRegistry();
433 };
434
435 /**
436 * TODO sets Additional map types to overlay.
437 *
438 * @param overlayMapTypes
439 */
440 public void setOverlayMapTypes(MVCArray<JavaScriptObject> overlayMapTypes) {
441 impl.setOverlayMapTypes(overlayMapTypes);
442 };
443
444 /**
445 * TODO gets Additional map types to overlay.
446 */
447 public MVCArray<JavaScriptObject> getOverlayMapTypes() {
448 return impl.getOverlayMapTypes();
449 };
450
451 /**
452 * This event is fired when the viewport bounds have changed.
453 *
454 * @param handler
455 * {@link BoundsChangeMapHandler}
456 * @return {@link MapHandlerRegistration}
457 */
458 public HandlerRegistration addBoundsChangeHandler(
459 BoundsChangeMapHandler handler) {
460 return impl.addBoundsChangeHandler(handler);
461 }
462
463 /**
464 * This event is fired when the map center property changes.
465 *
466 * @param handler
467 * {@link CenterChangeMapHandler}
468 * @return {@link MapHandlerRegistration}
469 */
470 public HandlerRegistration addCenterChangeHandler(
471 CenterChangeMapHandler handler) {
472 return impl.addCenterChangeHandler(handler);
473 }
474
475 /**
476 * This event is fired when the user clicks on the map (but not when they
477 * click on a marker or infowindow).
478 *
479 * @param handler
480 * {@link ClickMapHandler}
481 * @return {@link MapHandlerRegistration}
482 */
483 public HandlerRegistration addClickHandler(ClickMapHandler handler) {
484 return impl.addClickHandler(handler);
485 }
486
487 /**
488 * This event is fired when the user double-clicks on the map. Note that the
489 * click event will also fire, right before this one.
490 *
491 * @param handler
492 * {@link DblClickMapHandler}
493 * @return {@link MapHandlerRegistration}
494 */
495 public HandlerRegistration addDblClickHandler(DblClickMapHandler handler) {
496 return impl.addDblClickHandler(handler);
497 }
498
499 /**
500 * This event is repeatedly fired while the user drags the map.
501 *
502 * @param handler
503 * {@link DragMapHandler}
504 * @return {@link MapHandlerRegistration}
505 */
506 public HandlerRegistration addDragHandler(DragMapHandler handler) {
507 return impl.addDragHandler(handler);
508 }
509
510 /**
511 * This event is fired when the user stops dragging the map.
512 *
513 * @param handler
514 * {@link DragEndMapHandler}
515 * @return {@link MapHandlerRegistration}
516 */
517 public HandlerRegistration addDragEndHandler(DragEndMapHandler handler) {
518 return impl.addDragEndHandler(handler);
519 }
520
521 /**
522 * This event is fired when the user starts dragging the map.
523 *
524 * @param handler
525 * {@link DragStartMapHandler}
526 * @return {@link MapHandlerRegistration}
527 */
528 public HandlerRegistration addDragStartHandler(DragStartMapHandler handler) {
529 return impl.addDragStartHandler(handler);
530 }
531
532 /**
533 * This event is fired when the map heading property changes.
534 *
535 * @param handler
536 * {@link HeadingChangeMapHandler}
537 * @return {@link MapHandlerRegistration}
538 */
539 public HandlerRegistration addHeadingChangeHandler(
540 HeadingChangeMapHandler handler) {
541 return impl.addHeadingChangeHandler(handler);
542 }
543
544 /**
545 * This event is fired when the map becomes idle after panning or zooming.
546 *
547 * @param handler
548 * {@link IdleMapHandler}
549 * @return {@link MapHandlerRegistration}
550 */
551 public HandlerRegistration addIdleHandler(IdleMapHandler handler) {
552 return impl.addIdleHandler(handler);
553 }
554
555 /**
556 * This event is fired when the mapTypeId property changes.
557 *
558 * @param handler
559 * {@link MapTypeIdChangeMapHandler}
560 * @return {@link MapHandlerRegistration}
561 */
562 public HandlerRegistration addMapTypeIdChangeHandler(
563 MapTypeIdChangeMapHandler handler) {
564 return impl.addMapTypeIdChangeHandler(handler);
565 }
566
567 /**
568 * This event is fired whenever the user's mouse moves over the map
569 * container.
570 *
571 * @param handler
572 * {@link MouseMoveMapHandler}
573 * @return {@link MapHandlerRegistration}
574 */
575 public HandlerRegistration addMouseMoveHandler(MouseMoveMapHandler handler) {
576 return impl.addMouseMoveHandler(handler);
577 }
578
579 /**
580 * This event is fired when the user's mouse exits the map container.
581 *
582 * @param handler
583 * {@link MouseOutMapHandler}
584 * @return {@link MapHandlerRegistration}
585 */
586 public HandlerRegistration addMouseOutMoveHandler(MouseOutMapHandler handler) {
587 return impl.addMouseOutMoveHandler(handler);
588 }
589
590 /**
591 * This event is fired when the user's mouse enters the map container.
592 *
593 * @param handler
594 * {@link MouseOverMapHandler}
595 * @return {@link MapHandlerRegistration}
596 */
597 public HandlerRegistration addMouseOverHandler(MouseOverMapHandler handler) {
598 return impl.addMouseOverHandler(handler);
599 }
600
601 /**
602 * This event is fired when the projection has changed.
603 *
604 * @param handler
605 * {@link ProjectionChangeMapHandler}
606 * @return {@link MapHandlerRegistration}
607 */
608 public HandlerRegistration addProjectionChangeHandler(
609 ProjectionChangeMapHandler handler) {
610 return impl.addProjectionChangeHandler(handler);
611 }
612
613 /**
614 * Developers should trigger this event on the map when the div changes
615 * size: google.maps.event.trigger(map, 'resize') .
616 *
617 * @param handler
618 * {@link ResizeMapHandler}
619 * @return {@link MapHandlerRegistration}
620 */
621 public HandlerRegistration addResizeHandler(ResizeMapHandler handler) {
622 return impl.addResizeHandler(handler);
623 }
624
625 /**
626 * This event is fired when the DOM contextmenu event is fired on the map
627 * container.
628 *
629 * @param handler
630 * {@link RightClickMapHandler}
631 * @return {@link MapHandlerRegistration}
632 */
633 public HandlerRegistration addRightClickHandler(RightClickMapHandler handler) {
634 return impl.addRightClickHandler(handler);
635 }
636
637 /**
638 * This event is fired when the visible tiles have finished loading.
639 *
640 * @param handler
641 * {@link TilesLoadedMapHandler}
642 * @return {@link MapHandlerRegistration}
643 */
644 public HandlerRegistration addTilesLoadedHandler(
645 TilesLoadedMapHandler handler) {
646 return impl.addTilesLoadedHandler(handler);
647 }
648
649 /**
650 * This event is fired when the map tilt property changes.
651 *
652 * @param handler
653 * {@link TiltChangeMapHandler}
654 * @return {@link MapHandlerRegistration}
655 */
656 public HandlerRegistration addTiltChangeHandler(TiltChangeMapHandler handler) {
657 return impl.addTiltChangeHandler(handler);
658 }
659
660 /**
661 * This event is fired when the map zoom property changes.
662 *
663 * @param handler
664 * {@link ZoomChangeMapHandler}
665 * @return {@link MapHandlerRegistration}
666 */
667 public HandlerRegistration addZoomChangeHandler(ZoomChangeMapHandler handler) {
668 return impl.addZoomChangeHandler(handler);
669 }
670
671 }