1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
|
# $Id: Random.pm,v 1.16 2004/10/16 21:08:40 jfontain Exp $
# Perl module sample file with random data
# Corresponding pkgIndex.tcl file content:
# package ifneeded Random 1.9 "source [file join $dir Random.pm]"
# Module name must be capitalized and file extension .pm.
# The version number (1.9 here) must match the module version
# (see below).
package Random; # must be capitalized
# Note: the subroutines after(), yield(), flashMessage(), pushMessage(),
# popMessage() and traceMessage() are defined by the core in the module
# namespace and therefore should be seen as reserved subroutines, not to
# be redefined in the module (this file for the Random module).
use strict;
use warnings; # highly recommended, makes debugging much easier
BEGIN {
# There is no need to export anything,
# as moodss core uses fully qualified Perl names
# The version number is mandatory. It must match with the
# pkgIndex.tcl file content.
# Example: our $VERSION = 1.18;
our $VERSION = qw($Revision: 1.16 $)[1];
# Note: see version number management requirements in moodss HTML
# documentation (Module Development section)
}
# Module data is arranged in a hash and an array both named "data",
# It contains configuration values as well as dynamic data
# (see update subroutine).
our %data;
our @data;
our $asynchronous;
# Hash members are:
# - updates: a counter. Must be incremented as soon as the data has been
# updated. Must be initialized in the module body in all cases as it
# is used for automatic module detection (may not be changed in the
# initialize subroutine).
$data{updates} = 0;
# Column numbers must be positive, starting from 0 included. Column members are:
# - label: the title displayed on the top cell of the data column.
# - type: valid types are: ascii, clock, dictionary, integer and real.
# - ascii: simple strings.
# - clock: accepts most date and time formats (you must really read the Tcl
# clock command manual page, scan subcommand, for a precise description.
# - dictionary: strings with eventually embedded numbers, taken into account
# when sorting the column.
# - real: floating point values.
# - message: help text that appears in a widget tip when the mouse
# cursor is left over the column title cell for a short while.
# - anchor: optional member. Column data is either centered by default
# (center), tucked to the left (left) or right side (right) of the
# column.
$data{columns}[0] = {label => 'name', type => 'ascii', message => 'user name'};
$data{columns}[1] = {label => 'cpu', type => 'real', message => 'cpu usage in percent'};
$data{columns}[2] = {label => 'disk', type => 'integer', message => 'disk usage in megabytes'};
$data{columns}[3] = {label => 'memory', type => 'integer', message => 'memory usage in kilobytes'};
$data{columns}[4] = {label => 'command', type => 'dictionary', message => 'command name', anchor => 'left'};
# - pollTimes: in seconds. A list with the default poll time in first
# position. The other times can be in any order, as the core will sort
# them and use the lowest value as the minimum poll time value.
# The minimum poll seconds must be a reasonable value depending on the
# processing time of the update subroutine.
$data{pollTimes} = [10, 5, 20, 30, 60, 120, 300];
# - indices: an optional list that specifies the data columns that
# should be displayed. If not specified, all the data columns are
# visible.
# Can be used when there are no views (see below).
#$data{indices} = [0, 1, 2, 3];
# - sort: an optional entry that defines the initial column to be used
# for sorting the table data and in which direction. The specified
# column must be visible (see indices member above).
# Should be a hash with a single entry with the column as index and
# either the 'increasing' or 'decreasing' keyword as value.
# Can be used when there are no views (see below).
#$data{sort} = {1 => 'decreasing'};
# - indexColumns: a list that specifies the columns required to uniquely
# identify a row in the table. It is optional and defaults to the
# column 0, unless of course you do not have a 0 column index, in
# which case it is mandatory to specify this list. When specified, all
# the columns in the list must be visible (see indices member above or
# in views below).
$data{indexColumns} = [0, 4];
# - views: optional. Arrays of hashes. If specified, it
# defines one or more views to be used in place of the default
# view. One table will be displayed per view.
# For each view, 1 entry must be defined: 'indices' (syntax and usage
# identical to the 'indices' list above).
# 2 members are optional:
# 'sort' (syntax and usage identical to the 'sort' entry above),
# and
# 'swap', a boolean, specifies whether the data is displayed in a table
# with columns and rows swapped (useful when data has only a single or
# a couple of rows permanently).
#$data{views} = [
# {indices => [0, 1, 3, 4], sort => {1 => 'decreasing'}, swap => 1},
# {indices => [0, 2, 4], sort => {2 => 'decreasing'}}
#];
$data{views} = [
{indices => [0, 1, 3, 4], sort => {1 => 'decreasing'}},
{indices => [0, 2, 4], sort => {2 => 'decreasing'}}
];
# - persistent: optional (considered false if missing). A boolean
# value that tells whether row numbers (used by the core, along with
# the column numbers, to identify data cells) are identically mapped
# from data row keys across module instances.
$data{persistent} = 1;
# - switches: optional. A hash of boolean values indexed by switches.
# A switch is a single letter or a string prepended with the - or +
# sign. The boolean value (0 or 1) specifies whether the switch takes
# an argument. If the switches list is defined, an appropriate
# initialize subroutine must be defined in the module (see initialize
# subroutine example in this module). The core will take care of
# parsing the command line and reject any invalid switch / value
# combination for the module. The switches value may not be changed in
# the initialize subroutine.
$data{switches} =
{'-a' => 0, '--asynchronous' => 0, '-i' => 0, '--identify' => 0};
# - identifier: optional. A string that uniquely identifies this
# module. It will be displayed by the core in the initial data tables
# title area and data cell labels in viewers. This feature can be used
# for example in modules that gather data from a remote host: in such
# a case, the identifier could be set to dataType(hostName).
# $data{identifier} = 'random(test)';
# - resizableColumns: optional. A boolean value (0 or 1) which specifies
# whether displayed data table(s) columns can be manually resized by
# the user with the mouse. Not available on a per view basis.
# $data{resizableColumns} = 0;
# - helpText: displayed when the module help is launched from the main
# window help menu. Can be plain text or HTML formatted (<HTML> and
# <BODY> tags required), in which case it is properly rendered in the
# module help window (note: tables, frames, and may other tags are not
# supported: stick to formatted text at the moment).
# Here we load the HTML code from a file in this module directory, which
# the core changes to during the loading stage.
# The HTML code can obviously also be inlined.
$data{helpText} = `cat Random.htm`; # load HTML formatted help
# The initialize subroutine, if it exists, is invoked by the core before
# any update occurs (update subroutine invocation if the module is
# synchronous (always the case in Perl modules)). It can be used for
# module setup that cannot be accomplished during the loading phase.
# The initialize subroutine is optional when the module does not support
# command line arguments, and in such a case takes no arguments.
# The initialize subroutine is mandatory when the module supports command
# line arguments, and in such a case takes an hash as sole argument. The
# hash contains the switched options values, indexed by switch. For
# example, if the command line was:
# $ moodss random --asynchronous --other-option value -x 1234
# the hash will contain:
# $options{--asynchronous} = 1
# $options{--other-option} = value
# $options{-x} = 1234
# Note that the --asynchronous member value is filled with a boolean
# even though that switch takes no argument.
# For the above example, switches would have been defined as:
# $data{switches} = [qw(-a 0 --asynchronous 0 --other-option 1 -x 1)];
# In all cases, data members other than updates and switches can be set
# or updated in the initialize subroutine, and still taken into account by
# the core.
sub initialize(%) {
my %option = @_;
$asynchronous = ($option{'-a'} || $option{'--asynchronous'});
if ($asynchronous) {
$data{pollTimes} = [-10];
# use the core to call a subroutine after a number of milliseconds
# without blocking the user interface, as sleep() would do
after(3000, 'Random::update'); # boot simulation
}
if ($option{'-i'} || $option{'--identify'}) {
# generate a unique module identifier:
my $identifier = int(rand(100));
$data{identifier} = "random $identifier";
}
}
# The terminate subroutine if it exists is invoked by the core when
# the module is unloaded dynamically.
sub terminate() {
# We could do some cleanup chores right here.
}
# The dynamic data array is 2 dimensional, indexed by row and column.
# The column number must start from 0 up to the total number of
# columns minus 1 (no holes are allowed in the column sequence).
# The row number can take any positive integer value (between 0 and
# 2147483647) and be defined in any order, as long as it is unique
# during the lifetime of the module data. If a new row is created, it
# must take a value that was never used: thus, the number of a row
# that has disappeared is not allowed. Row numbers need not be
# consecutive.
# Voidness for numeric data cells (integer or real type) takes the
# form of the ? character. Reminder: as long as a data row exists, all
# its data cells must exist. Thus voidness cannot be expressed by
# non-existence.
# The update subroutine function is to update module data.
sub update() {
$data[0][0] = "John\nWo"; $data[0][4] = 'cc';
$data[0][1] = sprintf('%.1f', rand(30)); $data[0][2] = 100 + int(rand(50)); $data[0][3] = 10 + int(rand(50));
$data[1][0] = 'Bill'; $data[1][4] = 'xedit';
$data[1][1] = sprintf('%.1f', rand(3)); $data[1][2] = 300 + int(rand(100)); $data[1][3] = 30 + int(rand(100));
$data[2][0] = "Anny\nDoe"; $data[2][4] = 'ps';
$data[2][1] = sprintf('%.1f', rand(5)); $data[2][2] = 200 + int(rand(30)); $data[2][3] = 20 + int(rand(30));
$data[3][0] = 'Robert'; $data[3][4] = 'top';
$data[3][1] = sprintf('%.1f', rand(10)); $data[3][2] = 500 + int(rand(150)); $data[3][3] = 50 + int(rand(150));
$data[4][0] = "Peter\nWard"; $data[4][4] = 'ls';
$data[4][1] = sprintf('%.1f', rand(8)); $data[4][2] = 50 + int(rand(10)); $data[4][3] = 5 + int(rand(10));
$data[6][0] = 'Laura'; $data[6][4] = 'emacs';
$data[6][1] = sprintf('%.1f', rand(20)); $data[6][2] = 90 + int(rand(20)); $data[6][3] = 9 + int(rand(20));
$data[9][0] = 'Laura'; $data[9][4] = 'cc';
$data[9][1] = sprintf('%.1f', rand(30)); $data[9][2] = 100 + int(rand(50)); $data[9][3] = 10 + int(rand(50));
if (int(rand(4)) == 0) {
# it is possible to post messages to the user:
flashMessage('the Random module is still at work', 2);
# also available: pushMessage(), popMessage() and traceMessage()
}
$data{updates}++;
if ($asynchronous) { # simulate asynchronous operation if requested
# use the core to call a subroutine after a number of milliseconds
# without blocking the user interface, as sleep() would do
after(2000 + int(rand(9000)), 'Random::update');
}
}
END {
# does not seem to be executed when interpreter is destroyed
# as module is unloaded: you may use terminate() instead.
}
1; # traditional
|