use Reaction::Class;
use Reaction::UI::FocusStack;
-class Window which {
-
- has ctx => (isa => 'Catalyst', is => 'ro', required => 1);
- has view_name => (isa => 'Str', is => 'ro', lazy_fail => 1);
- has content_type => (isa => 'Str', is => 'ro', lazy_fail => 1);
- has title => (isa => 'Str', is => 'rw', default => sub { 'Untitled window' });
- has view => (
- # XXX compile failure because the Catalyst::View constraint would be
- # auto-generated which doesn't work with unions. ::Types::Catalyst needed.
- #isa => 'Catalyst::View|Reaction::UI::View',
- isa => 'Object', is => 'ro', lazy_build => 1
- );
- has focus_stack => (
- isa => 'Reaction::UI::FocusStack',
- is => 'ro', required => 1,
- default => sub { Reaction::UI::FocusStack->new },
- );
-
- implements _build_view => as {
- my ($self) = @_;
- return $self->ctx->view($self->view_name);
- };
-
- implements flush => as {
- my ($self) = @_;
- $self->flush_events;
- $self->flush_view;
- };
-
- implements flush_events => as {
- my ($self) = @_;
- my $ctx = $self->ctx;
-
- #I really think we should make a copies of the parameter hashes here
- #and then as we handle events, delete ethem from the event hashref, so
- #that it thins down as it makes it down the viewport tree. which would
- #limit the number of events that get to the children viewports. it wont
- #save that many subcalls unless there is a lot of child_items, but it's
- #more about doing the correct thing. It also avoids children viewports
- #being able to see their parents' events, which leaves the door open for
- #abuse of the system. thoughts anyone?
-
- foreach my $type (qw/query body/) {
- my $meth = "${type}_parameters";
- my $param_hash = $ctx->req->$meth;
- $self->focus_stack->apply_events($ctx, $param_hash)
- if keys %$param_hash;
+use namespace::clean -except => [ qw(meta) ];
+
+
+has ctx => (isa => 'Catalyst', is => 'ro', required => 1, weak_ref => 1);
+has view_name => (isa => 'Str', is => 'ro', lazy_fail => 1);
+has content_type => (isa => 'Str', is => 'rw', lazy_fail => 1);
+has title => (isa => 'Str', is => 'rw', default => sub { 'Untitled window' });
+has view => (
+ # XXX compile failure because the Catalyst::View constraint would be
+ # auto-generated which doesn't work with unions. ::Types::Catalyst needed.
+ #isa => 'Catalyst::View|Reaction::UI::View',
+ isa => 'Object', is => 'ro', lazy_build => 1
+);
+has focus_stack => (
+ isa => 'Reaction::UI::FocusStack',
+ is => 'ro', required => 1,
+ default => sub { Reaction::UI::FocusStack->new },
+);
+sub _build_view {
+ my ($self) = @_;
+ return $self->ctx->view($self->view_name);
+};
+sub flush {
+ my ($self) = @_;
+ my $res = $self->ctx->res;
+ if ( $res->status =~ /^3/ || length($res->body) ) {
+ $res->content_type('text/plain') unless $res->content_type;
+ return;
+ }
+ $self->flush_events;
+ $self->flush_view;
+};
+sub flush_events {
+ my ($self) = @_;
+ my $ctx = $self->ctx;
+
+ #I really think we should make a copies of the parameter hashes here
+ #and then as we handle events, delete ethem from the event hashref, so
+ #that it thins down as it makes it down the viewport tree. which would
+ #limit the number of events that get to the children viewports. it wont
+ #save that many subcalls unless there is a lot of child_items, but it's
+ #more about doing the correct thing. It also avoids children viewports
+ #being able to see their parents' events, which leaves the door open for
+ #abuse of the system. thoughts anyone?
+
+ foreach my $type (qw/query body/) {
+ my $meth = "${type}_parameters";
+ my $req_param = $ctx->req->$meth;
+ my $param_hash = {
+ map {
+ $_ =~ m/(^r.+\:\w+)\.(x|y)/ ? # for <input type="image"... buttons
+ ( $1 => $req_param->{$_} )
+ : ( $_ => $req_param->{$_} )
+ } keys %$req_param
+ }; # yeah, FocusStack deletes it
+ my @param_keys = keys %$param_hash;
+ if (@param_keys) {
+ for (@param_keys) {
+ utf8::decode($param_hash->{$_})
+ unless (utf8::is_utf8($param_hash->{$_}));
+ }
+ $self->focus_stack->apply_events($param_hash);
}
- };
-
- implements flush_view => as {
- my ($self) = @_;
- my $res = $self->ctx->res;
- #$res->content_type($self->content_type);
- return if $res->status =~ /^3/ || length($res->body);
- $res->body($self->view->render_window($self));
- $res->content_type($self->content_type);
- };
+ }
+};
+sub flush_view {
+ my ($self) = @_;
+ my $res = $self->ctx->res;
+ my $res_body = $self->view->render_window($self);
+ utf8::encode($res_body) if utf8::is_utf8($res_body);
+ $res->body($res_body);
+ $res->content_type($self->content_type);
+};
- # required by old Renderer::XHTML
+# required by old Renderer::XHTML
+sub render_viewport {
+ my ($self, $vp) = @_;
+ return unless $vp;
+ return $self->view->render_viewport($self, $vp);
+};
- implements render_viewport => as {
- my ($self, $vp) = @_;
- return unless $vp;
- return $self->view->render_viewport($self, $vp);
- };
+__PACKAGE__->meta->make_immutable;
-};
1;
elements (ViewPorts) that make up the UI. The Window is rendered in
the end action of the Root Controller to make up the page.
-To add L<ViewPorts|Reaction::UI::ViewPort> to the stack, read the
-L<Reaction::UI::FocusStack> and L<Reaction::UI::ViewPort> documentation.
-
-Several Window attributes are set by
-L<Reaction::UI::Controller::Root/begin> when a new Window is created,
-these are as follows:
+To add L<ViewPorts|Reaction::UI::ViewPort> to the stack, use the
+L<Reaction::UI::Controller/push_viewport> method. For more detailed
+information, read the L<Reaction::UI::FocusStack> and
+L<Reaction::UI::ViewPort> documentation.
-=over
+=head1 ATTRIBUTES
-=item ctx
-
-The current L<Catalyst> context object is set.
-
-=item view_name
-
-The view_name is set from the L<Reaction::UI::Controller::Root> attributes.
-
-=item content_type
-
-The content_type is set from the L<Reaction::UI::Controller::Root> attributes.
-
-=item title
-
-The title is set from the L<Reaction::UI::Controller::Root>
-window_title attribute.
-
-=back
-
-=head1 METHODS
+These are set for you by L<Reaction::UI::Controller::Root/begin> from
+your Root controller configuration.
=head2 ctx
=back
-Retrieve/set the current L<Catalyst> context object.
+The current L<Catalyst> context object.
=head2 view_name
=over
-=item Arguments: %viewname?
+=item Arguments: $viewname?
=back
to create more elements. An empty FocusStack is created by the
Controller::Root when the Window is created.
-=head2 render_viewport
-
-=over
-
-=item Arguments: $viewport
-
-=back
-
- $window->render_viewport($viewport);
-
- [% window.render_viewport(self.inner) %]
-
-Calls render on the L<view> object used by this Window. The following
-arguments are given:
-
-=over
-
-=item ctx
-
-The L<Catalyst> context object.
-
-=item self
-
-The ViewPort object to be rendered.
-
-=item window
-
-The Window object.
-
-=item type
-
-The string that describes the layout from L<Reaction::UI::ViewPort/layout>.
-
-=back
+=head1 METHODS
=head2 flush
Renders the page into the L<Catalyst::Response> body, unless the
response status is already set to 3xx, or the body has already been
-filled. This calls L<render_viewport> with the root
-L<Reaction::UI::ViewPort> from the L<focus_stack>. This method is
-called by L<flush>.
+filled. This is done via L<Reaction::UI::View/render_window>. This
+method is called by L<flush>.
=head1 AUTHORS