1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
package Reaction::UI::Controller::Root;
use base qw/Reaction::UI::Controller/;
use Reaction::Class;
use Reaction::UI::Window;
__PACKAGE__->config(
view_name => 'XHTML',
content_type => 'text/html',
);
has 'view_name' => (isa => 'Str', is => 'rw', required => 1);
has 'content_type' => (isa => 'Str', is => 'rw', required => 1);
has 'window_title' => (
isa => 'Str', is => 'rw', predicate => 'has_window_title'
);
sub begin :Private {
my ($self, $ctx) = @_;
$ctx->stash(
window => Reaction::UI::Window->new(
ctx => $ctx,
view_name => $self->view_name,
content_type => $self->content_type,
($self->has_window_title
? (title => $self->window_title)
: ()),
)
);
my $focus_stack = $ctx->stash->{window}->focus_stack;
$focus_stack->loc_prefix('r-vp');
$ctx->stash(focus_stack => $focus_stack);
}
sub end :Private {
my ($self, $ctx) = @_;
$ctx->stash->{window}->flush;
}
sub error_404 :Private {
my ($self, $c) = @_;
$c->res->body("Error 404: Not Found");
$c->res->status(404);
$c->res->content_type('text/plain');
}
sub error_403 :Private {
my ($self, $c) = @_;
$c->res->body("Error 403: Forbidden");
$c->res->status(403);
$c->res->content_type('text/plain');
}
1;
=head1 NAME
Reaction::UI::Controller::Root - Base component for the Root Controller
=head1 SYNOPSIS
package MyApp::Controller::Root;
use base 'Reaction::UI::Controller::Root';
__PACKAGE__->config(
view_name => 'Site',
window_title => 'Reaction Test App',
namespace => ''
);
# Create UI elements:
$c->self->push_viewport('Reaction::UI::ViewPort', %args);
# Access the window title in a template:
[% window.title %]
=head1 DESCRIPTION
Using this module as a base component for your L<Catalyst> Root
Controller provides automatic creation of a L<Reaction::UI::Window>
object containing an empty L<Reaction::UI::FocusStack> for your UI
elements. The stack is also resolved and rendered for you in the
C<end> action.
At the C<begin> of each request, the Window object is
created using the configured L</view_name>, L</content_type> and
L</window_title>. These thus should be directly changed on the stashed
window object at runtime, if needed.
=head1 ATTRIBUTES
=head2 view_name
=over
=item Arguments: $viewname?
=back
Set or retrieve the classname of the view used to render the UI. Can
also be set by a call to config. Defaults to 'XHTML'.
=head2 content_type
=over
=item Arguments: $contenttype?
=back
Set or retrieve the content type of the page created. Can also be set
by a call to config or in a config file. Defaults to 'text/html'.
=head2 window_title
=over
=item Arguments: $windowtitle?
=back
Set or retrieve the title of the page created. Can also be set by a
call to config or in a config file. No default.
=head1 ACTIONS
=head2 begin
Stuffs a new L<Reaction::UI::Window> object into the stash, using the
L</view_name> and L</content_type> provided in the
L<configuration|/SYNOPSIS>.
Make sure you call this base C<begin> action if writing your own.
=head2 end
Draws the UI via the L<Reaction::UI::Window/flush> method.
=head1 METHODS
=head2 error_404
Sets $c->res (the L<Catalyst::Response>) body, status and content type
to output a 404 (File not found) error.
=head2 error_403
Sets $c->res (the L<Catalyst::Response>) body, status and content type
to output a 403 (Forbidden) error.
=head1 AUTHORS
See L<Reaction::Class> for authors.
=head1 LICENSE
See L<Reaction::Class> for the license.
=cut
|