Oct 28

Why Python, Why Now?

So 9 years ago this month, I completed a rewrite of an app that a coworker had written in Python.

I rewrote it in a combination of simple Unix shell scripts and more complex .sql files.

Why?  Because it was the only Python program around, and there was NO GOOGLE.
 
 At least not in the way there is today, where hundreds of examples, tutorials, and guides are a keyword search away.
 
Also, because the parts that were written in Python were really simple, fire off a cron, send an email, but lots of code had been devoted to them as he explored the language.
 
But the parts that *needed* to be concentrated on were the database queries – it was an ETL program – one that did a massive 30GB data transformation every month.
 
 When I started on the project, the process from start to finish took three people and entire month.  When I left, it was running automatically in 10 hours.
 
So, it wasn’t that the Python itself was bad, rather, it was concentrating on the wrong problem.
Now I find myself contemplating taking on a huge Python-based project.  And I ask myself…why Python, Why Now?
 
Because for this project, the hard part IS something well-served by lots of tight snippets of app code, and now there IS Google.
 
But mainly, it’s because of the Python community – much like the much-touted iPhone slogan, in Python “There’s an egg for that”.  An egg is a little package of reusable code that someone else made ready for you to use…for free.
 
The library of eggs is now so vast, and so HIGH QUALITY (overall), that it’s a massively compelling toolbox now.
 
And, even if the egg is poorly documented, Python is so easy to read that it’s often a quick matter to figure out how to use it just from reading the source…which is NOT true of something like Java.
 
The world has changed a lot since 2001 – and IMO, in 2010, the winners in the tool wars will be the ones who get the most information on their tools available on the internet – for free…
Aug 27

Creating Custom Google Maps Overlays with GWT Widgets

So this is one of those that I went around and around on before finding out the solution, which of course turned out to be pretty darn simple.

What I was trying to do was add a box with some text under a marker on a Google Map.

I’m using Google Web Toolkit 1.5.1 and the official gwt-google-apis maps-api.jar to bind the maps stuff into GWT.

It turns out that the secret is coming to an understanding of how Panes work in Google Maps.

The pane is the whole map.  Even the stuff that you can’t see in the little container box on your page.

That pane has Pixel coordinates.

Those coordinates do not change, even when you scroll the map.

That’s right.

The pixel coordinates of the map pane do not change when you scroll the map around inside the box on your page.

So if you add a widget to the pane at a certain pixel location, that widget doesn’t have to change it’s location when you scroll the map.

It also means that the widget can slide under the edge of your viewing port just like Markers do.

So all you need to do is decide where you want your GWT Widget to be in terms of Lat/Long and call the handy myMapWidget.convertLatLngToDivPixel(LatLong) method, and you’ll get back a Point on the map that is an absolute location on the map pane to place your Widget on.

As soon as you realize that the map pane coordinates don’t change when you scroll, and that you need to add your widgets to the pane rather than some other panel, life is super-easy.

Here is the class I wrote to implement the label.  I use it to place under Markers to label them on the map.

/* Custom Map Overlay Code – Copyright 2008 Cyface Design, Released Under the Apache 2.2 License */

import com.google.gwt.maps.client.MapPane; import
com.google.gwt.maps.client.MapPaneType; import com.google.gwt.maps.client.MapWidget; import com.google.gwt.maps.client.geom.LatLng; import com.google.gwt.maps.client.geom.Point; import com.google.gwt.maps.client.overlay.Overlay; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.SimplePanel;
 
public class MapMarkerTextOverlay extends Overlay {
 
private final LatLng latLng;
private final SimplePanel textPanel;
private MapWidget parentMap;
private MapPane pane;
private String text;
private Point offset;
 
/** * Main constructor *
@param latLng
*/
 
public MapMarkerTextOverlay(LatLng latLng, String text, Point offset) {
 
/* Save our inputs to the object */
this.latLng = latLng;
this.text = text;
this.offset = offset;
 
/* Create a widget for the text */
HTML textWidget = new HTML(text);
 
/* Create the panel to hold the text */
textPanel = new SimplePanel(); textPanel.setStyleName(“textOverlayPanel”);
textPanel.add(textWidget);
 
/* Panel gets added to the map and placed in the initialize method */
 
}
 
@Override protected final void initialize(MapWidget map) {
 
/* Save a handle to the parent map widget */
parentMap = map;
//If we need to do redraws we’ll need this
/* Add our textPanel to the main map pane */
 
pane = map.getPane(MapPaneType.MARKER_PANE); pane.add(textPanel);
 
/* Place the textPanel on the pane in the correct spot */
Point locationPoint = parentMap.convertLatLngToDivPixel(getLatLng()); Point offsetPoint = new Point(locationPoint.getX()-getOffset().getX(), locationPoint.getY()-getOffset().getY()); pane.setWidgetPosition(textPanel, offsetPoint.getX(), offsetPoint.getY());
}
 
@Override protected final Overlay copy() {
return new MapMarkerTextOverlay(getLatLng(), getText(), getOffset());
} @Override protected final void redraw(boolean force) {
 
/* Shouldn’t need to do anything here since we’re on the Marker pane. */
} @Override protected final void remove() { textPanel.removeFromParent();
} public LatLng getLatLng() {
return latLng;
 
} public String getText() { return text; }
 
public void setText(String text) { this.text = text; }
public Point getOffset() { return offset; }
public void setOffset(Point offset) { this.offset = offset; }
}