Diff of /trunk/src/map-tool.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 40 by harbaum, Sun Aug 2 19:05:24 2009 UTC revision 41 by harbaum, Mon Aug 3 14:21:57 2009 UTC
# Line 155  static void map_draw_cachelist(GtkWidget Line 155  static void map_draw_cachelist(GtkWidget
155    }    }
156  }  }
157    
158    /* draw a nice popup */
159    typedef struct {
160      appdata_t *appdata;
161      GtkWidget *window;
162      GMainLoop *loop;
163    } popup_context_t;
164    
165    
166    #ifndef USE_HILDON
167    #define POPUP_WIDTH  300
168    #define POPUP_HEIGHT 100
169    #else
170    #define POPUP_WIDTH  600
171    #define POPUP_HEIGHT 200
172    #endif
173    
174    static gboolean
175    pointer_in_window(GtkWidget *widget, gint x_root, gint y_root) {
176      if(GTK_WIDGET_MAPPED(gtk_widget_get_toplevel(widget))) {
177        gint window_x, window_y;
178    
179        gdk_window_get_position(gtk_widget_get_toplevel(widget)->window,
180                                &window_x, &window_y);
181    
182        if(x_root >= window_x && x_root < window_x + widget->allocation.width &&
183            y_root >= window_y && y_root < window_y + widget->allocation.height)
184          return TRUE;
185      }
186    
187      return FALSE;
188    }
189    
190    static gboolean
191    on_button_press_event(GtkWidget *widget,
192                              GdkEventButton *event, popup_context_t *context) {
193      gboolean in = pointer_in_window(widget, event->x_root, event->y_root);
194    
195      printf("overlay button press(in = %d)\n", in);
196      return !in;
197    }
198    
199    static gboolean
200    on_button_release_event(GtkWidget *widget,
201                              GdkEventButton *event, popup_context_t *context) {
202      gboolean in = pointer_in_window(widget, event->x_root, event->y_root);
203    
204      printf("overlay button release(in = %d)\n", in);
205    
206      if(!in) {
207        printf("destroying popup\n");
208        gtk_widget_destroy(gtk_widget_get_toplevel(widget));
209      }
210    
211      return !in;
212    }
213    
214    static void
215    shutdown_loop(popup_context_t *context) {
216      if(g_main_loop_is_running(context->loop))
217        g_main_loop_quit(context->loop);
218    }
219    
220    static gint
221    run_delete_handler(GtkWindow *window, GdkEventAny *event,
222                       popup_context_t *context) {
223      shutdown_loop(context);
224      return TRUE; /* Do not destroy */
225    }
226    
227    static void
228    run_destroy_handler(GtkWindow *window, popup_context_t *context) {
229      /* shutdown_loop will be called by run_unmap_handler */
230      printf("popup destroyed\n");
231    }
232    
233    static void
234    run_unmap_handler(GtkWindow *window, popup_context_t *context) {
235      shutdown_loop(context);
236    }
237    
238    void cache_popup(appdata_t *appdata, cache_t *cache) {
239      popup_context_t context;
240      context.appdata = appdata;
241    
242      context.window = gtk_window_new(GTK_WINDOW_POPUP);
243      gtk_widget_realize(context.window);
244      gtk_window_set_default_size(GTK_WINDOW(context.window),
245                                  POPUP_WIDTH, POPUP_HEIGHT);
246      gtk_window_resize(GTK_WINDOW(context.window),
247                        POPUP_WIDTH, POPUP_HEIGHT);
248      //  gtk_window_set_resizable(GTK_WINDOW(context.window), FALSE);
249      gtk_window_set_transient_for(GTK_WINDOW(context.window),
250                                   GTK_WINDOW(appdata->window));
251      gtk_window_set_keep_above(GTK_WINDOW(context.window), TRUE);
252      gtk_window_set_destroy_with_parent(GTK_WINDOW(context.window), TRUE);
253      gtk_window_set_gravity(GTK_WINDOW(context.window), GDK_GRAVITY_STATIC);
254      gtk_window_set_modal(GTK_WINDOW(context.window), TRUE);
255    
256      /* connect events */
257      g_signal_connect(G_OBJECT(context.window), "button-press-event",
258                       G_CALLBACK(on_button_press_event), &context);
259      g_signal_connect(G_OBJECT(context.window), "button-release-event",
260                       G_CALLBACK(on_button_release_event), &context);
261      g_signal_connect(G_OBJECT(context.window), "delete-event",
262                       G_CALLBACK(run_delete_handler), &context);
263      g_signal_connect(G_OBJECT(context.window), "destroy",
264                       G_CALLBACK(run_destroy_handler), &context);
265      g_signal_connect(G_OBJECT(context.window), "unmap",
266                       G_CALLBACK(run_unmap_handler), &context);
267    
268      gdk_pointer_grab(context.window->window, TRUE,
269         GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_MOTION_MASK,
270                       NULL, NULL, GDK_CURRENT_TIME);
271      gtk_grab_add(context.window);
272    
273      //  gint x, y;
274      //  gdk_window_get_origin(button->window, &x, &y);
275    
276      //  gtk_window_move(GTK_WINDOW(context.window),
277      //              x + button->allocation.x,
278      //              y + button->allocation.y - HEIGHT);
279    
280    
281      gtk_window_move(GTK_WINDOW(context.window),
282                      100,
283                      100);
284    
285      /* a frame with a vscale inside */
286      GtkWidget *frame = gtk_frame_new(NULL);
287      gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
288    
289      gtk_container_add(GTK_CONTAINER(frame), gtk_label_new(cache->name));
290      gtk_container_add(GTK_CONTAINER(context.window), frame);
291    
292      gtk_widget_show_all(context.window);
293    
294      /* handle this popup until it's gone */
295    
296      context.loop = g_main_loop_new(NULL, FALSE);
297    
298      GDK_THREADS_LEAVE();
299      g_main_loop_run(context.loop);
300      GDK_THREADS_ENTER();
301    
302      g_main_loop_unref(context.loop);
303    
304      printf("cache popup removed\n");
305    }
306    
307    #define RAD2DEG(a)  (((a)*180.0)/M_PI)
308    
309    static void
310    map_cachelist_nearest(cache_t *cache, pos_t *pos,
311                          cache_t **result, float *distance) {
312      while(cache) {
313        float dist =
314          pow(cache->pos.lat - pos->lat, 2) +
315          pow(cache->pos.lon - pos->lon, 2);
316    
317        if(!(dist > *distance)) {
318          *result = cache;
319          *distance = dist;
320        }
321    
322        cache = cache->next;
323      }
324    }
325    
326    static cache_t *map_closest(map_context_t *context, pos_t *pos) {
327      cache_t *result = NULL;
328      float distance = NAN;
329    
330    #ifdef USE_MAEMO
331      if(!context->appdata->cur_gpx) {
332    #endif
333        /* search all geocaches */
334        gpx_t *gpx = context->appdata->gpx;
335        while(gpx) {
336          map_cachelist_nearest(gpx->cache, pos, &result, &distance);
337          gpx = gpx->next;
338        }
339    #ifdef USE_MAEMO
340      } else {
341        map_cachelist_nearest(context->appdata->cur_gpx->cache,
342                              pos, &result, &distance);
343      }
344    #endif
345    
346      return result;
347    }
348    
349    /* translate between osm-gps-map positions and gpxview ones */
350    pos_t coord2pos(coord_t coo) {
351      pos_t pos;
352      pos.lat = RAD2DEG(coo.rlat);
353      pos.lon = RAD2DEG(coo.rlon);
354      return pos;
355    }
356    
357    static gboolean
358    on_map_button_press_event(GtkWidget *widget,
359                                GdkEventButton *event, map_context_t *context) {
360      OsmGpsMap *map = OSM_GPS_MAP(context->widget);
361    
362      pos_t pos =
363        coord2pos(osm_gps_map_get_co_ordinates(map, (int)event->x, (int)event->y));
364    
365      printf("clicked at %f/%f\n", pos.lat, pos.lon);
366    
367      return FALSE;
368    }
369    
370    static gboolean
371    on_map_button_release_event(GtkWidget *widget,
372                                GdkEventButton *event, map_context_t *context) {
373      OsmGpsMap *map = OSM_GPS_MAP(context->widget);
374    
375      pos_t pos =
376        coord2pos(osm_gps_map_get_co_ordinates(map, (int)event->x, (int)event->y));
377    
378      printf("released at %f/%f\n", pos.lat, pos.lon);
379    
380      /* return true if we clicked a cache */
381      /* ... */
382    
383      cache_t *nearest = map_closest(context, &pos);
384    
385      if(nearest) {
386        float dist = gpx_pos_get_distance(pos, nearest->pos, FALSE);
387    
388        printf("nearest = %s, distance = %fkm\n", nearest->name, dist);
389    
390        cache_popup(context->appdata, nearest);
391    
392        return TRUE;
393      }
394    
395      return FALSE;
396    }
397    
398  #if MAEMO_VERSION_MAJOR == 5  #if MAEMO_VERSION_MAJOR == 5
399  static void on_window_destroy(GtkWidget *widget, map_context_t *context) {  static void on_window_destroy(GtkWidget *widget, map_context_t *context) {
400    printf("destroy map view\n");    printf("destroy map view\n");
# Line 171  void map(appdata_t *appdata) { Line 411  void map(appdata_t *appdata) {
411    map_context_t *context = g_new0(map_context_t, 1);    map_context_t *context = g_new0(map_context_t, 1);
412    context->appdata = appdata;    context->appdata = appdata;
413    
414      GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
415    
416      char *path = g_strdup_printf("%s/map/", appdata->image_path);
417      const char *proxy = get_proxy_uri(appdata);
418    
419      context->widget = g_object_new(OSM_TYPE_GPS_MAP,
420                    "repo-uri", MAP_SOURCE_OPENSTREETMAP,
421                    "tile-cache", path,
422                    proxy?"proxy-uri":NULL, proxy,
423                     NULL);
424    
425      g_free(path);
426    
427      char *name = NULL;
428    #ifdef USE_MAEMO
429      if(!appdata->cur_gpx) {
430    #endif
431        /* draw all geocaches */
432        gpx_t *gpx = appdata->gpx;
433        while(gpx) {
434          map_draw_cachelist(context->widget, gpx->cache);
435          gpx = gpx->next;
436        }
437        name = g_strdup(_("all geocaches"));
438    #ifdef USE_MAEMO
439      } else {
440        map_draw_cachelist(context->widget, appdata->cur_gpx->cache);
441        name = g_strdup(_("appdata->cur_gpx->name"));
442      }
443    #endif
444    
445      char *title = g_strdup_printf(_("Map - %s"), name);
446      g_free(name);
447    
448  #if MAEMO_VERSION_MAJOR == 5  #if MAEMO_VERSION_MAJOR == 5
449    GtkWidget *window = hildon_stackable_window_new();    GtkWidget *window = hildon_stackable_window_new();
450    gtk_window_set_title(GTK_WINDOW(window), _("Map"));    gtk_window_set_title(GTK_WINDOW(window), title);
451  #else  #else
452    GtkWidget *dialog = gtk_dialog_new_with_buttons(_("Map"),    GtkWidget *dialog = gtk_dialog_new_with_buttons(title,
453                            GTK_WINDOW(appdata->window),                            GTK_WINDOW(appdata->window),
454                            GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,                            GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
455                            GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,                            GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
# Line 188  void map(appdata_t *appdata) { Line 462  void map(appdata_t *appdata) {
462  #endif  #endif
463  #endif  #endif
464    
465    GtkWidget *hbox = gtk_hbox_new(FALSE, 0);    g_free(title);
   
   char *path = g_strdup_printf("%s/map/", appdata->image_path);  
   const char *proxy = get_proxy_uri(appdata);  
   
   context->widget = g_object_new(OSM_TYPE_GPS_MAP,  
                 "repo-uri", MAP_SOURCE_OPENSTREETMAP,  
                 "tile-cache", path,  
                 proxy?"proxy-uri":NULL, proxy,  
                  NULL);  
   
   g_free(path);  
   
   /* draw all geocaches */  
   gpx_t *gpx = appdata->gpx;  
   while(gpx) {  
     map_draw_cachelist(context->widget, gpx->cache);  
     gpx = gpx->next;  
   }  
466    
467    g_signal_connect(G_OBJECT(context->widget), "configure-event",    g_signal_connect(G_OBJECT(context->widget), "configure-event",
468                     G_CALLBACK(on_map_configure), context);                     G_CALLBACK(on_map_configure), context);
469  #if 0  
470      g_signal_connect(G_OBJECT(context->widget), "button-press-event",
471                       G_CALLBACK(on_map_button_press_event), context);
472    
473    g_signal_connect(G_OBJECT(context->widget), "button-release-event",    g_signal_connect(G_OBJECT(context->widget), "button-release-event",
474                     G_CALLBACK(on_map_button_release_event), context);                     G_CALLBACK(on_map_button_release_event), context);
 #endif  
475    
476    gtk_box_pack_start_defaults(GTK_BOX(hbox), context->widget);    gtk_box_pack_start_defaults(GTK_BOX(hbox), context->widget);
477    /* zoom button box */    /* zoom button box */

Legend:
Removed from v.40  
changed lines
  Added in v.41