Logo Search packages:      
Sourcecode: navit version File versions

gui_gtk_action.c

/**
 * 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);
}

Generated by  Doxygen 1.6.0   Back to index