File Coverage

blib/lib/Curses/UI/DelimitedTextViewer.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package Curses::UI::DelimitedTextViewer;
2             ###############################################################################
3             # subclass of Curses::UI::TextViewer that display delimited files onscreen
4             # in fixed width columns
5             #
6             # (c) 2002 by Garth Sainio. All rights reserved.
7             #
8             # This program is free software; you can redistribute it and/or modify it
9             # under the same terms as perl itself.
10             ###############################################################################
11 1     1   8013 use strict;
  1         3  
  1         45  
12 1     1   8 use warnings;
  1         4  
  1         125  
13 1     1   1591 use Curses;
  0            
  0            
14             use Curses::UI::Common;
15             use Curses::UI::TextViewer;
16              
17             use vars qw(
18             $VERSION
19             @ISA
20             );
21              
22             $VERSION = '0.10';
23              
24             @ISA = qw(
25             Curses::UI::TextViewer
26             );
27              
28             sub new () {
29             my $class = shift;
30              
31             my %userargs = @_;
32             keys_to_lowercase(\%userargs);
33              
34             my %args = (
35             %userargs,
36             );
37             my $obj = $class->SUPER::new( %args);
38              
39             # set the delimiter, default to tab
40             $obj->{'-delimiter'} = $userargs{'-delimiter'} || "\t";
41              
42             # set the fieldSeparator
43             $obj->{'-fieldSeparator'} = $userargs{'-fieldSeparator'} || "|";
44              
45             # Caclulate the widths of the columns
46             $obj->{'-widths'} = $obj->calculate_widths($userargs{'-text'});
47             $obj->{'-maxcolumns'} = scalar(@{$obj->{'-widths'}});
48             $obj->{'-current_column'} = 0;
49              
50             # Turn the delimited text into fixed width text
51             $obj->{'-text'} = $obj->process_text($obj->{'-text'});
52              
53             # Check to see if the user wants to scroll by column
54             if($userargs{'-columnScroll'}) {
55             $obj = $obj->set_routine('cursor-right', \&scroll_column_right);
56             $obj = $obj->set_routine('cursor-left', \&scroll_column_left);
57             }
58              
59             return $obj;
60             }
61              
62             ###############################################################################
63             # process_text
64             # reformat the incoming text and get a list of the width of each delimited
65             # field. Store those widths for future scrolling
66             ###############################################################################
67             sub process_text {
68             my ($self, $text) = @_;
69              
70             my $out_text = "";
71             my $column_width = $self->{'-widths'};
72              
73             # split on new lines
74             my @lines = split($/, $text);
75              
76             # Now format the lines
77             foreach my $line (@lines) {
78             chomp($line);
79             my @parts = split("\t", $line);
80             foreach my $i (0..$#parts) {
81             # pad the part
82             my $spaces = $column_width->[$i] - length($parts[$i]);
83             $out_text .= $parts[$i] . " " x $spaces;
84             $out_text .= $self->{'-fieldSeparator'};
85             }
86              
87             if($self->{'-addBlankColumns'}) {
88             # Check to see if there were fewer columns in the line
89             # than in the column_width array
90             my $missing = scalar(@{$column_width}) - scalar(@parts);
91             foreach my $i (1..$missing) {
92             $out_text .= " " x $column_width->[$#parts + $i];
93             $out_text .= $self->{'-fieldSeparator'};
94             }
95             }
96              
97             $out_text .= "$/";
98             }
99              
100             return $out_text;
101             }
102              
103             ###############################################################################
104             # calculate_widths
105             ###############################################################################
106             sub calculate_widths {
107             my($self, $text) = @_;
108             my @column_widths;
109              
110             # calculate the column widths
111             # split on new lines
112             my @lines = split("$/", $text);
113             foreach my $line (@lines) {
114             # then split on the delimiter
115             my @parts = split("\t", $line);
116             # Check to see if the width of the column is greater than the
117             # already existing width
118             foreach my $i (0..$#parts) {
119             my $length = length($parts[$i]);
120             unless(defined($column_widths[$i])) {
121             $column_widths[$i] = $length;
122             }
123             $column_widths[$i] = $length if($length > $column_widths[$i]);
124             }
125             }
126             return \@column_widths;
127             }
128              
129             ###############################################################################
130             # scroll the cursor by a column width at a time
131             ###############################################################################
132              
133             sub scroll_column_right {
134             my $self = shift;
135              
136             # Check to make sure that the cursor is not already at the last
137             # column
138              
139             return $self->dobeep
140             if($self->{'-current_column'} == $self->{'-maxcolumns'});
141              
142             # Look up the current columns width and use that as the offset
143             my $index = $self->{'-current_column'};
144             my @widths = @{$self->{'-widths'}};
145             my $offset = $self->{'-widths'}->[$self->{'-current_column'}];
146              
147             # Don't scroll if the last column is already completely on screen
148             return $self->dobeep
149             if(($self->{-xscrpos}) >= ($self->{-hscrolllen} - $self->canvaswidth));
150              
151             # The first column should only be shifted the width the column
152             # whereas the others should be shifted the width of the column
153             # plus one. This keep the left edge of the screen (where the $
154             # appears) as the last space in the previous column.
155             if($index > 0) {
156             $offset++;
157             }
158              
159             # update the current column
160             $self->{'-current_column'}++;
161              
162             $self->{-xscrpos} += $offset;
163             $self->{-hscrollpos} = $self->{-xscrpos};
164             $self->{-xpos} = $self->{-xscrpos};
165              
166             return $self;
167             }
168              
169             ###############################################################################
170             # scroll the cursor by a column width at a time
171             ###############################################################################
172              
173             sub scroll_column_left {
174             my $self = shift;
175              
176             # Check to make sure that the cursor is not already at the first column
177              
178             return $self->dobeep if($self->{'-current_column'} == 0);
179              
180             # Look up the previous column's width and use that as the offset
181             my $index = $self->{'-current_column'};
182             $index--;
183             my $offset = $self->{'-widths'}->[$index];
184              
185             # The first column should only be shifted the width the column
186             # whereas the others should be shifted the width of the column
187             # plus one. This keep the left edge of the screen (where the $
188             # appears) as the last space in the previous column.
189             if($index > 0) {
190             $offset++;
191             }
192              
193             # update the current column
194             $self->{'-current_column'}--;
195              
196             $self->{-xscrpos} -= $offset;
197             $self->{-hscrollpos} = $self->{-xscrpos};
198             $self->{-xpos} = $self->{-xscrpos};
199              
200             return $self;
201             }
202              
203              
204             1;
205              
206             =pod
207              
208             =head1 NAME
209             Curses::UI::DelimitedTextViewer - Displays delimited files as fixed width.
210              
211             =head1 CLASS HIERARCHY
212              
213             Curses::UI::Widget
214             Curses::UI::Searchable
215             |
216             +----Curses::UI::TextEditor
217             |
218             +----Curses::UI::TextViewer
219             |
220             +----Curses::UI::DelimitedTextViewer
221              
222             =head1 SYNOPSIS
223              
224             my $editor = $screen->add(
225             'editor', 'DelimitedTextViewer',
226             -border => 1,
227             -padtop => 0,
228             -padbottom => 3,
229             -showlines => 0,
230             -sbborder => 0,
231             -vscrollbar => 1,
232             -hscrollbar => 1,
233             -showhardreturns => 0,
234             -wrapping => 0,
235             -text => $text,
236             -columnScroll => 1,
237             -addBlankColumns => 1,
238             -fieldSeparator => "*",
239             );
240              
241             =head1 DESCRIPTION
242              
243             Curses::UI::DelimitedTextViewer is subclass of Curses::UI::TextViewer
244             which allows a delimited file to be viewed on screen as a fixed width
245             file. This class adds the following arguments to those used by
246             Curses::UI::TextViewer:
247              
248             -delimiter specifies the delimiter used in incoming data
249              
250             -scrollColumn sets to 1 to scroll left and right column by column
251              
252             -fieldSeparator character used to seperate one column from another, the
253             default is a |
254              
255             -addBlankColumns adds extra columns of spaces and seperators if the incoming
256             data line did not have the maximum number of fields in it
257              
258              
259             =head1 SEE ALSO
260              
261             L,
262             L
263              
264              
265             =head1 AUTHOR
266              
267             Copyright (c) 2002 Garth Sainio. All rights reserved.
268              
269             This package is free software and is provided "as is" without express
270             or implied warranty. It may be used, redistributed and/or modified
271             under the same terms as perl itself.
272              
273              
274             =cut