1 package Reaction::UI::ViewPort::GridView::Entity;
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';
14 class Entity is 'Reaction::UI::ViewPort', which {
16 has object => (isa => Object, is => 'ro', required => 1);
17 has field_order => (isa => 'ArrayRef', is => 'ro', required => 1);
19 has fields => (isa => 'ArrayRef', is => 'rw', lazy_build => 1);
20 has builder_cache => (isa => 'HashRef', is => 'ro');
21 has field_args => (isa => 'rw');
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;
29 implements _build_fields => as {
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 : {};
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;
48 implements get_builder_for => as {
49 my ($self, $attr) = @_;
50 my $attr_name = $attr->name;
51 my $builder = "_build_fields_for_name_${attr_name}";
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;
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;
64 my $builder = "_build_fields_for_type_${mangled_name}";
65 return $builder if $self->can($builder);
69 unless (defined($base_name)) {
70 $base_name = "(anon subtype of ${name})";
72 my $mangled_name = $name;
73 $mangled_name =~ s/:+/_/g;
74 my $builder = "_build_fields_for_type_${mangled_name}";
75 return $builder if $self->can($builder);
77 $constraint = $constraint->parent;
79 if (!defined($constraint)) {
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";
83 confess "Can't build field ${attr} without $builder method or type constraint";
88 implements _build_simple_field => as {
89 my ($self, $class, $obj, $attr, $args) = @_;
90 my $attr_name = $attr->name;
92 if (my $config = $args->{Field}{$attr_name}) {
105 implements _build_fields_for_type_Num => as {
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}
112 return $self->_build_simple_field(Number, $obj, $attr, $args);
115 implements _build_fields_for_type_Int => as {
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}
122 return $self->_build_simple_field(Number, $obj, $attr, $args);
125 implements _build_fields_for_type_Bool => as {
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}
132 return $self->_build_simple_field(Boolean, $obj, $attr, $args);
135 implements _build_fields_for_type_Password => as { return };
137 implements _build_fields_for_type_Str => as {
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}
144 return $self->_build_simple_field(String, $obj, $attr, $args);
147 implements _build_fields_for_type_SimpleStr => as {
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}
154 return $self->_build_simple_field(String, $obj, $attr, $args);
157 implements _build_fields_for_type_DateTime => as {
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}
164 return $self->_build_simple_field(DateTime, $obj, $attr, $args);
167 implements _build_fields_for_type_Enum => as {
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}
174 return $self->_build_simple_field(String, $obj, $attr, $args);