782af3f9472ef3efadbaec87aa329f5f6529d261
[navit-package] / navit / gui / gtk / gui_gtk_window.c
1 /**
2  * Navit, a modular navigation system.
3  * Copyright (C) 2005-2008 Navit Team
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * version 2 as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA  02110-1301, USA.
18  */
19
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <gdk/gdkkeysyms.h>
24 #if !defined(GDK_Book) || !defined(GDK_Calendar)
25 #include <X11/XF86keysym.h>
26 #endif
27 #include <gtk/gtk.h>
28 #include "config.h"
29 #include "item.h"
30 #include "navit.h"
31 #include "debug.h"
32 #include "gui.h"
33 #include "coord.h"
34 #include "point.h"
35 #include "plugin.h"
36 #include "graphics.h"
37 #include "gui_gtk.h"
38 #include "transform.h"
39 #include "config.h"
40 #include "callback.h"
41 #include "layout.h"
42 #include "vehicle.h"
43 #include "map.h"
44 #include "coord.h"
45 #include "navit_nls.h"
46
47 #ifdef USE_HILDON
48 #include "hildon/hildon-defines.h
49 #define KEY_ZOOM_IN HILDON_HARDKEY_INCREASE
50 #define KEY_ZOOM_OUT HILDON_HARDKEY_DECREASE
51 #define KEY_UP HILDON_HARDKEY_UP
52 #define KEY_DOWN HILDON_HARDKEY_DOWN
53 #define KEY_LEFT HILDON_HARDKEY_LEFT
54 #define KEY_RIGHT HILDON_HARDKEY_RIGHT
55 #else
56 #ifndef GDK_Book
57 #define GDK_Book XF86XK_Book
58 #endif
59 #ifndef GDK_Calendar
60 #define GDK_Calendar XF86XK_Calendar
61 #endif
62 #define KEY_ZOOM_IN GDK_Book
63 #define KEY_ZOOM_OUT GDK_Calendar 
64 #define KEY_UP GDK_Up
65 #define KEY_DOWN GDK_Down
66 #define KEY_LEFT GDK_Left
67 #define KEY_RIGHT GDK_Right
68 #endif
69
70 static gboolean
71 keypress(GtkWidget *widget, GdkEventKey *event, struct gui_priv *this)
72 {
73         int w,h;
74         #ifdef USE_HILDON
75         GtkToggleAction *action;
76         gboolean *fullscreen;
77         #endif /*HILDON*/
78         struct point p;
79         if (event->type != GDK_KEY_PRESS)
80                 return FALSE;
81         dbg(1,"keypress 0x%x\n", event->keyval);
82         transform_get_size(navit_get_trans(this->nav), &w, &h);
83         switch (event->keyval) {
84         case GDK_KP_Enter:
85                 gtk_menu_shell_select_first(GTK_MENU_SHELL(this->menubar), TRUE);
86                 break;
87         case KEY_UP:
88                 p.x=w/2;
89                 p.y=0;
90                 navit_set_center_screen(this->nav, &p);
91                 break;
92         case KEY_DOWN:
93                 p.x=w/2;
94                 p.y=h;
95                 navit_set_center_screen(this->nav, &p);
96                 break;
97         case KEY_LEFT:
98                 p.x=0;
99                 p.y=h/2;
100                 navit_set_center_screen(this->nav, &p);
101                 break;
102         case KEY_RIGHT:
103                 p.x=w;
104                 p.y=h/2;
105                 navit_set_center_screen(this->nav, &p);
106                 break;
107         case KEY_ZOOM_IN:
108                 navit_zoom_in(this->nav, 2, NULL);
109                 break;
110         case KEY_ZOOM_OUT:
111                 navit_zoom_out(this->nav, 2, NULL);
112                 break;
113         #ifdef USE_HILDON
114         case HILDON_HARDKEY_FULLSCREEN:
115                 action = GTK_TOGGLE_ACTION (gtk_action_group_get_action (this->base_group, "FullscreenAction"));
116                         
117                 if ( gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)))
118                 {
119                         fullscreen = 0;
120                 } else  {
121                         fullscreen = 1;
122                 }
123                 gtk_toggle_action_set_active (action, fullscreen);
124                 break;
125         #endif /*HILDON*/
126         default:
127                 return FALSE;
128         }
129         return TRUE;
130 }
131
132 static int
133 gui_gtk_set_graphics(struct gui_priv *this, struct graphics *gra)
134 {
135         GtkWidget *graphics;
136
137         graphics=graphics_get_data(gra, "gtk_widget");
138         if (! graphics)
139                 return 1;
140         GTK_WIDGET_SET_FLAGS (graphics, GTK_CAN_FOCUS);
141         gtk_widget_set_sensitive(graphics, TRUE);
142         g_signal_connect(G_OBJECT(graphics), "key-press-event", G_CALLBACK(keypress), this);
143         gtk_box_pack_end(GTK_BOX(this->vbox), graphics, TRUE, TRUE, 0);
144         gtk_widget_show_all(graphics);
145         gtk_widget_grab_focus(graphics);
146
147         return 0;
148 }
149
150 static void
151 gui_gtk_add_bookmark_do(struct gui_priv *gui)
152 {
153         navit_add_bookmark(gui->nav, &gui->dialog_coord, gtk_entry_get_text(GTK_ENTRY(gui->dialog_entry)));
154         gtk_widget_destroy(gui->dialog_win);
155 }
156
157 static int
158 gui_gtk_add_bookmark(struct gui_priv *gui, struct pcoord *c, char *description)
159 {
160         GtkWidget *button_ok,*button_cancel,*label,*vbox,*hbox;
161
162         gui->dialog_coord=*c;   
163         gui->dialog_win=gtk_window_new(GTK_WINDOW_TOPLEVEL);
164         vbox=gtk_vbox_new(FALSE, 0);
165         gtk_container_add (GTK_CONTAINER (gui->dialog_win), vbox);
166         gtk_window_set_title(GTK_WINDOW(gui->dialog_win),_("Add Bookmark"));
167         gtk_window_set_wmclass (GTK_WINDOW (gui->dialog_win), "navit", "Navit");
168         gtk_window_set_transient_for(GTK_WINDOW(gui->dialog_win), GTK_WINDOW(gui->win));
169         gtk_window_set_modal(GTK_WINDOW(gui->dialog_win), TRUE);
170         label=gtk_label_new(_("Name"));
171         gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
172         gui->dialog_entry=gtk_entry_new();
173         gtk_entry_set_text(GTK_ENTRY(gui->dialog_entry), description);
174         gtk_box_pack_start(GTK_BOX(vbox), gui->dialog_entry, TRUE, TRUE, 0);
175         hbox=gtk_hbox_new(FALSE, 0);
176         button_ok = gtk_button_new_from_stock (GTK_STOCK_OK);
177         gtk_box_pack_start(GTK_BOX(hbox), button_ok, TRUE, TRUE, 10);
178         button_cancel = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
179         gtk_box_pack_start(GTK_BOX(hbox), button_cancel, TRUE, TRUE, 10);
180         gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 10);
181         gtk_widget_show_all(gui->dialog_win);
182         GTK_WIDGET_SET_FLAGS (button_ok, GTK_CAN_DEFAULT);
183         gtk_widget_grab_default(button_ok);
184         g_signal_connect_swapped (G_OBJECT (button_cancel), "clicked", G_CALLBACK (gtk_widget_destroy), G_OBJECT (gui->dialog_win));
185         g_signal_connect_swapped (G_OBJECT (gui->dialog_entry), "activate", G_CALLBACK (gui_gtk_add_bookmark_do), gui);
186
187         g_signal_connect_swapped(G_OBJECT (button_ok), "clicked", G_CALLBACK (gui_gtk_add_bookmark_do), gui);
188
189         return 1;
190 }
191
192 struct gui_methods gui_gtk_methods = {
193         NULL,
194         gui_gtk_popup_new,
195         gui_gtk_set_graphics,
196         NULL,
197         gui_gtk_datawindow_new,
198         gui_gtk_add_bookmark,
199 };
200
201 static gboolean
202 gui_gtk_delete(GtkWidget *widget, GdkEvent *event, struct navit *nav)
203 {
204         /* FIXME remove attr_navit callback */
205         navit_destroy(nav);
206
207         return TRUE;
208 }
209
210 static void
211 gui_gtk_toggle_init(struct gui_priv *this)
212 {
213         struct attr attr;
214         GtkToggleAction *toggle_action;
215
216         if (navit_get_attr(this->nav, attr_cursor, &attr, NULL)) {
217                 toggle_action = GTK_TOGGLE_ACTION(gtk_action_group_get_action(this->base_group, "CursorAction"));
218                 gtk_toggle_action_set_active(toggle_action, attr.u.num);
219         } else {
220                 dbg(0, "Unable to locate CursorAction\n");
221         }
222         if (navit_get_attr(this->nav, attr_orientation, &attr, NULL)) {
223                 toggle_action = GTK_TOGGLE_ACTION(gtk_action_group_get_action(this->base_group, "OrientationAction"));
224                 gtk_toggle_action_set_active(toggle_action, attr.u.num != -1);
225         } else {
226                 dbg(0, "Unable to locate OrientationAction\n");
227         }
228         if (navit_get_attr(this->nav, attr_tracking, &attr, NULL)) {
229                 toggle_action = GTK_TOGGLE_ACTION(gtk_action_group_get_action(this->base_group, "TrackingAction"));
230                 gtk_toggle_action_set_active(toggle_action, attr.u.num);
231         } else {
232                 dbg(0, "Unable to locate TrackingAction\n");
233         }
234 }
235
236 struct action_cb_data {
237         struct gui_priv *gui;
238         struct attr attr;
239 };
240
241 static void
242 gui_gtk_action_activate(GtkAction *action, struct action_cb_data *data)
243 {
244         if(data->attr.type == attr_destination) {
245                 char * label;
246                 g_object_get(G_OBJECT(action), "label", &label,NULL);
247                 navit_set_destination(data->gui->nav, data->attr.u.pcoord, label);
248                 g_free(label);
249         }
250 }
251
252 struct gui_menu_info {
253         guint merge_id;
254         GtkAction *action;
255 };
256
257 static void
258 gui_gtk_del_menu(struct gui_priv *this, struct gui_menu_info *meninfo)
259 {
260         gtk_action_group_remove_action(this->dyn_group, meninfo->action);
261         gtk_ui_manager_remove_ui(this->ui_manager, meninfo->merge_id);
262 }
263
264 static struct gui_menu_info
265 gui_gtk_add_menu(struct gui_priv *this, char *name, char *label, char *path, int submenu, struct action_cb_data *data)
266 {
267         struct gui_menu_info meninfo;
268         GtkAction *action;
269         guint merge_id;
270
271         action=gtk_action_new(name, label, NULL, NULL);
272         meninfo.action = action;
273         if (data)
274                 g_signal_connect(action, "activate", G_CALLBACK(gui_gtk_action_activate), data);
275         gtk_action_group_add_action(this->dyn_group, action);
276         merge_id =gtk_ui_manager_new_merge_id(this->ui_manager);
277         meninfo.merge_id = merge_id;
278         gtk_ui_manager_add_ui(this->ui_manager, merge_id, path, name, name, submenu ? GTK_UI_MANAGER_MENU : GTK_UI_MANAGER_MENUITEM, FALSE);
279
280         return meninfo;
281 }
282
283 static void
284 gui_gtk_action_toggled(GtkToggleAction *action, struct action_cb_data *data)
285 {
286         struct attr active;
287         active.type=attr_active;
288         active.u.num=gtk_toggle_action_get_active(action);
289         map_set_attr(data->attr.u.map, &active);
290         navit_draw(data->gui->nav);
291 }
292
293 static void
294 gui_gtk_add_toggle_menu(struct gui_priv *this, char *name, char *label, char *path, struct action_cb_data *data, gboolean active)
295 {
296         GtkToggleAction *toggle_action;
297         guint merge_id;
298
299         toggle_action=gtk_toggle_action_new(name, label, NULL, NULL);
300         gtk_toggle_action_set_active(toggle_action, active);
301         g_signal_connect(GTK_ACTION(toggle_action), "toggled", G_CALLBACK(gui_gtk_action_toggled), data);
302         gtk_action_group_add_action(this->dyn_group, GTK_ACTION(toggle_action));
303         merge_id=gtk_ui_manager_new_merge_id(this->ui_manager);
304         gtk_ui_manager_add_ui(this->ui_manager, merge_id, path, name, name, GTK_UI_MANAGER_MENUITEM, FALSE);
305 }
306
307 static void
308 gui_gtk_action_changed(GtkRadioAction *action, GtkRadioAction *current, struct action_cb_data *data)
309 {
310         if (action == current) {
311                 navit_set_attr(data->gui->nav, &data->attr);
312         }
313 }
314
315 static void
316 gui_gtk_add_radio_menu(struct gui_priv *this, char *name, char *label, char *path, struct action_cb_data *data, GSList **g)
317 {
318         GtkRadioAction *radio_action;
319         guint merge_id;
320
321         radio_action=gtk_radio_action_new(name, label, NULL, NULL, 0);
322         gtk_radio_action_set_group(radio_action, *g);
323         *g=gtk_radio_action_get_group(radio_action);
324         g_signal_connect(GTK_ACTION(radio_action), "changed", G_CALLBACK(gui_gtk_action_changed), data);
325         gtk_action_group_add_action(this->dyn_group, GTK_ACTION(radio_action));
326         merge_id=gtk_ui_manager_new_merge_id(this->ui_manager);
327         gtk_ui_manager_add_ui(this->ui_manager, merge_id, path, name, name, GTK_UI_MANAGER_MENUITEM, FALSE);
328 }
329
330 static void
331 gui_gtk_layouts_init(struct gui_priv *this)
332 {
333         struct attr_iter *iter;
334         struct attr attr;
335         struct action_cb_data *data;
336         int count=0;
337         char *name;
338
339         iter=navit_attr_iter_new();
340         while(navit_get_attr(this->nav, attr_layout, &attr, iter)) {
341                 name=g_strdup_printf("Layout %d", count++);
342                 data=g_new(struct action_cb_data, 1);
343                 data->gui=this;
344                 data->attr.type=attr_layout;
345                 data->attr.u.layout=attr.u.layout;
346                 gui_gtk_add_radio_menu(this, name, attr.u.layout->name, "/ui/MenuBar/Map/Layout/LayoutMenuAdditions", data, &this->layout_group);
347                 g_free(name);
348         }
349         navit_attr_iter_destroy(iter);
350 }
351
352 static void
353 gui_gtk_projections_init(struct gui_priv *this)
354 {
355         struct action_cb_data *data;
356
357         data=g_new(struct action_cb_data, 1);
358         data->gui=this;
359         data->attr.type=attr_projection;
360         data->attr.u.projection=projection_mg;
361         gui_gtk_add_radio_menu(this, "Projection mg", "Map & Guide", "/ui/MenuBar/Map/Projection/ProjectionMenuAdditions", data, &this->projection_group);
362
363         data=g_new(struct action_cb_data, 1);
364         data->gui=this;
365         data->attr.type=attr_projection;
366         data->attr.u.projection=projection_garmin;
367         gui_gtk_add_radio_menu(this, "Projection garmin", "Garmin", "/ui/MenuBar/Map/Projection/ProjectionMenuAdditions", data, &this->projection_group);
368 }
369
370 static void
371 gui_gtk_vehicles_init(struct gui_priv *this)
372 {
373         struct attr_iter *iter;
374         struct attr attr,vattr;
375         struct action_cb_data *data;
376         int count=0;
377         char *name;
378
379         iter=navit_attr_iter_new();
380         while(navit_get_attr(this->nav, attr_vehicle, &attr, iter)) {
381                 vehicle_get_attr(attr.u.vehicle, attr_name, &vattr, NULL);
382                 name=g_strdup_printf("Vehicle %d", count++);
383                 data=g_new(struct action_cb_data, 1);
384                 data->gui=this;
385                 data->attr.type=attr_vehicle;
386                 data->attr.u.vehicle=attr.u.vehicle;
387                 gui_gtk_add_radio_menu(this, name, vattr.u.str, "/ui/MenuBar/Map/Vehicle/VehicleMenuAdditions", data, &this->vehicle_group);
388                 g_free(name);
389         }
390         navit_attr_iter_destroy(iter);
391 }
392
393 static void
394 gui_gtk_maps_init(struct gui_priv *this)
395 {
396         struct attr_iter *iter;
397         struct attr attr,active,type,data;
398         struct action_cb_data *cb_data;
399         int count=0;
400         char *name, *label;
401
402         iter=navit_attr_iter_new();
403         while(navit_get_attr(this->nav, attr_map, &attr, iter)) {
404                 name=g_strdup_printf("Map %d", count++);
405                 if (! map_get_attr(attr.u.map, attr_type, &type, NULL))
406                         type.u.str="";
407                 if (! map_get_attr(attr.u.map, attr_data, &data, NULL))
408                         data.u.str="";
409                 label=g_strdup_printf("%s:%s", type.u.str, data.u.str);
410                 cb_data=g_new(struct action_cb_data, 1);
411                 cb_data->gui=this;
412                 cb_data->attr.type=attr_map;
413                 cb_data->attr.u.map=attr.u.map;
414                 if (! map_get_attr(attr.u.map, attr_active, &active, NULL))
415                         active.u.num=1;
416                 gui_gtk_add_toggle_menu(this, name, label, "/ui/MenuBar/Map/MapMenuAdditions", cb_data, active.u.num);
417                 g_free(name);
418                 g_free(label);
419         }
420         navit_attr_iter_destroy(iter);
421
422 }
423
424 static void
425 gui_gtk_destinations_update(struct gui_priv *this)
426 {
427         GList *curr;
428         struct attr attr;
429         struct action_cb_data *data;
430         struct map_rect *mr=NULL;
431         struct item *item;
432         struct gui_menu_info *meninfo;
433         struct coord c;
434         int count=0;
435         char *name, *label;
436
437         curr = g_list_first(this->dest_menuitems);
438
439         while (curr) {
440                 gui_gtk_del_menu(this, (struct gui_menu_info *)curr->data);
441                 g_free((struct gui_menu_info *)curr->data);
442                 curr = g_list_next(curr);
443         };
444
445         g_list_free(this->dest_menuitems);
446         this->dest_menuitems = NULL;
447
448         if(navit_get_attr(this->nav, attr_former_destination_map, &attr, NULL) && attr.u.map && (mr=map_rect_new(attr.u.map, NULL))) {
449                 while ((item=map_rect_get_item(mr))) {
450                         if (item->type != type_former_destination) continue;
451                         name=g_strdup_printf("Destination %d", count++);
452                         item_attr_get(item, attr_label, &attr);
453                         label=attr.u.str;
454                         item_coord_get(item, &c, 1);
455                         data=g_new(struct action_cb_data, 1);
456                         data->gui=this;
457                         data->attr.type=attr_destination;
458                         data->attr.u.pcoord=g_new(struct pcoord, 1);
459                         data->attr.u.pcoord->pro=projection_mg;
460                         data->attr.u.pcoord->x=c.x;
461                         data->attr.u.pcoord->y=c.y;
462                         
463                         meninfo = g_new(struct gui_menu_info, 1);
464                         *meninfo = gui_gtk_add_menu(this, name, label, "/ui/MenuBar/Route/FormerDestinations/FormerDestinationMenuAdditions",0,data); 
465                         this->dest_menuitems = g_list_prepend(this->dest_menuitems, meninfo);
466                         g_free(name);
467                 }
468                 map_rect_destroy(mr);
469         }
470 }
471
472 static void
473 gui_gtk_destinations_init(struct gui_priv *this)
474 {
475         navit_add_callback(this->nav, callback_new_attr_1(callback_cast(gui_gtk_destinations_update), attr_destination, this));
476         gui_gtk_destinations_update(this);
477 }
478
479 static void
480 gui_gtk_bookmarks_update(struct gui_priv *this)
481 {
482         GList *curr;
483         struct attr attr;
484         struct action_cb_data *data;
485         struct map_rect *mr=NULL;
486         struct gui_menu_info *meninfo;
487         struct item *item;
488         struct coord c;
489         int count=0;
490         char *parent, *name, *label, *label_full, *menu_label, *tmp_parent, *s;
491         GHashTable *hash;
492
493         curr = g_list_first(this->bookmarks_menuitems);
494
495         while (curr) {
496                 gui_gtk_del_menu(this, (struct gui_menu_info *)curr->data);
497                 g_free((struct gui_menu_info *)curr->data);
498                 curr = g_list_next(curr);
499         };
500
501         g_list_free(this->bookmarks_menuitems);
502         this->bookmarks_menuitems = NULL;
503
504         if(navit_get_attr(this->nav, attr_bookmark_map, &attr, NULL) && attr.u.map && (mr=map_rect_new(attr.u.map, NULL))) {
505                 hash=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
506                 while ((item=map_rect_get_item(mr))) {
507                         if (item->type != type_bookmark) continue;
508                         item_attr_get(item, attr_label, &attr);
509                         label_full=attr.u.str;
510                         item_coord_get(item, &c, 1);
511                         menu_label=g_malloc(strlen(label_full)+1);
512                         label=label_full;
513                         parent=g_strdup("/ui/MenuBar/Route/Bookmarks/BookmarkMenuAdditions");
514                         while ((s=strchr(label, '/'))) {
515                                 strcpy(menu_label, label_full);
516                                 menu_label[s-label_full]='\0';
517                                 if ((tmp_parent=g_hash_table_lookup(hash, menu_label))) {
518                                         tmp_parent=g_strdup(tmp_parent);
519                                 } else {
520                                         name=g_strdup_printf("Bookmark %d", count++);
521                                         meninfo = g_new(struct gui_menu_info, 1);
522                                         *meninfo = gui_gtk_add_menu(this, name, menu_label+(label-label_full),parent,1,NULL);
523                                         this->bookmarks_menuitems = g_list_prepend(this->bookmarks_menuitems, meninfo);
524                                         tmp_parent=g_strdup_printf("%s/%s", parent, name);
525                                         g_hash_table_insert(hash, g_strdup(menu_label), g_strdup(tmp_parent));
526                                         g_free(name);
527                                 }
528                                 g_free(parent);
529                                 parent=tmp_parent;
530                                 label=s+1;
531                         }
532                         g_free(menu_label);
533                         data=g_new(struct action_cb_data, 1);
534                         data->gui=this;
535                         data->attr.type=attr_destination;
536                         data->attr.u.pcoord=g_new(struct pcoord, 1);
537                         data->attr.u.pcoord->pro=projection_mg;
538                         data->attr.u.pcoord->x=c.x;
539                         data->attr.u.pcoord->y=c.y;
540                         name=g_strdup_printf("Bookmark %d", count++);
541                         meninfo = g_new(struct gui_menu_info, 1);
542                         *meninfo = gui_gtk_add_menu(this, name, label, parent,0,data);
543                         this->bookmarks_menuitems = g_list_prepend(this->bookmarks_menuitems, meninfo);
544                         g_free(name);
545                         g_free(parent);
546                 }
547                 g_hash_table_destroy(hash);
548         }
549 }
550
551 static void
552 gui_gtk_bookmarks_init(struct gui_priv *this)
553 {
554         navit_add_callback(this->nav, callback_new_attr_1(callback_cast(gui_gtk_bookmarks_update), attr_bookmark_map, this));
555         gui_gtk_bookmarks_update(this);
556 }
557
558 static void
559 gui_gtk_init(struct gui_priv *this, struct navit *nav)
560 {
561
562
563         gui_gtk_toggle_init(this);
564         gui_gtk_layouts_init(this);
565         gui_gtk_projections_init(this);
566         gui_gtk_vehicles_init(this);
567         gui_gtk_maps_init(this);
568         gui_gtk_destinations_init(this);
569         gui_gtk_bookmarks_init(this);
570 }
571
572 static struct gui_priv *
573 gui_gtk_new(struct navit *nav, struct gui_methods *meth, struct attr **attrs) 
574 {
575         struct gui_priv *this;
576         int w=792, h=547;
577         char *cp = getenv("NAVIT_XID");
578         unsigned xid = 0;
579         struct attr *attr;
580         GtkWidget *widget;
581
582         if (cp) {
583                 xid = strtol(cp, NULL, 0);
584         }
585
586         this=g_new0(struct gui_priv, 1);
587         this->nav=nav;
588
589         attr = attr_search(attrs, NULL, attr_menubar);
590         if (attr) {
591                 this->menubar_enable=attr->u.num;
592         } else {
593                 this->menubar_enable=1;
594         }
595         attr=attr_search(attrs, NULL, attr_toolbar);
596         if (attr) {
597                 this->toolbar_enable=attr->u.num;
598         } else {
599                 this->toolbar_enable=1;
600         }
601         attr=attr_search(attrs, NULL, attr_statusbar);
602         if (attr) {
603                 this->statusbar_enable=attr->u.num;
604         } else {
605                 this->statusbar_enable=1;
606         }
607
608         *meth=gui_gtk_methods;
609
610         if (!xid) 
611                 this->win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
612         else
613                 this->win = gtk_plug_new(xid);
614
615         g_signal_connect(G_OBJECT(this->win), "delete-event", G_CALLBACK(gui_gtk_delete), nav);
616         this->vbox = gtk_vbox_new(FALSE, 0);
617         gtk_window_set_default_size(GTK_WINDOW(this->win), w, h);
618         gtk_window_set_title(GTK_WINDOW(this->win), "Navit");
619         gtk_window_set_wmclass (GTK_WINDOW (this->win), "navit", "Navit");
620         gtk_widget_realize(this->win);
621         gui_gtk_ui_init(this);
622         if (this->menubar_enable) {
623                 widget=gtk_ui_manager_get_widget(this->ui_manager, "/ui/MenuBar");
624                 GTK_WIDGET_UNSET_FLAGS (widget, GTK_CAN_FOCUS);
625                 gtk_box_pack_start (GTK_BOX(this->vbox), widget, FALSE, FALSE, 0);
626                 gtk_widget_show (widget);
627                 this->menubar=widget;
628         }
629         if (this->toolbar_enable) {
630                 widget=gtk_ui_manager_get_widget(this->ui_manager, "/ui/ToolBar");
631                 GTK_WIDGET_UNSET_FLAGS (widget, GTK_CAN_FOCUS);
632                 gtk_box_pack_start (GTK_BOX(this->vbox), widget, FALSE, FALSE, 0);
633                 gtk_widget_show (widget);
634         }
635         if (this->statusbar_enable) {
636                 this->statusbar=gui_gtk_statusbar_new(this);
637         }
638         gtk_container_add(GTK_CONTAINER(this->win), this->vbox);
639         gtk_widget_show_all(this->win);
640
641
642         navit_add_callback(nav, callback_new_attr_1(callback_cast(gui_gtk_init), attr_navit, this));
643         return this;
644 }
645
646 static int gtk_argc;
647 static char **gtk_argv={NULL};
648
649 void
650 plugin_init(void)
651 {
652         gtk_init(&gtk_argc, &gtk_argv);
653         gtk_set_locale();
654
655
656         plugin_register_gui_type("gtk", gui_gtk_new);
657 }