Tuesday, December 18, 2012

Tired eyes? Code on the dark side.

If you have a Mac, press ctrl-alt-command+8 and the screen colours invert.  Great for the eyes.  I wonder how many other obscure useful key combinations are hiding in OSX for me to discover?

I've been trying out IntelliJ IDEA again today and love the new "Darcular" theme that makes is easy on the eyes, especially at night. I do think that, given time, I would come to prefer it over Eclipse.  It seems everybody does.  The basic premise that a comercial product will have less bugs and more features holds true because they have more incentive to keep customers happy.

This week however, I do not have the time to re-learn all the keybindings and figure out where the configuration options are.  Once again I've put it aside till another day... or decade.


Wednesday, December 12, 2012

Google Maps v3 with GWT - Example

For a long time there was no official port of Google Maps v3 to GWT.  This issue, created in June 2010, is still marked as "Started".  Comments on that issue seem to indicate that the problem was due to the difficulty in generating the bindings automatically so it would be easy to keep in sync with the JavaScript API.  The older v2 maps API also did not use overlay types which allows more optimised code to be generated, which v3 does.

Finally in March 2012 an official "prerelease" build was posted to the issue but never properly released.  However, it is very usable and seems quite complete.  One nice thing is that because it is generated automatically from the JavaScript API, it matches up very closely to the official docs.  An obvious exception to this is the central class is name GoogleMap rather than Map for obvious reasons.

I'll write a little about getting started using these maps and include a little demo.  The demo uses your current location (from HTML5 geo location object) and draws a circle on the map where it things you are.  The map is zoomed according to how accurate the reading is so the circle should look about the same size no matter what the accuracy.

Start by getting the jar and putting it in a folder somewhere (not in your WEB-INF) and add it to your class path.  Keep an eye on the downloads page in case a more recent lib is released.  At this point it is for the Maps 3.8.1 API which is a already a little out of date but looking at the changelog, I can't see any great features I'd be missing.

First here is the working demo: (watch out for the dialog asking if it can use your location)


and here is the code... First the module
<module rename-to="mapdemo">
  <inherits name="com.google.gwt.user.User"/>
  <inherits name="com.google.maps.gwt.GoogleMaps"/>
  <entry-point class="com.vercer.mapdemo.client.Mapdemo"/>
  <add-linker name="xsiframe" />
</module>
and the GWT code to create a JS file that can be used "cross site"

public class Mapdemo implements EntryPoint
{
 public void onModuleLoad()
 {
  Geolocation geolocation = Geolocation.getIfSupported();
  if (geolocation == null)
  {
   Window.alert("Your old browser is stuck in the past");
  }
  
  geolocation.getCurrentPosition(new Callback<Position, PositionError>()
  {
   
   @Override
   public void onSuccess(Position result)
   {
    display(result.getCoordinates());
   }
   
   @Override
   public void onFailure(PositionError reason)
   {
    Window.alert(reason.getMessage());
   }
  });
 }

 protected void display(Coordinates coordinates)
 {
  // create a bounds 10 times larger than the accuracy error
  LatLng center = LatLng.create(coordinates.getLatitude(), coordinates.getLongitude());
  LatLng sw = Spherical.computeOffset(center, coordinates.getAccuracy() * 10, 225);
  LatLng ne = Spherical.computeOffset(center, coordinates.getAccuracy() * 10, 45);
  
  LatLngBounds outer = LatLngBounds.create(sw, ne);
  
  // create the map
  MapOptions mapOptions = MapOptions.create();
  mapOptions.setMapTypeId(MapTypeId.HYBRID);
  GoogleMap map = GoogleMap.create(Document.get().getElementById("map"), mapOptions);
  map.fitBounds(outer);
  
  // create a circle the size of the error
  CircleOptions circleOptions = CircleOptions.create();
  circleOptions.setFillOpacity(0.2);
  circleOptions.setFillColor("yellow");
  circleOptions.setStrokeColor("yellow");
  Circle circle = Circle.create(circleOptions);
  circle.setCenter(center);
  circle.setRadius(coordinates.getAccuracy());
  circle.setMap(map);
 }
}