*/
#include "viking.h"
#include "background.h"
+#include "acquire.h"
+#include "datasources.h"
#define VIKING_TITLE " - Viking " VIKING_VERSION " " VIKING_VERSION_NAME " " VIKING_URL
+#include <glib/gprintf.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
-
+#include <glib/gprintf.h>
#ifdef WINDOWS
/* TODO IMPORTANT: mkdir for windows header? is it called 'mkdir' */
#define make_dir(dir) mkdir(dir)
GtkItemFactory *item_factory;
+ /* ruler variables */
VikCoord oldcoord;
gboolean has_oldcoord;
+
+
guint current_tool;
guint16 tool_layer_id;
vik_viewport_draw_scale ( vw->viking_vvp );
}
+static void draw_ruler(VikViewport *vvp, GdkDrawable *d, GdkGC *gc, gint x1, gint y1, gint x2, gint y2, gdouble distance)
+{
+ PangoFontDescription *pfd;
+ PangoLayout *pl;
+ gchar str[128];
+ GdkGC *labgc = vik_viewport_new_gc ( vvp, "#cccccc", 1);
+ GdkGC *thickgc = gdk_gc_new(d);
+
+ gdouble len = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
+ gdouble dx = (x2-x1)/len*10;
+ gdouble dy = (y2-y1)/len*10;
+ gdouble c = cos(15.0 * M_PI/180.0);
+ gdouble s = sin(15.0 * M_PI/180.0);
+ gdouble angle;
+ gdouble baseangle = 0;
+ gint i;
+
+ /* draw line with arrow ends */
+ {
+ gint tmp_x1=x1, tmp_y1=y1, tmp_x2=x2, tmp_y2=y2;
+ a_viewport_clip_line(&tmp_x1, &tmp_y1, &tmp_x2, &tmp_y2);
+ gdk_draw_line(d, gc, tmp_x1, tmp_y1, tmp_x2, tmp_y2);
+ }
+
+ a_viewport_clip_line(&x1, &y1, &x2, &y2);
+ gdk_draw_line(d, gc, x1, y1, x2, y2);
+
+ gdk_draw_line(d, gc, x1 - dy, y1 + dx, x1 + dy, y1 - dx);
+ gdk_draw_line(d, gc, x2 - dy, y2 + dx, x2 + dy, y2 - dx);
+ gdk_draw_line(d, gc, x2, y2, x2 - (dx * c + dy * s), y2 - (dy * c - dx * s));
+ gdk_draw_line(d, gc, x2, y2, x2 - (dx * c - dy * s), y2 - (dy * c + dx * s));
+ gdk_draw_line(d, gc, x1, y1, x1 + (dx * c + dy * s), y1 + (dy * c - dx * s));
+ gdk_draw_line(d, gc, x1, y1, x1 + (dx * c - dy * s), y1 + (dy * c + dx * s));
+
+ /* draw compass */
+#define CR 80
+#define CW 4
+ angle = atan2(dy, dx) + M_PI_2;
+
+ if ( vik_viewport_get_drawmode ( vvp ) == VIK_VIEWPORT_DRAWMODE_UTM) {
+ VikCoord test;
+ struct LatLon ll;
+ struct UTM u;
+ gint tx, ty;
+
+ vik_viewport_screen_to_coord ( vvp, x1, y1, &test );
+ vik_coord_to_latlon ( &test, &ll );
+ ll.lat += vik_viewport_get_ympp ( vvp ) * vik_viewport_get_height ( vvp ) / 11000.0; // about 11km per degree latitude
+ a_coords_latlon_to_utm ( &ll, &u );
+ vik_coord_load_from_utm ( &test, VIK_VIEWPORT_DRAWMODE_UTM, &u );
+ vik_viewport_coord_to_screen ( vvp, &test, &tx, &ty );
+
+ baseangle = M_PI - atan2(tx-x1, ty-y1);
+ angle -= baseangle;
+ }
+
+ if (angle<0)
+ angle+=2*M_PI;
+ if (angle>2*M_PI)
+ angle-=2*M_PI;
+
+ {
+ GdkColor color;
+ gdk_gc_copy(thickgc, gc);
+ gdk_gc_set_line_attributes(thickgc, CW, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
+ gdk_color_parse("#2255cc", &color);
+ gdk_gc_set_rgb_fg_color(thickgc, &color);
+ }
+ gdk_draw_arc (d, thickgc, FALSE, x1-CR+CW/2, y1-CR+CW/2, 2*CR-CW, 2*CR-CW, (90 - baseangle*180/M_PI)*64, -angle*180/M_PI*64);
+
+
+ gdk_gc_copy(thickgc, gc);
+ gdk_gc_set_line_attributes(thickgc, 2, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
+ for (i=0; i<180; i++) {
+ c = cos(i*M_PI/90.0 + baseangle);
+ s = sin(i*M_PI/90.0 + baseangle);
+
+ if (i%5) {
+ gdk_draw_line (d, gc, x1 + CR*c, y1 + CR*s, x1 + (CR+CW)*c, y1 + (CR+CW)*s);
+ } else {
+ gdouble ticksize = 2*CW;
+ gdk_draw_line (d, thickgc, x1 + (CR-CW)*c, y1 + (CR-CW)*s, x1 + (CR+ticksize)*c, y1 + (CR+ticksize)*s);
+ }
+ }
+
+ gdk_draw_arc (d, gc, FALSE, x1-CR, y1-CR, 2*CR, 2*CR, 0, 64*360);
+ gdk_draw_arc (d, gc, FALSE, x1-CR-CW, y1-CR-CW, 2*(CR+CW), 2*(CR+CW), 0, 64*360);
+ gdk_draw_arc (d, gc, FALSE, x1-CR+CW, y1-CR+CW, 2*(CR-CW), 2*(CR-CW), 0, 64*360);
+ c = (CR+CW*2)*cos(baseangle);
+ s = (CR+CW*2)*sin(baseangle);
+ gdk_draw_line (d, gc, x1-c, y1-s, x1+c, y1+s);
+ gdk_draw_line (d, gc, x1+s, y1-c, x1-s, y1+c);
+
+ /* draw labels */
+#define LABEL(x, y, w, h) { \
+ gdk_draw_rectangle(d, labgc, TRUE, (x)-2, (y)-1, (w)+4, (h)+1); \
+ gdk_draw_rectangle(d, gc, FALSE, (x)-2, (y)-1, (w)+4, (h)+1); \
+ gdk_draw_layout(d, gc, (x), (y), pl); }
+ {
+ gint wd, hd, xd, yd;
+ gint wb, hb, xb, yb;
+
+ pl = gtk_widget_create_pango_layout (GTK_WIDGET(vvp), NULL);
+
+ pfd = pango_font_description_from_string ("Sans 8"); // FIXME: settable option? global variable?
+ pango_layout_set_font_description (pl, pfd);
+ pango_font_description_free (pfd);
+
+ pango_layout_set_text(pl, "N", -1);
+ gdk_draw_layout(d, gc, x1-5, y1-CR-3*CW-8, pl);
+
+ /* draw label with distance */
+ if (distance >= 1000 && distance < 100000) {
+ g_sprintf(str, "%3.2f km", distance/1000.0);
+ } else if (distance < 1000) {
+ g_sprintf(str, "%d m", (int)distance);
+ } else {
+ g_sprintf(str, "%d km", (int)distance/1000);
+ }
+ pango_layout_set_text(pl, str, -1);
+
+ pango_layout_get_pixel_size ( pl, &wd, &hd );
+ if (dy>0) {
+ xd = (x1+x2)/2 + dy;
+ yd = (y1+y2)/2 - hd/2 - dx;
+ } else {
+ xd = (x1+x2)/2 - dy;
+ yd = (y1+y2)/2 - hd/2 + dx;
+ }
+
+ if ( xd < -5 || yd < -5 || xd > vik_viewport_get_width(vvp)+5 || yd > vik_viewport_get_height(vvp)+5 ) {
+ xd = x2 + 10;
+ yd = y2 - 5;
+ }
+
+ LABEL(xd, yd, wd, hd);
+
+ /* draw label with bearing */
+ g_sprintf(str, "%3.1f°", angle*180.0/M_PI);
+ pango_layout_set_text(pl, str, -1);
+ pango_layout_get_pixel_size ( pl, &wb, &hb );
+ xb = x1 + CR*cos(angle-M_PI_2);
+ yb = y1 + CR*sin(angle-M_PI_2);
+
+ if ( xb < -5 || yb < -5 || xb > vik_viewport_get_width(vvp)+5 || yb > vik_viewport_get_height(vvp)+5 ) {
+ xb = x2 + 10;
+ yb = y2 + 10;
+ }
+
+ {
+ GdkRectangle r1 = {xd-2, yd-1, wd+4, hd+1}, r2 = {xb-2, yb-1, wb+4, hb+1};
+ if (gdk_rectangle_intersect(&r1, &r2, &r2)) {
+ xb = xd + wd + 5;
+ }
+ }
+ LABEL(xb, yb, wb, hb);
+ }
+#undef LABEL
+
+ g_object_unref ( G_OBJECT ( pl ) );
+ g_object_unref ( G_OBJECT ( labgc ) );
+ g_object_unref ( G_OBJECT ( thickgc ) );
+}
+
+gboolean draw_buf_done = TRUE;
+
+static gboolean draw_buf(gpointer data)
+{
+ gpointer *pass_along = data;
+ gdk_threads_enter();
+ gdk_draw_drawable (pass_along[0], pass_along[1],
+ pass_along[2], 0, 0, 0, 0, -1, -1);
+ gdk_threads_leave();
+ draw_buf_done = TRUE;
+ return FALSE;
+}
+
static void draw_mouse_motion (VikWindow *vw, GdkEventMotion *event)
{
+ VikViewport *vvp = vw->viking_vvp;
static VikCoord coord;
static struct UTM utm;
static struct LatLon ll;
vik_coord_to_utm ( &coord, &utm );
a_coords_utm_to_latlon ( &utm, &ll );
+ if ( vw->current_tool == TOOL_RULER )
+ {
+ struct LatLon ll;
+ VikCoord coord;
+ gchar *temp;
+
+ if ( vw->has_oldcoord ) {
+ int oldx, oldy, w1, h1, w2, h2;
+ static GdkPixmap *buf = NULL;
+ w1 = vik_viewport_get_width(vvp);
+ h1 = vik_viewport_get_height(vvp);
+ if (!buf) {
+ buf = gdk_pixmap_new ( GTK_WIDGET(vvp)->window, w1, h1, -1 );
+ }
+ gdk_drawable_get_size(buf, &w2, &h2);
+ if (w1 != w2 || h1 != h2) {
+ g_object_unref ( G_OBJECT ( buf ) );
+ buf = gdk_pixmap_new ( GTK_WIDGET(vvp)->window, w1, h1, -1 );
+ }
+
+ vik_viewport_screen_to_coord ( vvp, (gint) event->x, (gint) event->y, &coord );
+ vik_coord_to_latlon ( &coord, &ll );
+ vik_viewport_coord_to_screen ( vvp, &vw->oldcoord, &oldx, &oldy );
+
+ gdk_draw_drawable (buf, GTK_WIDGET(vvp)->style->black_gc,
+ vik_viewport_get_pixmap(vvp), 0, 0, 0, 0, -1, -1);
+ draw_ruler(vvp, buf, GTK_WIDGET(vvp)->style->black_gc, oldx, oldy, event->x, event->y, vik_coord_diff( &coord, &(vw->oldcoord)) );
+ if (draw_buf_done) {
+ static gpointer pass_along[3];
+ pass_along[0] = GTK_WIDGET(vvp)->window;
+ pass_along[1] = GTK_WIDGET(vvp)->style->black_gc;
+ pass_along[2] = buf;
+ g_idle_add (draw_buf, pass_along);
+ draw_buf_done = FALSE;
+ }
+
+ temp = g_strdup_printf ( "%f %f DIFF %f meters", ll.lat, ll.lon, vik_coord_diff( &coord, &(vw->oldcoord) ) );
+ vik_statusbar_set_message ( vw->viking_vs, 3, temp );
+ g_free ( temp );
+ }
+ }
+
g_snprintf ( pointer_buf, 36, "Cursor: %f %f", ll.lat, ll.lon );
if ( vw->pan_x != -1 ) {
{
vik_viewport_screen_to_coord ( vw->viking_vvp, (gint) event->x, (gint) event->y, &coord );
vik_coord_to_latlon ( &coord, &ll );
- if ( vw->has_oldcoord )
+ if ( vw->has_oldcoord ) {
temp = g_strdup_printf ( "%f %f DIFF %f meters", ll.lat, ll.lon, vik_coord_diff( &coord, &(vw->oldcoord) ) );
- else
+ vw->has_oldcoord = FALSE;
+ }
+ else {
temp = g_strdup_printf ( "%f %f", ll.lat, ll.lon );
+ vw->has_oldcoord = TRUE;
+ }
vik_statusbar_set_message ( vw->viking_vs, 3, temp );
g_free ( temp );
vw->oldcoord = coord;
/* we don't use anything else so far */
- vw->has_oldcoord = TRUE;
}
else
{
}
}
+static void acquire_from_gps ( GtkAction *a, VikWindow *vw )
+{
+ a_acquire(vw, vw->viking_vlp, vw->viking_vvp, &vik_datasource_gps_interface );
+}
+
+static void acquire_from_google ( GtkAction *a, VikWindow *vw )
+{
+ a_acquire(vw, vw->viking_vlp, vw->viking_vvp, &vik_datasource_google_interface );
+}
+
+static void acquire_from_gc ( GtkAction *a, VikWindow *vw )
+{
+ a_acquire(vw, vw->viking_vlp, vw->viking_vvp, &vik_datasource_gc_interface );
+}
+
static void clear_cb ( GtkAction *a, VikWindow *vw )
{
vik_layers_panel_clear ( vw->viking_vlp );
{ "New", GTK_STOCK_NEW, "_New", "<control>N", "New file", (GCallback)newwindow_cb },
{ "Open", GTK_STOCK_OPEN, "_Open", "<control>O", "Open a file", (GCallback)load_file },
{ "Append", GTK_STOCK_ADD, "A_ppend File", NULL, "Append data from a different file", (GCallback)load_file },
+ { "Acquire", NULL, "A_cquire", 0, 0, 0 },
+ { "AcquireGPS", NULL, "From _GPS", NULL, "Transfer data from a GPS device", (GCallback)acquire_from_gps },
+ { "AcquireGoogle", NULL, "Google _Directions", NULL, "Get driving directions from Google", (GCallback)acquire_from_google },
+ { "AcquireGC", NULL, "Geo_caches", NULL, "Get Geocaches from geocaching.com", (GCallback)acquire_from_gc },
{ "Save", GTK_STOCK_SAVE, "_Save", "<control>S", "Save the file", (GCallback)save_file },
{ "SaveAs", GTK_STOCK_SAVE_AS, "Save _As", NULL, "Save the file under different name", (GCallback)save_file_as },
{ "GenImg", GTK_STOCK_CLEAR, "_Generate Image File", NULL, "Save a snapshot of the workspace into a file", (GCallback)draw_to_image_file_cb },
}
-#include "icons.h"
+#include "icons/icons.h"
static struct {
const GdkPixdata *data;
gchar *stock_id;