Subversion Repositories Projects

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
365 rain-er 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
#
43
###############################################################################
44
 
45
$Version = "0.1.0 - 2009-04-01";
46
 
47
use threads;            # http://search.cpan.org/~jdhedden/threads-1.72/threads.pm
48
                        # http://perldoc.perl.org/threads.html
49
use threads::shared;    # http://search.cpan.org/~jdhedden/threads-shared-1.28/shared.pm
50
use Thread::Queue;      # http://search.cpan.org/dist/Thread-Queue-2.11/lib/Thread/Queue.pm
51
use Tk;
52
use Tk::Balloon;
53
use Tk::Dialog;
54
use Tk::Notebook;
55
use Math::Trig;
56
use Time::HiRes qw(usleep);  # http://search.cpan.org/~jhi/Time-HiRes-1.9719/HiRes.pm
57
use XML::Simple;             # http://search.cpan.org/dist/XML-Simple-2.18/lib/XML/Simple.pm
58
 
59
# change working directory to program path
60
my $Cwd = substr ($0, 0, rindex ($0, "mkcockpit.pl"));
61
chdir $Cwd;
62
 
63
# set path for local Perl libs
64
push @INC, $Cwd . "perl/lib", $Cwd . "perl/site/lib";
65
 
66
# Version setting
67
share (%Version);
68
$Version{'mkcockpit.pl'}  = $Version;
69
 
70
# Read configuration
71
 
72
$XmlConfigFile = "mkcockpit.xml";
73
$Cfg = XMLin($XmlConfigFile);
74
 
75
require "track.pl";     # Tracking antenna
76
require "mkcomm.pl";    # MK communication
77
require "logging.pl";   # CSV and GPX Logging
78
require "geserver.pl";  # Google Earth Server
79
require "$Cfg->{'map'}->{'MapDir'}/map.pl";   # Landkarte
80
require "libmap.pl";    # map subs
81
require "translate.pl"; # Übersetzungstable
82
 
83
# Thread fuer Kommunikation mit MK starten
84
# Output: %MkOsd, %MkTarget, %MkNcDebug, %Mk
85
# Input:  Thread-Queue: $MkSendQueue
86
$mk_thr = threads->create (\&MkCommLoop) -> detach();
87
 
88
# Start Logging Thread
89
$log_thr = threads->create (\&MkLogLoop) -> detach();
90
 
91
# Start GoogleEarth Thread
92
$ge_thr = threads->create (\&GeServer) -> detach();
93
 
94
# Aktuell gültige Karte
95
my %Map = %{$Maps{'Current'}};
96
 
97
# Hauptfenster
98
my $main = new MainWindow;
99
$main->title ("MK Mission Cockpit");
100
 
101
#-----------------------------------------------------------------
102
# Menu
103
#-----------------------------------------------------------------
104
 
105
# Menu bar
106
my $menu_bar = $main->Menu;
107
$main->optionAdd("*tearOff", "false");
108
$main->configure ('-menu' => $menu_bar);
109
 
110
my $menu_file = $menu_bar->cascade('-label' => "~Datei");
111
    $menu_file->command('-label' => 'Einstellungen',
112
                        '-command' => [\&Configure],
113
                       );
114
    $menu_file->command('-label' => 'Ende',
115
                        '-command' => sub{exit(0)},
116
                        );
117
 
118
my $menu_debug = $menu_bar->cascade(-label => "D~ebug");
119
    $menu_debug->command('-label' => 'NC ~OSD Datensatz (O)',
120
                         '-command' => [\&DisplayHash, \%MkOsd, "NC OSD Datensatz (O)", "Display Refresh Heartbeat"],
121
                        );
122
    $menu_debug->command('-label' => 'NC ~Target Datensatz (s)',
123
                         '-command' => [\&DisplayHash, \%MkTarget, "NC Target Datensatz (s)", "Display Refresh Heartbeat"],
124
                        );
125
    $menu_debug->command('-label' => 'NC ~Debug Datensatz (D)',
126
                         '-command' => [\&DisplayHash, \%MkNcDebug, "NC Debug Datensatz (D)", "Display Refresh Heartbeat"],
127
                                        );             
128
    $menu_debug->command('-label' => 'NC ~Sonstiges',
129
                         '-command' => [\&DisplayHash, \%Mk, "NC Sonstiges", "Display Refresh Heartbeat"],
130
                                        );
131
    $menu_debug->separator;                                    
132
    $menu_debug->command('-label' => 'Tracking ~Antenne Debug Datensatz',
133
                         '-command' => [\&DisplayHash, \%MkTrack, "Tracking Antenne Debug Datensatz", "Display Refresh Heartbeat"],
134
                        );
135
 
136
my $menu_help = $menu_bar->cascade(-label => "~Hilfe");
137
    $menu_help->command('-label' => 'Version',
138
                        '-command' => [\&DisplayHash, \%Version, "Version", "Display"],
139
                       );
140
    $menu_help->separator;
141
    $menu_help->command('-label' => 'Über',
142
                        '-command' => sub
143
        {
144
        my $License = <<EOF;
145
Copyright (C) 2009  Rainer Walther (rainerwalther-mail\@web.de)
146
 
147
Creative Commons Lizenz mit den Zusaetzen (by, nc, sa)
148
 
149
Siehe LICENSE.TXT
150
EOF
151
 
152
        my $DlgAbout = $frame_map->Dialog('-title' => 'Über MK Mission Cockpit',
153
                                          '-text' => "$License",
154
                                          '-buttons' => ['OK'],
155
                                          '-bitmap' => 'info',
156
                                         );
157
        $DlgAbout->Show;
158
        });  
159
 
160
 
161
# Hauptfenster Statuszeile
162
$frame_status = $main->Frame( '-background' => 'lightgray',
163
                         ) -> pack('-side' => 'bottom',
164
                                   '-anchor' => 'w',
165
                                   '-fill' => 'none',
166
                                   '-expand' => 'y',
167
                                    );
168
$status_line = $frame_status->Label ('-text' => 'Statuszeile',
169
                                    ) -> pack ('-side' => 'bottom',
170
                                               );
171
 
172
 
173
#-----------------------------------------------------------------
174
# Frames
175
#-----------------------------------------------------------------                        
176
 
177
#
178
# Frame: Map
179
#
180
 
181
$frame_map = $main->Frame( '-background' => 'lightgray',
182
                           '-relief' => 'sunken',
183
                           '-borderwidth' => 5,
184
                          ) -> pack('-side' => 'top',
185
                                    '-fill' => 'x',
186
                                    );
187
 
188
# Map Überschrift
189
$frame_map_top = $frame_map->Frame() -> pack( '-side' => 'top',
190
                                              '-expand' => 'x',
191
                                              '-anchor' => 'w',
192
                                            );
193
 
194
$frame_map_top->Label ('-text' => "Karte: $Map{'Name'} ($Map{'File'})",
195
                       '-background' => 'lightgray',
196
                       '-relief' => 'flat',
197
                       ) -> pack( '-side' => 'left' );
198
 
199
# Map Statuszeile
200
$map_status = $frame_map->Frame( '-background' => 'lightgray',
201
                               ) -> pack('-side' => 'bottom',
202
                                         '-anchor' => 'w',
203
                                         '-fill' => 'none',
204
                                         '-expand' => 'y',
205
                                        );
206
$map_status_line = $map_status->Label ( '-text' => 'Statuszeile',
207
                                        '-background' => 'lightgray',
208
                                       ) -> pack ('-side' => 'bottom',);
209
 
210
# Map Canvas
211
 
212
# Canvas size
213
$MapSizeX  = $Map{'Size_X'};
214
$MapSizeY  = $Map{'Size_Y'};
215
 
216
$map_canvas = $frame_map->Canvas( '-width'  => $MapSizeX,
217
                                  '-height' => $MapSizeY,
218
                                  '-cursor' => 'cross',
219
                                ) -> pack();
220
 
221
# load Map photo
222
$map_canvas->Photo( 'Map',
223
                    '-file' => "$Cfg->{'map'}->{'MapDir'}/$Map{'File'}",
224
                  );
225
 
226
$map_canvas->createImage( 0, 0,
227
                          '-tags' => 'Map',
228
                          '-anchor' => 'nw',
229
                          '-image'  => 'Map',
230
                        );             
231
 
232
# border polygon
233
$map_canvas->createPolygon( @Map{'Border'},
234
                           '-tags' => 'Map-Border',
235
                           '-fill' => '',
236
                           '-outline' => $Cfg->{'mkcockpit'}->{'ColorAirfield'}, '-width' => 2,
237
                          );
238
 
239
# load Heartbeat icon
240
$map_canvas->Photo( 'HeartbeatSmall',
241
                    '-file' => "$Cfg->{'mkcockpit'}->{'IconHeartSmall'}",
242
                  );
243
$map_canvas->Photo( 'HeartbeatLarge',
244
                    '-file' => "$Cfg->{'mkcockpit'}->{'IconHeartLarge'}",
245
                  );
246
$map_canvas->createImage( $MapSizeX/4, 10,
247
                          '-tags' => 'Heartbeat',
248
                          '-anchor' => 'nw',
249
                          '-image'  => 'HeartbeatSmall',
250
                        );
251
 
252
# load Satellite icon
253
$map_canvas->Photo( 'Satellite-Photo',
254
                    '-file' => "$Cfg->{'mkcockpit'}->{'IconSatellite'}",
255
                               );
256
$map_canvas->createImage($MapSizeX-180, -100,   # hide photo 
257
                         '-tags' => 'Satellite',
258
                         '-anchor' => 'nw',
259
                         '-image'  => 'Satellite-Photo',
260
                        );
261
 
262
# load Waypoint icon
263
$map_canvas->Photo( 'Waypoint-Photo',
264
                    '-file' => "$Cfg->{'mkcockpit'}->{'IconWaypoint'}",
265
                  );
266
# load Target icon
267
$map_canvas->Photo( 'Target-Photo',
268
                    '-file' => "$Cfg->{'mkcockpit'}->{'IconTarget'}",
269
                  );
270
 
271
$map_canvas->createImage(0, -100,   # hide photo 
272
                         '-tags' => 'Target',
273
                         '-anchor' => 'nw',
274
                         '-image'  => 'Target-Photo',
275
                        );
276
 
277
# load Fox icon
278
$map_canvas->Photo( 'Fox-Photo',
279
                    '-file' => "$Cfg->{'mkcockpit'}->{'IconFox'}",
280
                  );
281
$map_canvas->createImage($MapSizeX/2+50, $MapSizeY/2,
282
                         '-tags' => 'Fox',
283
                         '-anchor' => 'nw',
284
                         '-image'  => 'Fox-Photo',
285
                        );
286
 
287
# Balloon attached to Canvas
288
$map_balloon = $frame_map->Balloon('-statusbar' => $status_line, );
289
$map_balloon->attach($map_canvas,
290
                     '-balloonposition' => 'mouse',
291
                     '-state' => 'balloon',
292
                     '-msg' => { 'MK-Arrow' => "MikroKopter",
293
                                 'MK-Home-Line' => "Hier gehts nach Hause",
294
                                 'MK-Home-Dist' => "Entfernung nach Hause",
295
                                 'MK-Target-Line' => "Hier gehts zum Ziel",
296
                                 'MK-Target-Dist' => "Entfernung zum Ziel",
297
                                 'MK-Speed' => 'Geschwindigkeits-Vektor',
298
                                 'Map-Variometer' => 'Variometer',
299
                                 'Map-Variometer-Pointer' => 'Variometer',
300
                                 'Map-Variometer-Skala' => 'Variometer',
301
                                 'Fox' => 'Ziel für Fuchsjagd',
302
                                 'Heartbeat' => 'Aktivität Datenübertragung zum MK',
303
                                 'Satellite' => 'Guter Satelliten-Empfang',
304
                                 'Waypoint' => 'Wegpunkt',
305
                                 'Map-Border' => 'Flugplatz',
306
                                 'Waypoint-Connector' => 'Verbinder Wegpunkte',
307
                               },
308
                    );
309
#
310
# Mouse buttons
311
#
312
 
313
# general Mouse button 1
314
$map_canvas->CanvasBind("<Button-1>", sub
315
    {
316
    # print coords in status line
317
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
318
    my ($Lat, $Lon) = &MapXY2Gps($x, $y);
319
    $map_status_line->configure ('-text' => "Lat: $Lat  Lon: $Lon     x: $x  y: $y");
320
    });
321
 
322
# Mouse button 1 for Fox
323
my $FoxOldx = 0;
324
my $FoxOldy = 0;
325
 
326
# Pick Fox
327
$map_canvas->bind('Fox' => '<Button-1>' => sub
328
    {
329
    # prepare to move Fox
330
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
331
    $FoxOldx = $x;
332
    $FoxOldy = $y;
333
    $FoxTime = time;
334
    });
335
 
336
# Move Fox
337
$map_canvas->bind('Fox' => '<Button1-Motion>' => sub
338
    {
339
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
340
    my $id      = $map_canvas->find('withtag', 'current');
341
 
342
    $map_canvas->move($id => $x - $FoxOldx, $y - $FoxOldy);
343
    $FoxOldx = $x;
344
    $FoxOldy = $y;
345
 
346
    if ( time > $FoxTime )
347
        {
348
          # wenn in Bewegung Koordinaten nur 1/s senden
349
        my ($x0, $y0, $x1, $y1) = $map_canvas->bbox ($id);
350
        $x = $x0 + ($x1 - $x0)/2;
351
        $y = $y1;
352
 
353
        &MkFlyTo ( '-x' => $x,
354
                   '-y' => $y,
355
                   '-mode' => "Target",
356
                 );
357
        $FoxTime = time;
358
 
359
        $map_status_line->configure ('-text' => "Ziel-Koordinaten gesendet -> Lat: $Lat  Lon: $Lon     x: $x  y: $y");
360
        }
361
    });
362
 
363
# Release Fox
364
$map_canvas->bind('Fox' => '<Button1-ButtonRelease>' => sub
365
    {
366
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
367
    my $id      = $map_canvas->find('withtag', 'current');
368
 
369
    my ($x0, $y0, $x1, $y1) = $map_canvas->bbox ($id);
370
    $x = $x0 + ($x1 - $x0)/2;
371
    $y = $y1;
372
 
373
    &MkFlyTo ( '-x' => $x,
374
               '-y' => $y,
375
               '-mode' => "Target"
376
             );
377
 
378
    # Show user that Waypoints in MK are cleared
379
    $WaypointsModified = 1;
380
    &WpRedrawLines();
381
 
382
    $map_status_line->configure ('-text' => "Ziel-Koordinaten gesendet -> Lat: $Lat  Lon: $Lon     x: $x  y: $y");
383
    });
384
 
385
# Pick Waypoint
386
$map_canvas->bind('Waypoint' => '<Button-1>' => sub
387
    {
388
    # prepare to move
389
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
390
    $WpOldx = $x;
391
    $WpOldy = $y;
392
    });
393
 
394
# Move Waypoint
395
$map_canvas->bind('Waypoint' => '<Button1-Motion>' => sub
396
    {
397
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
398
    my $id      = $map_canvas->find('withtag', 'current');
399
 
400
    # move icon and Wp-Number
401
    my $WpIndex = &WpGetIndexFromId($id);
402
    if ( $WpIndex >= 0 )
403
        {
404
        my $Tag = $Waypoints[$WpIndex]{'Tag'};
405
        $map_canvas->move($Tag => $x - $WpOldx, $y - $WpOldy);
406
        }
407
 
408
    $WpOldx = $x;
409
    $WpOldy = $y;
410
    });
411
 
412
# Release Wp
413
$map_canvas->bind('Waypoint' => '<Button1-ButtonRelease>' => sub
414
    {
415
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
416
    my $id      = $map_canvas->find('withtag', 'current');
417
 
418
    # take coords from lower/middle icon position
419
    my ($x0, $y0, $x1, $y1) = $map_canvas->bbox ($id);
420
    $x = $x0 + ($x1 - $x0)/2;
421
    $y = $y1;
422
 
423
    # update Waypoint-Array
424
    my $WpIndex = &WpGetIndexFromId($id);
425
    if ( $WpIndex >= 0 )
426
        {
427
        # got it: set new coords
428
 
429
        my ($Lat, $Lon) = &MapXY2Gps($x, $y);
430
        my $Wp = $Waypoints[$WpIndex];
431
        $Wp->{'MapX'} = $x;
432
        $Wp->{'MapY'} = $y;
433
        $Wp->{'Pos_Lat'} = $Lat;
434
        $Wp->{'Pos_Lon'} = $Lon;
435
 
436
        # redraw connector-lines
437
        &WpRedrawLines();
438
 
439
        # red connectors: Wp still have to be sent to MK
440
        $map_canvas->itemconfigure('Waypoint-Connector',
441
                                       '-fill' => $Cfg->{'mkcockpit'}->{'ColorWpResend'},
442
                                      );
443
        $WaypointsModified = 1;
444
 
445
        my $WpNum = $WpIndex + 1;
446
        $map_status_line->configure ('-text' => "Wegpunkt $WpNum verschoben  Lat: $Lat  Lon: $Lon     x: $x  y: $y");
447
        }
448
    });
449
 
450
# Mouse button 3 context menu
451
my $map_menu = $map_canvas->Menu('-tearoff' => 0,
452
                                 '-title' =>'None',
453
                                 '-menuitems' =>
454
    [
455
     [Button => "Wegpunkt hinzufügen und senden",  -command => sub
456
        {
457
        my $Tag = sprintf "Waypoint-%d.%d", time, int (rand(9)) ;   # kind of unique Tag for this Wp
458
 
459
        # Waypoint Icon
460
        my $IconHeight = 48;
461
        my $IconWidth = 48;
462
        $map_canvas->createImage($MapCanvasX-$IconWidth/2, $MapCanvasY-$IconHeight,
463
                                 '-tags' => ['Waypoint', $Tag],
464
                                 '-anchor' => 'nw',
465
                                 '-image'  => 'Waypoint-Photo',
466
                                );
467
 
468
        # Waypoint Number
469
        my $WpNumber = scalar @Waypoints + 1;
470
        $map_canvas->createText ( $MapCanvasX+3, $MapCanvasY-$IconHeight/2+12,
471
                                  '-tags' => ['WaypointNumber', $Tag],
472
                                  '-text' => $WpNumber,
473
                                  '-font' => '-*-Arial-Bold-R-Normal--*-100-*',
474
                                  '-fill' => $Cfg->{'mkcockpit'}->{'ColorWpNumber'},
475
                                  '-anchor' => 'w',
476
                                 );    
477
 
478
        $map_canvas->lower('Waypoint', 'Fox');            # waypoint below Fox
479
        $map_canvas->lower('WaypointNumber', 'Waypoint'); # Nr below waypoint
480
 
481
        # send Wp to MK         
482
        ($Lat, $Lon) = &MapXY2Gps($MapCanvasX, $MapCanvasY);
483
        &MkFlyTo ( '-lat' => $Lat,
484
                   '-lon' => $Lon,
485
                   '-mode' => "Waypoint"
486
                 );
487
 
488
        # save Wp-Hash in Waypoint-Array
489
        my $Wp = {};        
490
        $Wp->{'Tag'} = $Tag;
491
        $Wp->{'MapX'} = $MapCanvasX;
492
        $Wp->{'MapY'} = $MapCanvasY;
493
        $Wp->{'Pos_Lat'} = $Lat;
494
        $Wp->{'Pos_Lon'} = $Lon;
495
        $Wp->{'Pos_Alt'} = $MkOsd{'CurPos_Alt'};
496
        $Wp->{'Heading'}         = $Cfg->{'waypoint'}->{'DefaultHeading'};
497
        $Wp->{'ToleranceRadius'} = $Cfg->{'waypoint'}->{'DefaultToleranceRadius'};
498
        $Wp->{'Holdtime'}        = $Cfg->{'waypoint'}->{'DefaultHoldtime'};
499
        $Wp->{'Event_Flag'}      = $Cfg->{'waypoint'}->{'DefaultEventFlag'};
500
        push @Waypoints, $Wp;
501
 
502
        # redraw connector-lines
503
        &WpRedrawLines();  
504
 
505
        $map_status_line->configure ('-text' => "Wegpunkt gespeichert und gesendet -> Lat: $Lat Lon: $Lon");
506
        }],
507
 
508
 
509
     [Button => "Wegpunkt Eigenschaften",  -command => sub
510
        {
511
 
512
 
513
        # find Wp-Hash for selected icon/tag
514
        my $WpIndex = &WpGetIndexFromId($MapCanvasId);
515
        if ( $WpIndex >= 0 )
516
            {
517
            my $Wp = $Waypoints[$WpIndex];
518
            my $WpNum = $WpIndex + 1;
519
 
520
            &DisplayHash ($Wp, "Eigenschaften Wegpunkt $WpNum", "Edit Waypoint Refresh");
521
 
522
            $map_status_line->configure ('-text' => "Wegpunkt $WpNum Eigenschaften");
523
            }
524
        }],
525
 
526
     [Button => "Alle Wegpunkte erneut senden",  -command => sub
527
        {
528
        &WpSendAll();
529
 
530
        $map_status_line->configure ('-text' => "Alle Wegpunkte gesendet");
531
        }],
532
 
533
      '',   # Separator
534
 
535
     [Button => "Wegpunkte laden und senden",  -command => sub
536
        {
537
        $WpFile = $main->getOpenFile('-defaultextension' => ".xml",
538
                                     '-filetypes'        =>
539
                                         [['Waypoints',     '.xml' ],
540
                                          ['All Files',     '*', ],
541
                                         ],
542
                                     '-initialdir' => $Cfg->{'waypoint'}->{'WpDir'},
543
                                     '-title' => "Wegpunkte laden",
544
                                    );
545
        if ( -f $WpFile )
546
            {
547
            # XML in Hash-Ref lesen
548
            my $Wp = XMLin($WpFile, ForceArray => 1);
549
 
550
            # XML Hash-Ref in Wp-Array umkopieren
551
            undef @Waypoints;
552
            foreach $key (sort keys %$Wp)
553
                {
554
                my $Point = $Wp->{$key}->[0];
555
 
556
                # GPS Koordinaten für die aktuelle Karte neu aus Map x/y berechnen
557
                my ($Lat, $Lon) = &MapXY2Gps($Point->{'MapX'}, $Point->{'MapY'});
558
                $Point->{'Pos_Lat'} = $Lat;
559
                $Point->{'Pos_Lon'} = $Lon;
560
 
561
                push @Waypoints, $Point;
562
                }
563
 
564
            &WpSendAll();
565
            &WpRedrawLines();
566
            &WpRedrawIcons();
567
 
568
            $map_status_line->configure ('-text' => "Wegpunkte aus $WpFile geladen und gesendet");
569
            }
570
        }],    
571
 
572
     [Button => "Wegpunkte speichern",  -command => sub
573
        {
574
        $WpFile = $main->getSaveFile('-defaultextension' => ".xml",
575
                                     '-filetypes'        =>
576
                                       [['Waypoints',     '.xml' ],
577
                                        ['All Files',     '*', ],
578
                                       ],
579
                                     '-initialdir' => $Cfg->{'waypoint'}->{'WpDir'},
580
                                     '-title' => "Wegpunkte speichern",
581
                                    );
582
 
583
        # Waypoint-Array in Hash umkopieren
584
        my %Wp;
585
        for  $i ( 0 .. $#Waypoints )
586
            {
587
            my $key = sprintf ("WP-%04d", $i);
588
            $Wp{$key} = $Waypoints[$i];
589
            }
590
 
591
        # WP-Hash als XML speichern
592
        &XMLout (\%Wp,
593
                 'OutputFile' => $WpFile,
594
                 'AttrIndent' => '1',
595
                 'RootName' => 'Waypoints',
596
                );
597
 
598
        $map_status_line->configure ('-text' => "Wegpunkte in $WpFile gespeichert");
599
        }],
600
 
601
     '',   # Separator
602
 
603
     [Button => "Wegpunkt löschen",  -command => sub
604
        {
605
        # find Wp-Hash for selected icon/tag
606
        my $WpIndex = &WpGetIndexFromId($MapCanvasId);
607
        if ( $WpIndex >= 0 )
608
            {
609
            my $Wp = $Waypoints[$WpIndex];
610
 
611
            # remove icon and Wp-Number on canvas;
612
            $map_canvas->delete($Wp->{'Tag'});
613
 
614
            # delete Wp in Waypoint-Array
615
            splice @Waypoints, $WpIndex, 1;
616
 
617
            # redraw connector-lines
618
            $WaypointsModified = 1;
619
            &WpRedrawLines();  
620
            &WpRedrawIcons();  # wg. Wp-Nummern
621
 
622
            $WpNum = $WpIndex + 1;
623
            $map_status_line->configure ('-text' => "Wegpunkt $WpNum gelöscht");
624
            }
625
        }],
626
 
627
     [Button => "Alle Wegpunkte löschen und senden",  -command => sub
628
        {
629
        undef @Waypoints;
630
 
631
        # remove all Wp-Icons and Wp-Number on canvas
632
        $map_canvas->delete('Waypoint');
633
        $map_canvas->delete('WaypointNumber');
634
 
635
        # redraw connector-lines
636
        &WpRedrawLines();  
637
 
638
        &WpSendAll();
639
 
640
        $map_status_line->configure ('-text' => "Alle Wegpunkte $WpIndex gelöscht");
641
        }],
642
 
643
    '',   # Separator
644
 
645
     [Button => "Ziel sofort anfliegen",  -command => sub
646
        {
647
        &MkFlyTo ( '-x' => $MapCanvasX,
648
                   '-y' => $MapCanvasY,
649
                   '-mode' => "Target"
650
                 );
651
 
652
        # redraw connector-lines
653
        $WaypointsModified = 1;
654
        &WpRedrawLines();  
655
 
656
        $map_status_line->configure ('-text' => "Ziel-Koordinaten gesendet -> Lat: $Lat  Lon: $Lon     x: $x  y: $y");
657
        }],
658
    ]
659
                                    );
660
$map_canvas->CanvasBind("<Button-3>" => [ sub
661
    {
662
    $map_canvas->focus;
663
    my($w, $x, $y) = @_;
664
    ($MapCanvasX, $MapCanvasY) = ($Tk::event->x, $Tk::event->y);
665
    $MapCanvasId = $map_canvas->find('withtag', 'current');
666
    $map_menu->post($x, $y);
667
    }, Ev('X'), Ev('Y') ] );
668
 
669
 
670
#
671
# Objects on canvas
672
#
673
 
674
# Line from MK to Home
675
$map_canvas->createLine ( $MapSizeX/2, $MapSizeY/2, $MapSizeX/2, $MapSizeY/2,
676
                          '-tags' => 'MK-Home-Line',
677
                          '-arrow' => 'none',
678
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorHomeLine'},
679
                          '-width' => 3,
680
                         );
681
 
682
# Text Entfernung positioniert an der Home-Linie
683
$map_canvas->createText ( $MapSizeX/2 + 8, $MapSizeY/2 - 8,
684
                          '-tags' => 'MK-Home-Dist',
685
                          '-text' => '0 m',
686
                          '-anchor' => 'w',
687
                          '-font' => '-*-Arial-Bold-R-Normal--*-200-*',
688
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorHomeDist'},
689
                          );
690
 
691
# Line from MK to Target, draw invisible out of sight
692
$map_canvas->createLine ( 0, -100, 0, -100,
693
                          '-tags' => 'MK-Target-Line',
694
                          '-arrow' => 'none',
695
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorTargetLine'},
696
                          '-width' => 3,
697
                         );
698
 
699
# Text Entfernung positioniert an der Target-Linie
700
$map_canvas->createText ( 0, -100,
701
                          '-tags' => 'MK-Target-Dist',
702
                          '-text' => '0 m',
703
                          '-anchor' => 'w',
704
                          '-font' => '-*-Arial-Bold-R-Normal--*-200-*',
705
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorTargetDist'},
706
                          );
707
 
708
# MK Geschwindigkeits-Vektor
709
$MapMkSpeedLen = 60;    # Länge Speed-Zeiger
710
my $x0 = $MapSizeX/2;
711
my $y0 = $MapSizeY/2;
712
my $x1 = $MapSizeX/2;
713
my $y1 = $MapSizeY/2 - $MapMkSpeedLen;
714
$map_canvas->createLine ( $x0, $y0, $x1, $y1,
715
                          '-tags' => 'MK-Speed',
716
                          '-arrow' => 'last',
717
                          '-arrowshape' => [10, 10, 3 ],
718
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorSpeedVector'},
719
                          '-width' => 4,
720
                         );
721
 
722
# MK als Pfeilspitze einer Linie darstellen
723
$MapMkLen = 25;
724
my $x0 = $MapSizeX/2;
725
my $y0 = $MapSizeY/2 + $MapMkLen/2;
726
my $x1 = $MapSizeX/2;
727
my $y1 = $MapSizeY/2 - $MapMkLen/2;
728
$map_canvas->createLine ( $x0, $y0, $x1, $y1,
729
                          '-tags' => 'MK-Arrow',
730
                          '-arrow' => 'last',
731
                          '-arrowshape' => [25, 30, 10 ],
732
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorMkSatNo'},
733
                          '-width' => 1
734
                         );
735
 
736
 
737
# OSD Daten auf Karte anzeigen
738
 
739
# Flugzeit
740
$map_canvas->createText ( $MapSizeX/2 - 40, 20,
741
                          '-tags' => 'MK-OSD-Tim-Label',
742
                          '-text' => 'TIM',
743
                          '-font' => '-*-Arial-Bold-R-Normal--*-150-*',
744
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorOsd'},
745
                          '-anchor' => 'w',
746
                         );
747
 
748
$map_canvas->createText ( $MapSizeX/2, 20,
749
                          '-tags' => 'MK-OSD-Tim-Value',
750
                          '-text' => $MkFlyingTime,            # $MkOsd{'FlyingTime'},
751
                          '-font' => '-*-Arial-Bold-R-Normal--*-270-*',
752
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorOsd'},
753
                          '-anchor' => 'w',
754
                         );
755
 
756
# Batterie Spannung
757
$map_canvas->createText ( $MapSizeX/2 - 40, 50,
758
                          '-tags' => 'MK-OSD-Bat-Label',
759
                          '-text' => 'BAT',
760
                          '-font' => '-*-Arial-Bold-R-Normal--*-150-*',
761
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorOsd'},
762
                          '-anchor' => 'w',
763
                         );
764
 
765
$map_canvas->createText ( $MapSizeX/2, 50,
766
                          '-tags' => 'MK-OSD-Bat-Value',
767
                          '-text' => sprintf ("%3.1f V", $MkOsd{'UBat'}),
768
                          '-font' => '-*-Arial-Bold-R-Normal--*-270-*',
769
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorOsd'},
770
                          '-anchor' => 'w',
771
                         );
772
 
773
# Ground speed
774
$map_canvas->createText ( 10,  20,
775
                          '-tags' => 'MK-OSD-Spd-Label',
776
                          '-text' => 'SPD',
777
                          '-font' => '-*-Arial-Bold-R-Normal--*-150-*',
778
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorOsd'},
779
                          '-anchor' => 'w',
780
                         );
781
 
782
$map_canvas->createText ( 50,  20,
783
                          '-tags' => 'MK-OSD-Spd-Value',
784
                          '-text' => sprintf ("%3d km/h", $MkOsd{'GroundSpeed'} * 0.036),
785
                          '-font' => '-*-Arial-Bold-R-Normal--*-270-*',
786
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorOsd'},
787
                          '-anchor' => 'w',
788
                         );
789
 
790
# Hoehe (Luftdruck)
791
$map_canvas->createText ( 10,  50,
792
                          '-tags' => 'MK-OSD-Alt-Label',
793
                          '-text' => 'ALT',
794
                          '-font' => '-*-Arial-Bold-R-Normal--*-150-*',
795
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorOsd'},
796
                          '-anchor' => 'w',
797
                         );
798
 
799
$map_canvas->createText ( 50,  50,
800
                          '-tags' => 'MK-OSD-Alt-Value',
801
                          '-text' => sprintf ("%3d m", $MkOsd{'Altimeter'}/$Cfg->{'mkcockpit'}->{'AltFactor'}),
802
                          '-font' => '-*-Arial-Bold-R-Normal--*-270-*',
803
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorOsd'},
804
                          '-anchor' => 'w',
805
                         );
806
 
807
# Variometer 
808
$map_canvas->createText ( 10,  80,
809
                          '-tags' => 'MK-OSD-Vsi-Label',
810
                          '-text' => 'VSI',
811
                          '-font' => '-*-Arial-Bold-R-Normal--*-150-*',
812
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorOsd'},
813
                          '-anchor' => 'w',
814
                         );
815
 
816
$map_canvas->createText ( 50,  80,
817
                          '-tags' => 'MK-OSD-Vsi-Value',
818
                          '-text' => sprintf ("%3d", $MkOsd{'Variometer'}),
819
                          '-font' => '-*-Arial-Bold-R-Normal--*-270-*',
820
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorOsd'},
821
                          '-anchor' => 'w',
822
                         );
823
 
824
# Anzahl Satelitten
825
$map_canvas->createText ( $MapSizeX - 120, 20,
826
                          '-tags' => 'MK-OSD-Sat-Label',
827
                          '-text' => 'SAT',
828
                          '-font' => '-*-Arial-Bold-R-Normal--*-150-*',
829
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorOsd'},
830
                          '-anchor' => 'w',
831
                         );
832
 
833
$map_canvas->createText ( $MapSizeX - 70, 20,
834
                          '-tags' => 'MK-OSD-Sat-Value',
835
                          '-text' => "$MkOsd{'SatsInUse'}",
836
                          '-font' => '-*-Arial-Bold-R-Normal--*-270-*',
837
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorOsd'},
838
                          '-anchor' => 'w',
839
                         );
840
 
841
# Wegpunkte
842
$map_canvas->createText ( $MapSizeX - 120, 50,
843
                          '-tags' => 'MK-OSD-Wp-Label',
844
                          '-text' => 'WPT',
845
                          '-font' => '-*-Arial-Bold-R-Normal--*-150-*',
846
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorOsd'},
847
                          '-anchor' => 'w',
848
                         );
849
 
850
$map_canvas->createText ( $MapSizeX - 70, 50,
851
                          '-tags' => 'MK-OSD-Wp-Value',
852
                          '-text' => $MkOsd{'WaypointIndex'} . "/" . $MkOsd{'WaypointNumber'} ,
853
                          '-font' => '-*-Arial-Bold-R-Normal--*-270-*',
854
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorOsd'},
855
                          '-anchor' => 'w',
856
                         );
857
# Navigation Mode
858
$map_canvas->createText ( $MapSizeX - 120, 80,
859
                          '-tags' => 'MK-OSD-Mode-Label',
860
                          '-text' => 'MOD',
861
                          '-font' => '-*-Arial-Bold-R-Normal--*-150-*',
862
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorOsd'},
863
                          '-anchor' => 'w',
864
                         );
865
 
866
$map_canvas->createText ( $MapSizeX - 70, 80,
867
                          '-tags' => 'MK-OSD-Mode-Value',
868
                          '-text' => '' ,
869
                          '-font' => '-*-Arial-Bold-R-Normal--*-270-*',
870
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorOsd'},
871
                          '-anchor' => 'w',
872
                         );
873
 
874
# Variometer on canvas
875
my @Polygon;
876
for ( $y = -100; $y <= 100; $y += 10)
877
    {
878
    my $Len = 5;
879
    if ( ($y % 50) == 0 )
880
        {
881
        $Len = 10;
882
        $map_canvas->createText ( $Len+5, $MapSizeY/2 + $y,
883
                                  '-tags' => 'Map-Variometer-Skala',
884
                                  '-text' => sprintf ("%3d", -$y / 10),
885
                                  '-anchor' => 'w',
886
                                  '-font' => '-*-Arial-Normal-R-Normal--*-150-*',
887
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorVariometer'},
888
                          );
889
        }
890
    push @Polygon, (   0, $MapSizeY/2 + $y);
891
    push @Polygon, ($Len, $MapSizeY/2 + $y);
892
    push @Polygon, (   0, $MapSizeY/2 + $y);
893
    }
894
 
895
$map_canvas->createLine(@Polygon,
896
                        '-tags' => 'Map-Variometer',
897
                        '-fill' => $Cfg->{'mkcockpit'}->{'ColorVariometer'},
898
                        '-width' => 2,
899
                        '-arrow' => 'none',
900
                       );
901
# Vario Pointer
902
$map_canvas->createPolygon( 5, $MapSizeY/2, 20, $MapSizeY/2+10, 20, $MapSizeY/2-10,
903
                           '-tags' => 'Map-Variometer-Pointer',
904
                           '-fill' => $Cfg->{'mkcockpit'}->{'ColorVariometerPointer'},
905
                           '-outline' => 'black', '-width' => 1,
906
                          );
907
 
908
# Tracking Canvas
909
 
910
if ( $Cfg->{'track'}->{'Active'} =~ /y/i )
911
    {
912
    # Canvas size
913
    $TrackSizeX  = 125;
914
    $TrackSizeY  = 100;
915
    $TrackOffY   = $TrackSizeY - $MapSizeY + 20;
916
    $TrackPtrLen = 50;    # Länge Zeiger
917
 
918
    # draw in map-canvas
919
    $track_canvas = $map_canvas;
920
 
921
    # Ziffernblatt
922
    my $x0 = $TrackSizeX/2 - $TrackPtrLen;
923
    my $y0 = $TrackSizeY + $TrackPtrLen - $TrackOffY;
924
    my $x1 = $TrackSizeX/2 + $TrackPtrLen;
925
    my $y1 = $TrackSizeY   - $TrackPtrLen - $TrackOffY;
926
    $track_canvas->createArc ( $x0, $y0, $x1, $y1,
927
                               '-extent' => '200',
928
                               '-start' => '-10',
929
                               '-style' => 'chord',
930
                               '-outline' => 'gray', '-width' => '1',
931
                             );
932
 
933
    # Skala Ziffernblatt
934
    for ($i=0; $i<=180; $i+=15)
935
        {
936
        my $pi = 3.14159265358979;
937
        my $x0 = $TrackSizeX/2 - ($TrackPtrLen - 20) * cos($i / 180 * $pi);
938
        my $y0 = $TrackSizeY   - ($TrackPtrLen - 20) * sin($i / 180 * $pi) - $TrackOffY;
939
        my $x1 = $TrackSizeX/2 - ($TrackPtrLen - 28) * cos($i / 180 * $pi);
940
        my $y1 = $TrackSizeY   - ($TrackPtrLen - 28) * sin($i / 180 * $pi) - $TrackOffY;
941
        $track_canvas->createLine ( $x0, $y0, $x1, $y1,
942
                                   '-fill' => 'white',
943
                                   '-width' => 1,
944
                                  );
945
        }
946
 
947
    # Skala Beschriftung Ziffernblatt
948
    for ($i=0; $i<=180; $i+=45)
949
        {
950
        my $pi = 3.14159265358979;
951
        my $x0 = $TrackSizeX/2 - ($TrackPtrLen - 12) * cos($i / 180 * $pi);
952
        my $y0 = $TrackSizeY   - ($TrackPtrLen - 12) * sin($i / 180 * $pi) - $TrackOffY;
953
        $track_canvas->createText ( $x0, $y0,
954
                                   '-text' => $i - 90,
955
                                   '-fill' => 'white',
956
                                  );
957
        }
958
 
959
    # Ziffernblatt Beschriftung Einheit
960
    my $x0 = $TrackSizeX/2;
961
    my $y0 = $MapSizeY -6;
962
    $track_canvas->createText ( $x0, $y0,
963
                                '-text' => "Antenne Winkel",
964
                                '-justify' => 'center',
965
                                '-fill' => 'white',
966
                                );
967
 
968
    # Zeiger
969
    my $x0 = $TrackSizeX/2;
970
    my $y0 = $TrackSizeY - 0 - $TrackOffY;
971
    my $x1 = $TrackSizeX/2;
972
    my $y1 = $TrackSizeY - ($TrackPtrLen - 22) - $TrackOffY;
973
    $track_ptr_id= $track_canvas->createLine ( $x0, $y0, $x1, $y1,
974
                                               '-tags' => 'Track-Ptr',
975
                                               '-arrow' => 'last',
976
                                               '-arrowshape' => [20, 30, 5 ],
977
                                               '-fill' => 'red',
978
                                               '-width' => 8,
979
                                              );
980
    # Zeiger Center
981
    my $Dia = 7;
982
    my $x0 = $TrackSizeX/2 - $Dia;
983
    my $y0 = $TrackSizeY + $Dia - $TrackOffY;
984
    my $x1 = $TrackSizeX/2 + $Dia;
985
    my $y1 = $TrackSizeY   - $Dia - $TrackOffY;
986
    $track_canvas->createArc ( $x0, $y0, $x1, $y1,
987
                               '-extent' => '359',
988
                               '-outline' => 'gray', '-width' => 1,
989
                               '-fill' => 'gray',
990
                             );
991
    }
992
 
993
#-----------------------------------------------------------------
994
# Timer
995
#-----------------------------------------------------------------                        
996
 
997
#
998
# Timer: 5s
999
#
1000
$main->repeat (5000, sub
1001
    {
1002
    if ( ! $MkSendWp )
1003
        {
1004
        # Abfragefrequenz OSD und Debug regelmäßig neu einstellen, falls Übertragungsfehler
1005
        $MkSendQueue->enqueue( "o", "$AddrNC", pack ("C", 10) );   # Frequenz OSD Datensatz, * 10ms
1006
        $MkSendQueue->enqueue( "d", "$AddrNC", pack ("C", 10) );   # Frequenz MK Debug Datensatz, * 10ms
1007
        $MkSendQueue->enqueue( "v", "$AddrNC", "");   # Version
1008
        $MkSendQueue->enqueue( "e", "$AddrNC", "");   # Error Text Request
1009
        }
1010
    });
1011
 
1012
#       
1013
# Timer: 0.1s - Map Overlay aktualisieren
1014
#
1015
$frame_map_top->repeat (100, sub
1016
    {
1017
    lock (%MkOsd);              # until end of block
1018
 
1019
    # Aktuell gültige Karte
1020
    my %Map = %{$Maps{'Current'}};
1021
 
1022
    if ( $MkOsd{'_Timestamp'} >= time-2 )
1023
        {
1024
        # Gueltige OSD Daten
1025
        my $SatsInUse = $MkOsd{'SatsInUse'};
1026
        if ( $SatsInUse > 0  and  $MkOsd{'CurPos_Stat'} == 1 and $MkOsd{'HomePos_Stat'} == 1 )
1027
            {
1028
            # ausreichender GPS Empfang
1029
 
1030
            # get x,y map coords of current position
1031
            my ($C_x, $C_y, $C_Angel) = &MapGps2XY($MkOsd{'CurPos_Lat'}, $MkOsd{'CurPos_Lon'}, $MkOsd{'CompassHeading'});
1032
 
1033
            # rotate MK arrow
1034
            my $dy = sin (deg2rad $C_Angel) * ($MapMkLen/2);
1035
            my $dx = cos (deg2rad $C_Angel) * ($MapMkLen/2);
1036
            my $x0 = $C_x - $dx;
1037
            my $y0 = $C_y - $dy;
1038
            my $x1 = $C_x + $dx;
1039
            my $y1 = $C_y + $dy;
1040
            $map_canvas->coords ('MK-Arrow', $x0, $y0, $x1, $y1);
1041
 
1042
            # Update speed vector
1043
            my $MapAngel = &MapAngel();   # Norh to Map-Horizont
1044
            my $GpsSpeedNorth = $MkNcDebug{'Analog_21'};
1045
            my $GpsSpeedEast  = $MkNcDebug{'Analog_22'};
1046
            my $PhiGpsSpeed = rad2deg atan2 ( $GpsSpeedEast, $GpsSpeedNorth );
1047
            $PhiMapSpeed = $PhiGpsSpeed - $MapAngel;
1048
 
1049
            # 555 cm/s ~ 20 km/h -> Zeigerlänge = $MkSpeedLen bei 20 km/h
1050
            my $dy = sin (deg2rad $PhiMapSpeed) * $MapMkSpeedLen * $MkOsd{'GroundSpeed'} / 555;
1051
            my $dx = cos (deg2rad $PhiMapSpeed) * $MapMkSpeedLen * $MkOsd{'GroundSpeed'} / 555;
1052
            my $x0 = $C_x;
1053
            my $y0 = $C_y;
1054
            my $x1 = $C_x + $dx;
1055
            my $y1 = $C_y + $dy;
1056
            $map_canvas->coords ('MK-Speed', $x0, $y0, $x1, $y1);
1057
 
1058
            # Update Line between Home and MK
1059
            my ($H_x, $H_y) = &MapGps2XY($MkOsd{'HomePos_Lat'}, $MkOsd{'HomePos_Lon'});
1060
            $map_canvas->coords ('MK-Home-Line', $H_x, $H_y, $C_x, $C_y);
1061
 
1062
            # Update Distance between Home and MK
1063
            my ($Dist, $Bearing) = MapGpsTo($MkOsd{'CurPos_Lat'}, $MkOsd{'CurPos_Lon'},
1064
                                                   $MkOsd{'HomePos_Lat'}, $MkOsd{'HomePos_Lon'} );
1065
            my $x = ($C_x - $H_x) / 2 + $H_x + 8;
1066
            my $y = ($C_y - $H_y) / 2 + $H_y + 8;
1067
            $map_canvas->coords ('MK-Home-Dist', $x, $y);
1068
            $map_canvas->itemconfigure ('MK-Home-Dist',
1069
                                        '-text' => sprintf ("%4d m", $Dist),
1070
                                       );
1071
 
1072
            if ( $MkOsd{'TargetPos_Stat'} == 1 )
1073
                {
1074
                # Valid Target
1075
                # Update Line between Target and MK
1076
                my ($T_x, $T_y) = &MapGps2XY($MkOsd{'TargetPos_Lat'}, $MkOsd{'TargetPos_Lon'});
1077
                $map_canvas->coords ('MK-Target-Line', $C_x, $C_y, $T_x, $T_y);
1078
 
1079
                # Update Distance between Target and MK
1080
                my ($Dist, $Bearing) = MapGpsTo($MkOsd{'CurPos_Lat'}, $MkOsd{'CurPos_Lon'},
1081
                                                        $MkOsd{'TargetPos_Lat'}, $MkOsd{'TargetPos_Lon'} );
1082
                my $x = ($C_x - $T_x) / 2 + $T_x - 8;
1083
                my $y = ($C_y - $T_y) / 2 + $T_y + 8;
1084
                $map_canvas->coords ('MK-Target-Dist', $x, $y);
1085
                $map_canvas->itemconfigure ('MK-Target-Dist',
1086
                                            '-text' => sprintf ("%4d m", $Dist),
1087
                                           );
1088
                # show target icon
1089
                my $IconHeight = 48;
1090
                my $IconWidth = 48;
1091
                $map_canvas->coords('Target', $T_x - $IconWidth/2, $T_y - $IconHeight );
1092
                }
1093
            else
1094
                {
1095
                # No valid Target, move target line out of sight/canvas
1096
                $map_canvas->coords ('MK-Target-Line', 0, -100, 0, -100);
1097
                                     $map_canvas->coords ('MK-Home-Dist', 0, -100);
1098
 
1099
                # hide target icon
1100
                $map_canvas->coords('Target', 0, -100, );
1101
                }
1102
 
1103
            # Update OSD - Sat dependent values
1104
            $map_canvas->itemconfigure ('MK-OSD-Spd-Value', '-text' => sprintf ("%3d km/h", $MkOsd{'GroundSpeed'} * 0.036) );
1105
            }
1106
        else
1107
            {
1108
            # kein ausreichender Sat-Empfang
1109
            $map_canvas->itemconfigure ('MK-OSD-Spd-Value', '-text' => sprintf ("%3d km/h", 0 ) );
1110
            }
1111
 
1112
        # Update OSD - non Sat dependent values
1113
        $map_canvas->itemconfigure ('MK-OSD-Sat-Value', '-text' => "$MkOsd{'SatsInUse'}" );
1114
        $map_canvas->itemconfigure ('MK-OSD-Wp-Value',  '-text' => $MkOsd{'WaypointIndex'} . "/" . $MkOsd{'WaypointNumber'});
1115
        $map_canvas->itemconfigure ('MK-OSD-Bat-Value', '-text' => sprintf ("%3.1f V", $MkOsd{'UBat'}) );
1116
        $map_canvas->itemconfigure ('MK-OSD-Alt-Value', '-text' => sprintf ("%3d m", $MkOsd{'Altimeter'}/$Cfg->{'mkcockpit'}->{'AltFactor'}) );
1117
        $map_canvas->itemconfigure ('MK-OSD-Vsi-Value', '-text' => sprintf ("%3d", $MkOsd{'Variometer'}) );
1118
        $map_canvas->itemconfigure ('MK-OSD-Tim-Value', '-text' => sprintf ("%02d:%02d", $MkFlyingTime / 60, $MkFlyingTime % 60) );
1119
 
1120
        # blink battery warning
1121
        $map_canvas->itemconfigure ('MK-OSD-Bat-Value', '-fill' => $Cfg->{'mkcockpit'}->{'ColorOsd'});
1122
        if ( $MkOsd{'UBat'}  <  $Cfg->{'mkcockpit'}->{'UBatWarning'} )
1123
            {
1124
            if ( time %2 )
1125
                {
1126
                $map_canvas->itemconfigure ('MK-OSD-Bat-Value', '-fill' => 'red');
1127
                }
1128
            }
1129
 
1130
        my $Mode = "";
1131
        if ($MkOsd{'NCFlags'} & 0x01) { $Mode = "Free"};
1132
        if ($MkOsd{'NCFlags'} & 0x02) { $Mode = "PH"};
1133
        if ($MkOsd{'NCFlags'} & 0x04) { $Mode = "WPT"};
1134
        if ($MkOsd{'NCFlags'} & 0x08) { $Mode = "$Mode" . " !"};  # Range Warning
1135
        $map_canvas->itemconfigure ('MK-OSD-Mode-Value', '-text' => "$Mode" );
1136
 
1137
        # Farbe MK-Zeiger abhängig vom GPS Empfang
1138
        my $MkCol= $Cfg->{'mkcockpit'}->{'ColorMkSatNo'};
1139
        if ( $SatsInUse >= 1 ) { $MkCol = $Cfg->{'mkcockpit'}->{'ColorMkSatLow'} ; }
1140
        if ( $SatsInUse >= 6 ) { $MkCol = $Cfg->{'mkcockpit'}->{'ColorMkSatGood'}; }
1141
        $map_canvas->itemconfigure ('MK-Arrow', '-fill' => $MkCol);
1142
 
1143
        # Variometer Pointer
1144
        my $dy = -$MkOsd{'Variometer'} * 10;
1145
        $map_canvas->coords('Map-Variometer-Pointer', 5, $MapSizeY/2+$dy, 20, $MapSizeY/2+10+$dy, 20, $MapSizeY/2-10+$dy);
1146
 
1147
        # Show/Hide SatFix Icon
1148
        if ($MkOsd{'SatsInUse'} >= 6 )
1149
            {
1150
            $map_canvas->coords('Satellite', $MapSizeX-180, 10, );
1151
            }
1152
        else
1153
            {
1154
            # move icon out of sight
1155
            $map_canvas->coords('Satellite', 0, -100, );
1156
            }
1157
        }
1158
    else
1159
        {
1160
        # keine aktuellen OSD Daten vom MK verfügbar
1161
        }
1162
 
1163
    });
1164
 
1165
#       
1166
# Timer: 0.1s - Tracking Anzeige aktualisieren
1167
#
1168
if ( $Cfg->{'track'}->{'Active'} =~ /y/i )
1169
    {
1170
    $frame_map_top->repeat (100, sub
1171
        {
1172
        # Aktuell gültige Karte
1173
        my %Map = %{$Maps{'Current'}};
1174
 
1175
        # Zeiger neu zeichnen
1176
        my $ServoPan = @ServoPos[$MkTrack{'ServoPan'}];
1177
        if ( $ServoPan ne ""  )
1178
            {
1179
            my $x0 = $TrackSizeX/2;    
1180
            my $y0 = $TrackSizeY - 0 - $TrackOffY;
1181
            my $x1 = $TrackSizeX/2 - ($TrackPtrLen-22) * cos( deg2rad $ServoPan);
1182
            my $y1 = $TrackSizeY   - ($TrackPtrLen-22) * sin (deg2rad $ServoPan) - $TrackOffY;
1183
            $track_canvas->coords ('Track-Ptr', $x0, $y0, $x1, $y1);
1184
            }
1185
 
1186
        # Farbe Zeiger abhängig vom GPS Empfang
1187
        my $SatsInUse = $MkOsd{'SatsInUse'};
1188
        my $TrackPtrCol= 'red';
1189
        if ( $SatsInUse >= 1 ) { $TrackPtrCol = 'orange'; }
1190
        if ( $SatsInUse >= 6 ) { $TrackPtrCol = 'green'; }
1191
        $track_canvas->itemconfigure ('Track-Ptr', '-fill' => $TrackPtrCol);
1192
        });
1193
    }
1194
 
1195
#       
1196
# Timer: 1s
1197
#
1198
$frame_map_top->repeat (1000, sub
1199
    {
1200
    # Aktuell gültige Karte
1201
    my %Map = %{$Maps{'Current'}};
1202
 
1203
    if ( $MkOsd{'_Timestamp'} >= time -2 )
1204
        {
1205
 
1206
        # Heartbeat MK Datenübertragung
1207
        if ( time %2 )
1208
            {
1209
            $map_canvas->itemconfigure('Heartbeat', '-image' => 'HeartbeatLarge', );
1210
            }
1211
        else
1212
            {
1213
            $map_canvas->itemconfigure('Heartbeat', '-image' => 'HeartbeatSmall', );
1214
            }
1215
 
1216
        # Flugzeit aktualisieren
1217
        # Flugzeit selber mitzählen, da $MkOsd{'FlyingTime'} immer 0 (0.14b)
1218
        if ( $MkOsd{'MKFlags'} & 0x02 )
1219
            {
1220
            $MkFlyingTime += 1;
1221
            }
1222
 
1223
        # Footprint
1224
        if ( $Cfg->{'mkcockpit'}->{'FootprintLength'} > 0 )
1225
            {
1226
            if ( $MkOsd{'SatsInUse'} > 0  and  $MkOsd{'CurPos_Stat'} == 1 )
1227
                {
1228
                # neuen Footprint hinten anhaengen
1229
                my ($x, $y) = &MapGps2XY($MkOsd{'CurPos_Lat'}, $MkOsd{'CurPos_Lon'});
1230
                push @Footprint, $x, $y;
1231
                }
1232
 
1233
            while ( $#Footprint / 2  >  $Cfg->{'mkcockpit'}->{'FootprintLength'} )
1234
                {
1235
                # alte Footprints entfernen
1236
                splice @Footprint, 0, 2;
1237
                }
1238
 
1239
            &FootprintRedraw();
1240
            }
1241
 
1242
 
1243
        # tracking antenne
1244
        if ( $MkOsd{'MKFlags'} & 0x01  and  ! $MkTrack{'IsRunning'} and
1245
             $Cfg->{'track'}->{'Active'} =~ /y/i )
1246
            {
1247
            # start track at 1st motor start
1248
            $track_thr = threads->create (\&TrackAntennaGps)->detach();
1249
            $MkTrack{'IsRunning'} = "Running";
1250
            }
1251
        }
1252
    });
1253
 
1254
 
1255
MainLoop();   # should never end
1256
 
1257
 
1258
#-----------------------------------------------------------------
1259
# Subroutines
1260
#-----------------------------------------------------------------                        
1261
 
1262
# Get Wp Index from Canvas Id
1263
sub WpGetIndexFromId()
1264
    {
1265
    my ($id) = @_;
1266
 
1267
    my @Tags = $map_canvas->gettags($id);
1268
    my $WpTag = $Tags[1];
1269
 
1270
    for $i (0 .. $#Waypoints)
1271
        {
1272
        my $Wp = $Waypoints[$i];
1273
        if ( $Wp->{'Tag'} eq $WpTag )
1274
            {
1275
            # got it
1276
            return $i;
1277
            }
1278
        }
1279
    return -1;
1280
    }
1281
 
1282
 
1283
# Resend all Waypoints to MK
1284
sub WpSendAll()
1285
    {
1286
    # OSD/Debug Abfragefrequenz verringern, sonst kommen nicht alle Wp im MK an
1287
    # Sicherheitshalber doppelt senden
1288
    $MkSendWp = 1;       # verhindert ueberschreiben im Timer
1289
    $MkSendQueue->enqueue( "o", "$AddrNC", pack ("C", 1000) );   # Frequenz OSD Datensatz, * 10ms
1290
    $MkSendQueue->enqueue( "d", "$AddrNC", pack ("C", 1000) );   # Frequenz MK Debug Datensatz, * 10ms
1291
    usleep (200000);
1292
    $MkSendQueue->enqueue( "o", "$AddrNC", pack ("C", 1000) );   # Frequenz OSD Datensatz, * 10ms
1293
    $MkSendQueue->enqueue( "d", "$AddrNC", pack ("C", 1000) );   # Frequenz MK Debug Datensatz, * 10ms
1294
    usleep (200000);
1295
 
1296
    # Alte WP-Liste im MK löschen
1297
    my $Wp = $Waypoints[0];
1298
    &MkFlyTo ( '-lat'  => $Wp->{'Pos_Lat'},
1299
               '-lon'  => Wp->{'Pos_Lon'},
1300
               '-mode' => "Waypoint Delete"
1301
             );
1302
 
1303
    for $i (0 .. $#Waypoints)
1304
        {
1305
        my $Wp = $Waypoints[$i];
1306
        &MkFlyTo ( '-lat'             => $Wp->{'Pos_Lat'},
1307
                   '-lon'             => $Wp->{'Pos_Lon'},
1308
                   '-alt'             => $Wp->{'Pos_Alt'},
1309
                   '-heading'         => $Wp->{'Heading'},
1310
                   '-toleranceradius' => $Wp->{'ToleranceRadius'},
1311
                   '-holdtime'        => $Wp->{'Holdtime'},
1312
                   '-eventflag'       => $Wp->{'Event_Flag'},
1313
                   '-mode'            => "Waypoint"
1314
                 );
1315
 
1316
        usleep (150000)  # NC Zeit zum Verarbeiten geben
1317
        }
1318
 
1319
    $MkSendWp = 0;  # normale OSD/Debug Abfragefrequenz wird automatisch im Timer wieder eingestellt
1320
 
1321
    # gray connectors: Wp are sent to MK
1322
    $map_canvas->itemconfigure('Waypoint-Connector',
1323
                               '-fill' => $Cfg->{'mkcockpit'}->{'ColorWpConnector'},
1324
                              );
1325
 
1326
    # MK ist nun synchron mit @Waypoints
1327
    $WaypointsModified = 0;
1328
    }          
1329
 
1330
 
1331
# Redraw Waypoint Icons
1332
sub WpRedrawIcons()
1333
    {
1334
    # delete old icons and Wp-Number from canvas
1335
    $map_canvas->delete('Waypoint');
1336
    $map_canvas->delete('WaypointNumber');
1337
 
1338
    # create new icons
1339
    for $i (0 .. $#Waypoints)
1340
        {
1341
        my $Wp = $Waypoints[$i];
1342
        my $x = $Wp->{'MapX'};
1343
        my $y = $Wp->{'MapY'};
1344
        my $Tag = $Wp->{'Tag'};
1345
 
1346
        # Waypoint Icon
1347
        my $IconHeight = 48;
1348
        my $IconWidth = 48;
1349
        $map_canvas->createImage($x-$IconWidth/2, $y-$IconHeight,
1350
                                 '-tags' => ['Waypoint', $Tag],
1351
                                 '-anchor' => 'nw',
1352
                                 '-image'  => 'Waypoint-Photo',
1353
                                );
1354
        # Waypoint Number
1355
        my $WpNumber = $i + 1;
1356
        $map_canvas->createText ( $x+3, $y-$IconHeight/2+12,
1357
                                  '-tags' => ['WaypointNumber', $Tag],
1358
                                  '-text' => $WpNumber,
1359
                                  '-font' => '-*-Arial-Bold-R-Normal--*-100-*',
1360
                                  '-fill' => $Cfg->{'mkcockpit'}->{'ColorWpNumber'},
1361
                                  '-anchor' => 'w',
1362
                                 );    
1363
 
1364
        }      
1365
    $map_canvas->lower('Waypoint', 'Fox');              # waypoint below Fox
1366
    $map_canvas->lower('WaypointNumber', 'Waypoint');   # waypoint-number below waypoint
1367
    }
1368
 
1369
 
1370
# Redraw Waypoint connectors
1371
sub WpRedrawLines()
1372
    {
1373
    # delete old connectors from canvas
1374
    $map_canvas->delete('Waypoint-Connector');  
1375
 
1376
    my $Color = $Cfg->{'mkcockpit'}->{'ColorWpConnector'};
1377
    if ( $WaypointsModified )
1378
        {
1379
        $Color = $Cfg->{'mkcockpit'}->{'ColorWpResend'};
1380
        }
1381
 
1382
    my $Wp = $Waypoints[0];
1383
    my $x_last = $Wp->{'MapX'};
1384
    my $y_last = $Wp->{'MapY'};
1385
    for $i (1 .. $#Waypoints)
1386
        {
1387
        my $Wp = $Waypoints[$i];
1388
        my $x = $Wp->{'MapX'};
1389
        my $y = $Wp->{'MapY'};
1390
 
1391
        $map_canvas->createLine ( $x_last, $y_last, $x, $y,
1392
                                  '-tags' => 'Waypoint-Connector',
1393
                                  '-arrow' => 'last',
1394
                                  '-arrowshape' => [10, 10, 3 ],
1395
                                  '-fill' => $Color,
1396
                                  '-width' => 1,
1397
                                );                                               
1398
        $x_last = $x;
1399
        $y_last = $y;
1400
        }
1401
 
1402
    $map_canvas->lower('Waypoint-Connector', 'Waypoint');   # connector below waypoint
1403
    }
1404
 
1405
 
1406
# Redraw Footprint
1407
sub FootprintRedraw()
1408
    {
1409
    # delete old Footprint fom canvas
1410
    $map_canvas->delete('Footprint');  
1411
 
1412
    if ( scalar @Footprint >= 4 )
1413
        {
1414
        $map_canvas->createLine ( @Footprint,
1415
                                  '-tags' => 'Footprint',
1416
                                  '-fill' => $Cfg->{'mkcockpit'}->{'ColorFootprint'},
1417
                                  '-width' => 1,
1418
                                );       
1419
        }
1420
 
1421
    $map_canvas->lower('Footprint', 'Fox');
1422
    }
1423
 
1424
 
1425
# Display or Modify Hash
1426
sub DisplayHash()
1427
    {
1428
    my ($hrefData, $Titel, $Mode) = @_;
1429
 
1430
    # $Mode: Display, Edit, Waypoint, Refresh
1431
 
1432
    my %Id;
1433
    my $Label;
1434
    my $Value;
1435
 
1436
    # Neues Fenster aufmachen
1437
    my $popup = $main->Toplevel();
1438
    $popup->title($Titel);
1439
 
1440
    # Buttons
1441
    my $popup_button = $popup->Frame() -> pack('-side' => 'bottom',
1442
                                               '-expand' => 'y',
1443
                                               '-anchor' => 's',
1444
                                               '-padx' => 5,
1445
                                               '-pady' => 5,
1446
                                               );
1447
    $popup_button->Button('-text'    => 'Schließen',
1448
                          '-command' => sub
1449
        {
1450
        if ( $Mode =~ /edit/i  and  $Mode =~ /waypoint/i )
1451
            {
1452
            $WaypointsModified = 1;            
1453
            &WpRedrawLines();
1454
            &WpRedrawIcons();
1455
            }
1456
 
1457
        $popup->destroy()
1458
        })->pack;
1459
 
1460
    # Frame mit den Labels
1461
    my $popup_label = $popup->Frame() -> pack('-side' => 'left',
1462
                                              '-expand' => 'y',
1463
                                              '-anchor' => 'w',
1464
                                              '-padx' => 10,
1465
                                              '-pady' => 10,
1466
                                              );
1467
    # Labels anzeigen                    
1468
    foreach $Label ( sort keys %{$hrefData})
1469
        {
1470
        if ( $Translate{$Label} ne "" )
1471
            {
1472
            $Label = $Translate{$Label};
1473
            }
1474
 
1475
        $popup_label->Label ('-text' => $Label,
1476
                             '-width' => 25,
1477
                             '-anchor' => 'w',
1478
                             ) -> pack();
1479
        }
1480
 
1481
    # Frame mit den Daten
1482
    my $popup_values = $popup->Frame() -> pack('-side' => 'left',
1483
                                               '-expand' => 'y',
1484
                                               '-anchor' => 'w',
1485
                                               '-padx' => 10,
1486
                                               '-pady' => 10,
1487
                                               );
1488
    # Daten anzeigen
1489
    foreach $Value ( sort keys %{$hrefData})
1490
        {                              
1491
        if ( $Mode =~ /display/i )
1492
            {
1493
            # Display
1494
            $Id{$Value} = $popup_values->Label ('-text' => ${$hrefData}{$Value},
1495
                                                '-width' => 20,
1496
                                                '-anchor' => 'e',
1497
                                                '-relief' => 'sunken',
1498
                                                ) -> pack();
1499
            }
1500
        if ( $Mode =~ /edit/i )
1501
            {
1502
            # Edit
1503
            $Id{$Value} = $popup_values->Entry ('-textvariable' => \${$hrefData}{$Value},
1504
                                                '-exportselection' => '1',
1505
                                                '-width' => 20,
1506
                                                '-relief' => 'sunken',
1507
                                               ) -> pack();
1508
            if ( $Mode =~ /waypoint/i )
1509
                {
1510
                # einige Waypoint-Felder nicht aenderbar einstellen
1511
                if ( "MapX MapY Pos_Lat Pos_Lon Tag" =~ /$Value/i )
1512
                    {
1513
                    $Id{$Value}->configure('-state' => 'disabled', );
1514
                    }
1515
                }      
1516
            }
1517
        }
1518
 
1519
    if ( $Mode =~ /refresh/i )
1520
        {
1521
        # Timer: 0.1s
1522
        $popup_values->repeat (100, sub
1523
            {
1524
            # Datenfelder alle 100ms aktualisieren
1525
 
1526
            my $BgColor = 'white';
1527
            if ( $Mode =~ /heartbeat/i )
1528
                {
1529
                $BgColor = 'red';
1530
                if ( $MkOsd{'_Timestamp'} >= time-2 )
1531
                    {
1532
                    # gültige daten vom MK
1533
                    $BgColor = 'white';
1534
                    }
1535
                }
1536
 
1537
            foreach $Value ( sort keys %{$hrefData} )
1538
                {
1539
                $Id{$Value}->configure('-text' => ${$hrefData}{$Value},
1540
                                       '-background' => "$BgColor",
1541
                                      );
1542
                }
1543
            });
1544
        }
1545
 
1546
    return 0;
1547
    }
1548
 
1549
 
1550
 
1551
# Konfigurationsdatei mkcockpit.xml im Popup-Fenster editieren
1552
sub Configure()
1553
    {
1554
 
1555
    # Copy Cfg-Hash for editing
1556
    my $CfgEdit = {%{$Cfg}};
1557
    foreach $key (keys %{$Cfg})
1558
        {
1559
        if ( ref $Cfg->{$key} )
1560
            {
1561
            $CfgEdit->{$key} = {%{$Cfg->{$key}}};
1562
            }
1563
        }
1564
 
1565
    # Neues Fenster aufmachen
1566
    my $popup = $main->Toplevel();
1567
    $popup->title("Einstellungen - $XmlConfigFile");
1568
 
1569
    my $book = $popup->NoteBook()->pack( -fill=>'both', -expand=>1 );
1570
 
1571
    # jede Sektion in einem Tab anzeigen
1572
    foreach $key (sort keys %{$CfgEdit})
1573
        {    
1574
        if ( ! ref $CfgEdit->{$key} )
1575
            {
1576
            next;
1577
            }
1578
 
1579
        my $TabLabel = "$key";
1580
        if ( $Translate{$key} ne "" )
1581
                {
1582
                $TabLabel = $Translate{$key};
1583
                }
1584
 
1585
        my $Tab = $book->add( "$key", -label=>"$TabLabel", );
1586
 
1587
        # Frame fuer Buttons
1588
        my $book_button = $Tab->Frame() -> pack('-side' => 'bottom',
1589
                                                '-expand' => 'y',
1590
                                                '-anchor' => 's',
1591
                                                '-padx' => 5,
1592
                                                '-pady' => 5,
1593
                                                );
1594
 
1595
        $book_button->Button('-text'    => 'OK',
1596
                             '-width' => '10',
1597
                             '-command' => sub
1598
            {
1599
            # Copy back CfgEdit-Hash
1600
            $Cfg = {%{$CfgEdit}};
1601
            foreach $key (keys %{$CfgEdit})
1602
                {
1603
                if ( ref $CfgEdit->{$key} )
1604
                    {
1605
                    $Cfg->{$key} = {%{$CfgEdit->{$key}}};
1606
                    }
1607
                }
1608
 
1609
            # set new timestamp
1610
            my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
1611
            my $TimeStamp = sprintf ("%04d%02d%02d-%02d%02d%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec);
1612
            $Cfg->{'CreationDate'} = $TimeStamp;
1613
 
1614
            # Cfg in mkcockpit.xml speichern
1615
            &XMLout ($Cfg,
1616
                     'OutputFile' => $XmlConfigFile,
1617
                     'AttrIndent' => '1',
1618
                     'RootName' => 'mkcockpit-Config',
1619
                    );
1620
 
1621
            $popup->destroy();
1622
            } )->pack ('-side' => 'left',
1623
                       '-expand' => 'y',
1624
                       '-anchor' => 's',
1625
                       '-padx' => 5,
1626
                       '-pady' => 5,
1627
                      );
1628
        $book_button->Button('-text'    => 'Abbruch',
1629
                             '-width' => '10',
1630
                             '-command' => sub { $popup->destroy() },
1631
                            )->pack ('-side' => 'left',
1632
                                     '-expand' => 'y',
1633
                                     '-anchor' => 's',
1634
                                     '-padx' => 5,
1635
                                     '-pady' => 5,
1636
                                     );
1637
        $book_button->Label ('-text' => "*) Aenderungen werden erst nach Programm-Neustart wirksam!",
1638
                             '-anchor' => 'w',
1639
                             '-foreground' => 'red',
1640
                            ) ->pack ('-side' => 'left',
1641
                                      '-expand' => 'y',
1642
                                      '-anchor' => 's',
1643
                                      '-padx' => 10,
1644
                                      '-pady' => 5,
1645
                                      );
1646
 
1647
        # Frame mit den Labels
1648
        my $popup_label = $Tab->Frame() -> pack('-side' => 'left',
1649
                                                '-expand' => 'y',
1650
                                                '-anchor' => 'w',
1651
                                                '-padx' => 10,
1652
                                                '-pady' => 10,
1653
                                                );
1654
        # Labels anzeigen                        
1655
        foreach $Label ( sort keys %{$CfgEdit->{$key}})
1656
            {
1657
            if ( $Translate{$Label} ne "" )
1658
                {
1659
                $Label = $Translate{$Label};
1660
                }
1661
 
1662
            $popup_label->Label ('-text' => $Label,
1663
                                 '-width' => 30,
1664
                                 '-anchor' => 'w',
1665
                                ) -> pack();
1666
            }
1667
 
1668
        # Frame mit den Daten
1669
        my $popup_values = $Tab->Frame() -> pack('-side' => 'left',
1670
                                                 '-expand' => 'y',
1671
                                                 '-anchor' => 'w',
1672
                                                 '-padx' => 10,
1673
                                                 '-pady' => 10,
1674
                                                 );
1675
        # Eingabefelder mit Daten anzeigen
1676
        foreach $Value ( sort keys %{$CfgEdit->{$key}})
1677
            {                          
1678
            $popup_values->Entry ('-textvariable' => \$CfgEdit->{$key}->{$Value},
1679
                                  '-exportselection' => '1',
1680
                                  '-width' => 30,
1681
                                  '-relief' => 'sunken',
1682
                                 ) -> pack();  
1683
            }
1684
        }
1685
    }
1686
 
1687
1;
1688
__END__