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 }