fiji_setup.pl 26.8 KB
Newer Older
Christian Fibich's avatar
Christian Fibich committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#-------------------------------------------------------------------------------
#  University of Applied Sciences Technikum Wien
#
#  Department of Embedded Systems
#  http://embsys.technikum-wien.at
#
#  Josef Ressel Center for Verification of Embedded Computing Systems
#  http://vecs.technikum-wien.at
#
#-------------------------------------------------------------------------------
#  File:              fiji_setup.pl
#  Created on:        25.02.2015
#  $LastChangedBy$
#  $LastChangedDate$
#
#  Description:
#
#  FIJI setup script (GUI)
#
#-------------------------------------------------------------------------------

Christian Fibich's avatar
Christian Fibich committed
22
23
## @file fiji_setup.pl
# @brief FIJI setup script (GUI)
24
## @file
Christian Fibich's avatar
Christian Fibich committed
25
# Displays a Tk GUI for entering, viewing and editing \ref FIJI::Settings
26
27
28

use strict;
use warnings;
29
use diagnostics;
30

31
32
33
use FindBin;
use lib "$FindBin::Bin";

34
35
36
use Log::Log4perl qw(get_logger);
use Tk;
use Tk::widgets qw(LabFrame Label Entry Button Dialog FBox Checkbutton);
37
use Tk::PNG;
38
use Clone qw(clone);
Christian Fibich's avatar
Christian Fibich committed
39
use File::Spec;
40
use Data::Dumper;
41
use FIJI::Settings;
Stefan Tauner's avatar
Stefan Tauner committed
42
use FIJI::Utils;
43
use Tk::FIJISettingsViewer;
44
use Tk::FIJIUtils;
Christian Fibich's avatar
Christian Fibich committed
45
46
use Time::HiRes qw(ualarm);

47
48
use Getopt::Long;

49
use FIJI qw(:fiji_dir :fiji_documentation_path);
50

51
## @var USE_MENU defines control style of fiji_settings:
52
53
# 0 => classic, no menu GUI
# 1 => toplevel menu
54
55
# undef => classic+menu GUI
use constant USE_MENU => undef;
56

Christian Fibich's avatar
Christian Fibich committed
57
use constant FILE_TYPES_CFG => [['FIJI Configurations', ['.cfg', '*.ini']], ['All files', '*'],];
58

Christian Fibich's avatar
Christian Fibich committed
59
use constant FILE_TYPES_NETLIST => [['Verilog Netlists', ['.v', '*.vqm']], ['All files', '*'],];
60

61
62
63
use constant CHANGED_VALUE   => "<M>";
use constant UNCHANGED_VALUE => "";

64
65
use constant APPNAME => 'FIJI Settings Editor';

66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
my $abouttxt = <<'END_ABOUT';
#-------------------------------------------------------------------------------
#  University of Applied Sciences Technikum Wien
#
#  Department of Embedded Systems
#  http://embsys.technikum-wien.at
#
#  Josef Ressel Center for Verification of Embedded Computing Systems
#  http://vecs.technikum-wien.at
#
#-------------------------------------------------------------------------------
#
#  $LastChangedBy$
#  $LastChangedDate$
#  
#-------------------------------------------------------------------------------
END_ABOUT

84
my $unsaved_changes = 0;
85
my $delete_main = 1;
86
87
my $error_image;
my $alert_image;
88
89
my $save_image;
my $dummy_image;
Christian Fibich's avatar
Christian Fibich committed
90
my $loading_image;
91
my $current_dir = ".";
Christian Fibich's avatar
Christian Fibich committed
92
93
94
95
my $splash;
my $do_splash;

use constant START_PERIOD => 500000; # 500 ms
96

97
98
99
my $usage=<<"END_USAGE";
Usage: $0 [OPTION]
The graphical FIJI Settings Editor
100

101
102
Optional command-line arguments:
   -s, --settings-file=FILE    load the given settings file at startup
103
   -n, --netlist-file=FILE     load the given netlist file at startup
104
105
   -h, --help                  display this help and exit
END_USAGE
106

107
sub main {
108
    my $logger = get_logger("");
109
110
111
112
    my $name   = $0;
    my @ARGV   = @_;
    $name =~ s/\.p[lm]//;
    $logger->debug("=== Starting new execution of $name ===");
Christian Fibich's avatar
Christian Fibich committed
113
    $logger->debug(sprintf("%d argument(s)%s", scalar(@_), scalar(@_) > 0 ? ": @_" : ""));
114

115
    my ($settings_filename, $netlist_filename, $help);
116
117

    my $parse = GetOptions("settings-file=s" => \$settings_filename,
118
                           "netlist-file=s"  => \$netlist_filename,
119
120
121
122
123
124
125
126
127
128
129
                           "help"            => \$help);

    if (!$parse) {
        print STDERR $usage;
        return -1;
    }
    if (defined $help) {
        print STDOUT $usage;
        return 0;
    }

130
    my %hash;
Christian Fibich's avatar
Christian Fibich committed
131
    my $self = bless(\%hash);
132

133
134
    my $libdir = File::Spec->catdir(FIJI_DIR, "lib");
    my $ugdir = File::Spec->catdir(FIJI_DIR, "docs", "userguide");
135
136
137
138
139
140
141
142
143

    my $ini_name;    # = $cfg{"cli.fiji_cfg"};
    $self->{'ini_name'} = \$ini_name;
    my $nl_name;
    $self->{'nl_name'} = \$nl_name;

    #
    # Start out with default settings
    #
144
145
146
147
148
    my ($settings_ref, $msg) = FIJI::Settings->new();
    if (defined $msg) {
        $logger->error($msg);
    }
    if (!defined($settings_ref)) {
149
150
151
152
153
154
155
        return 1;
    }
    $self->{'settings'} = $settings_ref;

    #
    # Build GUI
    #
156
157
158
159
160
    # Assigning $0 sets a "prettier" program title in Gnome's taskbar
    # Must not contain spaces (duh)
    $0 = (APPNAME =~ s/\s+/\-/rg);
    my $mw = MainWindow->new(-title => APPNAME);
    $mw->appname(APPNAME);
Christian Fibich's avatar
Christian Fibich committed
161
162
163
164
165
    $error_image   = $mw->Photo(-file => File::Spec->catfile($libdir, 'stop_48x48.xpm'),  -format => 'XPM');
    $alert_image   = $mw->Photo(-file => File::Spec->catfile($libdir, 'alert_48x48.xpm'), -format => 'XPM');
    $save_image    = $mw->Photo(-file => File::Spec->catfile($libdir, 'save_24x24.xpm'),  -format => 'XPM');
    $dummy_image   = $mw->Photo(-file => File::Spec->catfile($libdir, 'dummy_24x24.xpm'), -format => 'XPM');
    $loading_image = $mw->Photo(-file => File::Spec->catfile($libdir, 'fiji_logo_hires.xpm'), -format => 'XPM');
166

167
    $self->{'mw'} = $mw;
Christian Fibich's avatar
Christian Fibich committed
168
    $self->{'ctrl'} = _ctrl_frame($self, $mw);
169

Christian Fibich's avatar
Christian Fibich committed
170
    if (!defined USE_MENU || USE_MENU == 1) {
171
172
173
        $self->{'menu'} = $self->_menu($mw);
    }

Christian Fibich's avatar
Christian Fibich committed
174
175
176
177
178
    $mw->toplevel()->bind('<Control-o>'       => sub { $self->_open_settings_file; });
    $mw->toplevel()->bind('<Control-Shift-O>' => sub { $self->_open_netlist_file; });
    $mw->toplevel()->bind("<Control-s>"       => sub { $self->_save; });
    $mw->toplevel()->bind("<Control-Shift-S>" => sub { $self->_save_as; });
    $mw->toplevel()->bind("<F1>"              => sub { $self->_show_documentation; });
179
    $mw->toplevel()->bind("<Control-q>"       => sub { $self->_onexit; });
180
181

    $self->{'FIJISettingsViewer'} = $mw->FIJISettingsViewer(
182
183
        -mw               => $self->{'mw'},
        -delete_mw        => [\&_onexit, $self],
Christian Fibich's avatar
Christian Fibich committed
184
        -settings         => $self->{'settings'},
185
        -icon_path        => $libdir,
Christian Fibich's avatar
Christian Fibich committed
186
        -changes_callback => sub { my $set = shift; _indicate_changes($self, $set) },
187
188
189
190
191
      )->pack(
        '-fill'   => 'both',
        '-expand' => 1
      );

192
    $mw->protocol('WM_DELETE_WINDOW' => [\&_onexit, $self]);
193

194
    Tk::FIJIUtils::set_icon($mw, $libdir);
195

Christian Fibich's avatar
Christian Fibich committed
196
197
    $self->{'FIJISettingsViewer'}->append_fiu();               # add dummy FIU for layouting purposes
    $self->{'FIJISettingsViewer'}->set_state_as_original();    # no unsaved indicator
198
199
    $mw->update();

Christian Fibich's avatar
Christian Fibich committed
200
    $mw->minsize($self->{'FIJISettingsViewer'}->width(), $self->{'FIJISettingsViewer'}->height() + $self->{'ctrl'}->height());
Stefan Tauner's avatar
Stefan Tauner committed
201
    $mw->resizable(1, 1);
Christian Fibich's avatar
Christian Fibich committed
202
203
204
    $splash=$mw->toplevel->Frame();
    $splash->Label(-font => [-size => 16], -text => "Loading Netlist - Please wait...",-height=>2,)->pack(-side=>'bottom',-fill=>'both');
    $splash->Label(-image => $loading_image)->pack(-side=>'bottom',-expand=>1,-fill=>'both');
205
206
207
208
209
    $mw->update();

    #
    # Load settings if specified
    #
210
211
    if (defined $settings_filename) {
        my $filename = $settings_filename;
212
        my $fr       = $mw;
Christian Fibich's avatar
Christian Fibich committed
213
214
        if (-e $filename) {
            my $tmp_settings = \%{Clone::clone($self->{'settings'})};
215
216
217
218
            my $warn;
            ($tmp_settings, $warn) = FIJI::Settings->new('setup', $filename);
            if (defined($warn)) {
                my $msg = "Settings file $filename could not be loaded correctly: $warn";
219
                $logger->error($msg);
220
221
                my $d = $self->{'mw'}->FIJIModalDialog(-delete_mw => [\&_onexit, $self], 
                                                       -mw        => $self->{'mw'},
222
                                                       -image     => (!defined($tmp_settings) ? $error_image : $alert_image),
223
224
225
226
                                                       -wraplength => "200",
                                                       -text      => $msg,
                                                       -title     => 'Open FIJI Settings failed!',
                                                       -buttons   => ["OK"]);
227
                $d->Show();
228
                goto bailout if (!defined($tmp_settings));
229
            }
Christian Fibich's avatar
Christian Fibich committed
230
            if (!defined($self->{'FIJISettingsViewer'}->settings($tmp_settings))) {
231
232
                my $msg = "Could not update GUI correctly with new settings.";
                $logger->error($msg);
233
234
235
236
237
238
239
                my $d = $self->{'mw'}->FIJIModalDialog(-delete_mw => [\&_onexit, $self], 
                                                       -mw        => $self->{'mw'},
                                                       -image     => $error_image,
                                                       -wraplength => "200",
                                                       -text      => $msg,
                                                       -title     => 'Open FIJI Settings failed!',
                                                       -buttons   => ["OK"]);
240
                $d->Show();
241
                goto bailout;
242
243
244
245
246
            }
            $self->{'settings'} = $tmp_settings;
        } else {
            $self->{'settings'}->save($filename);
        }
Christian Fibich's avatar
Christian Fibich committed
247
        ${$self->{'ini_name'}} = $filename;
Christian Fibich's avatar
Christian Fibich committed
248
249
    }

250
251
    $self->_load_netlist_file($netlist_filename) if (defined $netlist_filename);

252
    MainLoop;
253

254
255
256
bailout:

    $self->_cleanup();
257
258
    $logger->trace("=== Stopping execution ===");
    return 0;
259
260
}

261
sub _menu {
Christian Fibich's avatar
Christian Fibich committed
262
    my ($self, $mw) = @_;
263

Christian Fibich's avatar
Christian Fibich committed
264
    my $menubar = $self->{'menu'} = $mw->Menu(-relief => "groove");
265

266
267
268
    my $file    = $menubar->cascade(-label => '~Configuration', -tearoff => 0);
    my $netlist = $menubar->cascade(-label => '~Netlist',       -tearoff => 0);
    my $help    = $menubar->cascade(-label => '~Help',          -tearoff => 0);
269
270
271
272
273
274

    $file->separator;
    $file->command(
        -label       => 'Open',
        -accelerator => 'Ctrl-o',
        -underline   => 0,
Christian Fibich's avatar
Christian Fibich committed
275
        -command     => [\&_open_settings_file, $self],
276
    );
277
278
    $file->separator;
    $file->command(
Christian Fibich's avatar
Christian Fibich committed
279
        -label       => 'Save',
280
        -accelerator => 'Ctrl-s',
Christian Fibich's avatar
Christian Fibich committed
281
282
        -underline   => 0,
        -command     => [\&_save, $self],
283
    );
284
    $file->command(
Christian Fibich's avatar
Christian Fibich committed
285
        -label       => 'Save As ...',
286
        -accelerator => 'Ctrl-Shift-s',
Christian Fibich's avatar
Christian Fibich committed
287
288
        -underline   => 1,
        -command     => [\&_save_as, $self],
289
290
291
292
293
294
295
    );

    $netlist->separator;
    $netlist->command(
        -label       => 'Load',
        -accelerator => 'Ctrl-Shift-O',
        -underline   => 0,
Christian Fibich's avatar
Christian Fibich committed
296
        -command     => [\&_open_netlist_file, $self],
297
    );
298
299
300
301
302
    $help->separator;
    $help->command(
        -label       => 'Open Documentation',
        -accelerator => 'F1',
        -underline   => 0,
Christian Fibich's avatar
Christian Fibich committed
303
        -command     => [\&_show_documentation, $self],
304
305
306
307
308
309
310
311
312
313
    );
    $help->separator;
    $help->command(
        -label     => 'About',
        -underline => 0,
        -command   => sub {
            my $d = $mw->DialogBox(
                -title   => "About",
                -buttons => ["Close"]
            );
Christian Fibich's avatar
Christian Fibich committed
314
315
            my $t = $d->Scrolled('Text', -scrollbars => "oe", -width => 80, -height => 16);
            $t->pack(-fill => "both", -expand => 1);
316
            $t->Contents($abouttxt);
Christian Fibich's avatar
Christian Fibich committed
317
            $t->configure(-state => "disabled");
318
319
320
            $d->Show();
        }
    );
Christian Fibich's avatar
Christian Fibich committed
321
    $mw->configure(-menu => $menubar);
322
323
}

324
sub _ctrl_frame {
Christian Fibich's avatar
Christian Fibich committed
325
    my ($self, $fr) = @_;
326
327
328
329
330
331
332
333
334
335
336
    my $fr_ctrl = $fr->LabFrame(
        -label     => "Control",
        -labelside => "acrosstop"
      )->pack(
        -side   => 'top',
        -anchor => 'w',
        -fill   => 'x',

        # -expand => 1
      );

337
    my $cfg_lbl;
338
    my $cfg_changed_lbl;
339
340
341
342
343
344
345
346
347
348
349
    my $cfg_btn_open;
    my $cfg_btn_save;
    my $cfg_btn_save_as;
    my $cfg_entry;
    my $nl_lbl;
    my $nl_btn_open;
    my $nl_entry;

    #
    # Configuration file entries
    #
Christian Fibich's avatar
Christian Fibich committed
350
    $cfg_lbl = $fr_ctrl->Label(-text => 'FIJI Configuration file',)->grid(
351
352
353
354
        '-row'    => 0,
        '-column' => 0,
        '-sticky' => 'w'
    );
Christian Fibich's avatar
Christian Fibich committed
355
    $self->{'change_label'} = $cfg_changed_lbl = $fr_ctrl->Label(-image => $dummy_image)->grid(
356
357
358
359
        '-row'    => 0,
        '-column' => 1,
        '-sticky' => 'w'
    );
360

361
    my $b = $fr_ctrl->Balloon();
Christian Fibich's avatar
Christian Fibich committed
362
    $b->attach($cfg_changed_lbl, -postcommand => sub { return $unsaved_changes == 1 }, -msg => "Unsaved changes");
363

Christian Fibich's avatar
Christian Fibich committed
364
    if (!defined USE_MENU || USE_MENU == 0) {
365
366
        $cfg_btn_open = $fr_ctrl->Button(
            -text    => 'Open',
Christian Fibich's avatar
Christian Fibich committed
367
            -command => [\&_open_settings_file, $self],
368
369
          )->grid(
            '-row'    => 0,
370
            '-column' => 2,
371
372
373
374
375
376
            '-sticky' => 'ew'
          );
        $cfg_btn_open->focus();

        $cfg_btn_save = $fr_ctrl->Button(
            -text    => 'Save',
Christian Fibich's avatar
Christian Fibich committed
377
            -command => [\&_save, $self],
378
379
          )->grid(
            '-row'    => 0,
380
            '-column' => 3,
381
382
383
384
385
            '-sticky' => 'ew'
          );

        $cfg_btn_save_as = $fr_ctrl->Button(
            -text    => 'Save as',
Christian Fibich's avatar
Christian Fibich committed
386
            -command => [\&_save_as, $self],
387
388
          )->grid(
            '-row'    => 0,
389
            '-column' => 4,
390
391
392
393
394
395
396
397
398
399
400
            '-sticky' => 'ew'
          );
    }

    $cfg_entry = $fr_ctrl->Entry(
        -textvariable       => $self->{'ini_name'},
        -state              => 'disabled',
        -disabledforeground => 'black',
        -takefocus          => 0,                     # default for disabled
      )->grid(
        '-row'    => 0,
401
        '-column' => 5,
402
403
404
405
406
407
        '-sticky' => 'ew'
      );

    #
    # Netlist file entries
    #
Christian Fibich's avatar
Christian Fibich committed
408
    $nl_lbl = $fr_ctrl->Label(-text => 'Input netlist file',)->grid(
409
410
        '-row'    => 1,
        '-column' => 0,
411
        '-sticky' => 'w',
412
413
    );

Christian Fibich's avatar
Christian Fibich committed
414
    if (!defined USE_MENU || USE_MENU == 0) {
415
416
        $nl_btn_open = $fr_ctrl->Button(
            -text    => 'Open',
Christian Fibich's avatar
Christian Fibich committed
417
            -command => [\&_open_netlist_file, $self],
418
419
          )->grid(
            '-row'    => 1,
420
            '-column' => 2,
421
422
423
424
425
426
427
428
429
430
          );
    }

    $nl_entry = $fr_ctrl->Entry(
        -textvariable       => $self->{'nl_name'},
        -state              => 'disabled',
        -disabledforeground => 'black',
        -takefocus          => 0,                    # default for disabled
      )->grid(
        '-row'        => 1,
431
        '-column'     => 3,
432
433
434
435
        '-columnspan' => 4,
        '-sticky'     => 'ew',
      );

436
    $fr_ctrl->gridColumnconfigure(5, -weight => 1);
437
438
439

    return $fr_ctrl;
}
440
441
442

sub _show_documentation {
    my $self = shift;
443
    my $mw   = $self->{'mw'};
444

Stefan Tauner's avatar
Stefan Tauner committed
445
    my $ret;
Christian Fibich's avatar
Christian Fibich committed
446
    if ($^O eq "MSWin32") {
447
        $ret = FIJI::Utils::system(1, "start " . FIJI_DOCUMENTATION_PATH);
Christian Fibich's avatar
Christian Fibich committed
448
    } elsif ($^O eq "linux") {
449
        $ret = FIJI::Utils::system("xdg-open " . FIJI_DOCUMENTATION_PATH);
450
    } else {
451
452
453
454
455
456
        my $d = $self->{'mw'}->FIJIModalDialog(-delete_mw => [\&_onexit, $self], 
                                               -mw        => $self->{'mw'},
                                               -image     => $error_image,
                                               -text      => "No default PDF viewer for OS \"" . $^O . "\"...",
                                               -title     => "Open Documentation failed",
                                               -buttons   => ["OK"]);
457
        $d->Show();
Stefan Tauner's avatar
Stefan Tauner committed
458
459
460
        return;
    }
    if (defined($ret)) {
461
462
463
464
465
466
        my $d = $self->{'mw'}->FIJIModalDialog(-delete_mw => [\&_onexit, $self], 
                                               -mw        => $self->{'mw'},
                                               -image     => $error_image,
                                               -text      => $ret,
                                               -title     => "Open Documentation failed",
                                               -buttons   => ["OK"]);
Stefan Tauner's avatar
Stefan Tauner committed
467
        $d->Show();
468
    }
469
470
}

471
472
473
sub _setdir {
    my $filename = shift;
    my ($volume,$directories,$file) = File::Spec->splitpath($filename);
474
    return File::Spec->catpath($volume, $directories, "");
475
476
}

477
sub _open_settings_file {
478
479
480
481
    my ($self) = @_;

    my $mw = $self->{'mw'};

482
    my $logger   = get_logger("");
483
484
485
486
    my $filename = $mw->FBox(
        -type        => 'open',
        -title       => 'Open FIJI Configuration file',
        -filetypes   => FILE_TYPES_CFG,
487
        -initialdir  => $current_dir,
488
        -initialfile => 'fiji.cfg'
489
    )->Show();
Christian Fibich's avatar
Christian Fibich committed
490
    if (!defined($filename)) {
491
492
493
        $logger->debug("User aborted open configuration action");
        return;
    }
494
    $current_dir = _setdir($filename);
Christian Fibich's avatar
Christian Fibich committed
495
    my $tmp_settings = \%{Clone::clone($self->{'settings'})};
496
497
    my $warn;
    ($tmp_settings, $warn) = FIJI::Settings->new('setup', $filename, $tmp_settings);
Christian Fibich's avatar
Christian Fibich committed
498
    if (!ref($tmp_settings)) {
499
500
        my $msg = "Settings file $filename could not be loaded correctly: $tmp_settings";
        $logger->error($msg);
501
502
503
504
505
506
507
        my $d = $self->{'mw'}->FIJIModalDialog(-delete_mw => [\&_onexit, $self], 
                                               -mw        => $self->{'mw'},
                                               -image     => $error_image,
                                               -wraplength => "200",
                                               -text      => $msg,
                                               -title     => 'Open FIJI Settings failed!',
                                               -buttons   => ["OK"]);
508
        $d->Show();
509
510
511
512
        return;
    }
    my $rv = $self->{'FIJISettingsViewer'}->settings($tmp_settings);

Christian Fibich's avatar
Christian Fibich committed
513
    if (!defined($rv)) {
514
515
        my $msg = "Could not update GUI correctly with new settings.";
        $logger->error($msg);
516
517
518
519
520
521
522
523

        my $d = $self->{'mw'}->FIJIModalDialog(-delete_mw => [\&_onexit, $self], 
                                               -mw        => $self->{'mw'},
                                               -image     => $error_image,
                                               -wraplength => "200",
                                               -text      => $msg,
                                               -title     => 'Open FIJI Settings failed!',
                                               -buttons   => ["OK"]);
524
        $d->Show();
525
        return;
Christian Fibich's avatar
Christian Fibich committed
526
    } elsif (ref($rv) eq "FIJI::Settings") {
527
        $self->{'settings'} = $tmp_settings;
Christian Fibich's avatar
Christian Fibich committed
528
        ${$self->{'ini_name'}} = $filename;
529
    }
530
531
532
}

sub _open_netlist_file {
533
    my $logger = get_logger("");
534
535
536
537
538
539
540
541
    my $self   = shift;

    my $mw = $self->{'mw'};

    my $filename = $mw->FBox(
        -type        => 'open',
        -title       => 'Open netlist file',
        -filetypes   => FILE_TYPES_NETLIST,
542
        -initialdir  => $current_dir,
543
        -initialfile => 'input.v'
544
    )->Show();
Christian Fibich's avatar
Christian Fibich committed
545
    if (!defined($filename)) {
546
547
548
        $logger->debug("User aborted open netlist action.");
        return;
    }
549
    $current_dir = _setdir($filename);
550
551
552
    $self->_load_netlist_file($filename);
}

Christian Fibich's avatar
Christian Fibich committed
553
554
555
$SIG{ALRM} = sub { if(defined $do_splash) {
                        if ($do_splash eq 'start') {
                            $splash->place(-bordermode=>'inside',-anchor=>'center',-relx => 0.5, -rely => 0.5,-relwidth=>1,-relheight=>1);
556
                            $splash->focus;
Christian Fibich's avatar
Christian Fibich committed
557
558
559
560
561
                            $splash->parent->update;
                        }
                    }
                };

562
563
564
565
566
567
sub _load_netlist_file {

    my $logger = get_logger("");
    my $self     = shift;
    my $filename = shift;
    my $mw = $self->{'mw'};
568

Christian Fibich's avatar
Christian Fibich committed
569
570
571
    $do_splash = 'start';
    ualarm START_PERIOD;

572
    # Display "Busy" cursor
Christian Fibich's avatar
Christian Fibich committed
573
574
    $mw->Busy();
    $mw->update();
575
576
577

    $logger->debug("Loading netlist...");
    my $nl = new FIJI::Netlist();
Christian Fibich's avatar
Christian Fibich committed
578
    if ($nl->read_file($filename) != 0) {
579
580
        my $msg = "Netlist could not be loaded correctly from \"$filename\".";
        $logger->error($msg);
581
582
583
584
585
586
587
        my $d = $self->{'mw'}->FIJIModalDialog(-delete_mw => [\&_onexit, $self], 
                                               -mw        => $self->{'mw'},
                                               -image     => $error_image,
                                               -wraplength => "200",
                                               -text      => $msg,
                                               -title     => 'Open netlist failed!',
                                               -buttons   => ["OK"]);
588
        $d->Show();
Christian Fibich's avatar
Christian Fibich committed
589
590
591
        undef $do_splash;
        $splash->placeForget();
        $mw->Unbusy();
592
593
594
595
        return;
    }
    $logger->debug("...done");
    $logger->debug("Updating viewer...");
Christian Fibich's avatar
Christian Fibich committed
596
    $mw->update();
597

Christian Fibich's avatar
Christian Fibich committed
598
    if (!defined($self->{'FIJISettingsViewer'}->netlist($nl))) {
599
600
        my $msg = "Could not update GUI correctly with new netlist.";
        $logger->error($msg);
601
602
603
604
605
606
607
608

        my $d = $self->{'mw'}->FIJIModalDialog(-delete_mw => [\&_onexit, $self], 
                                               -mw        => $self->{'mw'},
                                               -image     => $error_image,
                                               -wraplength => "200",
                                               -text      => $msg,
                                               -title     => 'Open netlist failed!',
                                               -buttons   => ["OK"]);
609
        $d->Show();
Christian Fibich's avatar
Christian Fibich committed
610
611
612
        undef $do_splash;
        $splash->placeForget();
        $mw->Unbusy();
613
614
        return;
    }
Christian Fibich's avatar
Christian Fibich committed
615
    ${$self->{'nl_name'}} = $filename;
616
617
618
    $logger->debug("...done");

    # Done...
Christian Fibich's avatar
Christian Fibich committed
619
620
621
622
    undef $do_splash;
    $splash->placeForget();
    $mw->Unbusy();
    $mw->update();
623
624
}

625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
sub _indicate_changes {
    my $logger = get_logger("");
    my $self   = shift;
    my $set    = shift;
    $unsaved_changes = $set;

    if ($unsaved_changes == 1) {
        $self->{'change_label'}->configure(-image => $save_image);
        $self->{'mw'}->configure(-title => "*" . APPNAME);
    } else {
        $self->{'change_label'}->configure(-image => $dummy_image);
        $self->{'mw'}->configure(-title => APPNAME);
    }
}

640
sub _overwrite_existing_file ($) {
Christian Fibich's avatar
Christian Fibich committed
641
    my ($self, $filename) = @_;
642
    my $logger = get_logger("");
Christian Fibich's avatar
Christian Fibich committed
643
    if (!-e $filename) {
644
645
        return 1;
    }
646
647
648
649
650
651
652
    my $d = $self->{'mw'}->FIJIModalDialog(-delete_mw => [\&_onexit, $self], 
                                           -mw        => $self->{'mw'},
                                           -image     => $alert_image,
                                           -text      => "File \"$filename\" already exists.\nDo you want to overwrite it?",
                                           -title     => 'Really overwrite?',
                                           -buttons   => ["Yes", "No"]);

653
    my $reply = $d->Show();
654
    return (defined $reply && lc($reply) eq 'yes');
655
656
}

657
sub _save_file {
Christian Fibich's avatar
Christian Fibich committed
658
    my ($self, $filename) = @_;
659
    my $logger = get_logger("");
Christian Fibich's avatar
Christian Fibich committed
660
    if (!$self->_overwrite_existing_file($filename)) {
661
662
663
664
        return;
    }

    # Check if all drivers are set, prompt for missing ones
665
    my $drv  = $self->{'FIJISettingsViewer'}->validate_all_drivers();
666
    my $dup  = $self->{'FIJISettingsViewer'}->validate_duplicate_nets();
667
    my $dsgn = $self->{'FIJISettingsViewer'}->validate_all_design_settings();
668

669
    # Warn the user if not all drivers could be validated successfully
670
671
672
673
674
675
676
677
678
    my $rv;
    if (defined($drv)) {
        $rv = "$drv\n";
        $logger->error($drv);
    }
    if (defined($dsgn)) {
        $rv .= "$dsgn\n";
        $logger->error($dsgn);
    }
679
680
681
682
    if (defined($dup)) {
        $rv .= "$dup\n";
        $logger->error($dup);
    }
683
    
684
    if (defined($drv) || defined($dsgn) || defined($dup)) {
685
686
687
        my $d = $self->{'mw'}->FIJIModalDialog(-delete_mw   => [\&_onexit, $self],
                                               -mw          => $self->{'mw'},
                                               -image       => $alert_image,
688
                                               -text        => $rv . "Save Settings nevertheless?",
689
690
691
692
                                               -wraplength  => 350,
                                               -title       => 'Validation failed',
                                               -buttons     => [qw/Yes No/]);

693
        my $save = $d->Show();
694
        if (!defined $save || $save eq "No") {
695
696
697
698
699
700
701
702
            $logger->info("Saving aborted.");
            return;
        }
        $logger->info("Saving settings nevertheless.");
    }

    # Try to save the settings file
    my $err = $self->{'settings'}->save($filename);
Christian Fibich's avatar
Christian Fibich committed
703
    if (defined($err)) {
704
705
        my $msg = "Saving to file $filename failed!\n$err";
        $logger->error($msg);
706
707
708
709
710
711
712
713

        my $d = $self->{'mw'}->FIJIModalDialog(-delete_mw   => [\&_onexit, $self], 
                                               -mw          => $self->{'mw'},
                                               -image       => $error_image,
                                               -text        => $msg,
                                               -title       => 'Save failed!',
                                               -buttons     => ["OK"]);

714
        $d->Show();
715
716
        return;
    }
Christian Fibich's avatar
Christian Fibich committed
717
    ${$self->{'ini_name'}} = $filename;
718

719
720
    $self->{'FIJISettingsViewer'}->set_state_as_original();

721
    $logger->info("Successfully saved to file $filename.");
722
723
724
}

sub _save {
725
    my ($self) = @_;
Christian Fibich's avatar
Christian Fibich committed
726
    if (!defined(${$self->{'ini_name'}})) {
727
728
        return $self->_save_as();
    } else {
Christian Fibich's avatar
Christian Fibich committed
729
        return $self->_save_file(${$self->{'ini_name'}});
730
    }
731
732
733
}

sub _save_as {
734
735
736
737
738
739
740
    my ($self) = @_;
    my $filename = $self->{'mw'}->FBox(
        -type             => 'save',
        -title            => 'Save FIJI Configuration file as...',
        -defaultextension => 'cfg',
        -filetypes        => FILE_TYPES_CFG,
        -initialdir       => '.',
741
742
743
744
        -initialfile      => 'fiji.cfg',
        -force            => 1, # prevent FBox's "overwrite?" dialog
                                #    because we have our own check and a nicer dialog
                                #    AND we want to prevent showing the dialog twice
745
746
    )->Show();

Christian Fibich's avatar
Christian Fibich committed
747
    if (!defined($filename)) {
748
749
750
        return;
    }
    return $self->_save_file($filename);
751
752
}

753
754
sub _onexit {
    my $logger = get_logger("");
755
756
    my ($self) = @_;
    my $mw = $self->{'mw'};
757

758
759
760
    return if (defined $self->{'already_clicked'} && $self->{'already_clicked'} == 1);
    $self->{'already_clicked'} = 1;

761
    my $response;
762
    if ($unsaved_changes == 1) {
763
764
765
766
767
768
769
770
771

        my $d = $self->{'mw'}->FIJIModalDialog(-delete_mw   => [\&_onexit, $self], 
                                               -mw          => $self->{'mw'},
                                               -image       => $alert_image,
                                               -text        => "Unsaved changes.\nDo you really want to quit?",
                                               -wraplength  => 350,
                                               -title       => 'Really quit?',
                                               -buttons     => ["Save", "Cancel", "Quit"]);

772
773
        $response = $d->Show();
        $self->{'already_clicked'} = 0;
774
        $logger->info("Settings changed. Asking to save.") if ($unsaved_changes == 1);
Christian Fibich's avatar
Christian Fibich committed
775

776
        # use _save_as to give the user the chance to save under a different name
777
        $self->_save_as if (defined $response && $response eq "Save");
778
        $logger->info("Save: " . (defined $response ? $response : "undef"));
779
780

        if (!defined $response || $response ne "Cancel") {
781
            goto finish;
782
783
        }
    } else {
784
        goto finish;
785
    }
786
787
788
789
790
791
792
793
794
795
796
    return;

finish:
    $delete_main = 0;
    $self->{'mw'}->destroy();
    return;
}

sub _cleanup {
    my $self = shift;
    $self->{'mw'}->destroy() if $delete_main; # according to Mastering O'Reilly
797
798
}

799
800
my $log_conf = File::Spec->catfile($FindBin::Bin, 'logger.conf');
Log::Log4perl::init_and_watch($log_conf, 'HUP');
801
exit main(@ARGV);