use MooseX::Types::Common and MooseX::Types::DateTime
[catagits/Reaction.git] / lib / Reaction / UI / ViewPort / Collection / Grid.pm
CommitLineData
ddccc6a2 1package Reaction::UI::ViewPort::Collection::Grid;
2
3use Reaction::Class;
4
5use aliased 'Reaction::InterfaceModel::Collection' => 'IM_Collection';
f46fa4fd 6use aliased 'Reaction::UI::ViewPort::Collection::Grid::Member::WithActions';
ddccc6a2 7
81393881 8use namespace::clean -except => [ qw(meta) ];
9extends 'Reaction::UI::ViewPort::Collection';
ddccc6a2 10
f46fa4fd 11has field_order => ( is => 'ro', isa => 'ArrayRef', lazy_build => 1);
81393881 12has excluded_fields => ( is => 'ro', isa => 'ArrayRef', lazy_build => 1);
f46fa4fd 13has computed_field_order => (is => 'ro', isa => 'ArrayRef', lazy_build => 1);
14
e113d857 15has _raw_field_labels => (
f46fa4fd 16 is => 'rw',
17 isa => 'HashRef',
e113d857 18 init_arg => 'field_labels',
f46fa4fd 19 default => sub { {} },
e113d857 20);
f46fa4fd 21
e113d857 22has field_labels => (
f46fa4fd 23 is => 'ro',
24 isa => 'HashRef',
25 lazy_build => 1,
26 init_arg => undef,
e113d857 27);
81393881 28
f46fa4fd 29has member_action_count => (
30 is => 'rw',
31 isa => 'Int',
32 required => 1,
33 lazy => 1,
34 default => sub {
35 my $self = shift;
36 for (@{ $self->members }) {
37 my $protos = $_->action_prototypes;
37728bba 38 return scalar(keys(%$protos));
f46fa4fd 39 }
40 return 1;
41 },
42);
81393881 43
44####################################
f46fa4fd 45sub _build_member_class { WithActions };
46
81393881 47sub _build_field_labels {
48 my $self = shift;
e113d857 49 my %labels = %{$self->_raw_field_labels};
50 for my $field ( @{$self->computed_field_order}) {
51 next if $labels{$field};
81393881 52 $labels{$field} = join(' ', map{ ucfirst } split('_', $field));
53 }
54 return \%labels;
f46fa4fd 55}
56
57sub _build_field_order { []; }
58
59sub _build_excluded_fields { []; }
60
61#this is a total clusterfuck and it sucks we should just eliminate it and have
62# the grid members not render ArrayRef or Collection fields
81393881 63sub _build_computed_field_order {
64 my ($self) = @_;
65 my %excluded = map { $_ => undef } @{ $self->excluded_fields };
66 #treat _$field_name as private and exclude fields with no reader
67 my @names = grep { $_ !~ /^_/ && !exists($excluded{$_})} map { $_->name }
68 grep {
69 !($_->has_type_constraint &&
70 ($_->type_constraint->is_a_type_of('ArrayRef') ||
71 eval {$_->type_constraint->name->isa('Reaction::InterfaceModel::Collection')} ||
72 eval { $_->_isa_metadata->isa('Reaction::InterfaceModel::Collection') }
73 )
74 ) }
75 grep { defined $_->get_read_method }
76 $self->current_collection->member_type->parameter_attributes;
77
78 return $self->sort_by_spec($self->field_order, \@names);
f46fa4fd 79}
ddccc6a2 80
f46fa4fd 81around _build_members => sub {
82 my $orig = shift;
83 my $self = shift;
81393881 84 $self->member_args->{computed_field_order} ||= $self->computed_field_order;
37728bba 85 $self->member_args->{computed_action_order} ||= [];
f46fa4fd 86 my $members = $self->$orig(@_);
87
88 # cache everything yo
37728bba 89 for my $member (@$members){
90 $member->clear_computed_action_order;
91 my $order = $member->computed_action_order;
92 @{ $self->member_args->{computed_action_order} } = @$order;
93 last;
94 }
f46fa4fd 95
96 return $members;
81393881 97};
98
99__PACKAGE__->meta->make_immutable;
100
101
2dba7201 1021;
ddccc6a2 103
2dba7201 104__END__;
ddccc6a2 105
2dba7201 106=head1 NAME
107
108Reaction::UI::ViewPort::Collection
109
110=head1 DESCRIPTION
111
112This subclass of L<Reaction::UI::ViewPort::Collection> allows you to display a
113homogenous collection of Reaction::InterfaceModel::Objects as a grid.
114
115=head1 ATTRIBUTES
116
117=head2 field_order
118
119=head2 excluded_fields
120
121=head2 field_labels
122
7460b544 123=head2 _raw_field_labels
124
2dba7201 125=head2 computed_field_order
126
7460b544 127=head2 member_action_count
128
2dba7201 129=head1 INTERNAL METHODS
130
131These methods, although stable, are subject to change without notice. These are meant
132to be used only by developers. End users should refrain from using these methods to
133avoid potential breakages.
134
135=head1 SEE ALSO
136
137L<Reaction::UI::ViewPort::Collection>
138
139=head1 AUTHORS
140
141See L<Reaction::Class> for authors.
142
143=head1 LICENSE
144
145See L<Reaction::Class> for the license.
146
147=cut