Commit | Line | Data |
b8faba69 |
1 | package Reaction::UI::ViewPort::GridView::Entity; |
2 | |
3 | use Reaction::Class; |
4 | use Catalyst::Utils; |
5 | use aliased 'Reaction::InterfaceModel::Object'; |
6 | use aliased 'Reaction::UI::ViewPort::DisplayField::Text'; |
7 | use aliased 'Reaction::UI::ViewPort::DisplayField::Number'; |
8 | use aliased 'Reaction::UI::ViewPort::DisplayField::Boolean'; |
9 | use aliased 'Reaction::UI::ViewPort::DisplayField::String'; |
10 | use aliased 'Reaction::UI::ViewPort::DisplayField::DateTime'; |
11 | use aliased 'Reaction::UI::ViewPort::DisplayField::RelatedObject'; |
12 | |
13 | |
14 | class Entity is 'Reaction::UI::ViewPort', which { |
15 | |
16 | has object => (isa => Object, is => 'ro', required => 1); |
17 | has field_order => (isa => 'ArrayRef', is => 'ro', required => 1); |
18 | |
19 | has fields => (isa => 'ArrayRef', is => 'rw', lazy_build => 1); |
20 | has builder_cache => (isa => 'HashRef', is => 'ro'); |
21 | has field_args => (isa => 'rw'); |
22 | |
23 | implements BUILD => as { |
24 | my ($self, $args) = @_; |
25 | my $field_args = delete $args->{Field}; |
26 | $self->field_args( {Field => $field_args} ) if ref $field_args; |
27 | }; |
28 | |
89939ff9 |
29 | implements _build_fields => as { |
b8faba69 |
30 | my ($self) = @_; |
31 | my $obj = $self->object; |
32 | my $args = $self->has_field_args ? $self->field_args : {}; |
33 | my $builders = $self->has_builder_cache ? $self->builder_cache : {}; |
34 | my @cells; |
35 | for my $field (@{ $self->field_order }) { |
36 | my $attr = $obj->meta->find_attribute_by_name($field); |
37 | my $build_meth = $builders->{$field} ||= $self->get_builder_for($attr); |
38 | my $loc = join('-', $self->location, 'field', $attr->name); |
39 | my $vp_args = {Field => { $attr->name => {location => $loc} } }; |
40 | my $merged = Catalyst::Utils::merge_hashes($args, $vp_args); |
41 | my $cell = $self->$build_meth($obj, $attr, $merged); |
42 | #XXX add a blank VP if !$cell here to mantain grid integrity |
43 | push(@cells, $cell) if $cell; |
44 | } |
45 | return \@cells; |
46 | }; |
47 | |
48 | implements get_builder_for => as { |
49 | my ($self, $attr) = @_; |
50 | my $attr_name = $attr->name; |
89939ff9 |
51 | my $builder = "_build_fields_for_name_${attr_name}"; |
b8faba69 |
52 | return $builder if $self->can($builder); |
53 | if ($attr->has_type_constraint) { |
54 | my $constraint = $attr->type_constraint; |
55 | my $base_name = $constraint->name; |
56 | my $tried_isa = 0; |
57 | CONSTRAINT: while (defined($constraint)) { |
58 | my $name = $constraint->name; |
59 | $name = $attr->_isa_metadata if($name eq '__ANON__'); |
60 | if (eval { $name->can('meta') } && !$tried_isa++) { |
61 | foreach my $class ($name->meta->class_precedence_list) { |
62 | my $mangled_name = $class; |
63 | $mangled_name =~ s/:+/_/g; |
89939ff9 |
64 | my $builder = "_build_fields_for_type_${mangled_name}"; |
b8faba69 |
65 | return $builder if $self->can($builder); |
66 | } |
67 | } |
68 | if (defined($name)) { |
69 | unless (defined($base_name)) { |
70 | $base_name = "(anon subtype of ${name})"; |
71 | } |
72 | my $mangled_name = $name; |
73 | $mangled_name =~ s/:+/_/g; |
89939ff9 |
74 | my $builder = "_build_fields_for_type_${mangled_name}"; |
b8faba69 |
75 | return $builder if $self->can($builder); |
76 | } |
77 | $constraint = $constraint->parent; |
78 | } |
79 | if (!defined($constraint)) { |
89939ff9 |
80 | confess "Can't build field ${attr_name} of type ${base_name} without $builder method or _build_fields_for_type_<type> method for type or any supertype"; |
b8faba69 |
81 | } |
82 | } else { |
83 | confess "Can't build field ${attr} without $builder method or type constraint"; |
84 | } |
85 | }; |
86 | |
87 | |
89939ff9 |
88 | implements _build_simple_field => as { |
b8faba69 |
89 | my ($self, $class, $obj, $attr, $args) = @_; |
90 | my $attr_name = $attr->name; |
91 | my %extra; |
92 | if (my $config = $args->{Field}{$attr_name}) { |
93 | %extra = %$config; |
94 | } |
95 | |
96 | return $class->new( |
97 | object => $obj, |
98 | attribute => $attr, |
99 | name => $attr->name, |
100 | ctx => $self->ctx, |
101 | %extra |
102 | ); |
103 | }; |
104 | |
89939ff9 |
105 | implements _build_fields_for_type_Num => as { |
b8faba69 |
106 | my ($self, $obj, $attr, $args) = @_; |
107 | $args->{Field}{$attr->name}{layout} = 'value/number' |
108 | unless( exists $args->{Field}{$attr->name} && |
109 | exists $args->{Field}{$attr->name}{layout} && |
110 | defined $args->{Field}{$attr->name}{layout} |
111 | ); |
89939ff9 |
112 | return $self->_build_simple_field(Number, $obj, $attr, $args); |
b8faba69 |
113 | }; |
114 | |
89939ff9 |
115 | implements _build_fields_for_type_Int => as { |
b8faba69 |
116 | my ($self, $obj, $attr, $args) = @_; |
117 | $args->{Field}{$attr->name}{layout} = 'value/number' |
118 | unless( exists $args->{Field}{$attr->name} && |
119 | exists $args->{Field}{$attr->name}{layout} && |
120 | defined $args->{Field}{$attr->name}{layout} |
121 | ); |
89939ff9 |
122 | return $self->_build_simple_field(Number, $obj, $attr, $args); |
b8faba69 |
123 | }; |
124 | |
89939ff9 |
125 | implements _build_fields_for_type_Bool => as { |
b8faba69 |
126 | my ($self, $obj, $attr, $args) = @_; |
127 | $args->{Field}{$attr->name}{layout} = 'value/boolean' |
128 | unless( exists $args->{Field}{$attr->name} && |
129 | exists $args->{Field}{$attr->name}{layout} && |
130 | defined $args->{Field}{$attr->name}{layout} |
131 | ); |
89939ff9 |
132 | return $self->_build_simple_field(Boolean, $obj, $attr, $args); |
b8faba69 |
133 | }; |
134 | |
89939ff9 |
135 | implements _build_fields_for_type_Password => as { return }; |
b8faba69 |
136 | |
89939ff9 |
137 | implements _build_fields_for_type_Str => as { |
b8faba69 |
138 | my ($self, $obj, $attr, $args) = @_; |
139 | $args->{Field}{$attr->name}{layout} = 'value/string' |
140 | unless( exists $args->{Field}{$attr->name} && |
141 | exists $args->{Field}{$attr->name}{layout} && |
142 | defined $args->{Field}{$attr->name}{layout} |
143 | ); |
89939ff9 |
144 | return $self->_build_simple_field(String, $obj, $attr, $args); |
b8faba69 |
145 | }; |
146 | |
89939ff9 |
147 | implements _build_fields_for_type_SimpleStr => as { |
b8faba69 |
148 | my ($self, $obj, $attr, $args) = @_; |
149 | $args->{Field}{$attr->name}{layout} = 'value/string' |
150 | unless( exists $args->{Field}{$attr->name} && |
151 | exists $args->{Field}{$attr->name}{layout} && |
152 | defined $args->{Field}{$attr->name}{layout} |
153 | ); |
89939ff9 |
154 | return $self->_build_simple_field(String, $obj, $attr, $args); |
b8faba69 |
155 | }; |
156 | |
89939ff9 |
157 | implements _build_fields_for_type_DateTime => as { |
b8faba69 |
158 | my ($self, $obj, $attr, $args) = @_; |
159 | $args->{Field}{$attr->name}{layout} = 'value/date_time' |
160 | unless( exists $args->{Field}{$attr->name} && |
161 | exists $args->{Field}{$attr->name}{layout} && |
162 | defined $args->{Field}{$attr->name}{layout} |
163 | ); |
89939ff9 |
164 | return $self->_build_simple_field(DateTime, $obj, $attr, $args); |
b8faba69 |
165 | }; |
166 | |
89939ff9 |
167 | implements _build_fields_for_type_Enum => as { |
b8faba69 |
168 | my ($self, $obj, $attr, $args) = @_; |
169 | $args->{Field}{$attr->name}{layout} = 'value/string' |
170 | unless( exists $args->{Field}{$attr->name} && |
171 | exists $args->{Field}{$attr->name}{layout} && |
172 | defined $args->{Field}{$attr->name}{layout} |
173 | ); |
89939ff9 |
174 | return $self->_build_simple_field(String, $obj, $attr, $args); |
b8faba69 |
175 | }; |
176 | }; |
177 | |
178 | 1; |