#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#include <math.h>
#include <libintl.h>
#include <glib.h>
#include "config.h"
#define STATE_SELECTED 2
#define STATE_HIGHLIGHTED 4
#define STATE_SENSITIVE 8
+#define STATE_EDIT 16
enum widget_type {
widget_box=1,
struct widget root;
struct widget *highlighted;
struct widget *highlighted_menu;
+ struct pcoord click, vehicle;
};
static void gui_internal_widget_render(struct gui_priv *this, struct widget *w);
return NULL;
}
+
static struct graphics_image *
image_new_o(struct gui_priv *this, char *name)
{
return image_new_scaled(this, name, this->icon_l, this->icon_l);
}
+static char *
+coordinates(struct pcoord *pc, char sep)
+{
+ struct coord_geo g;
+ struct coord c;
+ char latc='N',lngc='W';
+ int lat_deg,lat_min,lat_sec;
+ int lng_deg,lng_min,lng_sec;
+ c.x=pc->x;
+ c.y=pc->y;
+ transform_to_geo(pc->pro, &c, &g);
+ if (g.lat < 0) {
+ g.lat=-g.lat;
+ latc='S';
+ }
+ if (g.lng < 0) {
+ g.lng=-g.lng;
+ lngc='E';
+ }
+ lat_deg=g.lat;
+ lat_min=fmod(g.lat*60,60);
+ lat_sec=fmod(g.lat*3600,60);
+ lng_deg=g.lng;
+ lng_min=fmod(g.lng*60,60);
+ lng_sec=fmod(g.lng*3600,60);
+ return g_strdup_printf("%d°%d'%d\" %c%c%d°%d'%d\" %c",lat_deg,lat_min,lat_sec,latc,sep,lng_deg,lng_min,lng_sec,lngc);
+}
+
static void
gui_internal_background_render(struct gui_priv *this, struct widget *w)
{
GList *l=wi->children;
struct widget *ret,*child;
- if (wi->p.x > p->x || wi->p.y > p->y || wi->p.x + wi->w < p->x || wi->p.y + wi->h < p->y) {
+ if (p && (wi->p.x > p->x || wi->p.y > p->y || wi->p.x + wi->w < p->x || wi->p.y + wi->h < p->y))
return NULL;
- }
- if (wi->state & flags) {
+ if (wi->state & flags)
return wi;
- }
while (l) {
child=l->data;
ret=gui_internal_find_widget(child, p, flags);
}
static void
+gui_internal_cmd_point(struct gui_priv *this, struct widget *wm)
+{
+ struct widget *wb,*w;
+ struct pcoord *pc;
+ char *coord;
+
+ pc=&this->click;
+ wb=gui_internal_menu(this, "Map Point");
+ w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
+ gui_internal_widget_append(wb, w);
+ coord=coordinates(pc, ' ');
+ gui_internal_widget_append(w, gui_internal_label_new(this, coord));
+ g_free(coord);
+ gui_internal_widget_append(w,
+ gui_internal_button_new_with_callback(this, "Set as destination",
+ image_new_xs(this, "gui_active"), gravity_left_center|orientation_horizontal|flags_fill,
+ gui_internal_cmd_set_destination, wm));
+ gui_internal_menu_render(this);
+
+}
+static void
gui_internal_cmd_bookmarks(struct gui_priv *this, struct widget *wm)
{
struct attr attr,mattr;
gui_internal_menu_render(this);
}
+static void gui_internal_keypress_do(struct gui_priv *this, int key)
+{
+ struct widget *wi,*menu;
+ int len=0;
+ char *text;
+
+ menu=g_list_last(this->root.children)->data;
+ wi=gui_internal_find_widget(menu, NULL, STATE_EDIT);
+ if (wi) {
+ if (key == NAVIT_KEY_BACKSPACE && wi->text && (len=strlen(wi->text))) {
+ wi->text[--len]=' ';
+ text=g_strdup_printf("%s ", wi->text);
+ } else
+ text=g_strdup_printf("%s%c", wi->text ? wi->text : "", key);
+ g_free(wi->text);
+ wi->text=text;
+ gui_internal_widget_render(this, wi);
+ if (key == NAVIT_KEY_BACKSPACE) {
+ wi->text[len]='\0';
+ gui_internal_widget_render(this, wi);
+ }
+ }
+}
+
+
static void
gui_internal_cmd_keypress(struct gui_priv *this, struct widget *wm)
{
- dbg(0,"enter\n");
+ gui_internal_keypress_do(this, (int) wm->data);
}
static void
gui_internal_cmd_town(struct gui_priv *this, struct widget *wm)
{
- struct widget *wb,*wkbd,*wk,*w,*wr;
+ struct widget *wb,*wkbd,*wk,*w,*wr,*we;
int i;
wb=gui_internal_menu(this, "Town");
w=gui_internal_box_new(this, gravity_center|orientation_vertical|flags_expand|flags_fill);
gui_internal_widget_append(wb, w);
- wr=gui_internal_box_new(this, gravity_center|orientation_vertical|flags_expand|flags_fill);
+ wr=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill);
gui_internal_widget_append(w, wr);
+ we=gui_internal_box_new(this, gravity_left_center|orientation_horizontal|flags_fill);
+ gui_internal_widget_append(wr, we);
+ gui_internal_widget_append(we, wk=gui_internal_label_new(this, NULL));
+ wk->state |= STATE_EDIT;
+ wk->background=this->background;
+ wk->flags |= flags_expand|flags_fill;
wkbd=gui_internal_box_new(this, gravity_center|orientation_horizontal_vertical|flags_fill);
wkbd->cols=7;
gui_internal_widget_append(w, wkbd);
gui_internal_widget_append(wkbd, wk=gui_internal_button_new_with_callback(this, text,
NULL, gravity_center|orientation_vertical,
gui_internal_cmd_keypress, NULL));
+ wk->data=text[0];
wk->background=this->background;
wk->bl=8;
wk->br=8;
static void
gui_internal_cmd_actions(struct gui_priv *this, struct widget *wm)
{
- struct widget *w;
+ struct widget *w,*wc;
+ char *coord;
w=gui_internal_menu(this, "Actions");
gui_internal_widget_append(w,
gui_internal_button_new_with_callback(this, "Bookmarks",
image_new_l(this, "gui_bookmark"), gravity_center|orientation_vertical,
gui_internal_cmd_bookmarks, NULL));
+ coord=coordinates(&this->click, '\n');
gui_internal_widget_append(w,
- gui_internal_button_new_with_callback(this, "172°15'23\" E\n55°23'44\" S",
+ wc=gui_internal_button_new_with_callback(this, coord,
image_new_l(this, "gui_map"), gravity_center|orientation_vertical,
- gui_internal_cmd_bookmarks, NULL));
+ gui_internal_cmd_point, NULL));
+ g_free(coord);
gui_internal_widget_append(w,
gui_internal_button_new_with_callback(this, "172°15'23\" E\n55°23'44\" S",
image_new_l(this, "gui_rules"), gravity_center|orientation_vertical,
{
struct gui_priv *this=data;
struct graphics *gra=this->gra;
+ struct transformation *trans;
+ struct coord c;
// if still on the map (not in the menu, yet):
if (!this->root.children) {
// check whether the position of the mouse changed during press/release OR if it is the scrollwheel
if (!navit_handle_button(this->nav, pressed, button, p, NULL) || button >=4) // Maybe there's a better way to do this
return;
+
navit_block(this->nav, 1);
graphics_overlay_disable(gra, 1);
+ trans=navit_get_trans(this->nav);
+ this->click.pro=transform_get_projection(trans);
+ transform_reverse(trans, p, &c);
+ this->click.x=c.x;
+ this->click.y=c.y;
// draw menu
this->root.p.x=0;
this->root.p.y=0;
navit_zoom_out(this->nav, 2, NULL);
break;
default:
- dbg(0,"key=%d\n", key);
+ dbg(1,"key=%d\n", key, this);
+ if (this->root.children) {
+ graphics_draw_mode(this->gra, draw_mode_begin);
+ gui_internal_keypress_do(this, key);
+ graphics_draw_mode(this->gra, draw_mode_end);
+ }
}
}
#include "transform.h"
#include "projection.h"
#include "point.h"
+#include "item.h"
struct transformation {
long scale; /* Scale factor */
return 0;
}
+int
+transform_within_dist_point(struct coord *ref, struct coord *c, int dist)
+{
+ if (c->x-dist > ref->x)
+ return 0;
+ if (c->x+dist < ref->x)
+ return 0;
+ if (c->y-dist > ref->y)
+ return 0;
+ if (c->y+dist < ref->y)
+ return 0;
+ if ((c->x-ref->x)*(c->x-ref->x) + (c->y-ref->y)*(c->y-ref->y) <= dist*dist)
+ return 1;
+ return 0;
+}
+
+int
+transform_within_dist_line(struct coord *ref, struct coord *c0, struct coord *c1, int dist)
+{
+ int vx,vy,wx,wy;
+ int n1,n2;
+ struct coord lc;
+
+ if (c0->x < c1->x) {
+ if (c0->x-dist > ref->x)
+ return 0;
+ if (c1->x+dist < ref->x)
+ return 0;
+ } else {
+ if (c1->x-dist > ref->x)
+ return 0;
+ if (c0->x+dist < ref->x)
+ return 0;
+ }
+ if (c0->y < c1->y) {
+ if (c0->y-dist > ref->y)
+ return 0;
+ if (c1->y+dist < ref->y)
+ return 0;
+ } else {
+ if (c1->y-dist > ref->y)
+ return 0;
+ if (c0->y+dist < ref->y)
+ return 0;
+ }
+ vx=c1->x-c0->x;
+ vy=c1->y-c0->y;
+ wx=ref->x-c0->x;
+ wy=ref->y-c0->y;
+
+ n1=vx*wx+vy*wy;
+ if ( n1 <= 0 )
+ return transform_within_dist_point(ref, c0, dist);
+ n2=vx*vx+vy*vy;
+ if ( n2 <= n1 )
+ return transform_within_dist_point(ref, c1, dist);
+
+ lc.x=c0->x+vx*n1/n2;
+ lc.y=c0->y+vy*n1/n2;
+ return transform_within_dist_point(ref, &lc, dist);
+}
+
+int
+transform_within_dist_polyline(struct coord *ref, struct coord *c, int count, int close, int dist)
+{
+ int i;
+ for (i = 0 ; i < count-1 ; i++) {
+ if (transform_within_dist_line(ref,c+i,c+i+1,dist)) {
+ return 1;
+ }
+ }
+ if (close)
+ return (transform_within_dist_line(ref,c,c+count-1,dist));
+ return 0;
+}
+
+int
+transform_within_dist_polygon(struct coord *ref, struct coord *c, int count, int dist)
+{
+ int i, j, ci = 0;
+ for (i = 0, j = count-1; i < count; j = i++) {
+ if ((((c[i].y <= ref->y) && ( ref->y < c[j].y )) ||
+ ((c[j].y <= ref->y) && ( ref->y < c[i].y))) &&
+ (ref->x < (c[j].x - c[i].x) * (ref->y - c[i].y) / (c[j].y - c[i].y) + c[i].x))
+ ci = !ci;
+ }
+ if (! ci)
+ return transform_within_dist_polyline(ref, c, count, dist, 1);
+ return 1;
+}
+
+int
+transform_within_dist_item(struct coord *ref, enum item_type type, struct coord *c, int count, int dist)
+{
+ if (type < type_line)
+ return transform_within_dist_point(ref, c, dist);
+ if (type < type_area)
+ return transform_within_dist_polyline(ref, c, count, 0, dist);
+ return transform_within_dist_polygon(ref, c, count, dist);
+}
+
+
/*
Note: there are many mathematically equivalent ways to express these formulas. As usual, not all of them are computationally equivalent.
extern "C" {
#endif
/* prototypes */
+enum item_type;
+enum map_datum;
enum projection;
struct coord;
struct coord_geo;
+struct coord_geo_cart;
struct map_selection;
struct pcoord;
struct point;
void transform_to_geo(enum projection pro, struct coord *c, struct coord_geo *g);
void transform_from_geo(enum projection pro, struct coord_geo *g, struct coord *c);
void transform_from_to(struct coord *cfrom, enum projection from, struct coord *cto, enum projection to);
-int transform(struct transformation *t, enum projection pro, struct coord *c, struct point *p, int count, int flags);
+void transform_geo_to_cart(struct coord_geo *geo, double a, double b, struct coord_geo_cart *cart);
+void transform_cart_to_geo(struct coord_geo_cart *cart, double a, double b, struct coord_geo *geo);
+void transform_datum(struct coord_geo *from, enum map_datum from_datum, struct coord_geo *to, enum map_datum to_datum);
+int transform(struct transformation *t, enum projection pro, struct coord *c, struct point *p, int count, int unique);
void transform_reverse(struct transformation *t, struct point *p, struct coord *c);
enum projection transform_get_projection(struct transformation *this_);
void transform_set_projection(struct transformation *this_, enum projection pro);
void transform_print_deg(double deg);
int transform_get_angle_delta(struct coord *c1, struct coord *c2, int dir);
int transform_within_border(struct transformation *this_, struct point *p, int border);
+int transform_within_dist_point(struct coord *ref, struct coord *c, int dist);
+int transform_within_dist_line(struct coord *ref, struct coord *c0, struct coord *c1, int dist);
+int transform_within_dist_polyline(struct coord *ref, struct coord *c, int count, int close, int dist);
+int transform_within_dist_polygon(struct coord *ref, struct coord *c, int count, int dist);
+int transform_within_dist_item(struct coord *ref, enum item_type type, struct coord *c, int count, int dist);
/* end of prototypes */
#ifdef __cplusplus
}