1 package Reaction::UI::Window;
4 use Reaction::UI::FocusStack;
6 use namespace::clean -except => [ qw(meta) ];
9 has ctx => (isa => 'Catalyst', is => 'ro', required => 1, weak_ref => 1);
10 has view_name => (isa => 'Str', is => 'ro', lazy_fail => 1);
11 has content_type => (isa => 'Str', is => 'rw', lazy_fail => 1);
12 has title => (isa => 'Str', is => 'rw', default => sub { 'Untitled window' });
14 # XXX compile failure because the Catalyst::View constraint would be
15 # auto-generated which doesn't work with unions. ::Types::Catalyst needed.
16 #isa => 'Catalyst::View|Reaction::UI::View',
17 isa => 'Object', is => 'ro', lazy_build => 1
20 isa => 'Reaction::UI::FocusStack',
21 is => 'ro', required => 1,
22 default => sub { Reaction::UI::FocusStack->new },
26 return $self->ctx->view($self->view_name);
30 my $res = $self->ctx->res;
31 if ( $res->status =~ /^3/ || length($res->body) ) {
32 $res->content_type('text/plain') unless $res->content_type;
42 #I really think we should make a copies of the parameter hashes here
43 #and then as we handle events, delete ethem from the event hashref, so
44 #that it thins down as it makes it down the viewport tree. which would
45 #limit the number of events that get to the children viewports. it wont
46 #save that many subcalls unless there is a lot of child_items, but it's
47 #more about doing the correct thing. It also avoids children viewports
48 #being able to see their parents' events, which leaves the door open for
49 #abuse of the system. thoughts anyone?
51 foreach my $type (qw/query body/) {
52 my $meth = "${type}_parameters";
53 my $param_hash = $ctx->req->$meth;
54 $self->focus_stack->apply_events($param_hash)
60 my $res = $self->ctx->res;
61 $res->body($self->view->render_window($self));
62 $res->content_type($self->content_type);
65 # required by old Renderer::XHTML
69 return $self->view->render_viewport($self, $vp);
72 __PACKAGE__->meta->make_immutable;
79 Reaction::UI::Window - Container for rendering the UI elements in
83 my $window = Reaction::UI::Window->new(
85 view_name => $view_name,
86 content_type => $content_type,
87 title => $window_title,
90 # More commonly, as Reaction::UI::Controller::Root creates one for you:
91 my $window = $ctx->stash->{window};
93 # Resolve current events and render the view of the UI
94 # elements of this Window:
95 # This is called by the end action of Reaction::UI::Controller::Root
98 # Resolve current events:
99 $window->flush_events();
101 # Render the top ViewPort in the FocusStack of this Window:
102 $window->flush_view();
104 # Render a particular ViewPort:
105 $window->render_viewport($viewport);
108 [% window.render_viewport(self.inner) %]
110 # Add a ViewPort to the UI:
111 $window->focus_stack->push_viewport('Reaction::UI::ViewPort');
115 A Window object is created and stored in the stash by
116 L<Reaction::UI::Controller::Root>, it is used to contain all the
117 elements (ViewPorts) that make up the UI. The Window is rendered in
118 the end action of the Root Controller to make up the page.
120 To add L<ViewPorts|Reaction::UI::ViewPort> to the stack, use the
121 L<Reaction::UI::Controller/push_viewport> method. For more detailed
122 information, read the L<Reaction::UI::FocusStack> and
123 L<Reaction::UI::ViewPort> documentation.
127 These are set for you by L<Reaction::UI::Controller::Root/begin> from
128 your Root controller configuration.
134 =item Arguments: $ctx?
138 The current L<Catalyst> context object.
144 =item Arguments: $viewname?
148 Retrieve/set the name of the L<Catalyst::View> component used to render
149 this Window. If this has not been set, rendering the Window will fail.
155 =item Arguments: $contenttype?
159 Retrieve the content_type for the page. If this has not been set,
160 rendering the Window will fail.
166 =item Arguments: $title?
172 Retrieve/set the title of this page, if not set, it will default to
179 =item Arguments: none
183 Retrieve the L<Catalyst::View> instance, this can be set, or will be
184 instantiated using the L<view_name> class.
190 =item Arguments: none
194 $window->focus_stack->push_viewport('Reaction::UI::ViewPort');
196 Retrieve the L<stack|Reaction::UI::FocusStack> of
197 L<ViewPorts|Reaction::UI::ViewPorts> that contains all the UI elements
198 for this Window. Use L<Reaction::UI::FocusStack/push_viewport> on this
199 to create more elements. An empty FocusStack is created by the
200 Controller::Root when the Window is created.
208 =item Arguments: none
212 Synchronize the current events with all the L<Reaction::UI::ViewPort>
213 objects in the UI, then render the root ViewPort. This is called for
214 you by L<Reaction::UI::Controller::Root/end>.
220 =item Arguments: none
224 Resolves all the current events, first the query parameters then the
225 body parameters, with all the L<Reaction::UI::ViewPort> objects in the
226 UI. This calls L<Reaction::UI::FocusStack/apply_events>. This method
227 is called by L<flush>.
233 =item Arguments: none
237 Renders the page into the L<Catalyst::Response> body, unless the
238 response status is already set to 3xx, or the body has already been
239 filled. This is done via L<Reaction::UI::View/render_window>. This
240 method is called by L<flush>.
244 See L<Reaction::Class> for authors.
248 See L<Reaction::Class> for the license.