Google Map Widget - GMarkerEventClickListener

12 views
Skip to first unread message

www.gtraffic.info

unread,
Aug 23, 2006, 4:48:33 PM8/23/06
to Google Web Toolkit
I have created an marker event listener like so

class RegionMarkerEventListener implements GMarkerEventClickListener
{
MapApplication app = null;

RegionMarkerEventListener(MapApplication app)
{
this.app = app;
}

public void onClick(GMarker marker)
{
// Stuff
}

public void onDblClick(GMarker marker) {
// TODO Auto-generated method stub
}
}


This gets assigned to 'region' markers within my main 'MapApplication'
like so..

GMarkerEventManager markerEventManager =
GMarkerEventManager.getInstance();

markerEventManager.addOnClickListener(marker, new
RegionMarkerEventListener(this));

Where 'marker' is the region marker object.

When I click on the a marker on the map the onClick method of the
listener gets executed and then again and then again in some sort of
infinite loop. I have checked
the marker id (opaque) and it's always the same marker. Any ideas?

Is anyone else actually using the map widget? I am starting to feel a
bit lonely here.

Al
www.gtraffic.info

aglaforge

unread,
Aug 23, 2006, 6:31:39 PM8/23/06
to Google Web Toolkit
Al,

I'm most definately using the map widget (very extensively actually) on
my website (I'd be happy to send you a link).

Is your problem in FireFox, IE, or both? After looking at your post,
I'm finding a problem with how FireFox is behaving with some markers...
though I'm not entirerly certain why. I know previous version of the
Map Widget didn't have an issue (although that is to say previous
version of the Map Widget were running against a different GWT
framework). IE seems to be normal.

Regards,

Anthony

aglaforge

unread,
Aug 23, 2006, 11:51:38 PM8/23/06
to Google Web Toolkit
There appears to be something very strange going on at the GWT
generated level in Firefox. I have a feeling I'm going to need to
generate "pretty" code (e.g. no obfuscated code) and walk through this
with Vankman.

It's not clear exactly what is happening except that on the first try,
the onClick is sucessfully executed. On the second round the exception
comes back with XXX.h() is not a function. But it only seems to occur
the second time you click it... I think the "missing" function is on
the marker object for some reason but it's not clear how or why.

I'm almost wondering if there isn't a naming collision with the GWT
generated offuscated code and the Google Maps obfuscated code... not
sure why we would only be seeing this now.... hmm... need to look
closer, probably will not happen until next week.

aglaforge

unread,
Aug 24, 2006, 12:08:20 AM8/24/06
to Google Web Toolkit
In what has to be the scariest amount of voodoo code I've seen in the
while....take a look at the code below...one works, one does not... The
difference, the one that works calls the o.toString and does nothing
with it. The one that goes direct to the cast gets a method missing
error on the second time it's invoked with the same parameters.
Absolutely perplexing.

This works....

private void fireOnClickImpl(GMarker marker) {

if (clickEventListeners == null) return;

for (Iterator it = clickEventListeners.iterator(); it.hasNext();)
{
Object o = it.next();
o.toString();
GMarkerEventClickListener listener =
(GMarkerEventClickListener) o;
try
{
listener.onClick(marker);
}
catch(Throwable e)
{
Window.alert(e.getMessage());
}
}
}


--------------This doesn't

private void fireOnClickImpl(GMarker marker) {

if (clickEventListeners == null) return;

for (Iterator it = clickEventListeners.iterator(); it.hasNext();)
{
Object o = it.next();
GMarkerEventClickListener listener =
(GMarkerEventClickListener) o;
try
{
listener.onClick(marker);
}
catch(Throwable e)
{
Window.alert(e.getMessage());
}
}
}

aglaforge

unread,
Aug 24, 2006, 2:05:05 AM8/24/06
to Google Web Toolkit
I played around with this a bit more and simplified the above, but
still reached the same results. The error doesn't appear to be related
to the type cast (I went and created a seperate case which dealt
directly with the types) it seems to be related to the second (and
indeed all later) invocation(s) of onClick...

why a o.toString() in front would cure this problem...again this
appears to only be a FireFox issue...I dunno, maybe someone from GWT
might know.

www.gtraffic.info

unread,
Aug 24, 2006, 6:33:02 PM8/24/06
to Google Web Toolkit
Anthony,

I have tried this in hosted mode, Firefox and IE and it does the same
thing in all of them. Looking are your posts here I am not sure the
error you describe in your posts here is the same one I am seeing.

I am going to roll back to the previous version of your widget and the
previous version of GWT and see if the problem persists.

I would be interested in viewing the your GWT Google Map site. You can
mail me the link using the email mentioned in the 'About Me' section of
my gtraffic companion site www.netthreads.co.uk

I will keep the list posted on my progress.

Al.
www.gtraffic.info

www.gtraffic.info

unread,
Aug 25, 2006, 8:30:32 AM8/25/06
to Google Web Toolkit
Anthony.

Okay I have had a quick lunchtime debugging session and I think I have
found a bug in the widget code or I simply don't understand how to
create click handlers correctly.

My understanding of the listener is that when a marker is clicked the
listener associated with that marker is executed.

For each marker I execute the lines

GMarkerEventManager markerEventManager =
GMarkerEventManager.getInstance();
markerEventManager.addOnClickListener(marker, new
RegionMarkerEventListener(this));

Where I am passing a reference to the application I want the command
click hander to do something (in this case execute an HTTPRequest for
data). I am also passing a reference to the marker associated with the
handler. So far so good.

Putting a breakpoint into the onClick event of my marker click object
'RegionMarkerEventListener' I examine the call stack and see that the
calling function is 'fireOnClickImpl'. Lets look at the code for this.


private void fireOnClickImpl(GMarker marker) {

if (clickEventListeners == null) return;

for (Iterator it = clickEventListeners.iterator(); it.hasNext();)
{

GMarkerEventClickListener listener = (GMarkerEventClickListener)
it.next();
listener.onClick(marker);
}
}


Hmmmmm..that looks a bit like for..loop to to me and it seems to be
calling the onClick function for _every_ marker added. I have 84
clickable markers so that's 84 HHTPRequest calls getting executed which
is probably why my app grinds to a halt.

The only way I can get this to work is to pass a reference to each
associated marker into my 'RegionMarkerEventListener' class and in the
onClick method do the following


class RegionMarkerEventListener implements GMarkerEventClickListener
{
MapApplication app = null;

GMarker marker = null;


RegionMarkerEventListener(GMarker marker, MapApplication app)
{
this.marker = marker;
this.app = app;
}

public void onClick(GMarker marker)
{
if (this.marker.equals(marker))
{
// Something
}
}

public void onDblClick(GMarker marker) {
// TODO Auto-generated method stub
}
}

Either that or you store the associated marker in your
'GMarkerEventClickListener' and do a similar comparison on the function
'fireOnClickImpl'

private void fireOnClickImpl(GMarker marker) {

if (clickEventListeners == null) return;

Iterator it = clickEventListeners.iterator();
boolean found = false;
while (!found && it.hasNext()) {
GMarkerEventClickListener listener = (GMarkerEventClickListener)
it.next();
if (listener.getMarker().equals(marker) {
listener.onClick(marker);
found = true;
}
}
}

This has the added advantage that when it finds the target marker it
bails out of the loop.

Apologies if this is total bollocks and I haven't understood how to
create the handlers properly.

Al.
www.gtraffic.info

www.gtraffic.info

unread,
Sep 6, 2006, 3:18:49 PM9/6/06
to Google Web Toolkit
Obviously it wasn't a bug but a feature. For the sake of anyone else I
solved my problem by maintaining a HashMap of urls in the one listener
keyed on the marker reference. When a user clicks the region icon the
associated url is fetched from the HashMap and a request is made to
load the url data. Here is code:

class RegionMarkerEventListener implements GMarkerEventClickListener
{
private HashMap markers = null;
private MapApplication handler = null;

public RegionMarkerEventListener(MapApplication handler)
{
this.handler = handler;
markers = new HashMap();
}

public void onClick(GMarker marker)
{
// Find
String url = (String)markers.get(marker);
HTTPRequest.asyncGet("site/"+url, handler);
}

public void onDblClick(GMarker marker)
{
// TODO Auto-generated method stub
}

public void add(String url, GMarker marker)
{
if (!markers.containsKey(marker))
{
markers.put(marker, url);
}
}
}

aglaforge

unread,
Sep 6, 2006, 5:54:08 PM9/6/06
to Google Web Toolkit
You're actually correct, that wasn't the original design of event
dispatching system, mostly in a effort to keep the backend as simple as
possible. That said, I think it would make sense to add a little
complexity to migrate the backend portion a bit to align it better with
the original google maps API... Let me think on it for a little bit..
right now the best idea I have is to hash the values and have the hash
reference a vector of handlers which is do-able.... I saw your
implementation above and it would be equally effective. I'm open to
suggestions.

aglaforge

unread,
Sep 7, 2006, 12:54:08 AM9/7/06
to Google Web Toolkit
Keep your eyes open in the next few days for a new release with the
updated event system. What I ended up doing was removing a layer of
management code and directly calling the listener interfaces from the
native methods....

The net... behaviour that is more consistent with what google had
originally designed and principally more intuitive... more over a
simpler event manager class.

aglaforge

unread,
Sep 7, 2006, 1:30:57 AM9/7/06
to Google Web Toolkit
Based on the feedback in the thread above I went in and simplified the
GMarkerEventManager to directly pass the listener object (as opposed to
registering the listener class and managing itself). Code for the
manager is much simpler now and behaves as one would expect in terms of
only executing for the appropriate object.

Now that the proof of concept has been done for the markers I'll extend
the changes to the map and a new release with the updates will be
available very soon.

Cheers,

Anthony

P.S. An other issues?

Reply all
Reply to author
Forward
0 new messages