File Coverage

lib/Kephra/App/TabBar.pm
Criterion Covered Total %
statement 6 170 3.5
branch 0 76 0.0
condition 0 30 0.0
subroutine 2 40 5.0
pod 0 23 0.0
total 8 339 2.3


line stmt bran cond sub pod time code
1             package Kephra::App::TabBar;
2             our $VERSION = '0.18';
3              
4 1     1   1155 use strict;
  1         2  
  1         41  
5 1     1   6 use warnings;
  1         3  
  1         2453  
6              
7             # internal data
8             my $notebook;
9 0 0   0     sub _ref { $notebook = ref $_[0] eq 'Wx::AuiNotebook' ? $_[0] : $notebook }
10 0 0   0     sub _config { my $cfg = Kephra::API::settings(); $cfg->{app}{tabbar} if keys %$cfg }
  0            
11              
12             my @doc2tab_pos; # tab index numbers in doc order
13             my @tab2doc_pos; # doc numbers in tab index order
14             my @doc2vis_pos; # visible tab pos number in doc order
15             my @vis2doc_pos; # doc numbers in visible tab order
16             sub _update_doc_pos {
17 0     0     @doc2tab_pos = ();
18 0           @doc2vis_pos = ();
19 0           $doc2tab_pos[ $tab2doc_pos[$_] ] = $_ for 0 .. $#tab2doc_pos;
20 0           $doc2vis_pos[ $vis2doc_pos[$_] ] = $_ for 0 .. $#vis2doc_pos;
21             }
22 0     0     sub _validate_doc_nr { &Kephra::Document::Data::validate_doc_nr }
23             sub _doc2tab_pos {
24 0     0     my $nr = _validate_doc_nr(shift);
25 0 0         return $nr == -1 ? -1 : $doc2tab_pos[$nr];
26             }
27             sub _tab2doc_pos {
28 0     0     my $nr = _validate_doc_nr(shift);
29 0 0         return $nr == -1 ? -1 : $tab2doc_pos[$nr];
30             }
31             sub _vis2doc_pos {
32 0     0     my $nr = _validate_doc_nr(shift);
33 0 0         return $nr == -1 ? -1 : $vis2doc_pos[$nr];
34             }
35             sub _doc2vis_pos {
36 0     0     my $nr = _validate_doc_nr(shift);
37 0 0         return $nr == -1 ? -1 : $doc2vis_pos[$nr];
38             }
39             sub _move_vis_pos {
40 0     0     my $from = _validate_doc_nr(shift);
41 0           my $to = _validate_doc_nr(shift);
42 0 0 0       return if $from == -1 or $to == -1;
43 0           my $doc_nr = splice @vis2doc_pos, $from, 1;
44 0           splice @vis2doc_pos, $to, 0, $doc_nr;
45 0           _update_doc_pos();
46             #print "vis_order: @vis2doc_pos, tab_order: @tab2doc_pos\n";
47             #print $notebook->GetPageIndex( Kephra::Document::Data::_ep($_) )."\n" for @{Kephra::Document::Data::all_nr()};
48             }
49             sub _move_tab_pos {
50 0     0     my $from = _validate_doc_nr(shift);
51 0           my $to = _validate_doc_nr(shift);
52 0 0 0       return if $from == -1 or $to == -1;
53 0           my $doc_nr = splice @tab2doc_pos, $from, 1;
54 0           splice @tab2doc_pos, $to, 0, $doc_nr;
55 0           _update_doc_pos(); #print "taborder: @tab2doc_pos, doc_order: @doc_order\n";
56             #print $notebook->GetPageIndex( Kephra::Document::Data::_ep($_) )."\n" for @{Kephra::Document::Data::all_nr()};
57             }
58             sub _remove_tab {
59 0     0     my $tab_nr = _validate_doc_nr(shift);
60 0 0         return if $tab_nr == -1;
61 0           my $doc_nr = $tab2doc_pos[$tab_nr];
62 0           my $vis_nr = $doc2vis_pos[$doc_nr];
63 0           splice @tab2doc_pos, $tab_nr, 1;
64 0           splice @vis2doc_pos, $vis_nr, 1;
65 0 0         for (0 .. $#tab2doc_pos) {$tab2doc_pos[$_]-- if $tab2doc_pos[$_] > $doc_nr}
  0            
66 0 0         for (0 .. $#vis2doc_pos) {$vis2doc_pos[$_]-- if $vis2doc_pos[$_] > $doc_nr}
  0            
67 0           _update_doc_pos();
68             #print "vis_order: @vis2doc_pos, tab_order: @tab2doc_pos\n";
69             }
70             #
71             # basic toolbar creation
72             #
73             sub create {
74             # create notebook if there is none
75 0     0 0   my $notebook = _ref();
76 0 0         $notebook->Destroy if defined $notebook;
77 0           $notebook = Wx::AuiNotebook->new
78             (Kephra::App::Window::_ref(),-1, [0,0], [-1,23],
79             &Wx::wxAUI_NB_TOP | &Wx::wxAUI_NB_SCROLL_BUTTONS);
80 0           _ref($notebook);
81             #Wx::Event::EVT_LEFT_UP( $notebook, sub {
82             #my ($tabs, $event) = @_; print "\n left up\n";
83             #Kephra::Document::Data::set_value('b4tabchange', $tabs->GetSelection);
84             #$event->Skip;
85             #});
86             #Wx::Event::EVT_LEFT_DOWN( $notebook, sub {
87             #my ($tabs, $event) = @_; print "\n left down\n";
88             #Kephra::Document::Change::switch_back()
89             #if Kephra::Document::Data::get_value('b4tabchange')==$tabs->GetSelection;
90             #$event->Skip;
91             #});
92 0           my $begin_drag_index;
93             Wx::Event::EVT_AUINOTEBOOK_BEGIN_DRAG($notebook, -1, sub {
94 0     0     $begin_drag_index = $_[1]->GetSelection;
95 0           });
96             Wx::Event::EVT_AUINOTEBOOK_END_DRAG($notebook, -1, sub {
97 0     0     _move_vis_pos($begin_drag_index, $_[1]->GetSelection);
98             #rotate_tab($_[1]->GetSelection - $begin_drag_index);
99 0           Kephra::App::EditPanel::gets_focus();
100 0           Kephra::EventTable::trigger('document.list');
101 0           });
102             Wx::Event::EVT_AUINOTEBOOK_PAGE_CHANGED( $notebook, -1, sub {
103 0     0     my ( $bar, $event ) = @_;
104 0           my $new_nr = _tab2doc_pos( $event->GetSelection );
105 0           my $old_nr = _tab2doc_pos( $event->GetOldSelection );
106             #print "=begin change ".$event->GetSelection." page ; docs: $old_nr -> $new_nr\n";
107             #print "=end change page $nr\n";
108 0           Kephra::Document::Change::to_number( $new_nr, $old_nr);
109 0           Kephra::App::EditPanel::gets_focus();
110 0           $event->Skip;
111 0           });
112             Wx::Event::EVT_AUINOTEBOOK_PAGE_CLOSE( $notebook, -1, sub {
113 0     0     my ( $bar, $event ) = @_;
114 0           Kephra::File::close_nr( _tab2doc_pos($event->GetSelection) );
115 0           $event->Veto;
116 0           });
117             }
118              
119             sub apply_settings {
120 0     0 0   my $notebook = _ref();
121             # Optional middle click over the tabs
122 0 0         if ( _config()->{middle_click} ) {
123 0           Wx::Event::EVT_MIDDLE_UP(
124             $notebook,
125             Kephra::CommandList::get_cmd_property( _config()->{middle_click},'call')
126             );
127             }
128 0           my $style = $notebook->GetWindowStyleFlag();
129 0 0         $style |= &Wx::wxAUI_NB_TAB_MOVE if _config->{movable_tabs};
130 0 0         $style |= &Wx::wxAUI_NB_WINDOWLIST_BUTTON if _config->{tablist_button};
131 0 0         if (_config->{close_button} =~ /all/){ $style |= &Wx::wxAUI_NB_CLOSE_ON_ALL_TABS}
  0 0          
    0          
    0          
132 0           elsif (_config->{close_button} =~ /one/){ $style |= &Wx::wxAUI_NB_CLOSE_BUTTON}
  0            
133 0           elsif (_config->{close_button} =~ /current/){$style |= &Wx::wxAUI_NB_CLOSE_ON_ACTIVE_TAB}
134             elsif (_config->{close_button} =~ /active/) {$style |= &Wx::wxAUI_NB_CLOSE_ON_ACTIVE_TAB}
135             # wxAUI_NB_TAB_SPLIT wxAUI_NB_TAB_EXTERNAL_MOVE
136 0           $notebook->SetWindowStyle( $style );
137 0           show();
138             }
139             #
140             # tab functions
141             #
142             sub add_edit_tab {
143 0     0 0   my $current_nr = Kephra::Document::Data::current_nr();
144 0   0       my $doc_nr = shift || $current_nr;
145 0           my $config = _config();
146 0 0 0       my $mode = (ref $config and defined $config->{insert_new_tab})
147             ? $config->{insert_new_tab}
148             : 'rightmost';
149 0           my $vis_pos;
150 0 0         $vis_pos = 0 if $mode eq 'leftmost';
151 0 0         $vis_pos = $current_nr if $mode eq 'left';
152 0 0         $vis_pos = $current_nr+1 if $mode eq 'right';
153 0 0         $vis_pos = $doc_nr if $mode eq 'rightmost';
154 0           my $stc = Kephra::App::EditPanel::new();
155 0           Kephra::Document::Data::set_attribute('ep_ref', $stc, $doc_nr);
156             #my $panel = Wx::Panel->new( $notebook, -1);
157             #$stc->Reparent($panel);
158             #my $sizer = Wx::BoxSizer->new( &Wx::wxVERTICAL );
159             #$sizer->Add( $stc, 1, &Wx::wxGROW, 0);
160             #$panel->SetSizer($sizer);
161             #$panel->SetAutoLayout(1);
162             #$notebook->Freeze(); #$notebook->Thaw();
163 0           my $notebook = _ref();
164             #$notebook->InsertPage( $vis_pos, $stc, '', 0 );
165 0           $notebook->AddPage( $stc, '', 0 );
166 0           $notebook->Layout();
167 0           $stc->Layout();
168 0           splice @tab2doc_pos, $doc_nr, 0, $doc_nr; # splice @tab2doc_pos, $vis_pos, 0, $doc_nr;
169 0           splice @vis2doc_pos, $doc_nr, 0, $doc_nr; # splice @vis2doc_pos, $vis_pos, 0, $doc_nr;
170 0           _update_doc_pos();
171 0           return $stc;
172             }
173              
174             sub add_panel_tab {
175 0   0 0 0   my $doc_nr = shift || Kephra::Document::Data::current_nr();
176 0           my $panel = shift;
177 0 0 0       return unless defined $panel and substr(ref $panel, 0, 4) eq 'Wx::';
178 0           $panel->Reparent($notebook);
179 0           $notebook->InsertPage($panel, '', 0 ); # attention no $pos yet
180 0           return $panel;
181             }
182              
183 0     0 0   sub raise_tab_by_doc_nr { raise_tab_by_tab_nr( _doc2tab_pos(shift) ) }
184 0     0 0   sub raise_tab_by_vis_nr { raise_tab_by_tab_nr( _doc2tab_pos( _vis2doc_pos(shift)))}
185             sub raise_tab_by_tab_nr {
186 0     0 0   my $nr = shift;
187 0 0         $notebook->SetSelection($nr) unless $nr == $notebook->GetSelection;
188             }
189             sub raise_tab_left {
190 0     0 0   my $vis_nr = _doc2vis_pos( Kephra::Document::Data::current_nr() );
191 0           raise_tab_by_vis_nr( Kephra::Document::Data::next_nr(-1, $vis_nr) );
192             }
193             sub raise_tab_right {
194 0     0 0   my $vis_nr = _doc2vis_pos( Kephra::Document::Data::current_nr() );
195 0           raise_tab_by_vis_nr( Kephra::Document::Data::next_nr(1, $vis_nr) );
196             }
197 0     0 0   sub rotate_tab_left { rotate_tab(-1) }
198 0     0 0   sub rotate_tab_right{ rotate_tab( 1) }
199             sub rotate_tab {
200 0 0   0 0   return unless _config()->{movable_tabs};
201 0           my $rot_step = shift;
202 0           my $doc_nr = Kephra::Document::Data::current_nr();
203 0           my $old_tab_pos = _doc2tab_pos( $doc_nr );
204 0           my $old_vis_pos = _doc2vis_pos( $doc_nr );
205 0           my $new_vis_pos = Kephra::Document::Data::next_nr($rot_step, $old_vis_pos);
206 0           my $notebook = _ref();
207 0           my $label = $notebook->GetPageText( $old_tab_pos );
208 0           my $stc = Kephra::Document::Data::_ep($doc_nr);
209 0           $notebook->RemovePage( $old_tab_pos );
210 0           $notebook->InsertPage( $new_vis_pos, $stc, $label, 0 );
211 0           _move_tab_pos( $old_tab_pos, $new_vis_pos );
212 0           _move_vis_pos( $old_vis_pos, $new_vis_pos );
213 0           raise_tab_by_vis_nr($new_vis_pos);
214 0           Kephra::EventTable::trigger('document.list');
215             }
216              
217 0     0 0   sub delete_tab_by_doc_nr { delete_tab_by_tab_nr( _doc2tab_pos(shift) ) }
218             sub delete_tab_by_tab_nr {
219 0     0 0   my $tab_nr = shift;
220 0           my $doc_nr = _tab2doc_pos($tab_nr);
221 0           my $notebook = _ref();
222             #print "delete tab $tab_nr \n";
223 0           my $stc = Kephra::Document::Data::_ep($doc_nr);
224             #print $notebook->GetSelection."current, del tab nr $nr\n";
225 0           _remove_tab($tab_nr);
226 0           $notebook->RemovePage($tab_nr); # DeletePage,RemovePage
227 0           $stc->Destroy(); # $xw->Reparent( undef );
228             }
229             #
230             # refresh the label of given number
231             #
232             sub refresh_label {
233 0     0 0   my $doc_nr = shift;
234 0 0         $doc_nr = Kephra::Document::Data::current_nr() unless defined $doc_nr;
235 0 0         return unless _validate_doc_nr($doc_nr) > -1;
236              
237 0           my $config = _config();
238 0           my $untitled = Kephra::Config::Localisation::strings()->{app}{general}{untitled};
239 0   0       my $label = Kephra::Document::Data::get_attribute
240             ( $config->{file_info}, $doc_nr ) || "<$untitled>";
241              
242             # shorten too long filenames
243 0           my $max_width = $config->{max_tab_width};
244 0 0 0       if ( length($label) > $max_width and $max_width > 7 ) {
245 0           $label = substr( $label, 0, $max_width - 3 ) . '...';
246             }
247             # set config files in square brackets
248 0 0 0       if ( $config->{mark_configs}
      0        
249             and Kephra::Document::Data::get_attribute('config_file', $doc_nr)
250             and Kephra::API::settings()->{file}{save}{reload_config} ) {
251 0           $label = '$ ' . $label;
252             }
253 0 0         $label = ( $doc_nr + 1 ) . ' ' . $label if $config->{number_tabs};
254 0           Kephra::Document::Data::set_attribute('label', $label);
255 0 0         if ( $config->{info_symbol} ) {
256 0 0         $label .= ' #' if Kephra::Document::Data::get_attribute('editable');
257 0 0         $label .= ' *' if Kephra::Document::Data::get_attribute('modified');
258             }
259 0           $notebook->SetPageText( _doc2tab_pos($doc_nr), $label );
260             }
261              
262 0     0 0   sub refresh_current_label { refresh_label(Kephra::Document::Data::current_nr()) }
263             sub refresh_all_label {
264 0 0   0 0   if ( Kephra::Document::Data::get_value('loaded') ) {
265 0           refresh_label($_) for @{ Kephra::Document::Data::all_nr() };
  0            
266 0           raise_tab_by_doc_nr( Kephra::Document::Data::current_nr() );
267             }
268             }
269             #
270             # tabbar and his menu visibility
271             #
272 0     0 0   sub get_visibility { _config()->{visible} }
273 0     0 0   sub set_visibility { _config()->{visible} = shift }
274 0     0 0   sub switch_visibility { show( _config()->{visible} ^ 1 ) }
275             sub show {
276 0     0 0   my $visible = shift;
277 0 0         $visible = get_visibility() unless defined $visible;
278 0 0         $visible
279             ? _ref()->SetTabCtrlHeight(25)
280             : _ref()->SetTabCtrlHeight(0);
281 0           set_visibility($visible);
282             }
283              
284             sub switch_contextmenu_visibility {
285 0     0 0   _config()->{contextmenu_use} ^= 1;
286 0           Kephra::App::ContextMenu::connect_tabbar();
287             }
288 0     0 0   sub get_contextmenu_visibility { _config()->{contextmenu_use} }
289              
290             1;