changes so far for new moose / mop
[catagits/Reaction.git] / lib / Reaction / UI / ViewPort / GridView / Entity.pm
CommitLineData
b8faba69 1package Reaction::UI::ViewPort::GridView::Entity;
2
3use Reaction::Class;
4use Catalyst::Utils;
5use aliased 'Reaction::InterfaceModel::Object';
6use aliased 'Reaction::UI::ViewPort::DisplayField::Text';
7use aliased 'Reaction::UI::ViewPort::DisplayField::Number';
8use aliased 'Reaction::UI::ViewPort::DisplayField::Boolean';
9use aliased 'Reaction::UI::ViewPort::DisplayField::String';
10use aliased 'Reaction::UI::ViewPort::DisplayField::DateTime';
11use aliased 'Reaction::UI::ViewPort::DisplayField::RelatedObject';
12
13
14class 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
1781;