]> Pileus Git - grits/commitdiff
Refactoring a lot of things. Taking all the opengl and GIS stuff out of
authorAndy Spencer <andy753421@gmail.com>
Tue, 4 Aug 2009 06:22:49 +0000 (06:22 +0000)
committerAndy Spencer <andy753421@gmail.com>
Tue, 4 Aug 2009 06:22:49 +0000 (06:22 +0000)
AWeather and putting it in a Gis prefix.

16 files changed:
src/Makefile.am
src/aweather-gui.c
src/aweather-gui.h
src/aweather-view.c [deleted file]
src/aweather-view.h [deleted file]
src/gis-opengl.c [new file with mode: 0644]
src/gis-opengl.h [new file with mode: 0644]
src/gis-view.c [new file with mode: 0644]
src/gis-view.h [new file with mode: 0644]
src/gis-world.c [new file with mode: 0644]
src/gis-world.h [new file with mode: 0644]
src/location.h
src/main.c
src/plugin-example.c
src/plugin-radar.c
src/plugin-ridge.c

index 620cdcb18f280288915bb1a3f8238f3c0343030d..1c006359c643e3c83564f39a633c4f77d3160912 100644 (file)
@@ -6,8 +6,10 @@ BUILT_SOURCES = marshal.c marshal.h
 aweather_SOURCES  = main.c \
        marshal.c         marshal.h         \
        aweather-gui.c    aweather-gui.h    \
-       aweather-view.c   aweather-view.h   \
        aweather-plugin.c aweather-plugin.h \
+       gis-opengl.c      gis-opengl.h      \
+       gis-view.c        gis-view.h        \
+       gis-world.c       gis-world.h       \
        data.c            data.h            \
        location.c        location.h        \
        marching.c        marching.h        \
index da4c161d066bd6d67831baad3085505d16bbc5fd..47bc4f2858a6740ffadb2a27cfcbc6f8f32e587d 100644 (file)
 
 #include <config.h>
 #include <gtk/gtk.h>
-#include <gtk/gtkgl.h>
 #include <gdk/gdkkeysyms.h>
-#include <GL/gl.h>
-#include <GL/glu.h>
 #include <math.h>
 
 #include "misc.h"
 #include "aweather-gui.h"
-#include "aweather-view.h"
 #include "aweather-plugin.h"
+#include "gis-opengl.h"
 #include "location.h"
 
 /****************
  * GObject code *
  ****************/
 G_DEFINE_TYPE(AWeatherGui, aweather_gui, GTK_TYPE_WINDOW);
-static void aweather_gui_init(AWeatherGui *gui)
+static void aweather_gui_init(AWeatherGui *self)
 {
-       gui->plugins = NULL;
+       self->world   = NULL;
+       self->view    = NULL;
+       self->opengl  = NULL;
+       self->builder = NULL;
+       self->plugins = NULL;
        g_debug("AWeatherGui: init");
 }
 static GObject *aweather_gui_constructor(GType gtype, guint n_properties,
@@ -45,35 +46,41 @@ static GObject *aweather_gui_constructor(GType gtype, guint n_properties,
        GObjectClass *parent_class = G_OBJECT_CLASS(aweather_gui_parent_class);
        return  parent_class->constructor(gtype, n_properties, properties);
 }
-static void aweather_gui_dispose(GObject *gobject)
+static void aweather_gui_dispose(GObject *_self)
 {
        g_debug("AWeatherGui: dispose");
-       AWeatherGui *gui = AWEATHER_GUI(gobject);
-       if (gui->view) {
-               g_object_unref(gui->view);
-               gui->view = NULL;
+       AWeatherGui *self = AWEATHER_GUI(_self);
+       if (self->world) {
+               g_object_unref(self->world);
+               self->world = NULL;
        }
-       if (gui->builder) {
+       if (self->view) {
+               g_object_unref(self->view);
+               self->view = NULL;
+       }
+       if (self->opengl) {
+               g_object_unref(self->opengl);
+               self->opengl = NULL;
+       }
+       if (self->builder) {
                /* Reparent to avoid double unrefs */
-               GtkWidget *body   = aweather_gui_get_widget(gui, "body");
-               GtkWidget *window = aweather_gui_get_widget(gui, "window");
+               GtkWidget *body   = aweather_gui_get_widget(self, "body");
+               GtkWidget *window = aweather_gui_get_widget(self, "window");
                gtk_widget_reparent(body, window);
-               g_object_unref(gui->builder);
-               gui->builder = NULL;
+               g_object_unref(self->builder);
+               self->builder = NULL;
        }
-       if (gui->plugins) {
-               g_list_foreach(gui->plugins, (GFunc)g_object_unref, NULL);
-               g_list_free(gui->plugins);
-               gui->plugins = NULL;
+       if (self->plugins) {
+               g_list_foreach(self->plugins, (GFunc)g_object_unref, NULL);
+               g_list_free(self->plugins);
+               self->plugins = NULL;
        }
-       //for (GList *cur = gui->plugins; cur; cur = cur->next)
-       //      g_object_unref(cur->data);
-       G_OBJECT_CLASS(aweather_gui_parent_class)->dispose(gobject);
+       G_OBJECT_CLASS(aweather_gui_parent_class)->dispose(_self);
 }
-static void aweather_gui_finalize(GObject *gobject)
+static void aweather_gui_finalize(GObject *_self)
 {
        g_debug("AWeatherGui: finalize");
-       G_OBJECT_CLASS(aweather_gui_parent_class)->finalize(gobject);
+       G_OBJECT_CLASS(aweather_gui_parent_class)->finalize(_self);
        gtk_main_quit();
 
 }
@@ -89,45 +96,16 @@ static void aweather_gui_class_init(AWeatherGuiClass *klass)
 /*************
  * Callbacks *
  *************/
-gboolean on_drawing_button_press(GtkWidget *widget, GdkEventButton *event, AWeatherGui *gui)
-{
-       g_debug("AWeatherGui: on_drawing_button_press - Grabbing focus");
-       GtkWidget *drawing = aweather_gui_get_widget(gui, "drawing");
-       gtk_widget_grab_focus(drawing);
-       return TRUE;
-}
-gboolean on_drawing_key_press(GtkWidget *widget, GdkEventKey *event, AWeatherGui *gui)
-{
-       g_debug("AWeatherGui: on_drawing_key_press - key=%x, state=%x, plus=%x",
-                       event->keyval, event->state, GDK_plus);
-       AWeatherView *view = aweather_gui_get_view(gui);
-       double x,y,z;
-       aweather_view_get_location(view, &x, &y, &z);
-       guint kv = event->keyval;
-       if      (kv == GDK_Left  || kv == GDK_h) aweather_view_pan(view, -z/10, 0, 0);
-       else if (kv == GDK_Down  || kv == GDK_j) aweather_view_pan(view, 0, -z/10, 0);
-       else if (kv == GDK_Up    || kv == GDK_k) aweather_view_pan(view, 0,  z/10, 0);
-       else if (kv == GDK_Right || kv == GDK_l) aweather_view_pan(view,  z/10, 0, 0);
-       else if (kv == GDK_minus || kv == GDK_o) aweather_view_zoom(view, 10./9);
-       else if (kv == GDK_plus  || kv == GDK_i) aweather_view_zoom(view, 9./10);
-       else if (kv == GDK_H                   ) aweather_view_rotate(view,  0, -10, 0);
-       else if (kv == GDK_J                   ) aweather_view_rotate(view,  10,  0, 0);
-       else if (kv == GDK_K                   ) aweather_view_rotate(view, -10,  0, 0);
-       else if (kv == GDK_L                   ) aweather_view_rotate(view,  0,  10, 0);
-       return TRUE;
-}
-
-gboolean on_gui_key_press(GtkWidget *widget, GdkEventKey *event, AWeatherGui *gui)
+gboolean on_gui_key_press(GtkWidget *widget, GdkEventKey *event, AWeatherGui *self)
 {
        g_debug("AWeatherGui: on_gui_key_press - key=%x, state=%x",
                        event->keyval, event->state);
-       AWeatherView *view = aweather_gui_get_view(gui);
        if (event->keyval == GDK_q)
-               gtk_widget_destroy(GTK_WIDGET(gui));
+               gtk_widget_destroy(GTK_WIDGET(self));
        else if (event->keyval == GDK_r && event->state & GDK_CONTROL_MASK)
-               aweather_view_refresh(view);
+               gis_world_refresh(self->world);
        else if (event->keyval == GDK_Tab || event->keyval == GDK_ISO_Left_Tab) {
-               GtkNotebook *tabs = GTK_NOTEBOOK(aweather_gui_get_widget(gui, "tabs"));
+               GtkNotebook *tabs = GTK_NOTEBOOK(aweather_gui_get_widget(self, "tabs"));
                gint num_tabs = gtk_notebook_get_n_pages(tabs);
                gint cur_tab  = gtk_notebook_get_current_page(tabs);
                if (event->state & GDK_SHIFT_MASK)
@@ -138,37 +116,33 @@ gboolean on_gui_key_press(GtkWidget *widget, GdkEventKey *event, AWeatherGui *gu
        return FALSE;
 }
 
-void on_quit(GtkMenuItem *menu, AWeatherGui *gui)
+void on_quit(GtkMenuItem *menu, AWeatherGui *self)
 {
-       gtk_widget_destroy(GTK_WIDGET(gui));
+       gtk_widget_destroy(GTK_WIDGET(self));
 }
 
-void on_offline(GtkToggleAction *action, AWeatherGui *gui)
+void on_offline(GtkToggleAction *action, AWeatherGui *self)
 {
-       AWeatherView *view = aweather_gui_get_view(gui);
-       aweather_view_set_offline(view,
+       gis_world_set_offline(self->world,
                gtk_toggle_action_get_active(action));
 }
 
-void on_zoomin(GtkAction *action, AWeatherGui *gui)
+void on_zoomin(GtkAction *action, AWeatherGui *self)
 {
-       AWeatherView *view = aweather_gui_get_view(gui);
-       aweather_view_zoom(view, 3./4);
+       gis_view_zoom(self->view, 3./4);
 }
 
-void on_zoomout(GtkAction *action, AWeatherGui *gui)
+void on_zoomout(GtkAction *action, AWeatherGui *self)
 {
-       AWeatherView *view = aweather_gui_get_view(gui);
-       aweather_view_zoom(view, 4./3);
+       gis_view_zoom(self->view, 4./3);
 }
 
-void on_refresh(GtkAction *action, AWeatherGui *gui)
+void on_refresh(GtkAction *action, AWeatherGui *self)
 {
-       AWeatherView *view = aweather_gui_get_view(gui);
-       aweather_view_refresh(view);
+       gis_world_refresh(self->world);
 }
 
-void on_about(GtkAction *action, AWeatherGui *gui)
+void on_about(GtkAction *action, AWeatherGui *self)
 {
        // TODO: use gtk_widget_hide_on_delete()
        GError *error = NULL;
@@ -178,132 +152,39 @@ void on_about(GtkAction *action, AWeatherGui *gui)
        gtk_builder_connect_signals(builder, NULL);
        GtkWidget *window = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
        gtk_window_set_transient_for(GTK_WINDOW(window),
-                       GTK_WINDOW(aweather_gui_get_widget(gui, "window")));
+                       GTK_WINDOW(aweather_gui_get_widget(self, "window")));
        gtk_widget_show_all(window);
        g_object_unref(builder);
 }
 
 void on_time_changed(GtkTreeView *view, GtkTreePath *path,
-               GtkTreeViewColumn *column, AWeatherGui *gui)
+               GtkTreeViewColumn *column, AWeatherGui *self)
 {
        gchar *time;
        GtkTreeIter iter;
        GtkTreeModel *model = gtk_tree_view_get_model(view);
        gtk_tree_model_get_iter(model, &iter, path);
        gtk_tree_model_get(model, &iter, 0, &time, -1);
-       AWeatherView *aview = aweather_gui_get_view(gui);
-       aweather_view_set_time(aview, time);
+       gis_view_set_time(self->view, time);
        g_free(time);
 }
 
-void on_site_changed(GtkComboBox *combo, AWeatherGui *gui)
+void on_site_changed(GtkComboBox *combo, AWeatherGui *self)
 {
        gchar *site;
        GtkTreeIter iter;
        GtkTreeModel *model = gtk_combo_box_get_model(combo);
        gtk_combo_box_get_active_iter(combo, &iter);
        gtk_tree_model_get(model, &iter, 1, &site, -1);
-       AWeatherView *view = aweather_gui_get_view(gui);
-       aweather_view_set_site(view, site);
+       gis_view_set_site(self->view, site);
        g_free(site);
 }
 
-gboolean on_map(GtkWidget *da, GdkEventConfigure *event, AWeatherGui *gui)
-{
-       g_debug("AWeatherGui: on_map");
-       AWeatherView *view = aweather_gui_get_view(gui);
-
-       /* Misc */
-       glEnable(GL_BLEND);
-       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-       glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-
-       /* Tessellation, "finding intersecting triangles" */
-       /* http://research.microsoft.com/pubs/70307/tr-2006-81.pdf */
-       /* http://www.opengl.org/wiki/Alpha_Blending */
-       glAlphaFunc(GL_GREATER,0.1);
-       glEnable(GL_ALPHA_TEST);
-
-       /* Depth test */
-       glClearDepth(1.0);
-       glDepthFunc(GL_LEQUAL);
-       glEnable(GL_DEPTH_TEST);
-
-       aweather_gui_gl_end(gui);
-       return FALSE;
-}
-
-gboolean on_configure(GtkWidget *da, GdkEventConfigure *event, AWeatherGui *gui)
-{
-       g_debug("AWeatherGui: on_confiure");
-       aweather_gui_gl_begin(gui);
-
-       double x, y, z;
-       AWeatherView *view = aweather_gui_get_view(gui);
-       aweather_view_get_location(view, &x, &y, &z);
-
-       /* Window is at 500 m from camera */
-       double width  = da->allocation.width;
-       double height = da->allocation.height;
-
-       glViewport(0, 0, width, height);
-
-       /* Perspective */
-       glMatrixMode(GL_PROJECTION);
-       glLoadIdentity();
-       double ang = atan((height/2)/500);
-
-       //gluPerspective(r2d(ang)*2, width/height, -z-20, -z+20);
-       gluPerspective(r2d(ang)*2, width/height, 1, 500*1000);
-
-       aweather_gui_gl_end(gui);
-       return FALSE;
-}
-
-gboolean on_expose(GtkWidget *da, GdkEventExpose *event, AWeatherGui *gui)
-{
-       g_debug("AWeatherGui: on_expose - begin");
-       aweather_gui_gl_begin(gui);
-
-       double lx, ly, lz;
-       double rx, ry, rz;
-       AWeatherView *view = aweather_gui_get_view(gui);
-       aweather_view_get_location(view, &lx, &ly, &lz);
-       aweather_view_get_rotation(view, &rx, &ry, &rz);
-
-       glMatrixMode(GL_MODELVIEW);
-       glLoadIdentity();
-       glTranslatef(lx, ly, lz);
-       glRotatef(rx, 1, 0, 0);
-       glRotatef(ry, 0, 1, 0);
-       glRotatef(rz, 0, 0, 1);
-
-       /* Expose plugins */
-       for (GList *cur = gui->plugins; cur; cur = cur->next) {
-               AWeatherPlugin *plugin = AWEATHER_PLUGIN(cur->data);
-               aweather_plugin_expose(plugin);
-       }
-
-       aweather_gui_gl_end(gui);
-       aweather_gui_gl_flush(gui);
-       g_debug("AWeatherGui: on_expose - end\n");
-       return FALSE;
-}
-
-void on_state_changed(AWeatherView *view,
-               gdouble x, gdouble y, gdouble z, AWeatherGui *gui)
-{
-       /* Reset clipping area and redraw */
-       GtkWidget *da = aweather_gui_get_widget(gui, "drawing");
-       on_configure(da, NULL, gui);
-       aweather_gui_gl_redraw(gui);
-}
-
 /* TODO: replace the code in these with `gtk_tree_model_find' utility */
-static void update_time_widget(AWeatherView *view, const char *time, AWeatherGui *gui)
+static void update_time_widget(GisView *view, const char *time, AWeatherGui *self)
 {
        g_debug("AWeatherGui: update_time_widget - time=%s", time);
-       GtkTreeView  *tview = GTK_TREE_VIEW(aweather_gui_get_widget(gui, "time"));
+       GtkTreeView  *tview = GTK_TREE_VIEW(aweather_gui_get_widget(self, "time"));
        GtkTreeModel *model = GTK_TREE_MODEL(gtk_tree_view_get_model(tview));
        for (int i = 0; i < gtk_tree_model_iter_n_children(model, NULL); i++) {
                char *text;
@@ -313,10 +194,10 @@ static void update_time_widget(AWeatherView *view, const char *time, AWeatherGui
                if (g_str_equal(text, time)) {
                        GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
                        g_signal_handlers_block_by_func(tview,
-                                       G_CALLBACK(on_site_changed), gui);
+                                       G_CALLBACK(on_site_changed), self);
                        gtk_tree_view_set_cursor(tview, path, NULL, FALSE);
                        g_signal_handlers_unblock_by_func(tview,
-                                       G_CALLBACK(on_site_changed), gui);
+                                       G_CALLBACK(on_site_changed), self);
                        gtk_tree_path_free(path);
                        g_free(text);
                        return;
@@ -324,10 +205,10 @@ static void update_time_widget(AWeatherView *view, const char *time, AWeatherGui
                g_free(text);
        }
 }
-static void update_site_widget(AWeatherView *view, char *site, AWeatherGui *gui)
+static void update_site_widget(GisView *view, char *site, AWeatherGui *self)
 {
        g_debug("AWeatherGui: updat_site_widget - site=%s", site);
-       GtkComboBox  *combo = GTK_COMBO_BOX(aweather_gui_get_widget(gui, "site"));
+       GtkComboBox  *combo = GTK_COMBO_BOX(aweather_gui_get_widget(self, "site"));
        GtkTreeModel *model = GTK_TREE_MODEL(gtk_combo_box_get_model(combo));
        for (int i = 0; i < gtk_tree_model_iter_n_children(model, NULL); i++) {
                GtkTreeIter iter1;
@@ -341,10 +222,10 @@ static void update_site_widget(AWeatherView *view, char *site, AWeatherGui *gui)
                                continue;
                        if (g_str_equal(text, site)) {
                                g_signal_handlers_block_by_func(combo,
-                                               G_CALLBACK(on_site_changed), gui);
+                                               G_CALLBACK(on_site_changed), self);
                                gtk_combo_box_set_active_iter(combo, &iter2);
                                g_signal_handlers_unblock_by_func(combo,
-                                               G_CALLBACK(on_site_changed), gui);
+                                               G_CALLBACK(on_site_changed), self);
                                g_free(text);
                                return;
                        }
@@ -363,10 +244,10 @@ static void combo_sensitive(GtkCellLayout *cell_layout, GtkCellRenderer *cell,
        g_object_set(cell, "sensitive", sensitive, NULL);
 }
 
-static void site_setup(AWeatherGui *gui)
+static void site_setup(AWeatherGui *self)
 {
        GtkTreeIter state, city;
-       GtkTreeStore *store = GTK_TREE_STORE(aweather_gui_get_object(gui, "sites"));
+       GtkTreeStore *store = GTK_TREE_STORE(aweather_gui_get_object(self, "sites"));
        for (int i = 0; cities[i].label; i++) {
                if (cities[i].type == LOCATION_STATE) {
                        gtk_tree_store_append(store, &state, NULL);
@@ -379,18 +260,18 @@ static void site_setup(AWeatherGui *gui)
                }
        }
 
-       GtkWidget *combo    = aweather_gui_get_widget(gui, "site");
-       GObject   *renderer = aweather_gui_get_object(gui, "site_rend");
+       GtkWidget *combo    = aweather_gui_get_widget(self, "site");
+       GObject   *renderer = aweather_gui_get_object(self, "site_rend");
        gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(combo),
                        GTK_CELL_RENDERER(renderer), combo_sensitive, NULL, NULL);
 
-       AWeatherView *aview = aweather_gui_get_view(gui);
-       g_signal_connect(aview, "site-changed", G_CALLBACK(update_site_widget), gui);
+       g_signal_connect(self->view, "site-changed",
+                       G_CALLBACK(update_site_widget), self);
 }
 
-static void time_setup(AWeatherGui *gui)
+static void time_setup(AWeatherGui *self)
 {
-       GtkTreeView       *tview = GTK_TREE_VIEW(aweather_gui_get_widget(gui, "time"));
+       GtkTreeView       *tview = GTK_TREE_VIEW(aweather_gui_get_widget(self, "time"));
        GtkCellRenderer   *rend  = gtk_cell_renderer_text_new();
        GtkTreeViewColumn *col   = gtk_tree_view_column_new_with_attributes(
                                        "Time", rend, "text", 0, NULL);
@@ -398,27 +279,8 @@ static void time_setup(AWeatherGui *gui)
        gtk_tree_view_append_column(tview, col);
        g_object_set(rend, "size-points", 8.0, NULL);
 
-       AWeatherView *aview = aweather_gui_get_view(gui);
-       g_signal_connect(aview, "time-changed", G_CALLBACK(update_time_widget), gui);
-}
-
-static void opengl_setup(AWeatherGui *gui)
-{
-       GtkDrawingArea *drawing = GTK_DRAWING_AREA(aweather_gui_get_widget(gui, "drawing"));
-
-       GdkGLConfig *glconfig = gdk_gl_config_new_by_mode(
-                       GDK_GL_MODE_RGBA   | GDK_GL_MODE_DEPTH |
-                       GDK_GL_MODE_DOUBLE | GDK_GL_MODE_ALPHA);
-       if (!glconfig)
-               g_error("Failed to create glconfig");
-       if (!gtk_widget_set_gl_capability(GTK_WIDGET(drawing),
-                               glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE))
-               g_error("GL lacks required capabilities");
-
-       /* Set up OpenGL Stuff, glade doesn't like doing these */
-       g_signal_connect(drawing, "map-event",       G_CALLBACK(on_map),       gui);
-       g_signal_connect(drawing, "configure-event", G_CALLBACK(on_configure), gui);
-       g_signal_connect(drawing, "expose-event",    G_CALLBACK(on_expose),    gui);
+       g_signal_connect(self->view, "time-changed",
+                       G_CALLBACK(update_time_widget), self);
 }
 
 
@@ -432,94 +294,69 @@ AWeatherGui *aweather_gui_new()
        GError *error = NULL;
 
        AWeatherGui *self = g_object_new(AWEATHER_TYPE_GUI, NULL);
-       self->view    = aweather_view_new();
        self->builder = gtk_builder_new();
        if (!gtk_builder_add_from_file(self->builder, DATADIR "/aweather/main.ui", &error))
                g_error("Failed to create gtk builder: %s", error->message);
        gtk_widget_reparent(aweather_gui_get_widget(self, "body"), GTK_WIDGET(self));
 
+       GtkWidget *drawing = aweather_gui_get_widget(self, "drawing");
+       g_debug("drawing=%p", drawing);
+       self->world   = gis_world_new();
+       self->view    = gis_view_new();
+       self->opengl  = gis_opengl_new(self->world, self->view, GTK_DRAWING_AREA(drawing));
+
        /* Connect signals */
        gtk_builder_connect_signals(self->builder, self);
        g_signal_connect(self, "key-press-event",
                        G_CALLBACK(on_gui_key_press), self);
-       g_signal_connect(self->view, "location-changed",
-                       G_CALLBACK(on_state_changed), self);
-       g_signal_connect(self->view, "rotation-changed",
-                       G_CALLBACK(on_state_changed), self);
-       g_signal_connect_swapped(self->view, "offline",
+       g_signal_connect_swapped(self->world, "offline",
                        G_CALLBACK(gtk_toggle_action_set_active),
                        aweather_gui_get_object(self, "offline"));
 
        /* Load components */
        site_setup(self);
        time_setup(self);
-       opengl_setup(self);
 
        return self;
 }
-AWeatherView *aweather_gui_get_view(AWeatherGui *gui)
+GisWorld *aweather_gui_get_world(AWeatherGui *self)
 {
-       g_assert(AWEATHER_IS_GUI(gui));
-       return gui->view;
+       g_assert(AWEATHER_IS_GUI(self));
+       return self->world;
 }
-GtkBuilder *aweather_gui_get_builder(AWeatherGui *gui)
+GisView *aweather_gui_get_view(AWeatherGui *self)
+{
+       g_assert(AWEATHER_IS_GUI(self));
+       return self->view;
+}
+GisOpenGL *aweather_gui_get_opengl(AWeatherGui *self)
+{
+       g_assert(AWEATHER_IS_GUI(self));
+       return self->opengl;
+}
+GtkBuilder *aweather_gui_get_builder(AWeatherGui *self)
 {
        g_debug("AWeatherGui: get_builder");
-       g_assert(AWEATHER_IS_GUI(gui));
-       return gui->builder;
+       g_assert(AWEATHER_IS_GUI(self));
+       return self->builder;
 }
-GtkWidget *aweather_gui_get_widget(AWeatherGui *gui, const gchar *name)
+GtkWidget *aweather_gui_get_widget(AWeatherGui *self, const gchar *name)
 {
        g_debug("AWeatherGui: get_widget - name=%s", name);
-       g_assert(AWEATHER_IS_GUI(gui));
-       GObject *widget = gtk_builder_get_object(gui->builder, name);
+       g_assert(AWEATHER_IS_GUI(self));
+       GObject *widget = gtk_builder_get_object(self->builder, name);
        if (!GTK_IS_WIDGET(widget))
                g_error("Failed to get widget `%s'", name);
        return GTK_WIDGET(widget);
 }
-GObject *aweather_gui_get_object(AWeatherGui *gui, const gchar *name)
+GObject *aweather_gui_get_object(AWeatherGui *self, const gchar *name)
 {
        g_debug("AWeatherGui: get_widget - name=%s", name);
-       g_assert(AWEATHER_IS_GUI(gui));
-       return gtk_builder_get_object(gui->builder, name);
+       g_assert(AWEATHER_IS_GUI(self));
+       return gtk_builder_get_object(self->builder, name);
 }
-void aweather_gui_register_plugin(AWeatherGui *gui, AWeatherPlugin *plugin)
+void aweather_gui_register_plugin(AWeatherGui *self, AWeatherPlugin *plugin)
 {
        g_debug("AWeatherGui: register_plugin");
-       gui->plugins = g_list_append(gui->plugins, plugin);
-}
-void aweather_gui_gl_redraw(AWeatherGui *gui)
-{
-       g_debug("AWeatherGui: gl_redraw");
-       GtkWidget *drawing = aweather_gui_get_widget(gui, "drawing");
-       gtk_widget_queue_draw(drawing);
-}
-void aweather_gui_gl_begin(AWeatherGui *gui)
-{
-       g_assert(AWEATHER_IS_GUI(gui));
-
-       GtkDrawingArea *drawing    = GTK_DRAWING_AREA(aweather_gui_get_widget(gui, "drawing"));
-       GdkGLContext   *glcontext  = gtk_widget_get_gl_context(GTK_WIDGET(drawing));
-       GdkGLDrawable  *gldrawable = gtk_widget_get_gl_drawable(GTK_WIDGET(drawing));
-
-       if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext))
-               g_assert_not_reached();
-
-       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-}
-void aweather_gui_gl_end(AWeatherGui *gui)
-{
-       g_assert(AWEATHER_IS_GUI(gui));
-       GdkGLDrawable *gldrawable = gdk_gl_drawable_get_current();
-       gdk_gl_drawable_gl_end(gldrawable);
-}
-void aweather_gui_gl_flush(AWeatherGui *gui)
-{
-       g_assert(AWEATHER_IS_GUI(gui));
-       GdkGLDrawable *gldrawable = gdk_gl_drawable_get_current();
-       if (gdk_gl_drawable_is_double_buffered(gldrawable))
-               gdk_gl_drawable_swap_buffers(gldrawable);
-       else
-               glFlush();
-       gdk_gl_drawable_gl_end(gldrawable);
+       self->plugins = g_list_append(self->plugins, plugin);
 }
index 27383b258ccc293bc12f125ac055e13a5262d25d..020aed6a97f10c3d249c7df5be5bc26845b20c5b 100644 (file)
@@ -20,7 +20,9 @@
 
 #include <gtk/gtk.h>
 #include <glib-object.h>
-#include "aweather-view.h"
+#include "gis-opengl.h"
+#include "gis-world.h"
+#include "gis-view.h"
 #include "aweather-plugin.h"
 
 /* Type macros */
@@ -38,9 +40,11 @@ struct _AWeatherGui {
        GtkWindow parent_instance;
 
        /* instance members */
-       AWeatherView   *view;
-       GtkBuilder     *builder;
-       GList          *plugins;
+       GisWorld   *world;
+       GisView    *view;
+       GisOpenGL  *opengl;
+       GtkBuilder *builder;
+       GList      *plugins;
 };
 
 struct _AWeatherGuiClass {
@@ -53,13 +57,14 @@ GType aweather_gui_get_type(void);
 
 /* Methods */
 AWeatherGui    *aweather_gui_new();
-AWeatherView   *aweather_gui_get_view(AWeatherGui *gui);
+
+GisWorld       *aweather_gui_get_world(AWeatherGui *gui);
+GisOpenGL      *aweather_gui_get_opengl(AWeatherGui *gui);
+GisView        *aweather_gui_get_view(AWeatherGui *gui);
+
 GtkWidget      *aweather_gui_get_widget(AWeatherGui *gui, const gchar *name);
 GObject        *aweather_gui_get_object(AWeatherGui *gui, const gchar *name);
+
 void            aweather_gui_register_plugin(AWeatherGui *gui, AWeatherPlugin *plugin);
-void            aweather_gui_gl_redraw(AWeatherGui *gui);
-void            aweather_gui_gl_begin(AWeatherGui *gui);
-void            aweather_gui_gl_end(AWeatherGui *gui);
-void            aweather_gui_gl_flush(AWeatherGui *gui);
 
 #endif
diff --git a/src/aweather-view.c b/src/aweather-view.c
deleted file mode 100644 (file)
index 0c765fb..0000000
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * Copyright (C) 2009 Andy Spencer <spenceal@rose-hulman.edu>
- * 
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- * 
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include <glib.h>
-
-#include "marshal.h"
-#include "aweather-view.h"
-
-/****************
- * GObject code *
- ****************/
-/* Constants */
-enum {
-       PROP_0,
-       PROP_TIME,
-       PROP_SITE,
-};
-enum {
-       SIG_TIME_CHANGED,
-       SIG_SITE_CHANGED,
-       SIG_LOCATION_CHANGED,
-       SIG_ROTATION_CHANGED,
-       SIG_REFRESH,
-       SIG_OFFLINE,
-       NUM_SIGNALS,
-};
-static guint signals[NUM_SIGNALS];
-
-/* Class/Object init */
-G_DEFINE_TYPE(AWeatherView, aweather_view, G_TYPE_OBJECT);
-static void aweather_view_init(AWeatherView *self)
-{
-       g_debug("AWeatherView: init");
-       /* Default values */
-       self->time = g_strdup("");
-       self->site = g_strdup("");
-       self->location[0] = 0;
-       self->location[1] = 0;
-       self->location[2] = -300*1000;
-       self->rotation[0] = 0;
-       self->rotation[1] = 0;
-       self->rotation[2] = 0;
-       self->offline = FALSE;
-}
-static void aweather_view_dispose(GObject *gobject)
-{
-       g_debug("AWeatherView: dispose");
-       /* Drop references to other GObjects */
-       G_OBJECT_CLASS(aweather_view_parent_class)->dispose(gobject);
-}
-static void aweather_view_finalize(GObject *gobject)
-{
-       g_debug("AWeatherView: finalize");
-       AWeatherView *self = AWEATHER_VIEW(gobject);
-       g_free(self->time);
-       g_free(self->site);
-       G_OBJECT_CLASS(aweather_view_parent_class)->finalize(gobject);
-}
-static void aweather_view_set_property(GObject *object, guint property_id,
-               const GValue *value, GParamSpec *pspec)
-{
-       g_debug("AWeatherView: set_property");
-       AWeatherView *self = AWEATHER_VIEW(object);
-       switch (property_id) {
-       case PROP_TIME:     aweather_view_set_time(self, g_value_get_string(value)); break;
-       case PROP_SITE:     aweather_view_set_site(self, g_value_get_string(value)); break;
-       default:            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
-       }
-}
-static void aweather_view_get_property(GObject *object, guint property_id,
-               GValue *value, GParamSpec *pspec)
-{
-       g_debug("AWeatherView: get_property");
-       AWeatherView *self = AWEATHER_VIEW(object);
-       switch (property_id) {
-       case PROP_TIME:     g_value_set_string(value, aweather_view_get_time(self)); break;
-       case PROP_SITE:     g_value_set_string(value, aweather_view_get_site(self)); break;
-       default:            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
-       }
-}
-static void aweather_view_class_init(AWeatherViewClass *klass)
-{
-       g_debug("AWeatherView: class_init");
-       GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
-       gobject_class->dispose      = aweather_view_dispose;
-       gobject_class->finalize     = aweather_view_finalize;
-       gobject_class->get_property = aweather_view_get_property;
-       gobject_class->set_property = aweather_view_set_property;
-       g_object_class_install_property(gobject_class, PROP_TIME,
-               g_param_spec_pointer(
-                       "time",
-                       "time of the current frame",
-                       "(format unknown)", 
-                       G_PARAM_READWRITE));
-       g_object_class_install_property(gobject_class, PROP_SITE,
-               g_param_spec_pointer(
-                       "site",
-                       "site seen by the viewport",
-                       "Site of the viewport. Currently this is the name of the radar site.", 
-                       G_PARAM_READWRITE));
-       signals[SIG_TIME_CHANGED] = g_signal_new(
-                       "time-changed",
-                       G_TYPE_FROM_CLASS(gobject_class),
-                       G_SIGNAL_RUN_LAST,
-                       0,
-                       NULL,
-                       NULL,
-                       g_cclosure_marshal_VOID__STRING,
-                       G_TYPE_NONE,
-                       1,
-                       G_TYPE_STRING);
-       signals[SIG_SITE_CHANGED] = g_signal_new(
-                       "site-changed",
-                       G_TYPE_FROM_CLASS(gobject_class),
-                       G_SIGNAL_RUN_LAST,
-                       0,
-                       NULL,
-                       NULL,
-                       g_cclosure_marshal_VOID__STRING,
-                       G_TYPE_NONE,
-                       1,
-                       G_TYPE_STRING);
-       signals[SIG_LOCATION_CHANGED] = g_signal_new(
-                       "location-changed",
-                       G_TYPE_FROM_CLASS(gobject_class),
-                       G_SIGNAL_RUN_LAST,
-                       0,
-                       NULL,
-                       NULL,
-                       aweather_cclosure_marshal_VOID__DOUBLE_DOUBLE_DOUBLE,
-                       G_TYPE_NONE,
-                       3,
-                       G_TYPE_DOUBLE,
-                       G_TYPE_DOUBLE,
-                       G_TYPE_DOUBLE);
-       signals[SIG_ROTATION_CHANGED] = g_signal_new(
-                       "rotation-changed",
-                       G_TYPE_FROM_CLASS(gobject_class),
-                       G_SIGNAL_RUN_LAST,
-                       0,
-                       NULL,
-                       NULL,
-                       aweather_cclosure_marshal_VOID__DOUBLE_DOUBLE_DOUBLE,
-                       G_TYPE_NONE,
-                       3,
-                       G_TYPE_DOUBLE,
-                       G_TYPE_DOUBLE,
-                       G_TYPE_DOUBLE);
-       signals[SIG_REFRESH] = g_signal_new(
-                       "refresh",
-                       G_TYPE_FROM_CLASS(gobject_class),
-                       G_SIGNAL_RUN_LAST,
-                       0,
-                       NULL,
-                       NULL,
-                       g_cclosure_marshal_VOID__VOID,
-                       G_TYPE_NONE,
-                       0);
-       signals[SIG_OFFLINE] = g_signal_new(
-                       "offline",
-                       G_TYPE_FROM_CLASS(gobject_class),
-                       G_SIGNAL_RUN_LAST,
-                       0,
-                       NULL,
-                       NULL,
-                       g_cclosure_marshal_VOID__BOOLEAN,
-                       G_TYPE_NONE,
-                       1,
-                       G_TYPE_BOOLEAN);
-}
-
-/* Signal helpers */
-static void _aweather_view_emit_location_changed(AWeatherView *view)
-{
-       g_signal_emit(view, signals[SIG_LOCATION_CHANGED], 0, 
-                       view->location[0],
-                       view->location[1],
-                       view->location[2]);
-}
-static void _aweather_view_emit_rotation_changed(AWeatherView *view)
-{
-       g_signal_emit(view, signals[SIG_ROTATION_CHANGED], 0, 
-                       view->rotation[0],
-                       view->rotation[1],
-                       view->rotation[2]);
-}
-static void _aweather_view_emit_time_changed(AWeatherView *view)
-{
-       g_signal_emit(view, signals[SIG_TIME_CHANGED], 0,
-                       view->time);
-}
-static void _aweather_view_emit_site_changed(AWeatherView *view)
-{
-       g_signal_emit(view, signals[SIG_SITE_CHANGED], 0,
-                       view->site);
-}
-static void _aweather_view_emit_refresh(AWeatherView *view)
-{
-       g_signal_emit(view, signals[SIG_REFRESH], 0);
-}
-static void _aweather_view_emit_offline(AWeatherView *view)
-{
-       g_signal_emit(view, signals[SIG_OFFLINE], 0,
-                       view->offline);
-}
-
-
-/***********
- * Methods *
- ***********/
-AWeatherView *aweather_view_new()
-{
-       g_debug("AWeatherView: new");
-       return g_object_new(AWEATHER_TYPE_VIEW, NULL);
-}
-
-void aweather_view_set_time(AWeatherView *view, const char *time)
-{
-       g_assert(AWEATHER_IS_VIEW(view));
-       g_debug("AWeatherView: set_time - time=%s", time);
-       g_free(view->time);
-       view->time = g_strdup(time);
-       _aweather_view_emit_time_changed(view);
-}
-
-gchar *aweather_view_get_time(AWeatherView *view)
-{
-       g_assert(AWEATHER_IS_VIEW(view));
-       g_debug("AWeatherView: get_time");
-       return view->time;
-}
-
-void aweather_view_set_location(AWeatherView *view, gdouble x, gdouble y, gdouble z)
-{
-       g_assert(AWEATHER_IS_VIEW(view));
-       g_debug("AWeatherView: set_location");
-       view->location[0] = x;
-       view->location[1] = y;
-       view->location[2] = z;
-       _aweather_view_emit_location_changed(view);
-}
-
-void aweather_view_get_location(AWeatherView *view, gdouble *x, gdouble *y, gdouble *z)
-{
-       g_assert(AWEATHER_IS_VIEW(view));
-       g_debug("AWeatherView: get_location");
-       *x = view->location[0];
-       *y = view->location[1];
-       *z = view->location[2];
-}
-
-void aweather_view_pan(AWeatherView *view, gdouble x, gdouble y, gdouble z)
-{
-       g_assert(AWEATHER_IS_VIEW(view));
-       g_debug("AWeatherView: pan - x=%.0f, y=%.0f, z=%.0f", x, y, z);
-       view->location[0] += x;
-       view->location[1] += y;
-       view->location[2] += z;
-       _aweather_view_emit_location_changed(view);
-}
-
-void aweather_view_zoom(AWeatherView *view, gdouble scale)
-{
-       g_assert(AWEATHER_IS_VIEW(view));
-       g_debug("AWeatherView: zoom");
-       view->location[2] *= scale;
-       _aweather_view_emit_location_changed(view);
-}
-
-void aweather_view_set_rotation(AWeatherView *view, gdouble x, gdouble y, gdouble z)
-{
-       g_assert(AWEATHER_IS_VIEW(view));
-       g_debug("AWeatherView: set_rotation");
-       view->rotation[0] = x;
-       view->rotation[1] = y;
-       view->rotation[2] = z;
-       _aweather_view_emit_rotation_changed(view);
-}
-
-void aweather_view_get_rotation(AWeatherView *view, gdouble *x, gdouble *y, gdouble *z)
-{
-       g_assert(AWEATHER_IS_VIEW(view));
-       g_debug("AWeatherView: get_rotation");
-       *x = view->rotation[0];
-       *y = view->rotation[1];
-       *z = view->rotation[2];
-}
-
-void aweather_view_rotate(AWeatherView *view, gdouble x, gdouble y, gdouble z)
-{
-       g_assert(AWEATHER_IS_VIEW(view));
-       g_debug("AWeatherView: rotate - x=%.0f, y=%.0f, z=%.0f", x, y, z);
-       view->rotation[0] += x;
-       view->rotation[1] += y;
-       view->rotation[2] += z;
-       _aweather_view_emit_rotation_changed(view);
-}
-
-void aweather_view_refresh(AWeatherView *view)
-{
-       g_debug("AWeatherView: refresh");
-       _aweather_view_emit_refresh(view);
-}
-
-void aweather_view_set_offline(AWeatherView *view, gboolean offline)
-{
-       g_assert(AWEATHER_IS_VIEW(view));
-       g_debug("AWeatherView: set_offline - %d", offline);
-       view->offline = offline;
-       _aweather_view_emit_offline(view);
-}
-
-gboolean aweather_view_get_offline(AWeatherView *view)
-{
-       g_assert(AWEATHER_IS_VIEW(view));
-       g_debug("AWeatherView: get_offline - %d", view->offline);
-       return view->offline;
-}
-
-/* To be deprecated, use {get,set}_location */
-void aweather_view_set_site(AWeatherView *view, const gchar *site)
-{
-       g_assert(AWEATHER_IS_VIEW(view));
-       g_debug("AWeatherView: set_site");
-       g_free(view->site);
-       view->site = g_strdup(site);
-       _aweather_view_emit_site_changed(view);
-}
-
-gchar *aweather_view_get_site(AWeatherView *view)
-{
-       g_assert(AWEATHER_IS_VIEW(view));
-       g_debug("AWeatherView: get_site");
-       return view->site;
-}
diff --git a/src/aweather-view.h b/src/aweather-view.h
deleted file mode 100644 (file)
index c67c8d8..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2009 Andy Spencer <spenceal@rose-hulman.edu>
- * 
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- * 
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __AWEATHER_VIEW_H__
-#define __AWEATHER_VIEW_H__
-
-#include <glib-object.h>
-
-/* Type macros */
-#define AWEATHER_TYPE_VIEW            (aweather_view_get_type())
-#define AWEATHER_VIEW(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),   AWEATHER_TYPE_VIEW, AWeatherView))
-#define AWEATHER_IS_VIEW(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),   AWEATHER_TYPE_VIEW))
-#define AWEATHER_VIEW_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST   ((klass), AWEATHER_TYPE_VIEW, AWeatherViewClass))
-#define AWEATHER_IS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE   ((klass), AWEATHER_TYPE_VIEW))
-#define AWEATHER_VIEW_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),   AWEATHER_TYPE_VIEW, AWeatherViewClass))
-
-typedef struct _AWeatherView      AWeatherView;
-typedef struct _AWeatherViewClass AWeatherViewClass;
-
-struct _AWeatherView {
-       GObject parent_instance;
-
-       /* instance members */
-       gchar   *time;
-       gchar   *site;
-       gdouble  location[3];
-       gdouble  rotation[3];
-       gboolean offline;
-};
-
-struct _AWeatherViewClass {
-       GObjectClass parent_class;
-       
-       /* class members */
-};
-
-GType aweather_view_get_type(void);
-
-/* Methods */
-AWeatherView *aweather_view_new();
-
-void aweather_view_set_time(AWeatherView *view, const gchar *time);
-gchar *aweather_view_get_time(AWeatherView *view);
-
-void aweather_view_set_location(AWeatherView *view, gdouble  x, gdouble  y, gdouble  z);
-void aweather_view_get_location(AWeatherView *view, gdouble *x, gdouble *y, gdouble *z);
-void aweather_view_pan         (AWeatherView *view, gdouble  x, gdouble  y, gdouble  z);
-void aweather_view_zoom        (AWeatherView *view, gdouble  scale);
-
-void aweather_view_set_rotation(AWeatherView *view, gdouble  x, gdouble  y, gdouble  z);
-void aweather_view_get_rotation(AWeatherView *view, gdouble *x, gdouble *y, gdouble *z);
-void aweather_view_rotate      (AWeatherView *view, gdouble  x, gdouble  y, gdouble  z);
-
-void aweather_view_refresh(AWeatherView *view);
-
-void aweather_view_set_offline(AWeatherView *view, gboolean offline);
-gboolean aweather_view_get_offline(AWeatherView *view);
-
-/* To be deprecated, use {get,set}_location */
-void aweather_view_set_site(AWeatherView *view, const gchar *site);
-gchar *aweather_view_get_site(AWeatherView *view);
-
-#endif
diff --git a/src/gis-opengl.c b/src/gis-opengl.c
new file mode 100644 (file)
index 0000000..46eae60
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2009 Andy Spencer <spenceal@rose-hulman.edu>
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <math.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+#include <gtk/gtkgl.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+#include "misc.h"
+#include "aweather-gui.h"
+#include "gis-world.h"
+#include "gis-view.h"
+#include "gis-opengl.h"
+
+/****************
+ * GObject code *
+ ****************/
+G_DEFINE_TYPE(GisOpenGL, gis_opengl, G_TYPE_OBJECT);
+static void gis_opengl_init(GisOpenGL *self)
+{
+       g_debug("GisOpenGL: init");
+}
+static GObject *gis_opengl_constructor(GType gtype, guint n_properties,
+               GObjectConstructParam *properties)
+{
+       g_debug("gis_opengl: constructor");
+       GObjectClass *parent_class = G_OBJECT_CLASS(gis_opengl_parent_class);
+       return  parent_class->constructor(gtype, n_properties, properties);
+}
+static void gis_opengl_dispose(GObject *gobject)
+{
+       g_debug("GisOpenGL: dispose");
+       GisOpenGL *self = GIS_OPENGL(gobject);
+       if (self->world) {
+               g_object_unref(self->world);
+               self->world = NULL;
+       }
+       if (self->view) {
+               g_object_unref(self->view);
+               self->view = NULL;
+       }
+       if (self->drawing) {
+               g_object_unref(self->drawing);
+               self->drawing = NULL;
+       }
+       G_OBJECT_CLASS(gis_opengl_parent_class)->dispose(gobject);
+}
+static void gis_opengl_finalize(GObject *gobject)
+{
+       g_debug("GisOpenGL: finalize");
+       G_OBJECT_CLASS(gis_opengl_parent_class)->finalize(gobject);
+       gtk_main_quit();
+
+}
+static void gis_opengl_class_init(GisOpenGLClass *klass)
+{
+       g_debug("GisOpenGL: class_init");
+       GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+       gobject_class->constructor  = gis_opengl_constructor;
+       gobject_class->dispose      = gis_opengl_dispose;
+       gobject_class->finalize     = gis_opengl_finalize;
+}
+
+/*************
+ * Callbacks *
+ *************/
+gboolean on_button_press(GtkWidget *widget, GdkEventButton *event, GisOpenGL *self)
+{
+       g_debug("GisOpenGL: on_drawing_button_press - Grabbing focus");
+       gtk_widget_grab_focus(GTK_WIDGET(self->drawing));
+       return TRUE;
+}
+gboolean on_key_press(GtkWidget *widget, GdkEventKey *event, GisOpenGL *self)
+{
+       g_debug("GisOpenGL: on_drawing_key_press - key=%x, state=%x, plus=%x",
+                       event->keyval, event->state, GDK_plus);
+       double x,y,z;
+       gis_view_get_location(self->view, &x, &y, &z);
+       guint kv = event->keyval;
+       if      (kv == GDK_Left  || kv == GDK_h) gis_view_pan(self->view, -z/10, 0, 0);
+       else if (kv == GDK_Down  || kv == GDK_j) gis_view_pan(self->view, 0, -z/10, 0);
+       else if (kv == GDK_Up    || kv == GDK_k) gis_view_pan(self->view, 0,  z/10, 0);
+       else if (kv == GDK_Right || kv == GDK_l) gis_view_pan(self->view,  z/10, 0, 0);
+       else if (kv == GDK_minus || kv == GDK_o) gis_view_zoom(self->view, 10./9);
+       else if (kv == GDK_plus  || kv == GDK_i) gis_view_zoom(self->view, 9./10);
+       else if (kv == GDK_H                   ) gis_view_rotate(self->view,  0, -10, 0);
+       else if (kv == GDK_J                   ) gis_view_rotate(self->view,  10,  0, 0);
+       else if (kv == GDK_K                   ) gis_view_rotate(self->view, -10,  0, 0);
+       else if (kv == GDK_L                   ) gis_view_rotate(self->view,  0,  10, 0);
+       return TRUE;
+}
+
+
+gboolean on_map(GtkWidget *drawing, GdkEventConfigure *event, GisOpenGL *self)
+{
+       g_debug("GisOpenGL: on_map");
+
+       /* Misc */
+       glEnable(GL_BLEND);
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+       glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+       /* Tessellation, "finding intersecting triangles" */
+       /* http://research.microsoft.com/pubs/70307/tr-2006-81.pdf */
+       /* http://www.opengl.org/wiki/Alpha_Blending */
+       glAlphaFunc(GL_GREATER,0.1);
+       glEnable(GL_ALPHA_TEST);
+
+       /* Depth test */
+       glClearDepth(1.0);
+       glDepthFunc(GL_LEQUAL);
+       glEnable(GL_DEPTH_TEST);
+
+       gis_opengl_end(self);
+       return FALSE;
+}
+
+gboolean on_configure(GtkWidget *drawing, GdkEventConfigure *event, GisOpenGL *self)
+{
+       g_debug("GisOpenGL: on_confiure");
+       gis_opengl_begin(self);
+
+       double x, y, z;
+       gis_view_get_location(self->view, &x, &y, &z);
+
+       /* Window is at 500 m from camera */
+       double width  = GTK_WIDGET(self->drawing)->allocation.width;
+       double height = GTK_WIDGET(self->drawing)->allocation.height;
+
+       glViewport(0, 0, width, height);
+
+       /* Perspective */
+       glMatrixMode(GL_PROJECTION);
+       glLoadIdentity();
+       double ang = atan((height/2)/500);
+
+       //gluPerspective(r2d(ang)*2, width/height, -z-20, -z+20);
+       gluPerspective(r2d(ang)*2, width/height, 1, 500*1000);
+
+       gis_opengl_end(self);
+       return FALSE;
+}
+
+gboolean on_expose(GtkWidget *drawing, GdkEventExpose *event, GisOpenGL *self)
+{
+       g_debug("GisOpenGL: on_expose - begin");
+       gis_opengl_begin(self);
+
+       double lx, ly, lz;
+       double rx, ry, rz;
+       gis_view_get_location(self->view, &lx, &ly, &lz);
+       gis_view_get_rotation(self->view, &rx, &ry, &rz);
+
+       glMatrixMode(GL_MODELVIEW);
+       glLoadIdentity();
+       glTranslatef(lx, ly, lz);
+       glRotatef(rx, 1, 0, 0);
+       glRotatef(ry, 0, 1, 0);
+       glRotatef(rz, 0, 0, 1);
+
+       /* Expose plugins */
+       /* TODO: Figure out how to handle plugins:
+        *   - Do they belong to AWeatherGui, GisOpenGL, etc?
+        */
+       for (GList *cur = self->plugins; cur; cur = cur->next) {
+               AWeatherPlugin *plugin = AWEATHER_PLUGIN(cur->data);
+               aweather_plugin_expose(plugin);
+       }
+
+       gis_opengl_end(self);
+       gis_opengl_flush(self);
+       g_debug("GisOpenGL: on_expose - end\n");
+       return FALSE;
+}
+
+void on_state_changed(GisView *view,
+               gdouble x, gdouble y, gdouble z, GisOpenGL *self)
+{
+       /* Reset clipping area and redraw */
+       on_configure(NULL, NULL, self);
+       gis_opengl_redraw(self);
+}
+
+/***********
+ * Methods *
+ ***********/
+GisOpenGL *gis_opengl_new(GisWorld *world, GisView *view, GtkDrawingArea *drawing)
+{
+       g_debug("GisOpenGL: new");
+       GisOpenGL *self = g_object_new(GIS_TYPE_OPENGL, NULL);
+       self->world   = world;
+       self->view    = view;
+       self->drawing = drawing;
+       g_object_ref(world);
+       g_object_ref(view);
+       g_object_ref(drawing);
+
+       /* OpenGL setup */
+       GdkGLConfig *glconfig = gdk_gl_config_new_by_mode(
+                       GDK_GL_MODE_RGBA   | GDK_GL_MODE_DEPTH |
+                       GDK_GL_MODE_DOUBLE | GDK_GL_MODE_ALPHA);
+       if (!glconfig)
+               g_error("Failed to create glconfig");
+       if (!gtk_widget_set_gl_capability(GTK_WIDGET(self->drawing),
+                               glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE))
+               g_error("GL lacks required capabilities");
+
+       g_signal_connect(self->view, "location-changed", G_CALLBACK(on_state_changed), self);
+       g_signal_connect(self->view, "rotation-changed", G_CALLBACK(on_state_changed), self);
+
+       g_signal_connect(self->drawing, "map-event",       G_CALLBACK(on_map),       self);
+       g_signal_connect(self->drawing, "configure-event", G_CALLBACK(on_configure), self);
+       g_signal_connect(self->drawing, "expose-event",    G_CALLBACK(on_expose),    self);
+
+       g_signal_connect(self->drawing, "button-press-event", G_CALLBACK(on_button_press), self);
+       g_signal_connect(self->drawing, "enter-notify-event", G_CALLBACK(on_button_press), self);
+       g_signal_connect(self->drawing, "key-press-event",    G_CALLBACK(on_key_press),    self);
+       return self;
+}
+
+void gis_opengl_redraw(GisOpenGL *self)
+{
+       g_debug("GisOpenGL: gl_redraw");
+       gtk_widget_queue_draw(GTK_WIDGET(self->drawing));
+}
+void gis_opengl_begin(GisOpenGL *self)
+{
+       g_assert(GIS_IS_OPENGL(self));
+
+       GdkGLContext   *glcontext  = gtk_widget_get_gl_context(GTK_WIDGET(self->drawing));
+       GdkGLDrawable  *gldrawable = gtk_widget_get_gl_drawable(GTK_WIDGET(self->drawing));
+
+       if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext))
+               g_assert_not_reached();
+
+       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+}
+void gis_opengl_end(GisOpenGL *self)
+{
+       g_assert(GIS_IS_OPENGL(self));
+       GdkGLDrawable *gldrawable = gdk_gl_drawable_get_current();
+       gdk_gl_drawable_gl_end(gldrawable);
+}
+void gis_opengl_flush(GisOpenGL *self)
+{
+       g_assert(GIS_IS_OPENGL(self));
+       GdkGLDrawable *gldrawable = gdk_gl_drawable_get_current();
+       if (gdk_gl_drawable_is_double_buffered(gldrawable))
+               gdk_gl_drawable_swap_buffers(gldrawable);
+       else
+               glFlush();
+       gdk_gl_drawable_gl_end(gldrawable);
+}
diff --git a/src/gis-opengl.h b/src/gis-opengl.h
new file mode 100644 (file)
index 0000000..aca186f
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2009 Andy Spencer <spenceal@rose-hulman.edu>
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIS_OPENGL_H__
+#define __GIS_OPENGL_H__
+
+#include <config.h>
+#include <gtk/gtk.h>
+#include <gtk/gtkgl.h>
+#include <glib-object.h>
+
+#include "gis-view.h"
+#include "gis-world.h"
+
+/* Type macros */
+#define GIS_TYPE_OPENGL            (gis_opengl_get_type())
+#define GIS_OPENGL(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),   GIS_TYPE_OPENGL, GisOpenGL))
+#define GIS_IS_OPENGL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),   GIS_TYPE_OPENGL))
+#define GIS_OPENGL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST   ((klass), GIS_TYPE_OPENGL, GisOpenGLClass))
+#define GIS_IS_OPENGL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE   ((klass), GIS_TYPE_OPENGL))
+#define GIS_OPENGL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),   GIS_TYPE_OPENGL, GisOpenGLClass))
+
+typedef struct _GisOpenGL      GisOpenGL;
+typedef struct _GisOpenGLClass GisOpenGLClass;
+
+struct _GisOpenGL {
+       GObject parent_instance;
+
+       /* instance members */
+       GisWorld       *world;
+       GisView        *view;
+       GtkDrawingArea *drawing;
+       GList          *plugins;
+};
+
+struct _GisOpenGLClass {
+       GObjectClass parent_class;
+       
+       /* class members */
+};
+
+GType gis_opengl_get_type(void);
+
+/* Methods */
+GisOpenGL *gis_opengl_new(GisWorld *world, GisView *view, GtkDrawingArea *drawing);
+
+void       gis_opengl_redraw(GisOpenGL *gis);
+void       gis_opengl_begin(GisOpenGL *gis);
+void       gis_opengl_end(GisOpenGL *gis);
+void       gis_opengl_flush(GisOpenGL *gis);
+
+#endif
diff --git a/src/gis-view.c b/src/gis-view.c
new file mode 100644 (file)
index 0000000..e43aefb
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2009 Andy Spencer <spenceal@rose-hulman.edu>
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+
+#include "marshal.h"
+#include "gis-view.h"
+
+/****************
+ * GObject code *
+ ****************/
+/* Constants */
+enum {
+       PROP_0,
+       PROP_TIME,
+       PROP_SITE,
+};
+enum {
+       SIG_TIME_CHANGED,
+       SIG_SITE_CHANGED,
+       SIG_LOCATION_CHANGED,
+       SIG_ROTATION_CHANGED,
+       NUM_SIGNALS,
+};
+static guint signals[NUM_SIGNALS];
+
+/* Class/Object init */
+G_DEFINE_TYPE(GisView, gis_view, G_TYPE_OBJECT);
+static void gis_view_init(GisView *self)
+{
+       g_debug("GisView: init");
+       /* Default values */
+       self->time = g_strdup("");
+       self->site = g_strdup("");
+       self->location[0] = 0;
+       self->location[1] = 0;
+       self->location[2] = -300*1000;
+       self->rotation[0] = 0;
+       self->rotation[1] = 0;
+       self->rotation[2] = 0;
+}
+static void gis_view_dispose(GObject *gobject)
+{
+       g_debug("GisView: dispose");
+       /* Drop references to other GObjects */
+       G_OBJECT_CLASS(gis_view_parent_class)->dispose(gobject);
+}
+static void gis_view_finalize(GObject *gobject)
+{
+       g_debug("GisView: finalize");
+       GisView *self = GIS_VIEW(gobject);
+       g_free(self->time);
+       g_free(self->site);
+       G_OBJECT_CLASS(gis_view_parent_class)->finalize(gobject);
+}
+static void gis_view_set_property(GObject *object, guint property_id,
+               const GValue *value, GParamSpec *pspec)
+{
+       g_debug("GisView: set_property");
+       GisView *self = GIS_VIEW(object);
+       switch (property_id) {
+       case PROP_TIME:     gis_view_set_time(self, g_value_get_string(value)); break;
+       case PROP_SITE:     gis_view_set_site(self, g_value_get_string(value)); break;
+       default:            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+       }
+}
+static void gis_view_get_property(GObject *object, guint property_id,
+               GValue *value, GParamSpec *pspec)
+{
+       g_debug("GisView: get_property");
+       GisView *self = GIS_VIEW(object);
+       switch (property_id) {
+       case PROP_TIME:     g_value_set_string(value, gis_view_get_time(self)); break;
+       case PROP_SITE:     g_value_set_string(value, gis_view_get_site(self)); break;
+       default:            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+       }
+}
+static void gis_view_class_init(GisViewClass *klass)
+{
+       g_debug("GisView: class_init");
+       GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+       gobject_class->dispose      = gis_view_dispose;
+       gobject_class->finalize     = gis_view_finalize;
+       gobject_class->get_property = gis_view_get_property;
+       gobject_class->set_property = gis_view_set_property;
+       g_object_class_install_property(gobject_class, PROP_TIME,
+               g_param_spec_pointer(
+                       "time",
+                       "time of the current frame",
+                       "(format unknown)", 
+                       G_PARAM_READWRITE));
+       g_object_class_install_property(gobject_class, PROP_SITE,
+               g_param_spec_pointer(
+                       "site",
+                       "site seen by the viewport",
+                       "Site of the viewport. Currently this is the name of the radar site.", 
+                       G_PARAM_READWRITE));
+       signals[SIG_TIME_CHANGED] = g_signal_new(
+                       "time-changed",
+                       G_TYPE_FROM_CLASS(gobject_class),
+                       G_SIGNAL_RUN_LAST,
+                       0,
+                       NULL,
+                       NULL,
+                       g_cclosure_marshal_VOID__STRING,
+                       G_TYPE_NONE,
+                       1,
+                       G_TYPE_STRING);
+       signals[SIG_SITE_CHANGED] = g_signal_new(
+                       "site-changed",
+                       G_TYPE_FROM_CLASS(gobject_class),
+                       G_SIGNAL_RUN_LAST,
+                       0,
+                       NULL,
+                       NULL,
+                       g_cclosure_marshal_VOID__STRING,
+                       G_TYPE_NONE,
+                       1,
+                       G_TYPE_STRING);
+       signals[SIG_LOCATION_CHANGED] = g_signal_new(
+                       "location-changed",
+                       G_TYPE_FROM_CLASS(gobject_class),
+                       G_SIGNAL_RUN_LAST,
+                       0,
+                       NULL,
+                       NULL,
+                       aweather_cclosure_marshal_VOID__DOUBLE_DOUBLE_DOUBLE,
+                       G_TYPE_NONE,
+                       3,
+                       G_TYPE_DOUBLE,
+                       G_TYPE_DOUBLE,
+                       G_TYPE_DOUBLE);
+       signals[SIG_ROTATION_CHANGED] = g_signal_new(
+                       "rotation-changed",
+                       G_TYPE_FROM_CLASS(gobject_class),
+                       G_SIGNAL_RUN_LAST,
+                       0,
+                       NULL,
+                       NULL,
+                       aweather_cclosure_marshal_VOID__DOUBLE_DOUBLE_DOUBLE,
+                       G_TYPE_NONE,
+                       3,
+                       G_TYPE_DOUBLE,
+                       G_TYPE_DOUBLE,
+                       G_TYPE_DOUBLE);
+}
+
+/* Signal helpers */
+static void _gis_view_emit_location_changed(GisView *view)
+{
+       g_signal_emit(view, signals[SIG_LOCATION_CHANGED], 0, 
+                       view->location[0],
+                       view->location[1],
+                       view->location[2]);
+}
+static void _gis_view_emit_rotation_changed(GisView *view)
+{
+       g_signal_emit(view, signals[SIG_ROTATION_CHANGED], 0, 
+                       view->rotation[0],
+                       view->rotation[1],
+                       view->rotation[2]);
+}
+static void _gis_view_emit_time_changed(GisView *view)
+{
+       g_signal_emit(view, signals[SIG_TIME_CHANGED], 0,
+                       view->time);
+}
+static void _gis_view_emit_site_changed(GisView *view)
+{
+       g_signal_emit(view, signals[SIG_SITE_CHANGED], 0,
+                       view->site);
+}
+
+
+/***********
+ * Methods *
+ ***********/
+GisView *gis_view_new()
+{
+       g_debug("GisView: new");
+       return g_object_new(GIS_TYPE_VIEW, NULL);
+}
+
+void gis_view_set_time(GisView *view, const char *time)
+{
+       g_assert(GIS_IS_VIEW(view));
+       g_debug("GisView: set_time - time=%s", time);
+       g_free(view->time);
+       view->time = g_strdup(time);
+       _gis_view_emit_time_changed(view);
+}
+
+gchar *gis_view_get_time(GisView *view)
+{
+       g_assert(GIS_IS_VIEW(view));
+       g_debug("GisView: get_time");
+       return view->time;
+}
+
+void gis_view_set_location(GisView *view, gdouble x, gdouble y, gdouble z)
+{
+       g_assert(GIS_IS_VIEW(view));
+       g_debug("GisView: set_location");
+       view->location[0] = x;
+       view->location[1] = y;
+       view->location[2] = z;
+       _gis_view_emit_location_changed(view);
+}
+
+void gis_view_get_location(GisView *view, gdouble *x, gdouble *y, gdouble *z)
+{
+       g_assert(GIS_IS_VIEW(view));
+       g_debug("GisView: get_location");
+       *x = view->location[0];
+       *y = view->location[1];
+       *z = view->location[2];
+}
+
+void gis_view_pan(GisView *view, gdouble x, gdouble y, gdouble z)
+{
+       g_assert(GIS_IS_VIEW(view));
+       g_debug("GisView: pan - x=%.0f, y=%.0f, z=%.0f", x, y, z);
+       view->location[0] += x;
+       view->location[1] += y;
+       view->location[2] += z;
+       _gis_view_emit_location_changed(view);
+}
+
+void gis_view_zoom(GisView *view, gdouble scale)
+{
+       g_assert(GIS_IS_VIEW(view));
+       g_debug("GisView: zoom");
+       view->location[2] *= scale;
+       _gis_view_emit_location_changed(view);
+}
+
+void gis_view_set_rotation(GisView *view, gdouble x, gdouble y, gdouble z)
+{
+       g_assert(GIS_IS_VIEW(view));
+       g_debug("GisView: set_rotation");
+       view->rotation[0] = x;
+       view->rotation[1] = y;
+       view->rotation[2] = z;
+       _gis_view_emit_rotation_changed(view);
+}
+
+void gis_view_get_rotation(GisView *view, gdouble *x, gdouble *y, gdouble *z)
+{
+       g_assert(GIS_IS_VIEW(view));
+       g_debug("GisView: get_rotation");
+       *x = view->rotation[0];
+       *y = view->rotation[1];
+       *z = view->rotation[2];
+}
+
+void gis_view_rotate(GisView *view, gdouble x, gdouble y, gdouble z)
+{
+       g_assert(GIS_IS_VIEW(view));
+       g_debug("GisView: rotate - x=%.0f, y=%.0f, z=%.0f", x, y, z);
+       view->rotation[0] += x;
+       view->rotation[1] += y;
+       view->rotation[2] += z;
+       _gis_view_emit_rotation_changed(view);
+}
+
+/* To be deprecated, use {get,set}_location */
+void gis_view_set_site(GisView *view, const gchar *site)
+{
+       g_assert(GIS_IS_VIEW(view));
+       g_debug("GisView: set_site");
+       g_free(view->site);
+       view->site = g_strdup(site);
+       _gis_view_emit_site_changed(view);
+}
+
+gchar *gis_view_get_site(GisView *view)
+{
+       g_assert(GIS_IS_VIEW(view));
+       g_debug("GisView: get_site");
+       return view->site;
+}
diff --git a/src/gis-view.h b/src/gis-view.h
new file mode 100644 (file)
index 0000000..4608788
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2009 Andy Spencer <spenceal@rose-hulman.edu>
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIS_VIEW_H__
+#define __GIS_VIEW_H__
+
+#include <glib-object.h>
+
+/* Type macros */
+#define GIS_TYPE_VIEW            (gis_view_get_type())
+#define GIS_VIEW(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),   GIS_TYPE_VIEW, GisView))
+#define GIS_IS_VIEW(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),   GIS_TYPE_VIEW))
+#define GIS_VIEW_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST   ((klass), GIS_TYPE_VIEW, GisViewClass))
+#define GIS_IS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE   ((klass), GIS_TYPE_VIEW))
+#define GIS_VIEW_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),   GIS_TYPE_VIEW, GisViewClass))
+
+typedef struct _GisView      GisView;
+typedef struct _GisViewClass GisViewClass;
+
+struct _GisView {
+       GObject parent_instance;
+
+       /* instance members */
+       gchar   *time;
+       gchar   *site;
+       gdouble  location[3];
+       gdouble  rotation[3];
+};
+
+struct _GisViewClass {
+       GObjectClass parent_class;
+       
+       /* class members */
+};
+
+GType gis_view_get_type(void);
+
+/* Methods */
+GisView *gis_view_new();
+
+void gis_view_set_time(GisView *view, const gchar *time);
+gchar *gis_view_get_time(GisView *view);
+
+void gis_view_set_location(GisView *view, gdouble  x, gdouble  y, gdouble  z);
+void gis_view_get_location(GisView *view, gdouble *x, gdouble *y, gdouble *z);
+void gis_view_pan         (GisView *view, gdouble  x, gdouble  y, gdouble  z);
+void gis_view_zoom        (GisView *view, gdouble  scale);
+
+void gis_view_set_rotation(GisView *view, gdouble  x, gdouble  y, gdouble  z);
+void gis_view_get_rotation(GisView *view, gdouble *x, gdouble *y, gdouble *z);
+void gis_view_rotate      (GisView *view, gdouble  x, gdouble  y, gdouble  z);
+
+/* To be deprecated, use {get,set}_location */
+void gis_view_set_site(GisView *view, const gchar *site);
+gchar *gis_view_get_site(GisView *view);
+
+#endif
diff --git a/src/gis-world.c b/src/gis-world.c
new file mode 100644 (file)
index 0000000..4350f3a
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2009 Andy Spencer <spenceal@rose-hulman.edu>
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+
+#include "marshal.h"
+#include "gis-world.h"
+
+/****************
+ * GObject code *
+ ****************/
+/* Constants */
+enum {
+       SIG_REFRESH,
+       SIG_OFFLINE,
+       NUM_SIGNALS,
+};
+static guint signals[NUM_SIGNALS];
+
+/* Class/Object init */
+G_DEFINE_TYPE(GisWorld, gis_world, G_TYPE_OBJECT);
+static void gis_world_init(GisWorld *self)
+{
+       g_debug("GisWorld: init");
+       /* Default values */
+       self->offline = FALSE;
+}
+static void gis_world_dispose(GObject *gobject)
+{
+       g_debug("GisWorld: dispose");
+       /* Drop references to other GObjects */
+       G_OBJECT_CLASS(gis_world_parent_class)->dispose(gobject);
+}
+static void gis_world_finalize(GObject *gobject)
+{
+       g_debug("GisWorld: finalize");
+       GisWorld *self = GIS_WORLD(gobject);
+       G_OBJECT_CLASS(gis_world_parent_class)->finalize(gobject);
+}
+static void gis_world_class_init(GisWorldClass *klass)
+{
+       g_debug("GisWorld: class_init");
+       GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+       gobject_class->dispose      = gis_world_dispose;
+       gobject_class->finalize     = gis_world_finalize;
+       signals[SIG_REFRESH] = g_signal_new(
+                       "refresh",
+                       G_TYPE_FROM_CLASS(gobject_class),
+                       G_SIGNAL_RUN_LAST,
+                       0,
+                       NULL,
+                       NULL,
+                       g_cclosure_marshal_VOID__VOID,
+                       G_TYPE_NONE,
+                       0);
+       signals[SIG_OFFLINE] = g_signal_new(
+                       "offline",
+                       G_TYPE_FROM_CLASS(gobject_class),
+                       G_SIGNAL_RUN_LAST,
+                       0,
+                       NULL,
+                       NULL,
+                       g_cclosure_marshal_VOID__BOOLEAN,
+                       G_TYPE_NONE,
+                       1,
+                       G_TYPE_BOOLEAN);
+}
+
+/* Signal helpers */
+static void _gis_world_emit_refresh(GisWorld *world)
+{
+       g_signal_emit(world, signals[SIG_REFRESH], 0);
+}
+static void _gis_world_emit_offline(GisWorld *world)
+{
+       g_signal_emit(world, signals[SIG_OFFLINE], 0,
+                       world->offline);
+}
+
+
+/***********
+ * Methods *
+ ***********/
+GisWorld *gis_world_new()
+{
+       g_debug("GisWorld: new");
+       return g_object_new(GIS_TYPE_WORLD, NULL);
+}
+
+void gis_world_refresh(GisWorld *world)
+{
+       g_debug("GisWorld: refresh");
+       _gis_world_emit_refresh(world);
+}
+
+void gis_world_set_offline(GisWorld *world, gboolean offline)
+{
+       g_assert(GIS_IS_WORLD(world));
+       g_debug("GisWorld: set_offline - %d", offline);
+       world->offline = offline;
+       _gis_world_emit_offline(world);
+}
+
+gboolean gis_world_get_offline(GisWorld *world)
+{
+       g_assert(GIS_IS_WORLD(world));
+       g_debug("GisWorld: get_offline - %d", world->offline);
+       return world->offline;
+}
diff --git a/src/gis-world.h b/src/gis-world.h
new file mode 100644 (file)
index 0000000..64e52a2
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2009 Andy Spencer <spenceal@rose-hulman.edu>
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIS_WORLD_H__
+#define __GIS_WORLD_H__
+
+#include <glib-object.h>
+
+/* Type macros */
+#define GIS_TYPE_WORLD            (gis_world_get_type())
+#define GIS_WORLD(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),   GIS_TYPE_WORLD, GisWorld))
+#define GIS_IS_WORLD(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),   GIS_TYPE_WORLD))
+#define GIS_WORLD_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST   ((klass), GIS_TYPE_WORLD, GisWorldClass))
+#define GIS_IS_WORLD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE   ((klass), GIS_TYPE_WORLD))
+#define GIS_WORLD_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),   GIS_TYPE_WORLD, GisWorldClass))
+
+typedef struct _GisWorld      GisWorld;
+typedef struct _GisWorldClass GisWorldClass;
+
+struct _GisWorld {
+       GObject parent_instance;
+
+       /* instance members */
+       gboolean offline;
+};
+
+struct _GisWorldClass {
+       GObjectClass parent_class;
+       
+       /* class members */
+};
+
+GType gis_world_get_type(void);
+
+/* Methods */
+GisWorld *gis_world_new();
+
+void gis_world_refresh(GisWorld *world);
+
+void gis_world_set_offline(GisWorld *world, gboolean offline);
+gboolean gis_world_get_offline(GisWorld *world);
+
+#endif
index 82cf38cc56395f61991b69fa906eb130e2591143..b030f04b4d9caeb82aa58c58b97f1ae3b6c1e450 100644 (file)
@@ -15,8 +15,8 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef __SITE_H__
-#define __SITE_H__
+#ifndef __LOCATION_H__
+#define __LOCATION_H__
 
 enum {
        LOCATION_CITY,
index 4923b3732045b6e9a18922f625e056c85268738a..843592c54317804727410cd667bf1abbb37d6b14 100644 (file)
@@ -20,6 +20,8 @@
 #include <gtk/gtkgl.h>
 
 #include "aweather-gui.h"
+#include "gis-view.h"
+#include "gis-world.h"
 #include "plugin-radar.h"
 #include "plugin-ridge.h"
 #include "plugin-example.h"
@@ -36,8 +38,8 @@ static void log_func(const gchar *log_domain, GLogLevelFlags log_level,
 static gulong on_map_id = 0;
 static gboolean on_map(AWeatherGui *gui, GdkEvent *event, gchar *site)
 {
-       AWeatherView *view = aweather_gui_get_view(gui);
-       aweather_view_set_site(view, site);
+       GisView *view = aweather_gui_get_view(gui);
+       gis_view_set_site(view, site);
        g_signal_handler_disconnect(gui, on_map_id);
        return FALSE;
 }
@@ -78,15 +80,20 @@ int main(int argc, char *argv[])
        g_log_set_handler(NULL, G_LOG_LEVEL_MASK, log_func, NULL);
 
        /* Set up AWeather */
+       /* TODO: Figure out a better way to do plugins
+        *    AWeatherPlugin interface for tabs?
+        *    GisPlugin      interface for expose? */
        AWeatherGui  *gui  = aweather_gui_new();
-       AWeatherView *view = aweather_gui_get_view(gui);
-       aweather_view_set_offline(view, opt_offline);
+       GisWorld  *world  = aweather_gui_get_world(gui);
+       GisOpenGL *opengl = aweather_gui_get_opengl(gui);
+       gis_world_set_offline(world, opt_offline);
        on_map_id = g_signal_connect(gui, "map-event", G_CALLBACK(on_map), opt_site);
 
        /* Load plugins */
        aweather_gui_register_plugin(gui, AWEATHER_PLUGIN(aweather_example_new(gui)));
        aweather_gui_register_plugin(gui, AWEATHER_PLUGIN(aweather_ridge_new(gui)));
        aweather_gui_register_plugin(gui, AWEATHER_PLUGIN(aweather_radar_new(gui)));
+       opengl->plugins = gui->plugins;
 
        gtk_widget_show_all(GTK_WIDGET(gui));
        gtk_main();
index f2ae95ed364715bd5bb230829108e2ca6ab0c743..d81f11a8cc654607f68c99f8a1932a609041a36e 100644 (file)
@@ -73,12 +73,12 @@ static void aweather_example_class_init(AWeatherExampleClass *klass)
 /***********
  * Helpers *
  ***********/
-static gboolean rotate(gpointer _example)
+static gboolean rotate(gpointer _self)
 {
-       AWeatherExample *example = _example;
-       if (gtk_toggle_button_get_active(example->button)) {
-               example->rotation += 1.0;
-               aweather_gui_gl_redraw(example->gui);
+       AWeatherExample *self = _self;
+       if (gtk_toggle_button_get_active(self->button)) {
+               self->rotation += 1.0;
+               gis_opengl_redraw(aweather_gui_get_opengl(self->gui));
        }
        return TRUE;
 }
index 23b6d3ab774fdf1976e6c22bba71503ce413e4a8..6ddc4028110a21f961026a44734c463af394a5fc 100644 (file)
@@ -122,7 +122,8 @@ static void bscan_sweep(AWeatherRadar *self, Sweep *sweep, colormap_t *colormap,
 /* Load a sweep as the active texture */
 static void load_sweep(AWeatherRadar *self, Sweep *sweep)
 {
-       aweather_gui_gl_begin(self->gui);
+       GisOpenGL *opengl = aweather_gui_get_opengl(self->gui);
+       gis_opengl_begin(opengl);
        self->cur_sweep = sweep;
        int height, width;
        guint8 *data;
@@ -137,8 +138,8 @@ static void load_sweep(AWeatherRadar *self, Sweep *sweep)
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0,
                        GL_RGBA, GL_UNSIGNED_BYTE, data);
        g_free(data);
-       aweather_gui_gl_redraw(self->gui);
-       aweather_gui_gl_end(self->gui);
+       gis_opengl_redraw(opengl);
+       gis_opengl_end(opengl);
 }
 
 static void load_colormap(AWeatherRadar *self, gchar *table)
@@ -385,8 +386,8 @@ static void update_times_gtk(AWeatherRadar *self, GList *times)
                }
        }
 
-       AWeatherView *view = aweather_gui_get_view(self->gui);
-       aweather_view_set_time(view, last_time);
+       GisView *view = aweather_gui_get_view(self->gui);
+       gis_view_set_time(view, last_time);
 
        g_regex_unref(regex);
        g_list_foreach(times, (GFunc)g_free, NULL);
@@ -409,9 +410,10 @@ static void update_times_online_cb(char *path, gboolean updated, gpointer _self)
 
        update_times_gtk(_self, times);
 }
-static void update_times(AWeatherRadar *self, AWeatherView *view, char *site)
+static void update_times(AWeatherRadar *self, GisView *view, char *site)
 {
-       if (aweather_view_get_offline(view)) {
+       GisWorld *world = aweather_gui_get_world(self->gui);
+       if (gis_world_get_offline(world)) {
                GList *times = NULL;
                gchar *path = g_build_filename(g_get_user_cache_dir(), PACKAGE, "nexrd2", "raw", site, NULL);
                GDir *dir = g_dir_open(path, 0, NULL);
@@ -514,12 +516,12 @@ static void on_sweep_clicked(GtkRadioButton *button, gpointer _self)
        load_sweep   (self, g_object_get_data(G_OBJECT(button), "sweep"));
 }
 
-static void on_time_changed(AWeatherView *view, const char *time, gpointer _self)
+static void on_time_changed(GisView *view, const char *time, gpointer _self)
 {
        AWeatherRadar *self = AWEATHER_RADAR(_self);
        g_debug("AWeatherRadar: on_time_changed - setting time=%s", time);
        // format: http://mesonet.agron.iastate.edu/data/nexrd2/raw/KABR/KABR_20090510_0323
-       char *site = aweather_view_get_site(view);
+       char *site = gis_view_get_site(view);
        char *path = g_strdup_printf("nexrd2/raw/%s/%s_%s", site, site, time);
 
        /* Set up progress bar */
@@ -540,14 +542,14 @@ static void on_time_changed(AWeatherView *view, const char *time, gpointer _self
                RSL_free_radar(self->cur_radar);
        self->cur_radar = NULL;
        self->cur_sweep = NULL;
-       aweather_gui_gl_redraw(self->gui);
+       gis_opengl_redraw(aweather_gui_get_opengl(self->gui));
 
        /* Start loading the new radar */
        if (self->soup) {
                soup_session_abort(self->soup);
                self->soup = NULL;
        }
-       if (aweather_view_get_offline(view)) 
+       if (gis_world_get_offline(aweather_gui_get_world(self->gui))) 
                self->soup = cache_file(nexrad_base, path, AWEATHER_ONCE,
                                cache_chunk_cb, cache_done_cb, self);
        else 
@@ -556,17 +558,18 @@ static void on_time_changed(AWeatherView *view, const char *time, gpointer _self
        g_free(path);
 }
 
-static void on_site_changed(AWeatherView *view, char *site, gpointer _self)
+static void on_site_changed(GisView *view, char *site, gpointer _self)
 {
        AWeatherRadar *self = AWEATHER_RADAR(_self);
        g_debug("AWeatherRadar: on_site_changed - Loading wsr88d list for %s", site);
-       update_times(self, view, site), &time;
+       update_times(self, view, site);
 }
 
-static void on_refresh(AWeatherView *view, gpointer _self)
+static void on_refresh(GisWorld *world, gpointer _self)
 {
        AWeatherRadar *self = AWEATHER_RADAR(_self);
-       char *site = aweather_view_get_site(view);
+       GisView *view = aweather_gui_get_view(AWEATHER_RADAR(_self)->gui);
+       char *site = gis_view_get_site(view);
        update_times(self, view, site);
 }
 
@@ -577,10 +580,9 @@ AWeatherRadar *aweather_radar_new(AWeatherGui *gui)
 {
        g_debug("AWeatherRadar: new");
        AWeatherRadar *self = g_object_new(AWEATHER_TYPE_RADAR, NULL);
-       self->gui = gui;
+       self->gui  = gui;
 
        GtkWidget    *config  = aweather_gui_get_widget(gui, "tabs");
-       AWeatherView *view    = aweather_gui_get_view(gui);
 
        /* Add configuration tab */
        self->config_body = gtk_alignment_new(0, 0, 1, 1);
@@ -589,9 +591,11 @@ AWeatherRadar *aweather_radar_new(AWeatherGui *gui)
        gtk_notebook_prepend_page(GTK_NOTEBOOK(config), self->config_body, gtk_label_new("Radar"));
 
        /* Set up OpenGL Stuff */
-       g_signal_connect(view,    "site-changed", G_CALLBACK(on_site_changed), self);
-       g_signal_connect(view,    "time-changed", G_CALLBACK(on_time_changed), self);
-       g_signal_connect(view,    "refresh",      G_CALLBACK(on_refresh),      self);
+       GisView  *view  = aweather_gui_get_view(gui);
+       GisWorld *world = aweather_gui_get_world(gui);
+       g_signal_connect(view,  "site-changed", G_CALLBACK(on_site_changed), self);
+       g_signal_connect(view,  "time-changed", G_CALLBACK(on_time_changed), self);
+       g_signal_connect(world, "refresh",      G_CALLBACK(on_refresh),      self);
 
        return self;
 }
index 75927d93ed8f72253f2858370cb4b761cc225757..c500dadaa69e5153a478d6f909284ca765879e02 100644 (file)
@@ -110,7 +110,8 @@ static layer_t layers[] = {
  */
 void load_texture(AWeatherRidge *self, layer_t *layer, gchar *filename)
 {
-       aweather_gui_gl_begin(self->gui);
+       GisOpenGL *opengl = aweather_gui_get_opengl(self->gui);
+       gis_opengl_begin(opengl);
 
        /* Load image */
        GError *error = NULL;
@@ -142,12 +143,12 @@ void load_texture(AWeatherRidge *self, layer_t *layer, gchar *filename)
                base);
        g_free(base);
 
-       aweather_gui_gl_end(self->gui);
+       gis_opengl_end(opengl);
 
        g_object_unref(pixbuf);
 
        /* Redraw */
-       aweather_gui_gl_redraw(self->gui);
+       gis_opengl_redraw(opengl);
 }
 
 
@@ -168,7 +169,7 @@ void cached_cb(gchar *filename, gboolean updated, gpointer _udata)
 /*************
  * callbacks *
  *************/
-static void on_site_changed(AWeatherView *view, gchar *site, AWeatherRidge *self)
+static void on_site_changed(GisView *view, gchar *site, AWeatherRidge *self)
 {
        g_debug("AWeatherRidge: on_site_changed - site=%s", site);
        for (int i = 0; i < LAYER_COUNT; i++) {
@@ -183,11 +184,11 @@ static void on_site_changed(AWeatherView *view, gchar *site, AWeatherRidge *self
        }
 }
 
-void toggle_layer(GtkToggleButton *check, AWeatherGui *gui)
+void toggle_layer(GtkToggleButton *check, AWeatherRidge *self)
 {
        layer_t *layer = g_object_get_data(G_OBJECT(check), "layer");
        layer->enabled = gtk_toggle_button_get_active(check);
-       aweather_gui_gl_redraw(gui);
+       gis_opengl_redraw(aweather_gui_get_opengl(self->gui));
 }
 
 /***********
@@ -195,10 +196,10 @@ void toggle_layer(GtkToggleButton *check, AWeatherGui *gui)
  ***********/
 AWeatherRidge *aweather_ridge_new(AWeatherGui *gui)
 {
-       AWeatherRidge *ridge = g_object_new(AWEATHER_TYPE_RIDGE, NULL);
-       ridge->gui = gui;
+       AWeatherRidge *self = g_object_new(AWEATHER_TYPE_RIDGE, NULL);
+       self->gui = gui;
 
-       AWeatherView *view    = aweather_gui_get_view(gui);
+       GisView *view    = aweather_gui_get_view(gui);
        GtkWidget    *drawing = aweather_gui_get_widget(gui, "drawing");
        GtkWidget    *config  = aweather_gui_get_widget(gui, "tabs");
 
@@ -211,14 +212,14 @@ AWeatherRidge *aweather_ridge_new(AWeatherGui *gui)
                gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), layers[i].enabled);
                gtk_box_pack_start(GTK_BOX(hbox), check, FALSE, TRUE, 0);
                g_object_set_data(G_OBJECT(check), "layer", &layers[i]);
-               g_signal_connect(check, "toggled", G_CALLBACK(toggle_layer), gui);
+               g_signal_connect(check, "toggled", G_CALLBACK(toggle_layer), self);
        }
        gtk_container_add(GTK_CONTAINER(body), hbox);
        gtk_notebook_append_page(GTK_NOTEBOOK(config), body, tab);
 
-       g_signal_connect(view, "site-changed", G_CALLBACK(on_site_changed),  ridge);
+       g_signal_connect(view, "site-changed", G_CALLBACK(on_site_changed), self);
 
-       return ridge;
+       return self;
 }
 
 static void aweather_ridge_expose(AWeatherPlugin *_ridge)