diff options
author | Matt Wilson <msw@redhat.com> | 1999-08-27 14:18:26 +0000 |
---|---|---|
committer | Matt Wilson <msw@redhat.com> | 1999-08-27 14:18:26 +0000 |
commit | 7abfae68775d4f87f9245490741b042f4e5262c4 (patch) | |
tree | 780bdaed5dc3eaedf1add7c2950c3d561f2755e9 /gnome-map/timezonemapmodule.c | |
parent | 8411cdf5f15b03fa76dda9ed13e75796e1ca2030 (diff) | |
download | anaconda-7abfae68775d4f87f9245490741b042f4e5262c4.tar.gz anaconda-7abfae68775d4f87f9245490741b042f4e5262c4.tar.xz anaconda-7abfae68775d4f87f9245490741b042f4e5262c4.zip |
added gnome-map
Diffstat (limited to 'gnome-map/timezonemapmodule.c')
-rw-r--r-- | gnome-map/timezonemapmodule.c | 824 |
1 files changed, 824 insertions, 0 deletions
diff --git a/gnome-map/timezonemapmodule.c b/gnome-map/timezonemapmodule.c new file mode 100644 index 000000000..33027c177 --- /dev/null +++ b/gnome-map/timezonemapmodule.c @@ -0,0 +1,824 @@ +/* Copyright (C) 1999 Red Hat, Inc. */ +/* Original work by Michael Fulbright <drmike@redhat.com> */ + +#include <gnome.h> +#include <stdlib.h> +#include <unistd.h> +#include <math.h> + +#include <Python.h> + +#include "pygtk.h" +#include "gnome-map.h" +#include "gnome-canvas-dot.h" +#include "timezones.h" + + +/* Command line options */ +/* image - filename of file to use for map (must be PNG for antialias) */ +/* mapwidth - width to scale image to (also size of canvas widget) */ +/* mapheight - height to scale image to (also size of canvas widget) */ +/* aa - if TRUE use antialiased canvas instead of normal */ + +typedef struct MapData_t { + GnomeMap *map; + GtkWidget * locationlist; + GtkWidget * citylist; + GtkWidget * statusbar; + GtkWidget * views; + gint curselection; + GnomeCanvasItem *selmarker; + GnomeCanvasItem *curmarker; + GnomeCanvasItem **markers; + GPtrArray *Locations; + GnomeCanvasItem *hiliterubberband; + gint hiliteindex; +} MapData; + +/* if TRUE we do not want to act on the select_row events to locationlist */ +/* used when we are manually manipulating rows in locationlist and we */ +/* want to ignore the events going to the callback. */ +gboolean ignore_locationlist_selectevents=FALSE; + +/* Canvas item circle for selected location */ +double oldselx, oldsely; /* old location of selection */ +#define SELECTED_COLOR "red" +#define HILITED_COLOR "limegreen" +#define CITY_COLOR "yellow" + +GnomeMap *WorldMap; + +/* view data */ +/* Views are defined by a range of either longitude or latitude */ +/* as well as the central value for the other axis. */ +typedef enum +{ + LONGITUDE_CONSTRAINT, + LATITUDE_CONSTRAINT +} ViewContraintType; + +struct _VIEW_DEF { + gchar *name; + ViewContraintType type; + double constraint1, constraint2, constraint3; +}; + +typedef struct _VIEW_DEF ViewDefinition; + +ViewDefinition Views[] = { + { "World", LONGITUDE_CONSTRAINT, -180.0, 180.0, 0.0 }, + { "North America", LONGITUDE_CONSTRAINT, -171.0, -21.0, 40.0 }, + { "South America", LATITUDE_CONSTRAINT, 15.0, -70.0, -70.0 }, + { "Pacific Rim", LATITUDE_CONSTRAINT, -47.0, 47.0, 155.0}, + { "Europe", LONGITUDE_CONSTRAINT, -25.0, 70.0, 45.0 }, + { "Africa", LATITUDE_CONSTRAINT, 40.0, -40.0, 15.0}, + { "Asia", LONGITUDE_CONSTRAINT, 20.0, 165.0, 40.0} +}; + +static gint numviews = sizeof(Views)/sizeof(ViewDefinition); + +static gint item_event (GnomeCanvasItem *item, GdkEvent *event, gpointer data); +static GtkWidget * create_location_list (MapData *mapdata); + +/* give a location name search for match in Locations db */ +/* returns index if found, -1 if not */ +static int +find_location (GPtrArray *Locations, gchar *locname) +{ + TimeZoneLocation *loc; + gint i; + + for (i=0; i < Locations->len; i++) { + loc = g_ptr_array_index (Locations, i); + + if (!strcmp (loc->zone, locname)) + return i; + } + + return -1; +} + + +/* find nearest location to specified map coords - clips to current view */ +/* if no match return -1 */ +static int +find_nearest (GPtrArray * Locations, double longitude, double latitude ) +{ + double mindist; + double dist; + double dx, dy; + int i, mini; + gboolean first=TRUE; + TimeZoneLocation *loc; + + mini = -1; + for (i=0; i < Locations->len; i++) { + loc = g_ptr_array_index (Locations, i); + + if (!gnome_map_is_loc_in_view (WorldMap, + loc->longitude, loc->latitude)) + continue; + + dx = (loc->longitude-longitude); + dy = (loc->latitude-latitude); + dist = dx*dx + dy*dy; + + if (dist < mindist || first) { + mindist = dist; + mini = i; + first = FALSE; + } + } + + return mini; +} + +/* attach to signal for canvas items so we can track motion and mouse */ +/* events */ +static void +setup_item (GnomeCanvasItem *item, MapData *mapdata) +{ + gtk_signal_connect (GTK_OBJECT (item), "event", + (GtkSignalFunc) item_event, + mapdata); +} + +/* Moves marker (a 'x' currently) to the specified location */ +/* and sets it to the specified color. The oldx and oldy */ +/* variables are required because the canvas only allows one */ +/* to do relative moves for items. These are automatically */ +/* set to x and y by this function before it returns. */ +/* */ +/* The first time this function is called for a given marker */ +/* *curmarker should equal NULL. The marker will be created */ +/* automatically. */ + +static void +set_flag_marker (MapData *mapdata, gchar *color, + double x, double y, double *oldx, double *oldy) +{ + GnomeCanvasGroup *canvas_root; + GnomeCanvasItem *group; + + g_return_if_fail ( color != NULL ); + + canvas_root = gnome_canvas_root (GNOME_CANVAS(WorldMap->canvas)); + if (!mapdata->curmarker) { + group = gnome_canvas_item_new ( canvas_root, + gnome_canvas_group_get_type(), + "x", x, + "y", y, + NULL); + +#define MARKER_RADIUS 3.5 +#define MARKER_WIDTH_PIX 1 + + setup_item (gnome_canvas_item_new (GNOME_CANVAS_GROUP (group), + gnome_canvas_text_get_type (), + "font", "-adobe-helvetica-bold-r-normal--12-*-72-72-p-*-iso8859-1", + "anchor", GTK_ANCHOR_CENTER, + "fill_color", "red", + "text", "x", + NULL), mapdata); + + mapdata->curmarker = GNOME_CANVAS_ITEM (group); + } else { + gnome_canvas_item_move (mapdata->curmarker, x - *oldx, y - *oldy); + } + + *oldx = x; + *oldy = y; +} + +/* Given a pointer to a GnomeMap and an index into the Locations db */ +/* mark it as the selected location on the canvas */ +static void +map_mark_location_selected (GnomeMap *map, gint index) +{ + TimeZoneLocation *loc; + double selx, sely; + MapData *mapdata = (MapData *) map->data; + + g_return_if_fail ( map != NULL ); + g_return_if_fail ( index >= 0 ); + + loc = g_ptr_array_index (mapdata->Locations, index); + + gnome_map_xlat_map2screen ( map, + loc->longitude, loc->latitude, + &selx, &sely ); + set_flag_marker (mapdata, SELECTED_COLOR, selx, sely, &oldselx, &oldsely); + + if (mapdata->curselection >= 0) { + gnome_canvas_item_set (mapdata->markers[mapdata->curselection], + "fill_color", CITY_COLOR, NULL); + gnome_canvas_item_show (mapdata->markers[mapdata->curselection]); + } + + gnome_canvas_item_hide (mapdata->markers[index]); +} + +/* Given a pointer to a GnomeMap and an index into the Locations db */ +/* mark it as the selected location in the clist of locations */ +/* The jumpto gboolean is used to specify if the clist should be */ +/* forced to scroll to the new location. Used because when the */ +/* clist is autoscrolling we do not want to force selection to be */ +/* constantly recentered. */ +static void +list_mark_location_selected (GnomeMap *map, gint index, gboolean jumpto) +{ + gint newrow; + MapData * mapdata; + + mapdata = (MapData *) map->data; + + /* We're messing with list manually, so let callback know to */ + /* ignore any events till we're done */ + ignore_locationlist_selectevents = TRUE; + + /* if current selection is visible then select it again, otherwise */ + /* change clist to not have a current selection */ + if (index >= 0) { + TimeZoneLocation *loc = g_ptr_array_index (mapdata->Locations, index); + + if (gnome_map_is_loc_in_view (map,loc->longitude,loc->latitude)) { + gtk_clist_set_selection_mode (GTK_CLIST (mapdata->locationlist), + GTK_SELECTION_BROWSE); + } else { + gtk_clist_set_selection_mode (GTK_CLIST (mapdata->locationlist), + GTK_SELECTION_SINGLE); + } + } + + /* find in list of locations and set as current */ + newrow = gtk_clist_find_row_from_data (GTK_CLIST (mapdata->locationlist), + GINT_TO_POINTER (index)); + + if (newrow >= 0 ) { + gtk_clist_select_row (GTK_CLIST(mapdata->locationlist), newrow, 0); + if (jumpto && gtk_clist_row_is_visible (GTK_CLIST (mapdata->locationlist), newrow) != GTK_VISIBILITY_FULL) { + gtk_clist_moveto (GTK_CLIST (mapdata->locationlist), newrow , 0, 0.5, 0.5 ); + } + } + + /* We're done mucking with clist, ok to listen to events again */ + ignore_locationlist_selectevents = FALSE; + +} +/* handles all canvas drawing for making the selected location # index */ +/* in the sorted list in the Locations variable */ +static void +set_selection (MapData *mapdata, gint index, gboolean jumpto) +{ + g_return_if_fail ( index >= 0 ); + + map_mark_location_selected (WorldMap, index); + + list_mark_location_selected (WorldMap, index, jumpto); + + /* NOTE: curselection is global variable. Only place it gets set */ + mapdata->curselection = index; +} + +/* Given an index into the Locations db and a position, draw the hilite */ +/* marker around it to indicate it is city cursor is pointing at */ +static void +set_hilited (MapData *mapdata, gint index, double item_x, double item_y) +{ + TimeZoneLocation *loc; + GnomeCanvasPoints *points; + + g_return_if_fail ( index >= 0 ); + + loc = g_ptr_array_index (mapdata->Locations, index); + + points = gnome_canvas_points_new (2); + points->coords[0] = item_x; + points->coords[1] = item_y; + gnome_map_xlat_map2screen ( WorldMap, + loc->longitude, loc->latitude, + &points->coords[2], &points->coords[3] ); + if (mapdata->hiliterubberband) { + gnome_canvas_item_set (mapdata->hiliterubberband, "points", points, NULL); + gnome_canvas_item_show (mapdata->hiliterubberband); + } else { + GnomeCanvasGroup *canvas_root = gnome_canvas_root (GNOME_CANVAS (WorldMap->canvas)); + + mapdata->hiliterubberband = + gnome_canvas_item_new (canvas_root, + gnome_canvas_line_get_type (), + "points", points, + "fill_color", HILITED_COLOR, + "width_pixels", 2, + "first_arrowhead", FALSE, + "last_arrowhead", TRUE, + "arrow_shape_a", 4.0, + "arrow_shape_b", 8.0, + "arrow_shape_c", 4.0, + NULL); + setup_item (mapdata->hiliterubberband, mapdata); + } + + /* if hilited city isn't also currently selected city, draw the */ + /* hilite marker as well */ + if (index != mapdata->curselection) { + + if (mapdata->hiliteindex >= 0 && mapdata->hiliteindex != index) { + if (mapdata->hiliteindex != mapdata->curselection) + gnome_canvas_item_set (mapdata->markers[mapdata->hiliteindex], + "fill_color", CITY_COLOR, + NULL); + else + gnome_canvas_item_set (mapdata->markers[mapdata->hiliteindex], + "fill_color", SELECTED_COLOR, + NULL); + } + mapdata->hiliteindex = index; + gtk_statusbar_pop (GTK_STATUSBAR (mapdata->statusbar), 1); + gtk_statusbar_push (GTK_STATUSBAR (mapdata->statusbar), 1, loc->zone ); + } + + gnome_canvas_points_free (points); +} + +/* Handles case where cursor leaves the map */ +static int +canvas_event (GtkWidget *canvas, GdkEvent *event, gpointer data) +{ + MapData *mapdata = (MapData *) data; + + /* if pointer just left canvas, hide hilite marker(s) */ + if (event->type == GDK_LEAVE_NOTIFY) { + if (mapdata->hiliterubberband) + gnome_canvas_item_hide (mapdata->hiliterubberband); + if (mapdata->hiliteindex >= 0 && + mapdata->hiliteindex != mapdata->curselection) + gnome_canvas_item_set (mapdata->markers[mapdata->hiliteindex], + "fill_color", CITY_COLOR, + NULL); + + } + return FALSE; +} + +/* Handles as motion and mouse button events in the map */ +static gint +item_event (GnomeCanvasItem *item, GdkEvent *event, gpointer data) +{ + double longitude, latitude; + double item_x, item_y; + int nearest; + MapData *mapdata = (MapData *) data; + + item_x = event->button.x; + item_y = event->button.y; + gnome_canvas_item_w2i (WorldMap->image_item, &item_x, &item_y); + + switch (event->type) { + + /* User selected a new location with a left mouse button press */ + case GDK_BUTTON_PRESS: + switch (event->button.button) { + case 1: + + gnome_map_xlat_screen2map (WorldMap, item_x, item_y, + &longitude, &latitude); + + nearest = find_nearest(mapdata->Locations, longitude, latitude); + + set_selection (mapdata, nearest, TRUE); + + break; + + default: + break; + } + + break; + + /* highlight city which a button press will select */ + case GDK_MOTION_NOTIFY: + + gnome_map_xlat_screen2map ( WorldMap, item_x, item_y, + &longitude, &latitude); + + nearest = find_nearest(mapdata->Locations, longitude, latitude); + set_hilited (mapdata, nearest, item_x, item_y); + break; + + default: + break; + } + + return FALSE; +} + +/* Handles events for the clist of locations */ +static void +list_select_event ( GtkWidget *clist, gint row, gint column, + GdkEventButton *event, gpointer data) +{ + gchar *text; + gint index; + MapData * mapdata = (MapData *) data; + + /* should we do anything? */ + if (ignore_locationlist_selectevents) + return; + + /* msf - always read zero because sometimes col == -1 if they select */ + /* without a mouse click (ie. keyboard navigation ) */ + gtk_clist_get_text(GTK_CLIST(clist), row, 0, &text); + + /* Just prints some information about the selected row */ + g_print("You selected row %d. More specifically you clicked in column %d, and the text in this cell is %s\n\n", row, column, text); + + index = find_location (mapdata->Locations, text); + if (index < 0) + return; + + set_selection (mapdata, index, FALSE); + return; +} + + +static GnomeCanvasItem * +draw_city_marker ( GnomeMap *map, double longitude, double latitude) +{ + double x, y; + GnomeCanvasItem *item; + GnomeCanvasGroup *canvas_root; + MapData *mapdata = (MapData *) map->data; + + canvas_root = gnome_canvas_root (GNOME_CANVAS (map->canvas)); + + gnome_map_xlat_map2screen (map, longitude, latitude, &x, &y); + +#define RAD 1 +#ifdef ELLIPSE + item = gnome_canvas_item_new (canvas_root, + gnome_canvas_ellipse_get_type (), + "x1", x-RAD, + "y1", y-RAD, + "x2", x+RAD, + "y2", y+RAD, + "fill_color", CITY_COLOR, + NULL); +#else + item = gnome_canvas_item_new (canvas_root, + gnome_canvas_dot_get_type (), + "x", x, + "y", y, + "diameter_pixels", RAD, + "fill_color", CITY_COLOR, + NULL); +#endif + + setup_item (item, mapdata); + return item; +} + +static void +draw_cities (GnomeMap *map) +{ + gint i; + MapData * mapdata = (MapData *) map->data; + + if (mapdata->markers) + g_free(mapdata->markers); + + mapdata->markers = g_new( GnomeCanvasItem *, mapdata->Locations->len); + for (i=0; i < mapdata->Locations->len; i++) { + TimeZoneLocation *loc = g_ptr_array_index (mapdata->Locations, i); + + mapdata->markers[i] = draw_city_marker (map, loc->longitude, loc->latitude); + } +} + +static void +view_menu_activate (GtkWidget *widget, void *data) +{ + static gint curitem = -1; + gint item = GPOINTER_TO_INT (data); + MapData *mapdata = gtk_object_get_data (GTK_OBJECT (widget), "mapdata"); + + double lat1, long1, lat2, long2; + double dlat, dlong; + + if ( item == curitem ) + return; + + curitem = item; + + /* compute aspect correct view and set canvas to it */ + /* we may have to shift view if it extends outside of map */ + if (Views[item].type == LONGITUDE_CONSTRAINT) { + long1 = Views[item].constraint1; + long2 = Views[item].constraint2; + dlong = fabs(long2 - long1); + dlat = dlong/2.0; + lat1 = Views[item].constraint3 - dlat/2.0; + lat2 = Views[item].constraint3 + dlat/2.0; + + if (lat1 < -90.0) { + lat2 -= (lat1-90.0); + lat1 = -90.0; + } else if (lat2 > 90.0) { + lat1 -= (lat2-90.0); + lat2 = 90.0; + } + } else if (Views[item].type == LATITUDE_CONSTRAINT) { + lat1 = Views[item].constraint1; + lat2 = Views[item].constraint2; + dlat = fabs(lat2 - lat1); + dlong = 2.0*dlat; + long1 = Views[item].constraint3 - dlong/2.0; + long2 = Views[item].constraint3 + dlong/2.0; + + if (long1 < -180.0) { + long2 -= (long1-180.0); + long1 = -180.0; + } else if (long2 > 180.0) { + long1 -= (long2-180.0); + long2 = 180.0; + } + } else { + g_warning ("Bad contraint type %d in Views structure item # %d.\n", + item, Views[item].type); + return; + } + + gnome_map_set_view (WorldMap, long1, lat1, long2, lat2); + + /* make locationlist clist entries reflect those visible*/ + create_location_list (mapdata); +} + +GtkWidget * +create_view_menu (MapData *mapdata) +{ + GtkWidget *omenu; + GtkWidget *menu; + GtkWidget *menu_item; + gint i; + + omenu = gtk_option_menu_new (); + + menu = gtk_menu_new (); + + for (i=0; i < numviews; i++) { + menu_item = gtk_menu_item_new_with_label (Views[i].name); + gtk_menu_append (GTK_MENU (menu), menu_item); + + gtk_signal_connect (GTK_OBJECT (menu_item), "activate", + (GtkSignalFunc) view_menu_activate, + GINT_TO_POINTER (i)); + + gtk_object_set_data (GTK_OBJECT (menu_item), "mapdata", mapdata); + + gtk_widget_show (menu_item); + } + gtk_option_menu_set_menu (GTK_OPTION_MENU (omenu), menu); + gtk_option_menu_set_history (GTK_OPTION_MENU (omenu), 0); + + gtk_widget_show (omenu); + + return omenu; +} + +/* returns pointer to the scrolled window containing the clist */ +/* pointer to clist is returned via the passed argument if it doesnt */ +/* already exist. The list is clipped to the current world view */ +static GtkWidget * +create_location_list (MapData *mapdata) +{ + TimeZoneLocation *loc; + GtkWidget *scrolledwin; + gchar *titles[] = { "Location", NULL }; + gchar *row[1]; + gint i; + + ignore_locationlist_selectevents = TRUE; + + if (! mapdata->locationlist) { + scrolledwin = gtk_scrolled_window_new (NULL, NULL); + + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwin), + GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); + + gtk_widget_show (scrolledwin); + + mapdata->locationlist = gtk_clist_new_with_titles (1, titles); + + gtk_clist_set_selection_mode (GTK_CLIST(mapdata->locationlist), + GTK_SELECTION_BROWSE); + gtk_clist_column_title_passive (GTK_CLIST(mapdata->locationlist), 0); + gtk_signal_connect(GTK_OBJECT(mapdata->locationlist), "select_row", + GTK_SIGNAL_FUNC(list_select_event), + mapdata); + + gtk_container_add (GTK_CONTAINER (scrolledwin), mapdata->locationlist); + } else { + gtk_clist_clear (GTK_CLIST (mapdata->locationlist)); + scrolledwin = NULL; + } + + for (i=0; i < mapdata->Locations->len; i++) { + gint newrow; + + loc = g_ptr_array_index (mapdata->Locations, i); + if (!gnome_map_is_loc_in_view (WorldMap, loc->longitude, loc->latitude)) + continue; + + row[0] = loc->zone; + newrow = gtk_clist_append (GTK_CLIST (mapdata->locationlist), row); + gtk_clist_set_row_data (GTK_CLIST (mapdata->locationlist), newrow, + GINT_TO_POINTER (i)); + } + + /* restore selection of location in list now we've recreated it */ + list_mark_location_selected(WorldMap, mapdata->curselection, TRUE); + + ignore_locationlist_selectevents = FALSE; + return scrolledwin; +} + +MapData * new_mapdata (void) +{ + MapData * mapdata; + mapdata = g_new0 (MapData, 1); + + /* make a new map view */ + WorldMap = gnome_map_new ("map480.png", 390, 180, FALSE); + if (!WorldMap) { + g_warning ("Could not create map view."); + exit (1); + } + WorldMap->data = mapdata; + mapdata->map = WorldMap; + + setup_item (WorldMap->image_item, mapdata); + gtk_signal_connect (GTK_OBJECT (WorldMap->canvas), "event", + (GtkSignalFunc) canvas_event, + mapdata); + + /* load timezone data */ + mapdata->Locations = loadTZDB (); + if (!mapdata->Locations) { + g_warning (_("Cannot load timezone data")); + exit (1); + } + + mapdata->citylist = create_location_list (mapdata); + draw_cities (WorldMap); + + mapdata->statusbar = gtk_statusbar_new (); + mapdata->views = create_view_menu (mapdata); + + return mapdata; +} + +#if 0 +int +main (int argc, char **argv) +{ + GtkWidget *frame; + GtkWidget *hbox1, *hbox2; + GtkWidget *vbox1, *vbox2; + GtkWidget *viewcombo; + GtkWidget *statusbar; + GtkWidget *aframe; + GtkWidget *mainwindow; + MapData *mapdata; + + gnome_init ("gglobe", "0.1", argc, argv); + + mapdata = new_mapdata (); + + mainwindow = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_position (GTK_WINDOW (mainwindow), GTK_WIN_POS_CENTER); + gtk_window_set_title (GTK_WINDOW (mainwindow), _("gglobe-canvas")); + + gtk_container_add (GTK_CONTAINER (mainwindow), WorldMap->canvas); + + gtk_widget_show (statusbar); + + /* add View combo box */ + aframe = gtk_frame_new (NULL); + gtk_box_pack_start (GTK_BOX (hbox1), frame, FALSE, FALSE, 2); + + vbox2 = gtk_vbox_new (FALSE, 2); + gtk_container_add (GTK_CONTAINER (frame), vbox2); + + hbox2 = gtk_hbox_new (FALSE, 2); + gtk_box_pack_start (GTK_BOX (vbox2), hbox2, FALSE, FALSE, 2); + + viewcombo = create_view_menu (mapdata); + gtk_box_pack_start (GTK_BOX (hbox2), gtk_label_new ("View: "), + FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox2), viewcombo, FALSE, FALSE, 2); + + /* put cities on the world map */ + + /* add list of all timezones */ + frame = gtk_frame_new (NULL); + gtk_box_pack_start (GTK_BOX (vbox2), + create_location_list (mapdata), + TRUE, TRUE, 2); + + /* display and wait */ + gtk_widget_show_all (mainwindow); + + /* pick New York City as default */ + set_selection (mapdata, + find_location (mapdata->Locations, "America/New_York"), + TRUE); + + gtk_main (); + + return 0; +} + +#endif + +static PyMethodDef tzObjectMethods[] = { + { NULL }, +}; + +typedef struct tzObject_t { + PyObject_HEAD; + MapData * mapdata; +} tzObject; + +/* typedef struct tzObject_t tzObject; */ + +static PyObject * tzGetAttr(tzObject * o, char * name); +static void tzDealloc (tzObject * o); + +static PyTypeObject tzType = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /* ob_size */ + "timezonemap", /* tp_name */ + sizeof(tzObject), /* tp_size */ + 0, /* tp_itemsize */ + (destructor) tzDealloc, /* tp_dealloc */ + 0, /* tp_print */ + (getattrfunc) tzGetAttr, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ +}; + +static PyObject * tzGetAttr(tzObject * o, char * name) { + if (!strncmp (name, "map", 3)) { + return PyGtk_New((GtkObject *) o->mapdata->map->canvas); + } + if (!strncmp (name, "citylist", 8)) { + return PyGtk_New((GtkObject *) o->mapdata->citylist); + } + if (!strncmp (name, "statusbar", 9)) { + return PyGtk_New((GtkObject *) o->mapdata->statusbar); + } + if (!strncmp (name, "views", 5)) { + return PyGtk_New((GtkObject *) o->mapdata->views); + } + return Py_FindMethod(tzObjectMethods, (PyObject *) o, name); +}; + +static void tzDealloc (tzObject * o) +{ + return; +} + +static tzObject * doNewTZ (PyObject * s, PyObject * args); + +static PyMethodDef timezoneMethods[] = { + { "new", (PyCFunction) doNewTZ, METH_VARARGS, NULL }, + { NULL }, +}; + +static tzObject * doNewTZ (PyObject * s, PyObject * args) { + tzObject *o; + + o = (tzObject *) PyObject_NEW(tzObject, &tzType); + + o->mapdata = new_mapdata (); + + if (!WorldMap) { + PyErr_SetString(PyExc_TypeError, "Could not create map view."); + return NULL; + } + + return o; +} + +#include <gdk_imlib.h> + +void inittimezonemap (void) { + init_pygtk(); + + Py_InitModule("timezonemap", timezoneMethods); +} |