ba7051a3ab7553b6a33ce4587dc97c041b54d26d
[navit-package] / src / cursor.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <fcntl.h>
6 #include <math.h>
7 #include <glib.h>
8 #include "debug.h"
9 #include "coord.h"
10 #include "transform.h"
11 #include "projection.h"
12 #include "point.h"
13 #include "graphics.h"
14 #include "statusbar.h"
15 #include "menu.h"
16 #include "vehicle.h"
17 #include "navit.h"
18 #include "callback.h"
19 #include "color.h"
20 #include "cursor.h"
21 #include "compass.h"
22 /* #include "track.h" */
23
24
25
26 struct cursor {
27         struct graphics *gra;
28         struct graphics_gc *cursor_gc;
29         struct transformation *trans;
30         struct point cursor_pnt;
31         struct callback_list *update_cbl;
32         struct vehicle *v;
33         struct callback *vehicle_cb;
34         int dir;
35         int speed;
36         struct coord pos;
37         enum projection pro;
38 };
39
40 struct coord *
41 cursor_pos_get(struct cursor *this)
42 {
43         return &this->pos;
44 #if 0
45         return vehicle_pos_get(this->v);
46 #endif
47 }
48
49
50 void
51 cursor_pos_set(struct cursor *this, struct coord *pos)
52 {
53         this->pos=*pos;
54 #if 0
55         return vehicle_pos_get(this->v);
56 #endif
57 }
58
59
60 static void
61 cursor_draw(struct cursor *this, struct point *pnt, int dir, int draw_dir)
62 {
63         int x=this->cursor_pnt.x;
64         int y=this->cursor_pnt.y;
65         int r=12,lw=2;
66         double dx,dy;
67         double fac1,fac2;
68         struct point cpnt[3];
69         struct graphics *gra=this->gra;
70
71         if (pnt && x == pnt->x && y == pnt->y)
72                 return;
73         if (!graphics_ready(gra))
74                 return;
75         cpnt[0]=this->cursor_pnt;
76         cpnt[0].x-=r+lw;
77         cpnt[0].y-=r+lw;
78         graphics_draw_restore(gra, &cpnt[0], (r+lw)*2, (r+lw)*2);
79         if (pnt) {
80                 graphics_draw_mode(gra, draw_mode_cursor);
81                 this->cursor_pnt=*pnt;
82                 x=pnt->x;
83                 y=pnt->y;
84                 cpnt[0].x=x;
85                 cpnt[0].y=y;
86                 graphics_draw_circle(gra, this->cursor_gc, &cpnt[0], r*2);
87                 if (draw_dir) {
88                         dx=sin(M_PI*dir/180.0);
89                         dy=-cos(M_PI*dir/180.0);
90
91                         fac1=0.7*r;
92                         fac2=0.4*r;     
93                         cpnt[0].x=x-dx*fac1+dy*fac2;
94                         cpnt[0].y=y-dy*fac1-dx*fac2;
95                         cpnt[1].x=x+dx*r;
96                         cpnt[1].y=y+dy*r;
97                         cpnt[2].x=x-dx*fac1-dy*fac2;
98                         cpnt[2].y=y-dy*fac1+dx*fac2;
99                         graphics_draw_lines(gra, this->cursor_gc, cpnt, 3);
100                 } else {
101                         cpnt[1]=cpnt[0];
102                         graphics_draw_lines(gra, this->cursor_gc, cpnt, 2);
103                 }
104                 graphics_draw_mode(gra, draw_mode_end);
105         }
106 }
107
108 void
109 cursor_redraw(struct cursor *this)
110 {
111         struct point pnt;
112         transform(this->trans, this->pro, &this->pos, &pnt);
113         cursor_draw(this, &pnt, this->dir-transform_get_angle(this->trans, 0), this->speed > 2.5);
114 }
115
116 #if 0
117 static void
118 cursor_map_reposition_screen(struct cursor *this, struct coord *c, double *dir, int x_new, int y_new)
119 {
120         struct coord c_new;
121         struct transformation tr;
122         struct point pnt;
123         unsigned long scale;
124         long x,y;
125         int dir_i;
126         struct container *co=this->co;
127
128         if (dir)
129                 dir_i=*dir;
130         else
131                 dir_i=0;
132
133         pnt.x=co->trans->width-x_new;
134         pnt.y=co->trans->height-y_new;
135         graphics_get_view(co, &x, &y, &scale);
136         tr=*this->co->trans;
137         transform_setup(&tr, c->x, c->y, scale, dir_i);
138         transform_reverse(&tr, &pnt, &c_new);
139         printf("%lx %lx vs %lx %lx\n", c->x, c->y, c_new.x, c_new.y);
140         x=c_new.x;
141         y=c_new.y;
142         transform_set_angle(co->trans,dir_i);
143         graphics_set_view(co, &x, &y, &scale);
144 }
145
146 static void
147 cursor_map_reposition(struct cursor *this, struct coord *c, double *dir)
148 {
149         if (this->co->flags->orient_north) {
150                 graphics_set_view(this->co, &c->x, &c->y, NULL);
151         } else {
152                 cursor_map_reposition_screen(this, c, dir, this->co->trans->width/2, this->co->trans->height*0.8);
153         }
154 }
155
156 static int
157 cursor_map_reposition_boundary(struct cursor *this, struct coord *c, double *dir, struct point *pnt)
158 {
159         struct point pnt_new;
160         struct transformation *t=this->co->trans;
161
162         pnt_new.x=-1;
163         pnt_new.y=-1;
164         if (pnt->x < 0.1*t->width) {
165                 pnt_new.x=0.8*t->width;
166                 pnt_new.y=t->height/2;
167         }
168         if (pnt->x > 0.9*t->width) {
169                 pnt_new.x=0.2*t->width;
170                 pnt_new.y=t->height/2;
171         }
172         if (pnt->y < (this->co->flags->orient_north ? 0.1 : 0.5)*t->height) {
173                 pnt_new.x=t->width/2;
174                 pnt_new.y=0.8*t->height;
175         }
176         if (pnt->y > 0.9*t->height) {
177                 pnt_new.x=t->width/2;
178                 pnt_new.y=0.2*t->height;
179         }
180         if (pnt_new.x != -1) {
181                 if (this->co->flags->orient_north) {
182                         cursor_map_reposition_screen(this, c, NULL, pnt_new.x, pnt_new.y);
183                 } else {
184                         cursor_map_reposition(this, c, dir);
185                 }
186                 return 1;
187         }
188         return 0;
189 }
190
191 #endif
192
193 int
194 cursor_get_dir(struct  cursor *this)
195 {
196         return this->dir;
197 }
198
199 int
200 cursor_get_speed(struct cursor *this)
201 {
202         return this->speed;
203 }
204
205 static void
206 cursor_update(struct cursor *this, struct vehicle *v)
207 {
208         struct point pnt;
209         struct coord *pos;
210         double *dir;
211         double *speed;
212         enum projection pro;
213
214         if (v) {
215                 pos=vehicle_pos_get(v); 
216                 dir=vehicle_dir_get(v);
217                 speed=vehicle_speed_get(v);
218                 pro=vehicle_projection(v);
219                 this->dir=*dir;
220                 this->speed=*speed;
221                 this->pos=*pos;
222                 this->pro=pro;
223                 callback_list_call_1(this->update_cbl, this);
224                 transform(this->trans, pro, &this->pos, &pnt);
225                 cursor_draw(this, &pnt, *dir-transform_get_angle(this->trans, 0), *speed > 2.5);
226         }
227 #if 0
228         compass_draw(this->co->compass, this->co);
229 #endif
230 }
231
232 struct cursor *
233 cursor_new(struct graphics *gra, struct vehicle *v, struct color *c, struct transformation *t)
234 {
235         dbg(2,"enter gra=%p v=%p c=%p t=%p\n", gra, v, c, t);
236         struct cursor *this=g_new(struct cursor,1);
237 #if 0
238         this->offscreen_cbl=callback_list_new();
239 #endif
240         this->update_cbl=callback_list_new();
241         this->gra=gra;
242         this->trans=t;
243         this->cursor_gc=graphics_gc_new(gra);
244         this->v=v;
245         graphics_gc_set_foreground(this->cursor_gc, c);
246         graphics_gc_set_linewidth(this->cursor_gc, 2);
247         this->vehicle_cb=callback_new_1(callback_cast(cursor_update), this);
248         vehicle_callback_add(v, this->vehicle_cb);
249         dbg(2,"ret=%p\n", this);
250         return this;
251 }
252
253 void
254 cursor_add_callback(struct cursor *this, struct callback *cb)
255 {
256         callback_list_add(this->update_cbl, cb);
257 }