X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FReaction%2FUI%2FViewPort%2FObject.pm;h=9a8738e1b8ac6fdda4e39258b0e658d63ab38c4c;hb=565a1fc7fe67c721f2766bdc3f55c5fcb33fc760;hp=e7a2e3a420b8977f86dc91e5eae636af4bbc6ee4;hpb=599c1172394e3377d8e3e28c06557a99a1a10d1e;p=catagits%2FReaction.git diff --git a/lib/Reaction/UI/ViewPort/Object.pm b/lib/Reaction/UI/ViewPort/Object.pm index e7a2e3a..9a8738e 100644 --- a/lib/Reaction/UI/ViewPort/Object.pm +++ b/lib/Reaction/UI/ViewPort/Object.pm @@ -16,23 +16,26 @@ use aliased 'Reaction::UI::ViewPort::Field::Container'; use aliased 'Reaction::InterfaceModel::Object' => 'IM_Object'; +use MooseX::Types::Moose qw/ArrayRef HashRef/; + use namespace::clean -except => [ qw(meta) ]; extends 'Reaction::UI::ViewPort'; #everything is read only right now. Later I can make somethings read-write #but first I need to figure out what depends on what so we can have decent triggers has model => (is => 'ro', isa => IM_Object, required => 1); -has fields => (is => 'ro', isa => 'ArrayRef', lazy_build => 1); +has fields => (is => 'ro', isa => ArrayRef, lazy_build => 1); has field_args => (is => 'rw'); -has field_order => (is => 'ro', isa => 'ArrayRef'); +has field_order => (is => 'ro', isa => ArrayRef); -has builder_cache => (is => 'ro', isa => 'HashRef', lazy_build => 1); -has excluded_fields => (is => 'ro', isa => 'ArrayRef', lazy_build => 1); -has computed_field_order => (is => 'ro', isa => 'ArrayRef', lazy_build => 1); +has builder_cache => (is => 'ro', isa => HashRef, lazy_build => 1); +has excluded_fields => (is => 'ro', isa => ArrayRef, lazy_build => 1); +has included_fields => (is => 'ro', isa => ArrayRef, lazy_build => 1); +has computed_field_order => (is => 'ro', isa => ArrayRef, lazy_build => 1); -has containers => ( is => 'ro', isa => 'ArrayRef', lazy_build => 1); -has container_layouts => ( is => 'rw', isa => 'ArrayRef' ); +has containers => ( is => 'ro', isa => ArrayRef, lazy_build => 1); +has container_layouts => ( is => 'rw', isa => ArrayRef ); sub BUILD { my ($self, $args) = @_; @@ -43,6 +46,7 @@ sub BUILD { sub _build_builder_cache { {} } sub _build_excluded_fields { [] } +sub _build_included_fields { [] } sub _build_containers { my $self = shift; @@ -105,8 +109,10 @@ sub _build_fields { sub _build_computed_field_order { my ($self) = @_; my %excluded = map { $_ => undef } @{ $self->excluded_fields }; + my %included = map { $_ => undef } @{ $self->included_fields }; #treat _$field_name as private and exclude fields with no reader - my @names = grep { $_ !~ /^_/ && !exists($excluded{$_})} map { $_->name } + my @names = grep { $_ !~ /^_/ && (!%included || exists( $included{$_}) ) + && !exists($excluded{$_}) } map { $_->name } grep { defined $_->get_read_method } $self->model->parameter_attributes; return $self->sort_by_spec($self->field_order || [], \@names); } @@ -170,11 +176,11 @@ sub _build_simple_field { my $field_name = $args{attribute}->name; return $class->new( - ctx => $self->ctx, - model => $self->model, - location => join('-', $self->location, 'field', $field_name), - %args - ); + ctx => $self->ctx, + model => $self->model, + location => join('-', $self->location, 'field', $field_name), + %args + ); } sub _build_fields_for_type_Num { @@ -239,6 +245,25 @@ sub _build_fields_for_type_Reaction_InterfaceModel_Collection { $self->_build_simple_field(attribute => $attr, class => Collection, %$args); } +sub _build_fields_for_type_MooseX_Types_Common_String_SimpleStr { + my ($self, $attr, $args) = @_; + $self->_build_simple_field(attribute => $attr, class => String, %$args); +} + +sub _build_fields_for_type_MooseX_Types_Common_String_Password { + return; +} + +sub _build_fields_for_type_MooseX_Types_DateTime_DateTime { + my ($self, $attr, $args) = @_; + $self->_build_simple_field(attribute => $attr, class => DateTime, %$args); +} + +sub _build_fields_for_type_DateTime { + my ($self, $attr, $args) = @_; + $self->_build_simple_field(attribute => $attr, class => DateTime, %$args); +} + __PACKAGE__->meta->make_immutable; 1; @@ -247,26 +272,72 @@ __END__; =head1 NAME -Reaction::UI::ViewPort::Object +Reaction::UI::ViewPort::Object - Display an InterfaceModel::Object + +=head1 SYNOPSIS + + use aliased 'Reaction::UI::ViewPort::Object'; + + ... + $controller->push_viewport(Object, + model => $person_interface_model_object, + fields_order => [qw( firstname lastname )], + excluded_fields => [qw( password )], + ); =head1 DESCRIPTION +Takes a L class and displays the +configured fields. + =head1 ATTRIBUTES =head2 model +Required L. + =head2 fields +Initialised via L + =head2 field_args +Hash reference keyed by field names. Values are hash references containing +arguments to the field builder method of the attribute. + =head2 field_order +Array reference of strings defining the order of all fields (including +the ones that might be excluded). + =head2 builder_cache +Hash reference containing resolved builder method names per field. Utilised +by L + =head2 excluded_fields +Array reference of strings naming fields to exclude from the interface. + +=head2 included_fields + +List of field names to include. If both C and +C are specified the result is those fields which +are in C and not in C. + =head2 computed_field_order +Array reference of strings Initialised by the L method. +Contains the fields to show in the correct order. + +=head2 containers + +Array reference populated by L. + +=head2 container_layouts + +Array reference containing container layout specifications. + =head1 INTERNAL METHODS These methods, although stable, are subject to change without notice. These are meant @@ -275,10 +346,61 @@ avoid potential breakages. =head2 BUILD +Takes the value of the C constructor argument, if true, and sets it as +the new L hash reference. + =head2 get_builder_for +Takes an attribute object as argument and returns a string containing +the name of the method that builds the fields for this attribute. + +If the viewport implements it, C<_build_fields_for_name_${attr_name}> will be used. + +If that is not available, it will take the C information of the type constraint +and see if it is a loaded class implementing C. If it is, every class in its +C will be taken and used to try to find a +C<_build_fields_for_type_${mangled_class_name}> method on the viewport. + +"mangled" means here that every C<:*> will be replaced with C<_>. For example: +C would become C. + +If the C information was not obtainable or no fitting method was found, it will +try the type name in a method named C<_build_fields_for_type_${mangled_type_name}>. + +If could be found on this constraint, it will make the same attempts to find a +method on its parent type constraint. + +This method will die if it can't locate a method to build a field for this +attribute. + +=head2 _build_containers + +Uses L to build a list of L +objects. + +=head2 _build_fields + +Takes the Ls C to build fields via L. +They will be ordered as specified in L. + +=head2 _build_computed_field_order + +Takes the names of the Ls C' reader methods and assumes +them as field names. Then it uses L and L to calculate +the order of all included fields and returns those names. + =head2 _build_simple_field + $self->_build_simple_field( + attribute => $attribute_object, + class => $field_class, + %field_attrs, + ); + +Takes an attribute meta object, a field class (a L subclass) +and an additional set of arguments to pass to the field constructor and returns the new +field. Field classes themselves are L subclasses. + =head2 _build_fields_for_type_Num =head2 _build_fields_for_type_Int @@ -301,6 +423,20 @@ avoid potential breakages. =head2 _build_fields_for_type_Reaction_InterfaceModel_Collection +=head1 FIELD TYPES + +L, +L, +L, +L, +L, +L, +L, +L, +L, +L, +L + =head1 AUTHORS See L for authors.