summaryrefslogtreecommitdiff
path: root/gui/gtk
diff options
context:
space:
mode:
Diffstat (limited to 'gui/gtk')
-rw-r--r--gui/gtk/Makefile.am6
-rw-r--r--gui/gtk/datawindow.c214
-rw-r--r--gui/gtk/destination.c539
-rw-r--r--gui/gtk/gui_gtk.h62
-rw-r--r--gui/gtk/gui_gtk_action.c627
-rw-r--r--gui/gtk/gui_gtk_statusbar.c178
-rw-r--r--gui/gtk/gui_gtk_window.c771
7 files changed, 2397 insertions, 0 deletions
diff --git a/gui/gtk/Makefile.am b/gui/gtk/Makefile.am
new file mode 100644
index 00000000..1588bfe8
--- /dev/null
+++ b/gui/gtk/Makefile.am
@@ -0,0 +1,6 @@
+include $(top_srcdir)/Makefile.inc
+AM_CPPFLAGS = -I$(top_srcdir)/navit @NAVIT_CFLAGS@ @HILDON_CFLAGS@ @GTK2_CFLAGS@ -DMODULE=gui_gtk
+modulegui_LTLIBRARIES = libgui_gtk.la
+libgui_gtk_la_SOURCES = datawindow.c destination.c gui_gtk_statusbar.c gui_gtk_action.c gui_gtk_window.c gui_gtk.h
+libgui_gtk_la_LIBADD = @GTK2_LIBS@
+libgui_gtk_la_LDFLAGS = -module -avoid-version
diff --git a/gui/gtk/datawindow.c b/gui/gtk/datawindow.c
new file mode 100644
index 00000000..75f43a80
--- /dev/null
+++ b/gui/gtk/datawindow.c
@@ -0,0 +1,214 @@
+/**
+ * Navit, a modular navigation system.
+ * Copyright (C) 2005-2008 Navit Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+#include "debug.h"
+#include "callback.h"
+#include "param.h"
+#include "data_window.h"
+#include "gui_gtk.h"
+
+struct datawindow_priv {
+ GtkWidget *window;
+ GtkWidget *scrolled_window;
+ GtkWidget *treeview;
+ GtkWidget *button;
+ GtkListStore *liststore;
+ GtkTreeModel *sortmodel;
+ struct callback *click, *close;
+ struct gui_priv *gui;
+};
+
+static GValue value;
+static void
+select_row(GtkTreeView *tree, GtkTreePath *path, GtkTreeViewColumn *column, struct datawindow_priv *win)
+{
+ char *cols[20];
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ int i;
+
+ dbg(0,"win=%p\n", win);
+
+ model=gtk_tree_view_get_model(tree);
+ gtk_tree_model_get_iter(model, &iter, path);
+
+ for (i=0;i<gtk_tree_model_get_n_columns(model);i++) {
+ gtk_tree_model_get_value(model, &iter, i, &value);
+ cols[i]=g_strdup_value_contents(&value)+1;
+ cols[i][strlen(cols[i])-1]='\0';
+ g_value_unset(&value);
+ }
+ callback_call_1(win->click, cols);
+}
+
+static void
+gui_gtk_datawindow_add(struct datawindow_priv *win, struct param_list *param, int count)
+{
+ int i;
+ GtkCellRenderer *cell;
+ GtkTreeIter iter;
+ GType types[count];
+
+ if (! win->treeview) {
+ win->treeview=gtk_tree_view_new();
+ gtk_tree_view_set_model (GTK_TREE_VIEW (win->treeview), NULL);
+ gtk_container_add(GTK_CONTAINER(win->scrolled_window), win->treeview);
+ gtk_widget_show_all(GTK_WIDGET(win->window));
+ gtk_widget_grab_focus(GTK_WIDGET(win->treeview));
+
+ /* add column names to treeview */
+ for(i=0;i<count;i++) {
+ if (param[i].name) {
+ cell=gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (win->treeview),-1,param[i].name,
+ cell,"text",i, NULL);
+ }
+ }
+#if 0
+ g_signal_connect(G_OBJECT(win->treeview), "click-column", G_CALLBACK(click_column), NULL);
+#endif
+ g_signal_connect(G_OBJECT(win->treeview), "row-activated", G_CALLBACK(select_row), win);
+ }
+
+ /* find data storage and create a new one if none is there */
+ if (gtk_tree_view_get_model(GTK_TREE_VIEW (win->treeview)) == NULL) {
+ for(i=0;i<count;i++) {
+ if (param[i].name && !strcmp(param[i].name, "Distance"))
+ types[i]=G_TYPE_INT;
+ else
+ types[i]=G_TYPE_STRING;
+ }
+ win->liststore=gtk_list_store_newv(count,types);
+ if (! strcmp(param[0].name, "Distance")) {
+ win->sortmodel=gtk_tree_model_sort_new_with_model(GTK_TREE_MODEL(win->liststore));
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (win->sortmodel), 0, GTK_SORT_ASCENDING);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (win->treeview), GTK_TREE_MODEL(win->sortmodel));
+ } else
+ gtk_tree_view_set_model (GTK_TREE_VIEW (win->treeview), GTK_TREE_MODEL(win->liststore));
+ }
+
+ gtk_list_store_append(win->liststore,&iter);
+
+ /* add data to data storage */
+ for(i=0;i<count;i++) {
+ if (param[i].name && !strcmp(param[i].name, "Distance")) {
+ gtk_list_store_set(win->liststore,&iter,i,atoi(param[i].value),-1);
+ } else {
+ gtk_list_store_set(win->liststore,&iter,i,param[i].value,-1);
+ }
+ }
+}
+
+static void
+gui_gtk_datawindow_mode(struct datawindow_priv *win, int start)
+{
+ if (start) {
+ if (win && win->treeview) {
+ gtk_tree_view_set_model (GTK_TREE_VIEW (win->treeview), NULL);
+ }
+ }
+}
+
+static gboolean
+gui_gtk_datawindow_delete(GtkWidget *widget, GdkEvent *event, struct datawindow_priv *win)
+{
+ callback_call_0(win->close);
+
+ if (win->button) {
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION(win->button), FALSE);
+ }
+
+ return FALSE;
+}
+
+void
+gui_gtk_datawindow_destroy(struct datawindow_priv *win)
+{
+ if ((!win->gui) || (!win->gui->datawindow)) {
+ return;
+ }
+
+ gui_gtk_datawindow_delete(NULL, NULL, win);
+ gtk_widget_destroy(win->window);
+ win->gui->datawindow = NULL;
+
+ return;
+}
+
+void
+gui_gtk_datawindow_set_button(struct datawindow_priv *this_, GtkWidget *btn)
+{
+ this_->button = btn;
+}
+
+static gboolean
+keypress(GtkWidget *widget, GdkEventKey *event, struct datawindow_priv *win)
+{
+ if (event->type != GDK_KEY_PRESS)
+ return FALSE;
+ if (event->keyval == GDK_Cancel) {
+ gui_gtk_datawindow_delete(widget, (GdkEvent *)event, win);
+ gtk_widget_destroy(win->window);
+ }
+ return FALSE;
+}
+
+
+static struct datawindow_methods gui_gtk_datawindow_meth = {
+ gui_gtk_datawindow_destroy,
+ gui_gtk_datawindow_add,
+ gui_gtk_datawindow_mode,
+};
+
+struct datawindow_priv *
+gui_gtk_datawindow_new(struct gui_priv *gui, char *name, struct callback *click, struct callback *close, struct datawindow_methods *meth)
+{
+ struct datawindow_priv *win;
+
+ if (!gui)
+ return NULL;
+ *meth=gui_gtk_datawindow_meth;
+ win=g_new0(struct datawindow_priv, 1);
+ win->window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_default_size(GTK_WINDOW(win->window), 320, 200);
+ gtk_window_set_title(GTK_WINDOW(win->window), name);
+ gtk_window_set_wmclass (GTK_WINDOW (win->window), "navit", "Navit");
+
+ win->scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (win->scrolled_window),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_container_add(GTK_CONTAINER(win->window), win->scrolled_window);
+ g_signal_connect(G_OBJECT(win->window), "key-press-event", G_CALLBACK(keypress), win);
+ win->treeview=NULL;
+ win->click=click;
+ win->close=close;
+ gtk_window_set_transient_for(GTK_WINDOW((GtkWidget *)(win->window)), GTK_WINDOW(gui->win));
+ g_signal_connect(G_OBJECT(win->window), "delete-event", G_CALLBACK(gui_gtk_datawindow_delete), win);
+ gtk_widget_show_all(win->window);
+
+ win->gui = gui;
+ gui->datawindow = win;
+ return win;
+}
+
diff --git a/gui/gtk/destination.c b/gui/gtk/destination.c
new file mode 100644
index 00000000..a9c5b2cd
--- /dev/null
+++ b/gui/gtk/destination.c
@@ -0,0 +1,539 @@
+/**
+ * Navit, a modular navigation system.
+ * Copyright (C) 2005-2008 Navit Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <gtk/gtk.h>
+#include "debug.h"
+#include "destination.h"
+#include "navit.h"
+#include "item.h"
+#include "coord.h"
+#include "track.h"
+#include "country.h"
+#include "search.h"
+#include "projection.h"
+#include "navit_nls.h"
+
+#define COL_COUNT 8
+
+static struct search_param {
+ struct navit *nav;
+ struct mapset *ms;
+ struct search_list *sl;
+ struct attr attr;
+ int partial;
+ GtkWidget *entry_country, *entry_postal, *entry_city, *entry_district;
+ GtkWidget *entry_street, *entry_number;
+ GtkWidget *listbox;
+ GtkWidget *treeview;
+ GtkListStore *liststore;
+ GtkTreeModel *liststore2;
+} search_param;
+
+static void button_map(GtkWidget *widget, struct search_param *search)
+{
+ GtkTreePath *path;
+ GtkTreeViewColumn *focus_column;
+ struct pcoord *c=NULL;
+ GtkTreeIter iter;
+
+ gtk_tree_view_get_cursor(GTK_TREE_VIEW(search->treeview), &path, &focus_column);
+ if(!path)
+ return;
+ if(!gtk_tree_model_get_iter(search->liststore2, &iter, path))
+ return;
+ gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), &iter, COL_COUNT, &c, -1);
+ if (c) {
+ navit_set_center(search->nav, c, 1);
+ }
+}
+
+static char *description(struct search_param *search, GtkTreeIter *iter)
+{
+ char *desc,*car,*postal,*town,*street;
+ char empty='\0';
+
+ gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), iter, 0, &car, -1);
+ gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), iter, 1, &postal, -1);
+ gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), iter, 2, &town, -1);
+ gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), iter, 4, &street, -1);
+
+ /* protect against nulls */
+ if (car==0) car=&empty;
+ if (postal==0) postal=&empty;
+ if (town==0) town=&empty;
+ if (street==0) street=&empty;
+
+ if (search->attr.type == attr_town_name)
+ desc=g_strdup_printf("%s-%s %s", car, postal, town);
+ else
+ desc=g_strdup_printf("%s-%s %s, %s", car, postal, town, street);
+ return desc;
+}
+
+static void button_destination(GtkWidget *widget, struct search_param *search)
+{
+ struct pcoord *c=NULL;
+ GtkTreeIter iter;
+ char *desc;
+
+ if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (search->liststore2), &iter))
+ return;
+ gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), &iter, COL_COUNT, &c, -1);
+ if (c) {
+ desc=description(search, &iter);
+ navit_set_destination(search->nav, c, desc, 1);
+ g_free(desc);
+ }
+}
+
+static void button_bookmark(GtkWidget *widget, struct search_param *search)
+{
+ struct pcoord *c=NULL;
+ GtkTreeIter iter;
+ char *desc;
+
+ if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (search->liststore2), &iter))
+ return;
+ gtk_tree_model_get (GTK_TREE_MODEL (search->liststore2), &iter, COL_COUNT, &c, -1);
+ if (c) {
+ desc=description(search, &iter);
+ navit_add_bookmark(search->nav, c, desc);
+ g_free(desc);
+ }
+}
+
+
+char **columns_text[] = {
+ (char *[]){_n("Car"),_n("Iso2"),_n("Iso3"),_n("Country"),NULL},
+ (char *[]){_n("Car"),_n("Postal"),_n("Town"),_n("District"),NULL},
+ (char *[]){_n("Car"),_n("Postal"),_n("Town"),_n("District"),_n("Street"),NULL},
+ (char *[]){_n("Car"),_n("Postal"),_n("Town"),_n("District"),_n("Street"),_n("Number"),NULL},
+};
+
+static void set_columns(struct search_param *param, int mode)
+{
+ GList *columns_list,*columns;
+ char **column_text=columns_text[mode];
+ int i=0;
+
+ columns_list=gtk_tree_view_get_columns(GTK_TREE_VIEW(param->treeview));
+ columns=columns_list;
+ while (columns) {
+ gtk_tree_view_remove_column(GTK_TREE_VIEW(param->treeview), columns->data);
+ columns=g_list_next(columns);
+ }
+ g_list_free(columns_list);
+ while (*column_text) {
+ GtkCellRenderer *cell=gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (param->treeview),-1, gettext(*column_text), cell, "text", i, NULL);
+ i++;
+ column_text++;
+ }
+
+}
+
+static void row_activated(GtkWidget *widget, GtkTreePath *p1, GtkTreeViewColumn *c, struct search_param *search)
+{
+ GtkTreePath *path;
+ GtkTreeViewColumn *focus_column;
+ GtkTreeIter iter;
+ GtkWidget *entry_widget;
+ char *str;
+ int column;
+
+ dbg(0,"enter\n");
+ gtk_tree_view_get_cursor(GTK_TREE_VIEW(search->treeview), &path, &focus_column);
+ if(!path)
+ return;
+ if(!gtk_tree_model_get_iter(search->liststore2, &iter, path))
+ return;
+ switch(search->attr.type) {
+ case attr_country_all:
+ entry_widget=search->entry_country;
+ column=3;
+ break;
+ case attr_town_name:
+ entry_widget=search->entry_city;
+ column=2;
+ break;
+ case attr_street_name:
+ entry_widget=search->entry_street;
+ column=4;
+ break;
+ default:
+ dbg(0,"Unknown mode\n");
+ return;
+ }
+ gtk_tree_model_get(search->liststore2, &iter, column, &str, -1);
+ dbg(0,"str=%s\n", str);
+ search->partial=0;
+ gtk_entry_set_text(GTK_ENTRY(entry_widget), str);
+}
+
+static void tree_view_button_release(GtkWidget *widget, GdkEventButton *event, struct search_param *search)
+{
+ GtkTreePath *path;
+ GtkTreeViewColumn *column;
+ gtk_tree_view_get_cursor(GTK_TREE_VIEW(search->treeview), &path, &column);
+ gtk_tree_view_row_activated(GTK_TREE_VIEW(search->treeview), path, column);
+
+}
+static void
+next_focus(struct search_param *search, GtkWidget *widget)
+{
+ if (widget == search->entry_country)
+ gtk_widget_grab_focus(search->entry_city);
+ if (widget == search->entry_city)
+ gtk_widget_grab_focus(search->entry_street);
+ if (widget == search->entry_street)
+ gtk_widget_grab_focus(search->entry_number);
+
+}
+
+static void changed(GtkWidget *widget, struct search_param *search)
+{
+ struct search_list_result *res;
+ GtkTreeIter iter;
+
+ search->attr.u.str=(char *)gtk_entry_get_text(GTK_ENTRY(widget));
+ printf("changed %s partial %d\n", search->attr.u.str, search->partial);
+ if (widget == search->entry_country) {
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (search->liststore2), 3, GTK_SORT_ASCENDING);
+ dbg(0,"country\n");
+ search->attr.type=attr_country_all;
+ set_columns(search, 0);
+ }
+ if (widget == search->entry_postal) {
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (search->liststore2), 1, GTK_SORT_ASCENDING);
+ dbg(0,"postal\n");
+ search->attr.type=attr_town_postal;
+ if (strlen(search->attr.u.str) < 2)
+ return;
+ set_columns(search, 1);
+ }
+ if (widget == search->entry_city) {
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (search->liststore2), 2, GTK_SORT_ASCENDING);
+ dbg(0,"town\n");
+ search->attr.type=attr_town_name;
+ if (strlen(search->attr.u.str) < 3)
+ return;
+ set_columns(search, 1);
+ }
+ if (widget == search->entry_street) {
+ dbg(0,"street\n");
+ search->attr.type=attr_street_name;
+ set_columns(search, 2);
+ }
+
+
+ search_list_search(search->sl, &search->attr, search->partial);
+ gtk_list_store_clear(search->liststore);
+ while((res=search_list_get_result(search->sl))) {
+ gtk_list_store_append(search->liststore,&iter);
+ gtk_list_store_set(search->liststore,&iter,COL_COUNT,res->c,-1);
+ if (widget == search->entry_country) {
+ if (res->country) {
+ gtk_list_store_set(search->liststore,&iter,0,res->country->car,-1);
+ gtk_list_store_set(search->liststore,&iter,1,res->country->iso3,-1);
+ gtk_list_store_set(search->liststore,&iter,2,res->country->iso2,-1);
+ gtk_list_store_set(search->liststore,&iter,3,res->country->name,-1);
+ }
+ } else {
+ if (res->country)
+ gtk_list_store_set(search->liststore,&iter,0,res->country->car,-1);
+ else
+ gtk_list_store_set(search->liststore,&iter,0,"",-1);
+ if (res->town) {
+ gtk_list_store_set(search->liststore,&iter,1,res->town->common.postal,-1);
+ gtk_list_store_set(search->liststore,&iter,2,res->town->name,-1);
+ gtk_list_store_set(search->liststore,&iter,3,res->town->district,-1);
+ } else {
+ gtk_list_store_set(search->liststore,&iter,1,"",-1);
+ gtk_list_store_set(search->liststore,&iter,2,"",-1);
+ gtk_list_store_set(search->liststore,&iter,3,"",-1);
+ }
+ if (res->street)
+ gtk_list_store_set(search->liststore,&iter,4,res->street->name,-1);
+ else
+ gtk_list_store_set(search->liststore,&iter,4,"",-1);
+
+ }
+ }
+ if (! search->partial)
+ next_focus(search, widget);
+ search->partial=1;
+}
+
+/* borrowed from gpe-login */
+
+
+#define MAX_ARGS 8
+
+static void
+parse_xkbd_args (const char *cmd, char **argv)
+{
+ const char *p = cmd;
+ char buf[strlen (cmd) + 1], *bufp = buf;
+ int nargs = 0;
+ int escape = 0, squote = 0, dquote = 0;
+
+ while (*p)
+ {
+ if (escape)
+ {
+ *bufp++ = *p;
+ escape = 0;
+ }
+ else
+ {
+ switch (*p)
+ {
+ case '\\':
+ escape = 1;
+ break;
+ case '"':
+ if (squote)
+ *bufp++ = *p;
+ else
+ dquote = !dquote;
+ break;
+ case '\'':
+ if (dquote)
+ *bufp++ = *p;
+ else
+ squote = !squote;
+ break;
+ case ' ':
+ if (!squote && !dquote)
+ {
+ *bufp = 0;
+ if (nargs < MAX_ARGS)
+ argv[nargs++] = strdup (buf);
+ bufp = buf;
+ break;
+ }
+ default:
+ *bufp++ = *p;
+ break;
+ }
+ }
+ p++;
+ }
+
+ if (bufp != buf)
+ {
+ *bufp = 0;
+ if (nargs < MAX_ARGS)
+ argv[nargs++] = strdup (buf);
+ }
+ argv[nargs] = NULL;
+}
+
+int kbd_pid;
+
+static int
+spawn_xkbd (char *xkbd_path, char *xkbd_str)
+{
+#ifdef _WIN32 // AF FIXME for WIN32
+ #ifndef F_SETFD
+ #define F_SETFD 2
+ #endif
+#else
+ char *xkbd_args[MAX_ARGS + 1];
+ int fd[2];
+ char buf[256];
+ char c;
+ int a = 0;
+ size_t n;
+
+ pipe (fd);
+ kbd_pid = fork ();
+ if (kbd_pid == 0)
+ {
+ close (fd[0]);
+ if (dup2 (fd[1], 1) < 0)
+ perror ("dup2");
+ close (fd[1]);
+ if (fcntl (1, F_SETFD, 0))
+ perror ("fcntl");
+ xkbd_args[0] = (char *)xkbd_path;
+ xkbd_args[1] = "-xid";
+ if (xkbd_str)
+ parse_xkbd_args (xkbd_str, xkbd_args + 2);
+ else
+ xkbd_args[2] = NULL;
+ execvp (xkbd_path, xkbd_args);
+ perror (xkbd_path);
+ _exit (1);
+ }
+ close (fd[1]);
+ do {
+ n = read (fd[0], &c, 1);
+ if (n)
+ {
+ buf[a++] = c;
+ }
+ } while (n && (c != 10) && (a < (sizeof (buf) - 1)));
+
+ if (a)
+ {
+ buf[a] = 0;
+ return atoi (buf);
+ }
+#endif
+ return 0;
+}
+
+int destination_address(struct navit *nav)
+{
+
+ GtkWidget *window2, *keyboard, *vbox, *table;
+ GtkWidget *label_country;
+ GtkWidget *label_postal, *label_city, *label_district;
+ GtkWidget *label_street, *label_number;
+ GtkWidget *hseparator1,*hseparator2;
+ GtkWidget *button1,*button2,*button3;
+ int i;
+ struct search_param *search=&search_param;
+ struct attr search_attr, country_name, *country_attr;
+ struct tracking *tracking;
+ struct country_search *cs;
+ struct item *item;
+
+
+ search->nav=nav;
+ search->ms=navit_get_mapset(nav);
+ search->sl=search_list_new(search->ms);
+
+ window2 = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title(GTK_WINDOW(window2),_("Enter Destination"));
+ gtk_window_set_wmclass (GTK_WINDOW (window2), "navit", "Navit");
+ vbox = gtk_vbox_new(FALSE, 0);
+ table = gtk_table_new(3, 8, FALSE);
+
+ search->entry_country = gtk_entry_new();
+ label_country = gtk_label_new(_("Country"));
+ search->entry_postal = gtk_entry_new();
+ gtk_widget_set_sensitive(GTK_WIDGET(search->entry_postal), FALSE);
+ label_postal = gtk_label_new(_("Zip Code"));
+ search->entry_city = gtk_entry_new();
+ label_city = gtk_label_new(_("City"));
+ search->entry_district = gtk_entry_new();
+ gtk_widget_set_sensitive(GTK_WIDGET(search->entry_district), FALSE);
+ label_district = gtk_label_new(_("District/Township"));
+ hseparator1 = gtk_vseparator_new();
+ search->entry_street = gtk_entry_new();
+ label_street = gtk_label_new(_("Street"));
+ search->entry_number = gtk_entry_new();
+ label_number = gtk_label_new(_("Number"));
+ search->treeview=gtk_tree_view_new();
+ search->listbox = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (search->listbox),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
+ gtk_tree_view_set_model (GTK_TREE_VIEW (search->treeview), NULL);
+ gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(search->listbox),search->treeview);
+ {
+ GType types[COL_COUNT+1];
+ for(i=0;i<COL_COUNT;i++)
+ types[i]=G_TYPE_STRING;
+ types[i]=G_TYPE_POINTER;
+ search->liststore=gtk_list_store_newv(COL_COUNT+1,types);
+ search->liststore2=gtk_tree_model_sort_new_with_model(GTK_TREE_MODEL(search->liststore));
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (search->liststore2), 3, GTK_SORT_ASCENDING);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (search->treeview), GTK_TREE_MODEL(search->liststore2));
+ }
+
+
+
+
+ hseparator2 = gtk_vseparator_new();
+ button1 = gtk_button_new_with_label(_("Map"));
+ button2 = gtk_button_new_with_label(_("Bookmark"));
+ button3 = gtk_button_new_with_label(_("Destination"));
+
+ gtk_table_attach(GTK_TABLE(table), label_country, 0, 1, 0, 1, 0, GTK_FILL, 0, 0);
+ gtk_table_attach(GTK_TABLE(table), label_postal, 1, 2, 0, 1, 0, GTK_FILL, 0, 0);
+ gtk_table_attach(GTK_TABLE(table), label_city, 2, 3, 0, 1, 0, GTK_FILL, 0, 0);
+
+ gtk_table_attach(GTK_TABLE(table), search->entry_country, 0, 1, 1, 2, 0, GTK_FILL, 0, 0);
+ gtk_table_attach(GTK_TABLE(table), search->entry_postal, 1, 2, 1, 2, 0, GTK_FILL, 0, 0);
+ gtk_table_attach(GTK_TABLE(table), search->entry_city, 2, 3, 1, 2, 0, GTK_FILL, 0, 0);
+
+ gtk_table_attach(GTK_TABLE(table), label_district, 0, 1, 2, 3, 0, GTK_FILL, 0, 0);
+ gtk_table_attach(GTK_TABLE(table), label_street, 1, 2, 2, 3, 0, GTK_FILL, 0, 0);
+ gtk_table_attach(GTK_TABLE(table), label_number, 2, 3, 2, 3, 0, GTK_FILL, 0, 0);
+
+ gtk_table_attach(GTK_TABLE(table), search->entry_district, 0, 1, 3, 4, 0, GTK_FILL, 0, 0);
+ gtk_table_attach(GTK_TABLE(table), search->entry_street, 1, 2, 3, 4, 0, GTK_FILL, 0, 0);
+ gtk_table_attach(GTK_TABLE(table), search->entry_number, 2, 3, 3, 4, 0, GTK_FILL, 0, 0);
+
+ gtk_table_attach(GTK_TABLE(table), search->listbox, 0, 3, 4, 5, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0);
+
+ gtk_table_attach(GTK_TABLE(table), button1, 0, 1, 5, 6, GTK_FILL, GTK_FILL, 0, 0);
+ gtk_table_attach(GTK_TABLE(table), button2, 1, 2, 5, 6, GTK_FILL, GTK_FILL, 0, 0);
+ gtk_table_attach(GTK_TABLE(table), button3, 2, 3, 5, 6, GTK_FILL, GTK_FILL, 0, 0);
+
+ g_signal_connect(G_OBJECT(search->entry_country), "changed", G_CALLBACK(changed), search);
+ g_signal_connect(G_OBJECT(search->entry_postal), "changed", G_CALLBACK(changed), search);
+ g_signal_connect(G_OBJECT(search->entry_city), "changed", G_CALLBACK(changed), search);
+ g_signal_connect(G_OBJECT(search->entry_district), "changed", G_CALLBACK(changed), search);
+ g_signal_connect(G_OBJECT(search->entry_street), "changed", G_CALLBACK(changed), search);
+ g_signal_connect(G_OBJECT(search->entry_number), "changed", G_CALLBACK(changed), search);
+ g_signal_connect(G_OBJECT(button1), "clicked", G_CALLBACK(button_map), search);
+ g_signal_connect(G_OBJECT(button2), "clicked", G_CALLBACK(button_bookmark), search);
+ g_signal_connect(G_OBJECT(button3), "clicked", G_CALLBACK(button_destination), search);
+ g_signal_connect(G_OBJECT(search->treeview), "button-release-event", G_CALLBACK(tree_view_button_release), search);
+ g_signal_connect(G_OBJECT(search->treeview), "row_activated", G_CALLBACK(row_activated), search);
+
+ gtk_widget_grab_focus(search->entry_city);
+
+ gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 0);
+ keyboard=gtk_socket_new();
+ gtk_box_pack_end(GTK_BOX(vbox), keyboard, FALSE, FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(window2), vbox);
+#if 0
+ g_signal_connect(G_OBJECT(listbox), "select-row", G_CALLBACK(select_row), NULL);
+#endif
+ gtk_widget_show_all(window2);
+
+#ifndef _WIN32
+ gtk_socket_steal(GTK_SOCKET(keyboard), spawn_xkbd("xkbd","-geometry 200x100"));
+#endif
+
+ country_attr=country_default();
+ tracking=navit_get_tracking(nav);
+ if (tracking && tracking_get_attr(tracking, attr_country_id, &search_attr, NULL))
+ country_attr=&search_attr;
+ if (country_attr) {
+ cs=country_search_new(country_attr, 0);
+ item=country_search_get_item(cs);
+ if (item && item_attr_get(item, attr_country_name, &country_name))
+ gtk_entry_set_text(GTK_ENTRY(search->entry_country), country_name.u.str);
+ country_search_destroy(cs);
+ } else {
+ dbg(0,"warning: no default country found\n");
+ }
+ search->partial=1;
+ return 0;
+}
diff --git a/gui/gtk/gui_gtk.h b/gui/gtk/gui_gtk.h
new file mode 100644
index 00000000..6168b9ae
--- /dev/null
+++ b/gui/gtk/gui_gtk.h
@@ -0,0 +1,62 @@
+/**
+ * Navit, a modular navigation system.
+ * Copyright (C) 2005-2008 Navit Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "coord.h"
+
+struct menu_methods;
+struct datawindow_methods;
+struct navit;
+struct callback;
+struct statusbar_priv;
+
+struct gui_priv {
+ struct navit *nav;
+ GtkWidget *win;
+ GtkWidget *dialog_win;
+ GtkWidget *dialog_entry;
+ struct pcoord dialog_coord;
+ GtkWidget *vbox;
+ GtkWidget *menubar;
+ GtkActionGroup *base_group;
+ GtkActionGroup *debug_group;
+ GtkActionGroup *dyn_group;
+ GtkUIManager *ui_manager;
+ GSList *layout_group;
+ GSList *projection_group;
+ GSList *vehicle_group;
+ GList *dest_menuitems;
+ GList *bookmarks_menuitems;
+ GList *vehicle_menuitems;
+ GtkUIManager *menu_manager; // old
+ struct statusbar_priv *statusbar;
+ int menubar_enable;
+ int toolbar_enable;
+ int statusbar_enable;
+ int dyn_counter;
+ struct datawindow_priv *datawindow;
+};
+
+void gui_gtk_ui_init(struct gui_priv *this);
+struct menu_priv *gui_gtk_menubar_new(struct gui_priv *gui, struct menu_methods *meth);
+struct statusbar_priv *gui_gtk_statusbar_new(struct gui_priv *gui);
+struct menu_priv *gui_gtk_popup_new(struct gui_priv *gui, struct menu_methods *meth);
+struct datawindow_priv *gui_gtk_datawindow_new(struct gui_priv *gui, char *name, struct callback *click, struct callback *close, struct datawindow_methods *meth);
+void gui_gtk_datawindow_destroy(struct datawindow_priv *win);
+void gui_gtk_datawindow_set_button(struct datawindow_priv *this_, GtkWidget *btn);
+
diff --git a/gui/gtk/gui_gtk_action.c b/gui/gtk/gui_gtk_action.c
new file mode 100644
index 00000000..144a8270
--- /dev/null
+++ b/gui/gtk/gui_gtk_action.c
@@ -0,0 +1,627 @@
+/**
+ * Navit, a modular navigation system.
+ * Copyright (C) 2005-2008 Navit Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <string.h>
+#include <gtk/gtk.h>
+#include "navit.h"
+#include "gui_gtk.h"
+#include "menu.h"
+#include "coord.h"
+#include "item.h"
+#include "attr.h"
+#include "callback.h"
+#include "debug.h"
+#include "destination.h"
+
+#define gettext_noop(String) String
+#define _(STRING) gettext(STRING)
+#define _n(STRING) gettext_noop(STRING)
+
+struct menu_priv {
+ char *path;
+ GtkAction *action;
+ struct gui_priv *gui;
+ enum menu_type type;
+ struct callback *cb;
+ struct menu_priv *child;
+ struct menu_priv *sibling;
+ gulong handler_id;
+ guint merge_id;
+ GtkWidget *widget;
+};
+
+/* Create callbacks that implement our Actions */
+
+static void
+zoom_in_action(GtkWidget *w, struct gui_priv *gui, void *dummy)
+{
+ navit_zoom_in(gui->nav, 2, NULL);
+}
+
+static void
+zoom_out_action(GtkWidget *w, struct gui_priv *gui, void *dummy)
+{
+ navit_zoom_out(gui->nav, 2, NULL);
+}
+
+static void
+refresh_action(GtkWidget *w, struct gui_priv *gui, void *dummy)
+{
+ navit_draw(gui->nav);
+}
+
+// Forward declarations, these should not be visible outside the GUI, so
+// they are not in the header files, but here
+void gui_gtk_datawindow_set_button(struct datawindow_priv *this_, GtkWidget *btn);
+void gui_gtk_datawindow_destroy(struct datawindow_priv *win);
+
+static void
+roadbook_action(GtkWidget *w, struct gui_priv *gui, void *dummy)
+{
+
+ if (! gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w))) {
+ gui_gtk_datawindow_destroy(gui->datawindow);
+ } else {
+ navit_window_roadbook_new(gui->nav);
+ if (gui->datawindow) {
+ gui_gtk_datawindow_set_button(gui->datawindow, w);
+ }
+ }
+}
+
+static void
+autozoom_action(GtkWidget *w, struct gui_priv *gui, void *dummy)
+{
+ struct attr autozoom_attr;
+
+ autozoom_attr.type = attr_autozoom_active;
+ if (! gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w))) {
+ autozoom_attr.u.num = 0;
+ } else {
+ autozoom_attr.u.num = 1;
+ }
+
+ navit_set_attr(gui->nav, &autozoom_attr);
+}
+
+static void
+cursor_action(GtkWidget *w, struct gui_priv *gui, void *dummy)
+{
+ struct attr attr;
+
+ attr.type=attr_cursor;
+ attr.u.num=gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w));
+ if(!navit_set_attr(gui->nav, &attr)) {
+ dbg(0, "Failed to set attr_cursor\n");
+ }
+}
+
+static void
+tracking_action(GtkWidget *w, struct gui_priv *gui, void *dummy)
+{
+ struct attr attr;
+
+ attr.type=attr_tracking;
+ attr.u.num=gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w));
+ if(!navit_set_attr(gui->nav, &attr)) {
+ dbg(0, "Failed to set attr_tracking\n");
+ }
+}
+
+static void
+orient_north_action(GtkWidget *w, struct gui_priv *gui, void *dummy)
+{
+ struct attr attr;
+
+ attr.type=attr_orientation;
+ attr.u.num=gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w)) ? 0:-1;
+ if(!navit_set_attr(gui->nav, &attr)) {
+ dbg(0, "Failed to set attr_orientation\n");
+ }
+}
+
+static void
+window_fullscreen_action(GtkWidget *w, struct gui_priv *gui, void *dummy)
+{
+ if(gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w)))
+ gtk_window_fullscreen(GTK_WINDOW(gui->win));
+ else
+ gtk_window_unfullscreen(GTK_WINDOW(gui->win));
+}
+
+#include <stdlib.h>
+#include "point.h"
+#include "transform.h"
+
+static void
+info_action(GtkWidget *w, struct gui_priv *gui, void *dummy)
+{
+ char buffer[512];
+ int mw,mh;
+ struct coord lt, rb;
+ struct point p;
+ struct transformation *t;
+
+ t=navit_get_trans(gui->nav);
+ transform_get_size(t, &mw, &mh);
+ p.x=0;
+ p.y=0;
+ transform_reverse(t, &p, &lt);
+ p.x=mw;
+ p.y=mh;
+ transform_reverse(t, &p, &rb);
+
+ sprintf(buffer,"./info.sh %d,%d 0x%x,0x%x 0x%x,0x%x", mw, mh, lt.x, lt.y, rb.x, rb.y);
+ system(buffer);
+
+}
+
+
+static void
+route_clear_action(GtkWidget *w, struct gui_priv *gui, void *dummy)
+{
+ navit_set_destination(gui->nav, NULL, NULL, 0);
+}
+
+static void
+destination_action(GtkWidget *w, struct gui_priv *gui, void *dummy)
+{
+ destination_address(gui->nav);
+}
+
+static void
+quit_action (GtkWidget *w, struct gui_priv *gui, void *dummy)
+{
+ navit_destroy(gui->nav);
+}
+
+static GtkActionEntry entries[] =
+{
+ { "DisplayMenuAction", NULL, _n("Display") },
+ { "RouteMenuAction", NULL, _n("Route") },
+ { "FormerDestinationMenuAction", NULL, _n("Former Destinations") },
+ { "BookmarkMenuAction", NULL, _n("Bookmarks") },
+ { "MapMenuAction", NULL, _n("Map") },
+ { "LayoutMenuAction", NULL, _n("Layout") },
+ { "ProjectionMenuAction", NULL, _n("Projection") },
+ { "VehicleMenuAction", NULL, _n("Vehicle") },
+ { "ZoomOutAction", GTK_STOCK_ZOOM_OUT, _n("ZoomOut"), NULL, NULL, G_CALLBACK(zoom_out_action) },
+ { "ZoomInAction", GTK_STOCK_ZOOM_IN, _n("ZoomIn"), NULL, NULL, G_CALLBACK(zoom_in_action) },
+ { "RefreshAction", GTK_STOCK_REFRESH, _n("Recalculate"), NULL, NULL, G_CALLBACK(refresh_action) },
+#ifdef GTK_STOCK_INFO
+ { "InfoAction", GTK_STOCK_INFO, _n("Info"), NULL, NULL, G_CALLBACK(info_action) },
+#else
+ { "InfoAction", NULL, _n("Info"), NULL, NULL, G_CALLBACK(info_action) },
+#endif /*GTK_STOCK_INFO*/
+ { "DestinationAction", "flag_icon", _n("Destination"), NULL, NULL, G_CALLBACK(destination_action) },
+ { "RouteClearAction", NULL, _n("Stop Navigation"), NULL, NULL, G_CALLBACK(route_clear_action) },
+ { "Test", NULL, _n("Test"), NULL, NULL, G_CALLBACK(destination_action) },
+ { "QuitAction", GTK_STOCK_QUIT, _n("_Quit"), "<control>Q",NULL, G_CALLBACK (quit_action) }
+};
+
+static guint n_entries = G_N_ELEMENTS (entries);
+
+static GtkToggleActionEntry toggleentries[] =
+{
+ { "CursorAction", "cursor_icon",_n("Cursor"), NULL, NULL, G_CALLBACK(cursor_action),TRUE },
+ { "TrackingAction", NULL ,_n("Lock on Road"), NULL, NULL, G_CALLBACK(tracking_action),TRUE },
+ { "OrientationAction", "orientation_icon", _n("Northing"), NULL, NULL, G_CALLBACK(orient_north_action),FALSE },
+ { "RoadbookAction", GTK_STOCK_JUSTIFY_FILL, _n("Roadbook"), NULL, NULL, G_CALLBACK(roadbook_action), FALSE },
+ { "AutozoomAction", GTK_STOCK_ZOOM_FIT, _n("Autozoom"), NULL, NULL, G_CALLBACK(autozoom_action), FALSE },
+#ifdef GTK_STOCK_FULLSCREEN
+ { "FullscreenAction",GTK_STOCK_FULLSCREEN, _n("Fullscreen"), NULL, NULL, G_CALLBACK(window_fullscreen_action), FALSE }
+#else
+ { "FullscreenAction", NULL, _n("Fullscreen"), NULL, NULL, G_CALLBACK(window_fullscreen_action), FALSE }
+#endif /*GTK_STOCK_FULLSCREEN*/
+};
+
+static guint n_toggleentries = G_N_ELEMENTS (toggleentries);
+
+static GtkActionEntry debug_entries[] =
+{
+ { "DataMenuAction", NULL, _n("Data") },
+};
+
+static guint n_debug_entries = G_N_ELEMENTS (debug_entries);
+
+
+static const char * cursor_xpm[] = {
+"22 22 2 1",
+" c None",
+". c #0000FF",
+" ",
+" ",
+" ",
+" .. ",
+" .. .. ",
+" .. .. ",
+" . . ",
+" . . ",
+" . ... . ",
+" . ... . . ",
+" . ... . . ",
+" . .. . . ",
+" . . . ",
+" . . . ",
+" . . . ",
+" . . . ",
+" .. .. ",
+" .. .. ",
+" .. ",
+" ",
+" ",
+" "};
+
+
+static const char * north_xpm[] = {
+"22 22 2 1",
+" c None",
+". c #000000",
+" ",
+" ",
+" . ",
+" ... ",
+" . . . ",
+" . . . ",
+" . ",
+" .... . .... ",
+" .... . .... ",
+" .... . .. ",
+" .. .. .. ",
+" .. .. .. ",
+" .. .. .. ",
+" .. .. .. ",
+" .. . .... ",
+" .... . .... ",
+" .... . .... ",
+" . ",
+" . ",
+" . ",
+" ",
+" "};
+
+
+static const char * flag_xpm[] = {
+"22 22 2 1",
+" c None",
+"+ c #000000",
+"+++++++ ",
+"+ +++++++++ ",
+"+ +++ +++++++++ ",
+"+ +++ +++ +++ ",
+"++++ +++ +++ ",
+"++++ +++ +++ ",
+"++++ +++ +++ + ",
+"+ ++++++ +++ + ",
+"+ +++ ++++++ + ",
+"+ +++ +++ +++ ",
+"++++ +++ +++ ",
+"++++ +++ +++ ",
+"++++++++++ +++ + ",
+"+ +++++++++ + ",
+"+ ++++++ ",
+"+ ",
+"+ ",
+"+ ",
+"+ ",
+"+ ",
+"+ ",
+"+ "};
+
+
+
+static struct {
+ gchar *stockid;
+ const char **icon_xpm;
+} stock_icons[] = {
+ {"cursor_icon", cursor_xpm },
+ {"orientation_icon", north_xpm },
+ {"flag_icon", flag_xpm }
+};
+
+
+static gint n_stock_icons = G_N_ELEMENTS (stock_icons);
+
+
+static void
+register_my_stock_icons (void)
+{
+ GtkIconFactory *icon_factory;
+ GtkIconSet *icon_set;
+ GdkPixbuf *pixbuf;
+ gint i;
+
+ icon_factory = gtk_icon_factory_new ();
+
+ for (i = 0; i < n_stock_icons; i++)
+ {
+ pixbuf = gdk_pixbuf_new_from_xpm_data(stock_icons[i].icon_xpm);
+ icon_set = gtk_icon_set_new_from_pixbuf (pixbuf);
+ g_object_unref(pixbuf);
+ gtk_icon_factory_add (icon_factory, stock_icons[i].stockid, icon_set);
+ gtk_icon_set_unref (icon_set);
+ }
+
+ gtk_icon_factory_add_default(icon_factory);
+
+ g_object_unref(icon_factory);
+}
+
+
+static char layout[] =
+ "<ui>\
+ <menubar name=\"MenuBar\">\
+ <menu name=\"Display\" action=\"DisplayMenuAction\">\
+ <menuitem name=\"Zoom in\" action=\"ZoomInAction\" />\
+ <menuitem name=\"Zoom out\" action=\"ZoomOutAction\" />\
+ <menuitem name=\"Cursor\" action=\"CursorAction\"/>\
+ <menuitem name=\"Tracking\" action=\"TrackingAction\"/>\
+ <menuitem name=\"Orientation\" action=\"OrientationAction\"/>\
+ <menuitem name=\"Roadbook\" action=\"RoadbookAction\"/>\
+ <menuitem name=\"Autozoom\" action=\"AutozoomAction\"/>\
+ <menuitem name=\"Fullscreen\" action=\"FullscreenAction\"/>\
+ <menuitem name=\"Quit\" action=\"QuitAction\" />\
+ <placeholder name=\"RouteMenuAdditions\" />\
+ </menu>\
+ <menu name=\"Data\" action=\"DataMenuAction\">\
+ <placeholder name=\"DataMenuAdditions\" />\
+ </menu>\
+ <menu name=\"Route\" action=\"RouteMenuAction\">\
+ <menuitem name=\"Refresh\" action=\"RefreshAction\" />\
+ <menuitem name=\"Destination\" action=\"DestinationAction\" />\
+ <menuitem name=\"Clear\" action=\"RouteClearAction\" />\
+ <menu name=\"FormerDestinations\" action=\"FormerDestinationMenuAction\">\
+ <placeholder name=\"FormerDestinationMenuAdditions\" />\
+ </menu>\
+ <menu name=\"Bookmarks\" action=\"BookmarkMenuAction\">\
+ <placeholder name=\"BookmarkMenuAdditions\" />\
+ </menu>\
+ <placeholder name=\"RouteMenuAdditions\" />\
+ </menu>\
+ <menu name=\"Map\" action=\"MapMenuAction\">\
+ <menu name=\"Layout\" action=\"LayoutMenuAction\">\
+ <placeholder name=\"LayoutMenuAdditions\" />\
+ </menu>\
+ <menu name=\"Projection\" action=\"ProjectionMenuAction\">\
+ <placeholder name=\"ProjectionMenuAdditions\" />\
+ </menu>\
+ <menu name=\"Vehicle\" action=\"VehicleMenuAction\">\
+ <placeholder name=\"VehicleMenuAdditions\" />\
+ </menu>\
+ <placeholder name=\"MapMenuAdditions\" />\
+ </menu>\
+ </menubar>\
+ <toolbar name=\"ToolBar\" action=\"BaseToolbar\" action=\"BaseToolbarAction\">\
+ <placeholder name=\"ToolItems\">\
+ <separator/>\
+ <toolitem name=\"Zoom in\" action=\"ZoomInAction\"/>\
+ <toolitem name=\"Zoom out\" action=\"ZoomOutAction\"/>\
+ <toolitem name=\"Refresh\" action=\"RefreshAction\"/>\
+ <toolitem name=\"Cursor\" action=\"CursorAction\"/>\
+ <toolitem name=\"Orientation\" action=\"OrientationAction\"/>\
+ <toolitem name=\"Destination\" action=\"DestinationAction\"/>\
+ <!-- <toolitem name=\"Info\" action=\"InfoAction\"/> -->\
+ <toolitem name=\"Roadbook\" action=\"RoadbookAction\"/>\
+ <toolitem name=\"Autozoom\" action=\"AutozoomAction\"/>\
+ <toolitem name=\"Quit\" action=\"QuitAction\"/>\
+ <separator/>\
+ </placeholder>\
+ </toolbar>\
+ <popup name=\"PopUp\">\
+ </popup>\
+ </ui>";
+
+
+static void
+activate(void *dummy, struct menu_priv *menu)
+{
+ if (menu->cb)
+ callback_call_0(menu->cb);
+}
+
+static struct menu_methods menu_methods;
+
+static struct menu_priv *
+add_menu(struct menu_priv *menu, struct menu_methods *meth, char *name, enum menu_type type, struct callback *cb)
+{
+ struct menu_priv *ret;
+ char *dynname;
+
+ ret=g_new0(struct menu_priv, 1);
+ *meth=menu_methods;
+ if (! strcmp(menu->path, "/ui/MenuBar") && !strcmp(name,"Route")) {
+ dynname=g_strdup("Route");
+ } else if (! strcmp(menu->path, "/ui/MenuBar") && !strcmp(name,"Data")) {
+ dynname=g_strdup("Data");
+ } else {
+ dynname=g_strdup_printf("%d", menu->gui->dyn_counter++);
+ if (type == menu_type_toggle)
+ ret->action=GTK_ACTION(gtk_toggle_action_new(dynname, name, NULL, NULL));
+ else
+ ret->action=gtk_action_new(dynname, name, NULL, NULL);
+ if (cb)
+ ret->handler_id=g_signal_connect(ret->action, "activate", G_CALLBACK(activate), ret);
+ gtk_action_group_add_action(menu->gui->dyn_group, ret->action);
+ ret->merge_id=gtk_ui_manager_new_merge_id(menu->gui->ui_manager);
+ gtk_ui_manager_add_ui( menu->gui->ui_manager, ret->merge_id, menu->path, dynname, dynname, type == menu_type_submenu ? GTK_UI_MANAGER_MENU : GTK_UI_MANAGER_MENUITEM, FALSE);
+ }
+ ret->gui=menu->gui;
+ ret->path=g_strdup_printf("%s/%s", menu->path, dynname);
+ ret->type=type;
+ ret->cb=cb;
+ ret->sibling=menu->child;
+ menu->child=ret;
+ g_free(dynname);
+ return ret;
+
+}
+
+static void
+remove_menu(struct menu_priv *item, int recursive)
+{
+
+ if (recursive) {
+ struct menu_priv *next,*child=item->child;
+ while (child) {
+ next=child->sibling;
+ remove_menu(child, recursive);
+ child=next;
+ }
+ }
+ if (item->action) {
+ gtk_ui_manager_remove_ui(item->gui->ui_manager, item->merge_id);
+ gtk_action_group_remove_action(item->gui->dyn_group, item->action);
+#if 0
+ if (item->callback)
+ g_signal_handler_disconnect(item->action, item->handler_id);
+#endif
+ g_object_unref(item->action);
+ }
+ g_free(item->path);
+ g_free(item);
+}
+
+static void
+set_toggle(struct menu_priv *menu, int active)
+{
+ gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(menu->action), active);
+}
+
+static int
+get_toggle(struct menu_priv *menu)
+{
+ return gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(menu->action));
+}
+
+static struct menu_methods menu_methods = {
+#if 1
+ add_menu,
+ set_toggle,
+ get_toggle,
+#else
+ NULL,
+ NULL,
+ NULL
+#endif
+};
+
+
+static void
+popup_deactivate(GtkWidget *widget, struct menu_priv *menu)
+{
+ g_signal_handler_disconnect(widget, menu->handler_id);
+ remove_menu(menu, 1);
+}
+
+static void
+popup_activate(struct menu_priv *menu)
+{
+#ifdef _WIN32
+ menu->widget=gtk_ui_manager_get_widget(menu->gui->ui_manager, menu->path );
+#endif
+ gtk_menu_popup(GTK_MENU(menu->widget), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time ());
+ menu->handler_id=g_signal_connect(menu->widget, "selection-done", G_CALLBACK(popup_deactivate), menu);
+}
+
+void
+gui_gtk_ui_init(struct gui_priv *this)
+{
+ GError *error = NULL;
+ struct attr attr;
+ GtkToggleAction *toggle_action;
+
+ this->base_group = gtk_action_group_new ("BaseActions");
+ this->debug_group = gtk_action_group_new ("DebugActions");
+ this->dyn_group = gtk_action_group_new ("DynamicActions");
+ register_my_stock_icons();
+ this->ui_manager = gtk_ui_manager_new ();
+ gtk_action_group_set_translation_domain(this->base_group,"navit");
+ gtk_action_group_set_translation_domain(this->debug_group,"navit");
+ gtk_action_group_set_translation_domain(this->dyn_group,"navit");
+ gtk_action_group_add_actions (this->base_group, entries, n_entries, this);
+ gtk_action_group_add_toggle_actions (this->base_group, toggleentries, n_toggleentries, this);
+ gtk_ui_manager_insert_action_group (this->ui_manager, this->base_group, 0);
+ gtk_action_group_add_actions (this->debug_group, debug_entries, n_debug_entries, this);
+ gtk_ui_manager_insert_action_group (this->ui_manager, this->debug_group, 0);
+ gtk_ui_manager_add_ui_from_string (this->ui_manager, layout, strlen(layout), &error);
+ gtk_ui_manager_insert_action_group (this->ui_manager, this->dyn_group, 0);
+ if (error) {
+ g_message ("building menus failed: %s", error->message);
+ g_error_free (error);
+ }
+ if (navit_get_attr(this->nav, attr_cursor, &attr, NULL)) {
+ toggle_action = GTK_TOGGLE_ACTION(gtk_action_group_get_action(this->base_group, "CursorAction"));
+ gtk_toggle_action_set_active(toggle_action, attr.u.num);
+ }
+ if (navit_get_attr(this->nav, attr_orientation, &attr, NULL)) {
+ toggle_action = GTK_TOGGLE_ACTION(gtk_action_group_get_action(this->base_group, "OrientationAction"));
+ gtk_toggle_action_set_active(toggle_action, attr.u.num != -1);
+ }
+ if (navit_get_attr(this->nav, attr_tracking, &attr, NULL)) {
+ toggle_action = GTK_TOGGLE_ACTION(gtk_action_group_get_action(this->base_group, "TrackingAction"));
+ gtk_toggle_action_set_active(toggle_action, attr.u.num);
+ }
+ toggle_action = GTK_TOGGLE_ACTION(gtk_action_group_get_action(this->base_group, "RoadbookAction"));
+ gtk_toggle_action_set_active(toggle_action, 0);
+
+ if (navit_get_attr(this->nav, attr_autozoom_active, &attr, NULL)) {
+ toggle_action = GTK_TOGGLE_ACTION(gtk_action_group_get_action(this->base_group, "AutozoomAction"));
+ gtk_toggle_action_set_active(toggle_action, attr.u.num);
+ }
+
+}
+
+static struct menu_priv *
+gui_gtk_ui_new (struct gui_priv *this, struct menu_methods *meth, char *path, int popup, GtkWidget **widget_ret)
+{
+ struct menu_priv *ret;
+ GtkWidget *widget;
+
+ *meth=menu_methods;
+ ret=g_new0(struct menu_priv, 1);
+ ret->path=g_strdup(path);
+ ret->gui=this;
+
+ widget=gtk_ui_manager_get_widget(this->ui_manager, path);
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_CAN_FOCUS);
+ if (widget_ret)
+ *widget_ret=widget;
+ if (! popup) {
+ gtk_box_pack_start (GTK_BOX(this->vbox), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+ } else {
+ ret->widget=widget;
+ meth->popup=popup_activate;
+ }
+ return ret;
+}
+
+#if 0
+struct menu_priv *
+gui_gtk_menubar_new(struct gui_priv *this, struct menu_methods *meth)
+{
+ return gui_gtk_ui_new(this, meth, "/ui/MenuBar", 0, &this->menubar);
+}
+#endif
+
+struct menu_priv *
+gui_gtk_popup_new(struct gui_priv *this, struct menu_methods *meth)
+{
+ return gui_gtk_ui_new(this, meth, "/ui/PopUp", 1, NULL);
+}
diff --git a/gui/gtk/gui_gtk_statusbar.c b/gui/gtk/gui_gtk_statusbar.c
new file mode 100644
index 00000000..f31cf078
--- /dev/null
+++ b/gui/gtk/gui_gtk_statusbar.c
@@ -0,0 +1,178 @@
+/**
+ * Navit, a modular navigation system.
+ * Copyright (C) 2005-2008 Navit Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <math.h>
+#include <gtk/gtk.h>
+#include "item.h"
+#include "coord.h"
+#include "debug.h"
+#include "vehicle.h"
+#include "callback.h"
+#include "route.h"
+#include "transform.h"
+#include "navit.h"
+#include "map.h"
+#include "navigation.h"
+#include "gui_gtk.h"
+#include "navit_nls.h"
+
+struct statusbar_priv {
+ struct gui_priv *gui;
+ GtkWidget *hbox;
+ char gps_text[128];
+ GtkWidget *gps;
+ char route_text[128];
+ GtkWidget *route;
+ struct callback *vehicle_cb;
+};
+
+#if 0
+static void
+statusbar_destroy(struct statusbar_priv *this)
+{
+ g_free(this);
+}
+
+static void
+statusbar_gps_update(struct statusbar_priv *this, int sats, int qual, double lng, double lat, double height, double direction, double speed)
+{
+ char *dirs[]={_("N"),_("NE"),_("E"),_("SE"),_("S"),_("SW"),_("W"),_("NW"),_("N")};
+ char *dir;
+ int dir_idx;
+ char pos_text[26];
+
+ coord_format(lat,lng,DEGREES_MINUTES_SECONDS,pos_text,sizeof(pos_text));
+ dir=dirs[dir_idx];
+ sprintf(this->gps_text, "GPS %02d/%02d %s %4.0fm %3.0f°%-2s %3.0fkm/h", sats, qual, pos_text, height, direction, dir, speed);
+ gtk_label_set_text(GTK_LABEL(this->gps), this->gps_text);
+
+}
+#endif
+
+static char *status_fix2str(int type)
+{
+ switch(type) {
+ case 0: return _("No");
+ case 1: return _("2D");
+ case 3: return _("3D");
+ default:
+ return _("OT");
+ }
+}
+
+static void
+statusbar_route_update(struct statusbar_priv *this, struct navit *navit, struct vehicle *v)
+{
+ struct navigation *nav=NULL;
+ struct map *map=NULL;
+ struct map_rect *mr=NULL;
+ struct item *item=NULL;
+ struct attr attr;
+ double route_len=0;
+ time_t eta;
+ struct tm *eta_tm=NULL;
+ char buffer[128];
+ double lng, lat, direction=0, height=0, speed=0, hdop=0;
+ int sats=0, qual=0;
+ int status=0;
+ char *dirs[]={_("N"),_("NE"),_("E"),_("SE"),_("S"),_("SW"),_("W"),_("NW"),_("N")};
+ char *dir;
+ int dir_idx;
+
+ if (navit)
+ nav=navit_get_navigation(navit);
+ if (nav)
+ map=navigation_get_map(nav);
+ if (map)
+ mr=map_rect_new(map, NULL);
+ if (mr)
+ item=map_rect_get_item(mr);
+ if (item) {
+ if (item_attr_get(item, attr_destination_length, &attr))
+ route_len=attr.u.num;
+ if (item_attr_get(item, attr_destination_time, &attr)) {
+ eta=time(NULL)+attr.u.num/10;
+ eta_tm=localtime(&eta);
+ }
+ }
+ if (mr)
+ map_rect_destroy(mr);
+ sprintf(buffer,_("Route %4.0fkm %02d:%02d ETA" ),route_len/1000, eta_tm ? eta_tm->tm_hour : 0 , eta_tm ? eta_tm->tm_min : 0);
+ if (strcmp(buffer, this->route_text)) {
+ strcpy(this->route_text, buffer);
+ gtk_label_set_text(GTK_LABEL(this->route), this->route_text);
+ }
+ if (!vehicle_get_attr(v, attr_position_coord_geo, &attr, NULL))
+ return;
+ lng=attr.u.coord_geo->lng;
+ lat=attr.u.coord_geo->lat;
+ if (vehicle_get_attr(v, attr_position_fix_type, &attr, NULL))
+ status=attr.u.num;
+ if (vehicle_get_attr(v, attr_position_direction, &attr, NULL))
+ direction=*(attr.u.numd);
+ direction=fmod(direction,360);
+ if (direction < 0)
+ direction+=360;
+ dir_idx=(direction+22.5)/45;
+ dir=dirs[dir_idx];
+ if (vehicle_get_attr(v, attr_position_height, &attr, NULL))
+ height=*(attr.u.numd);
+ if (vehicle_get_attr(v, attr_position_hdop, &attr, NULL))
+ hdop=*(attr.u.numd);
+ if (vehicle_get_attr(v, attr_position_speed, &attr, NULL))
+ speed=*(attr.u.numd);
+ if (vehicle_get_attr(v, attr_position_sats_used, &attr, NULL))
+ sats=attr.u.num;
+ if (vehicle_get_attr(v, attr_position_qual, &attr, NULL))
+ qual=attr.u.num;
+ coord_format(lat,lng,DEGREES_MINUTES_SECONDS,buffer,sizeof(buffer));
+ sprintf(this->gps_text,"GPS:%s %02d/%02d HD:%02.2f %s %4.0fm %3.0f°%-2s %3.0fkm/h",
+ status_fix2str(status),
+ sats, qual, hdop, buffer, height,
+ direction, dir, speed);
+ gtk_label_set_text(GTK_LABEL(this->gps), this->gps_text);
+}
+
+struct statusbar_priv *
+gui_gtk_statusbar_new(struct gui_priv *gui)
+{
+ struct statusbar_priv *this=g_new0(struct statusbar_priv, 1);
+
+ this->gui=gui;
+ this->hbox=gtk_hbox_new(FALSE, 1);
+ this->gps=gtk_label_new( "GPS 00/0 0000.0000N 00000.0000E 0000m 000°NO 000km/h" );
+ gtk_label_set_justify(GTK_LABEL(this->gps), GTK_JUSTIFY_LEFT);
+ this->route=gtk_label_new( _( "Route 0000km 0+00:00 ETA" ) );
+ gtk_label_set_justify(GTK_LABEL(this->route), GTK_JUSTIFY_LEFT);
+ gtk_box_pack_start(GTK_BOX(this->hbox), this->gps, TRUE, TRUE, 2);
+ gtk_box_pack_start(GTK_BOX(this->hbox), gtk_vseparator_new(), TRUE, TRUE, 2);
+ gtk_box_pack_start(GTK_BOX(this->hbox), this->route, TRUE, TRUE, 2);
+ GTK_WIDGET_UNSET_FLAGS (this->hbox, GTK_CAN_FOCUS);
+
+ gtk_box_pack_end(GTK_BOX(gui->vbox), this->hbox, FALSE, FALSE, 0);
+ gtk_widget_show_all(this->hbox);
+ /* add a callback for position updates */
+ this->vehicle_cb=callback_new_attr_1(callback_cast(statusbar_route_update), attr_position_coord_geo, this);
+ navit_add_callback(gui->nav, this->vehicle_cb);
+ return this;
+}
+
diff --git a/gui/gtk/gui_gtk_window.c b/gui/gtk/gui_gtk_window.c
new file mode 100644
index 00000000..a95b8e1b
--- /dev/null
+++ b/gui/gtk/gui_gtk_window.c
@@ -0,0 +1,771 @@
+/**
+ * Navit, a modular navigation system.
+ * Copyright (C) 2005-2008 Navit Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <gdk/gdkkeysyms.h>
+#if !defined(GDK_Book) || !defined(GDK_Calendar)
+#include <X11/XF86keysym.h>
+#endif
+#include <gtk/gtk.h>
+#include "config.h"
+#include "item.h"
+#include "navit.h"
+#include "debug.h"
+#include "gui.h"
+#include "coord.h"
+#include "point.h"
+#include "plugin.h"
+#include "graphics.h"
+#include "gui_gtk.h"
+#include "transform.h"
+#include "config.h"
+#include "callback.h"
+#include "layout.h"
+#include "vehicle.h"
+#include "map.h"
+#include "coord.h"
+#include "event.h"
+#include "navit_nls.h"
+
+#ifdef USE_HILDON
+#include "hildon/hildon-defines.h"
+#define KEY_ZOOM_IN HILDON_HARDKEY_INCREASE
+#define KEY_ZOOM_OUT HILDON_HARDKEY_DECREASE
+#define KEY_UP HILDON_HARDKEY_UP
+#define KEY_DOWN HILDON_HARDKEY_DOWN
+#define KEY_LEFT HILDON_HARDKEY_LEFT
+#define KEY_RIGHT HILDON_HARDKEY_RIGHT
+#else
+#ifndef GDK_Book
+#define GDK_Book XF86XK_Book
+#endif
+#ifndef GDK_Calendar
+#define GDK_Calendar XF86XK_Calendar
+#endif
+#define KEY_ZOOM_IN GDK_Book
+#define KEY_ZOOM_OUT GDK_Calendar
+#define KEY_UP GDK_Up
+#define KEY_DOWN GDK_Down
+#define KEY_LEFT GDK_Left
+#define KEY_RIGHT GDK_Right
+#endif
+
+static gboolean
+keypress(GtkWidget *widget, GdkEventKey *event, struct gui_priv *this)
+{
+ int w,h;
+ struct transformation *t;
+ #ifdef USE_HILDON
+ GtkToggleAction *action;
+ gboolean *fullscreen;
+ #endif /*HILDON*/
+ struct point p;
+ if (event->type != GDK_KEY_PRESS)
+ return FALSE;
+ dbg(1,"keypress 0x%x\n", event->keyval);
+ transform_get_size(navit_get_trans(this->nav), &w, &h);
+ switch (event->keyval) {
+ case GDK_KP_Enter:
+ gtk_menu_shell_select_first(GTK_MENU_SHELL(this->menubar), TRUE);
+ break;
+ case KEY_UP:
+ p.x=w/2;
+ p.y=0;
+ navit_set_center_screen(this->nav, &p, 1);
+ break;
+ case KEY_DOWN:
+ p.x=w/2;
+ p.y=h;
+ navit_set_center_screen(this->nav, &p, 1);
+ break;
+ case KEY_LEFT:
+ p.x=0;
+ p.y=h/2;
+ navit_set_center_screen(this->nav, &p, 1);
+ break;
+ case KEY_RIGHT:
+ p.x=w;
+ p.y=h/2;
+ navit_set_center_screen(this->nav, &p, 1);
+ break;
+ case KEY_ZOOM_IN:
+ navit_zoom_in(this->nav, 2, NULL);
+ break;
+ case KEY_ZOOM_OUT:
+ navit_zoom_out(this->nav, 2, NULL);
+ break;
+ case 'a':
+ t=navit_get_trans(this->nav);
+ transform_set_yaw(t, (transform_get_yaw(t)+15)%360);
+ navit_draw(this->nav);
+ break;
+ case 'd':
+ t=navit_get_trans(this->nav);
+ transform_set_yaw(t, (transform_get_yaw(t)-15)%360);
+ navit_draw(this->nav);
+ break;
+ case 'w':
+ t=navit_get_trans(this->nav);
+ transform_set_pitch(t, (transform_get_pitch(t)+5)%360);
+ navit_draw(this->nav);
+ break;
+ case 'x':
+ t=navit_get_trans(this->nav);
+ transform_set_pitch(t, (transform_get_pitch(t)-5)%360);
+ navit_draw(this->nav);
+ break;
+ case 'r':
+ t=navit_get_trans(this->nav);
+ transform_set_distance(t, (transform_get_distance(t)-5));
+ navit_draw(this->nav);
+ break;
+ case 'f':
+ t=navit_get_trans(this->nav);
+ transform_set_distance(t, (transform_get_distance(t)+5));
+ navit_draw(this->nav);
+ break;
+ case 'z':
+ t=navit_get_trans(this->nav);
+ transform_set_hog(t, (transform_get_hog(t)+1));
+ navit_draw(this->nav);
+ break;
+ case 'h':
+ t=navit_get_trans(this->nav);
+ transform_set_hog(t, (transform_get_hog(t)-1));
+ navit_draw(this->nav);
+ break;
+ case 't':
+ {
+ struct coord *p;
+ struct pcoord pc;
+ t=navit_get_trans(this->nav);
+ p=transform_center(t);
+ pc.pro=projection_mg;
+ p->y+=50*cos(transform_get_yaw(t)*M_PI/180);
+ p->x+=50*sin(transform_get_yaw(t)*M_PI/180);
+ pc.x=p->x;
+ pc.y=p->y;
+ navit_set_center(this->nav, &pc, 1);
+ }
+ break;
+ case 'g':
+ {
+ struct coord *p;
+ struct pcoord pc;
+ t=navit_get_trans(this->nav);
+ p=transform_center(t);
+ pc.pro=projection_mg;
+ p->y-=50*cos(transform_get_yaw(t)*M_PI/180);
+ p->x-=50*sin(transform_get_yaw(t)*M_PI/180);
+ pc.x=p->x;
+ pc.y=p->y;
+ navit_set_center(this->nav, &pc, 1);
+ }
+ break;
+ #ifdef USE_HILDON
+ case HILDON_HARDKEY_FULLSCREEN:
+ action = GTK_TOGGLE_ACTION (gtk_action_group_get_action (this->base_group, "FullscreenAction"));
+
+ if ( gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)))
+ {
+ fullscreen = 0;
+ } else {
+ fullscreen = 1;
+ }
+ gtk_toggle_action_set_active (action, fullscreen);
+ break;
+ #endif /*HILDON*/
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static int
+gui_gtk_set_graphics(struct gui_priv *this, struct graphics *gra)
+{
+ GtkWidget *graphics;
+
+ graphics=graphics_get_data(gra, "gtk_widget");
+ if (! graphics)
+ return 1;
+ GTK_WIDGET_SET_FLAGS (graphics, GTK_CAN_FOCUS);
+ gtk_widget_set_sensitive(graphics, TRUE);
+ g_signal_connect(G_OBJECT(graphics), "key-press-event", G_CALLBACK(keypress), this);
+ gtk_box_pack_end(GTK_BOX(this->vbox), graphics, TRUE, TRUE, 0);
+ gtk_widget_show_all(graphics);
+ gtk_widget_grab_focus(graphics);
+
+ return 0;
+}
+
+static void
+gui_gtk_add_bookmark_do(struct gui_priv *gui)
+{
+ navit_add_bookmark(gui->nav, &gui->dialog_coord, gtk_entry_get_text(GTK_ENTRY(gui->dialog_entry)));
+ gtk_widget_destroy(gui->dialog_win);
+}
+
+static int
+gui_gtk_add_bookmark(struct gui_priv *gui, struct pcoord *c, char *description)
+{
+ GtkWidget *button_ok,*button_cancel,*label,*vbox,*hbox;
+
+ gui->dialog_coord=*c;
+ gui->dialog_win=gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ vbox=gtk_vbox_new(FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (gui->dialog_win), vbox);
+ gtk_window_set_title(GTK_WINDOW(gui->dialog_win),_("Add Bookmark"));
+ gtk_window_set_wmclass (GTK_WINDOW (gui->dialog_win), "navit", "Navit");
+ gtk_window_set_transient_for(GTK_WINDOW(gui->dialog_win), GTK_WINDOW(gui->win));
+ gtk_window_set_modal(GTK_WINDOW(gui->dialog_win), TRUE);
+ label=gtk_label_new(_("Name"));
+ gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
+ gui->dialog_entry=gtk_entry_new();
+ gtk_entry_set_text(GTK_ENTRY(gui->dialog_entry), description);
+ gtk_box_pack_start(GTK_BOX(vbox), gui->dialog_entry, TRUE, TRUE, 0);
+ hbox=gtk_hbox_new(FALSE, 0);
+ button_ok = gtk_button_new_from_stock (GTK_STOCK_OK);
+ gtk_box_pack_start(GTK_BOX(hbox), button_ok, TRUE, TRUE, 10);
+ button_cancel = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
+ gtk_box_pack_start(GTK_BOX(hbox), button_cancel, TRUE, TRUE, 10);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 10);
+ gtk_widget_show_all(gui->dialog_win);
+ GTK_WIDGET_SET_FLAGS (button_ok, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default(button_ok);
+ g_signal_connect_swapped (G_OBJECT (button_cancel), "clicked", G_CALLBACK (gtk_widget_destroy), G_OBJECT (gui->dialog_win));
+ g_signal_connect_swapped (G_OBJECT (gui->dialog_entry), "activate", G_CALLBACK (gui_gtk_add_bookmark_do), gui);
+
+ g_signal_connect_swapped(G_OBJECT (button_ok), "clicked", G_CALLBACK (gui_gtk_add_bookmark_do), gui);
+
+ return 1;
+}
+
+struct gui_methods gui_gtk_methods = {
+ NULL,
+ gui_gtk_popup_new,
+ gui_gtk_set_graphics,
+ NULL,
+ gui_gtk_datawindow_new,
+ gui_gtk_add_bookmark,
+};
+
+static gboolean
+gui_gtk_delete(GtkWidget *widget, GdkEvent *event, struct navit *nav)
+{
+ /* FIXME remove attr_navit callback */
+ navit_destroy(nav);
+
+ return TRUE;
+}
+
+static void
+gui_gtk_toggle_init(struct gui_priv *this)
+{
+ struct attr attr;
+ GtkToggleAction *toggle_action;
+
+ if (navit_get_attr(this->nav, attr_cursor, &attr, NULL)) {
+ toggle_action = GTK_TOGGLE_ACTION(gtk_action_group_get_action(this->base_group, "CursorAction"));
+ gtk_toggle_action_set_active(toggle_action, attr.u.num);
+ } else {
+ dbg(1, "Unable to locate CursorAction\n");
+ }
+ if (navit_get_attr(this->nav, attr_orientation, &attr, NULL)) {
+ toggle_action = GTK_TOGGLE_ACTION(gtk_action_group_get_action(this->base_group, "OrientationAction"));
+ gtk_toggle_action_set_active(toggle_action, attr.u.num != -1);
+ } else {
+ dbg(0, "Unable to locate OrientationAction\n");
+ }
+ if (navit_get_attr(this->nav, attr_tracking, &attr, NULL)) {
+ toggle_action = GTK_TOGGLE_ACTION(gtk_action_group_get_action(this->base_group, "TrackingAction"));
+ gtk_toggle_action_set_active(toggle_action, attr.u.num);
+ } else {
+ dbg(0, "Unable to locate TrackingAction\n");
+ }
+}
+
+struct action_cb_data {
+ struct gui_priv *gui;
+ struct attr attr;
+};
+
+static void
+gui_gtk_action_activate(GtkAction *action, struct action_cb_data *data)
+{
+ if(data->attr.type == attr_destination) {
+ char * label;
+ g_object_get(G_OBJECT(action), "label", &label,NULL);
+ navit_set_destination(data->gui->nav, data->attr.u.pcoord, label, 1);
+ g_free(label);
+ }
+}
+
+struct gui_menu_info {
+ guint merge_id;
+ GtkAction *action;
+};
+
+static void
+gui_gtk_del_menu(struct gui_priv *this, struct gui_menu_info *meninfo)
+{
+ gtk_action_group_remove_action(this->dyn_group, meninfo->action);
+ gtk_ui_manager_remove_ui(this->ui_manager, meninfo->merge_id);
+}
+
+static struct gui_menu_info
+gui_gtk_add_menu(struct gui_priv *this, char *name, char *label, char *path, int submenu, struct action_cb_data *data)
+{
+ struct gui_menu_info meninfo;
+ GtkAction *action;
+ guint merge_id;
+
+ action=gtk_action_new(name, label, NULL, NULL);
+ meninfo.action = action;
+ if (data)
+ g_signal_connect(action, "activate", G_CALLBACK(gui_gtk_action_activate), data);
+ gtk_action_group_add_action(this->dyn_group, action);
+ merge_id =gtk_ui_manager_new_merge_id(this->ui_manager);
+ meninfo.merge_id = merge_id;
+ gtk_ui_manager_add_ui(this->ui_manager, merge_id, path, name, name, submenu ? GTK_UI_MANAGER_MENU : GTK_UI_MANAGER_MENUITEM, FALSE);
+
+ return meninfo;
+}
+
+static void
+gui_gtk_action_toggled(GtkToggleAction *action, struct action_cb_data *data)
+{
+ struct attr active;
+ active.type=attr_active;
+ active.u.num=gtk_toggle_action_get_active(action);
+ map_set_attr(data->attr.u.map, &active);
+ navit_draw(data->gui->nav);
+}
+
+static void
+gui_gtk_add_toggle_menu(struct gui_priv *this, char *name, char *label, char *path, struct action_cb_data *data, gboolean active)
+{
+ GtkToggleAction *toggle_action;
+ guint merge_id;
+
+ toggle_action=gtk_toggle_action_new(name, label, NULL, NULL);
+ gtk_toggle_action_set_active(toggle_action, active);
+ g_signal_connect(GTK_ACTION(toggle_action), "toggled", G_CALLBACK(gui_gtk_action_toggled), data);
+ gtk_action_group_add_action(this->dyn_group, GTK_ACTION(toggle_action));
+ merge_id=gtk_ui_manager_new_merge_id(this->ui_manager);
+ gtk_ui_manager_add_ui(this->ui_manager, merge_id, path, name, name, GTK_UI_MANAGER_MENUITEM, FALSE);
+}
+
+static void
+gui_gtk_action_changed(GtkRadioAction *action, GtkRadioAction *current, struct action_cb_data *data)
+{
+ if (action == current) {
+ navit_set_attr(data->gui->nav, &data->attr);
+ }
+}
+
+static struct gui_menu_info
+gui_gtk_add_radio_menu(struct gui_priv *this, char *name, char *label, char *path, struct action_cb_data *data, GSList **g)
+{
+ struct gui_menu_info meninfo;
+ GtkRadioAction *radio_action;
+ guint merge_id;
+
+ radio_action=gtk_radio_action_new(name, label, NULL, NULL, 0);
+ meninfo.action = (GtkAction *)radio_action;
+ gtk_radio_action_set_group(radio_action, *g);
+ *g=gtk_radio_action_get_group(radio_action);
+ g_signal_connect(GTK_ACTION(radio_action), "changed", G_CALLBACK(gui_gtk_action_changed), data);
+ gtk_action_group_add_action(this->dyn_group, GTK_ACTION(radio_action));
+ merge_id=gtk_ui_manager_new_merge_id(this->ui_manager);
+ meninfo.merge_id = merge_id;
+ gtk_ui_manager_add_ui(this->ui_manager, merge_id, path, name, name, GTK_UI_MANAGER_MENUITEM, FALSE);
+
+ return meninfo;
+}
+
+static void
+gui_gtk_layouts_init(struct gui_priv *this)
+{
+ struct attr_iter *iter;
+ struct attr attr;
+ struct action_cb_data *data;
+ int count=0;
+ char *name;
+
+ iter=navit_attr_iter_new();
+ while(navit_get_attr(this->nav, attr_layout, &attr, iter)) {
+ name=g_strdup_printf("Layout %d", count++);
+ data=g_new(struct action_cb_data, 1);
+ data->gui=this;
+ data->attr.type=attr_layout;
+ data->attr.u.layout=attr.u.layout;
+ gui_gtk_add_radio_menu(this, name, attr.u.layout->name, "/ui/MenuBar/Map/Layout/LayoutMenuAdditions", data, &this->layout_group);
+ g_free(name);
+ }
+ navit_attr_iter_destroy(iter);
+}
+
+static void
+gui_gtk_projections_init(struct gui_priv *this)
+{
+ struct action_cb_data *data;
+
+ data=g_new(struct action_cb_data, 1);
+ data->gui=this;
+ data->attr.type=attr_projection;
+ data->attr.u.projection=projection_mg;
+ gui_gtk_add_radio_menu(this, "Projection mg", "Map & Guide", "/ui/MenuBar/Map/Projection/ProjectionMenuAdditions", data, &this->projection_group);
+
+ data=g_new(struct action_cb_data, 1);
+ data->gui=this;
+ data->attr.type=attr_projection;
+ data->attr.u.projection=projection_garmin;
+ gui_gtk_add_radio_menu(this, "Projection garmin", "Garmin", "/ui/MenuBar/Map/Projection/ProjectionMenuAdditions", data, &this->projection_group);
+}
+
+static void
+gui_gtk_vehicles_update(struct gui_priv *this)
+{
+ struct attr_iter *iter;
+ struct attr attr,vattr;
+ struct action_cb_data *data;
+ int count=0;
+ char *name;
+ GList *curr;
+ struct gui_menu_info *meninfo;
+ dbg(1,"enter\n");
+
+ curr = g_list_first(this->vehicle_menuitems);
+
+ while (curr) {
+ gui_gtk_del_menu(this, (struct gui_menu_info *)curr->data);
+ g_free((struct gui_menu_info *)curr->data);
+ curr = g_list_next(curr);
+ };
+
+ g_list_free(this->vehicle_menuitems);
+ this->vehicle_menuitems = NULL;
+
+ iter=navit_attr_iter_new();
+ while(navit_get_attr(this->nav, attr_vehicle, &attr, iter)) {
+ vehicle_get_attr(attr.u.vehicle, attr_name, &vattr, NULL);
+ name=g_strdup_printf("Vehicle %d", count++);
+ data=g_new(struct action_cb_data, 1);
+ data->gui=this;
+ data->attr.type=attr_vehicle;
+ data->attr.u.vehicle=attr.u.vehicle;
+ meninfo = g_new(struct gui_menu_info, 1);
+ *meninfo = gui_gtk_add_radio_menu(this, name, vattr.u.str, "/ui/MenuBar/Map/Vehicle/VehicleMenuAdditions", data, &this->vehicle_group);
+ this->vehicle_menuitems = g_list_prepend(this->vehicle_menuitems, meninfo);
+ g_free(name);
+ }
+ navit_attr_iter_destroy(iter);
+}
+
+static void
+gui_gtk_vehicles_init(struct gui_priv *this)
+{
+ navit_add_callback(this->nav, callback_new_attr_1(callback_cast(gui_gtk_vehicles_update), attr_vehicle, this));
+ gui_gtk_vehicles_update(this);
+}
+
+static void
+gui_gtk_maps_init(struct gui_priv *this)
+{
+ struct attr_iter *iter;
+ struct attr attr,active,type,data;
+ struct action_cb_data *cb_data;
+ int count=0;
+ char *name, *label;
+
+ iter=navit_attr_iter_new();
+ while(navit_get_attr(this->nav, attr_map, &attr, iter)) {
+ name=g_strdup_printf("Map %d", count++);
+ if (! map_get_attr(attr.u.map, attr_type, &type, NULL))
+ type.u.str="";
+ if (! map_get_attr(attr.u.map, attr_data, &data, NULL))
+ data.u.str="";
+ label=g_strdup_printf("%s:%s", type.u.str, data.u.str);
+ cb_data=g_new(struct action_cb_data, 1);
+ cb_data->gui=this;
+ cb_data->attr.type=attr_map;
+ cb_data->attr.u.map=attr.u.map;
+ if (! map_get_attr(attr.u.map, attr_active, &active, NULL))
+ active.u.num=1;
+ gui_gtk_add_toggle_menu(this, name, label, "/ui/MenuBar/Map/MapMenuAdditions", cb_data, active.u.num);
+ g_free(name);
+ g_free(label);
+ }
+ navit_attr_iter_destroy(iter);
+
+}
+
+static void
+gui_gtk_destinations_update(struct gui_priv *this)
+{
+ GList *curr;
+ struct attr attr;
+ struct action_cb_data *data;
+ struct map_rect *mr=NULL;
+ struct item *item;
+ struct gui_menu_info *meninfo;
+ struct coord c;
+ int count=0;
+ char *name, *label;
+
+ curr = g_list_first(this->dest_menuitems);
+
+ while (curr) {
+ gui_gtk_del_menu(this, (struct gui_menu_info *)curr->data);
+ g_free((struct gui_menu_info *)curr->data);
+ curr = g_list_next(curr);
+ };
+
+ g_list_free(this->dest_menuitems);
+ this->dest_menuitems = NULL;
+
+ if(navit_get_attr(this->nav, attr_former_destination_map, &attr, NULL) && attr.u.map && (mr=map_rect_new(attr.u.map, NULL))) {
+ while ((item=map_rect_get_item(mr))) {
+ if (item->type != type_former_destination) continue;
+ name=g_strdup_printf("Destination %d", count++);
+ item_attr_get(item, attr_label, &attr);
+ label=attr.u.str;
+ item_coord_get(item, &c, 1);
+ data=g_new(struct action_cb_data, 1);
+ data->gui=this;
+ data->attr.type=attr_destination;
+ data->attr.u.pcoord=g_new(struct pcoord, 1);
+ data->attr.u.pcoord->pro=projection_mg;
+ data->attr.u.pcoord->x=c.x;
+ data->attr.u.pcoord->y=c.y;
+
+ meninfo = g_new(struct gui_menu_info, 1);
+ *meninfo = gui_gtk_add_menu(this, name, label, "/ui/MenuBar/Route/FormerDestinations/FormerDestinationMenuAdditions",0,data);
+ this->dest_menuitems = g_list_prepend(this->dest_menuitems, meninfo);
+ g_free(name);
+ }
+ map_rect_destroy(mr);
+ }
+}
+
+static void
+gui_gtk_destinations_init(struct gui_priv *this)
+{
+ navit_add_callback(this->nav, callback_new_attr_1(callback_cast(gui_gtk_destinations_update), attr_destination, this));
+ gui_gtk_destinations_update(this);
+}
+
+static void
+gui_gtk_bookmarks_update(struct gui_priv *this)
+{
+ GList *curr;
+ struct attr attr;
+ struct action_cb_data *data;
+ struct map_rect *mr=NULL;
+ struct gui_menu_info *meninfo;
+ struct item *item;
+ struct coord c;
+ int count=0;
+ char *parent, *name, *label, *label_full, *menu_label, *tmp_parent, *s;
+ GHashTable *hash;
+
+ curr = g_list_first(this->bookmarks_menuitems);
+
+ while (curr) {
+ gui_gtk_del_menu(this, (struct gui_menu_info *)curr->data);
+ g_free((struct gui_menu_info *)curr->data);
+ curr = g_list_next(curr);
+ };
+
+ g_list_free(this->bookmarks_menuitems);
+ this->bookmarks_menuitems = NULL;
+
+ if(navit_get_attr(this->nav, attr_bookmark_map, &attr, NULL) && attr.u.map && (mr=map_rect_new(attr.u.map, NULL))) {
+ hash=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+ while ((item=map_rect_get_item(mr))) {
+ if (item->type != type_bookmark) continue;
+ item_attr_get(item, attr_label, &attr);
+ label_full=attr.u.str;
+ item_coord_get(item, &c, 1);
+ menu_label=g_malloc(strlen(label_full)+1);
+ label=label_full;
+ parent=g_strdup("/ui/MenuBar/Route/Bookmarks/BookmarkMenuAdditions");
+ while ((s=strchr(label, '/'))) {
+ strcpy(menu_label, label_full);
+ menu_label[s-label_full]='\0';
+ if ((tmp_parent=g_hash_table_lookup(hash, menu_label))) {
+ tmp_parent=g_strdup(tmp_parent);
+ } else {
+ name=g_strdup_printf("Bookmark %d", count++);
+ meninfo = g_new(struct gui_menu_info, 1);
+ *meninfo = gui_gtk_add_menu(this, name, menu_label+(label-label_full),parent,1,NULL);
+ this->bookmarks_menuitems = g_list_prepend(this->bookmarks_menuitems, meninfo);
+ tmp_parent=g_strdup_printf("%s/%s", parent, name);
+ g_hash_table_insert(hash, g_strdup(menu_label), g_strdup(tmp_parent));
+ g_free(name);
+ }
+ g_free(parent);
+ parent=tmp_parent;
+ label=s+1;
+ }
+ g_free(menu_label);
+ data=g_new(struct action_cb_data, 1);
+ data->gui=this;
+ data->attr.type=attr_destination;
+ data->attr.u.pcoord=g_new(struct pcoord, 1);
+ data->attr.u.pcoord->pro=projection_mg;
+ data->attr.u.pcoord->x=c.x;
+ data->attr.u.pcoord->y=c.y;
+ name=g_strdup_printf("Bookmark %d", count++);
+ meninfo = g_new(struct gui_menu_info, 1);
+ *meninfo = gui_gtk_add_menu(this, name, label, parent,0,data);
+ this->bookmarks_menuitems = g_list_prepend(this->bookmarks_menuitems, meninfo);
+ g_free(name);
+ g_free(parent);
+ }
+ g_hash_table_destroy(hash);
+ }
+}
+
+static void
+gui_gtk_bookmarks_init(struct gui_priv *this)
+{
+ navit_add_callback(this->nav, callback_new_attr_1(callback_cast(gui_gtk_bookmarks_update), attr_bookmark_map, this));
+ gui_gtk_bookmarks_update(this);
+}
+
+static void
+gui_gtk_init(struct gui_priv *this, struct navit *nav)
+{
+
+
+ gui_gtk_toggle_init(this);
+ gui_gtk_layouts_init(this);
+ gui_gtk_projections_init(this);
+ gui_gtk_vehicles_init(this);
+ gui_gtk_maps_init(this);
+ gui_gtk_destinations_init(this);
+ gui_gtk_bookmarks_init(this);
+}
+
+static struct gui_priv *
+gui_gtk_new(struct navit *nav, struct gui_methods *meth, struct attr **attrs)
+{
+ struct gui_priv *this;
+ int w=792, h=547;
+ char *cp = getenv("NAVIT_XID");
+ unsigned xid = 0;
+ struct attr *attr;
+ GtkWidget *widget;
+ int fullscreen = 0;
+
+ if (! event_request_system("glib","gui_gtk_new"))
+ return NULL;
+
+ if (cp) {
+ xid = strtol(cp, NULL, 0);
+ }
+
+ this=g_new0(struct gui_priv, 1);
+ this->nav=nav;
+
+ attr = attr_search(attrs, NULL, attr_menubar);
+ if (attr) {
+ this->menubar_enable=attr->u.num;
+ } else {
+ this->menubar_enable=1;
+ }
+ attr=attr_search(attrs, NULL, attr_toolbar);
+ if (attr) {
+ this->toolbar_enable=attr->u.num;
+ } else {
+ this->toolbar_enable=1;
+ }
+ attr=attr_search(attrs, NULL, attr_statusbar);
+ if (attr) {
+ this->statusbar_enable=attr->u.num;
+ } else {
+ this->statusbar_enable=1;
+ }
+
+ *meth=gui_gtk_methods;
+
+ if (!xid)
+ this->win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ else
+ this->win = gtk_plug_new(xid);
+
+
+ g_signal_connect(G_OBJECT(this->win), "delete-event", G_CALLBACK(gui_gtk_delete), nav);
+ this->vbox = gtk_vbox_new(FALSE, 0);
+ gtk_window_set_default_size(GTK_WINDOW(this->win), w, h);
+ gtk_window_set_title(GTK_WINDOW(this->win), "Navit");
+ gtk_window_set_wmclass (GTK_WINDOW (this->win), "navit", "Navit");
+ gtk_widget_realize(this->win);
+ gui_gtk_ui_init(this);
+ if (this->menubar_enable) {
+ widget=gtk_ui_manager_get_widget(this->ui_manager, "/ui/MenuBar");
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_CAN_FOCUS);
+ gtk_box_pack_start (GTK_BOX(this->vbox), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+ this->menubar=widget;
+ }
+ if (this->toolbar_enable) {
+ widget=gtk_ui_manager_get_widget(this->ui_manager, "/ui/ToolBar");
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_CAN_FOCUS);
+ gtk_box_pack_start (GTK_BOX(this->vbox), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+ }
+ if (this->statusbar_enable) {
+ this->statusbar=gui_gtk_statusbar_new(this);
+ }
+ gtk_container_add(GTK_CONTAINER(this->win), this->vbox);
+ gtk_widget_show_all(this->win);
+
+
+ navit_add_callback(nav, callback_new_attr_1(callback_cast(gui_gtk_init), attr_navit, this));
+
+ if ((attr=attr_search(attrs, NULL, attr_fullscreen)))
+ fullscreen=attr->u.num;
+
+ if (fullscreen) {
+ GtkToggleAction *action;
+ action = GTK_TOGGLE_ACTION (gtk_action_group_get_action (this->base_group, "FullscreenAction"));
+ gtk_toggle_action_set_active (action, fullscreen);
+ }
+
+ return this;
+}
+
+static int gtk_argc;
+static char **gtk_argv={NULL};
+
+void
+plugin_init(void)
+{
+ gtk_init(&gtk_argc, &gtk_argv);
+ gtk_set_locale();
+
+
+ plugin_register_gui_type("gtk", gui_gtk_new);
+}