File Coverage

blib/lib/Webinject/Gui.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package Webinject::Gui;
2              
3             # Copyright 2004-2006 Corey Goldberg (corey@goldb.org)
4             #
5             # This file is part of WebInject.
6             #
7             # WebInject is free software; you can redistribute it and/or modify
8             # it under the terms of the GNU General Public License as published by
9             # the Free Software Foundation; either version 2 of the License, or
10             # (at your option) any later version.
11             #
12             # WebInject is distributed in the hope that it will be useful,
13             # but without any warranty; without even the implied warranty of
14             # merchantability or fitness for a particular purpose. See the
15             # GNU General Public License for more details.
16              
17 1     1   1007 use 5.006;
  1         4  
  1         36  
18 1     1   5 use strict;
  1         3  
  1         40  
19 1     1   17 use warnings;
  1         2  
  1         43  
20 1     1   521 use Tk;
  0            
  0            
21             use Tk::Stderr;
22             use Tk::ROText;
23             use Tk::Compound;
24             use Tk::ProgressBar::Mac;
25             use Tk::NoteBook;
26             use Tk::PNG;
27             use base qw/Webinject/;
28              
29             our $VERSION = '1.56';
30              
31             =head1 NAME
32              
33             Webinject::Gui - Gui part of Webinject
34              
35             =head1 SYNOPSIS
36              
37             use Webinject::Gui;
38             my $webinjectgui = Webinject::Gui->new();
39              
40             =head1 DESCRIPTION
41              
42             WebInject is a free tool for automated testing of web applications and web
43             services. It can be used to test individual system components that have HTTP
44             interfaces (JSP, ASP, CGI, PHP, AJAX, Servlets, HTML Forms, XML/SOAP Web
45             Services, REST, etc), and can be used as a test harness to create a suite of
46             [HTTP level] automated functional, acceptance, and regression tests. A test
47             harness allows you to run many test cases and collect/report your results.
48             WebInject offers real-time results display and may also be used for monitoring
49             system response times.
50              
51             =head1 CONSTRUCTOR
52              
53             =head2 new ( [ARGS] )
54              
55             Creates an C object.
56              
57             =cut
58              
59             sub new {
60             my $class = shift;
61             my (%options) = @_;
62             $| = 1; # don't buffer output to STDOUT
63              
64             my $self = {
65             'mainloop' => 1,
66             'stderrwindow' => 1,
67             };
68              
69             for my $opt_key ( keys %options ) {
70             if ( exists $self->{$opt_key} ) {
71             $self->{$opt_key} = $options{$opt_key};
72             }
73             else {
74             croak("unknown option: $opt_key");
75             }
76             }
77              
78             bless $self, $class;
79              
80             # save command line for later restarts
81             $self->{'command_line'} = $0." ".join(" ", @ARGV);
82             $self->{'gui'} = 1;
83              
84             $self->_set_defaults();
85             $self->_whackoldfiles();
86             $self->_init_main_window();
87              
88             return $self;
89             }
90              
91             ########################################
92              
93             =head1 METHODS
94              
95             =cut
96              
97             sub _init_main_window {
98             my $self = shift;
99              
100             $self->{'mainwindow'} = MainWindow->new(
101             -title => 'WebInject - HTTP Test Tool (version '. $Webinject::Gui::VERSION . ')',
102             -bg => '#666699',
103             -takefocus => '1', #start on top
104             );
105              
106             $self->{'mainwindow'}->geometry("750x650+0+0"); # size and screen placement
107             if($self->{'stderrwindow'}) {
108             $self->{'mainwindow'}->InitStderr; # redirect all STDERR to a window
109             }
110             $self->{'mainwindow'}->raise; # put application in front at startup
111             $self->{'mainwindow'}->bind( '' => sub { $self->engine(); } ); # F5 key makes it run
112              
113             if ( -e "icon.gif" ) { # if icon graphic exists, use it
114             $self->{'mainwindow'}->update();
115             my $icon = $self->{'mainwindow'}->Photo( -file => 'icon.gif' );
116             $self->{'mainwindow'}->iconimage($icon);
117             }
118              
119             if ( -e "logo.gif" ) { # if logo graphic exists, use it
120             $self->{'mainwindow'}->Photo( 'logogif', -file => "logo.gif" );
121             $self->{'mainwindow'}->Label(
122             -image => 'logogif',
123             -bg => '#666699',
124             )->place(qw/-x 305 -y 12/);
125             $self->{'mainwindow'}->update();
126             }
127              
128             my $menubar = $self->{'mainwindow'}->Frame(qw/-relief flat -borderwidth 2/);
129             $menubar->place(qw/-x 0 -y 0/);
130             $menubar->configure( -background => '#666699' ); # menu outline
131              
132             my $filemenu = $menubar->Menubutton(
133             -text => 'File',
134             -foreground => 'white',
135             -background => '#666699',
136             -activebackground => '#666699',
137             -activeforeground => 'black',
138             -tearoff => '0',
139             )->pack(qw/-side left/);
140              
141             $filemenu->command(
142             -label => 'Restart',
143             -background => '#666699',
144             -activebackground => '#EFEFEF',
145             -foreground => 'white',
146             -activeforeground => 'black',
147             -command => sub { $self->_gui_restart(); },
148             );
149              
150             $filemenu->command(
151             -label => 'Exit',
152             -background => '#666699',
153             -activebackground => '#EFEFEF',
154             -foreground => 'white',
155             -activeforeground => 'black',
156             -command => sub { exit; }
157             );
158              
159             my $viewmenu = $menubar->Menubutton(
160             -text => 'View',
161             -foreground => 'white',
162             -background => '#666699',
163             -activebackground => '#666699',
164             -activeforeground => 'black',
165             -tearoff => '0',
166             )->pack(qw/-side left/);
167              
168             $viewmenu->command(
169             -label => 'config.xml',
170             -background => '#666699',
171             -activebackground => '#EFEFEF',
172             -foreground => 'white',
173             -activeforeground => 'black',
174             -command => sub { $self->_viewconfig(); },
175             );
176              
177             my $aboutmenu = $menubar->Menubutton(
178             -text => 'About',
179             -foreground => 'white',
180             -background => '#666699',
181             -activebackground => '#666699',
182             -activeforeground => 'black',
183             -tearoff => '0',
184             )->pack(qw/-side left/);
185              
186             $aboutmenu->command(
187             -label => 'About WebInject',
188             -background => '#666699',
189             -activebackground => '#EFEFEF',
190             -foreground => 'white',
191             -activeforeground => 'black',
192             -command => sub { $self->_about() },
193             );
194              
195             $self->{'mainwindow'}->Label(
196             -text => 'Engine Status:',
197             -bg => '#666699',
198             -fg => '#FFFFFF',
199             )->place(qw/-x 12 -y 100/);
200             $self->{'mainwindow'}->update();
201              
202             $self->{'out_window'} = $self->{'mainwindow'}->Scrolled(
203             'ROText', # engine status window
204             -scrollbars => 'e',
205             -background => '#EFEFEF',
206             -width => '103',
207             -height => '7',
208             )->place(qw/-x 12 -y 118/);
209             $self->{'mainwindow'}->update();
210              
211             $self->{'tabs'} = $self->{'mainwindow'}->NoteBook(
212             -backpagecolor => '#666699',
213             -background => '#EFEFEF', # color for active tab
214             -foreground => 'black', # text color for active tab
215             -inactivebackground => '#BFBFBF', # color for inactive tabs
216             )->place(qw/-x 12 -y 240/); # outer notebook object
217              
218             my $status_tab = $self->{'tabs'}->add( 'statustab', -label => 'Status' );
219             $self->{'mainwindow'}->update();
220              
221             my $statustab_canvas = $status_tab->Canvas(
222             -width => '719',
223             -height => '365',
224             -highlightcolor => '#CCCCCC',
225             -background => '#EFEFEF',
226             )->pack();
227             $self->{'mainwindow'}->update(); # canvas to fill tab (to place widgets into)
228              
229             my $statustab_buttoncanvas = $statustab_canvas->Canvas(
230             -width => '700',
231             -height => '24',
232             -background => '#666699',
233             )->place(qw/-x 10 -y 334/);
234             $self->{'mainwindow'}->update(); # canvas to place buttons into
235              
236             $self->{'minimalcheckbx'} = 'minimal_off'; # give it a default value
237             $statustab_buttoncanvas->Label(
238             -text => 'Minimal Output',
239             -bg => '#666699',
240             -fg => 'white',
241             )->place(qw/-x 49 -y 4/);
242             $self->{'mainwindow'}->update();
243             $statustab_buttoncanvas->Checkbutton(
244             -text => '', # using a text widget instead
245             -onvalue => 'minimal_on',
246             -offvalue => 'minimal_off',
247             -variable => \$self->{'minimalcheckbx'},
248             -background => '#666699',
249             -activebackground => '#666699',
250             -highlightbackground => '#666699',
251             )->place(qw/-x 20 -y 2/);
252             $self->{'mainwindow'}->update();
253              
254             $self->{'timercheckbx'} = 'timer_off'; # give it a default value
255             $statustab_buttoncanvas->Label(
256             -text => 'Response Timer Output',
257             -bg => '#666699',
258             -fg => 'white',
259             )->place(qw/-x 199 -y 4/);
260             $self->{'mainwindow'}->update();
261             $statustab_buttoncanvas->Checkbutton(
262             -text => '', # using a text widget instead
263             -onvalue => 'timer_on',
264             -offvalue => 'timer_off',
265             -variable => \$self->{'timercheckbx'},
266             -background => '#666699',
267             -activebackground => '#666699',
268             -highlightbackground => '#666699',
269             )->place(qw/-x 170 -y 2/);
270             $self->{'mainwindow'}->update();
271              
272             $self->{'status_window'} = $statustab_canvas->Scrolled(
273             'ROText', # test case status monitor window
274             -scrollbars => 'e',
275             -background => '#EFEFEF',
276             -width => '102',
277             -height => '23',
278             )->place(qw/-x 0 -y 0/);
279             $self->{'mainwindow'}->update();
280             $self->{'status_window'}->tagConfigure( 'red', -foreground => '#FF3333' )
281             ; #define tag for font color
282             $self->{'status_window'}->tagConfigure( 'green', -foreground => '#009900' )
283             ; #define tag for font color
284              
285             $self->{'monitorenabledchkbx'} = 'monitor_on'; #give it a default value
286             $self->{'mainwindow'}->Label(
287             -text => 'Disable Monitor',
288             -bg => '#666699',
289             -fg => 'white',
290             )->place(qw/-x 189 -y 242/);
291             $self->{'mainwindow'}->update();
292             $self->{'monitor_enabledchkbx'} = $self->{'mainwindow'}->Checkbutton(
293             -text => '', #using a text widget instead
294             -onvalue => 'monitor_off',
295             -offvalue => 'monitor_on',
296             -variable => \$self->{'monitorenabledchkbx'},
297             -background => '#666699',
298             -activebackground => '#666699',
299             -highlightbackground => '#666699',
300             -command => sub { $self->_monitor_enable_disable(); },
301             )->place(qw/-x 160 -y 240/);
302             $self->{'mainwindow'}->update();
303             $self->_monitor_enable_disable(); #call sub to enable and create monitor
304              
305             $self->{'stop_button'} = $self->{'mainwindow'}->Button->Compound;
306             $self->{'stop_button'}->Text( -text => "Stop" );
307             $self->{'stop_button'} = $self->{'mainwindow'}->Button(
308             -width => '50',
309             -height => '13',
310             -background => '#EFEFEF',
311             -activebackground => '#666699',
312             -foreground => '#000000',
313             -activeforeground => '#FFFFFF',
314             -borderwidth => '3',
315             -image => $self->{'stop_button'},
316             -command => sub { $self->{'stop'} = 'yes'; },
317             )->place;
318             $self->{'mainwindow'}->update(); #create this button but don't place it yet
319              
320             $self->{'rtc_button'} = $self->{'mainwindow'}->Button->Compound;
321             $self->{'rtc_button'}->Text( -text => "Run" );
322             $self->{'rtc_button'} = $self->{'mainwindow'}->Button(
323             -width => '50',
324             -height => '13',
325             -background => '#EFEFEF',
326             -activebackground => '#666699',
327             -foreground => '#000000',
328             -activeforeground => '#FFFFFF',
329             -borderwidth => '3',
330             -image => $self->{'rtc_button'},
331             -command => sub { $self->engine(); },
332             )->place(qw/-x 110 -y 65/);
333             $self->{'mainwindow'}->update();
334             $self->{'rtc_button'}->focus();
335              
336             $self->{'progressbar'} = $self->{'mainwindow'}->ProgressBar(
337             -width => '420',
338             -bg => '#666699'
339             )->place(qw/-x 176 -y 65/);
340             $self->{'mainwindow'}->update();
341              
342             $self->{'status_ind'} = $self->{'mainwindow'}->Canvas(
343             -width => '28', #engine status indicator
344             -height => '9',
345             -background => '#666699',
346             )->place(qw/-x 621 -y 69/);
347             $self->{'mainwindow'}->update();
348              
349             if($self->{'mainloop'}) {
350             MainLoop;
351             }
352             return;
353             }
354              
355             ########################################
356             sub _gui_initial { #this runs when engine is first loaded
357             my $self = shift;
358              
359             $self->{'out_window'}->delete( '0.0', 'end' ); # clear window before starting
360             $self->{'status_window'}->delete( '0.0', 'end' ); # clear window before starting
361              
362             # change status color amber while running
363             $self->{'status_ind'}->configure( -background => '#FF9900' );
364              
365             $self->{'rtc_button'}->placeForget; # remove the run button
366             $self->{'stop_button'}->place(qw/-x 110 -y 65/); # place the stop button
367              
368             # disable button while running
369             $self->{'monitor_enabledchkbx'}->configure( -state => 'disabled' );
370              
371             $self->{'out_window'}->insert( "end", "Starting Webinject Engine... \n\n" );
372             $self->{'out_window'}->see("end");
373              
374             return;
375             }
376              
377             ########################################
378             sub _gui_restart { #kill the entire app and restart it
379             my $self = shift;
380             return exec $self->{'command_line'};
381             }
382              
383             ########################################
384             sub _gui_processing_msg {
385             my $self = shift;
386             my $file = shift;
387             $self->{'out_window'}->insert( "end", "processing test case file:\n".$file."\n\n", 'bold' );
388             $self->{'out_window'}->see("end");
389             return;
390             }
391              
392             ########################################
393             sub _gui_statusbar {
394             my $self = shift;
395             my $percentcomplete = ( $self->{'result'}->{'runcount'} / $self->{'result'}->{'casecount'} ) * 100;
396             # update progressbar with current status
397             $self->{'progressbar'}->set($percentcomplete);
398             return;
399             }
400              
401             ########################################
402             sub _gui_tc_descript {
403             my $self = shift;
404             my $case = shift;
405             unless ( $self->{'minimalcheckbx'} eq "minimal_on" ) {
406             $self->{'status_window'}->insert( "end", "- " . $case->{description1} . "\n" );
407             $self->{'status_window'}->see("end");
408             }
409             return;
410             }
411              
412             ########################################
413             sub _gui_status_passed {
414             my $self = shift;
415             $self->{'status_window'}->insert( "end", "PASSED\n", 'green' );
416             $self->{'status_window'}->see("end");
417             return;
418             }
419              
420             ########################################
421             sub _gui_status_failed {
422             my $self = shift;
423             if ( $1 and $2 ) {
424             $self->{'status_window'}->insert( "end", "FAILED ($1$2)\n", 'red' );
425             $self->{'status_window'}->see("end");
426             }
427             else {
428             $self->{'status_window'}->insert( "end", "FAILED\n", 'red' );
429             $self->{'status_window'}->see("end");
430             }
431             return;
432             }
433              
434             ########################################
435             sub _gui_timer_output {
436             my $self = shift;
437             my $latency = shift;
438             if ( $self->{'timercheckbx'} eq "timer_on" ) {
439             $self->{'status_window'}->insert( "end", $latency." s\n" );
440             $self->{'status_window'}->see("end");
441             }
442             return;
443             }
444              
445             ########################################
446             sub _gui_final {
447             my $self = shift;
448              
449             $self->{'out_window'}->insert( "end", "Execution Finished... see results.html file for detailed output report");
450             $self->{'out_window'}->see("end");
451              
452             $self->{'status_window'}->insert( "end", "\n\n------------------------------\nTotal Run Time: $self->{'result'}->{'totalruntime'} seconds\n");
453             $self->{'status_window'}->insert( "end", "\nTest Cases Run: $self->{'result'}->{'totalruncount'}\nTest Cases Passed: $self->{'result'}->{'totalcasespassedcount'}\nTest Cases Failed: $self->{'result'}->{'totalcasesfailedcount'}\nVerifications Passed: $self->{'result'}->{'totalpassedcount'}\nVerifications Failed: $self->{'result'}->{'totalfailedcount'}\n" );
454             $self->{'status_window'}->see("end");
455              
456             # change status color to reflect failure or all tests passed
457             if( $self->{'result'}->{'totalfailedcount'} > 0 ) {
458             # red
459             $self->{'status_ind'}->configure( -background => '#FF3333' );
460             }
461             else {
462             # green
463             $self->{'status_ind'}->configure( -background => '#009900' );
464             }
465              
466             # re-enable button after finish
467             $self->{'monitor_enabledchkbx'}->configure( -state => 'normal' );
468              
469             return;
470             }
471              
472             ########################################
473             sub _gui_updatemontab {
474             my $self = shift;
475              
476             # don't try to update if monitor is disabled in gui
477             if ( $self->{'monitorenabledchkbx'} ne 'monitor_off' ) {
478             if (
479             ( -e $self->{'config'}->{'output_dir'}."plot.png" )
480             and ( ( $self->{'config'}->{'graphtype'} ne 'nograph' )
481             or ( $self->{'switches'}->{'plotclear'} ne 'yes' ) )
482             )
483             {
484             # if plot graphic exists, put it in canvas
485             $self->{'montab_plotcanvas'}->Photo( 'plotgraph', -file => $self->{'config'}->{'output_dir'}."plot.png" );
486             $self->{'montab_plotcanvas'}->Label( -image => 'plotgraph' )->place(qw/-x 7 -y 0/);
487             }
488             }
489             return;
490             }
491              
492             ########################################
493             sub _gui_updatemonstats { #update timers and counts in monitor tab
494             my $self = shift;
495              
496             #don't try to update if monitor is disabled in gui
497             if( $self->{'monitorenabledchkbx'} ne 'monitor_off' ) {
498              
499             $self->{'mintime_text'}->configure( -text => "Min: $self->{'result'}->{'minresponse'} sec" );
500             $self->{'maxtime_text'}->configure( -text => "Max: $self->{'result'}->{'maxresponse'} sec" );
501             $self->{'avgtime_text'}->configure( -text => "Avg: $self->{'result'}->{'avgresponse'} sec" );
502             $self->{'runcounttotal_text'}->configure( -text => "Total: $self->{'result'}->{'totalruncount'}" );
503             $self->{'runcountcasespassed_text'}->configure( -text => "Passed: $self->{'result'}->{'totalcasespassedcount'}" );
504             $self->{'runcountcasespfailed_text'}->configure( -text => "Failed: $self->{'result'}->{'totalcasesfailedcount'}" );
505             }
506             return;
507             }
508              
509             ########################################
510             # flip button and do cleanup when user clicks Stop
511             sub _gui_stop {
512             my $self = shift;
513              
514             $self->{'stop_button'}->placeForget; #remove the stop botton
515             $self->{'rtc_button'}->place(qw/-x 110 -y 65/); #place the stop button
516              
517             $self->{'progressbar'}->set(-1); #update progressbar back to zero
518              
519             $self->{'mainwindow'}->update();
520              
521             $self->_gui_final();
522             return;
523             }
524              
525             ########################################
526             # remove graph
527             sub _gui_cleargraph {
528             my $self = shift;
529              
530             $self->_reset_result();
531              
532             # delete a plot file if it exists so an old one is never rendered
533             if ( -e $self->{'config'}->{'output_dir'}."plot.png" ) {
534             unlink $self->{'config'}->{'output_dir'}."plot.png";
535             }
536              
537             $self->{'montab_plotcanvas'}->destroy; # destroy the canvas
538              
539             $self->{'montab_plotcanvas'} = $self->{'montab_canvas'}->Canvas(
540             -width => '718',
541             -height => '240',
542             -background => '#EFEFEF',
543             )->place(qw/-x 0 -y 0/);
544             # canvas to place graph into
545             $self->{'mainwindow'}->update();
546             return;
547             }
548              
549             ########################################
550             # remove graph then set value to truncate log
551             sub _gui_cleargraph_button {
552             my $self = shift;
553              
554             $self->_gui_cleargraph();
555              
556             # set value so engine knows to truncate plot log
557             $self->{'switches'}->{'plotclear'} = 'yes';
558             return;
559             }
560              
561             ########################################
562             sub _about {
563             my $self = shift;
564              
565             $self->{'about'} = MainWindow->new(
566             -title => 'About WebInject',
567             -bg => '#666699',
568             -takefocus => '1', #start on top
569             );
570             $self->{'about'}->raise; #put in front
571             $self->{'about'}->geometry("320x200+200+200"); #size and screen placement
572             if ( -e "icon.gif" ) { #if icon graphic exists, use it
573             $self->{'about'}->update();
574             my $icon = $self->{'about'}->Photo( -file => 'icon.gif' );
575             $self->{'about'}->iconimage($icon);
576             }
577              
578             my $about_text = $self->{'about'}->ROText(
579             -width =>
580             '100', #make these big. window size is controlled by geometry instead
581             -height => '100',
582             -background => '#666699',
583             -foreground => 'white',
584             )->pack;
585              
586             $about_text->insert(
587             "end", qq|
588             WebInject
589             ©2004-2006 Corey Goldberg
590              
591             Please visit www.webinject.org
592             for information and documentation.
593              
594             WebInject is Free and Open Source.
595             Licensed under the terms of the GNU GPL.
596             |
597             );
598              
599             return;
600             }
601              
602             ########################################
603             sub _viewconfig {
604             my $self = shift;
605              
606             $self->{'viewconfig'} = MainWindow->new(
607             -title => 'config.xml',
608             -bg => '#666699',
609             -takefocus => '1', #start on top
610             );
611             $self->{'viewconfig'}->raise; #put in front
612             $self->{'viewconfig'}->geometry("500x400+200+200")
613             ; #size and screen placement
614             if ( -e "logo.gif" ) { #if icon graphic exists, use it
615             $self->{'viewconfig'}->update();
616             my $icon = $self->{'viewconfig'}->Photo( -file => 'icon.gif' );
617             $self->{'viewconfig'}->iconimage($icon);
618             }
619              
620             my $config_text = $self->{'viewconfig'}->ROText(
621             -width =>
622             '100', #make these big. window size is controlled by geometry instead
623             -height => '100',
624             -background => '#666699',
625             -foreground => 'white',
626             )->pack;
627              
628             my $file;
629             if($self->{'opt_configfile'} ) {
630             $file = $self->{'opt_configfile'};
631             } elsif(-e "config.xml") {
632             $file = "config.xml";
633             }
634             if(defined $file) {
635             # open file handle
636             open( my $config, '<', $file )
637             or die "\nERROR: Failed to open ".$file." file: $!\n\n";
638             # read the file into an array
639             my @configfile = <$config>;
640             $config_text->insert( "end", @configfile );
641             close($config);
642             } else {
643             $config_text->insert( "end", "couldn't open default config file" );
644             }
645              
646             return;
647             }
648              
649             ########################################
650             sub _monitor_enable_disable {
651             my $self = shift;
652              
653             my $mon_tab;
654             if ( !defined $self->{'monitorenabledchkbx'}
655             or $self->{'monitorenabledchkbx'} eq 'monitor_on' )
656             { #create the monitor tab and all it's widgets
657              
658             $mon_tab = $self->{'tabs'}->add( 'montab', -label => 'Monitor' );
659             $self->{'mainwindow'}->update(); #add the notebook tab
660              
661             $self->{'montab_canvas'} = $mon_tab->Canvas(
662             -width => '719',
663             -height => '365',
664             -background => '#EFEFEF',
665             )->place(qw/-x 0 -y 0/);
666             $self->{'mainwindow'}->update()
667             ; #canvas to fill tab (to place widgets into)
668              
669             $self->{'montab_plotcanvas'} = $self->{'montab_canvas'}->Canvas(
670             -width => '718',
671             -height => '240',
672             -background => '#EFEFEF',
673             )->place(qw/-x 0 -y 0/);
674             $self->{'mainwindow'}->update(); #canvas to place graph into
675              
676             my $clear_graph = $mon_tab->Button->Compound;
677             $clear_graph->Text( -text => "Clear Graph" );
678             $clear_graph = $mon_tab->Button(
679             -width => '70',
680             -height => '13',
681             -background => '#EFEFEF',
682             -activebackground => '#666699',
683             -foreground => '#000000',
684             -activeforeground => '#FFFFFF',
685             -borderwidth => '3',
686             -image => $clear_graph,
687             -command => sub { $self->_gui_cleargraph_button(); },
688             )->place(qw/-x 630 -y 310/);
689             $self->{'mainwindow'}->update();
690              
691             $self->{'montab_buttoncanvas'} = $self->{'montab_canvas'}->Canvas(
692             -width => '700',
693             -height => '26',
694             -background => '#666699',
695             )->place(qw/-x 10 -y 334/);
696             $self->{'mainwindow'}->update(); #canvas to place buttons into
697              
698             $self->{'montab_buttoncanvas'}->Label(
699             -text => 'Line Graph',
700             -bg => '#666699',
701             -fg => 'white',
702             )->place(qw/-x 49 -y 4/);
703             $self->{'mainwindow'}->update();
704             my $radiolinegraph = $self->{'montab_buttoncanvas'}->Radiobutton(
705             -value => 'lines',
706             -variable => \$self->{'graphtype'},
707             -indicatoron => 'true',
708             -background => '#666699',
709             -activebackground => '#666699',
710             -highlightbackground => '#666699',
711             )->place(qw/-x 20 -y 2/);
712             $self->{'mainwindow'}->update();
713              
714             $radiolinegraph->select; #select as default
715              
716             $self->{'montab_buttoncanvas'}->Label(
717             -text => 'Impulse Graph',
718             -bg => '#666699',
719             -fg => 'white',
720             )->place(qw/-x 199 -y 4/);
721             $self->{'mainwindow'}->update();
722             $self->{'montab_buttoncanvas'}->Radiobutton(
723             -value => 'impulses',
724             -variable => \$self->{'graphtype'},
725             -background => '#666699',
726             -activebackground => '#666699',
727             -highlightbackground => '#666699',
728             )->place(qw/-x 170 -y 2/);
729             $self->{'mainwindow'}->update();
730              
731             $self->{'montab_buttoncanvas'}->Label(
732             -text => 'No Graph',
733             -bg => '#666699',
734             -fg => 'white',
735             )->place(qw/-x 349 -y 4/);
736             $self->{'mainwindow'}->update();
737             $self->{'montab_buttoncanvas'}->Radiobutton(
738             -value => 'nograph',
739             -variable => \$self->{'graphtype'},
740             -background => '#666699',
741             -activebackground => '#666699',
742             -highlightbackground => '#666699',
743             -command => sub { $self->_gui_cleargraph(); }
744             , #remove graph from view
745             )->place(qw/-x 320 -y 2/);
746             $self->{'mainwindow'}->update();
747              
748             my $resptime_label = $self->{'montab_canvas'}->Label(
749             -width => '25',
750             -height => '1',
751             -background => '#EFEFEF',
752             -foreground => 'black',
753             -relief => 'flat',
754             -anchor => 'w',
755             )->place(qw/-x 12 -y 245/);
756             $self->{'mainwindow'}->update();
757             $resptime_label->configure( -text => 'Response Times:' );
758              
759             $self->{'minresponse'} = 'N/A'; #set initial value for timer display
760             $self->{'mintime_text'} = $self->{'montab_canvas'}->Label(
761             -width => '25',
762             -height => '1',
763             -background => '#EFEFEF',
764             -foreground => 'black',
765             -relief => 'flat',
766             -anchor => 'w',
767             )->place(qw/-x 32 -y 265/);
768             $self->{'mainwindow'}->update();
769             $self->{'mintime_text'}
770             ->configure( -text => "Min: $self->{'minresponse'} sec" );
771              
772             $self->{'maxresponse'} = 'N/A'; #set initial value for timer display
773             $self->{'maxtime_text'} = $self->{'montab_canvas'}->Label(
774             -width => '25',
775             -height => '1',
776             -background => '#EFEFEF',
777             -foreground => 'black',
778             -relief => 'flat',
779             -anchor => 'w',
780             )->place(qw/-x 32 -y 285/);
781             $self->{'mainwindow'}->update();
782             $self->{'maxtime_text'}
783             ->configure( -text => "Max: $self->{'maxresponse'} sec" );
784              
785             $self->{'avgresponse'} = 'N/A'; #set initial value for timer display
786             $self->{'avgtime_text'} = $self->{'montab_canvas'}->Label(
787             -width => '25',
788             -height => '1',
789             -background => '#EFEFEF',
790             -foreground => 'black',
791             -relief => 'flat',
792             -anchor => 'w',
793             )->place(qw/-x 32 -y 305/);
794             $self->{'mainwindow'}->update();
795             $self->{'avgtime_text'}
796             ->configure( -text => "Avg: $self->{'avgresponse'} sec" );
797              
798             $self->{'runcount_label'} = $self->{'montab_canvas'}->Label(
799             -width => '25',
800             -height => '1',
801             -background => '#EFEFEF',
802             -foreground => 'black',
803             -relief => 'flat',
804             -anchor => 'w',
805             )->place(qw/-x 250 -y 245/);
806             $self->{'mainwindow'}->update();
807             $self->{'runcount_label'}->configure( -text => 'Runtime Counts:' );
808              
809             $self->{'totalruncount'} = 'N/A'; #set initial value for count display
810             $self->{'runcounttotal_text'} = $self->{'montab_canvas'}->Label(
811             -width => '25',
812             -height => '1',
813             -background => '#EFEFEF',
814             -foreground => 'black',
815             -relief => 'flat',
816             -anchor => 'w',
817             )->place(qw/-x 270 -y 265/);
818             $self->{'mainwindow'}->update();
819             $self->{'runcounttotal_text'}
820             ->configure( -text => "Total: $self->{'totalruncount'}" );
821              
822             $self->{'casepassedcount'} = 'N/A'; #set initial value for count display
823             $self->{'runcountcasespassed_text'} = $self->{'montab_canvas'}->Label(
824             -width => '25',
825             -height => '1',
826             -background => '#EFEFEF',
827             -foreground => 'black',
828             -relief => 'flat',
829             -anchor => 'w',
830             )->place(qw/-x 270 -y 285/);
831             $self->{'mainwindow'}->update();
832             $self->{'runcountcasespassed_text'}
833             ->configure( -text => "Passed: $self->{'casepassedcount'}" );
834              
835             $self->{'casefailedcount'} = 'N/A'; #set initial value for count display
836             $self->{'runcountcasespfailed_text'} = $self->{'montab_canvas'}->Label(
837             -width => '25',
838             -height => '1',
839             -background => '#EFEFEF',
840             -foreground => 'black',
841             -relief => 'flat',
842             -anchor => 'w',
843             )->place(qw/-x 270 -y 305/);
844             $self->{'mainwindow'}->update();
845             $self->{'runcountcasespfailed_text'}
846             ->configure( -text => "Failed: $self->{'casefailedcount'}" );
847              
848             } #end monitor create
849              
850             if ( defined $self->{'monitorenabledchkbx'}
851             and $self->{'monitorenabledchkbx'} eq 'monitor_off' )
852             { #delete the tab when disabled
853             $mon_tab = $self->{'tabs'}->delete( 'montab', -label => 'Monitor' );
854             $self->{'mainwindow'}->update();
855             }
856              
857             return;
858             }
859              
860             ########################################
861             sub _gui_no_plotter_found { #if gnuplot not specified, notify on gui
862             my $self = shift;
863              
864             $self->{'montab_plotcanvas'}->Label(
865             -text =>
866             "Sorry, I can't display the graph.\nMake sure you have gnuplot on your system and it's location is specified in config.xml. ",
867             -bg => '#EFEFEF',
868             -fg => 'black',
869             )->place(qw/-x 95 -y 100/);
870             $self->{'mainwindow'}->update();
871             return;
872             }
873              
874              
875             =head1 SEE ALSO
876              
877             For more information about webinject visit http://www.webinject.org
878              
879             =head1 AUTHOR
880              
881             Corey Goldberg, Ecorey@goldb.orgE
882              
883             Sven Nierlein, Enierlein@cpan.orgE
884              
885             =head1 COPYRIGHT AND LICENSE
886              
887             Copyright (C) 2010 by Sven Nierlein
888              
889             Copyright (C) 2004-2006 by Corey Goldberg
890              
891             This library is free software; you can redistribute it under the GPL2 license.
892              
893             =cut
894              
895             1;
896             __END__