1package App::ZFSCurses::WidgetFactory;
2
3use 5.10.1;
4use strict;
5use warnings;
6
7=head1 NAME
8
9App::ZFSCurses::WidgetFactory - Create widgets.
10
11=head1 METHODS
12
13=head1 VERSION
14
15Version 1.212.
16
17=cut
18
19our $VERSION = '1.212';
20
21=head2 new
22
23Create an instance of App::ZFSCurses::WidgetFactory.
24
25=cut
26
27sub new {
28    my $class = shift;
29
30    my %args = (
31        container     => {},
32        properties    => {},
33        ro_properties => [
34            'available',         'compressratio',
35            'createtxg',         'creation',
36            'clones',            'defer_destroy',
37            'encryption_root',   'filesystem_count',
38            'keystatus',         'guid',
39            'logicalreferenced', 'logicalused',
40            'mounted',           'objsetid',
41            'origin',            'refcompressratio',
42            'referenced',        'receive_resume_token',
43            'snapshot_count',    'type',
44            'used',              'usedbychildren',
45            'usedbydataset',     'usedbyrefreservation',
46            'usedbysnapshots',   'userrefs',
47            'volsize',           'written',
48            'utf8only'
49        ]
50    );
51
52    my $this = bless \%args, $class;
53    $this->fill_property_hash();
54
55    return $this;
56}
57
58=head2 search_value
59
60Search a value in an array. Return the value index if found. Return -1 if not
61found.
62
63=cut
64
65sub search_value {
66    my $self = shift;
67    my ( $element, $array ) = @_;
68
69    foreach ( 0 .. $#$array ) {
70        if ( $array->[$_] eq $element ) {
71            return $_;
72        }
73    }
74
75    return -1;
76}
77
78=head2 widget_selector
79
80Select the right widget to create. This method expects a property list as first
81argument. It will then check for its type, create the widget accordingly and
82return it.
83
84=cut
85
86sub widget_selector {
87    my $self            = shift;
88    my $property_values = shift;
89
90    my $ref    = ref $property_values;
91    my $widget = {};
92
93    if ( $ref =~ /ARRAY/ ) {
94        $widget->{type}   = 'Radiobuttonbox';
95        $widget->{values} = {
96            -height      => -1,
97            -width       => -1,
98            -y           => 3,
99            -padleft     => 1,
100            -padright    => 1,
101            -padbottom   => 2,
102            -fg          => 'blue',
103            -bg          => 'black',
104            -vscrollbar  => 1,
105            -wraparound  => 1,
106            -intellidraw => 1,
107            -selected =>
108              $self->search_value( $self->{current_value}, $property_values ),
109            -values => $property_values
110        };
111    }
112    elsif ( $ref =~ /SCALAR/ ) {
113        $widget->{type}   = 'TextEntry';
114        $widget->{values} = {
115            -y        => 3,
116            -ipadleft => 1,
117            -sbborder => 1,
118            -width    => 10
119        };
120    }
121    else {
122        $widget->{type} = '';
123    }
124
125    return $widget;
126}
127
128=head2 make_widget
129
130Make a widget depending on the property type. This method expects a property
131and, sometimes, the current value (selected in the UI). This method is called
132from the UI module when a user selects a property and wants to change it.
133
134=cut
135
136sub make_widget {
137    my $self = shift;
138    my ( $property, $current_value ) = @_;
139
140    $self->{current_value} = $current_value;
141    my $property_values = $self->{properties}->{$property};
142    my $widget          = $self->widget_selector($property_values);
143
144    my $property_widget = $self->{container}
145      ->add( 'property_widget', $widget->{type}, %{ $widget->{values} } );
146
147    $property_widget->draw();
148    return $property_widget;
149}
150
151=head2 set_container
152
153Set the container that will contain the created widget.
154
155=cut
156
157sub set_container {
158    my $self      = shift;
159    my $container = shift;
160    $self->{container} = $container;
161}
162
163=head2 fill_property_hash
164
165Read the DATA handle and fill the property hash. __DATA__ contains a list of
166key value pairs that represent a property and its possible values. Note: the
167ALNUM value means the property is alphanumerical and a textfield has to be
168created to be shown to the user. Otherwise, a radio button box is created with
169the possible values. See the widget_selector function.
170
171=cut
172
173sub fill_property_hash {
174    my $self = shift;
175
176    while (<DATA>) {
177        chomp;
178
179        my ( $property, $values ) = split /%/;
180        my @values = split /,/, $values;
181
182        if ( $property =~ /compression/ ) {
183            push @values, do {
184                my $gzip = [];
185                push @$gzip, "gzip-$_", for ( 1 .. 9 );
186                @$gzip;
187            };
188        }
189
190        if ( $values eq 'ALNUM' ) {
191            $self->{properties}->{$property} = \$values;
192        }
193        else {
194            $self->{properties}->{$property} = [ sort @values ];
195        }
196    }
197}
198
199=head2 properties
200
201Return the properties hash.
202
203=cut
204
205sub properties {
206    my $self = shift;
207    return $self->{properties};
208}
209
210=head2 is_property_ro
211
212Check whether a property is read only (cannot be changed).
213
214=cut
215
216sub is_property_ro {
217    my $self     = shift;
218    my $property = shift;
219    my $array    = $self->{ro_properties};
220
221    # 1 -> true. property is read only.
222    # 0 -> false. property is not read only.
223    my $is_ro = 1;
224
225    foreach ( 0 .. $#$array ) {
226        if ( $array->[$_] eq $property ) {
227            $is_ro = 0;
228            last;
229        }
230    }
231
232    return $is_ro;
233}
234
235=head1 AUTHOR
236
237Patrice Clement <monsieurp at cpan.org>
238
239=head1 LICENSE AND COPYRIGHT
240
241This software is copyright (c) 2020 by Patrice Clement.
242
243This is free software, licensed under the (three-clause) BSD License.
244
245See the LICENSE file.
246
247=cut
248
2491;
250
251__DATA__
252aclinherit%discard,noallow,restricted,passthrough,passthrough-x
253aclmode%discard,groupmask,passthrough,restricted
254atime%on,off
255canmount%on,off,noauto
256checksum%on,off,fletcher2,fletcher4,sha256,noparity,sha512,skein
257compression%on,off,lzjb,zle,lz4,gzip
258copies%1,2,3
259casesensitivity%sensitive,insensitive,mixed
260dedup%on,off,verify,sha256,sha256verify,sha512,sha512verify,skein,skeinverify
261devices%on,off
262dnodesize%legacy,auto,1k,2k,4k,8k,16k
263exec%on,off
264jailed%off,on
265logbias%latency,throughput
266mlslabel%label,none
267nbmand%on,off
268normalization%none,formC,formD,formKC,formKD
269primarycache%all,none,metadata
270readonly%on,off
271redundant_metadata%all,most
272secondarycache%all,none,metadata
273setuid%on,off
274sharenfs%on,off,opts
275sharesmb%on,off,opts
276version%1,2,3,4,5,current
277snapdir%hidden,visible
278sync%standard,always,disabled
279volmode%default,geom,dev,none
280vscan%off,on
281xattr%off,on
282snapshot_limit%ALNUM
283filesystem_limit%ALNUM
284quota%ALNUM
285recordsize%ALNUM
286refquota%ALNUM
287refreservation%ALNUM
288reservation%ALNUM
289mountpoint%ALNUM
290volsize%ALNUM
291