2 * Copyright (C) 2009 Andy Spencer <spenceal@rose-hulman.edu>
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <gdk/gdkkeysyms.h>
22 #include "gis-marshal.h"
23 #include "gis-viewer.h"
37 static guint signals[NUM_SIGNALS];
44 static void _gis_viewer_fix_location(GisViewer *self)
46 while (self->location[0] < -90) self->location[0] += 180;
47 while (self->location[0] > 90) self->location[0] -= 180;
48 while (self->location[1] < -180) self->location[1] += 360;
49 while (self->location[1] > 180) self->location[1] -= 360;
50 self->location[2] = ABS(self->location[2]);
54 static void _gis_viewer_emit_location_changed(GisViewer *self)
56 g_signal_emit(self, signals[SIG_LOCATION_CHANGED], 0,
61 static void _gis_viewer_emit_rotation_changed(GisViewer *self)
63 g_signal_emit(self, signals[SIG_ROTATION_CHANGED], 0,
68 static void _gis_viewer_emit_time_changed(GisViewer *self)
70 g_signal_emit(self, signals[SIG_TIME_CHANGED], 0,
73 static void _gis_viewer_emit_refresh(GisViewer *self)
75 g_signal_emit(self, signals[SIG_REFRESH], 0);
77 static void _gis_viewer_emit_offline(GisViewer *self)
79 g_signal_emit(self, signals[SIG_OFFLINE], 0,
86 static gboolean on_button_press(GisViewer *self, GdkEventButton *event, gpointer _)
88 g_debug("GisViewer: on_button_press - Grabbing focus");
89 gtk_widget_grab_focus(GTK_WIDGET(self));
92 static gboolean on_key_press(GisViewer *self, GdkEventKey *event, gpointer _)
94 g_debug("GisViewer: on_key_press - key=%x, state=%x, plus=%x",
95 event->keyval, event->state, GDK_plus);
97 double lat, lon, elev, pan;
98 gis_viewer_get_location(self, &lat, &lon, &elev);
99 pan = MIN(elev/(EARTH_R/2), 30);
100 guint kv = event->keyval;
102 if (kv == GDK_Left || kv == GDK_h) gis_viewer_pan(self, 0, -pan, 0);
103 else if (kv == GDK_Down || kv == GDK_j) gis_viewer_pan(self, -pan, 0, 0);
104 else if (kv == GDK_Up || kv == GDK_k) gis_viewer_pan(self, pan, 0, 0);
105 else if (kv == GDK_Right || kv == GDK_l) gis_viewer_pan(self, 0, pan, 0);
106 else if (kv == GDK_minus || kv == GDK_o) gis_viewer_zoom(self, 10./9);
107 else if (kv == GDK_plus || kv == GDK_i) gis_viewer_zoom(self, 9./10);
108 else if (kv == GDK_H) gis_viewer_rotate(self, 0, 0, -2);
109 else if (kv == GDK_J) gis_viewer_rotate(self, 2, 0, 0);
110 else if (kv == GDK_K) gis_viewer_rotate(self, -2, 0, 0);
111 else if (kv == GDK_L) gis_viewer_rotate(self, 0, 0, 2);
114 static void on_view_changed(GisViewer *self,
115 gdouble _1, gdouble _2, gdouble _3)
117 gtk_widget_queue_draw(GTK_WIDGET(self));
123 void gis_viewer_set_time(GisViewer *self, const char *time)
125 g_assert(GIS_IS_VIEWER(self));
126 g_debug("GisViewer: set_time - time=%s", time);
128 self->time = g_strdup(time);
129 _gis_viewer_emit_time_changed(self);
132 gchar *gis_viewer_get_time(GisViewer *self)
134 g_assert(GIS_IS_VIEWER(self));
135 g_debug("GisViewer: get_time");
139 void gis_viewer_set_location(GisViewer *self, gdouble lat, gdouble lon, gdouble elev)
141 g_assert(GIS_IS_VIEWER(self));
142 g_debug("GisViewer: set_location");
143 self->location[0] = lat;
144 self->location[1] = lon;
145 self->location[2] = elev;
146 _gis_viewer_fix_location(self);
147 _gis_viewer_emit_location_changed(self);
150 void gis_viewer_get_location(GisViewer *self, gdouble *lat, gdouble *lon, gdouble *elev)
152 g_assert(GIS_IS_VIEWER(self));
153 //g_debug("GisViewer: get_location");
154 *lat = self->location[0];
155 *lon = self->location[1];
156 *elev = self->location[2];
159 void gis_viewer_pan(GisViewer *self, gdouble lat, gdouble lon, gdouble elev)
161 g_assert(GIS_IS_VIEWER(self));
162 g_debug("GisViewer: pan - lat=%8.3f, lon=%8.3f, elev=%8.3f", lat, lon, elev);
163 self->location[0] += lat;
164 self->location[1] += lon;
165 self->location[2] += elev;
166 _gis_viewer_fix_location(self);
167 _gis_viewer_emit_location_changed(self);
170 void gis_viewer_zoom(GisViewer *self, gdouble scale)
172 g_assert(GIS_IS_VIEWER(self));
173 g_debug("GisViewer: zoom");
174 self->location[2] *= scale;
175 _gis_viewer_emit_location_changed(self);
178 void gis_viewer_set_rotation(GisViewer *self, gdouble x, gdouble y, gdouble z)
180 g_assert(GIS_IS_VIEWER(self));
181 g_debug("GisViewer: set_rotation");
182 self->rotation[0] = x;
183 self->rotation[1] = y;
184 self->rotation[2] = z;
185 _gis_viewer_emit_rotation_changed(self);
188 void gis_viewer_get_rotation(GisViewer *self, gdouble *x, gdouble *y, gdouble *z)
190 g_assert(GIS_IS_VIEWER(self));
191 g_debug("GisViewer: get_rotation");
192 *x = self->rotation[0];
193 *y = self->rotation[1];
194 *z = self->rotation[2];
197 void gis_viewer_rotate(GisViewer *self, gdouble x, gdouble y, gdouble z)
199 g_assert(GIS_IS_VIEWER(self));
200 g_debug("GisViewer: rotate - x=%.0f, y=%.0f, z=%.0f", x, y, z);
201 self->rotation[0] += x;
202 self->rotation[1] += y;
203 self->rotation[2] += z;
204 _gis_viewer_emit_rotation_changed(self);
207 void gis_viewer_refresh(GisViewer *self)
209 g_debug("GisViewer: refresh");
210 _gis_viewer_emit_refresh(self);
213 void gis_viewer_set_offline(GisViewer *self, gboolean offline)
215 g_assert(GIS_IS_VIEWER(self));
216 g_debug("GisViewer: set_offline - %d", offline);
217 self->offline = offline;
218 _gis_viewer_emit_offline(self);
221 gboolean gis_viewer_get_offline(GisViewer *self)
223 g_assert(GIS_IS_VIEWER(self));
224 g_debug("GisViewer: get_offline - %d", self->offline);
225 return self->offline;
228 /* To be implemented by subclasses */
229 void gis_viewer_center_position(GisViewer *self,
230 gdouble lat, gdouble lon, gdouble elev)
232 GisViewerClass *klass = GIS_VIEWER_GET_CLASS(self);
233 if (!klass->center_position)
234 g_warning("GisViewer: center_position - Unimplemented");
235 klass->center_position(self, lat, lon, elev);
238 void gis_viewer_project(GisViewer *self,
239 gdouble lat, gdouble lon, gdouble elev,
240 gdouble *px, gdouble *py, gdouble *pz)
242 GisViewerClass *klass = GIS_VIEWER_GET_CLASS(self);
244 g_warning("GisViewer: project - Unimplemented");
245 klass->project(self, lat, lon, elev, px, py, pz);
248 void gis_viewer_clear_height_func(GisViewer *self)
250 GisViewerClass *klass = GIS_VIEWER_GET_CLASS(self);
251 if (!klass->clear_height_func)
252 g_warning("GisViewer: clear_height_func - Unimplemented");
253 klass->clear_height_func(self);
256 void gis_viewer_set_height_func(GisViewer *self, GisTile *tile,
257 GisHeightFunc height_func, gpointer user_data,
260 GisViewerClass *klass = GIS_VIEWER_GET_CLASS(self);
261 if (!klass->set_height_func)
262 g_warning("GisViewer: set_height_func - Unimplemented");
263 klass->set_height_func(self, tile, height_func, user_data, update);
266 void gis_viewer_render_tile(GisViewer *self, GisTile *tile)
268 GisViewerClass *klass = GIS_VIEWER_GET_CLASS(self);
269 if (!klass->render_tile)
270 g_warning("GisViewer: render_tile - Unimplemented");
271 klass->render_tile(self, tile);
274 void gis_viewer_render_tiles(GisViewer *self, GisTile *root)
276 GisViewerClass *klass = GIS_VIEWER_GET_CLASS(self);
277 if (!klass->render_tiles)
278 g_warning("GisViewer: render_tiles - Unimplemented");
279 klass->render_tiles(self, root);
282 void gis_viewer_begin(GisViewer *self)
284 GisViewerClass *klass = GIS_VIEWER_GET_CLASS(self);
286 g_warning("GisViewer: begin - Unimplemented");
290 void gis_viewer_end(GisViewer *self)
292 GisViewerClass *klass = GIS_VIEWER_GET_CLASS(self);
294 g_warning("GisViewer: end - Unimplemented");
298 gpointer gis_viewer_add(GisViewer *self, GisObject *object,
299 gint level, gboolean sort)
301 GisViewerClass *klass = GIS_VIEWER_GET_CLASS(self);
303 g_warning("GisViewer: add - Unimplemented");
304 return klass->add(self, object, level, sort);
307 void gis_viewer_remove(GisViewer *self, gpointer ref)
309 GisViewerClass *klass = GIS_VIEWER_GET_CLASS(self);
311 g_warning("GisViewer: remove - Unimplemented");
312 klass->remove(self, ref);
318 G_DEFINE_ABSTRACT_TYPE(GisViewer, gis_viewer, GTK_TYPE_DRAWING_AREA);
319 static void gis_viewer_init(GisViewer *self)
321 g_debug("GisViewer: init");
323 self->time = g_strdup("");
324 self->location[0] = 40;
325 self->location[1] = -100;
326 self->location[2] = 1.5*EARTH_R;
327 self->rotation[0] = 0;
328 self->rotation[1] = 0;
329 self->rotation[2] = 0;
331 g_signal_connect(self, "key-press-event", G_CALLBACK(on_key_press), NULL);
332 g_signal_connect(self, "button-press-event", G_CALLBACK(on_button_press), NULL);
334 g_signal_connect(self, "location-changed", G_CALLBACK(on_view_changed), NULL);
335 g_signal_connect(self, "rotation-changed", G_CALLBACK(on_view_changed), NULL);
337 static void gis_viewer_finalize(GObject *gobject)
339 g_debug("GisViewer: finalize");
340 GisViewer *self = GIS_VIEWER(gobject);
342 G_OBJECT_CLASS(gis_viewer_parent_class)->finalize(gobject);
344 static void gis_viewer_class_init(GisViewerClass *klass)
346 g_debug("GisViewer: class_init");
347 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
348 gobject_class->finalize = gis_viewer_finalize;
349 signals[SIG_TIME_CHANGED] = g_signal_new(
351 G_TYPE_FROM_CLASS(gobject_class),
356 g_cclosure_marshal_VOID__STRING,
360 signals[SIG_LOCATION_CHANGED] = g_signal_new(
362 G_TYPE_FROM_CLASS(gobject_class),
367 gis_cclosure_marshal_VOID__DOUBLE_DOUBLE_DOUBLE,
373 signals[SIG_ROTATION_CHANGED] = g_signal_new(
375 G_TYPE_FROM_CLASS(gobject_class),
380 gis_cclosure_marshal_VOID__DOUBLE_DOUBLE_DOUBLE,
386 signals[SIG_REFRESH] = g_signal_new(
388 G_TYPE_FROM_CLASS(gobject_class),
393 g_cclosure_marshal_VOID__VOID,
396 signals[SIG_OFFLINE] = g_signal_new(
398 G_TYPE_FROM_CLASS(gobject_class),
403 g_cclosure_marshal_VOID__BOOLEAN,