1 package Reaction::UI::FocusStack;
5 class FocusStack which {
7 has vp_head => (isa => 'Reaction::UI::ViewPort', is => 'rw');
8 has vp_tail => (isa => 'Reaction::UI::ViewPort', is => 'rw');
10 isa => 'Int', is => 'rw', required => 1, default => sub { 0 }
12 has loc_prefix => (isa => 'Str', is => 'rw', predicate => 'has_loc_prefix');
14 implements push_viewport => as {
15 my ($self, $class, %create) = @_;
16 my $tail = $self->vp_tail;
17 my $loc = $self->vp_count;
18 if ($self->has_loc_prefix) {
19 $loc = join('.', $self->loc_prefix, $loc);
25 (defined $tail ? ( outer => $tail ) : ()), # XXX possibly a bug in
28 if ($tail) { # if we already have a tail (non-empty vp stack)
29 $tail->inner($vp); # set the current tail's inner vp to the new vp
30 } else { # else we're currently an empty stack
31 $self->vp_head($vp); # so set the head to the new vp
33 $self->vp_count($self->vp_count + 1);
38 implements pop_viewport => as {
40 my $head = $self->vp_head;
41 confess "Can't pop from empty focus stack" unless defined($head);
42 my $vp = $self->vp_tail;
44 $self->vp_head(undef);
46 $self->vp_tail($vp->outer);
47 $self->vp_count($self->vp_count - 1);
51 implements pop_viewports_to => as {
53 1 while ($self->pop_viewport ne $vp);
57 implements apply_events => as {
59 my $vp = $self->vp_tail;
61 $vp->apply_events(@_);
73 Reaction::UI::FocusStack - A linked list of ViewPort-based objects
77 my $stack = Reaction::UI::FocusStack->new();
79 # Or more commonly, in a Reaction::UI::RootController based
80 # Catalyst Controller:
81 my $stack = $ctx->focus_stack;
83 # Add a new basic viewport inside the last viewport on the stack:
84 my $vp = $stack->push_viewport('Reaction::UI::ViewPort' =>
88 # Fetch the innermost viewport from the stack:
89 my $vp = $stack->pop_viewport();
91 # Remove all viewports inside a given viewport:
92 $stack->pop_viewports_to($vp);
94 # Create a named stack as a tangent to an existing viewport:
95 my $newstack = $vp->create_tangent('somename');
97 # Resolve current events using your stack:
98 # This is called by Reaction::UI::RootController in the end action.
99 $stack->apply_events($ctx, $param_hash);
103 A FocusStack represents a list of related L<ViewPort|Reaction::UI::ViewPort>
104 objects. The L<Reaction::UI::RootController> creates an empty stack for you in
105 it's begin action, which represents the main thread/container of the page.
106 Typically you add new ViewPorts to this stack as the main parts of your page.
107 To add multiple parallel page subparts, create a tangent from the outer
108 viewport, and add more viewports as normal.
116 =item Arguments: none
120 Create a new empty FocusStack. This is done for you in
121 L<Reaction::UI::RootController>.
127 =item Arguments: $class, %options
131 Creates a new L<Reaction::UI::ViewPort> based object and adds it to the stack.
133 The following attributes of the new ViewPort are set:
139 Is set to the preceding ViewPort in the stack.
143 Is set to the FocusStack object that created the ViewPort.
147 Is set to the location of the ViewPort in the stack.
155 =item Arguments: none
159 Removes the last/innermost ViewPort from the stack and returns it.
161 =head2 pop_viewports_to
165 =item Arguments: $viewport
169 Pops all ViewPorts off the stack until the given ViewPort object
170 remains as the last item. If passed a $viewport not on the stack, this
171 will empty the stack completely (and then die complainingly).
173 TODO: Should pop_viewports_to check $vp->focus_stack eq $self first?
179 =item Arguments: none
183 Retrieve the first ViewPort in this stack. Useful for calling
184 L<Reaction::UI::Window/render_viewport> on a
185 L<Reaction::UI::ViewPort/focus_tangent>.
191 =item Arguments: none
195 Retrieve the first ViewPort in this stack. Useful for calling
196 L<Reaction::UI::Window/render_viewport> on a
197 L<Reaction::UI::ViewPort/focus_tangent>.
203 =item Arguments: none
207 Retrieve the last ViewPort in this stack. Useful for calling
208 L<Reaction::UI::Window/render_viewport> on a
209 L<Reaction::UI::ViewPort/focus_tangent>.
215 =item Arguments: none
225 =item Arguments: $ctx, $params_hashref
229 Instruct each of the ViewPorts in the stack to apply the given events
230 to each of it's tangent stacks, and then to itself. These are applied
231 starting with the last/innermost ViewPort first.
235 See L<Reaction::Class> for authors.
239 See L<Reaction::Class> for the license.