File Coverage

lib/Devel/ebug/Wx/Service/ViewManager.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package Devel::ebug::Wx::Service::ViewManager;
2              
3 1     1   1662 use strict;
  1         3  
  1         35  
4 1     1   5 use base qw(Devel::ebug::Wx::Service::Base);
  1         2  
  1         83  
5 1     1   5 use Devel::ebug::Wx::Plugin qw(:manager :plugin);
  1         2  
  1         137  
6              
7             =head1 NAME
8              
9             Devel::ebug::Wx::Service::ViewManager - manage view docking/undocking
10              
11             =head1 SYNOPSIS
12              
13             my $vm = ...->get_service( 'view_manager' );
14             my $bool = $vm->has_view( $tag );
15             $vm->register_view( $view );
16             $vm->unregister_view( $view );
17              
18             # both create_* methods don't call ->register_view()
19             $vm->create_pane( $view, { name => $tag,
20             caption => 'Displayed name',
21             float => 1,
22             } );
23             $vm->create_pane_and_update( ... ); # like ->create_pane()
24              
25             my @view_classes = Devel::ebug::Wx::Service::ViewManager->views;
26              
27             =head1 DESCRIPTION
28              
29             The C service manages windows (views) using the
30             wxWidgets Advanced User Interface (AUI). The service automatically
31             manages saving/restoring the state and layout of registered views.
32             Unregistered views are allowed but their state is not preserved
33             between sessions.
34              
35             =head1 METHODS
36              
37             =cut
38              
39 1     1   486 use Wx;
  0            
  0            
40             use Wx::AUI;
41             use Devel::ebug::Wx::ServiceManager::Holder;
42              
43             load_plugins( search_path => 'Devel::ebug::Wx::View' );
44              
45             __PACKAGE__->mk_accessors( qw(wxebug active_views manager pane_info) );
46              
47             sub views { Devel::ebug::Wx::Plugin->view_classes }
48              
49             sub service_name : Service { 'view_manager' }
50              
51             sub initialize {
52             my( $self, $manager ) = @_;
53              
54             $self->wxebug( $manager->get_service( 'ebug_wx' ) );
55             $self->manager( Wx::AuiManager->new );
56             $self->active_views( {} );
57             $self->views; # force loading of views
58              
59             $self->manager->SetManagedWindow( $self->wxebug );
60              
61             # default Pane Info
62             $self->{pane_info} = Wx::AuiPaneInfo->new
63             ->CenterPane->TopDockable->BottomDockable->LeftDockable->RightDockable
64             ->Floatable->Movable->PinButton->CaptionVisible->Resizable
65             ->CloseButton->DestroyOnClose( 0 );
66             }
67              
68             sub save_configuration {
69             my( $self ) = @_;
70              
71             my $cfg = $self->configuration_service->get_config( 'view_manager' );
72             my( @xywh ) = ( $self->wxebug->GetPositionXY, $self->wxebug->GetSizeWH );
73             $cfg->set_value( 'aui_perspective', $self->manager->SavePerspective );
74             $cfg->set_serialized_value( 'views', [ map $_->get_layout_state,
75             grep $_->is_managed,
76             $self->active_views_list ] );
77             $cfg->set_value( 'frame_geometry', sprintf '%d,%d,%d,%d', @xywh );
78             }
79              
80             sub load_configuration {
81             my( $self ) = @_;
82              
83             # FIXME alignment between the AUI config and views, grep out views
84             # without perspective
85             my $cfg = $self->configuration_service->get_config( 'view_manager' );
86             my $profile = $cfg->get_value( 'aui_perspective', '' );
87             my $views = $cfg->get_serialized_value( 'views', [] );
88             foreach my $view ( @$views ) {
89             my $instance = $view->{class}->new( $self->wxebug, $self->wxebug,
90             $view );
91             my $pane_info = $self->pane_info->Name( $instance->tag )
92             ->DestroyOnClose( 0 );
93             $pane_info->DestroyOnClose( 1 ) unless Wx->VERSION > 0.67;
94             $pane_info->DestroyOnClose( 1 ) if $instance->can( 'is_multiview' )
95             && $instance->is_multiview;
96             $self->manager->AddPane( $instance, $pane_info );
97             }
98              
99             $self->manager->LoadPerspective( $profile ) if $profile;
100              
101             # destroy hidden multiviews (they can't currently be reshown)
102             $_->Destroy foreach grep $_->can( 'is_multiview' ) && $_->is_multiview,
103             grep !$self->is_shown( $_->tag ),
104             $self->active_views_list;
105              
106             my( @xywh ) = split ',', $cfg->get_value( 'frame_geometry', ',,,' );
107             if( length $xywh[0] ) {
108             $self->wxebug->SetSize( @xywh );
109             }
110              
111             $self->manager->Update;
112             }
113              
114             # FIXME document get_state/set_state as part of view interface
115             sub save_program_state {
116             my( $self, $file ) = @_;
117             my $cfg = $self->get_service( 'configuration' )
118             ->get_config( 'view_manager', $file );
119              
120             foreach my $view ( $self->active_views_list ) {
121             next unless $view->can( 'get_state' );
122             $cfg->set_serialized_value( $view->tag, $view->get_state );
123             }
124             }
125              
126             sub load_program_state {
127             my( $self, $file ) = @_;
128             my $cfg = $self->get_service( 'configuration' )
129             ->get_config( 'view_manager', $file );
130              
131             # FIXME what about the state of an inactive view?
132             foreach my $view ( $self->active_views_list ) {
133             next unless $view->can( 'set_state' );
134             my $state = $cfg->get_serialized_value( $view->tag );
135             next unless $state;
136             $view->set_state( $state );
137             }
138             }
139              
140             =head2 active_views_list
141              
142             my @views = $vm->active_views_list;
143              
144             =cut
145              
146             sub active_views_list {
147             my( $self ) = @_;
148              
149             return values %{$self->active_views};
150             }
151              
152             =head2 has_view
153              
154             =head2 get_view
155              
156             my $is_active = $vm->has_view( $tag );
157             my $view = $vm->get_view( $tag );
158              
159             C returns C if a view vith the given tag is currently
160             shown and managed by the view manager; in this case C can be
161             used to retrieve the view.
162              
163             =cut
164              
165             sub has_view {
166             my( $self, $tag ) = @_;
167              
168             return exists $self->active_views->{$tag} ? 1 : 0;
169             }
170              
171             sub get_view {
172             my( $self, $tag ) = @_;
173              
174             return $self->active_views->{$tag};
175             }
176              
177             =head2 register_view
178              
179             $vm->register_view( $view );
180              
181             Registers a view with the view manager. Please notice that at any
182             given time only one view can be registered with the service with a
183             given tag.
184              
185             =cut
186              
187             sub register_view {
188             my( $self, $view ) = @_;
189              
190             $self->active_views->{$view->tag} = $view;
191             }
192              
193             =head2 unregister_view
194              
195             $vm->unregister_view( $view );
196              
197             Unregisters the view from the view manager.
198              
199             =cut
200              
201             sub unregister_view {
202             my( $self, $view ) = @_;
203              
204             delete $self->active_views->{$view->tag};
205             $self->manager->DetachPane( $view ) unless $self->finalized;
206             }
207              
208             =head2 create_pane
209              
210             =head2 create_pane_and_update
211              
212             $vm->create_pane( $view, { name => 'view_tag',
213             caption => 'Pane title',
214             float => 1,
215             } );
216             $vm->create_pane_and_update( ... );
217              
218             Both functions create a floatable pane containing C<$window>;
219             C also causes the pane to be shown. Neither
220             function calls C to register the view with the view
221             manager.
222              
223             =cut
224              
225             sub create_pane_and_update {
226             my( $self, @args ) = @_;
227              
228             $self->create_pane( @args );
229             $self->manager->Update;
230             }
231              
232             sub create_pane {
233             my( $self, $window, $info ) = @_;
234              
235             my $pane_info = $self->pane_info ->Name( $info->{name} )
236             ->Caption( $info->{caption} )->DestroyOnClose( 0 );
237             $pane_info->Float if $info->{float};
238             $self->{pane_info}->DestroyOnClose( 1 ) unless Wx->VERSION > 0.67;
239             $pane_info->DestroyOnClose( 1 ) if $window->can( 'is_multiview' )
240             && $window->is_multiview;
241             $self->manager->AddPane( $window, $pane_info );
242             }
243              
244             =head2 show_view
245              
246             =head2 hide_view
247              
248             $vm->show_view( $tag );
249             $vm->hide_view( $tag );
250             my $shown = $vm->is_shown( $tag );
251              
252             =cut
253              
254             sub show_view {
255             my( $self, $tag ) = @_;
256              
257             $self->manager->GetPane( $tag )->Show;
258             $self->manager->Update;
259             }
260              
261             sub hide_view {
262             my( $self, $tag ) = @_;
263              
264             if( Wx->VERSION > 0.67 ) {
265             $self->manager->GetPane( $tag )->Hide;
266             } else {
267             $self->manager->GetPane( $tag )->Destroy;
268             }
269             $self->manager->Update;
270             }
271              
272             # FIXME needs to be smarter for Notebooks
273             sub is_shown {
274             my( $self, $tag ) = @_;
275             my $view = $self->get_view( $tag );
276              
277             return 1 if $view && !$view->is_managed;
278             return 0 unless $self->has_view( $tag );
279             return $self->manager->GetPane( $tag )->IsShown ? 1 : 0;
280             }
281              
282             =head2 views
283              
284             my @view_classes = Devel::ebug::Wx::Service::ViewManager->views;
285              
286             Returns a list of view classes known to the view manager.
287              
288             =cut
289              
290             1;