Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
810 - 1
#!/usr/bin/perl
2
#!/usr/bin/perl -d:ptkdb
3
 
4
###############################################################################
5
#
6
# mkcockpit.pl -  MK Mission Cockpit - GUI
7
#
8
# Copyright (C) 2009  Rainer Walther  (rainerwalther-mail@web.de)
9
#
10
# Creative Commons Lizenz mit den Zusaetzen (by, nc, sa)
11
#
12
# Es ist Ihnen gestattet: 
13
#     * das Werk vervielfältigen, verbreiten und öffentlich zugänglich machen
14
#     * Abwandlungen bzw. Bearbeitungen des Inhaltes anfertigen
15
# 
16
# Zu den folgenden Bedingungen:
17
#     * Namensnennung.
18
#       Sie müssen den Namen des Autors/Rechteinhabers in der von ihm festgelegten Weise nennen.
19
#     * Keine kommerzielle Nutzung.
20
#       Dieses Werk darf nicht für kommerzielle Zwecke verwendet werden.
21
#     * Weitergabe unter gleichen Bedingungen.
22
#       Wenn Sie den lizenzierten Inhalt bearbeiten oder in anderer Weise umgestalten,
23
#       verändern oder als Grundlage für einen anderen Inhalt verwenden,
24
#       dürfen Sie den neu entstandenen Inhalt nur unter Verwendung von Lizenzbedingungen
25
#       weitergeben, die mit denen dieses Lizenzvertrages identisch oder vergleichbar sind.
26
# 
27
# Im Falle einer Verbreitung müssen Sie anderen die Lizenzbedingungen, unter welche dieses
28
# Werk fällt, mitteilen. Am Einfachsten ist es, einen Link auf diese Seite einzubinden.
29
# 
30
# Jede der vorgenannten Bedingungen kann aufgehoben werden, sofern Sie die Einwilligung
31
# des Rechteinhabers dazu erhalten.
32
# 
33
# Diese Lizenz lässt die Urheberpersönlichkeitsrechte unberührt.
34
# 
35
# Weitere Details zur Lizenzbestimmung gibt es hier:
36
#   Kurzform: http://creativecommons.org/licenses/by-nc-sa/3.0/de/
37
#   Komplett: http://creativecommons.org/licenses/by-nc-sa/3.0/de/legalcode
38
#
39
###############################################################################
40
# 2009-02-20 0.0.1 rw created
41
# 2009-04-01 0.1.0 rw RC1
42
# 2009-04-16 0.1.1 rw Bugfix, ALT= average of airsensor and Sat
43
# 2009-05-14 0.2.0 rw Waypoint Player
44
# 2009-05-17 0.2.1 rw Cursor-Steuerung fuer WP-Player. Cmdline-Parameter "-geometry"
45
# 2009-07-18 0.2.2 rw DE/EN multinational
46
#                     Target-Balloon with Distance, Tolerance and Holdtime
47
#                     Fix footprint "Ausreiser"
48
#                     JPEG and PNG maps supported
49
#                     Player for KML Files
50
# 2009-07-26 0.2.3 rw System Messages Balloon
51
# 2009-07-31 0.2.4 rw ODO Kilometerzähler
52
#                     Enter WP-Number from Keyboard
53
#                     Random WP-Player (Waypoint and Map)
54
#                     Check Airfield Border
55
#                     Draw Calibration points on map
56
# 2009-08-08 0.2.5 rw KML Recorder
57
#                     Text to speech
58
#                     Subroutines moved to libmkcockpit.pl
59
#                     Timer moved to libmktimer.pl
60
#                     Start Scenarion configuration
61
#                     Battery capacity estimation
62
#                     Read map definition from maps/map.xml
63
# 2009-08-23 0.2.6 rw Tracking-Antenna Icon
64
#                     Show Fox only in Player-Pause mode
65
#                     POI heading control
66
#                     Display scale
67
#                     Measuring-tool on left mouse button
68
#                     Display Operation Radius Border
69
#                     Read map definition from KML file (GE import)
70
#                     Include of local *.pm changed
71
#                     Copy x/y/Lat/Lon to Clipboard when pressing left mouse button
72
#                     Calculate size of map image
73
#                     track.pl - Commandline parameter added for COM ports
74
#                     don't use local perl libs any more
75
# 2009-10-18 0.2.7 rw Mk-Simulator
76
#                     Start tracker at program start. Coldstart at MK-calibration
77
#                     COM Port >9; PortSetSkip config
78
#                     Reset Flight-Time and ODO when clicking on OSD-value
79
# 2009-10-25 0.3.0 rw NC 0.17
80
#                     Read/Write KopterTool WPL Waypoint list
81
#                     Cfg Optionmenues
82
# 2010-02-09 0.4.0 rw Canvas - Popup focus improvement
83
#                     bugfix "WP hinzufügen und senden" in classic mode
84
#                     Grid on canvas
85
#                     joystick and 3D-Mouse
86
#                     remove main window status line
87
#                     Event engine
88
#                     Serial Channel
89
#                     External Control
90
#                     Expo, Dualrate
91
#                     Player Pause move relative to MAP or MK
92
#                     Load plugin directory
93
#                     Current, UsedCapacity, Power added
94
#                     RETURN turns off External-Control + Serial Channel
95
# 2010-02-15 0.4.1 rw F-Keys for Event
96
# 2010-03-20 0.4.2 rw Maestro Servo Controller
97
# 2010-07-01 0.5.0 rw WP/POI adjustments for NC 0.19/0.20
98
#                     TTS system messages closer to current situation
99
#                     NC Hardware Error Codes
100
# 2010-09-09 0.5.1 rw Use exifTool
101
#                     rename map/map.pl --> libmapdef.pl
102
#                     Tracker start at motor start
103
#                     Start web browser (GeoMapTool)
104
#                     Change Map without program restart
105
#                     Support JPEG from geomaptool.de
106
#
107
###############################################################################
108
 
109
$Version = "0.5.1 - 2010-09-09";
110
 
111
# change working directory to program path
112
my $Cwd = substr ($0, 0, rindex ($0, "mkcockpit.pl"));
113
chdir $Cwd;
114
 
115
# set path for local Perl libs
116
push @INC, $Cwd . "perl/lib";
117
 
118
use threads;            # http://search.cpan.org/~jdhedden/threads-1.72/threads.pm
119
                        # http://perldoc.perl.org/threads.html
120
use threads::shared;    # http://search.cpan.org/~jdhedden/threads-shared-1.28/shared.pm
121
use Thread::Queue;      # http://search.cpan.org/dist/Thread-Queue-2.11/lib/Thread/Queue.pm
122
use Tk;
123
use Tk::Balloon;
124
use Tk::Dialog;
125
use Tk::Notebook;
126
use Tk::JPEG;           # http://search.cpan.org/~srezic/Tk-804.028/JPEG/JPEG.pm
127
use Tk::PNG;            # http://search.cpan.org/~srezic/Tk-804.028/PNG/PNG.pm
128
use Tk::Tree;
129
use Math::Trig;
130
use Time::HiRes qw(usleep);  # http://search.cpan.org/~jhi/Time-HiRes-1.9719/HiRes.pm
131
use XML::Simple;             # http://search.cpan.org/dist/XML-Simple-2.18/lib/XML/Simple.pm
132
use Clipboard;               # http://search.cpan.org/~king/Clipboard-0.09/lib/Clipboard.pm
133
use Tk::BrowseEntry;         # http://search.cpan.org/~srezic/Tk-804.028/pod/BrowseEntry.pod
134
 
135
# Version setting
136
share (%Version);
137
$Version{'mkcockpit.pl'}  = $Version;
138
 
139
# Read configuration
140
$XmlConfigFile = "mkcockpit.xml";
141
$Cfg = XMLin($XmlConfigFile);
142
 
143
require "track.pl";        # Tracking antenna
144
require "mkcomm.pl";       # MK communication
145
require "logging.pl";      # CSV and GPX Logging
146
require "geserver.pl";     # Google Earth Server
147
require "libmapdef.pl";    # Map definition
148
 
149
&MapDefLoad();             # Load the Maps in hash %Maps
150
 
151
require "libmap.pl";       # map subs
152
require "translate.pl";    # Übersetzungstable
153
require "tts.pl";          # Text to Speech
154
require "libmkcockpit.pl"; # Subroutines
155
require "libmksim.pl";     # MK Simulator
156
require "libcfgopt.pl";    # Option menu values
157
require "libmouse.pl";     # 3D Mouse
158
require "libjoystick.pl";  # joystick
159
 
160
# Commandline parameter
161
my %CmdLine = @ARGV;
162
 
163
# Aktuell gültige Karte
164
my %Map = %{$Maps{'Current'}};
165
 
166
# Canvas size - get image size
167
$MapSizeX  = $Map{'Size_X'};
168
$MapSizeY  = $Map{'Size_Y'};
169
 
170
# Thread fuer Kommunikation mit MK starten
171
# Output: %MkOsd, %MkTarget, %MkNcDebug, %Mk
172
# Input:  Thread-Queue: $MkSendQueue
173
$mk_thr = threads->create (\&MkCommLoop) -> detach();
174
 
175
# Start Logging Thread
176
$log_thr = threads->create (\&MkLogLoop) -> detach();
177
 
178
# Start GoogleEarth Thread
179
$ge_thr = threads->create (\&GeServer) -> detach();
180
 
181
# Start TTS Thread
182
$tts_thr = threads->create (\&TtsLoop) -> detach();
183
 
184
# Start Antenna tracker
185
if ( $Cfg->{'track'}->{'Active'} =~ /y/i )
186
    {
187
    $track_thr = threads->create (\&TrackAntennaGps)->detach();
188
    }
189
 
190
# 3D Mouse Thread
191
$mouse_thr = threads->create (\&Mouse3D) -> detach();
192
 
193
# Joystick Thread
194
$joystick_thr = threads->create (\&Joystick) -> detach();
195
 
196
 
197
#
198
# Player:
199
#    Waypoint-List:   @Waypoints
200
#    KML-Target-List: @KmlTargets
201
#
202
 
203
# Player state machine
204
$PlayerMode = 'Stop';       # Play, Stop, Pause, Home ...
205
$PlayerWptKmlMode = 'WPT';  # WPT, KML
206
$PlayerRandomMode = 'STD';  # STD, RND, MAP
207
$PlayerRecordMode = "";     # "", REC
208
$PlayerPauseMode  = "MAP";  # MAP, MK
209
$WpPlayerIndex = 0;
210
$WpPlayerHoldtime = -1;
211
$KmlPlayerIndex = 0;
212
$PlayerPause_Lat = "";
213
$PlayerPause_Lon = "";
214
 
215
# Point Of Interest (POI)
216
my $Poi_x = $MapSizeX/2-50;
217
my $Poi_y = $MapSizeY/2 ;
218
($Poi_Lat, $Poi_Lon) = &MapXY2Gps($Poi_x + 24, $Poi_y + 48);
219
 
220
# POI from Map configuration
221
if ( $Map{'Poi_Lat'} ne ""  and  $Map{'Poi_Lon'} ne "" )
222
    {
223
    $Poi_Lat = $Map{'Poi_Lat'};
224
    $Poi_Lon = $Map{'Poi_Lon'};
225
    ($Poi_x, $Poi_y) = &MapGps2XY($Poi_Lat, $Poi_Lon);
226
    $Poi_x = $Poi_x - 24;
227
    $Poi_y = $Poi_y - 48;
228
    }
229
$Poi_Mode = 0;     # POI Mode off
230
$TxExtOn = 0;      # Tx External-Control/SerialChannel off
231
 
232
# Event configuration
233
my $XmlEventConfigFile = $Cfg->{'StartScenario'}->{'EventFile'} || "event/mkevent.xml";
234
if ( ! -f $XmlEventConfigFile )
235
    {
236
    $XmlEventConfigFile = "event/" . $XmlEventConfigFile;
237
    }
238
if ( -f $XmlEventConfigFile )
239
    {
240
    $Event = XMLin($XmlEventConfigFile);
241
    }
242
 
243
if ( scalar keys %{$Event} == 0 )
244
    {
245
    # create new dummy event, if no XML or XML is empty
246
    &EventInit("Dummy", $Event);
247
    }
248
 
249
my %EventStat;    # internal state of event maschine
250
 
251
 
252
# load user plugins
253
opendir DIR, "plugin";
254
my @Plugin = readdir DIR;
255
closedir DIR;
256
@Plugin = grep /\.pl$/, @Plugin;
257
foreach my $File (@Plugin)
258
    {
259
    require "plugin/$File";
260
    }
261
 
262
 
263
# Hauptfenster
264
$main = new MainWindow;
265
$main->title ("MK Mission Cockpit - Version $Version");
266
 
267
if ( $CmdLine{'-geometry'} ne "" )
268
    {
269
    $main->geometry( "$CmdLine{'-geometry'}" );
270
    }
271
 
272
# pattern for dashed lines
273
my $stipple_bits = [];
274
foreach my $b (1..8)
275
    {
276
    push @$stipple_bits, pack ('b8', '1' x $b . '.' x (8 - $b));
277
    $main->DefineBitmap("stipple$b" => 8, 1, $stipple_bits->[$b-1]);
278
    }
279
 
280
# Catch delete window event and exit
281
$main->protocol( 'WM_DELETE_WINDOW' => sub
282
    {
283
    &CbExit();
284
    });
285
 
286
# disable main window Key-Bindings for F10
287
$main->bind('all', '<Key-F10>', undef);
288
 
289
#-----------------------------------------------------------------
290
# Menu
291
#-----------------------------------------------------------------
292
 
293
# Menu bar
294
my $menu_bar = $main->Menu;
295
$main->optionAdd("*tearOff", "false");
296
$main->configure ('-menu' => $menu_bar);
297
 
298
my $menu_file = $menu_bar->cascade('-label' => $Translate{'File'});
299
    $menu_file->command('-label' => $Translate{'Preferences'},
300
                        '-command' => sub
301
        {
302
        # Reload Map directory
303
        &MapDefLoad();
304
        &Configure ($XmlConfigFile, $Cfg, "CONFIG");
305
        },
306
                       );
307
    $menu_file->command('-label' => $Translate{'ConfigEvent'},
308
                        '-command' => [\&Configure, $XmlEventConfigFile, $Event, "EVENT", ],
309
                       );
310
    $menu_file->separator;
311
    $menu_file->command('-label' => $Translate{'GeoMapTool'},
312
                        '-command' => [\&StartBrowser, "http://www.geomaptool.de", ],
313
                       );
314
    $menu_file->separator;                                     
315
    $menu_file->command('-label' => $Translate{'Exit'},
316
                        '-command' => [\&CbExit ],
317
                        );
318
 
319
my $menu_debug = $menu_bar->cascade(-label => $Translate{'Debug'});
320
    $menu_debug->command('-label' => $Translate{'NcOsdDataset'},
321
                         '-command' => [\&DisplayHash, \%MkOsd, $Translate{'NcOsdDataset'}, "Display Refresh Heartbeat"],
322
                        );
323
    $menu_debug->command('-label' => $Translate{'NcTargetDataset'},
324
                         '-command' => [\&DisplayHash, \%MkTarget, $Translate{'NcTargetDataset'}, "Display Refresh Heartbeat"],
325
                        );
326
    $menu_debug->command('-label' => $Translate{'NcDebugDataset'},
327
                         '-command' => [\&DisplayHash, \%MkNcDebug, $Translate{'NcDebugDataset'}, "Display Refresh Heartbeat"],
328
                                        );             
329
    $menu_debug->command('-label' => $Translate{'NcOther'},
330
                         '-command' => [\&DisplayHash, \%Mk, $Translate{'NcOther'}, "Display Refresh Heartbeat"],
331
                                        );
332
    $menu_debug->command('-label' => $Translate{'TrackingDebugDataset'},
333
                         '-command' => [\&DisplayHash, \%MkTrack, $Translate{'TrackingDebugDataset'}, "Display Refresh Heartbeat"],
334
                        );
335
 
336
    $menu_debug->command('-label' => $Translate{'MapDebugDataset'},
337
                         '-command' => [\&DisplayHash, \%Map, $Translate{'MapDebugDataset'}, "Display"],
338
                        );
339
    $menu_debug->command('-label' => $Translate{'SystemDebug'},
340
                         '-command' => [\&DisplayHash, \%System, $Translate{'SystemDebug'}, "Display Refresh"],
341
                        );
342
    $menu_debug->separator;                                    
343
    $menu_debug->command('-label' => $Translate{'StickDebug'},
344
                         '-command' => [\&DisplayHash, \%Stick, $Translate{'StickDebug'}, "Display Refresh"],
345
                        );
346
    $menu_debug->command('-label' => $Translate{'SerialChannel'},
347
                         '-command' => [\&DisplayHash, \%MkSerialChannel, $Translate{'SerialChannel'}, "Display Refresh SerialChannel"],
348
                        );
349
    $menu_debug->command('-label' => $Translate{'ExternControl'},
350
                         '-command' => [\&DisplayHash, \%MkExternControl, $Translate{'ExternControl'}, "Display Refresh ExternControl"],
351
                        );
352
    $menu_debug->separator;                                    
353
    $menu_debug->command('-label' => $Translate{'MkDebugSim'},
354
                         '-command' => \&MkSim,
355
                        );
356
 
357
 
358
my $menu_help = $menu_bar->cascade(-label => $Translate{'Help'});
359
    $menu_help->command('-label' => 'Version',
360
                        '-command' => [\&DisplayHash, \%Version, $Translate{'Version'}, "Display"],
361
                       );
362
    $menu_help->separator;
363
    $menu_help->command('-label' => $Translate{'About'},
364
                        '-command' => sub
365
        {
366
        my $License = <<EOF;
367
Copyright (C) 2010  Rainer Walther (rainerwalther-mail\@web.de)
368
 
369
Creative Commons Lizenz mit den Zusaetzen (by, nc, sa)
370
 
371
See LICENSE.TXT
372
EOF
373
 
374
        my $DlgAbout = $frame_map->Dialog('-title' => $Translate{'AboutMissionCockpit'},
375
                                          '-text' => "$License",
376
                                          '-buttons' => ['OK'],
377
                                          '-bitmap' => 'info',
378
                                         );
379
        $DlgAbout->Show;
380
        });  
381
 
382
 
383
#-----------------------------------------------------------------
384
# Frames
385
#-----------------------------------------------------------------                        
386
 
387
#
388
# Frame: Map
389
#
390
 
391
$frame_map = $main->Frame( '-background' => 'lightgray',
392
                           '-relief' => 'sunken',
393
                           '-borderwidth' => 5,
394
                          ) -> pack('-side' => 'top',
395
                                    '-fill' => 'x',
396
                                    );
397
 
398
# Map Überschrift
399
$frame_map_top = $frame_map->Frame( -background => 'lightgray',
400
                                  ) -> pack( -side   => 'top',
401
                                             -anchor => 'w',
402
                                             -fill => 'x',
403
                                             -expand => 1,
404
                                           );
405
 
406
$map_top_label = $frame_map_top->Label (-text       => "$Translate{'Map'}: $Map{'Name'} ($Map{'File'})",
407
                                        -background => 'lightgray',
408
                                        -relief     => 'flat',
409
                                       ) -> pack( -side => 'left' );
410
 
411
 
412
# 10 placeholders for status texts in upper status line. Field update in libmktimer
413
for ($i=0; $i<10; $i++)
414
    {
415
    $map_status_top[$i] = $frame_map_top->Label ( -text       => "",
416
                                                  -background => 'lightgray',
417
                                                  -anchor     => 'e',
418
                                                ) -> pack (-side => 'right',
419
                                                           -anchor => 'e',
420
                                                           -padx  => 1,
421
                                                          );
422
    }
423
 
424
# Map Statuszeile
425
$map_status = $frame_map->Frame( -background => 'lightgray',
426
                               ) -> pack( -side   => 'bottom',
427
                                          -anchor => 'w',
428
                                          -fill   => 'x',
429
                                          -expand => 1,
430
                                        );
431
$map_status_line = $map_status->Label ( -text => $Translate{'StatusLine'},
432
                                        -background => 'lightgray',
433
                                       ) -> pack (-side   => 'left',
434
                                                  -anchor => 'w',
435
                                                  -expand => 1,
436
                                                  );
437
 
438
# 10 placeholders for event status in lower status line. Field update in libmktimer
439
for ($i=0; $i<10; $i++)
440
    {
441
    $map_status_event[$i] = $map_status->Label ( -text       => "",
442
                                                 -background => 'lightgray',
443
                                                 -anchor     => 'e',
444
                                               ) -> pack (-side => 'right',
445
                                                          -anchor => 'e',
446
                                                          -padx  => 1,
447
                                                         );
448
    }
449
 
450
#
451
# Map Canvas
452
#
453
&CanvasCreate();
454
 
455
 
456
# Balloon attached to Canvas
457
$map_balloon = $frame_map->Balloon('-statusbar' => $status_line, );
458
$map_balloon->attach($map_canvas,
459
                     '-balloonposition' => 'mouse',
460
                     '-state' => 'balloon',
461
                     '-msg' => { 'MK-Arrow'               => $Translate{'Balloon-MK-Arrow'},
462
                                 'MK-Home-Line'           => $Translate{'Balloon-MK-Home-Line'},
463
                                 'MK-Home-Dist'           => $Translate{'Balloon-MK-Home-Dist'},
464
                                 'MK-Target-Line'         => $Translate{'Balloon-MK-Target-Line' },
465
                                 'MK-Target-Dist'         => $Translate{'Balloon-MK-Target-Dist'},
466
                                 'MK-Speed'               => $Translate{'Balloon-MK-Speed'},
467
                                 'Map-Variometer'         => $Translate{'Balloon-Map-Variometer' },
468
                                 'Map-Variometer-Pointer' => $Translate{'Balloon-Map-Variometer-Pointer'},
469
                                 'Map-Variometer-Skala'   => $Translate{'Balloon-Map-Variometer-Pointer'},
470
                                 'Fox'                    => $Translate{'Balloon-Fox'},
471
                                 'Heartbeat'              => $Translate{'Balloon-Heartbeat'},
472
                                 'Satellite'              => $Translate{'Balloon-Satellite'},
473
                                 'Waypoint'               => $Translate{'Balloon-Waypoint'},
474
                                 'Map-Border'             => $Translate{'Balloon-Map-Border'},
475
                                 'Waypoint-Connector'     => $Translate{'Balloon-Waypoint-Connector'},
476
                                 'Wp-PlayPause'           => $Translate{'Balloon-Wp-PlayPause'},
477
                                 'Wp-Stop'                => $Translate{'Balloon-Wp-Stop'},
478
                                 'Wp-First'               => $Translate{'Balloon-Wp-First'},
479
                                 'Wp-Last'                => $Translate{'Balloon-Wp-Last'},
480
                                 'Wp-Next'                => $Translate{'Balloon-Wp-Next'},
481
                                 'Wp-Prev'                => $Translate{'Balloon-Wp-Prev'},
482
                                 'Wp-Home'                => $Translate{'Balloon-Wp-Home'},
483
                                 'Wp-WptKml'              => $Translate{'Balloon-Wp-WptKml'},
484
                                 'Wp-WptRandom'           => $Translate{'Balloon-Wp-WptRandom'},
485
                                 'Wp-Record'              => $Translate{'Balloon-Wp-Record'},
486
                                 'Track-Antenna'          => $Translate{'Balloon-TrackAntenna'},
487
                                 'POI'                    => $Translate{'Balloon-Poi'},
488
                               },
489
                    );
490
 
491
#                                       
492
# Mouse button 1
493
#
494
 
495
# Button 1 Press
496
$map_canvas->CanvasBind("<Button-1>", sub
497
    {
498
    # print coords in status line
499
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
500
    my ($Lat, $Lon) = &MapXY2Gps($x, $y);
501
 
502
    $map_status_line->configure ('-text' => "Lat: $Lat  Lon: $Lon     x: $x  y: $y");
503
 
504
    # save Coords and GPS-Pos for Button-Motion and Release
505
    $Button1_x = $x;
506
    $Button1_y = $y;
507
    $Button1_Lat = $Lat;
508
    $Button1_Lon = $Lon;
509
 
510
    # copy Pixel-Coordinates to Clipboard
511
    Clipboard->copy ("x=$x\r\n" . "y=$y\r\n" . "Lat=$Lat\r\n" . "Lon=$Lon\r\n");
512
    });
513
 
514
# Button 1 Motion
515
$map_canvas->CanvasBind("<Button1-Motion>", sub
516
    {
517
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
518
    my $id      = $map_canvas->find('withtag', 'current');
519
 
520
    # delete old measuring line
521
    $map_canvas->delete('Map-Measure');
522
 
523
    my @Tags = $map_canvas->gettags($id);
524
    if ( ( $Tags[0] eq "Map"  or $Tags[0] eq "Map-Border") and
525
         $x ne $Button1_x  and  $y ne $Button1_y )
526
        {
527
        # button moved on Map
528
 
529
        # draw new measuring line
530
        $map_canvas->createLine ( $Button1_x, $Button1_y, $x, $y,
531
                                  '-tags' => 'Map-Measure',
532
                                  '-arrow' => 'none',
533
                                  '-fill' => 'white',
534
                                  '-width' => 1,
535
                         );
536
 
537
        # update status line
538
        my ($Lat, $Lon) = &MapXY2Gps($x, $y);
539
        my ($Dist, $Bearing) = &MapGpsTo($Button1_Lat, $Button1_Lon, $Lat, $Lon);
540
        $Dist = sprintf ("%.2f m", $Dist);
541
        $Bearing = sprintf ("%.2f degree", $Bearing);
542
 
543
        $map_status_line->configure ('-text' => "Dist: $Dist  Bearing: $Bearing");
544
        }
545
    });
546
 
547
# Button 1 Release
548
$map_canvas->CanvasBind("<Button1-ButtonRelease>", sub
549
    {
550
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
551
    my $id      = $map_canvas->find('withtag', 'current');
552
 
553
    # delete measuring line
554
    $map_canvas->delete('Map-Measure');
555
 
556
    my @Tags = $map_canvas->gettags($id);
557
    if ( ( $Tags[0] eq "Map"  or $Tags[0] eq "Map-Border") and
558
         $x ne $Button1_x  and  $y ne $Button1_y )
559
        {
560
        # button released on Map
561
 
562
        # update status line
563
        my ($Lat, $Lon) = &MapXY2Gps($x, $y);
564
        my ($Dist, $Bearing) = &MapGpsTo($Button1_Lat, $Button1_Lon, $Lat, $Lon);
565
        $Dist = sprintf ("%.2f m", $Dist);
566
        $Bearing = sprintf ("%.2f degree", $Bearing);
567
 
568
        $map_status_line->configure ('-text' => "Dist: $Dist  Bearing: $Bearing");
569
        }
570
    });
571
 
572
 
573
# Mouse button 1 for Fox
574
my $FoxOldx = 0;
575
my $FoxOldy = 0;
576
my $FoxTime = time;
577
&FoxHide();   # Show only in Player-Pause Mode
578
 
579
# Pick Fox
580
$map_canvas->bind('Fox' => '<Button-1>' => sub
581
    {
582
    # prepare to move Fox
583
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
584
    $FoxOldx = $x;
585
    $FoxOldy = $y;
586
    $FoxTime = time;
587
    });
588
 
589
# Move Fox
590
$map_canvas->bind('Fox' => '<Button1-Motion>' => sub
591
    {
592
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
593
    my $id      = $map_canvas->find('withtag', 'current');
594
 
595
    $map_canvas->move($id => $x - $FoxOldx, $y - $FoxOldy);
596
    $FoxOldx = $x;
597
    $FoxOldy = $y;
598
 
599
    if ( time > $FoxTime )
600
        {
601
        # wenn in Bewegung Koordinaten nur 1/s senden
602
        my ($x0, $y0, $x1, $y1) = $map_canvas->bbox ($id);
603
        $x = $x0 + ($x1 - $x0)/2;
604
        $y = $y1;
605
 
606
        ($PlayerPause_Lat, $PlayerPause_Lon) = &MapXY2Gps($x, $y);
607
        $FoxTime = time;
608
 
609
        $map_status_line->configure ('-text' => "$Translate{'TargetCoordSent'} -> Lat: $PlayerPause_Lat  Lon: $PlayerPause_Lon     x: $x  y: $y");
610
        }
611
    });
612
 
613
# Release Fox
614
$map_canvas->bind('Fox' => '<Button1-ButtonRelease>' => sub
615
    {
616
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
617
    my $id      = $map_canvas->find('withtag', 'current');
618
 
619
    my ($x0, $y0, $x1, $y1) = $map_canvas->bbox ($id);
620
    $x = $x0 + ($x1 - $x0)/2;
621
    $y = $y1;
622
 
623
    ($PlayerPause_Lat, $PlayerPause_Lon) = &MapXY2Gps($x, $y);
624
 
625
    # Show user that Waypoints in MK are cleared
626
    $WaypointsModified = 1;
627
    &WpRedrawLines();
628
 
629
    $map_status_line->configure ('-text' => "$Translate{'TargetCoordSent'} -> Lat: $PlayerPause_Lat  Lon: $PlayerPause_Lon     x: $x  y: $y");
630
    });
631
 
632
# Pick Waypoint
633
my $WpOldx;
634
my $WpOldy;
635
$map_canvas->bind('Waypoint' => '<Button-1>' => sub
636
    {
637
    # prepare to move
638
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
639
    $WpOldx = $x;
640
    $WpOldy = $y;
641
    });
642
 
643
# Move Waypoint
644
$map_canvas->bind('Waypoint' => '<Button1-Motion>' => sub
645
    {
646
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
647
    my $id      = $map_canvas->find('withtag', 'current');
648
 
649
    # move icon and Wp-Number
650
    my $WpIndex = &WpGetIndexFromId($id);
651
    if ( $WpIndex >= 0 )
652
        {
653
        my $Tag = $Waypoints[$WpIndex]{'Tag'};
654
        $map_canvas->move($Tag => $x - $WpOldx, $y - $WpOldy);
655
        }
656
 
657
    $WpOldx = $x;
658
    $WpOldy = $y;
659
    });
660
 
661
# Release Wp
662
$map_canvas->bind('Waypoint' => '<Button1-ButtonRelease>' => sub
663
    {
664
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
665
    my $id      = $map_canvas->find('withtag', 'current');
666
 
667
    # take coords from lower/middle icon position
668
    my ($x0, $y0, $x1, $y1) = $map_canvas->bbox ($id);
669
    $x = $x0 + ($x1 - $x0)/2;
670
    $y = $y1;
671
 
672
    # update Waypoint-Array
673
    my $WpIndex = &WpGetIndexFromId($id);
674
    if ( $WpIndex >= 0 )
675
            {
676
        # got it: set new coords
677
 
678
        my ($Lat, $Lon) = &MapXY2Gps($x, $y);
679
        my $Wp = $Waypoints[$WpIndex];
680
        $Wp->{'MapX'} = $x;
681
        $Wp->{'MapY'} = $y;
682
        $Wp->{'_MapX_Rel'} = $x / $MapSizeX;
683
        $Wp->{'_MapY_Rel'} = $y / $MapSizeY;
684
        $Wp->{'Pos_Lat'} = $Lat;
685
        $Wp->{'Pos_Lon'} = $Lon;
686
 
687
        # redraw connector-lines
688
        &WpRedrawLines();
689
 
690
        # red connectors: Wp still have to be sent to MK
691
        $map_canvas->itemconfigure('Waypoint-Connector',
692
                                           '-fill' => $Cfg->{'mkcockpit'}->{'ColorWpResend'},
693
                                  );
694
        $WaypointsModified = 1;
695
 
696
        my $WpNum = $WpIndex + 1;
697
        $map_status_line->configure ('-text' => "$Translate{'WpMoved'}: $WpNum -> Lat: $Lat  Lon: $Lon     x: $x  y: $y");
698
        }
699
    });
700
 
701
# Mouse button 1 for POI
702
my $PoiOldx = 0;
703
my $PoiOldy = 0;
704
&PoiHide();
705
 
706
# Pick POI
707
$map_canvas->bind('POI' => '<Button-1>' => sub
708
    {
709
    # prepare to move Icon
710
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
711
    $PoiOldx = $x;
712
    $PoiOldy = $y;
713
    });
714
 
715
# Move POI
716
$map_canvas->bind('POI' => '<Button1-Motion>' => sub
717
    {
718
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
719
    my $id      = $map_canvas->find('withtag', 'current');
720
 
721
    $map_canvas->move($id => $x - $PoiOldx, $y - $PoiOldy);
722
    $PoiOldx = $x;
723
    $PoiOldy = $y;
724
    });
725
 
726
# Release POI
727
$map_canvas->bind('POI' => '<Button1-ButtonRelease>' => sub
728
    {
729
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
730
    my $id      = $map_canvas->find('withtag', 'current');
731
 
732
    my ($x0, $y0, $x1, $y1) = $map_canvas->bbox ($id);
733
    $x = $x0 + ($x1 - $x0)/2;
734
    $y = $y1;
735
 
736
    ($Poi_Lat, $Poi_Lon) = &MapXY2Gps($x, $y);
737
 
738
    $map_status_line->configure ('-text' => "$Translate{'PoiMoved'}: ->   Lat: $Poi_Lat  Lon: $Poi_Lon     x: $x  y: $y");
739
    });
740
 
741
 
742
# Reset Flight time
743
$map_canvas->bind('MK-OSD-Tim-Value' => '<Button-1>' => sub
744
    {
745
    $MkFlyingTime = 0;
746
    });
747
 
748
# Reset ODO
749
$map_canvas->bind('MK-OSD-Odo-Value' => '<Button-1>' => sub
750
    {
751
    $OdoMeter = 0;
752
    });
753
 
754
 
755
#
756
# Mouse button 3 context menu
757
#
758
my $map_menu = $map_canvas->Menu('-tearoff' => 0,
759
                                 '-title' =>'None',
760
                                 '-menuitems' =>
761
    [
762
     [Button => $Translate{'WpAddAndSend'},  -command => sub
763
        {
764
        # send Wp to MK         
765
        my ($Lat, $Lon) = &MapXY2Gps($MapCanvasX, $MapCanvasY);
766
        &MkFlyTo ( -lat => $Lat,
767
                   -lon => $Lon,
768
                   -mode => "Waypoint",
769
                   -index => scalar @Waypoints,
770
                 );
771
 
772
        # Add Wp to Waypoints list
773
        &WpAdd (-lat => $Lat,
774
                -lon => $Lon,
775
                -x   => $MapCanvasX,
776
                -y   => $MapCanvasY,
777
               );
778
 
779
        # switch player to Wp mode and redraw waypoints
780
        &PlayerWpt();
781
 
782
        $map_status_line->configure ('-text' => "$Translate{'WpSavedAndSent'} -> Lat: $Lat Lon: $Lon");
783
        }],
784
 
785
 
786
     [Button => $Translate{'WpProperties'},  -command => sub
787
        {
788
        # find Wp-Hash for selected icon/tag
789
        my $WpIndex = &WpGetIndexFromId($MapCanvasId);
790
        if ( $WpIndex >= 0 )
791
            {
792
            my $Wp = $Waypoints[$WpIndex];
793
            my $WpNum = $WpIndex + 1;
794
 
795
            &DisplayHash ($Wp, "$Translate{'WpProperties'} $WpNum", "Edit Waypoint Refresh");
796
 
797
            $map_status_line->configure ('-text' => "$Translate{'WpProperties'} $WpNum");
798
            }
799
        }],
800
 
801
     [Button => $Translate{'WpResendAll'},  -command => sub
802
        {
803
        &WpSendAll();
804
 
805
        $map_status_line->configure ('-text' => $Translate{'WpAllSent'});
806
        }],
807
 
808
      '',   # Separator
809
 
810
     [Button => $Translate{'WpLoadAndSend'},  -command => sub
811
        {
812
        my $WpFile = $main->getOpenFile('-defaultextension' => ".xml",
813
                                        '-filetypes'        =>
814
                                            [['Mission Cockpit',  '.xml' ],
815
                                             ['Mikrokopter Tool', '.wpl' ],
816
                                             ['All Files',     '*', ],
817
                                            ],
818
                                        '-initialdir' => $Cfg->{'waypoint'}->{'WpDir'},
819
                                        '-title' => $Translate{'WpLoad'},
820
                                       );
821
        if ( -f $WpFile )
822
            {
823
            &WpLoadFile ($WpFile);
824
 
825
            # send all Wp to MK
826
            &WpSendAll();
827
 
828
            # switch player to Wp mode and redraw waypoints
829
            $PlayerRandomMode  = 'STD';
830
            &PlayerWpt();
831
 
832
            $map_status_line->configure ('-text' => "$Translate{'WpLoadedAndSent'}: $WpFile");
833
            }
834
        }],    
835
 
836
     [Button => $Translate{'WpSave'},  -command => sub
837
        {
838
        my $WpFile = $main->getSaveFile('-defaultextension' => ".xml",
839
                                        '-filetypes'        =>
840
                                         [['Mission Cockpit',  '.xml' ],
841
                                          ['Mikrokopter Tool', '.wpl' ],
842
                                          ['All Files',     '*', ],
843
                                          ],
844
                                        '-initialdir' => $Cfg->{'waypoint'}->{'WpDir'},
845
                                        '-title' => $Translate{'WpSave'},
846
                                       );
847
 
848
        &WpSaveFile ($WpFile);
849
 
850
        $map_status_line->configure ('-text' => "$Translate{'WpSaved'}: $WpFile");
851
        }],
852
 
853
     '',   # Separator
854
 
855
     [Button => $Translate{'WpDelete'},  -command => sub
856
        {
857
        # find Wp-Hash for selected icon/tag
858
        my $WpIndex = &WpGetIndexFromId($MapCanvasId);
859
        if ( $WpIndex >= 0 )
860
            {
861
            &WpDelete ($WpIndex);
862
 
863
            # redraw connector-lines
864
            $WaypointsModified = 1;
865
            &WpRedrawLines();  
866
            &WpRedrawIcons();  # wg. Wp-Nummern
867
 
868
            my $WpNum = $WpIndex + 1;
869
            $map_status_line->configure ('-text' => "$Translate{'WpDeleted'}: $WpNum");
870
            }
871
        }],
872
 
873
     [Button => $Translate{'WpAllDeleteAndSend'},  -command => sub
874
        {
875
        &WpDeleteAll();
876
        &WpSendAll();
877
 
878
        $map_status_line->configure ('-text' => "$Translate{'WpAllDeleted'}: $WpIndex");
879
        }],
880
 
881
    '',   # Separator
882
 
883
     [Button => $Translate{'KmlLoadAndPlay'},  -command => sub
884
        {
885
        $KmlFile = $main->getOpenFile('-defaultextension' => ".kml",
886
                                     '-filetypes'        =>
887
                                         [['KML',           '.kml' ],
888
                                          ['All Files',     '*', ],
889
                                         ],
890
                                     '-initialdir' => $Cfg->{'waypoint'}->{'KmlDir'},
891
                                     '-title' => $Translate{'KmlLoad'},
892
                                    );
893
        if ( -f $KmlFile )
894
            {
895
            &KmlLoadFile($KmlFile);
896
 
897
            # switch player to KML mode and redraw track
898
            &PlayerKml();
899
 
900
            $map_status_line->configure ('-text' => "$Translate{'KmlLoaded'}: $KmlFile" );
901
            }
902
 
903
        }],
904
    ]
905
                                    );
906
$map_canvas->CanvasBind("<Button-3>" => [ sub
907
    {
908
    $map_canvas->focus;
909
    my($w, $x, $y) = @_;
910
    ($MapCanvasX, $MapCanvasY) = ($Tk::event->x, $Tk::event->y);
911
    $MapCanvasId = $map_canvas->find('withtag', 'current');
912
    $map_menu->post($x, $y);
913
    }, Ev('X'), Ev('Y') ] );
914
 
915
 
916
# Mouse bindings
917
$map_canvas->bind('Wp-PlayPause' => '<Button-1>' => \&CbPlayerPlayPause );
918
$map_canvas->bind('Wp-Next'      => '<Button-1>' => \&CbPlayerNext );
919
$map_canvas->bind('Wp-Prev'      => '<Button-1>' => \&CbPlayerPrev );
920
$map_canvas->bind('Wp-First'     => '<Button-1>' => \&CbPlayerFirst );
921
$map_canvas->bind('Wp-Last'      => '<Button-1>' => \&CbPlayerLast );
922
$map_canvas->bind('Wp-Home'      => '<Button-1>' => \&CbPlayerHome );
923
$map_canvas->bind('Wp-Stop'      => '<Button-1>' => \&CbPlayerStop );
924
$map_canvas->bind('Wp-WptKml'    => '<Button-1>' => \&CbPlayerWptKml );
925
$map_canvas->bind('Wp-WptRandom' => '<Button-1>' => \&CbPlayerWptRandom );
926
$map_canvas->bind('Wp-Record'    => '<Button-1>' => \&CbPlayerRecord );
927
 
928
 
929
# Focus Canvas, if any key pressed. Needed for the following key-bindings
930
my $bBindFocus = 0;
931
$main->bind('<Any-Enter>' => sub
932
    {
933
    if ($bBindFocus == 0)
934
        {
935
        # focus only once. Verhindern vom canvas-popup, wenn Config-Dialog aktiv ist.
936
        # funktioniert so, habe aber keine Ahnung warum
937
        $map_canvas->Tk::focus;
938
        $bBindFocus = 1;
939
        }
940
    });
941
 
942
 
943
# Disable default arrow-key bindings on canvas
944
$main->bind('Tk::Canvas',"<$_>",undef)for qw /Left Right Up Down/;
945
 
946
# keyboard bindings
947
$map_canvas->Tk::bind( '<Key-space>' , \&CbPlayerPlayPause );
948
$map_canvas->Tk::bind( '<Key-n>'     , \&CbPlayerNext );
949
$map_canvas->Tk::bind( '<Key-p>'     , \&CbPlayerPrev );
950
$map_canvas->Tk::bind( '<Key-f>'     , \&CbPlayerFirst );
951
$map_canvas->Tk::bind( '<Key-l>'     , \&CbPlayerLast );
952
$map_canvas->Tk::bind( '<Key-h>'     , \&CbPlayerHome );
953
$map_canvas->Tk::bind( '<Key-s>'     , \&CbPlayerStop );
954
$map_canvas->Tk::bind( '<Key-w>'     , \&CbPlayerWptKml );
955
$map_canvas->Tk::bind( '<Key-k>'     , \&CbPlayerWptKml );
956
$map_canvas->Tk::bind( '<Key-r>'     , \&CbPlayerWptRandom );
957
$map_canvas->Tk::bind( '<Key-a>'     , \&CbPlayerRecord );
958
$map_canvas->Tk::bind( '<Key-m>'     , \&CbPlayerMute );
959
$map_canvas->Tk::bind( '<Key-v>'     , \&CbPoi );
960
$map_canvas->Tk::bind( '<Key-g>'     , \&CbGrid );
961
$map_canvas->Tk::bind( '<Key-x>'     , \&CbPlayerPauseMode );
962
$map_canvas->Tk::bind( '<Key-0>'     , [\&CbPlayerNum, "0"] );
963
$map_canvas->Tk::bind( '<Key-1>'     , [\&CbPlayerNum, "1"] );
964
$map_canvas->Tk::bind( '<Key-2>'     , [\&CbPlayerNum, "2"] );
965
$map_canvas->Tk::bind( '<Key-3>'     , [\&CbPlayerNum, "3"] );
966
$map_canvas->Tk::bind( '<Key-4>'     , [\&CbPlayerNum, "4"] );
967
$map_canvas->Tk::bind( '<Key-5>'     , [\&CbPlayerNum, "5"] );
968
$map_canvas->Tk::bind( '<Key-6>'     , [\&CbPlayerNum, "6"] );
969
$map_canvas->Tk::bind( '<Key-7>'     , [\&CbPlayerNum, "7"] );
970
$map_canvas->Tk::bind( '<Key-8>'     , [\&CbPlayerNum, "8"] );
971
$map_canvas->Tk::bind( '<Key-9>'     , [\&CbPlayerNum, "9"] );
972
$map_canvas->Tk::bind( '<Key-Left>'  , [\&CbPlayerMove, -1,  0] );
973
$map_canvas->Tk::bind( '<Key-Right>' , [\&CbPlayerMove,  1,  0] );
974
$map_canvas->Tk::bind( '<Key-Up>'    , [\&CbPlayerMove,  0,  1] );
975
$map_canvas->Tk::bind( '<Key-Down>'  , [\&CbPlayerMove,  0, -1] );
976
$map_canvas->Tk::bind( '<Key-Escape>', \&CbExit );
977
$map_canvas->Tk::bind( '<Key-Return>', \&CbTxOnOff );
978
 
979
# Fct-Keys F1 .. F12
980
for ($i=1; $i <= 12; $i++)
981
    {
982
    $map_canvas->Tk::bind( "<KeyPress-F$i>",   [\&CbFctKeyPress,   "$i"] );
983
    $map_canvas->Tk::bind( "<KeyRelease-F$i>", [\&CbFctKeyRelease, "$i"] );
984
    }
985
$Stick{'FctKey'} = 0;
986
 
987
 
988
#
989
# Load Start Scenario
990
#
991
 
992
# Waypoint file
993
my $CfgVal = $Cfg->{'StartScenario'}->{'WpFile'};
994
if ( ! -f $CfgVal )
995
    {
996
    $CfgVal = $Cfg->{'waypoint'}->{'WpDir'} . "/" . $Cfg->{'StartScenario'}->{'WpFile'};
997
    }
998
if ( -f $CfgVal )
999
    {
1000
    &WpLoadFile($CfgVal);
1001
 
1002
    # send all Wp to MK
1003
    &WpSendAll();
1004
    }
1005
 
1006
# KML file
1007
my $CfgVal = $Cfg->{'StartScenario'}->{'KmlFile'};
1008
if ( ! -f $CfgVal )
1009
    {
1010
    $CfgVal = $Cfg->{'waypoint'}->{'KmlDir'} . "/" . $Cfg->{'StartScenario'}->{'KmlFile'};
1011
    }
1012
if ( -f $CfgVal )
1013
    {
1014
    &KmlLoadFile($CfgVal);
1015
    }
1016
 
1017
# PLayer Mode
1018
my $CfgVal  = $Cfg->{'StartScenario'}->{'PlayerMode'};
1019
if ( $CfgVal =~ /Play/i )  { &PlayerPlay(); }
1020
if ( $CfgVal =~ /Pause/i ) { &PlayerPause(); }
1021
if ( $CfgVal =~ /Home/i )  { &PlayerHome(); }
1022
if ( $CfgVal =~ /Stop/i )  { &PlayerStop(); }
1023
 
1024
# Player Random Mode
1025
my $CfgVal  = $Cfg->{'StartScenario'}->{'PlayerRandomMode'};
1026
if ( $CfgVal eq "STD" ) { &PlayerRandomStd(); }
1027
if ( $CfgVal eq "RND" ) { &PlayerRandomRnd(); }
1028
if ( $CfgVal eq "MAP" ) { &PlayerRandomMap(); }
1029
 
1030
# PLayer Wpt/Kml Mode
1031
my $CfgVal  = $Cfg->{'StartScenario'}->{'PlayerWptKmlMode'};
1032
if ( $CfgVal eq "WPT" )  { &PlayerWpt(); }
1033
if ( $CfgVal eq "KML" )  { &PlayerKml(); }
1034
 
1035
# PLayer Pause Mode
1036
my $CfgVal  = $Cfg->{'StartScenario'}->{'PlayerPauseMode'};
1037
if ( $CfgVal eq "MAP" )  { &PlayerPauseMode("MAP"); }
1038
if ( $CfgVal eq "MK" )   { &PlayerPauseMode("MK"); }
1039
 
1040
# Audio TTS Mute
1041
my $CfgVal  = $Cfg->{'StartScenario'}->{'AudioMute'};
1042
if ( $CfgVal =~ /y/i )
1043
    {
1044
    $TtsMute = 1;    
1045
    }
1046
 
1047
# External-Contorl/Serial Channel Tx On/Off
1048
my $CfgVal  = $Cfg->{'StartScenario'}->{'TxExtOn'};
1049
if ( $CfgVal =~ /y/i )
1050
    {
1051
    $TxExtOn = 1;    
1052
    }
1053
 
1054
#
1055
# Timer
1056
#
1057
require "libmktimer.pl";
1058
 
1059
MainLoop();   # should never end
1060
 
1061
 
1062
#
1063
# Canvas handling
1064
# 
1065
 
1066
# Create map canvas
1067
sub CanvasCreate()
1068
    {
1069
    if ( defined $map_canvas )
1070
        {
1071
        # update size
1072
        $map_canvas->configure ('-width' => $MapSizeX,
1073
                                '-height' => $MapSizeY,
1074
                               );
1075
        }
1076
    else
1077
        {
1078
        # create new
1079
        $map_canvas = $frame_map->Canvas( '-width'  => $MapSizeX,
1080
                                          '-height' => $MapSizeY,
1081
                                          '-cursor' => 'cross',
1082
                                        ) -> pack();
1083
        }
1084
 
1085
    # Images and Icons on canvas
1086
    my @Icons = (
1087
                # Image             Tag             File                                       Pos_x            Pos_y
1088
                'Map',              'Map',          "$Cfg->{'map'}->{'MapDir'}/$Map{'File'}",  0,               0,
1089
                'HeartbeatSmall',   'Heartbeat',    "$Cfg->{'mkcockpit'}->{'IconHeartSmall'}", $MapSizeX/4-10,  10,
1090
                'HeartbeatLarge',   'Heartbeat',    "$Cfg->{'mkcockpit'}->{'IconHeartLarge'}", $MapSizeX/4-10,  -100,
1091
                'Satellite-Photo',  'Satellite',    "$Cfg->{'mkcockpit'}->{'IconSatellite'}",  $MapSizeX-50,    -100,
1092
                'Antenna-Photo',    'Track-Antenna',"$Cfg->{'track'}->{'IconAntenna'}",        0,               -50,
1093
                'POI-Photo',        'POI'          ,"$Cfg->{'mkcockpit'}->{'IconPoi'}",        $Poi_x,          $Poi_y,
1094
                'Waypoint-Photo',   'Waypoint',     "$Cfg->{'mkcockpit'}->{'IconWaypoint'}",   0,               -150,
1095
                'Target-Photo',     'Target',       "$Cfg->{'mkcockpit'}->{'IconTarget'}",     0,               -100,
1096
                'Fox-Photo',        'Fox',          "$Cfg->{'mkcockpit'}->{'IconFox'}",        $MapSizeX/2-100, $MapSizeY/2,
1097
                'WpPlay-Foto',      'Wp-PlayPause', "$Cfg->{'waypoint'}->{'IconPlay'}",        $MapSizeX/2+150, $MapSizeY-48,
1098
                'WpPause-Foto',     'Wp-PlayPause', "$Cfg->{'waypoint'}->{'IconPause'}",       $MapSizeX/2+150, -100,
1099
                'WpStop-Foto',      'Wp-Stop',      "$Cfg->{'waypoint'}->{'IconStop'}",        $MapSizeX/2+200, $MapSizeY-48,
1100
                'WpNext-Foto',      'Wp-Next',      "$Cfg->{'waypoint'}->{'IconNext'}",        $MapSizeX/2+50,  $MapSizeY-48,
1101
                'WpPrev-Foto',      'Wp-Prev',      "$Cfg->{'waypoint'}->{'IconPrev'}",        $MapSizeX/2,     $MapSizeY-48,
1102
                'WpFirst-Foto',     'Wp-First',     "$Cfg->{'waypoint'}->{'IconFirst'}",       $MapSizeX/2-50,  $MapSizeY-48,
1103
                'WpLast-Foto',      'Wp-Last',      "$Cfg->{'waypoint'}->{'IconLast'}",        $MapSizeX/2+100, $MapSizeY-48,
1104
                'WpHome-Foto',      'Wp-Home',      "$Cfg->{'waypoint'}->{'IconHome'}",        $MapSizeX/2-100, $MapSizeY-48,
1105
                'WpRecord-Foto',    'Wp-Record',    "$Cfg->{'waypoint'}->{'IconRecord'}",      $MapSizeX/2-150, $MapSizeY-48,
1106
                'WpRandomOff-Foto', 'Wp-WptRandom', "$Cfg->{'waypoint'}->{'IconRandomOff'}",   $MapSizeX/2-200, -100,
1107
                'WpRandomOn-Foto',  'Wp-WptRandom', "$Cfg->{'waypoint'}->{'IconRandomOn'}",    $MapSizeX/2-200, $MapSizeY-48,
1108
                'WpRandomMap-Foto', 'Wp-WptRandom', "$Cfg->{'waypoint'}->{'IconRandomMap'}",   $MapSizeX/2-200, -100,
1109
                'WpWpt-Foto',       'Wp-WptKml',    "$Cfg->{'waypoint'}->{'IconWpt'}",         $MapSizeX/2-250, $MapSizeY-48,
1110
                'WpKml-Foto',       'Wp-WptKml',    "$Cfg->{'waypoint'}->{'IconKml'}",         $MapSizeX/2-250, -100 ,
1111
                );
1112
    my $i = 0;
1113
    for $Icon (0 .. $#Icons/5)
1114
        {
1115
        my $Image =  $Icons[$i++];
1116
        my $Tag =    $Icons[$i++];
1117
        my $File =   $Icons[$i++];
1118
        my $Pos_x =  $Icons[$i++];
1119
        my $Pos_y =  $Icons[$i++];
1120
 
1121
        $map_canvas->Photo( $Image,
1122
                            -file => $File,
1123
                          );
1124
 
1125
        $map_canvas->delete($Tag);
1126
        $map_canvas->createImage( $Pos_x, $Pos_y,
1127
                                  -tags   => $Tag,
1128
                                  -anchor => 'nw',
1129
                                  -image  => $Image,
1130
                                );
1131
        }
1132
 
1133
 
1134
    # Calibration Points
1135
    $map_canvas->delete('Calibration');
1136
    $map_canvas->createLine ( $Map{'P1_x'}-8, $Map{'P1_y'},
1137
                              $Map{'P1_x'}+8, $Map{'P1_y'},
1138
                              $Map{'P1_x'},   $Map{'P1_y'},
1139
                              $Map{'P1_x'},   $Map{'P1_y'}-8,
1140
                              $Map{'P1_x'},   $Map{'P1_y'}+8,
1141
                              '-tags'  => 'Calibration',
1142
                              '-arrow' => 'none',
1143
                              '-fill'  => 'red',
1144
                              '-width' => 1,
1145
                             );
1146
    $map_canvas->createLine ( $Map{'P2_x'}-8, $Map{'P2_y'},
1147
                              $Map{'P2_x'}+8, $Map{'P2_y'},
1148
                              $Map{'P2_x'},   $Map{'P2_y'},
1149
                              $Map{'P2_x'},   $Map{'P2_y'}-8,
1150
                              $Map{'P2_x'},   $Map{'P2_y'}+8,
1151
                              '-tags'  => 'Calibration',
1152
                              '-arrow' => 'none',
1153
                              '-fill'  => 'red',
1154
                              '-width' => 1,
1155
                             );
1156
 
1157
    # display scale on canvas
1158
    my $x1 = $MapSizeX/2 +280;
1159
    my $x2 = $MapSizeX -30;
1160
    my $y1 = $MapSizeY - 20;
1161
    my $y2 = $MapSizeY - 15;
1162
    if ( $x2 - $x1 > 150 )
1163
        {
1164
        $x1 = $x2 - 150;
1165
        }
1166
 
1167
    $map_canvas->delete('Scale');
1168
    $map_canvas->createLine ( $x1, $y1,
1169
                              $x1, $y2,
1170
                              $x2, $y2,
1171
                              $x2, $y1,
1172
                              '-tags'  => 'Scale',
1173
                              '-arrow' => 'none',
1174
                              '-fill'  => 'red',
1175
                              '-fill' => $Cfg->{'mkcockpit'}->{'ColorScale'} || 'white',
1176
                              '-width' => 1,
1177
                              );
1178
 
1179
    my ($Lat1, $Lon1) = &MapXY2Gps($x1, $y1);
1180
    my ($Lat2, $Lon2) = &MapXY2Gps($x2, $y2);
1181
    my ($Dist, $Bearing) = &MapGpsTo($Lat1, $Lon1, $Lat2, $Lon2 );
1182
    $Dist = sprintf ("%.2f m", $Dist);
1183
    $map_canvas->delete('Scale-Text');
1184
    $map_canvas->createText ( $x1 + ($x2 - $x1)/2 - 20, $y1 - ($y2 - $y1)/2,
1185
                              '-tags' => 'Scale-Text',
1186
                              '-text' => $Dist,
1187
                              '-anchor' => 'w',
1188
                              '-font' => '-*-Arial-Bold-R-Normal--*-120-*',
1189
                              '-fill' => $Cfg->{'mkcockpit'}->{'ColorScale'} || 'white',
1190
                              );
1191
 
1192
    # border polygon
1193
    $map_canvas->delete('Map-Border');
1194
    $map_canvas->createPolygon( @Map{'Border'},
1195
                               '-tags' => 'Map-Border',
1196
                               '-fill' => '',
1197
                               '-outline' => $Cfg->{'mkcockpit'}->{'ColorAirfield'}, '-width' => 2,
1198
                              );
1199
    $map_canvas->raise('Map-Border', 'Map');  # Border above Map
1200
 
1201
 
1202
    #
1203
    # dynamic objecs on canvas
1204
    #
1205
 
1206
    # current MK position on canvas
1207
    $MkPos_x = $MapSizeX/2;
1208
    $MkPos_y = $MapSizeY/2;
1209
 
1210
    # Line from MK to Home
1211
    $map_canvas->delete('MK-Home-Line');
1212
    $map_canvas->createLine ( $MapSizeX/2, $MapSizeY/2, $MapSizeX/2, $MapSizeY/2,
1213
                              '-tags' => 'MK-Home-Line',
1214
                              '-arrow' => 'none',
1215
                              '-fill' => $Cfg->{'mkcockpit'}->{'ColorHomeLine'},
1216
                              '-width' => 3,
1217
                             );
1218
 
1219
    # Text Entfernung positioniert an der Home-Linie
1220
    $map_canvas->delete('MK-Home-Dist');
1221
    $map_canvas->createText ( $MapSizeX/2 + 8, $MapSizeY/2 - 8,
1222
                              '-tags' => 'MK-Home-Dist',
1223
                              '-text' => '0 m',
1224
                              '-anchor' => 'w',
1225
                              '-font' => '-*-Arial-Bold-R-Normal--*-200-*',
1226
                              '-fill' => $Cfg->{'mkcockpit'}->{'ColorHomeDist'},
1227
                              );
1228
 
1229
    # Line from MK to Target, draw invisible out of sight
1230
    $map_canvas->delete('MK-Target-Line');
1231
    $map_canvas->createLine ( 0, -100, 0, -100,
1232
                              '-tags' => 'MK-Target-Line',
1233
                              '-arrow' => 'none',
1234
                              '-fill' => $Cfg->{'mkcockpit'}->{'ColorTargetLine'},
1235
                              '-width' => 3,
1236
                             );
1237
 
1238
    # Text Entfernung positioniert an der Target-Linie
1239
    $map_canvas->delete('MK-Target-Dist');
1240
    $map_canvas->createText ( 0, -100,
1241
                              '-tags' => 'MK-Target-Dist',
1242
                              '-text' => '0 m',
1243
                              '-anchor' => 'w',
1244
                              '-font' => '-*-Arial-Bold-R-Normal--*-200-*',
1245
                              '-fill' => $Cfg->{'mkcockpit'}->{'ColorTargetDist'},
1246
                              );
1247
 
1248
    # Line from MK to POI, draw invisible out of sight
1249
    $map_canvas->delete('MK-POI-Line');
1250
    $map_canvas->createLine ( 0, -200, 0, -200,
1251
                              '-tags' => 'MK-POI-Line',
1252
                              '-arrow' => 'none',
1253
                              '-fill' => $Cfg->{'mkcockpit'}->{'ColorPoiLine'},
1254
                              '-stipple' => "stipple4",
1255
                              '-width' => 1,
1256
                             );
1257
    $map_canvas->lower('MK-POI-Line', 'Target');
1258
 
1259
    # MK Geschwindigkeits-Vektor
1260
    $MapMkSpeedLen = 60;    # Länge Speed-Zeiger
1261
    my $x0 = $MapSizeX/2;
1262
    my $y0 = $MapSizeY/2;
1263
    my $x1 = $MapSizeX/2;
1264
    my $y1 = $MapSizeY/2 - $MapMkSpeedLen;
1265
    $map_canvas->delete('MK-Speed');
1266
    $map_canvas->createLine ( $x0, $y0, $x1, $y1,
1267
                              '-tags' => 'MK-Speed',
1268
                              '-arrow' => 'last',
1269
                              '-arrowshape' => [10, 10, 3 ],
1270
                              '-fill' => $Cfg->{'mkcockpit'}->{'ColorSpeedVector'},
1271
                              '-width' => 4,
1272
                             );
1273
 
1274
    # MK als Pfeilspitze einer Linie darstellen
1275
    $MapMkLen = 25;
1276
    my $x0 = $MapSizeX/2;
1277
    my $y0 = $MapSizeY/2 + $MapMkLen/2;
1278
    my $x1 = $MapSizeX/2;
1279
    my $y1 = $MapSizeY/2 - $MapMkLen/2;
1280
    $map_canvas->delete('MK-Arrow');
1281
    $map_canvas->createLine ( $x0, $y0, $x1, $y1,
1282
                              '-tags' => 'MK-Arrow',
1283
                              '-arrow' => 'last',
1284
                              '-arrowshape' => [25, 30, 10 ],
1285
                              '-fill' => $Cfg->{'mkcockpit'}->{'ColorMkSatNo'},
1286
                              '-width' => 1
1287
                             );
1288
 
1289
    # OSD Texte auf Karte anzeigen
1290
    my @Texts = (
1291
                # Tag                 Text         Pos_x           Pos_y  Font
1292
                'MK-OSD-Tim-Label',   "TIM",       $MapSizeX/2 + 30,  20, '-*-Arial-Bold-R-Normal--*-150-*',
1293
                'MK-OSD-Tim-Value',   "00:00",     $MapSizeX/2 + 80,  20, '-*-Arial-Bold-R-Normal--*-270-*',
1294
                'MK-OSD-Bat-Label',   "BAT",       $MapSizeX/2 + 30,  50, '-*-Arial-Bold-R-Normal--*-150-*',
1295
                'MK-OSD-Bat-Value',   "0.0 V",     $MapSizeX/2 + 80,  50, '-*-Arial-Bold-R-Normal--*-270-*',
1296
                'MK-OSD-Cap-Label',   "CAP",       $MapSizeX/2 - 150, 20, '-*-Arial-Bold-R-Normal--*-150-*',
1297
                'MK-OSD-Cap-Value',   "0.00 Ah",   $MapSizeX/2 - 100, 20, '-*-Arial-Bold-R-Normal--*-270-*',
1298
                'MK-OSD-Cur-Label',   "CUR",       $MapSizeX/2 - 150, 50, '-*-Arial-Bold-R-Normal--*-150-*',
1299
                'MK-OSD-Cur-Value',   "0.0 A",     $MapSizeX/2 - 100, 50, '-*-Arial-Bold-R-Normal--*-270-*',
1300
                'MK-OSD-Pow-Label',   "POW",       $MapSizeX/2 - 150, 80, '-*-Arial-Bold-R-Normal--*-150-*',
1301
                'MK-OSD-Pow-Value',   "0.0 W",     $MapSizeX/2 - 100, 80, '-*-Arial-Bold-R-Normal--*-270-*',
1302
                'MK-OSD-Spd-Label',   "SPD",       10,                20, '-*-Arial-Bold-R-Normal--*-150-*',
1303
                'MK-OSD-Spd-Value',   "0.0 km/h",  60,                20, '-*-Arial-Bold-R-Normal--*-270-*',
1304
                'MK-OSD-Alt-Label',   "ALT",       10,                50, '-*-Arial-Bold-R-Normal--*-150-*',
1305
                'MK-OSD-Alt-Value',   "0 m",       60,                50, '-*-Arial-Bold-R-Normal--*-270-*',
1306
                'MK-OSD-Odo-Label',   "ODO",       10,                80, '-*-Arial-Bold-R-Normal--*-150-*',
1307
                'MK-OSD-Odo-Value',   "0.000 km",  60,                80, '-*-Arial-Bold-R-Normal--*-270-*',
1308
                'MK-OSD-Sat-Label',   "SAT",       $MapSizeX - 230,   20, '-*-Arial-Bold-R-Normal--*-150-*',
1309
                'MK-OSD-Sat-Value',   "0",         $MapSizeX - 180,   20, '-*-Arial-Bold-R-Normal--*-270-*',
1310
                'MK-OSD-Wp-Label',    "WPT",       $MapSizeX - 230,   50, '-*-Arial-Bold-R-Normal--*-150-*',
1311
                'MK-OSD-Wp-Value',    "0 / 0",     $MapSizeX - 180,   50, '-*-Arial-Bold-R-Normal--*-270-*',
1312
                'MK-OSD-Mode-Label',  "MOD",       $MapSizeX - 230,   80, '-*-Arial-Bold-R-Normal--*-150-*',
1313
                'MK-OSD-Mode-Value',  "",          $MapSizeX - 180,   80, '-*-Arial-Bold-R-Normal--*-270-*',
1314
                'MK-OSD-Rec-Value',   "",          $MapSizeX - 180,  110, '-*-Arial-Bold-R-Normal--*-200-*',
1315
                );
1316
    my $i = 0;
1317
    for $Text (0 .. $#Texts/5)
1318
        {
1319
        my $Tag =   $Texts[$i++];
1320
        my $Text =  $Texts[$i++];
1321
        my $Pos_x = $Texts[$i++];
1322
        my $Pos_y = $Texts[$i++];
1323
        my $Font =  $Texts[$i++];
1324
 
1325
        $map_canvas->delete($Tag);
1326
        $map_canvas->createText ( $Pos_x, $Pos_y,
1327
                                  '-tags' => $Tag,
1328
                                  '-text' => $Text,
1329
                                  '-font' => $Font,
1330
                                  '-fill' => $Cfg->{'mkcockpit'}->{'ColorOsd'},
1331
                                  '-anchor' => 'w',
1332
                                 );
1333
        }
1334
 
1335
 
1336
    # Variometer on canvas
1337
    $map_canvas->delete('Map-Variometer-Skala');
1338
 
1339
    my @Polygon;
1340
    for ( $y = -100; $y <= 100; $y += 10)
1341
        {
1342
        my $Len = 5;
1343
        if ( ($y % 50) == 0 )
1344
            {
1345
            $Len = 10;
1346
            $map_canvas->createText ( $Len+5, $MapSizeY/2 + $y,
1347
                                      '-tags' => 'Map-Variometer-Skala',
1348
                                      '-text' => sprintf ("%3d", -$y / 10),
1349
                                      '-anchor' => 'w',
1350
                                      '-font' => '-*-Arial-Normal-R-Normal--*-150-*',
1351
                              '-fill' => $Cfg->{'mkcockpit'}->{'ColorVariometer'},
1352
                              );
1353
            }
1354
        push @Polygon, (   0, $MapSizeY/2 + $y);
1355
        push @Polygon, ($Len, $MapSizeY/2 + $y);
1356
        push @Polygon, (   0, $MapSizeY/2 + $y);
1357
        }
1358
 
1359
    $map_canvas->delete('Map-Variometer');
1360
    $map_canvas->createLine(@Polygon,
1361
                            '-tags' => 'Map-Variometer',
1362
                            '-fill' => $Cfg->{'mkcockpit'}->{'ColorVariometer'},
1363
                            '-width' => 2,
1364
                            '-arrow' => 'none',
1365
                           );
1366
    # Vario Pointer
1367
    $map_canvas->delete('Map-Variometer-Pointer');
1368
    $map_canvas->createPolygon( 5, $MapSizeY/2, 20, $MapSizeY/2+10, 20, $MapSizeY/2-10,
1369
                               '-tags' => 'Map-Variometer-Pointer',
1370
                               '-fill' => $Cfg->{'mkcockpit'}->{'ColorVariometerPointer'},
1371
                               '-outline' => 'black', '-width' => 1,
1372
                              );
1373
 
1374
    # Crosshair
1375
    $map_canvas->delete('Map-Crosshair');
1376
    $map_canvas->createLine ( 0, $MapSizeY/2, $MapSizeX, $MapSizeY/2,
1377
                              '-tags' => ['Map-Crosshair', 'Map-Crosshair-X'],
1378
                              '-arrow' => 'none',
1379
                              '-fill' => $Cfg->{'map'}->{'CrosshairColor'},
1380
                              '-width' => 1,
1381
                            );
1382
    $map_canvas->createLine ( $MapSizeX/2, 0, $MapSizeX/2, $MapSizeY,
1383
                              '-tags' => ['Map-Crosshair', 'Map-Crosshair-Y'],
1384
                              '-arrow' => 'none',
1385
                              '-fill' => $Cfg->{'map'}->{'CrosshairColor'},
1386
                              '-width' => 1,
1387
                            );
1388
    $map_canvas->lower('Map-Crosshair', 'Map');   # hide below map
1389
 
1390
 
1391
    # Tracking Canvas
1392
 
1393
    if ( $Cfg->{'track'}->{'Active'} =~ /y/i )
1394
        {
1395
        # Canvas size
1396
        $TrackSizeX  = 125;
1397
        $TrackSizeY  = 100;
1398
        $TrackOffY   = $TrackSizeY - $MapSizeY + $TrackSizeY/2;
1399
        $TrackPtrLen = 50;    # Länge Zeiger
1400
 
1401
        # draw in map-canvas
1402
        $track_canvas = $map_canvas;
1403
 
1404
        # Ziffernblatt
1405
        my $x0 = $TrackSizeX/2 - $TrackPtrLen;
1406
        my $y0 = $TrackSizeY   + $TrackPtrLen - $TrackOffY;
1407
        my $x1 = $TrackSizeX/2 + $TrackPtrLen;
1408
        my $y1 = $TrackSizeY   - $TrackPtrLen - $TrackOffY;
1409
        $map_canvas->delete('Map-Tracker');
1410
        $track_canvas->createArc ( $x0, $y0, $x1, $y1,
1411
                                   '-tags'   => 'Map-Tracker',
1412
                                   '-extent' => '359',
1413
                                   '-start' => '0',
1414
                                   '-style' => 'chord',
1415
                                   '-outline' => 'gray', '-width' => '1',
1416
                                 );
1417
 
1418
        # Skala Ziffernblatt
1419
        for ($i=0; $i<360; $i+=15)
1420
            {
1421
            my $x0 = $TrackSizeX/2 - ($TrackPtrLen - 20) * cos( deg2rad $i );
1422
            my $y0 = $TrackSizeY   - ($TrackPtrLen - 20) * sin( deg2rad $i ) - $TrackOffY;
1423
            my $x1 = $TrackSizeX/2 - ($TrackPtrLen - 28) * cos( deg2rad $i );
1424
            my $y1 = $TrackSizeY   - ($TrackPtrLen - 28) * sin( deg2rad $i ) - $TrackOffY;
1425
            $track_canvas->createLine ( $x0, $y0, $x1, $y1,
1426
                                       '-tags'   => 'Map-Tracker',
1427
                                       '-fill' => 'white',
1428
                                       '-width' => 1,
1429
                                      );
1430
            }
1431
 
1432
        # Skala Beschriftung Ziffernblatt
1433
        for ($i=-180; $i<180; $i+=45)
1434
            {
1435
            my $x0 = $TrackSizeX/2 - ($TrackPtrLen - 12) * cos( deg2rad $i+90 );
1436
            my $y0 = $TrackSizeY   - ($TrackPtrLen - 12) * sin( deg2rad $i+90 ) - $TrackOffY;
1437
            $track_canvas->createText ( $x0, $y0,
1438
                                       '-tags'   => 'Map-Tracker',
1439
                                       '-text' => $i,
1440
                                       '-fill' => 'white',
1441
                                      );
1442
            }
1443
 
1444
        # Zeiger Pan
1445
        my $x0 = $TrackSizeX/2;
1446
        my $y0 = $TrackSizeY - 0 - $TrackOffY;
1447
        my $x1 = $TrackSizeX/2;
1448
        my $y1 = $TrackSizeY - ($TrackPtrLen - 22) - $TrackOffY;
1449
        $track_canvas->createLine ( $x0, $y0, $x1, $y1,
1450
                                    '-tags' => [ 'Map-Tracker', 'Track-Ptr-Pan' ],
1451
                                    '-arrow' => 'last',
1452
                                    '-arrowshape' => [20, 30, 5 ],
1453
                                    '-fill' => 'red',
1454
                                    '-width' => 8,
1455
                                    );
1456
        # Zeiger Tilt
1457
        my $x0 = $TrackSizeX/2;
1458
        my $y0 = $TrackSizeY - 0 - $TrackOffY;
1459
        my $x1 = $TrackSizeX/2;
1460
        my $y1 = $TrackSizeY - ($TrackPtrLen - 22) - $TrackOffY;
1461
        $track_canvas->createLine ( $x0, $y0, $x1, $y1,
1462
                                    '-tags' => [ 'Map-Tracker', 'Track-Ptr-Tilt' ],
1463
                                    '-fill' => 'white',
1464
                                    '-width' => 1,
1465
                                  );
1466
 
1467
        # Zeiger Center
1468
        my $Dia = 7;
1469
        my $x0 = $TrackSizeX/2 - $Dia;
1470
        my $y0 = $TrackSizeY + $Dia - $TrackOffY;
1471
        my $x1 = $TrackSizeX/2 + $Dia;
1472
        my $y1 = $TrackSizeY   - $Dia - $TrackOffY;
1473
        $track_canvas->createArc ( $x0, $y0, $x1, $y1,
1474
                                   '-tags'   => 'Map-Tracker',
1475
                                   '-extent' => '359',
1476
                                   '-outline' => 'gray', '-width' => 1,
1477
                                   '-fill' => 'gray',
1478
                                 );
1479
        }
1480
 
1481
 
1482
    $map_status_line->configure ('-text' => "" );
1483
    $map_top_label->configure (-text => "$Translate{'Map'}: $Map{'Name'} ($Map{'File'})", );
1484
    }
1485
 
1486
 
1487
# Redraw map canvas after Map change
1488
sub CanvasRedraw()
1489
    {
1490
    # Aktuell gültige Karte
1491
    &MapSetCurrentFromCfg();
1492
 
1493
    # global map variables used everywhere
1494
    %Map = %{$Maps{'Current'}};
1495
    $MapSizeX  = $Map{'Size_X'};
1496
    $MapSizeY  = $Map{'Size_Y'};
1497
 
1498
    # Draw new Canvas
1499
    &CanvasCreate();
1500
 
1501
    # Re-calculate WP Lat/Lon from X/Y for map
1502
    &WpRecalc();
1503
 
1504
    # PLayer Mode
1505
    if ( $PlayerMode =~ /Play/i )  { &PlayerPlay(); }
1506
    if ( $PlayerMode =~ /Pause/i ) { &PlayerPause(); }
1507
    if ( $PlayerMode =~ /Home/i )  { &PlayerHome(); }
1508
    if ( $PlayerMode =~ /Stop/i )  { &PlayerStop(); }
1509
 
1510
    # Player Random Mode
1511
    if ( $PlayerRandomMode eq "STD" ) { &PlayerRandomStd(); }
1512
    if ( $PlayerRandomMode eq "RND" ) { &PlayerRandomRnd(); }
1513
    if ( $PlayerRandomMode eq "MAP" ) { &PlayerRandomMap(); }
1514
 
1515
    # PLayer Wpt/Kml Mode
1516
    if ( $PlayerWptKmlMode eq "WPT" )  { &PlayerWpt(); }
1517
    if ( $PlayerWptKmlMode eq "KML" )  { &PlayerKml(); }
1518
 
1519
    # PLayer Pause Mode
1520
    if ( $PlayerPauseMode eq "MAP" )  { &PlayerPauseMode("MAP"); }
1521
    if ( $PlayerPauseMode eq "MK" )   { &PlayerPauseMode("MK"); }
1522
 
1523
    # Set POI position
1524
    ($Poi_Lat, $Poi_Lon) = &MapXY2Gps($Poi_x + 24, $Poi_y + 48);
1525
    if ( $PoiMode )
1526
        {
1527
        &PoiShow();
1528
        }
1529
    else
1530
        {
1531
        &PoiHide();
1532
        }
1533
 
1534
 
1535
    # delete Footprint
1536
    @Footprint = ();
1537
    &FootprintRedraw();
1538
    }
1539
 
1540
 
1541
 
1542
# Start Web Browser with URL
1543
sub StartBrowser()
1544
    {
1545
    ($Url) = @_;
1546
    system ("start $Url")
1547
    }
1548
 
1549
#
1550
# GUI Call Back
1551
# 
1552
 
1553
# Player CallBack: Play/Pause button
1554
sub CbPlayerPlayPause()
1555
    {
1556
    if ( ($PlayerMode eq "Pause") or  ($PlayerMode eq "Stop") or  ($PlayerMode eq "Home") )
1557
        {
1558
        &PlayerPlay();
1559
        }
1560
    else
1561
        {
1562
        &PlayerPause();
1563
        }
1564
    }
1565
 
1566
 
1567
# Player CallBack: Next
1568
sub CbPlayerNext()
1569
    {
1570
    if ( $PlayerMode ne 'Stop' )
1571
        {
1572
        if ( $PlayerWptKmlMode eq 'WPT' )
1573
           {
1574
           &WpTargetNext();
1575
           }
1576
        if ( $PlayerWptKmlMode eq 'KML' )
1577
           {
1578
           &KmlTargetNext();
1579
           }
1580
        }
1581
    }
1582
 
1583
 
1584
# Player CallBack: Prev
1585
sub CbPlayerPrev()
1586
    {
1587
    if ( $PlayerMode ne 'Stop' )
1588
        {
1589
        if ( $PlayerWptKmlMode eq 'WPT' )
1590
           {
1591
           &WpTargetPrev();
1592
           }
1593
        if ( $PlayerWptKmlMode eq 'KML' )
1594
           {
1595
           &KmlTargetPrev();
1596
           }
1597
        }
1598
    }
1599
 
1600
 
1601
# Player CallBack: First
1602
sub CbPlayerFirst()
1603
    {
1604
    if ( $PlayerMode ne 'Stop' )
1605
        {
1606
        if ( $PlayerWptKmlMode eq 'WPT' )
1607
           {
1608
           &WpTargetFirst();
1609
           }
1610
        if ( $PlayerWptKmlMode eq 'KML' )
1611
           {
1612
           &KmlTargetFirst();
1613
           }
1614
        }
1615
    }
1616
 
1617
# Player CallBack: Last
1618
sub CbPlayerLast()
1619
    {
1620
    if ( $PlayerMode ne 'Stop' )
1621
        {
1622
        if ( $PlayerWptKmlMode eq 'WPT' )
1623
           {
1624
           &WpTargetLast();
1625
           }
1626
        if ( $PlayerWptKmlMode eq 'KML' )
1627
           {
1628
           &KmlTargetLast();
1629
           }
1630
        }
1631
    }
1632
 
1633
 
1634
# Player CallBack: Home
1635
sub CbPlayerHome()
1636
    {
1637
    if ( $PlayerMode ne 'Stop' )
1638
        {
1639
        &PlayerHome();
1640
        }
1641
    }
1642
 
1643
 
1644
# Player CallBack: Stop
1645
sub CbPlayerStop()
1646
    {
1647
    if ( $PlayerMode ne 'Stop' )
1648
        {
1649
        &PlayerStop();
1650
        }
1651
    }
1652
 
1653
 
1654
# Player CallBack: Move MK in Pause-Mode
1655
sub CbPlayerMove()
1656
    {
1657
    my ($Id, $DirX, $DirY) = @_;
1658
 
1659
    if ( $PlayerMode eq 'Pause'  and
1660
         $PlayerPause_Lat ne ""  and  $PlayerPause_Lon ne "" )
1661
        {
1662
        my $Dist = $Cfg->{'map'}->{'PauseMoveDist'} || 1;  # 1m default
1663
 
1664
        my $BearingTop = &MapAngel() - 90.0;
1665
        my $BearingKey = rad2deg atan2($DirX, $DirY);
1666
        my $Bearing = $BearingTop + $BearingKey;
1667
        if ( $PlayerPauseMode eq "MK" )
1668
            {
1669
            # MK Reference
1670
            $Bearing = $MkOsd{'CompassHeading'} + $BearingKey;
1671
            }
1672
 
1673
        ($PlayerPause_Lat, $PlayerPause_Lon) = &MapGpsAt($PlayerPause_Lat, $PlayerPause_Lon, $Dist, $Bearing);
1674
 
1675
        # restart crosshair display timer
1676
        $CrosshairTimerCnt = 0;
1677
        }
1678
    }
1679
 
1680
 
1681
# Player CallBack: Toggle WPT/KML button
1682
sub CbPlayerWptKml()
1683
    {
1684
 
1685
    if ( $PlayerWptKmlMode =~ /WPT/i )
1686
        {
1687
        &PlayerKml();
1688
        }
1689
    elsif ( $PlayerWptKmlMode =~ /KML/i )
1690
        {
1691
        &PlayerWpt();
1692
        }
1693
    }
1694
 
1695
 
1696
# Player CallBack: Toggle Random modes. STD -> RND -> MAP
1697
sub CbPlayerWptRandom()
1698
    {
1699
    if ( $PlayerRandomMode eq "STD" )
1700
        {
1701
        &PlayerRandomRnd();
1702
        }
1703
    elsif ( $PlayerRandomMode eq "RND" )
1704
        {
1705
        &PlayerRandomMap();
1706
        }
1707
    else
1708
        {
1709
        &PlayerRandomStd();
1710
        }
1711
    }
1712
 
1713
 
1714
# Player CallBack: Togglle Record KML
1715
sub CbPlayerRecord()
1716
    {
1717
    if ( $PlayerRecordMode =~ /REC/i )
1718
        {
1719
        &PlayerRecordOff();
1720
        }
1721
    elsif ( $PlayerRecordMode eq "" )
1722
        {
1723
        &PlayerRecordOn();
1724
        }
1725
    }
1726
 
1727
 
1728
# Player CallBack: Number Keys
1729
sub CbPlayerNum()
1730
    {
1731
    my ($Id, $Num) = @_;
1732
 
1733
    $CbPlayerKey = "$CbPlayerKey" . "$Num";
1734
    }
1735
 
1736
 
1737
# Player CallBack: mute TTS audio
1738
sub CbPlayerMute()
1739
    {
1740
    if ( $TtsMute )
1741
        {
1742
        &TtsMute(0);
1743
        }
1744
    else
1745
        {
1746
        &TtsMute(1);
1747
        }
1748
    }
1749
 
1750
# Switch POI Mode
1751
sub CbPoi()
1752
    {
1753
    if ( $PoiMode )
1754
        {
1755
        $PoiMode = 0;
1756
        &PoiHide();
1757
        }
1758
    else
1759
        {
1760
        $PoiMode = 1;
1761
        &PoiShow();
1762
        }
1763
    }
1764
 
1765
# Grid on canvas
1766
$GridIsOn = 0;
1767
sub CbGrid()
1768
    {
1769
    if ( $GridIsOn )
1770
        {
1771
        $GridIsOn = 0;
1772
        &GridHide();
1773
        }
1774
    else
1775
        {
1776
        $GridIsOn = 1;
1777
        &GridShow();
1778
        }
1779
    }
1780
 
1781
# Player Pause Mode
1782
sub CbPlayerPauseMode()
1783
    {
1784
    if ( $PlayerPauseMode eq "MAP" )
1785
        {
1786
        &PlayerPauseMode("MK");
1787
        }
1788
    else
1789
        {
1790
        &PlayerPauseMode("MAP");
1791
        }
1792
    }
1793
 
1794
# External-Control, SerialChannel On/Off
1795
sub CbTxOnOff()
1796
    {
1797
    if ( $TxExtOn == 1 )
1798
        {
1799
        $TxExtOn = 0;
1800
        }
1801
    else
1802
        {
1803
        $TxExtOn = 1;
1804
        }
1805
    }
1806
 
1807
 
1808
# Function Key Press
1809
sub CbFctKeyPress()
1810
    {
1811
    my ($Id, $Num) = @_;
1812
 
1813
    $Num --;
1814
    $Stick{'FctKey'} |= (1 << $Num);
1815
    }
1816
 
1817
 
1818
# Function Key Release
1819
sub CbFctKeyRelease()
1820
    {
1821
    my ($Id, $Num) = @_;
1822
 
1823
    $Num --;
1824
    $Stick{'FctKey'} ^= (1 << $Num);
1825
    }
1826
 
1827
 
1828
# CallBack: Exit Mission Cockpit
1829
sub CbExit()
1830
    {
1831
 
1832
    # stop 3D Mouse
1833
    &Mouse3DStop();
1834
 
1835
    # stop Joystick
1836
    &JoystickStop();
1837
 
1838
    # stop antenna tracking
1839
    $TrackQueue->enqueue( "IDLE" );
1840
 
1841
    # wait for tracker shutdown, with timeout
1842
    if ( $Cfg->{'track'}->{'Active'} =~ /y/i )
1843
        {
1844
        for ($i=0; $i < 5; $i++)
1845
            {
1846
            if ( $MkTrack{'State'} ne "Idle" )
1847
                {
1848
                sleep 1;
1849
                }
1850
            }
1851
        }
1852
 
1853
    exit;
1854
    }
1855
 
1856
 
1857
__END__