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);
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);
37 #I really think we should make a copies of the parameter hashes here
38 #and then as we handle events, delete ethem from the event hashref, so
39 #that it thins down as it makes it down the viewport tree. which would
40 #limit the number of events that get to the children viewports. it wont
41 #save that many subcalls unless there is a lot of child_items, but it's
42 #more about doing the correct thing. It also avoids children viewports
43 #being able to see their parents' events, which leaves the door open for
44 #abuse of the system. thoughts anyone?
46 foreach my $type (qw/query body/) {
47 my $meth = "${type}_parameters";
48 my $param_hash = $ctx->req->$meth;
49 $self->focus_stack->apply_events($param_hash)
55 my $res = $self->ctx->res;
56 if ( $res->status =~ /^3/ || length($res->body) ) {
57 $res->content_type('text/plain') unless $res->content_type;
60 $res->body($self->view->render_window($self));
61 $res->content_type($self->content_type);
64 # required by old Renderer::XHTML
68 return $self->view->render_viewport($self, $vp);
71 __PACKAGE__->meta->make_immutable;
78 Reaction::UI::Window - Container for rendering the UI elements in
82 my $window = Reaction::UI::Window->new(
84 view_name => $view_name,
85 content_type => $content_type,
86 title => $window_title,
89 # More commonly, as Reaction::UI::Controller::Root creates one for you:
90 my $window = $ctx->stash->{window};
92 # Resolve current events and render the view of the UI
93 # elements of this Window:
94 # This is called by the end action of Reaction::UI::Controller::Root
97 # Resolve current events:
98 $window->flush_events();
100 # Render the top ViewPort in the FocusStack of this Window:
101 $window->flush_view();
103 # Render a particular ViewPort:
104 $window->render_viewport($viewport);
107 [% window.render_viewport(self.inner) %]
109 # Add a ViewPort to the UI:
110 $window->focus_stack->push_viewport('Reaction::UI::ViewPort');
114 A Window object is created and stored in the stash by
115 L<Reaction::UI::Controller::Root>, it is used to contain all the
116 elements (ViewPorts) that make up the UI. The Window is rendered in
117 the end action of the Root Controller to make up the page.
119 To add L<ViewPorts|Reaction::UI::ViewPort> to the stack, use the
120 L<Reaction::UI::Controller/push_viewport> method. For more detailed
121 information, read the L<Reaction::UI::FocusStack> and
122 L<Reaction::UI::ViewPort> documentation.
126 These are set for you by L<Reaction::UI::Controller::Root/begin> from
127 your Root controller configuration.
133 =item Arguments: $ctx?
137 The current L<Catalyst> context object.
143 =item Arguments: $viewname?
147 Retrieve/set the name of the L<Catalyst::View> component used to render
148 this Window. If this has not been set, rendering the Window will fail.
154 =item Arguments: $contenttype?
158 Retrieve the content_type for the page. If this has not been set,
159 rendering the Window will fail.
165 =item Arguments: $title?
171 Retrieve/set the title of this page, if not set, it will default to
178 =item Arguments: none
182 Retrieve the L<Catalyst::View> instance, this can be set, or will be
183 instantiated using the L<view_name> class.
189 =item Arguments: none
193 $window->focus_stack->push_viewport('Reaction::UI::ViewPort');
195 Retrieve the L<stack|Reaction::UI::FocusStack> of
196 L<ViewPorts|Reaction::UI::ViewPorts> that contains all the UI elements
197 for this Window. Use L<Reaction::UI::FocusStack/push_viewport> on this
198 to create more elements. An empty FocusStack is created by the
199 Controller::Root when the Window is created.
207 =item Arguments: none
211 Synchronize the current events with all the L<Reaction::UI::ViewPort>
212 objects in the UI, then render the root ViewPort. This is called for
213 you by L<Reaction::UI::Controller::Root/end>.
219 =item Arguments: none
223 Resolves all the current events, first the query parameters then the
224 body parameters, with all the L<Reaction::UI::ViewPort> objects in the
225 UI. This calls L<Reaction::UI::FocusStack/apply_events>. This method
226 is called by L<flush>.
232 =item Arguments: none
236 Renders the page into the L<Catalyst::Response> body, unless the
237 response status is already set to 3xx, or the body has already been
238 filled. This is done via L<Reaction::UI::View/render_window>. This
239 method is called by L<flush>.
243 See L<Reaction::Class> for authors.
247 See L<Reaction::Class> for the license.