AWeather and putting it in a Gis prefix.
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 \
#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,
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();
}
/*************
* 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)
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;
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;
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;
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;
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;
}
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);
}
}
- 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);
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);
}
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);
}
#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 */
GtkWindow parent_instance;
/* instance members */
- AWeatherView *view;
- GtkBuilder *builder;
- GList *plugins;
+ GisWorld *world;
+ GisView *view;
+ GisOpenGL *opengl;
+ GtkBuilder *builder;
+ GList *plugins;
};
struct _AWeatherGuiClass {
/* 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
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-/*
- * 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
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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
* 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,
#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"
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;
}
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();
/***********
* 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;
}
/* 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;
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)
}
}
- 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);
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);
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 */
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
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);
}
{
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);
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;
}
*/
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;
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);
}
/*************
* 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++) {
}
}
-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));
}
/***********
***********/
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");
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)