Commit | Line | Data |
7adfd53f |
1 | package Reaction::UI::Window; |
2 | |
3 | use Reaction::Class; |
4 | use Reaction::UI::FocusStack; |
5 | |
6 | class Window which { |
7 | |
8 | has ctx => (isa => 'Catalyst', is => 'ro', required => 1); |
9 | has view_name => (isa => 'Str', is => 'ro', lazy_fail => 1); |
10 | has content_type => (isa => 'Str', is => 'ro', lazy_fail => 1); |
11 | has title => (isa => 'Str', is => 'rw', default => sub { 'Untitled window' }); |
12 | has view => ( |
13 | # XXX compile failure because the Catalyst::View constraint would be |
14 | # auto-generated which doesn't work with unions. ::Types::Catalyst needed. |
15 | #isa => 'Catalyst::View|Reaction::UI::View', |
16 | isa => 'Object', is => 'ro', lazy_build => 1 |
17 | ); |
18 | has focus_stack => ( |
19 | isa => 'Reaction::UI::FocusStack', |
20 | is => 'ro', required => 1, |
21 | default => sub { Reaction::UI::FocusStack->new }, |
22 | ); |
89939ff9 |
23 | |
24 | implements _build_view => as { |
7adfd53f |
25 | my ($self) = @_; |
26 | return $self->ctx->view($self->view_name); |
27 | }; |
89939ff9 |
28 | |
7adfd53f |
29 | implements flush => as { |
30 | my ($self) = @_; |
31 | $self->flush_events; |
32 | $self->flush_view; |
33 | }; |
89939ff9 |
34 | |
7adfd53f |
35 | implements flush_events => as { |
36 | my ($self) = @_; |
37 | my $ctx = $self->ctx; |
38 | foreach my $type (qw/query body/) { |
39 | my $meth = "${type}_parameters"; |
40 | my $param_hash = $ctx->req->$meth; |
41 | $self->focus_stack->apply_events($ctx, $param_hash); |
42 | } |
43 | }; |
89939ff9 |
44 | |
7adfd53f |
45 | implements flush_view => as { |
46 | my ($self) = @_; |
47 | return if $self->ctx->res->status =~ /^3/ || length($self->ctx->res->body); |
48 | $self->ctx->res->body( |
49 | $self->view->render_window($self) |
50 | ); |
51 | $self->ctx->res->content_type($self->content_type); |
52 | }; |
53 | |
54 | # required by old Renderer::XHTML |
89939ff9 |
55 | |
7adfd53f |
56 | implements render_viewport => as { |
57 | my ($self, $vp) = @_; |
58 | return unless $vp; |
59 | return $self->view->render_viewport($self, $vp); |
60 | }; |
61 | |
62 | }; |
63 | |
64 | 1; |
65 | |
66 | =head1 NAME |
67 | |
68 | Reaction::UI::Window - Container for rendering the UI elements in |
69 | |
70 | =head1 SYNOPSIS |
71 | |
72 | my $window = Reaction::UI::Window->new( |
73 | ctx => $ctx, |
74 | view_name => $view_name, |
75 | content_type => $content_type, |
76 | title => $window_title, |
77 | ); |
78 | |
9964b409 |
79 | # More commonly, as Reaction::UI::Controller::Root creates one for you: |
7adfd53f |
80 | my $window = $ctx->stash->{window}; |
81 | |
89939ff9 |
82 | # Resolve current events and render the view of the UI |
7adfd53f |
83 | # elements of this Window: |
9964b409 |
84 | # This is called by the end action of Reaction::UI::Controller::Root |
7adfd53f |
85 | $window->flush(); |
86 | |
87 | # Resolve current events: |
88 | $window->flush_events(); |
89 | |
90 | # Render the top ViewPort in the FocusStack of this Window: |
91 | $window->flush_view(); |
92 | |
93 | # Render a particular ViewPort: |
94 | $window->render_viewport($viewport); |
95 | |
96 | # Or in a template: |
97 | [% window.render_viewport(self.inner) %] |
98 | |
99 | # Add a ViewPort to the UI: |
100 | $window->focus_stack->push_viewport('Reaction::UI::ViewPort'); |
101 | |
102 | =head1 DESCRIPTION |
103 | |
104 | A Window object is created and stored in the stash by |
9964b409 |
105 | L<Reaction::UI::Controller::Root>, it is used to contain all the |
7adfd53f |
106 | elements (ViewPorts) that make up the UI. The Window is rendered in |
9964b409 |
107 | the end action of the Root Controller to make up the page. |
7adfd53f |
108 | |
109 | To add L<ViewPorts|Reaction::UI::ViewPort> to the stack, read the |
110 | L<Reaction::UI::FocusStack> and L<Reaction::UI::ViewPort> documentation. |
111 | |
112 | Several Window attributes are set by |
9964b409 |
113 | L<Reaction::UI::Controller::Root/begin> when a new Window is created, |
7adfd53f |
114 | these are as follows: |
115 | |
116 | =over |
117 | |
118 | =item ctx |
119 | |
120 | The current L<Catalyst> context object is set. |
121 | |
122 | =item view_name |
123 | |
9964b409 |
124 | The view_name is set from the L<Reaction::UI::Controller::Root> attributes. |
7adfd53f |
125 | |
126 | =item content_type |
127 | |
9964b409 |
128 | The content_type is set from the L<Reaction::UI::Controller::Root> attributes. |
7adfd53f |
129 | |
9964b409 |
130 | =item title |
7adfd53f |
131 | |
9964b409 |
132 | The title is set from the L<Reaction::UI::Controller::Root> |
133 | window_title attribute. |
7adfd53f |
134 | |
135 | =back |
136 | |
137 | =head1 METHODS |
138 | |
139 | =head2 ctx |
140 | |
141 | =over |
142 | |
9964b409 |
143 | =item Arguments: $ctx? |
7adfd53f |
144 | |
145 | =back |
146 | |
9964b409 |
147 | Retrieve/set the current L<Catalyst> context object. |
7adfd53f |
148 | |
149 | =head2 view_name |
150 | |
151 | =over |
152 | |
9964b409 |
153 | =item Arguments: %viewname? |
7adfd53f |
154 | |
155 | =back |
156 | |
9964b409 |
157 | Retrieve/set the name of the L<Catalyst::View> component used to render |
7adfd53f |
158 | this Window. If this has not been set, rendering the Window will fail. |
159 | |
160 | =head2 content_type |
161 | |
162 | =over |
163 | |
9964b409 |
164 | =item Arguments: $contenttype? |
7adfd53f |
165 | |
166 | =back |
167 | |
168 | Retrieve the content_type for the page. If this has not been set, |
169 | rendering the Window will fail. |
170 | |
171 | =head2 title |
172 | |
173 | =over |
174 | |
175 | =item Arguments: $title? |
176 | |
177 | =back |
178 | |
179 | [% window.title %] |
180 | |
9964b409 |
181 | Retrieve/set the title of this page, if not set, it will default to |
7adfd53f |
182 | "Untitled window". |
183 | |
184 | =head2 view |
185 | |
186 | =over |
187 | |
188 | =item Arguments: none |
189 | |
190 | =back |
191 | |
192 | Retrieve the L<Catalyst::View> instance, this can be set, or will be |
193 | instantiated using the L<view_name> class. |
194 | |
195 | =head2 focus_stack |
196 | |
197 | =over |
198 | |
199 | =item Arguments: none |
200 | |
201 | =back |
202 | |
203 | $window->focus_stack->push_viewport('Reaction::UI::ViewPort'); |
204 | |
205 | Retrieve the L<stack|Reaction::UI::FocusStack> of |
206 | L<ViewPorts|Reaction::UI::ViewPorts> that contains all the UI elements |
207 | for this Window. Use L<Reaction::UI::FocusStack/push_viewport> on this |
208 | to create more elements. An empty FocusStack is created by the |
9964b409 |
209 | Controller::Root when the Window is created. |
7adfd53f |
210 | |
211 | =head2 render_viewport |
212 | |
213 | =over |
214 | |
215 | =item Arguments: $viewport |
216 | |
217 | =back |
218 | |
219 | $window->render_viewport($viewport); |
220 | |
221 | [% window.render_viewport(self.inner) %] |
222 | |
223 | Calls render on the L<view> object used by this Window. The following |
224 | arguments are given: |
225 | |
226 | =over |
227 | |
228 | =item ctx |
229 | |
230 | The L<Catalyst> context object. |
231 | |
232 | =item self |
233 | |
234 | The ViewPort object to be rendered. |
235 | |
236 | =item window |
237 | |
238 | The Window object. |
239 | |
240 | =item type |
241 | |
242 | The string that describes the layout from L<Reaction::UI::ViewPort/layout>. |
243 | |
244 | =back |
245 | |
246 | =head2 flush |
247 | |
248 | =over |
249 | |
250 | =item Arguments: none |
251 | |
252 | =back |
253 | |
254 | Synchronize the current events with all the L<Reaction::UI::ViewPort> |
255 | objects in the UI, then render the root ViewPort. This is called for |
9964b409 |
256 | you by L<Reaction::UI::Controller::Root/end>. |
7adfd53f |
257 | |
258 | =head2 flush_events |
259 | |
260 | =over |
261 | |
262 | =item Arguments: none |
263 | |
264 | =back |
265 | |
266 | Resolves all the current events, first the query parameters then the |
267 | body parameters, with all the L<Reaction::UI::ViewPort> objects in the |
268 | UI. This calls L<Reaction::UI::FocusStack/apply_events>. This method |
269 | is called by L<flush>. |
270 | |
271 | =head2 flush_view |
272 | |
273 | =over |
274 | |
275 | =item Arguments: none |
276 | |
277 | =back |
278 | |
279 | Renders the page into the L<Catalyst::Response> body, unless the |
280 | response status is already set to 3xx, or the body has already been |
281 | filled. This calls L<render_viewport> with the root |
282 | L<Reaction::UI::ViewPort> from the L<focus_stack>. This method is |
283 | called by L<flush>. |
284 | |
285 | =head1 AUTHORS |
286 | |
287 | See L<Reaction::Class> for authors. |
288 | |
289 | =head1 LICENSE |
290 | |
291 | See L<Reaction::Class> for the license. |
292 | |
293 | =cut |