rework skin path handling
[catagits/Reaction.git] / lib / Reaction / UI / Window.pm
CommitLineData
7adfd53f 1package Reaction::UI::Window;
2
3use Reaction::Class;
4use Reaction::UI::FocusStack;
5
6class 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;
54756bc8 38
39 #I really think we should make a copies of the parameter hashes here
40 #and then as we handle events, delete ethem from the event hashref, so
41 #that it thins down as it makes it down the viewport tree. which would
42 #limit the number of events that get to the children viewports. it wont
43 #save that many subcalls unless there is a lot of child_items, but it's
44 #more about doing the correct thing. It also avoids children viewports
45 #being able to see their parents' events, which leaves the door open for
46 #abuse of the system. thoughts anyone?
47
7adfd53f 48 foreach my $type (qw/query body/) {
49 my $meth = "${type}_parameters";
50 my $param_hash = $ctx->req->$meth;
54756bc8 51 $self->focus_stack->apply_events($ctx, $param_hash)
52 if keys %$param_hash;
7adfd53f 53 }
54 };
89939ff9 55
7adfd53f 56 implements flush_view => as {
57 my ($self) = @_;
54756bc8 58 my $res = $self->ctx->res;
59 return if $res->status =~ /^3/ || length($res->body);
60 $res->body($self->view->render_window($self));
61 $res->content_type($self->content_type);
7adfd53f 62 };
63
64 # required by old Renderer::XHTML
89939ff9 65
7adfd53f 66 implements render_viewport => as {
67 my ($self, $vp) = @_;
68 return unless $vp;
69 return $self->view->render_viewport($self, $vp);
70 };
71
72};
73
741;
75
76=head1 NAME
77
78Reaction::UI::Window - Container for rendering the UI elements in
79
80=head1 SYNOPSIS
81
82 my $window = Reaction::UI::Window->new(
83 ctx => $ctx,
84 view_name => $view_name,
85 content_type => $content_type,
86 title => $window_title,
87 );
88
9964b409 89 # More commonly, as Reaction::UI::Controller::Root creates one for you:
7adfd53f 90 my $window = $ctx->stash->{window};
91
89939ff9 92 # Resolve current events and render the view of the UI
7adfd53f 93 # elements of this Window:
9964b409 94 # This is called by the end action of Reaction::UI::Controller::Root
7adfd53f 95 $window->flush();
96
97 # Resolve current events:
98 $window->flush_events();
99
100 # Render the top ViewPort in the FocusStack of this Window:
101 $window->flush_view();
102
103 # Render a particular ViewPort:
104 $window->render_viewport($viewport);
105
106 # Or in a template:
107 [% window.render_viewport(self.inner) %]
108
109 # Add a ViewPort to the UI:
110 $window->focus_stack->push_viewport('Reaction::UI::ViewPort');
111
112=head1 DESCRIPTION
113
114A Window object is created and stored in the stash by
9964b409 115L<Reaction::UI::Controller::Root>, it is used to contain all the
7adfd53f 116elements (ViewPorts) that make up the UI. The Window is rendered in
9964b409 117the end action of the Root Controller to make up the page.
7adfd53f 118
119To add L<ViewPorts|Reaction::UI::ViewPort> to the stack, read the
120L<Reaction::UI::FocusStack> and L<Reaction::UI::ViewPort> documentation.
121
122Several Window attributes are set by
9964b409 123L<Reaction::UI::Controller::Root/begin> when a new Window is created,
7adfd53f 124these are as follows:
125
126=over
127
128=item ctx
129
130The current L<Catalyst> context object is set.
131
132=item view_name
133
9964b409 134The view_name is set from the L<Reaction::UI::Controller::Root> attributes.
7adfd53f 135
136=item content_type
137
9964b409 138The content_type is set from the L<Reaction::UI::Controller::Root> attributes.
7adfd53f 139
9964b409 140=item title
7adfd53f 141
9964b409 142The title is set from the L<Reaction::UI::Controller::Root>
143window_title attribute.
7adfd53f 144
145=back
146
147=head1 METHODS
148
149=head2 ctx
150
151=over
152
9964b409 153=item Arguments: $ctx?
7adfd53f 154
155=back
156
9964b409 157Retrieve/set the current L<Catalyst> context object.
7adfd53f 158
159=head2 view_name
160
161=over
162
9964b409 163=item Arguments: %viewname?
7adfd53f 164
165=back
166
9964b409 167Retrieve/set the name of the L<Catalyst::View> component used to render
7adfd53f 168this Window. If this has not been set, rendering the Window will fail.
169
170=head2 content_type
171
172=over
173
9964b409 174=item Arguments: $contenttype?
7adfd53f 175
176=back
177
178Retrieve the content_type for the page. If this has not been set,
179rendering the Window will fail.
180
181=head2 title
182
183=over
184
185=item Arguments: $title?
186
187=back
188
189 [% window.title %]
190
9964b409 191Retrieve/set the title of this page, if not set, it will default to
7adfd53f 192"Untitled window".
193
194=head2 view
195
196=over
197
198=item Arguments: none
199
200=back
201
202Retrieve the L<Catalyst::View> instance, this can be set, or will be
203instantiated using the L<view_name> class.
204
205=head2 focus_stack
206
207=over
208
209=item Arguments: none
210
211=back
212
213 $window->focus_stack->push_viewport('Reaction::UI::ViewPort');
214
215Retrieve the L<stack|Reaction::UI::FocusStack> of
216L<ViewPorts|Reaction::UI::ViewPorts> that contains all the UI elements
217for this Window. Use L<Reaction::UI::FocusStack/push_viewport> on this
218to create more elements. An empty FocusStack is created by the
9964b409 219Controller::Root when the Window is created.
7adfd53f 220
221=head2 render_viewport
222
223=over
224
225=item Arguments: $viewport
226
227=back
228
229 $window->render_viewport($viewport);
230
231 [% window.render_viewport(self.inner) %]
232
233Calls render on the L<view> object used by this Window. The following
234arguments are given:
235
236=over
237
238=item ctx
239
240The L<Catalyst> context object.
241
242=item self
243
244The ViewPort object to be rendered.
245
246=item window
247
248The Window object.
249
250=item type
251
252The string that describes the layout from L<Reaction::UI::ViewPort/layout>.
253
254=back
255
256=head2 flush
257
258=over
259
260=item Arguments: none
261
262=back
263
264Synchronize the current events with all the L<Reaction::UI::ViewPort>
265objects in the UI, then render the root ViewPort. This is called for
9964b409 266you by L<Reaction::UI::Controller::Root/end>.
7adfd53f 267
268=head2 flush_events
269
270=over
271
272=item Arguments: none
273
274=back
275
276Resolves all the current events, first the query parameters then the
277body parameters, with all the L<Reaction::UI::ViewPort> objects in the
278UI. This calls L<Reaction::UI::FocusStack/apply_events>. This method
279is called by L<flush>.
280
281=head2 flush_view
282
283=over
284
285=item Arguments: none
286
287=back
288
289Renders the page into the L<Catalyst::Response> body, unless the
290response status is already set to 3xx, or the body has already been
291filled. This calls L<render_viewport> with the root
292L<Reaction::UI::ViewPort> from the L<focus_stack>. This method is
293called by L<flush>.
294
295=head1 AUTHORS
296
297See L<Reaction::Class> for authors.
298
299=head1 LICENSE
300
301See L<Reaction::Class> for the license.
302
303=cut