
package Filesystem;

# Class "Filesystem": constructor, methods, destructor, global class data,
# etcetera.  Because a Filesystem object is a composite widget all the 
# Composite base class methods and advertised widgets are available to you.

require 5.002;
use English;
use Tk;
use strict;
use Tk::Frame;
@Filesystem::ISA = qw(Tk::Frame);
Construct Tk::Widget 'Filesystem';

# Filesystem Data Structures
# 
# 	%OBJTABLE
# 
# 		A hash indexed by Filesystem object name.  Each object entry
#               is itself an implicit reference to yet another hash (a Tk
#               composite Filesystem object) with the following keys:
# 
# 		{'error'}        = 1 IFF `df' error line
# 		{'stale_count'}  = log file no-show count
# 
# Filesystem Static Methods
# 
# 	Filesystem->delete_stale_objects(@active_objects);
# 
# 		The `delete_stale_objects' method removes Filesystem objects
#               who are missing from the MONDS "pretty print" log and have
#               exceeded the $MAXIMUM_STALE_COUNT.
# 
# 		@active_objects  = list of object names of currently active
#                                  Filesystem objects
# 
# 	Filesystem->find_object($objname);
# 	
# 		The `find_object' method returns an object reference
#               corresponding to an object name.
# 
# 		$objname = name of Filesystem object, typically of the form
#                          "host/fs".
# 
# Filesystem Virtual Methods
# 
# 	$objref = $mw->Filesystem(-object_name => $objname, -error => $error);
# 
# 		This is the Filesystem constructor.
# 
# 		$objname         = object name
# 		$error           = 1 IFF this is a `df' error widget
# 
# 	$objref->update_widget($text, $used, $color);
# 
# 		The `update_widget' method configures a Filesystem widget to
#               reflect the latest `df' date/time stamp and percent-used value
#               by changing the value of the Entry and Button widgets.  Also,
#               the Frame widget that acts as the bar graph is colored and
#               lengthened or shortened as required.
# 
# 		$text  = date/time stamp
# 		$used  = percent used
# 		$color = bar graph color

# Initialize global variables.

my $MAXIMUM_STALE_COUNT = 2;	# max log file no-show count
%Filesystem::OBJTABLE = ();	# list of Filesystem objects

# Public methods.

sub delete_stale_objects {

    # Compare the Active Objects list with the list of all objects and remove
    # old objects that aren't active anymore. By remove we mean:  destroy the
    # composite Tk widget and delete the object table hash entry.

    my($class, @active_objs) = @ARG;

    my($objname, $found, $actobj);
    foreach $objname (keys %Filesystem::OBJTABLE) {
	$found = 0;
	foreach $actobj (@active_objs) {
	    if ($actobj == $Filesystem::OBJTABLE{$objname}) {
		$found = 1;
		last;		# active object
	    }
	} # forend all objects
	if (not $found and $Filesystem::OBJTABLE{$objname}->{'stale_count'}++
	      >= $MAXIMUM_STALE_COUNT) {
	    my $stale = $Filesystem::OBJTABLE{$objname};
	    $Filesystem::OBJTABLE{$objname}->destroy;
	    delete $Filesystem::OBJTABLE{$objname};
	} elsif ($found) {
	    $Filesystem::OBJTABLE{$objname}->{'stale_count'} = 0;  
	}
    } # forend all active objects

} # end delete_stale_objects

sub find_object {

    # Map an object name to an object reference via %OBJTABLE.

    my($class, $objname) = @ARG;

    return $Filesystem::OBJTABLE{$objname};

} # end find_object

sub Populate {

    # Filesystem composite widget constructor.  If $error we have a `df'
    # error message and so construct a slightly different widget.

    my($cw, $args) = @ARG;

    $cw->SUPER::Populate($args);
    my($objname, $error) = (delete $args->{-object_name},
	delete $args->{-error});
    $args->{-borderwidth} = 0;

    my $ent = $cw->Component(
        'Entry'             => 'entry',
        -relief             => 'sunken',
        -borderwidth        => 1,
        -font               => 'fixed',
        -width              => ($error ? 60 : 15),
    );
    $ent->pack(-side => 'left');

    if (not $error) {
	my $but = $cw->Component(
            'Button'            => 'button',
	    -font               => 'fixed',
            -width              => 4,
	    -relief             => 'flat',
	    -disabledforeground => 'black',
	    -state              => 'disabled',
            -pady               => 1,
        );
	$but->pack(-side => 'left');

	my $bar = $cw->Component('Frame' => 'bar', -height => 8);
	$bar->pack(-side => 'left');
    }

    $cw->{'error'}       = $error;
    $cw->{'stale_count'} = 0;

    $Filesystem::OBJTABLE{$objname} = $cw;
    return $cw;

} # end Populate, Filesystem constructor

sub update_widget {

    # Update the Entry widget with new host/filesystem/date/time information,
    # the Button with percentage full and lengthen or shorten the colored
    # Frame as required.

    my($objref, $text, $width, $color) = @ARG;

    my $e = $objref->Subwidget('entry');
    $e->configure(-state => 'normal');
    $e->delete(0, 'end');
    $e->insert(0, $text);
    $e->configure(-state => 'disabled');
    if (not $objref->{'error'}) {
	$objref->Subwidget('button')->configure(-text => "$width%");
	$objref->Subwidget('bar')->configure(
            -width      => ($width - 89) * 20 - 14,
            -background => $color,
        );
    }

} # end update_widget

1;

